draw_beach_ball.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "draw_beach_ball.h"
  9. #ifndef IGL_NO_OPENGL
  10. #include "OpenGL_convenience.h"
  11. // I'm not sure why windows would need it this way:
  12. // http://lists.cairographics.org/archives/cairo/2008-January/012722.html
  13. #ifdef _MSC_VER
  14. #define SAFE_INLINE __inline
  15. #else
  16. #define SAFE_INLINE inline
  17. #endif
  18. #include <vector>
  19. #include <cmath>
  20. #include <iostream>
  21. // Most of this implementation comes from the AntTweakBar source code:
  22. // TwMgr.cpp, TwMgr.h, TwColor.h, TwColor.cpp, TwOpenGL.h and TwOpenGL.cpp
  23. ////////////////////////////////////////////////////////////////////////////
  24. // Begin Copied Straight from AntTweakBar
  25. ////////////////////////////////////////////////////////////////////////////
  26. static const float FLOAT_EPS = 1.0e-7f;
  27. static const float FLOAT_EPS_SQ = 1.0e-14f;
  28. static const float FLOAT_PI = 3.14159265358979323846f;
  29. enum EArrowParts { ARROW_CONE, ARROW_CONE_CAP, ARROW_CYL, ARROW_CYL_CAP };
  30. template <typename T> SAFE_INLINE const T& TClamp(const T& X, const T& Limit1, const T& Limit2)
  31. {
  32. if( Limit1<Limit2 )
  33. return (X<=Limit1) ? Limit1 : ( (X>=Limit2) ? Limit2 : X );
  34. else
  35. return (X<=Limit2) ? Limit2 : ( (X>=Limit1) ? Limit1 : X );
  36. }
  37. typedef unsigned int color32;
  38. static SAFE_INLINE color32 Color32FromARGBi(int A, int R, int G, int B)
  39. {
  40. return (((color32)TClamp(A, 0, 255))<<24) | (((color32)TClamp(R, 0, 255))<<16) | (((color32)TClamp(G, 0, 255))<<8) | ((color32)TClamp(B, 0, 255));
  41. }
  42. static SAFE_INLINE color32 Color32FromARGBf(float A, float R, float G, float B)
  43. {
  44. return (((color32)TClamp(A*256.0f, 0.0f, 255.0f))<<24) | (((color32)TClamp(R*256.0f, 0.0f, 255.0f))<<16) | (((color32)TClamp(G*256.0f, 0.0f, 255.0f))<<8) | ((color32)TClamp(B*256.0f, 0.0f, 255.0f));
  45. }
  46. static SAFE_INLINE void Color32ToARGBi(color32 Color, int *A, int *R, int *G, int *B)
  47. {
  48. if(A) *A = (Color>>24)&0xff;
  49. if(R) *R = (Color>>16)&0xff;
  50. if(G) *G = (Color>>8)&0xff;
  51. if(B) *B = Color&0xff;
  52. }
  53. static SAFE_INLINE void Color32ToARGBf(color32 Color, float *A, float *R, float *G, float *B)
  54. {
  55. if(A) *A = (1.0f/255.0f)*float((Color>>24)&0xff);
  56. if(R) *R = (1.0f/255.0f)*float((Color>>16)&0xff);
  57. if(G) *G = (1.0f/255.0f)*float((Color>>8)&0xff);
  58. if(B) *B = (1.0f/255.0f)*float(Color&0xff);
  59. }
  60. static color32 ColorBlend(color32 Color1, color32 Color2, float S)
  61. {
  62. float a1, r1, g1, b1, a2, r2, g2, b2;
  63. Color32ToARGBf(Color1, &a1, &r1, &g1, &b1);
  64. Color32ToARGBf(Color2, &a2, &r2, &g2, &b2);
  65. float t = 1.0f-S;
  66. return Color32FromARGBf(t*a1+S*a2, t*r1+S*r2, t*g1+S*g2, t*b1+S*b2);
  67. }
  68. static std::vector<float> s_SphTri;
  69. static std::vector<color32> s_SphCol;
  70. static void CreateSphere()
  71. {
  72. const int SUBDIV = 7;
  73. s_SphTri.clear();
  74. s_SphCol.clear();
  75. const float A[8*3] = { 1,0,0, 0,0,-1, -1,0,0, 0,0,1, 0,0,1, 1,0,0, 0,0,-1, -1,0,0 };
  76. const float B[8*3] = { 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0 };
  77. const float C[8*3] = { 0,0,1, 1,0,0, 0,0,-1, -1,0,0, 1,0,0, 0,0,-1, -1,0,0, 0,0,1 };
  78. //const color32 COL_A[8] = { 0xffff8080, 0xff000080, 0xff800000, 0xff8080ff, 0xff8080ff, 0xffff8080, 0xff000080, 0xff800000 };
  79. //const color32 COL_B[8] = { 0xff80ff80, 0xff80ff80, 0xff80ff80, 0xff80ff80, 0xff008000, 0xff008000, 0xff008000, 0xff008000 };
  80. //const color32 COL_C[8] = { 0xff8080ff, 0xffff8080, 0xff000080, 0xff800000, 0xffff8080, 0xff000080, 0xff800000, 0xff8080ff };
  81. const color32 COL_A[8] = { 0xffffffff, 0xffffff40, 0xff40ff40, 0xff40ffff, 0xffff40ff, 0xffff4040, 0xff404040, 0xff4040ff };
  82. const color32 COL_B[8] = { 0xffffffff, 0xffffff40, 0xff40ff40, 0xff40ffff, 0xffff40ff, 0xffff4040, 0xff404040, 0xff4040ff };
  83. const color32 COL_C[8] = { 0xffffffff, 0xffffff40, 0xff40ff40, 0xff40ffff, 0xffff40ff, 0xffff4040, 0xff404040, 0xff4040ff };
  84. int i, j, k, l;
  85. float xa, ya, za, xb, yb, zb, xc, yc, zc, x, y, z, norm, u[3], v[3];
  86. color32 col;
  87. for( i=0; i<8; ++i )
  88. {
  89. xa = A[3*i+0]; ya = A[3*i+1]; za = A[3*i+2];
  90. xb = B[3*i+0]; yb = B[3*i+1]; zb = B[3*i+2];
  91. xc = C[3*i+0]; yc = C[3*i+1]; zc = C[3*i+2];
  92. for( j=0; j<=SUBDIV; ++j )
  93. for( k=0; k<=2*(SUBDIV-j); ++k )
  94. {
  95. if( k%2==0 )
  96. {
  97. u[0] = ((float)j)/(SUBDIV+1);
  98. v[0] = ((float)(k/2))/(SUBDIV+1);
  99. u[1] = ((float)(j+1))/(SUBDIV+1);
  100. v[1] = ((float)(k/2))/(SUBDIV+1);
  101. u[2] = ((float)j)/(SUBDIV+1);
  102. v[2] = ((float)(k/2+1))/(SUBDIV+1);
  103. }
  104. else
  105. {
  106. u[0] = ((float)j)/(SUBDIV+1);
  107. v[0] = ((float)(k/2+1))/(SUBDIV+1);
  108. u[1] = ((float)(j+1))/(SUBDIV+1);
  109. v[1] = ((float)(k/2))/(SUBDIV+1);
  110. u[2] = ((float)(j+1))/(SUBDIV+1);
  111. v[2] = ((float)(k/2+1))/(SUBDIV+1);
  112. }
  113. for( l=0; l<3; ++l )
  114. {
  115. x = (1.0f-u[l]-v[l])*xa + u[l]*xb + v[l]*xc;
  116. y = (1.0f-u[l]-v[l])*ya + u[l]*yb + v[l]*yc;
  117. z = (1.0f-u[l]-v[l])*za + u[l]*zb + v[l]*zc;
  118. norm = sqrtf(x*x+y*y+z*z);
  119. x /= norm; y /= norm; z /= norm;
  120. s_SphTri.push_back(x); s_SphTri.push_back(y); s_SphTri.push_back(z);
  121. if( u[l]+v[l]>FLOAT_EPS )
  122. col = ColorBlend(COL_A[i], ColorBlend(COL_B[i], COL_C[i], v[l]/(u[l]+v[l])), u[l]+v[l]);
  123. else
  124. col = COL_A[i];
  125. //if( (j==0 && k==0) || (j==0 && k==2*SUBDIV) || (j==SUBDIV && k==0) )
  126. // col = 0xffff0000;
  127. s_SphCol.push_back(col);
  128. }
  129. }
  130. }
  131. //s_SphTriProj.clear();
  132. //s_SphTriProj.resize(2*s_SphCol.size(), 0);
  133. //s_SphColLight.clear();
  134. //s_SphColLight.resize(s_SphCol.size(), 0);
  135. }
  136. static std::vector<float> s_ArrowTri[4];
  137. static std::vector<float> s_ArrowNorm[4];
  138. static void CreateArrow()
  139. {
  140. const int SUBDIV = 15;
  141. const float CYL_RADIUS = 0.08f;
  142. const float CONE_RADIUS = 0.16f;
  143. const float CONE_LENGTH = 0.25f;
  144. const float ARROW_BGN = -1.1f;
  145. const float ARROW_END = 1.15f;
  146. int i;
  147. for(i=0; i<4; ++i)
  148. {
  149. s_ArrowTri[i].clear();
  150. s_ArrowNorm[i].clear();
  151. }
  152. float x0, x1, y0, y1, z0, z1, a0, a1, nx, nn;
  153. for(i=0; i<SUBDIV; ++i)
  154. {
  155. a0 = 2.0f*FLOAT_PI*(float(i))/SUBDIV;
  156. a1 = 2.0f*FLOAT_PI*(float(i+1))/SUBDIV;
  157. x0 = ARROW_BGN;
  158. x1 = ARROW_END-CONE_LENGTH;
  159. y0 = cosf(a0);
  160. z0 = sinf(a0);
  161. y1 = cosf(a1);
  162. z1 = sinf(a1);
  163. s_ArrowTri[ARROW_CYL].push_back(x1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z0);
  164. s_ArrowTri[ARROW_CYL].push_back(x0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z0);
  165. s_ArrowTri[ARROW_CYL].push_back(x0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z1);
  166. s_ArrowTri[ARROW_CYL].push_back(x1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z0);
  167. s_ArrowTri[ARROW_CYL].push_back(x0); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z1);
  168. s_ArrowTri[ARROW_CYL].push_back(x1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*y1); s_ArrowTri[ARROW_CYL].push_back(CYL_RADIUS*z1);
  169. s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y0); s_ArrowNorm[ARROW_CYL].push_back(z0);
  170. s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y0); s_ArrowNorm[ARROW_CYL].push_back(z0);
  171. s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y1); s_ArrowNorm[ARROW_CYL].push_back(z1);
  172. s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y0); s_ArrowNorm[ARROW_CYL].push_back(z0);
  173. s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y1); s_ArrowNorm[ARROW_CYL].push_back(z1);
  174. s_ArrowNorm[ARROW_CYL].push_back(0); s_ArrowNorm[ARROW_CYL].push_back(y1); s_ArrowNorm[ARROW_CYL].push_back(z1);
  175. s_ArrowTri[ARROW_CYL_CAP].push_back(x0); s_ArrowTri[ARROW_CYL_CAP].push_back(0); s_ArrowTri[ARROW_CYL_CAP].push_back(0);
  176. s_ArrowTri[ARROW_CYL_CAP].push_back(x0); s_ArrowTri[ARROW_CYL_CAP].push_back(CYL_RADIUS*y1); s_ArrowTri[ARROW_CYL_CAP].push_back(CYL_RADIUS*z1);
  177. s_ArrowTri[ARROW_CYL_CAP].push_back(x0); s_ArrowTri[ARROW_CYL_CAP].push_back(CYL_RADIUS*y0); s_ArrowTri[ARROW_CYL_CAP].push_back(CYL_RADIUS*z0);
  178. s_ArrowNorm[ARROW_CYL_CAP].push_back(-1); s_ArrowNorm[ARROW_CYL_CAP].push_back(0); s_ArrowNorm[ARROW_CYL_CAP].push_back(0);
  179. s_ArrowNorm[ARROW_CYL_CAP].push_back(-1); s_ArrowNorm[ARROW_CYL_CAP].push_back(0); s_ArrowNorm[ARROW_CYL_CAP].push_back(0);
  180. s_ArrowNorm[ARROW_CYL_CAP].push_back(-1); s_ArrowNorm[ARROW_CYL_CAP].push_back(0); s_ArrowNorm[ARROW_CYL_CAP].push_back(0);
  181. x0 = ARROW_END-CONE_LENGTH;
  182. x1 = ARROW_END;
  183. nx = CONE_RADIUS/(x1-x0);
  184. nn = 1.0f/sqrtf(nx*nx+1);
  185. s_ArrowTri[ARROW_CONE].push_back(x1); s_ArrowTri[ARROW_CONE].push_back(0); s_ArrowTri[ARROW_CONE].push_back(0);
  186. s_ArrowTri[ARROW_CONE].push_back(x0); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*y0); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*z0);
  187. s_ArrowTri[ARROW_CONE].push_back(x0); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*y1); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*z1);
  188. s_ArrowTri[ARROW_CONE].push_back(x1); s_ArrowTri[ARROW_CONE].push_back(0); s_ArrowTri[ARROW_CONE].push_back(0);
  189. s_ArrowTri[ARROW_CONE].push_back(x0); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*y1); s_ArrowTri[ARROW_CONE].push_back(CONE_RADIUS*z1);
  190. s_ArrowTri[ARROW_CONE].push_back(x1); s_ArrowTri[ARROW_CONE].push_back(0); s_ArrowTri[ARROW_CONE].push_back(0);
  191. s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y0); s_ArrowNorm[ARROW_CONE].push_back(nn*z0);
  192. s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y0); s_ArrowNorm[ARROW_CONE].push_back(nn*z0);
  193. s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y1); s_ArrowNorm[ARROW_CONE].push_back(nn*z1);
  194. s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y0); s_ArrowNorm[ARROW_CONE].push_back(nn*z0);
  195. s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y1); s_ArrowNorm[ARROW_CONE].push_back(nn*z1);
  196. s_ArrowNorm[ARROW_CONE].push_back(nn*nx); s_ArrowNorm[ARROW_CONE].push_back(nn*y1); s_ArrowNorm[ARROW_CONE].push_back(nn*z1);
  197. s_ArrowTri[ARROW_CONE_CAP].push_back(x0); s_ArrowTri[ARROW_CONE_CAP].push_back(0); s_ArrowTri[ARROW_CONE_CAP].push_back(0);
  198. s_ArrowTri[ARROW_CONE_CAP].push_back(x0); s_ArrowTri[ARROW_CONE_CAP].push_back(CONE_RADIUS*y1); s_ArrowTri[ARROW_CONE_CAP].push_back(CONE_RADIUS*z1);
  199. s_ArrowTri[ARROW_CONE_CAP].push_back(x0); s_ArrowTri[ARROW_CONE_CAP].push_back(CONE_RADIUS*y0); s_ArrowTri[ARROW_CONE_CAP].push_back(CONE_RADIUS*z0);
  200. s_ArrowNorm[ARROW_CONE_CAP].push_back(-1); s_ArrowNorm[ARROW_CONE_CAP].push_back(0); s_ArrowNorm[ARROW_CONE_CAP].push_back(0);
  201. s_ArrowNorm[ARROW_CONE_CAP].push_back(-1); s_ArrowNorm[ARROW_CONE_CAP].push_back(0); s_ArrowNorm[ARROW_CONE_CAP].push_back(0);
  202. s_ArrowNorm[ARROW_CONE_CAP].push_back(-1); s_ArrowNorm[ARROW_CONE_CAP].push_back(0); s_ArrowNorm[ARROW_CONE_CAP].push_back(0);
  203. }
  204. //for(i=0; i<4; ++i)
  205. //{
  206. // s_ArrowTriProj[i].clear();
  207. // s_ArrowTriProj[i].resize(2*(s_ArrowTri[i].size()/3), 0);
  208. // s_ArrowColLight[i].clear();
  209. // s_ArrowColLight[i].resize(s_ArrowTri[i].size()/3, 0);
  210. //}
  211. }
  212. ////////////////////////////////////////////////////////////////////////////
  213. // End Copied Straight from AntTweakBar
  214. ////////////////////////////////////////////////////////////////////////////
  215. IGL_INLINE void igl::draw_beach_ball()
  216. {
  217. using namespace std;
  218. CreateSphere();
  219. // Keep track of opengl settings
  220. int cm;
  221. glGetIntegerv(GL_COLOR_MATERIAL,&cm);
  222. // Draw triangles
  223. glEnable(GL_COLOR_MATERIAL);
  224. glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
  225. float mat_ambient[4] = {0.1,0.1,0.1,1.0};
  226. float mat_specular[4] = {0.0,0.0,0.0,1.0};
  227. float mat_shininess = 1;
  228. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
  229. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
  230. glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
  231. glPushMatrix();
  232. glScalef(0.7,0.7,0.7);
  233. glEnable(GL_NORMALIZE);
  234. glBegin(GL_TRIANGLES);
  235. for(int i = 0;i<(int)s_SphCol.size();i++)
  236. {
  237. glNormal3fv(&s_SphTri[i*3]);
  238. glColor4ub(GLubyte(s_SphCol[i]>>16), GLubyte(s_SphCol[i]>>8), GLubyte(s_SphCol[i]), GLubyte(s_SphCol[i]>>24));
  239. glVertex3fv(&s_SphTri[i*3]);
  240. }
  241. glEnd();
  242. glPopMatrix();
  243. CreateArrow();
  244. for(int k = 0;k<3;k++)
  245. {
  246. glPushMatrix();
  247. glColor3f(k==0,k==1,k==2);
  248. glRotatef((k==2?-1.0:1.0)*90,k==0,k==2,k==1);
  249. glBegin(GL_TRIANGLES);
  250. for(int j = 0;j<4;j++)
  251. {
  252. for(int i = 0;i<(int)s_ArrowTri[j].size();i+=3)
  253. {
  254. glNormal3fv(&s_ArrowNorm[j][i]);
  255. glVertex3fv(&s_ArrowTri[j][i]);
  256. }
  257. }
  258. glEnd();
  259. glPopMatrix();
  260. }
  261. (cm ? glEnable(GL_COLOR_MATERIAL):glDisable(GL_COLOR_MATERIAL));
  262. }
  263. #endif