/external/AntTweakBar-1.16/examples/TwAdvanced1.cpp
C++ | 737 lines | 506 code | 102 blank | 129 comment | 43 complexity | 6270136ec57cec4f08bda2e95bd4dfc4 MD5 | raw file
- // ---------------------------------------------------------------------------
- //
- // @file TwAdvanced1.cpp
- // @brief An example showing many features of AntTweakBar,
- // including variable accessed by callbacks and
- // the definition of a custom structure type.
- // It also uses OpenGL and GLFW windowing system
- // but could be easily adapted to other frameworks.
- //
- // AntTweakBar: http://anttweakbar.sourceforge.net/doc
- // OpenGL: http://www.opengl.org
- // GLFW: http://www.glfw.org
- //
- //
- // This example draws a simple scene that can be re-tesselated
- // interactively, and illuminated dynamically by an adjustable
- // number of moving lights.
- //
- //
- // @author Philippe Decaudin
- // @date 2006/05/20
- //
- // ---------------------------------------------------------------------------
- #include <AntTweakBar.h>
- #define GLFW_DLL // use GLFW as a dynamically linked library
- #include "glfw.h"
- #include <cmath>
- #include <iostream>
- #include <cstdlib>
- #include <cstdio>
- #if !defined(_WIN32) && !defined(_WIN64)
- # define _snprintf snprintf
- #endif
- const float FLOAT_2PI = 6.283185307f; // 2*PI
- // Light structure: embeds light parameters
- struct Light
- {
- bool Active; // light On or Off
- float Pos[4]; // light position (in homogeneous coordinates, ie. Pos[4]=1)
- float Color[4]; // light color (no alpha, ie. Color[4]=1)
- float Radius; // radius of the light influence area
- float Dist0, Angle0, Height0, Speed0; // light initial cylindrical coordinates and speed
- char Name[4]; // light short name (will be named "1", "2", "3",...)
- enum AnimMode { ANIM_FIXED, ANIM_BOUNCE, ANIM_ROTATE, ANIM_COMBINED };
- AnimMode Animation; // light animation mode
- };
- // Class that describes the scene and its methods
- class Scene
- {
- public:
- bool Wireframe; // draw scene in wireframe or filled
- int Subdiv; // number of subdivisions used to tessellate the scene
- int NumLights; // number of dynamic lights
- float BgColor0[3], BgColor1[3]; // top and bottom background colors
- float Ambient; // scene ambient factor
- float Reflection; // ground plane reflection factor (0=no reflection, 1=full reflection)
- double RotYAngle; // rotation angle of the scene around its Y axis (in degree)
- enum RotMode { ROT_OFF, ROT_CW, ROT_CCW };
- RotMode Rotation; // scene rotation mode (off, clockwise, counter-clockwise)
- Scene(); // constructor
- ~Scene(); // destructor
- void Init(bool changeLightPos); // (re)initialize the scene
- void Draw() const; // draw scene
- void Update(double time); // move lights
- private:
- void CreateBar(); // create a tweak bar for lights
- // Some drawing subroutines
- void DrawSubdivPlaneY(float xMin, float xMax, float y, float zMin, float zMax, int xSubdiv, int zSubdiv) const;
- void DrawSubdivCylinderY(float xCenter, float yBottom, float zCenter, float height, float radiusBottom, float radiusTop, int sideSubdiv, int ySubdiv) const;
- void DrawSubdivHaloZ(float x, float y, float z, float radius, int subdiv) const;
- void DrawHalos(bool reflected) const;
- GLuint objList, groundList, haloList; // OpenGL display list IDs
- int maxLights; // maximum number of dynamic lights allowed by the graphic card
- Light * lights; // array of lights
- TwBar * lightsBar; // pointer to the tweak bar for lights created by CreateBar()
- };
- // Constructor
- Scene::Scene()
- {
- // Set scene members.
- // The scene will be created by Scene::Init( )
- Wireframe = false;
- Subdiv = 20;
- NumLights = 0;
- BgColor0[0] = 0.9f;
- BgColor0[1] = 0.0f;
- BgColor0[2] = 0.0f;
- BgColor1[0] = 0.3f;
- BgColor1[1] = 0.0f;
- BgColor1[2] = 0.0f;
- Ambient = 0.2f;
- Reflection = 0.5f;
- RotYAngle = 0;
- Rotation = ROT_CCW;
- objList = 0;
- groundList = 0;
- haloList = 0;
- maxLights = 0;
- lights = NULL;
- lightsBar = NULL;
- }
- // Destructor
- Scene::~Scene()
- {
- // delete all lights
- if( lights )
- delete[] lights;
- }
- // Create the scene, and (re)initialize lights if changeLights is true
- void Scene::Init(bool changeLights)
- {
- // Get the max number of lights allowed by the graphic card
- glGetIntegerv(GL_MAX_LIGHTS, &maxLights);
- if( maxLights>16 )
- maxLights = 16;
- // Create the lights array
- if( lights==NULL && maxLights>0 )
- {
- lights = new Light[maxLights];
- NumLights = 3; // default number of lights
- if( NumLights>maxLights )
- NumLights = maxLights;
- changeLights = true; // force lights initialization
- // Create a tweak bar for lights
- CreateBar();
- }
- // (Re)initialize lights if needed (uses random values)
- if( changeLights )
- for(int i=0; i<maxLights; ++i)
- {
- lights[i].Dist0 = 0.5f*(float)rand()/RAND_MAX + 0.55f;
- lights[i].Angle0 = FLOAT_2PI*((float)rand()/RAND_MAX);
- lights[i].Height0 = FLOAT_2PI*(float)rand()/RAND_MAX;
- lights[i].Speed0 = 4.0f*(float)rand()/RAND_MAX - 2.0f;
- lights[i].Animation = (Light::AnimMode)(Light::ANIM_BOUNCE + (rand()%3));
- lights[i].Radius = (float)rand()/RAND_MAX+0.05f;
- lights[i].Color[0] = (float)rand()/RAND_MAX;
- lights[i].Color[1] = (float)rand()/RAND_MAX;
- lights[i].Color[2] = (lights[i].Color[0]>lights[i].Color[1]) ? 1.0f-lights[i].Color[1] : 1.0f-lights[i].Color[0];
- lights[i].Color[3] = 1;
- lights[i].Active = true;
- }
- // Initialize some OpenGL states
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_LIGHTING);
- glEnable(GL_CULL_FACE);
- glEnable(GL_NORMALIZE);
- glEnable(GL_COLOR_MATERIAL);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
- // Create objects display list using the current Subdiv parameter to control the tesselation
- if( objList>0 )
- glDeleteLists(objList, 1); // delete previously created display list
- objList = glGenLists(1);
- glNewList(objList, GL_COMPILE);
- DrawSubdivCylinderY(-0.9f, 0, -0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv);
- DrawSubdivCylinderY(+0.9f, 0, -0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv);
- DrawSubdivCylinderY(+0.9f, 0, +0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv);
- DrawSubdivCylinderY(-0.9f, 0, +0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv);
- DrawSubdivCylinderY(0, 0, 0, 0.4f, 0.5f, 0.3f, Subdiv+16, Subdiv/8+1);
- DrawSubdivCylinderY(0, 0.4f, 0, 0.05f, 0.3f, 0.0f, Subdiv+16, Subdiv/16+1);
- glEndList();
- // Create ground display list
- if( groundList>0 )
- glDeleteLists(groundList, 1); // delete previously created display list
- groundList = glGenLists(1);
- glNewList(groundList, GL_COMPILE);
- DrawSubdivPlaneY(-1.2f, 1.2f, 0, -1.2f, 1.2f, (3*Subdiv)/2, (3*Subdiv)/2);
- glEndList();
- // Create display list to draw light halos
- if( haloList>0 )
- glDeleteLists(haloList, 1); // delete previously created display list
- haloList = glGenLists(1);
- glNewList(haloList, GL_COMPILE);
- DrawSubdivHaloZ(0, 0, 0, 1, 32);
- glEndList();
- }
- // Callback function associated to the 'Change lights' button of the lights tweak bar.
- void TW_CALL ReinitCB(void *clientData)
- {
- Scene *scene = static_cast<Scene *>(clientData); // scene pointer is stored in clientData
- scene->Init(true); // re-initialize the scene
- }
- // Create a tweak bar for lights.
- // New enum type and struct type are defined and used by this bar.
- void Scene::CreateBar()
- {
- // Create a new tweak bar and change its label, position and transparency
- lightsBar = TwNewBar("Lights");
- TwDefine(" Lights label='Lights TweakBar' position='580 16' alpha=0 help='Use this bar to edit the lights in the scene.' ");
- // Add a variable of type int to control the number of lights
- TwAddVarRW(lightsBar, "NumLights", TW_TYPE_INT32, &NumLights,
- " label='Number of lights' keyIncr=l keyDecr=L help='Changes the number of lights in the scene.' ");
- // Set the NumLights min value (=0) and max value (depends on the user graphic card)
- int zero = 0;
- TwSetParam(lightsBar, "NumLights", "min", TW_PARAM_INT32, 1, &zero);
- TwSetParam(lightsBar, "NumLights", "max", TW_PARAM_INT32, 1, &maxLights);
- // Note, TwDefine could also have been used for that pupose like this:
- // char def[256];
- // _snprintf(def, 255, "Lights/NumLights min=0 max=%d", maxLights);
- // TwDefine(def); // min and max are defined using a definition string
- // Add a button to re-initialize the lights; this button calls the ReinitCB callback function
- TwAddButton(lightsBar, "Reinit", ReinitCB, this,
- " label='Change lights' key=c help='Random changes of lights parameters.' ");
- // Define a new enum type for the tweak bar
- TwEnumVal modeEV[] = // array used to describe the Scene::AnimMode enum values
- {
- { Light::ANIM_FIXED, "Fixed" },
- { Light::ANIM_BOUNCE, "Bounce" },
- { Light::ANIM_ROTATE, "Rotate" },
- { Light::ANIM_COMBINED, "Combined" }
- };
- TwType modeType = TwDefineEnum("Mode", modeEV, 4); // create a new TwType associated to the enum defined by the modeEV array
- // Define a new struct type: light variables are embedded in this structure
- TwStructMember lightMembers[] = // array used to describe tweakable variables of the Light structure
- {
- { "Active", TW_TYPE_BOOLCPP, offsetof(Light, Active), " help='Enable/disable the light.' " }, // Light::Active is a C++ boolean value
- { "Color", TW_TYPE_COLOR4F, offsetof(Light, Color), " noalpha help='Light color.' " }, // Light::Color is represented by 4 floats, but alpha channel should be ignored
- { "Radius", TW_TYPE_FLOAT, offsetof(Light, Radius), " min=0 max=4 step=0.02 help='Light radius.' " },
- { "Animation", modeType, offsetof(Light, Animation), " help='Change the animation mode.' " }, // use the enum 'modeType' created before to tweak the Light::Animation variable
- { "Speed", TW_TYPE_FLOAT, offsetof(Light, Speed0), " readonly=true help='Light moving speed.' " } // Light::Speed is made read-only
- };
- TwType lightType = TwDefineStruct("Light", lightMembers, 5, sizeof(Light), NULL, NULL); // create a new TwType associated to the struct defined by the lightMembers array
- // Use the newly created 'lightType' to add variables associated with lights
- for(int i=0; i<maxLights; ++i) // Add 'maxLights' variables of type lightType;
- { // unused lights variables (over NumLights) will hidden by Scene::Update( )
- _snprintf(lights[i].Name, sizeof(lights[i].Name), "%d", i+1); // Create a name for each light ("1", "2", "3",...)
- TwAddVarRW(lightsBar, lights[i].Name, lightType, &lights[i], " group='Edit lights' "); // Add a lightType variable and group it into the 'Edit lights' group
- // Set 'label' and 'help' parameters of the light
- char paramValue[64];
- _snprintf(paramValue, sizeof(paramValue), "Light #%d", i+1);
- TwSetParam(lightsBar, lights[i].Name, "label", TW_PARAM_CSTRING, 1, paramValue); // Set label
- _snprintf(paramValue, sizeof(paramValue), "Parameters of the light #%d", i+1);
- TwSetParam(lightsBar, lights[i].Name, "help", TW_PARAM_CSTRING, 1, paramValue); // Set help
- // Note, parameters could also have been set using the define string of TwAddVarRW like this:
- // char def[256];
- // _snprintf(def, sizeof(def), "group='Edit lights' label='Light #%d' help='Parameters of the light #%d' ", i+1, i+1);
- // 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'
- }
- }
- // Move lights
- void Scene::Update(double time)
- {
- float horizSpeed, vertSpeed;
- for(int i=0; i<NumLights; ++i)
- {
- // Change light position according to its current animation mode
- if( lights[i].Animation==Light::ANIM_ROTATE || lights[i].Animation==Light::ANIM_COMBINED )
- horizSpeed = lights[i].Speed0;
- else
- horizSpeed = 0;
- if( lights[i].Animation==Light::ANIM_BOUNCE || lights[i].Animation==Light::ANIM_COMBINED )
- vertSpeed = 1;
- else
- vertSpeed = 0;
- lights[i].Pos[0] = lights[i].Dist0 * (float)cos(horizSpeed*time + lights[i].Angle0);
- lights[i].Pos[1] = (float)fabs(cos(vertSpeed*time + lights[i].Height0));
- lights[i].Pos[2] = lights[i].Dist0 * (float)sin(horizSpeed*time + lights[i].Angle0);
- lights[i].Pos[3] = 1;
- }
- }
- // Activate OpenGL lights; hide unused lights in the Lights tweak bar;
- // and draw the scene. The scene is reflected by the ground plane, so it is
- // drawn two times: first reflected, and second normal (unreflected).
- void Scene::Draw() const
- {
- // Rotate the scene
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glRotated(RotYAngle, 0, 1, 0);
- // Hide/active lights
- int i, lightVisible;
- for(i=0; i<maxLights; ++i)
- {
- if( i<NumLights )
- {
- // Lights under NumLights are shown in the Lights tweak bar
- lightVisible = 1;
- // Tell OpenGL to enable or disable the light
- if( lights[i].Active )
- glEnable(GL_LIGHT0+i);
- else
- glDisable(GL_LIGHT0+i);
- // Update OpenGL light parameters (for the reflected scene)
- float reflectPos[4] = { lights[i].Pos[0], -lights[i].Pos[1], lights[i].Pos[2], lights[i].Pos[3] };
- glLightfv(GL_LIGHT0+i, GL_POSITION, reflectPos);
- glLightfv(GL_LIGHT0+i, GL_DIFFUSE, lights[i].Color);
- glLightf(GL_LIGHT0+i, GL_CONSTANT_ATTENUATION, 1);
- glLightf(GL_LIGHT0+i, GL_LINEAR_ATTENUATION, 0);
- glLightf(GL_LIGHT0+i, GL_QUADRATIC_ATTENUATION, 1.0f/(lights[i].Radius*lights[i].Radius));
- }
- else
- {
- // Lights over NumLights are hidden in the Lights tweak bar
- lightVisible = 0;
- // Disable the OpenGL light
- glDisable(GL_LIGHT0+i);
-
- }
- // Show or hide the light variable in the Lights tweak bar
- TwSetParam(lightsBar, lights[i].Name, "visible", TW_PARAM_INT32, 1, &lightVisible);
- }
- // Set global ambient and clear screen and depth buffer
- float ambient[4] = { Ambient*(BgColor0[0]+BgColor1[0])/2, Ambient*(BgColor0[1]+BgColor1[1])/2,
- Ambient*(BgColor0[2]+BgColor1[2])/2, 1 };
- glClearColor(ambient[0], ambient[1], ambient[2], 1);
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
- glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
- // Draw the reflected scene
- glPolygonMode(GL_FRONT_AND_BACK, (Wireframe ? GL_LINE : GL_FILL));
- glCullFace(GL_FRONT);
- glPushMatrix();
- glScalef(1, -1, 1);
- glColor3f(1, 1, 1);
- glCallList(objList);
- DrawHalos(true);
- glPopMatrix();
- glCullFace(GL_BACK);
- // clear depth buffer again
- glClear(GL_DEPTH_BUFFER_BIT);
- // Draw the ground plane (using the Reflection parameter as transparency)
- glColor4f(1, 1, 1, 1.0f-Reflection);
- glCallList(groundList);
- // Draw the gradient background (requires to switch to screen-space normalized coordinates)
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glDisable(GL_LIGHTING);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glBegin(GL_QUADS);
- glColor3f(BgColor0[0], BgColor0[1], BgColor0[2]);
- glVertex3f(-1, -1, 0.9f);
- glVertex3f(1, -1, 0.9f);
- glColor3f(BgColor1[0], BgColor1[1], BgColor1[2]);
- glVertex3f(1, 1, 0.9f);
- glVertex3f(-1, 1, 0.9f);
- glEnd();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- glEnable(GL_LIGHTING);
- // Update light positions for unreflected scene
- for(i=0; i<NumLights; ++i)
- glLightfv(GL_LIGHT0+i, GL_POSITION, lights[i].Pos);
- // Draw the unreflected scene
- glPolygonMode(GL_FRONT_AND_BACK, (Wireframe ? GL_LINE : GL_FILL));
- glColor3f(1, 1, 1);
- glCallList(objList);
- DrawHalos(false);
- }
- // Subroutine used to draw halos around light positions
- void Scene::DrawHalos(bool reflected) const
- {
- //glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- glDepthMask(GL_FALSE);
- float prevAmbient[4];
- glGetFloatv(GL_LIGHT_MODEL_AMBIENT, prevAmbient);
- glPushMatrix();
- glLoadIdentity();
- if( reflected )
- glScalef(1, -1 ,1);
- float black[4] = {0, 0, 0, 1};
- float cr = (float)cos(FLOAT_2PI*RotYAngle/360.0f);
- float sr = (float)sin(FLOAT_2PI*RotYAngle/360.0f);
- for(int i=0; i<NumLights; ++i)
- {
- if( lights[i].Active )
- glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lights[i].Color);
- else
- glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black);
- glPushMatrix();
- 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]);
- //glScalef(0.5f*lights[i].Radius, 0.5f*lights[i].Radius, 1);
- glScalef(0.05f, 0.05f, 1);
- glCallList(haloList);
- glPopMatrix();
- }
- glPopMatrix();
- glLightModelfv(GL_LIGHT_MODEL_AMBIENT, prevAmbient);
- glDepthMask(GL_TRUE);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- // Subroutine used to build the ground plane display list (mesh subdivision is adjustable)
- void Scene::DrawSubdivPlaneY(float xMin, float xMax, float y, float zMin, float zMax, int xSubdiv, int zSubdiv) const
- {
- const float FLOAT_EPS = 1.0e-5f;
- float dx = (xMax-xMin)/xSubdiv;
- float dz = (zMax-zMin)/zSubdiv;
- glBegin(GL_QUADS);
- glNormal3f(0, -1, 0);
- for( float z=zMin; z<zMax-FLOAT_EPS; z+=dz )
- for( float x=xMin; x<xMax-FLOAT_EPS; x+=dx )
- {
- glVertex3f(x, y, z);
- glVertex3f(x, y, z+dz);
- glVertex3f(x+dx, y, z+dz);
- glVertex3f(x+dx, y, z);
- }
- glEnd();
- }
- // Subroutine used to build objects display list (mesh subdivision is adjustable)
- void Scene::DrawSubdivCylinderY(float xCenter, float yBottom, float zCenter, float height, float radiusBottom, float radiusTop, int sideSubdiv, int ySubdiv) const
- {
- float h0, h1, y0, y1, r0, r1, a0, a1, cosa0, sina0, cosa1, sina1;
- glBegin(GL_QUADS);
- glNormal3f(0, 1, 0);
- for( int j=0; j<ySubdiv; ++j )
- for( int i=0; i<sideSubdiv; ++i )
- {
- h0 = (float)j/ySubdiv;
- h1 = (float)(j+1)/ySubdiv;
- y0 = yBottom + h0*height;
- y1 = yBottom + h1*height;
- r0 = radiusBottom + h0*(radiusTop-radiusBottom);
- r1 = radiusBottom + h1*(radiusTop-radiusBottom);
- a0 = FLOAT_2PI*(float)i/sideSubdiv;
- a1 = FLOAT_2PI*(float)(i+1)/sideSubdiv;
- cosa0 = (float)cos(a0);
- sina0 = (float)sin(a0);
- cosa1 = (float)cos(a1);
- sina1 = (float)sin(a1);
- glNormal3f(cosa0, 0, sina0);
- glVertex3f(xCenter+r0*cosa0, y0, zCenter+r0*sina0);
- glNormal3f(cosa0, 0, sina0);
- glVertex3f(xCenter+r1*cosa0, y1, zCenter+r1*sina0);
- glNormal3f(cosa1, 0, sina1);
- glVertex3f(xCenter+r1*cosa1, y1, zCenter+r1*sina1);
- glNormal3f(cosa1, 0, sina1);
- glVertex3f(xCenter+r0*cosa1, y0, zCenter+r0*sina1);
- }
- glEnd();
- }
- // Subroutine used to build halo display list
- void Scene::DrawSubdivHaloZ(float x, float y, float z, float radius, int subdiv) const
- {
- glBegin(GL_TRIANGLE_FAN);
- glNormal3f(0, 0, 0);
- glColor4f(1, 1, 1, 1);
- glVertex3f(x, y, z);
- for( int i=0; i<=subdiv; ++i )
- {
- glColor4f(1, 1, 1, 0);
- glVertex3f(x+radius*(float)cos(FLOAT_2PI*(float)i/subdiv), x+radius*(float)sin(FLOAT_2PI*(float)i/subdiv), z);
- }
- glEnd();
- }
- // Callback function called by GLFW when a mouse button is clicked
- void GLFWCALL OnMouseButton(int glfwButton, int glfwAction)
- {
- if( !TwEventMouseButtonGLFW(glfwButton, glfwAction) ) // Send event to AntTweakBar
- {
- // Event has not been handled by AntTweakBar
- // Do something if needed.
- }
- }
- // Callback function called by GLFW when mouse has moved
- void GLFWCALL OnMousePos(int mouseX, int mouseY)
- {
- if( !TwEventMousePosGLFW(mouseX, mouseY) ) // Send event to AntTweakBar
- {
- // Event has not been handled by AntTweakBar
- // Do something if needed.
- }
- }
- // Callback function called by GLFW on mouse wheel event
- void GLFWCALL OnMouseWheel(int pos)
- {
- if( !TwEventMouseWheelGLFW(pos) ) // Send event to AntTweakBar
- {
- // Event has not been handled by AntTweakBar
- // Do something if needed.
- }
- }
- // Callback function called by GLFW on key event
- void GLFWCALL OnKey(int glfwKey, int glfwAction)
- {
- if( !TwEventKeyGLFW(glfwKey, glfwAction) ) // Send event to AntTweakBar
- {
- if( glfwKey==GLFW_KEY_ESC && glfwAction==GLFW_PRESS ) // Want to quit?
- glfwCloseWindow();
- else
- {
- // Event has not been handled
- // Do something if needed.
- }
- }
- }
- // Callback function called by GLFW on char event
- void GLFWCALL OnChar(int glfwChar, int glfwAction)
- {
- if( !TwEventCharGLFW(glfwChar, glfwAction) ) // Send event to AntTweakBar
- {
- // Event has not been handled by AntTweakBar
- // Do something if needed.
- }
- }
- // Callback function called by GLFW when window size changes
- void GLFWCALL OnWindowSize(int width, int height)
- {
- // Set OpenGL viewport and camera
- glViewport(0, 0, width, height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(40, (double)width/height, 1, 10);
- gluLookAt(-0.3,1,3.5, -0.3,0,0, 0,1,0);
- glTranslated(0, -0.3, 0);
-
- // Send the new window size to AntTweakBar
- TwWindowSize(width, height);
- }
- // Callback function called when the 'Subdiv' variable value of the main tweak bar has changed.
- void TW_CALL SetSubdivCB(const void *value, void *clientData)
- {
- Scene *scene = static_cast<Scene *>(clientData); // scene pointer is stored in clientData
- scene->Subdiv = *static_cast<const int *>(value); // copy value to scene->Subdiv
- scene->Init(false); // re-init scene with the new Subdiv parameter
- }
- // Callback function called by the main tweak bar to get the 'Subdiv' value
- void TW_CALL GetSubdivCB(void *value, void *clientData)
- {
- Scene *scene = static_cast<Scene *>(clientData); // scene pointer is stored in clientData
- *static_cast<int *>(value) = scene->Subdiv; // copy scene->Subdiv to value
- }
- // Main function
- int main()
- {
- // Initialize GLFW
- if( !glfwInit() )
- {
- // A fatal error occurred
- std::cerr << "GLFW initialization failed" << std::endl;
- return 1;
- }
- // Create a window
- GLFWvidmode mode;
- glfwGetDesktopMode(&mode);
- if( !glfwOpenWindow(800, 600, mode.RedBits, mode.GreenBits, mode.BlueBits, 0, 16, 0, GLFW_WINDOW /* or GLFW_FULLSCREEN */) )
- {
- // A fatal error occurred
- std::cerr << "Cannot open GLFW window" << std::endl;
- glfwTerminate();
- return 1;
- }
- glfwSwapInterval(0);
- glfwEnable(GLFW_MOUSE_CURSOR);
- glfwEnable(GLFW_KEY_REPEAT);
- const char title[] = "AntTweakBar example: TwAdvanced1";
- glfwSetWindowTitle(title);
- // Set GLFW event callbacks
- glfwSetWindowSizeCallback(OnWindowSize);
- glfwSetMouseButtonCallback(OnMouseButton);
- glfwSetMousePosCallback(OnMousePos);
- glfwSetMouseWheelCallback(OnMouseWheel);
- glfwSetKeyCallback(OnKey);
- glfwSetCharCallback(OnChar);
- // Initialize AntTweakBar
- TwInit(TW_OPENGL, NULL);
- // Change the font size, and add a global message to the Help bar.
- TwDefine(" GLOBAL fontSize=3 help='This example illustrates the definition of custom structure type as well as many other features.' ");
- // Initialize the 3D scene
- Scene scene;
- scene.Init(true);
- // Create a tweak bar called 'Main' and change its refresh rate, position, size and transparency
- TwBar *mainBar = TwNewBar("Main");
- TwDefine(" Main label='Main TweakBar' refresh=0.5 position='16 16' size='260 320' alpha=0");
- // Add some variables to the Main tweak bar
- TwAddVarRW(mainBar, "Wireframe", TW_TYPE_BOOLCPP, &scene.Wireframe,
- " group='Display' key=w help='Toggle wireframe display mode.' "); // 'Wireframe' is put in the group 'Display' (which is then created)
- TwAddVarRW(mainBar, "BgTop", TW_TYPE_COLOR3F, &scene.BgColor1,
- " group='Background' help='Change the top background color.' "); // 'BgTop' and 'BgBottom' are put in the group 'Background' (which is then created)
- TwAddVarRW(mainBar, "BgBottom", TW_TYPE_COLOR3F, &scene.BgColor0,
- " group='Background' help='Change the bottom background color.' ");
- TwDefine(" Main/Background group='Display' "); // The group 'Background' of bar 'Main' is put in the group 'Display'
- TwAddVarCB(mainBar, "Subdiv", TW_TYPE_INT32, SetSubdivCB, GetSubdivCB, &scene,
- " 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).' ");
- TwAddVarRW(mainBar, "Ambient", TW_TYPE_FLOAT, &scene.Ambient,
- " label='Ambient factor' group='Scene' min=0 max=1 step=0.001 keyIncr=a keyDecr=A help='Change scene ambient.' ");
- TwAddVarRW(mainBar, "Reflection", TW_TYPE_FLOAT, &scene.Reflection,
- " label='Reflection factor' group='Scene' min=0 max=1 step=0.001 keyIncr=r keyDecr=R help='Change ground reflection.' ");
- // Create a new TwType called rotationType associated with the Scene::RotMode enum, and use it
- TwEnumVal rotationEV[] = { { Scene::ROT_OFF, "Stopped"},
- { Scene::ROT_CW, "Clockwise" },
- { Scene::ROT_CCW, "Counter-clockwise" } };
- TwType rotationType = TwDefineEnum( "Rotation Mode", rotationEV, 3 );
- TwAddVarRW(mainBar, "Rotation", rotationType, &scene.Rotation,
- " group='Scene' keyIncr=Backspace keyDecr=SHIFT+Backspace help='Stop or change the rotation mode.' ");
- // Add a read-only float variable; its precision is 0 which means that the fractionnal part of the float value will not be displayed
- TwAddVarRO(mainBar, "RotYAngle", TW_TYPE_DOUBLE, &scene.RotYAngle,
- " group='Scene' label='Rot angle (degree)' precision=0 help='Animated rotation angle' ");
- // Initialize time
- double time = glfwGetTime(), dt = 0; // Current time and elapsed time
- double frameDTime = 0, frameCount = 0, fps = 0; // Framerate
- // Main loop (repeated while window is not closed)
- while( glfwGetWindowParam(GLFW_OPENED) )
- {
- // Get elapsed time
- dt = glfwGetTime() - time;
- if (dt < 0) dt = 0;
- time += dt;
- // Rotate scene
- if( scene.Rotation==Scene::ROT_CW )
- scene.RotYAngle -= 5.0*dt;
- else if( scene.Rotation==Scene::ROT_CCW )
- scene.RotYAngle += 5.0*dt;
- // Move lights
- scene.Update(time);
- // Draw scene
- scene.Draw();
- // Draw tweak bars
- TwDraw();
- // Present frame buffer
- glfwSwapBuffers();
- // Estimate framerate
- frameCount++;
- frameDTime += dt;
- if( frameDTime>1.0 )
- {
- fps = frameCount/frameDTime;
- char newTitle[128];
- _snprintf(newTitle, sizeof(newTitle), "%s (%.1f fps)", title, fps);
- //glfwSetWindowTitle(newTitle); // uncomment to display framerate
- frameCount = frameDTime = 0;
- }
- }
- // Terminate AntTweakBar and GLFW
- TwTerminate();
- glfwTerminate();
- return 0;
- }