PageRenderTime 64ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/external/AntTweakBar-1.16/examples/TwAdvanced1.cpp

https://gitlab.com/dannywillems/mass_collide
C++ | 737 lines | 506 code | 102 blank | 129 comment | 43 complexity | 6270136ec57cec4f08bda2e95bd4dfc4 MD5 | raw file
  1. // ---------------------------------------------------------------------------
  2. //
  3. // @file TwAdvanced1.cpp
  4. // @brief An example showing many features of AntTweakBar,
  5. // including variable accessed by callbacks and
  6. // the definition of a custom structure type.
  7. // It also uses OpenGL and GLFW windowing system
  8. // but could be easily adapted to other frameworks.
  9. //
  10. // AntTweakBar: http://anttweakbar.sourceforge.net/doc
  11. // OpenGL: http://www.opengl.org
  12. // GLFW: http://www.glfw.org
  13. //
  14. //
  15. // This example draws a simple scene that can be re-tesselated
  16. // interactively, and illuminated dynamically by an adjustable
  17. // number of moving lights.
  18. //
  19. //
  20. // @author Philippe Decaudin
  21. // @date 2006/05/20
  22. //
  23. // ---------------------------------------------------------------------------
  24. #include <AntTweakBar.h>
  25. #define GLFW_DLL // use GLFW as a dynamically linked library
  26. #include "glfw.h"
  27. #include <cmath>
  28. #include <iostream>
  29. #include <cstdlib>
  30. #include <cstdio>
  31. #if !defined(_WIN32) && !defined(_WIN64)
  32. # define _snprintf snprintf
  33. #endif
  34. const float FLOAT_2PI = 6.283185307f; // 2*PI
  35. // Light structure: embeds light parameters
  36. struct Light
  37. {
  38. bool Active; // light On or Off
  39. float Pos[4]; // light position (in homogeneous coordinates, ie. Pos[4]=1)
  40. float Color[4]; // light color (no alpha, ie. Color[4]=1)
  41. float Radius; // radius of the light influence area
  42. float Dist0, Angle0, Height0, Speed0; // light initial cylindrical coordinates and speed
  43. char Name[4]; // light short name (will be named "1", "2", "3",...)
  44. enum AnimMode { ANIM_FIXED, ANIM_BOUNCE, ANIM_ROTATE, ANIM_COMBINED };
  45. AnimMode Animation; // light animation mode
  46. };
  47. // Class that describes the scene and its methods
  48. class Scene
  49. {
  50. public:
  51. bool Wireframe; // draw scene in wireframe or filled
  52. int Subdiv; // number of subdivisions used to tessellate the scene
  53. int NumLights; // number of dynamic lights
  54. float BgColor0[3], BgColor1[3]; // top and bottom background colors
  55. float Ambient; // scene ambient factor
  56. float Reflection; // ground plane reflection factor (0=no reflection, 1=full reflection)
  57. double RotYAngle; // rotation angle of the scene around its Y axis (in degree)
  58. enum RotMode { ROT_OFF, ROT_CW, ROT_CCW };
  59. RotMode Rotation; // scene rotation mode (off, clockwise, counter-clockwise)
  60. Scene(); // constructor
  61. ~Scene(); // destructor
  62. void Init(bool changeLightPos); // (re)initialize the scene
  63. void Draw() const; // draw scene
  64. void Update(double time); // move lights
  65. private:
  66. void CreateBar(); // create a tweak bar for lights
  67. // Some drawing subroutines
  68. void DrawSubdivPlaneY(float xMin, float xMax, float y, float zMin, float zMax, int xSubdiv, int zSubdiv) const;
  69. void DrawSubdivCylinderY(float xCenter, float yBottom, float zCenter, float height, float radiusBottom, float radiusTop, int sideSubdiv, int ySubdiv) const;
  70. void DrawSubdivHaloZ(float x, float y, float z, float radius, int subdiv) const;
  71. void DrawHalos(bool reflected) const;
  72. GLuint objList, groundList, haloList; // OpenGL display list IDs
  73. int maxLights; // maximum number of dynamic lights allowed by the graphic card
  74. Light * lights; // array of lights
  75. TwBar * lightsBar; // pointer to the tweak bar for lights created by CreateBar()
  76. };
  77. // Constructor
  78. Scene::Scene()
  79. {
  80. // Set scene members.
  81. // The scene will be created by Scene::Init( )
  82. Wireframe = false;
  83. Subdiv = 20;
  84. NumLights = 0;
  85. BgColor0[0] = 0.9f;
  86. BgColor0[1] = 0.0f;
  87. BgColor0[2] = 0.0f;
  88. BgColor1[0] = 0.3f;
  89. BgColor1[1] = 0.0f;
  90. BgColor1[2] = 0.0f;
  91. Ambient = 0.2f;
  92. Reflection = 0.5f;
  93. RotYAngle = 0;
  94. Rotation = ROT_CCW;
  95. objList = 0;
  96. groundList = 0;
  97. haloList = 0;
  98. maxLights = 0;
  99. lights = NULL;
  100. lightsBar = NULL;
  101. }
  102. // Destructor
  103. Scene::~Scene()
  104. {
  105. // delete all lights
  106. if( lights )
  107. delete[] lights;
  108. }
  109. // Create the scene, and (re)initialize lights if changeLights is true
  110. void Scene::Init(bool changeLights)
  111. {
  112. // Get the max number of lights allowed by the graphic card
  113. glGetIntegerv(GL_MAX_LIGHTS, &maxLights);
  114. if( maxLights>16 )
  115. maxLights = 16;
  116. // Create the lights array
  117. if( lights==NULL && maxLights>0 )
  118. {
  119. lights = new Light[maxLights];
  120. NumLights = 3; // default number of lights
  121. if( NumLights>maxLights )
  122. NumLights = maxLights;
  123. changeLights = true; // force lights initialization
  124. // Create a tweak bar for lights
  125. CreateBar();
  126. }
  127. // (Re)initialize lights if needed (uses random values)
  128. if( changeLights )
  129. for(int i=0; i<maxLights; ++i)
  130. {
  131. lights[i].Dist0 = 0.5f*(float)rand()/RAND_MAX + 0.55f;
  132. lights[i].Angle0 = FLOAT_2PI*((float)rand()/RAND_MAX);
  133. lights[i].Height0 = FLOAT_2PI*(float)rand()/RAND_MAX;
  134. lights[i].Speed0 = 4.0f*(float)rand()/RAND_MAX - 2.0f;
  135. lights[i].Animation = (Light::AnimMode)(Light::ANIM_BOUNCE + (rand()%3));
  136. lights[i].Radius = (float)rand()/RAND_MAX+0.05f;
  137. lights[i].Color[0] = (float)rand()/RAND_MAX;
  138. lights[i].Color[1] = (float)rand()/RAND_MAX;
  139. lights[i].Color[2] = (lights[i].Color[0]>lights[i].Color[1]) ? 1.0f-lights[i].Color[1] : 1.0f-lights[i].Color[0];
  140. lights[i].Color[3] = 1;
  141. lights[i].Active = true;
  142. }
  143. // Initialize some OpenGL states
  144. glMatrixMode(GL_MODELVIEW);
  145. glLoadIdentity();
  146. glEnable(GL_DEPTH_TEST);
  147. glEnable(GL_BLEND);
  148. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  149. glEnable(GL_LIGHTING);
  150. glEnable(GL_CULL_FACE);
  151. glEnable(GL_NORMALIZE);
  152. glEnable(GL_COLOR_MATERIAL);
  153. glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
  154. glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
  155. // Create objects display list using the current Subdiv parameter to control the tesselation
  156. if( objList>0 )
  157. glDeleteLists(objList, 1); // delete previously created display list
  158. objList = glGenLists(1);
  159. glNewList(objList, GL_COMPILE);
  160. DrawSubdivCylinderY(-0.9f, 0, -0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv);
  161. DrawSubdivCylinderY(+0.9f, 0, -0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv);
  162. DrawSubdivCylinderY(+0.9f, 0, +0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv);
  163. DrawSubdivCylinderY(-0.9f, 0, +0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv);
  164. DrawSubdivCylinderY(0, 0, 0, 0.4f, 0.5f, 0.3f, Subdiv+16, Subdiv/8+1);
  165. DrawSubdivCylinderY(0, 0.4f, 0, 0.05f, 0.3f, 0.0f, Subdiv+16, Subdiv/16+1);
  166. glEndList();
  167. // Create ground display list
  168. if( groundList>0 )
  169. glDeleteLists(groundList, 1); // delete previously created display list
  170. groundList = glGenLists(1);
  171. glNewList(groundList, GL_COMPILE);
  172. DrawSubdivPlaneY(-1.2f, 1.2f, 0, -1.2f, 1.2f, (3*Subdiv)/2, (3*Subdiv)/2);
  173. glEndList();
  174. // Create display list to draw light halos
  175. if( haloList>0 )
  176. glDeleteLists(haloList, 1); // delete previously created display list
  177. haloList = glGenLists(1);
  178. glNewList(haloList, GL_COMPILE);
  179. DrawSubdivHaloZ(0, 0, 0, 1, 32);
  180. glEndList();
  181. }
  182. // Callback function associated to the 'Change lights' button of the lights tweak bar.
  183. void TW_CALL ReinitCB(void *clientData)
  184. {
  185. Scene *scene = static_cast<Scene *>(clientData); // scene pointer is stored in clientData
  186. scene->Init(true); // re-initialize the scene
  187. }
  188. // Create a tweak bar for lights.
  189. // New enum type and struct type are defined and used by this bar.
  190. void Scene::CreateBar()
  191. {
  192. // Create a new tweak bar and change its label, position and transparency
  193. lightsBar = TwNewBar("Lights");
  194. TwDefine(" Lights label='Lights TweakBar' position='580 16' alpha=0 help='Use this bar to edit the lights in the scene.' ");
  195. // Add a variable of type int to control the number of lights
  196. TwAddVarRW(lightsBar, "NumLights", TW_TYPE_INT32, &NumLights,
  197. " label='Number of lights' keyIncr=l keyDecr=L help='Changes the number of lights in the scene.' ");
  198. // Set the NumLights min value (=0) and max value (depends on the user graphic card)
  199. int zero = 0;
  200. TwSetParam(lightsBar, "NumLights", "min", TW_PARAM_INT32, 1, &zero);
  201. TwSetParam(lightsBar, "NumLights", "max", TW_PARAM_INT32, 1, &maxLights);
  202. // Note, TwDefine could also have been used for that pupose like this:
  203. // char def[256];
  204. // _snprintf(def, 255, "Lights/NumLights min=0 max=%d", maxLights);
  205. // TwDefine(def); // min and max are defined using a definition string
  206. // Add a button to re-initialize the lights; this button calls the ReinitCB callback function
  207. TwAddButton(lightsBar, "Reinit", ReinitCB, this,
  208. " label='Change lights' key=c help='Random changes of lights parameters.' ");
  209. // Define a new enum type for the tweak bar
  210. TwEnumVal modeEV[] = // array used to describe the Scene::AnimMode enum values
  211. {
  212. { Light::ANIM_FIXED, "Fixed" },
  213. { Light::ANIM_BOUNCE, "Bounce" },
  214. { Light::ANIM_ROTATE, "Rotate" },
  215. { Light::ANIM_COMBINED, "Combined" }
  216. };
  217. TwType modeType = TwDefineEnum("Mode", modeEV, 4); // create a new TwType associated to the enum defined by the modeEV array
  218. // Define a new struct type: light variables are embedded in this structure
  219. TwStructMember lightMembers[] = // array used to describe tweakable variables of the Light structure
  220. {
  221. { "Active", TW_TYPE_BOOLCPP, offsetof(Light, Active), " help='Enable/disable the light.' " }, // Light::Active is a C++ boolean value
  222. { "Color", TW_TYPE_COLOR4F, offsetof(Light, Color), " noalpha help='Light color.' " }, // Light::Color is represented by 4 floats, but alpha channel should be ignored
  223. { "Radius", TW_TYPE_FLOAT, offsetof(Light, Radius), " min=0 max=4 step=0.02 help='Light radius.' " },
  224. { "Animation", modeType, offsetof(Light, Animation), " help='Change the animation mode.' " }, // use the enum 'modeType' created before to tweak the Light::Animation variable
  225. { "Speed", TW_TYPE_FLOAT, offsetof(Light, Speed0), " readonly=true help='Light moving speed.' " } // Light::Speed is made read-only
  226. };
  227. TwType lightType = TwDefineStruct("Light", lightMembers, 5, sizeof(Light), NULL, NULL); // create a new TwType associated to the struct defined by the lightMembers array
  228. // Use the newly created 'lightType' to add variables associated with lights
  229. for(int i=0; i<maxLights; ++i) // Add 'maxLights' variables of type lightType;
  230. { // unused lights variables (over NumLights) will hidden by Scene::Update( )
  231. _snprintf(lights[i].Name, sizeof(lights[i].Name), "%d", i+1); // Create a name for each light ("1", "2", "3",...)
  232. TwAddVarRW(lightsBar, lights[i].Name, lightType, &lights[i], " group='Edit lights' "); // Add a lightType variable and group it into the 'Edit lights' group
  233. // Set 'label' and 'help' parameters of the light
  234. char paramValue[64];
  235. _snprintf(paramValue, sizeof(paramValue), "Light #%d", i+1);
  236. TwSetParam(lightsBar, lights[i].Name, "label", TW_PARAM_CSTRING, 1, paramValue); // Set label
  237. _snprintf(paramValue, sizeof(paramValue), "Parameters of the light #%d", i+1);
  238. TwSetParam(lightsBar, lights[i].Name, "help", TW_PARAM_CSTRING, 1, paramValue); // Set help
  239. // Note, parameters could also have been set using the define string of TwAddVarRW like this:
  240. // char def[256];
  241. // _snprintf(def, sizeof(def), "group='Edit lights' label='Light #%d' help='Parameters of the light #%d' ", i+1, i+1);
  242. // TwAddVarRW(lightsBar, lights[i].Name, lightType, &lights[i], def); // Add a lightType variable, group it into the 'Edit lights' group, and name it 'Light #n'
  243. }
  244. }
  245. // Move lights
  246. void Scene::Update(double time)
  247. {
  248. float horizSpeed, vertSpeed;
  249. for(int i=0; i<NumLights; ++i)
  250. {
  251. // Change light position according to its current animation mode
  252. if( lights[i].Animation==Light::ANIM_ROTATE || lights[i].Animation==Light::ANIM_COMBINED )
  253. horizSpeed = lights[i].Speed0;
  254. else
  255. horizSpeed = 0;
  256. if( lights[i].Animation==Light::ANIM_BOUNCE || lights[i].Animation==Light::ANIM_COMBINED )
  257. vertSpeed = 1;
  258. else
  259. vertSpeed = 0;
  260. lights[i].Pos[0] = lights[i].Dist0 * (float)cos(horizSpeed*time + lights[i].Angle0);
  261. lights[i].Pos[1] = (float)fabs(cos(vertSpeed*time + lights[i].Height0));
  262. lights[i].Pos[2] = lights[i].Dist0 * (float)sin(horizSpeed*time + lights[i].Angle0);
  263. lights[i].Pos[3] = 1;
  264. }
  265. }
  266. // Activate OpenGL lights; hide unused lights in the Lights tweak bar;
  267. // and draw the scene. The scene is reflected by the ground plane, so it is
  268. // drawn two times: first reflected, and second normal (unreflected).
  269. void Scene::Draw() const
  270. {
  271. // Rotate the scene
  272. glMatrixMode(GL_MODELVIEW);
  273. glLoadIdentity();
  274. glRotated(RotYAngle, 0, 1, 0);
  275. // Hide/active lights
  276. int i, lightVisible;
  277. for(i=0; i<maxLights; ++i)
  278. {
  279. if( i<NumLights )
  280. {
  281. // Lights under NumLights are shown in the Lights tweak bar
  282. lightVisible = 1;
  283. // Tell OpenGL to enable or disable the light
  284. if( lights[i].Active )
  285. glEnable(GL_LIGHT0+i);
  286. else
  287. glDisable(GL_LIGHT0+i);
  288. // Update OpenGL light parameters (for the reflected scene)
  289. float reflectPos[4] = { lights[i].Pos[0], -lights[i].Pos[1], lights[i].Pos[2], lights[i].Pos[3] };
  290. glLightfv(GL_LIGHT0+i, GL_POSITION, reflectPos);
  291. glLightfv(GL_LIGHT0+i, GL_DIFFUSE, lights[i].Color);
  292. glLightf(GL_LIGHT0+i, GL_CONSTANT_ATTENUATION, 1);
  293. glLightf(GL_LIGHT0+i, GL_LINEAR_ATTENUATION, 0);
  294. glLightf(GL_LIGHT0+i, GL_QUADRATIC_ATTENUATION, 1.0f/(lights[i].Radius*lights[i].Radius));
  295. }
  296. else
  297. {
  298. // Lights over NumLights are hidden in the Lights tweak bar
  299. lightVisible = 0;
  300. // Disable the OpenGL light
  301. glDisable(GL_LIGHT0+i);
  302. }
  303. // Show or hide the light variable in the Lights tweak bar
  304. TwSetParam(lightsBar, lights[i].Name, "visible", TW_PARAM_INT32, 1, &lightVisible);
  305. }
  306. // Set global ambient and clear screen and depth buffer
  307. float ambient[4] = { Ambient*(BgColor0[0]+BgColor1[0])/2, Ambient*(BgColor0[1]+BgColor1[1])/2,
  308. Ambient*(BgColor0[2]+BgColor1[2])/2, 1 };
  309. glClearColor(ambient[0], ambient[1], ambient[2], 1);
  310. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  311. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
  312. // Draw the reflected scene
  313. glPolygonMode(GL_FRONT_AND_BACK, (Wireframe ? GL_LINE : GL_FILL));
  314. glCullFace(GL_FRONT);
  315. glPushMatrix();
  316. glScalef(1, -1, 1);
  317. glColor3f(1, 1, 1);
  318. glCallList(objList);
  319. DrawHalos(true);
  320. glPopMatrix();
  321. glCullFace(GL_BACK);
  322. // clear depth buffer again
  323. glClear(GL_DEPTH_BUFFER_BIT);
  324. // Draw the ground plane (using the Reflection parameter as transparency)
  325. glColor4f(1, 1, 1, 1.0f-Reflection);
  326. glCallList(groundList);
  327. // Draw the gradient background (requires to switch to screen-space normalized coordinates)
  328. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  329. glDisable(GL_LIGHTING);
  330. glMatrixMode(GL_PROJECTION);
  331. glPushMatrix();
  332. glLoadIdentity();
  333. glMatrixMode(GL_MODELVIEW);
  334. glPushMatrix();
  335. glLoadIdentity();
  336. glBegin(GL_QUADS);
  337. glColor3f(BgColor0[0], BgColor0[1], BgColor0[2]);
  338. glVertex3f(-1, -1, 0.9f);
  339. glVertex3f(1, -1, 0.9f);
  340. glColor3f(BgColor1[0], BgColor1[1], BgColor1[2]);
  341. glVertex3f(1, 1, 0.9f);
  342. glVertex3f(-1, 1, 0.9f);
  343. glEnd();
  344. glMatrixMode(GL_PROJECTION);
  345. glPopMatrix();
  346. glMatrixMode(GL_MODELVIEW);
  347. glPopMatrix();
  348. glEnable(GL_LIGHTING);
  349. // Update light positions for unreflected scene
  350. for(i=0; i<NumLights; ++i)
  351. glLightfv(GL_LIGHT0+i, GL_POSITION, lights[i].Pos);
  352. // Draw the unreflected scene
  353. glPolygonMode(GL_FRONT_AND_BACK, (Wireframe ? GL_LINE : GL_FILL));
  354. glColor3f(1, 1, 1);
  355. glCallList(objList);
  356. DrawHalos(false);
  357. }
  358. // Subroutine used to draw halos around light positions
  359. void Scene::DrawHalos(bool reflected) const
  360. {
  361. //glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  362. glDepthMask(GL_FALSE);
  363. float prevAmbient[4];
  364. glGetFloatv(GL_LIGHT_MODEL_AMBIENT, prevAmbient);
  365. glPushMatrix();
  366. glLoadIdentity();
  367. if( reflected )
  368. glScalef(1, -1 ,1);
  369. float black[4] = {0, 0, 0, 1};
  370. float cr = (float)cos(FLOAT_2PI*RotYAngle/360.0f);
  371. float sr = (float)sin(FLOAT_2PI*RotYAngle/360.0f);
  372. for(int i=0; i<NumLights; ++i)
  373. {
  374. if( lights[i].Active )
  375. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lights[i].Color);
  376. else
  377. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black);
  378. glPushMatrix();
  379. glTranslatef(cr*lights[i].Pos[0]+sr*lights[i].Pos[2], lights[i].Pos[1], -sr*lights[i].Pos[0]+cr*lights[i].Pos[2]);
  380. //glScalef(0.5f*lights[i].Radius, 0.5f*lights[i].Radius, 1);
  381. glScalef(0.05f, 0.05f, 1);
  382. glCallList(haloList);
  383. glPopMatrix();
  384. }
  385. glPopMatrix();
  386. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, prevAmbient);
  387. glDepthMask(GL_TRUE);
  388. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  389. }
  390. // Subroutine used to build the ground plane display list (mesh subdivision is adjustable)
  391. void Scene::DrawSubdivPlaneY(float xMin, float xMax, float y, float zMin, float zMax, int xSubdiv, int zSubdiv) const
  392. {
  393. const float FLOAT_EPS = 1.0e-5f;
  394. float dx = (xMax-xMin)/xSubdiv;
  395. float dz = (zMax-zMin)/zSubdiv;
  396. glBegin(GL_QUADS);
  397. glNormal3f(0, -1, 0);
  398. for( float z=zMin; z<zMax-FLOAT_EPS; z+=dz )
  399. for( float x=xMin; x<xMax-FLOAT_EPS; x+=dx )
  400. {
  401. glVertex3f(x, y, z);
  402. glVertex3f(x, y, z+dz);
  403. glVertex3f(x+dx, y, z+dz);
  404. glVertex3f(x+dx, y, z);
  405. }
  406. glEnd();
  407. }
  408. // Subroutine used to build objects display list (mesh subdivision is adjustable)
  409. void Scene::DrawSubdivCylinderY(float xCenter, float yBottom, float zCenter, float height, float radiusBottom, float radiusTop, int sideSubdiv, int ySubdiv) const
  410. {
  411. float h0, h1, y0, y1, r0, r1, a0, a1, cosa0, sina0, cosa1, sina1;
  412. glBegin(GL_QUADS);
  413. glNormal3f(0, 1, 0);
  414. for( int j=0; j<ySubdiv; ++j )
  415. for( int i=0; i<sideSubdiv; ++i )
  416. {
  417. h0 = (float)j/ySubdiv;
  418. h1 = (float)(j+1)/ySubdiv;
  419. y0 = yBottom + h0*height;
  420. y1 = yBottom + h1*height;
  421. r0 = radiusBottom + h0*(radiusTop-radiusBottom);
  422. r1 = radiusBottom + h1*(radiusTop-radiusBottom);
  423. a0 = FLOAT_2PI*(float)i/sideSubdiv;
  424. a1 = FLOAT_2PI*(float)(i+1)/sideSubdiv;
  425. cosa0 = (float)cos(a0);
  426. sina0 = (float)sin(a0);
  427. cosa1 = (float)cos(a1);
  428. sina1 = (float)sin(a1);
  429. glNormal3f(cosa0, 0, sina0);
  430. glVertex3f(xCenter+r0*cosa0, y0, zCenter+r0*sina0);
  431. glNormal3f(cosa0, 0, sina0);
  432. glVertex3f(xCenter+r1*cosa0, y1, zCenter+r1*sina0);
  433. glNormal3f(cosa1, 0, sina1);
  434. glVertex3f(xCenter+r1*cosa1, y1, zCenter+r1*sina1);
  435. glNormal3f(cosa1, 0, sina1);
  436. glVertex3f(xCenter+r0*cosa1, y0, zCenter+r0*sina1);
  437. }
  438. glEnd();
  439. }
  440. // Subroutine used to build halo display list
  441. void Scene::DrawSubdivHaloZ(float x, float y, float z, float radius, int subdiv) const
  442. {
  443. glBegin(GL_TRIANGLE_FAN);
  444. glNormal3f(0, 0, 0);
  445. glColor4f(1, 1, 1, 1);
  446. glVertex3f(x, y, z);
  447. for( int i=0; i<=subdiv; ++i )
  448. {
  449. glColor4f(1, 1, 1, 0);
  450. glVertex3f(x+radius*(float)cos(FLOAT_2PI*(float)i/subdiv), x+radius*(float)sin(FLOAT_2PI*(float)i/subdiv), z);
  451. }
  452. glEnd();
  453. }
  454. // Callback function called by GLFW when a mouse button is clicked
  455. void GLFWCALL OnMouseButton(int glfwButton, int glfwAction)
  456. {
  457. if( !TwEventMouseButtonGLFW(glfwButton, glfwAction) ) // Send event to AntTweakBar
  458. {
  459. // Event has not been handled by AntTweakBar
  460. // Do something if needed.
  461. }
  462. }
  463. // Callback function called by GLFW when mouse has moved
  464. void GLFWCALL OnMousePos(int mouseX, int mouseY)
  465. {
  466. if( !TwEventMousePosGLFW(mouseX, mouseY) ) // Send event to AntTweakBar
  467. {
  468. // Event has not been handled by AntTweakBar
  469. // Do something if needed.
  470. }
  471. }
  472. // Callback function called by GLFW on mouse wheel event
  473. void GLFWCALL OnMouseWheel(int pos)
  474. {
  475. if( !TwEventMouseWheelGLFW(pos) ) // Send event to AntTweakBar
  476. {
  477. // Event has not been handled by AntTweakBar
  478. // Do something if needed.
  479. }
  480. }
  481. // Callback function called by GLFW on key event
  482. void GLFWCALL OnKey(int glfwKey, int glfwAction)
  483. {
  484. if( !TwEventKeyGLFW(glfwKey, glfwAction) ) // Send event to AntTweakBar
  485. {
  486. if( glfwKey==GLFW_KEY_ESC && glfwAction==GLFW_PRESS ) // Want to quit?
  487. glfwCloseWindow();
  488. else
  489. {
  490. // Event has not been handled
  491. // Do something if needed.
  492. }
  493. }
  494. }
  495. // Callback function called by GLFW on char event
  496. void GLFWCALL OnChar(int glfwChar, int glfwAction)
  497. {
  498. if( !TwEventCharGLFW(glfwChar, glfwAction) ) // Send event to AntTweakBar
  499. {
  500. // Event has not been handled by AntTweakBar
  501. // Do something if needed.
  502. }
  503. }
  504. // Callback function called by GLFW when window size changes
  505. void GLFWCALL OnWindowSize(int width, int height)
  506. {
  507. // Set OpenGL viewport and camera
  508. glViewport(0, 0, width, height);
  509. glMatrixMode(GL_PROJECTION);
  510. glLoadIdentity();
  511. gluPerspective(40, (double)width/height, 1, 10);
  512. gluLookAt(-0.3,1,3.5, -0.3,0,0, 0,1,0);
  513. glTranslated(0, -0.3, 0);
  514. // Send the new window size to AntTweakBar
  515. TwWindowSize(width, height);
  516. }
  517. // Callback function called when the 'Subdiv' variable value of the main tweak bar has changed.
  518. void TW_CALL SetSubdivCB(const void *value, void *clientData)
  519. {
  520. Scene *scene = static_cast<Scene *>(clientData); // scene pointer is stored in clientData
  521. scene->Subdiv = *static_cast<const int *>(value); // copy value to scene->Subdiv
  522. scene->Init(false); // re-init scene with the new Subdiv parameter
  523. }
  524. // Callback function called by the main tweak bar to get the 'Subdiv' value
  525. void TW_CALL GetSubdivCB(void *value, void *clientData)
  526. {
  527. Scene *scene = static_cast<Scene *>(clientData); // scene pointer is stored in clientData
  528. *static_cast<int *>(value) = scene->Subdiv; // copy scene->Subdiv to value
  529. }
  530. // Main function
  531. int main()
  532. {
  533. // Initialize GLFW
  534. if( !glfwInit() )
  535. {
  536. // A fatal error occurred
  537. std::cerr << "GLFW initialization failed" << std::endl;
  538. return 1;
  539. }
  540. // Create a window
  541. GLFWvidmode mode;
  542. glfwGetDesktopMode(&mode);
  543. if( !glfwOpenWindow(800, 600, mode.RedBits, mode.GreenBits, mode.BlueBits, 0, 16, 0, GLFW_WINDOW /* or GLFW_FULLSCREEN */) )
  544. {
  545. // A fatal error occurred
  546. std::cerr << "Cannot open GLFW window" << std::endl;
  547. glfwTerminate();
  548. return 1;
  549. }
  550. glfwSwapInterval(0);
  551. glfwEnable(GLFW_MOUSE_CURSOR);
  552. glfwEnable(GLFW_KEY_REPEAT);
  553. const char title[] = "AntTweakBar example: TwAdvanced1";
  554. glfwSetWindowTitle(title);
  555. // Set GLFW event callbacks
  556. glfwSetWindowSizeCallback(OnWindowSize);
  557. glfwSetMouseButtonCallback(OnMouseButton);
  558. glfwSetMousePosCallback(OnMousePos);
  559. glfwSetMouseWheelCallback(OnMouseWheel);
  560. glfwSetKeyCallback(OnKey);
  561. glfwSetCharCallback(OnChar);
  562. // Initialize AntTweakBar
  563. TwInit(TW_OPENGL, NULL);
  564. // Change the font size, and add a global message to the Help bar.
  565. TwDefine(" GLOBAL fontSize=3 help='This example illustrates the definition of custom structure type as well as many other features.' ");
  566. // Initialize the 3D scene
  567. Scene scene;
  568. scene.Init(true);
  569. // Create a tweak bar called 'Main' and change its refresh rate, position, size and transparency
  570. TwBar *mainBar = TwNewBar("Main");
  571. TwDefine(" Main label='Main TweakBar' refresh=0.5 position='16 16' size='260 320' alpha=0");
  572. // Add some variables to the Main tweak bar
  573. TwAddVarRW(mainBar, "Wireframe", TW_TYPE_BOOLCPP, &scene.Wireframe,
  574. " group='Display' key=w help='Toggle wireframe display mode.' "); // 'Wireframe' is put in the group 'Display' (which is then created)
  575. TwAddVarRW(mainBar, "BgTop", TW_TYPE_COLOR3F, &scene.BgColor1,
  576. " group='Background' help='Change the top background color.' "); // 'BgTop' and 'BgBottom' are put in the group 'Background' (which is then created)
  577. TwAddVarRW(mainBar, "BgBottom", TW_TYPE_COLOR3F, &scene.BgColor0,
  578. " group='Background' help='Change the bottom background color.' ");
  579. TwDefine(" Main/Background group='Display' "); // The group 'Background' of bar 'Main' is put in the group 'Display'
  580. TwAddVarCB(mainBar, "Subdiv", TW_TYPE_INT32, SetSubdivCB, GetSubdivCB, &scene,
  581. " group='Scene' label='Meshes subdivision' min=1 max=50 keyincr=s keyDecr=S help='Subdivide the meshes more or less (switch to wireframe to see the effect).' ");
  582. TwAddVarRW(mainBar, "Ambient", TW_TYPE_FLOAT, &scene.Ambient,
  583. " label='Ambient factor' group='Scene' min=0 max=1 step=0.001 keyIncr=a keyDecr=A help='Change scene ambient.' ");
  584. TwAddVarRW(mainBar, "Reflection", TW_TYPE_FLOAT, &scene.Reflection,
  585. " label='Reflection factor' group='Scene' min=0 max=1 step=0.001 keyIncr=r keyDecr=R help='Change ground reflection.' ");
  586. // Create a new TwType called rotationType associated with the Scene::RotMode enum, and use it
  587. TwEnumVal rotationEV[] = { { Scene::ROT_OFF, "Stopped"},
  588. { Scene::ROT_CW, "Clockwise" },
  589. { Scene::ROT_CCW, "Counter-clockwise" } };
  590. TwType rotationType = TwDefineEnum( "Rotation Mode", rotationEV, 3 );
  591. TwAddVarRW(mainBar, "Rotation", rotationType, &scene.Rotation,
  592. " group='Scene' keyIncr=Backspace keyDecr=SHIFT+Backspace help='Stop or change the rotation mode.' ");
  593. // Add a read-only float variable; its precision is 0 which means that the fractionnal part of the float value will not be displayed
  594. TwAddVarRO(mainBar, "RotYAngle", TW_TYPE_DOUBLE, &scene.RotYAngle,
  595. " group='Scene' label='Rot angle (degree)' precision=0 help='Animated rotation angle' ");
  596. // Initialize time
  597. double time = glfwGetTime(), dt = 0; // Current time and elapsed time
  598. double frameDTime = 0, frameCount = 0, fps = 0; // Framerate
  599. // Main loop (repeated while window is not closed)
  600. while( glfwGetWindowParam(GLFW_OPENED) )
  601. {
  602. // Get elapsed time
  603. dt = glfwGetTime() - time;
  604. if (dt < 0) dt = 0;
  605. time += dt;
  606. // Rotate scene
  607. if( scene.Rotation==Scene::ROT_CW )
  608. scene.RotYAngle -= 5.0*dt;
  609. else if( scene.Rotation==Scene::ROT_CCW )
  610. scene.RotYAngle += 5.0*dt;
  611. // Move lights
  612. scene.Update(time);
  613. // Draw scene
  614. scene.Draw();
  615. // Draw tweak bars
  616. TwDraw();
  617. // Present frame buffer
  618. glfwSwapBuffers();
  619. // Estimate framerate
  620. frameCount++;
  621. frameDTime += dt;
  622. if( frameDTime>1.0 )
  623. {
  624. fps = frameCount/frameDTime;
  625. char newTitle[128];
  626. _snprintf(newTitle, sizeof(newTitle), "%s (%.1f fps)", title, fps);
  627. //glfwSetWindowTitle(newTitle); // uncomment to display framerate
  628. frameCount = frameDTime = 0;
  629. }
  630. }
  631. // Terminate AntTweakBar and GLFW
  632. TwTerminate();
  633. glfwTerminate();
  634. return 0;
  635. }