diff --git a/Demos/Box2dDemo/Box2dDemo.cpp b/Demos/Box2dDemo/Box2dDemo.cpp index 2bb8239a1..59b64e762 100644 --- a/Demos/Box2dDemo/Box2dDemo.cpp +++ b/Demos/Box2dDemo/Box2dDemo.cpp @@ -17,8 +17,11 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h" +#include "GL_DialogDynamicsWorld.h" +#include "GL_DialogWindow.h" +#include "BulletCollision/CollisionShapes/btBox2dShape.h" #include "BulletCollision/CollisionShapes/btConvex2dShape.h" #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" @@ -61,6 +64,9 @@ void Box2dDemo::clientMoveAndDisplay() renderme(); + if (m_dialogDynamicsWorld) + m_dialogDynamicsWorld->draw(ms / 1000000.f); + glFlush(); glutSwapBuffers(); @@ -79,21 +85,62 @@ void Box2dDemo::displayCallback(void) { if (m_dynamicsWorld) m_dynamicsWorld->debugDrawWorld(); + if (m_dialogDynamicsWorld) + m_dialogDynamicsWorld->draw(0.f); + glFlush(); glutSwapBuffers(); } - +void Box2dDemo::reshape(int w, int h) +{ + if (m_dialogDynamicsWorld) + m_dialogDynamicsWorld->setScreenSize(w,h); + GlutDemoApplication::reshape(w,h); +} void Box2dDemo::initPhysics() { + + m_dialogDynamicsWorld = new GL_DialogDynamicsWorld(); + + //m_dialogDynamicsWorld->createDialog(100,110,200,50); + //m_dialogDynamicsWorld->createDialog(100,00,100,100); + //m_dialogDynamicsWorld->createDialog(0,0,100,100); + GL_DialogWindow* settings = m_dialogDynamicsWorld->createDialog(50,0,200,120,"Settings"); + GL_ToggleControl* toggle = m_dialogDynamicsWorld->createToggle(settings,"Toggle 1"); + toggle = m_dialogDynamicsWorld->createToggle(settings,"Toggle 2"); + toggle ->m_active = true; + toggle = m_dialogDynamicsWorld->createToggle(settings,"Toggle 3"); + GL_SliderControl* slider = m_dialogDynamicsWorld->createSlider(settings,"Slider"); + + GL_DialogWindow* dialog = m_dialogDynamicsWorld->createDialog(0,200,420,300,"Help"); + GL_TextControl* txt = new GL_TextControl; + dialog->addControl(txt); + txt->m_textLines.push_back("Mouse to move"); + txt->m_textLines.push_back("Test 2"); + txt->m_textLines.push_back("mouse to interact"); + txt->m_textLines.push_back("ALT + mouse to move camera"); + txt->m_textLines.push_back("space to reset"); + txt->m_textLines.push_back("cursor keys and z,x to navigate"); + txt->m_textLines.push_back("i to toggle simulation, s single step"); + txt->m_textLines.push_back("q to quit"); + txt->m_textLines.push_back(". to shoot box"); + txt->m_textLines.push_back("d to toggle deactivation"); + txt->m_textLines.push_back("g to toggle mesh animation (ConcaveDemo)"); + txt->m_textLines.push_back("h to toggle help text"); + txt->m_textLines.push_back("o to toggle orthogonal/perspective view"); + //txt->m_textLines.push_back("+- shooting speed = %10.2f",m_ShootBoxInitialSpeed); + + + setTexturing(true); setShadows(true); setCameraDistance(btScalar(SCALING*50.)); - m_cameraTargetPosition.setValue(0, ARRAY_SIZE_Y, 0); + m_cameraTargetPosition.setValue(0,0,0);//0, ARRAY_SIZE_Y, 0); ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); @@ -255,6 +302,8 @@ void Box2dDemo::initPhysics() void Box2dDemo::exitPhysics() { + delete m_dialogDynamicsWorld; + m_dialogDynamicsWorld = 0; //cleanup in the reverse order of creation/initialization @@ -292,6 +341,18 @@ void Box2dDemo::exitPhysics() } +void Box2dDemo::mouseFunc(int button, int state, int x, int y) +{ + if (!m_dialogDynamicsWorld->mouseFunc(button,state,x,y)) + { + DemoApplication::mouseFunc(button,state,x,y); + } +} +void Box2dDemo::mouseMotionFunc(int x,int y) +{ + m_dialogDynamicsWorld->mouseMotionFunc(x,y); + DemoApplication::mouseMotionFunc(x,y); +} diff --git a/Demos/Box2dDemo/Box2dDemo.h b/Demos/Box2dDemo/Box2dDemo.h index d83b0b8ff..8fccfbd09 100644 --- a/Demos/Box2dDemo/Box2dDemo.h +++ b/Demos/Box2dDemo/Box2dDemo.h @@ -25,6 +25,7 @@ class btCollisionDispatcher; class btConstraintSolver; struct btCollisionAlgorithmCreateFunc; class btDefaultCollisionConfiguration; +class GL_DialogDynamicsWorld; ///Box2dDemo is good starting point for learning the code base and porting. class Box2dDemo : public GlutDemoApplication @@ -41,15 +42,20 @@ class Box2dDemo : public GlutDemoApplication btDefaultCollisionConfiguration* m_collisionConfiguration; + GL_DialogDynamicsWorld* m_dialogDynamicsWorld; + public: - Box2dDemo() + Box2dDemo() : m_dialogDynamicsWorld(0) { } virtual ~Box2dDemo() { exitPhysics(); } + + virtual void reshape(int w, int h); + void initPhysics(); void exitPhysics(); @@ -66,6 +72,9 @@ class Box2dDemo : public GlutDemoApplication return demo; } + virtual void mouseFunc(int button, int state, int x, int y); + virtual void mouseMotionFunc(int x,int y); + }; diff --git a/Demos/OpenGL/DemoApplication.cpp b/Demos/OpenGL/DemoApplication.cpp index a754d2844..65be34f1b 100644 --- a/Demos/OpenGL/DemoApplication.cpp +++ b/Demos/OpenGL/DemoApplication.cpp @@ -1211,125 +1211,7 @@ void DemoApplication::renderme() #endif //USE_QUICKPROF - sprintf(buf,"mouse to interact"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"ALT + mouse to move camera"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"space to reset"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"cursor keys and z,x to navigate"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"i to toggle simulation, s single step"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"q to quit"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,". to shoot box"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - // not yet hooked up again after refactoring... - - sprintf(buf,"d to toggle deactivation"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - - sprintf(buf,"g to toggle mesh animation (ConcaveDemo)"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - - sprintf(buf,"h to toggle help text"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"o to toggle orthogonal/perspective view"); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - - //bool useBulletLCP = !(getDebugMode() & btIDebugDraw::DBG_DisableBulletLCP); - //bool useCCD = (getDebugMode() & btIDebugDraw::DBG_EnableCCD); - //glRasterPos3f(xOffset,yStart,0); - //sprintf(buf,"1 CCD mode (adhoc) = %i",useCCD); - //GLDebugDrawString(BMF_GetFont(BMF_kHelvetica10),buf); - //yStart += yIncr; - - - - sprintf(buf,"+- shooting speed = %10.2f",m_ShootBoxInitialSpeed); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - -#ifdef SHOW_NUM_DEEP_PENETRATIONS - - - sprintf(buf,"gNumDeepPenetrationChecks = %d",gNumDeepPenetrationChecks); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"gNumGjkChecks= %d",gNumGjkChecks); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - sprintf(buf,"gNumClampedCcdMotions = %d",gNumClampedCcdMotions); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"gNumSplitImpulseRecoveries= %d",gNumSplitImpulseRecoveries); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"gNumAlignedAllocs = %d",gNumAlignedAllocs); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"gNumAlignedFree= %d",gNumAlignedFree); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - sprintf(buf,"# alloc-free = %d",gNumAlignedAllocs-gNumAlignedFree); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - //enable BT_DEBUG_MEMORY_ALLOCATIONS define in Bullet/src/LinearMath/btAlignedAllocator.h for memory leak detection -#ifdef BT_DEBUG_MEMORY_ALLOCATIONS - glRasterPos3f(xOffset,yStart,0); - sprintf(buf,"gTotalBytesAlignedAllocs = %d",gTotalBytesAlignedAllocs); - GLDebugDrawString(BMF_GetFont(BMF_kHelvetica10),buf); - yStart += yIncr; -#endif //BT_DEBUG_MEMORY_ALLOCATIONS - - if (getDynamicsWorld()) - { - glRasterPos3f(xOffset,yStart,0); - sprintf(buf,"# objects = %d",getDynamicsWorld()->getNumCollisionObjects()); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - glRasterPos3f(xOffset,yStart,0); - sprintf(buf,"# pairs = %d",getDynamicsWorld()->getBroadphase()->getOverlappingPairCache()->getNumOverlappingPairs()); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - sprintf(buf,"# hitPos = %f,%f,%f",gHitPos.getX(),gHitPos.getY(),gHitPos.getZ()); - GLDebugDrawString(xOffset,yStart,buf); - yStart += yIncr; - - } - - -#endif //SHOW_NUM_DEEP_PENETRATIONS resetPerspectiveProjection(); } diff --git a/Demos/OpenGL/GLDebugFont.cpp b/Demos/OpenGL/GLDebugFont.cpp index a0cfa2786..e2dbebbd5 100644 --- a/Demos/OpenGL/GLDebugFont.cpp +++ b/Demos/OpenGL/GLDebugFont.cpp @@ -48,10 +48,10 @@ void GLDebugResetFont(int screenWidth,int screenHeight) } -void GLDebugDrawString(int x,int y,const char* string) -{ - const char* string2 = "test"; +void GLDebugDrawStringInternal(int x,int y,const char* string, const btVector3& rgb) +{ +const char* string2 = "test"; if (sTexture==-1) { GLDebugResetFont(sScreenWidth,sScreenHeight); @@ -59,7 +59,7 @@ void GLDebugDrawString(int x,int y,const char* string) if (strlen(string)) { - glColor3f(1.,1.,1.); + glColor3f(rgb.getX(),rgb.getY(),rgb.getZ()); float cx; float cy; @@ -128,6 +128,13 @@ void GLDebugDrawString(int x,int y,const char* string) } } +void GLDebugDrawString(int x,int y,const char* string) +{ + + btVector3 rgb(1,1,1); + GLDebugDrawStringInternal(x,y,string,rgb); +} + unsigned char sFontData[] = { diff --git a/Demos/OpenGL/GLDebugFont.h b/Demos/OpenGL/GLDebugFont.h index 1468c337b..3b91df0df 100644 --- a/Demos/OpenGL/GLDebugFont.h +++ b/Demos/OpenGL/GLDebugFont.h @@ -17,6 +17,9 @@ subject to the following restrictions: #ifndef BT_DEBUG_FONT_H #define BT_DEBUG_FONT_H +#include "LinearMath/btVector3.h" + +void GLDebugDrawStringInternal(int x,int y,const char* string,const btVector3& rgb); void GLDebugDrawString(int x,int y,const char* string); void GLDebugResetFont(int screenWidth,int screenHeight); diff --git a/Demos/OpenGL/GL_DialogDynamicsWorld.cpp b/Demos/OpenGL/GL_DialogDynamicsWorld.cpp new file mode 100644 index 000000000..486e799b0 --- /dev/null +++ b/Demos/OpenGL/GL_DialogDynamicsWorld.cpp @@ -0,0 +1,736 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "GL_DialogDynamicsWorld.h" +#include "GL_DialogWindow.h" +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h" +#include "BulletCollision/CollisionShapes/btBox2dShape.h" +#include "BulletCollision/CollisionShapes/btConvex2dShape.h" +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" + +GL_DialogDynamicsWorld::GL_DialogDynamicsWorld() +{ + m_upperBorder = 0; + m_lowerBorder =0; + + m_pickConstraint = 0; + m_screenWidth = 0; + m_screenHeight = 0; + + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + m_broadphase = new btDbvtBroadphase(); + m_constraintSolver = new btSequentialImpulseConstraintSolver(); + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_constraintSolver,m_collisionConfiguration); + m_dynamicsWorld ->getSolverInfo().m_splitImpulse = true; + //m_dynamicsWorld->setGravity(btVector3(0,10,0)); + m_dynamicsWorld->setGravity(btVector3(0,0,0)); + + m_simplexSolver = new btVoronoiSimplexSolver(); + m_pdSolver = new btMinkowskiPenetrationDepthSolver(); + + btConvex2dConvex2dAlgorithm::CreateFunc* convexAlgo2d = new btConvex2dConvex2dAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); + + m_dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE,CONVEX_2D_SHAPE_PROXYTYPE,convexAlgo2d); + m_dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE,CONVEX_2D_SHAPE_PROXYTYPE,convexAlgo2d); + m_dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE,BOX_2D_SHAPE_PROXYTYPE,convexAlgo2d); + m_dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE,BOX_2D_SHAPE_PROXYTYPE,new btBox2dBox2dCollisionAlgorithm::CreateFunc()); + + ///enable boarders, to avoid 'loosing' menus +#if 1 + btTransform tr; + tr.setIdentity(); + + { + btStaticPlaneShape* plane = new btStaticPlaneShape(btVector3(0,1,0),0); + m_upperBorder = new btCollisionObject(); + tr.setOrigin(btVector3(0,-BT_LARGE_FLOAT,0)); + m_upperBorder->setWorldTransform(tr); + m_upperBorder->setCollisionShape(plane); + m_dynamicsWorld->addCollisionObject(m_upperBorder); + } + + { + btStaticPlaneShape* plane = new btStaticPlaneShape(btVector3(0,-1,0),0); + m_lowerBorder = new btCollisionObject(); + + tr.setIdentity(); + tr.setOrigin(btVector3(0,BT_LARGE_FLOAT,0)); + m_lowerBorder->setWorldTransform(tr); + m_lowerBorder->setCollisionShape(plane); + m_dynamicsWorld->addCollisionObject(m_lowerBorder); + } + { + btStaticPlaneShape* plane = new btStaticPlaneShape(btVector3(1,0,0),0); + m_leftBorder = new btCollisionObject(); + tr.setIdentity(); + tr.setOrigin(btVector3(-BT_LARGE_FLOAT,0,0)); + m_leftBorder->setWorldTransform(tr); + m_leftBorder->setCollisionShape(plane); + m_dynamicsWorld->addCollisionObject(m_leftBorder); + } + { + btStaticPlaneShape* plane = new btStaticPlaneShape(btVector3(-1,0,0),0); + m_rightBorder = new btCollisionObject(); + tr.setIdentity(); + tr.setOrigin(btVector3(BT_LARGE_FLOAT,0,0)); + m_rightBorder->setWorldTransform(tr); + m_rightBorder->setCollisionShape(plane); + m_dynamicsWorld->addCollisionObject(m_rightBorder); + } +#endif + +} + +GL_DialogDynamicsWorld::~GL_DialogDynamicsWorld() +{ + delete m_dynamicsWorld; + delete m_dispatcher; + delete m_constraintSolver; + delete m_broadphase; + delete m_collisionConfiguration; +} + +void GL_DialogDynamicsWorld::setScreenSize(int width, int height) +{ + + + for (int i=0;igetCollisionObjectArray().size();i++) + { + btCollisionObject* colObj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(colObj); + if (body) + { + m_dynamicsWorld->removeRigidBody(body); + btVector3 newPos = colObj->getWorldTransform().getOrigin() + btVector3(m_screenWidth/2,m_screenHeight/2,0)-btVector3(width/2,height/2,0); + colObj->getWorldTransform().setOrigin(newPos); + m_dynamicsWorld->addRigidBody(body); + } else + { + m_dynamicsWorld->removeCollisionObject(colObj); + btVector3 newPos = colObj->getWorldTransform().getOrigin() + btVector3(m_screenWidth/2,m_screenHeight/2,0)-btVector3(width/2,height/2,0); + colObj->getWorldTransform().setOrigin(newPos); + m_dynamicsWorld->addCollisionObject(colObj); + } + } + + for (int i=0;isetScreenSize(width,height); + } + if (width && height) + { + if (m_upperBorder) + { + m_dynamicsWorld->removeCollisionObject(m_upperBorder); + + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(0,-height/2,0)); + m_upperBorder->setWorldTransform(tr); + m_dynamicsWorld->addCollisionObject(m_upperBorder); + } + + if (m_lowerBorder) + { + m_dynamicsWorld->removeCollisionObject(m_lowerBorder); + + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(0,height/2,0)); + m_lowerBorder->setWorldTransform(tr); + m_dynamicsWorld->addCollisionObject(m_lowerBorder); + } + if (m_leftBorder) + { + m_dynamicsWorld->removeCollisionObject(m_leftBorder); + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(-width/2,0,0)); + m_leftBorder->setWorldTransform(tr); + m_dynamicsWorld->addCollisionObject(m_leftBorder); + } + if (m_rightBorder) + { + m_dynamicsWorld->removeCollisionObject(m_rightBorder); + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(width/2,0,0)); + m_rightBorder->setWorldTransform(tr); + m_dynamicsWorld->addCollisionObject(m_rightBorder); + + } + + } + + + m_screenWidth = width; + m_screenHeight = height; +} + +GL_DialogWindow* GL_DialogDynamicsWorld::createDialog(int horPos,int vertPos,int dialogWidth,int dialogHeight, const char* dialogTitle ) +{ + btBox2dShape* boxShape = new btBox2dShape(btVector3(dialogWidth/2.,dialogHeight/2.,0.4)); + btScalar mass = 100.f; + btVector3 localInertia; + boxShape->calculateLocalInertia(mass,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,boxShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + btTransform trans; + trans.setIdentity(); + trans.setOrigin(btVector3(horPos-m_screenWidth/2+dialogWidth/2, vertPos+m_screenHeight/2.+dialogHeight/2,0.)); + + + + body->setWorldTransform(trans); + body->setDamping(0.999,0.99); + + //body->setContactProcessingThreshold(colShape->getContactBreakingThreshold()); + //body->setActivationState(ISLAND_SLEEPING); + body->setLinearFactor(btVector3(1,1,0)); + //body->setAngularFactor(btVector3(0,0,1)); + body->setAngularFactor(btVector3(0,0,0)); + + GL_DialogWindow* dialogWindow = new GL_DialogWindow(horPos,vertPos,dialogWidth,dialogHeight,body,dialogTitle); + m_dialogs.push_back(dialogWindow); + m_dynamicsWorld->addRigidBody(body); + + return dialogWindow; + +} + +GL_SliderControl* GL_DialogDynamicsWorld::createSlider(GL_DialogWindow* dialog, const char* sliderText) +{ + btBox2dShape* boxShape = new btBox2dShape(btVector3(6,6,0.4)); + btScalar mass = .1f; + btVector3 localInertia; + boxShape->calculateLocalInertia(mass,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,boxShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + btTransform trans; + trans.setIdentity(); + trans.setOrigin(btVector3(dialog->getDialogHorPos()-m_screenWidth/2+dialog->getDialogWidth()/2, dialog->getDialogVertPos()+m_screenHeight/2.+dialog->getDialogHeight()/2+dialog->getNumControls()*20,-0.2)); + + body->setWorldTransform(trans); + //body->setDamping(0.999,0.99); + + //body->setContactProcessingThreshold(colShape->getContactBreakingThreshold()); + //body->setActivationState(ISLAND_SLEEPING); + body->setLinearFactor(btVector3(1,1,0)); + //body->setAngularFactor(btVector3(0,0,1)); + body->setAngularFactor(btVector3(0,0,0)); + + m_dynamicsWorld->addRigidBody(body); + + btRigidBody* dialogBody = btRigidBody::upcast(dialog->getCollisionObject()); + btAssert(dialogBody); + + + + btTransform frameInA; + frameInA.setIdentity(); + btVector3 offset(btVector3(-dialog->getDialogWidth()/2+16,-dialog->getDialogHeight()/2+dialog->getNumControls()*20+36,0.2)); + frameInA.setOrigin(offset); + + + btTransform frameInB; + frameInB.setIdentity(); + //frameInB.setOrigin(-offset/2); + bool useFrameA = false; + + btScalar lowerLimit = 80; + btScalar upperLimit = 170; + +#if 0 + btGeneric6DofConstraint* constraint = new btGeneric6DofConstraint(*dialogBody,*body,frameInA,frameInB,useFrameA); + m_dynamicsWorld->addConstraint(constraint,true); + constraint->setLimit(0,lowerLimit,upperLimit); +#else + btSliderConstraint* sliderConstraint = new btSliderConstraint(*dialogBody,*body,frameInA,frameInB,true);//useFrameA); + sliderConstraint->setLowerLinLimit(lowerLimit); + sliderConstraint->setUpperLinLimit(upperLimit); + m_dynamicsWorld->addConstraint(sliderConstraint,true); + +#endif + + GL_SliderControl* slider = new GL_SliderControl(sliderText, body,dialog,lowerLimit,upperLimit, sliderConstraint); + body->setUserPointer(slider); + dialog->addControl(slider); + return slider; +} + + +GL_ToggleControl* GL_DialogDynamicsWorld::createToggle(GL_DialogWindow* dialog, const char* toggleText) +{ + + + btBox2dShape* boxShape = new btBox2dShape(btVector3(6,6,0.4)); + btScalar mass = 0.1f; + btVector3 localInertia; + boxShape->calculateLocalInertia(mass,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,boxShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + btTransform trans; + trans.setIdentity(); + trans.setOrigin(btVector3(dialog->getDialogHorPos()-m_screenWidth/2+dialog->getDialogWidth()/2, dialog->getDialogVertPos()+m_screenHeight/2.+dialog->getDialogHeight()/2+dialog->getNumControls()*20,-0.2)); + + body->setWorldTransform(trans); + body->setDamping(0.999,0.99); + + //body->setContactProcessingThreshold(colShape->getContactBreakingThreshold()); + //body->setActivationState(ISLAND_SLEEPING); + body->setLinearFactor(btVector3(1,1,0)); + //body->setAngularFactor(btVector3(0,0,1)); + body->setAngularFactor(btVector3(0,0,0)); + + m_dynamicsWorld->addRigidBody(body); + + btRigidBody* dialogBody = btRigidBody::upcast(dialog->getCollisionObject()); + btAssert(dialogBody); + + + + btTransform frameInA; + frameInA.setIdentity(); + btVector3 offset(btVector3(+dialog->getDialogWidth()/2-32,-dialog->getDialogHeight()/2+dialog->getNumControls()*20+36,0.2)); + frameInA.setOrigin(offset); + + + btTransform frameInB; + frameInB.setIdentity(); + //frameInB.setOrigin(-offset/2); + bool useFrameA = true; + + btGeneric6DofConstraint* constraint = new btGeneric6DofConstraint(*dialogBody,*body,frameInA,frameInB,useFrameA); + m_dynamicsWorld->addConstraint(constraint,true); + + + GL_ToggleControl* toggle = new GL_ToggleControl(toggleText, body,dialog); + body->setUserPointer(toggle); + dialog->addControl(toggle); + return toggle; +} + +void GL_DialogDynamicsWorld::draw(btScalar timeStep) +{ + if (timeStep) + { + m_dynamicsWorld->stepSimulation(timeStep); + } + + for (int i=0;idraw(timeStep); + } +} + +static btRigidBody* pickedBody = 0;//for deactivation state +static btScalar mousePickClamping = 111130.f; + +static int gPickingConstraintId = 0; +static btVector3 gOldPickingPos; +static btVector3 gHitPos(-1,-1,-1); + +static float gOldPickingDist = 0.f; + +bool GL_DialogDynamicsWorld::mouseFunc(int button, int state, int x, int y) +{ + if (state == 0) + { + m_mouseButtons |= 1<rayTest(m_cameraPosition,rayTo,rayCallback); + if (rayCallback.hasHit()) + { + + btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + body->setActivationState(ACTIVE_TAG); + btVector3 impulse = rayTo; + impulse.normalize(); + float impulseStrength = 10.f; + impulse *= impulseStrength; + btVector3 relPos = rayCallback.m_hitPointWorld - body->getCenterOfMassPosition(); + body->applyImpulse(impulse,relPos); + } + } + } +#endif + + + + } else + { + + } + break; + } + + case 0: + { + if (state==0) + { + + + //add a point to point constraint for picking + if (m_dynamicsWorld) + { + + btVector3 rayFrom; + if (1)//m_ortho) + { + rayFrom = rayTo; + rayFrom.setZ(-100.f); + } + //else + //{ + // rayFrom = m_cameraPosition; + //} + + btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo); + m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback); + if (rayCallback.hasHit()) + { + + + btScalar maxPickingClamp = mousePickClamping; + + btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + bool doPick = true; + if (body->getUserPointer()) + { + ///deal with controls in a special way + GL_DialogControl* ctrl = (GL_DialogControl*)body->getUserPointer(); + + switch(ctrl->getType()) + { + case GL_TOGGLE_CONTROL: + { + GL_ToggleControl* toggle = (GL_ToggleControl*) ctrl; + toggle->m_active = !toggle->m_active; + doPick = false; + break; + } + case GL_SLIDER_CONTROL: + { + GL_SliderControl* slider = (GL_SliderControl*) ctrl; + btTypedConstraint* constraint = slider->getConstraint(); + if (constraint->getConstraintType() == SLIDER_CONSTRAINT_TYPE) + { + btSliderConstraint* sliderConstraint = (btSliderConstraint*) constraint; + sliderConstraint->setLowerLinLimit(slider->getLowerLimit()); + sliderConstraint->setUpperLinLimit(slider->getUpperLimit()); + } + maxPickingClamp = 100; + } + default: + { + } + }; + + }; + + if (doPick) + { + //other exclusions? + if (!(body->isStaticObject() || body->isKinematicObject())) + { + pickedBody = body; + pickedBody->setActivationState(DISABLE_DEACTIVATION); + + + + btVector3 pickPos = rayCallback.m_hitPointWorld; + //printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ()); + + + btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos; + + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body,localPivot); + p2p->m_setting.m_impulseClamp = maxPickingClamp; + + m_dynamicsWorld->addConstraint(p2p); + m_pickConstraint = p2p; + + //save mouse position for dragging + gOldPickingPos = rayTo; + gHitPos = pickPos; + + gOldPickingDist = (pickPos-rayFrom).length(); + + //very weak constraint for picking + p2p->m_setting.m_tau = 0.1f; + } + } + return true; + } + } + } + + } else + { + + if (m_pickConstraint && m_dynamicsWorld) + { + m_dynamicsWorld->removeConstraint(m_pickConstraint); + delete m_pickConstraint; + //printf("removed constraint %i",gPickingConstraintId); + m_pickConstraint = 0; + pickedBody->forceActivationState(ACTIVE_TAG); + pickedBody->setDeactivationTime( 0.f ); + + + if (pickedBody->getUserPointer()) + { + ///deal with controls in a special way + GL_DialogControl* ctrl = (GL_DialogControl*)pickedBody->getUserPointer(); + if (ctrl->getType()==GL_SLIDER_CONTROL) + { + GL_SliderControl* sliderControl = (GL_SliderControl*) ctrl; + + btSliderConstraint* slider = 0; + btTypedConstraint* constraint = sliderControl->getConstraint(); + if (constraint->getConstraintType() == SLIDER_CONSTRAINT_TYPE) + { + slider = (btSliderConstraint*)constraint; + } + if (slider) + { + btScalar linDepth = slider->getLinearPos(); + btScalar lowLim = slider->getLowerLinLimit(); + btScalar hiLim = slider->getUpperLinLimit(); + slider->setPoweredLinMotor(false); + if(linDepth <= lowLim) + { + slider->setLowerLinLimit(lowLim); + slider->setUpperLinLimit(lowLim); + } + else if(linDepth > hiLim) + { + slider->setLowerLinLimit(hiLim); + slider->setUpperLinLimit(hiLim); + } + else + { + slider->setLowerLinLimit(linDepth); + slider->setUpperLinLimit(linDepth); + } + } + } + + } + + pickedBody = 0; + + } + + + + } + + break; + + } + + default: + { + } + } + + return false; + +} + + + +btVector3 GL_DialogDynamicsWorld::getRayTo(int x,int y) +{ + float cameraDistance = m_screenHeight/2;//m_screenWidth/2;//1.f; + btVector3 cameraTargetPosition(0,0,0); + btVector3 cameraUp(0,-1,0); + + if (1)//_ortho) + { + + btScalar aspect; + btVector3 extents; + if (m_screenWidth> m_screenHeight) + { + + aspect = m_screenWidth / (btScalar)m_screenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + } else + { + cameraDistance = m_screenWidth/2; + aspect = m_screenHeight / (btScalar)m_screenWidth; + extents.setValue(1.0f, aspect*1.f,0); + } + + + + extents *= cameraDistance; + btVector3 lower = cameraTargetPosition - extents; + btVector3 upper = cameraTargetPosition + extents; + + btScalar u = x / btScalar(m_screenWidth); + btScalar v = (m_screenHeight - y) / btScalar(m_screenHeight); + + btVector3 p(0,0,0); + p.setValue( + (1.0f - u) * lower.getX() + u * upper.getX(), + -((1.0f - v) * lower.getY() + v * upper.getY()), + cameraTargetPosition.getZ()); + return p; + } + + float top = 1.f; + float bottom = -1.f; + float nearPlane = 1.f; + float tanFov = (top-bottom)*0.5f / nearPlane; + float fov = 2.0 * atanf (tanFov); + + btVector3 cameraPosition(0,0,-100); + btVector3 rayFrom = cameraPosition; + btVector3 rayForward = (cameraTargetPosition-cameraPosition); + rayForward.normalize(); + float farPlane = 10000.f; + rayForward*= farPlane; + + btVector3 rightOffset; + btVector3 vertical = cameraUp; + + btVector3 hor; + hor = rayForward.cross(vertical); + hor.normalize(); + vertical = hor.cross(rayForward); + vertical.normalize(); + + float tanfov = tanf(0.5f*fov); + + + hor *= 2.f * farPlane * tanfov; + vertical *= 2.f * farPlane * tanfov; + + btScalar aspect; + + if (m_screenWidth > m_screenHeight) + { + aspect = m_screenWidth / (btScalar)m_screenHeight; + + hor*=aspect; + } else + { + aspect = m_screenHeight / (btScalar)m_screenWidth; + vertical*=aspect; + } + + + btVector3 rayToCenter = rayFrom + rayForward; + btVector3 dHor = hor * 1.f/float(m_screenWidth); + btVector3 dVert = vertical * 1.f/float(m_screenHeight); + + + btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical; + rayTo += x * dHor; + rayTo -= y * dVert; + //rayTo += y * dVert; + + return rayTo; +} + + + +void GL_DialogDynamicsWorld::mouseMotionFunc(int x,int y) +{ + + if (m_pickConstraint) + { + //move the constraint pivot + btPoint2PointConstraint* p2p = static_cast(m_pickConstraint); + if (p2p) + { + //keep it at the same picking distance + + btVector3 newRayTo = getRayTo(x,y); + btVector3 rayFrom; + btVector3 oldPivotInB = p2p->getPivotInB(); + btVector3 newPivotB; + if (1)//_ortho) + { + newPivotB = oldPivotInB; + newPivotB.setX(newRayTo.getX()); + newPivotB.setY(newRayTo.getY()); + } else + { + //rayFrom = m_cameraPosition; + // btVector3 dir = newRayTo-rayFrom; + // dir.normalize(); + // dir *= gOldPickingDist; + + // newPivotB = rayFrom + dir; + } + + + + p2p->setPivotB(newPivotB); + } + + } + + float dx, dy; + dx = x - m_mouseOldX; + dy = y - m_mouseOldY; + + + + + m_mouseOldX = x; + m_mouseOldY = y; +// updateCamera(); + + +} diff --git a/Demos/OpenGL/GL_DialogDynamicsWorld.h b/Demos/OpenGL/GL_DialogDynamicsWorld.h new file mode 100644 index 000000000..0babec618 --- /dev/null +++ b/Demos/OpenGL/GL_DialogDynamicsWorld.h @@ -0,0 +1,91 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef GL_DIALOG_DYNAMICS_WORLD_H +#define GL_DIALOG_DYNAMICS_WORLD_H + +class btDiscreteDynamicsWorld; +class GL_DialogWindow; +class btDefaultCollisionConfiguration; +struct btDbvtBroadphase; +class btSequentialImpulseConstraintSolver; +class btCollisionDispatcher; +class btVoronoiSimplexSolver; +class btMinkowskiPenetrationDepthSolver; +class btCollisionObject; +class btTypedConstraint; +struct GL_ToggleControl; +struct GL_SliderControl; + + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btVector3.h" + +class GL_DialogDynamicsWorld +{ + + btDefaultCollisionConfiguration* m_collisionConfiguration; + btDbvtBroadphase* m_broadphase; + btSequentialImpulseConstraintSolver* m_constraintSolver; + btCollisionDispatcher* m_dispatcher; + btVoronoiSimplexSolver* m_simplexSolver; + btMinkowskiPenetrationDepthSolver* m_pdSolver; + + btDiscreteDynamicsWorld* m_dynamicsWorld; + + btCollisionObject* m_lowerBorder; + btCollisionObject* m_upperBorder; + btCollisionObject* m_leftBorder; + btCollisionObject* m_rightBorder; + + btAlignedObjectArray m_dialogs; + + int m_screenWidth; + int m_screenHeight; + + + ///for picking + int m_mouseOldX; + int m_mouseOldY; + int m_mouseButtons; + ///constraint for mouse picking + btTypedConstraint* m_pickConstraint; + + btVector3 getRayTo(int x,int y); + +public: + + GL_DialogDynamicsWorld(); + + virtual ~GL_DialogDynamicsWorld(); + + virtual void setScreenSize(int width, int height); + + virtual GL_DialogWindow* createDialog(int horPos,int vertPos,int dialogWidth,int dialogHeight, const char* dialogTitle ); + + GL_ToggleControl* createToggle(GL_DialogWindow* dialog, const char* toggleText); + + GL_SliderControl* createSlider(GL_DialogWindow* dialog, const char* sliderText); + + virtual void draw(btScalar timeStep); + + virtual bool mouseFunc(int button, int state, int x, int y); + + virtual void mouseMotionFunc(int x,int y); + +}; + +#endif //GL_DIALOG_DYNAMICS_WORLD_H diff --git a/Demos/OpenGL/GL_DialogWindow.cpp b/Demos/OpenGL/GL_DialogWindow.cpp new file mode 100644 index 000000000..194163715 --- /dev/null +++ b/Demos/OpenGL/GL_DialogWindow.cpp @@ -0,0 +1,519 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "GL_DialogWindow.h" +#include "GlutStuff.h" +#include "GLDebugFont.h" +#include "btBulletDynamicsCommon.h" +// --------------------------------------------------------------------------- +// Extensions + +typedef void (APIENTRY * PFNGLBindBufferARB)(GLenum target, GLuint buffer); +typedef void (APIENTRY * PFNGLBindProgramARB)(GLenum target, GLuint program); +typedef GLuint (APIENTRY * PFNGLGetHandleARB)(GLenum pname); +typedef void (APIENTRY * PFNGLUseProgramObjectARB)(GLuint programObj); +typedef void (APIENTRY * PFNGLTexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLActiveTextureARB)(GLenum texture); +typedef void (APIENTRY * PFNGLClientActiveTextureARB)(GLenum texture); +typedef void (APIENTRY * PFNGLBlendEquation)(GLenum mode); +typedef void (APIENTRY * PFNGLBlendEquationSeparate)(GLenum srcMode, GLenum dstMode); +typedef void (APIENTRY * PFNGLBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +PFNGLBindBufferARB glBindBufferARB = NULL; +PFNGLBindProgramARB glBindProgramARB = NULL; +PFNGLGetHandleARB glGetHandleARB = NULL; +PFNGLUseProgramObjectARB glUseProgramObjectARB = NULL; +PFNGLTexImage3D glTexImage3D = NULL; +PFNGLActiveTextureARB glActiveTextureARB = NULL; +PFNGLClientActiveTextureARB glClientActiveTextureARB = NULL; +PFNGLBlendEquation glBlendEquation = NULL; +PFNGLBlendEquationSeparate glBlendEquationSeparate = NULL; +PFNGLBlendFuncSeparate glBlendFuncSeparate = NULL; +#ifndef GL_ARRAY_BUFFER_ARB +# define GL_ARRAY_BUFFER_ARB 0x8892 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER_ARB +# define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#endif +#ifndef GL_ARRAY_BUFFER_BINDING_ARB +# define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB +# define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#endif +#ifndef GL_VERTEX_PROGRAM_ARB +# define GL_VERTEX_PROGRAM_ARB 0x8620 +#endif +#ifndef GL_FRAGMENT_PROGRAM_ARB +# define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#endif +#ifndef GL_PROGRAM_OBJECT_ARB +# define GL_PROGRAM_OBJECT_ARB 0x8B40 +#endif +#ifndef GL_TEXTURE_3D +# define GL_TEXTURE_3D 0x806F +#endif +#ifndef GL_TEXTURE0_ARB +# define GL_TEXTURE0_ARB 0x84C0 +#endif +#ifndef GL_ACTIVE_TEXTURE_ARB +# define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#endif +#ifndef GL_MAX_TEXTURE_UNITS_ARB +# define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 +#endif +#ifndef GL_TEXTURE_RECTANGLE_ARB +# define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#endif +#ifndef GL_FUNC_ADD +# define GL_FUNC_ADD 0x8006 +#endif +#ifndef GL_BLEND_EQUATION +# define GL_BLEND_EQUATION 0x8009 +#endif +#ifndef GL_BLEND_EQUATION_RGB +# define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION +#endif +#ifndef GL_BLEND_EQUATION_ALPHA +# define GL_BLEND_EQUATION_ALPHA 0x883D +#endif +#ifndef GL_BLEND_SRC_RGB +# define GL_BLEND_SRC_RGB 0x80C9 +#endif +#ifndef GL_BLEND_DST_RGB +# define GL_BLEND_DST_RGB 0x80C8 +#endif +#ifndef GL_BLEND_SRC_ALPHA +# define GL_BLEND_SRC_ALPHA 0x80CB +#endif +#ifndef GL_BLEND_DST_ALPHA +# define GL_BLEND_DST_ALPHA 0x80CA +#endif + + +GL_DialogWindow::GL_DialogWindow(int horPos,int vertPos,int dialogWidth,int dialogHeight, btCollisionObject* collisionObject,const char* dialogTitle) +:m_dialogHorPos(horPos), +m_dialogVertPos(vertPos), +m_dialogWidth(dialogWidth), +m_dialogHeight(dialogHeight), +m_screenWidth(0), +m_screenHeight(0), +m_MaxClipPlanes(-1), +m_collisionObject(collisionObject), +m_dialogTitle(dialogTitle) +{ +} + +void GL_DialogWindow::setScreenSize(int width, int height) +{ + m_screenWidth = width; + m_screenHeight = height; +} +GL_DialogWindow::~GL_DialogWindow() +{ + +} + + + +static void drawLine(int _X0, int _Y0, int _X1, int _Y1, unsigned int _Color0, unsigned int _Color1) +{ + const GLfloat dx = +0.5f; + const GLfloat dy = -0.5f; + + bool antiAliased = false; + if( antiAliased ) + glEnable(GL_LINE_SMOOTH); + else + glDisable(GL_LINE_SMOOTH); + glDisable(GL_TEXTURE_2D); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glBegin(GL_LINES); + glColor4ub(GLubyte(_Color0>>16), GLubyte(_Color0>>8), GLubyte(_Color0), GLubyte(_Color0>>24)); + glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y0+dy); + glColor4ub(GLubyte(_Color1>>16), GLubyte(_Color1>>8), GLubyte(_Color1), GLubyte(_Color1>>24)); + glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y1+dy); + glEnd(); + glDisable(GL_LINE_SMOOTH); +} + +static void drawRect(int horStart, int vertStart, int horEnd, int vertEnd, unsigned int argbColor00,unsigned int argbColor10,unsigned int argbColor01,unsigned int argbColor11) +{ + float dx = 0; + float dy = 0; + glDisable(GL_TEXTURE_2D); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glBegin(GL_QUADS); + glColor4ub(GLubyte(argbColor00>>16), GLubyte(argbColor00>>8), GLubyte(argbColor00), GLubyte(argbColor00>>24)); + glVertex2f((GLfloat)horStart+dx, (GLfloat)vertStart+dy); + glColor4ub(GLubyte(argbColor10>>16), GLubyte(argbColor10>>8), GLubyte(argbColor10), GLubyte(argbColor10>>24)); + glVertex2f((GLfloat)horEnd+dx, (GLfloat)vertStart+dy); + glColor4ub(GLubyte(argbColor11>>16), GLubyte(argbColor11>>8), GLubyte(argbColor11), GLubyte(argbColor11>>24)); + glVertex2f((GLfloat)horEnd+dx, (GLfloat)vertEnd+dy); + glColor4ub(GLubyte(argbColor01>>16), GLubyte(argbColor01>>8), GLubyte(argbColor01), GLubyte(argbColor01>>24)); + glVertex2f((GLfloat)horStart+dx, (GLfloat)vertEnd+dy); + glEnd(); +} + +void GL_DialogWindow::draw(btScalar deltaTime) +{ + if (!m_screenWidth || !m_screenHeight) + return; + + m_dialogHorPos = m_collisionObject->getWorldTransform().getOrigin()[0]+m_screenWidth/2-m_dialogWidth/2; + + m_dialogVertPos = m_collisionObject->getWorldTransform().getOrigin()[1]+m_screenHeight/2-m_dialogHeight/2; + saveOpenGLState(); + + //drawRect(m_dialogHorPos,m_dialogVertPos,m_dialogHorPos+m_dialogWidth,m_dialogVertPos+m_dialogHeight,0xa6000000); + unsigned int argbColor = 0x86000000; + int charHeight = 16; + int charWidth = 10; + + int titleHeight = charHeight + 2; + + drawRect(m_dialogHorPos,m_dialogVertPos,m_dialogHorPos+m_dialogWidth-1,m_dialogVertPos+titleHeight,argbColor,argbColor,argbColor,argbColor); + //const unsigned int COL0 = 0x50ffffff; + const unsigned int COL0 = 0xffffffff; + const unsigned int COL1 = 0xff1f1f1f; + + drawRect(m_dialogHorPos,m_dialogVertPos,m_dialogHorPos+m_dialogWidth-1,m_dialogVertPos+1,COL0,COL0,COL1,COL1); + + argbColor = 0x864f4f4f; + drawRect(m_dialogHorPos+1,m_dialogVertPos+titleHeight,m_dialogHorPos+m_dialogWidth-1,m_dialogVertPos+m_dialogHeight,argbColor,argbColor,argbColor,argbColor); + + + int y = m_dialogVertPos+charHeight+1; + glLineWidth(3); + drawLine(m_dialogHorPos, y, m_dialogHorPos+m_dialogWidth-1, y, 0x80afafaf,0x80afafaf); + + + + unsigned int clight = 0x5FFFFFFF; // bar contour + drawLine(m_dialogHorPos, m_dialogVertPos, m_dialogHorPos, m_dialogVertPos+m_dialogHeight, clight,clight); + drawLine(m_dialogHorPos, m_dialogVertPos, m_dialogHorPos+m_dialogWidth, m_dialogVertPos, clight,clight); + drawLine(m_dialogHorPos+m_dialogWidth, m_dialogVertPos, m_dialogHorPos+m_dialogWidth, m_dialogVertPos+m_dialogHeight, clight,clight); + drawLine(m_dialogHorPos, m_dialogVertPos+m_dialogHeight, m_dialogHorPos+m_dialogWidth, m_dialogVertPos+m_dialogHeight, clight,clight); + int dshad = 3; // bar shadows + + unsigned int cshad = (((0x40000000>>24)/2)<<24) & 0xFF000000; + drawRect(m_dialogHorPos, m_dialogVertPos+m_dialogHeight, m_dialogHorPos+dshad, m_dialogVertPos+m_dialogHeight+dshad, 0, cshad, 0, 0); + drawRect(m_dialogHorPos+dshad+1, m_dialogVertPos+m_dialogHeight, m_dialogHorPos+m_dialogWidth-1, m_dialogVertPos+m_dialogHeight+dshad, cshad, cshad, 0, 0); + drawRect(m_dialogHorPos+m_dialogWidth, m_dialogVertPos+m_dialogHeight, m_dialogHorPos+m_dialogWidth+dshad, m_dialogVertPos+m_dialogHeight+dshad, cshad, 0, 0, 0); + drawRect(m_dialogHorPos+m_dialogWidth, m_dialogVertPos, m_dialogHorPos+m_dialogWidth+dshad, m_dialogVertPos+dshad, 0, 0, cshad, 0); + drawRect(m_dialogHorPos+m_dialogWidth, m_dialogVertPos+dshad+1, m_dialogHorPos+m_dialogWidth+dshad, m_dialogVertPos+m_dialogHeight-1, cshad, 0, cshad, 0); + + int yInc = 16; + int curHorPos = m_dialogHorPos+5; + int curVertPos = m_dialogVertPos; + curVertPos += yInc; + + GLDebugDrawString(m_dialogHorPos+m_dialogWidth/2-((strlen(m_dialogTitle)/2)*charWidth),m_dialogVertPos+yInc ,m_dialogTitle); + curVertPos += 20; + + + for (int i=0;idraw(curHorPos,curVertPos,deltaTime); + } + + restoreOpenGLState(); +} + + +void GL_DialogWindow::saveOpenGLState() +{ + + glPushAttrib(GL_ALL_ATTRIB_BITS); + glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); + + if( glActiveTextureARB ) + { + glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &m_PrevActiveTextureARB); + int maxTexUnits = 1; + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTexUnits); + maxTexUnits = max(1, min(32, maxTexUnits)); + for( int i=0; i0 && m_screenHeight>0 ) + { + Vp[0] = 0; + Vp[1] = 0; + Vp[2] = m_screenWidth-1; + Vp[3] = m_screenHeight-1; + glViewport(Vp[0], Vp[1], Vp[2], Vp[3]); + } + glLoadIdentity(); + glOrtho(Vp[0], Vp[0]+Vp[2], Vp[1]+Vp[3], Vp[1], -1, 1); + glGetIntegerv(GL_VIEWPORT, m_ViewportInit); + glGetFloatv(GL_PROJECTION_MATRIX, m_ProjMatrixInit); + + glGetFloatv(GL_LINE_WIDTH, &m_PrevLineWidth); + glDisable(GL_POLYGON_STIPPLE); + glLineWidth(1); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_LINE_STIPPLE); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &m_PrevTexEnv); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glGetIntegerv(GL_POLYGON_MODE, m_PrevPolygonMode); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glDisable(GL_ALPHA_TEST); + //glEnable(GL_ALPHA_TEST); + //glAlphaFunc(GL_GREATER, 0); + glDisable(GL_FOG); + glDisable(GL_LOGIC_OP); + glDisable(GL_SCISSOR_TEST); + if( m_MaxClipPlanes<0 ) + { + glGetIntegerv(GL_MAX_CLIP_PLANES, &m_MaxClipPlanes); + if( m_MaxClipPlanes<0 || m_MaxClipPlanes>255 ) + m_MaxClipPlanes = 6; + } + for( int i=0; igetWorldTransform().getOrigin()[0]+m_parentWindow->getScreenWidth()/2;//-m_parentWindow->getDialogWidth()/2; + int controlVertPos = m_toggleBody->getWorldTransform().getOrigin()[1]+m_parentWindow->getScreenHeight()/2;//-m_parentWindow->getDialogHeight()/2; + + int parentHorPos = controlHorPos-8; + int parentVertPos = controlVertPos-8; + + unsigned int grey = 0xff6f6f6f; + + drawRect(parentHorPos, parentVertPos, parentHorPos+16, parentVertPos+16, grey, grey, grey, grey); + + int borderSize = 2; + unsigned int white = 0xffefefef; + drawRect(parentHorPos+borderSize, parentVertPos+borderSize, parentHorPos+16-borderSize, parentVertPos+16-borderSize, white,white,white,white); + + + if (m_active) + { + //unsigned int red = 0xff8f0000; + unsigned int white = 0xff8f0000; + unsigned int black = 0xff1f1f1f; + borderSize = 4; + drawRect(parentHorPos+borderSize, parentVertPos+borderSize, parentHorPos+16-borderSize, parentVertPos+16-borderSize, black,black,black,black); + } + + btVector3 rgb(1,1,0); + + if (!m_active) + { + rgb.setValue(1,1,1); + } + + GLDebugDrawStringInternal(parentHorPos2,parentVertPos+16,m_toggleText,rgb); + parentVertPos2+=20; + +} + + +void GL_SliderControl::draw(int& parentHorPos2,int& parentVertPos2,btScalar deltaTime) +{ + + int controlHorPos = m_sliderBody->getWorldTransform().getOrigin()[0]+m_parentWindow->getScreenWidth()/2; + int controlVertPos = m_sliderBody->getWorldTransform().getOrigin()[1]+m_parentWindow->getScreenHeight()/2; + + int parentHorPos = controlHorPos-8; + int parentVertPos = controlVertPos-8; + + unsigned int grey = 0xff6f6f6f; + int borderSize = 2; + unsigned int white = 0xffefefef; + drawRect(parentHorPos2+80+borderSize, parentVertPos2+borderSize, parentHorPos2+m_parentWindow->getDialogWidth()-16-borderSize, parentVertPos2+2-borderSize, white,white,white,white); + + drawRect(parentHorPos, parentVertPos, parentHorPos+16, parentVertPos+16, grey, grey, grey, grey); + + + + drawRect(parentHorPos+borderSize, parentVertPos+borderSize, parentHorPos+16-borderSize, parentVertPos+16-borderSize, white,white,white,white); + + + + btVector3 rgb(1,1,1); + + GLDebugDrawStringInternal(parentHorPos2,parentVertPos2+8,m_sliderText,rgb); + parentVertPos2+=20; + +} diff --git a/Demos/OpenGL/GL_DialogWindow.h b/Demos/OpenGL/GL_DialogWindow.h new file mode 100644 index 000000000..1662c8fda --- /dev/null +++ b/Demos/OpenGL/GL_DialogWindow.h @@ -0,0 +1,256 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef GL_DIALOG_WINDOW_H +#define GL_DIALOG_WINDOW_H + +class btCollisionObject; +#include "GlutStuff.h" +#include "LinearMath/btScalar.h" +#include "LinearMath/btAlignedObjectArray.h" +class btTypedConstraint; + +class GL_DialogWindow; + +enum GL_DIALOG_CONTROL_TYPES +{ + GL_TEXT_CONTROL=1, + GL_TOGGLE_CONTROL, + GL_SLIDER_CONTROL, + GL_CONTROL_MAX_TYPE +}; + +class GL_DialogControl +{ +protected: + int m_type; + +public: + + virtual ~GL_DialogControl() + { + } + virtual void draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime)=0; + + int getType() const + { + return m_type; + } +}; + +struct GL_TextControl : public GL_DialogControl +{ +public: + + btAlignedObjectArray m_textLines; + + GL_TextControl() + { + m_type = GL_TEXT_CONTROL; + } + + virtual void draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime); +}; + + +struct GL_ToggleControl : public GL_DialogControl +{ + btCollisionObject* m_toggleBody; + GL_DialogWindow* m_parentWindow; + + const char* m_toggleText; + +public: + + bool m_active; + + + GL_ToggleControl(const char* toggleText,btCollisionObject* toggleBody, GL_DialogWindow* parentWindow) + :m_toggleBody(toggleBody), + m_parentWindow(parentWindow), + m_toggleText(toggleText), + m_active(false) + { + m_type = GL_TOGGLE_CONTROL; + } + + virtual void draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime); +}; + +struct GL_SliderControl : public GL_DialogControl +{ + btCollisionObject* m_sliderBody; + GL_DialogWindow* m_parentWindow; + btScalar m_lowerLimit; + btScalar m_upperLimit; + btTypedConstraint* m_constraint; + + const char* m_sliderText; +public: + + GL_SliderControl(const char* sliderText,btCollisionObject* sliderBody, GL_DialogWindow* parentWindow, btScalar lowerLimit,btScalar upperLimit,btTypedConstraint* constaint) + :m_sliderBody(sliderBody), + m_parentWindow(parentWindow), + m_sliderText(sliderText), + m_lowerLimit(lowerLimit), + m_upperLimit(upperLimit), + m_constraint(constaint) + { + m_type = GL_SLIDER_CONTROL; + } + + virtual void draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime); + + btScalar btGetFraction(); + + btScalar getLowerLimit() + { + return m_lowerLimit; + } + btScalar getUpperLimit() + { + return m_upperLimit; + } + btTypedConstraint* getConstraint() + { + return m_constraint; + } +}; + +///Very basic OpenGL Graphical Userinterface Window with text, toggle, slider control +class GL_DialogWindow +{ + + int m_dialogHorPos; + int m_dialogVertPos; + int m_dialogWidth; + int m_dialogHeight; + + int m_screenWidth; + int m_screenHeight; + + const char* m_dialogTitle; + + //saved OpenGL settings + GLfloat m_PrevLineWidth; + GLint m_PrevTexEnv; + GLint m_PrevPolygonMode[2]; + GLint m_MaxClipPlanes; + GLint m_PrevTexture; + GLint m_PrevArrayBufferARB; + GLint m_PrevElementArrayBufferARB; + GLboolean m_PrevVertexProgramARB; + GLboolean m_PrevFragmentProgramARB; + GLuint m_PrevProgramObjectARB; + GLboolean m_PrevTexture3D; + GLboolean m_PrevActiveTexture1D[32]; + GLboolean m_PrevActiveTexture2D[32]; + GLboolean m_PrevActiveTexture3D[32]; + GLint m_PrevActiveTextureARB; + bool m_SupportTexRect; + GLboolean m_PrevTexRectARB; + GLint m_PrevBlendEquation; + GLint m_PrevBlendEquationRGB; + GLint m_PrevBlendEquationAlpha; + GLint m_PrevBlendSrcRGB; + GLint m_PrevBlendDstRGB; + GLint m_PrevBlendSrcAlpha; + GLint m_PrevBlendDstAlpha; + GLint m_ViewportInit[4]; + GLfloat m_ProjMatrixInit[16]; + + btCollisionObject* m_collisionObject; + + btAlignedObjectArray m_controls; + +protected: + + + void saveOpenGLState(); + void restoreOpenGLState(); + +// void drawLine(int _X0, int _Y0, int _X1, int _Y1, unsigned int _Color0, unsigned int _Color1, bool antiAliased); +// void drawRect(int horStart, int vertStart, int horEnd, int vertEnd, unsigned int argbColor00,unsigned int argbColor10,unsigned int argbColor01,unsigned int argbColor11); + +public: + + + GL_DialogWindow(int horPos,int vertPos,int dialogWidth,int dialogHeight,btCollisionObject* colObject, const char* dialogTitle); + + virtual ~GL_DialogWindow(); + + void draw(btScalar deltaTime); + + void setScreenSize(int width, int height); + + void setStartPosition(int dialogHorPos,int dialogVertPos); + + void addControl(GL_DialogControl* control) + { + m_controls.push_back(control); + } + + void removeControl(GL_DialogControl* control) + { + m_controls.remove(control); + } + + btCollisionObject* getCollisionObject() + { + return m_collisionObject; + } + + int getDialogHorPos() const + { + return m_dialogHorPos; + } + int getDialogVertPos() const + { + return m_dialogVertPos; + } + int getDialogWidth() const + { + return m_dialogWidth; + } + + int getDialogHeight() const + { + return m_dialogHeight; + } + int getScreenWidth() const + { + return m_screenWidth; + } + int getScreenHeight() const + { + return m_screenHeight; + } + + int getNumControls() const + { + return m_controls.size(); + } + + const GL_DialogControl* getControl(int index) const + { + return m_controls[index]; + } + GL_DialogControl* getControl(int index) + { + return m_controls[index]; + } +}; + +#endif //GL_DIALOG_WINDOW_H \ No newline at end of file diff --git a/Demos/OpenGL/GlutStuff.cpp b/Demos/OpenGL/GlutStuff.cpp index 766c6bb01..cc2d95f43 100644 --- a/Demos/OpenGL/GlutStuff.cpp +++ b/Demos/OpenGL/GlutStuff.cpp @@ -95,6 +95,7 @@ int glutmain(int argc, char **argv,int width,int height,const char* title,DemoAp //createMenu(); glutIdleFunc(glutMoveAndDisplayCallback); glutMouseFunc(glutMouseFuncCallback); + glutPassiveMotionFunc(glutMotionFuncCallback); glutMotionFunc(glutMotionFuncCallback); glutDisplayFunc( glutDisplayCallback );