// --------------------------------------------------------------------------- // // @file TwAdvanced1.cpp // @brief An example showing many features of AntTweakBar. // It also uses OpenGL and GLFW windowing system // but could be easily adapted to other frameworks. // // AntTweakBar: http://www.antisphere.com/Wiki/tools:anttweakbar // OpenGL: http://www.opengl.org // GLFW: http://glfw.sourceforge.net // // // 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 - http://www.antisphere.com // @date 2006/05/20 // // note: TAB=4 // // Compilation: // http://www.antisphere.com/Wiki/tools:anttweakbar:examples#twadvanced1 // // --------------------------------------------------------------------------- #include #define GLFW_DLL // use GLFW as a dynamically linked library #include "glfw.h" #include #include #ifndef _WIN32 # define _snprintf snprintf #endif const float FLOAT_2PI = 6.283185307f; // 2*PI // Light structure: embed 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 tesselate 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) float 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)intialize the scene void Draw(); // draw scene void Update(float 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); void DrawSubdivCylinderY(float xCenter, float yBottom, float zCenter, float height, float radiusBottom, float radiusTop, int sideSubdiv, int ySubdiv); void DrawSubdivHaloZ(float x, float y, float z, float radius, int subdiv); void DrawHalos(bool reflected); 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.6f; BgColor1[1] = 0.6f; BgColor1[2] = 0.6f; Ambient = 0.3f; 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 = maxLights/2; // default number of lights if( NumLights==0 ) NumLights = 1; 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; ilights[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(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 lightsBar = TwNewBar("Lights"); TwDefine(" Lights label='Lights TweakBar' "); // 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 "); // Set the NumLights min value (=0) and max value (depends on the user graphic card) char def[256]; _snprintf(def, 255, "Lights/NumLights min=0 max=%d", maxLights); TwDefine(def); // min and max are defined using a defintion 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=RETURN "); // 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 embeded in this structure TwStructMember lightMembers[] = // array used to describe tweakable variables of the Light structure { { "Active", TW_TYPE_BOOLCPP, offsetof(Light, Active), "" }, // Light::Active is a C++ boolean value { "Color", TW_TYPE_COLOR4F, offsetof(Light, Color), "noalpha" }, // 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" }, { "Animation", modeType, offsetof(Light, Animation), "" }, // use the enum 'modeType' created before to tweak the Light::Animation variable { "Speed", TW_TYPE_FLOAT, offsetof(Light, Speed0), "readonly" } // 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