rename ObsoleteDemos back to Demos

fix some relative path issues for loading assets
This commit is contained in:
Erwin Coumans
2014-05-12 16:12:01 -07:00
parent 23a2a4f4f9
commit dc491936a2
312 changed files with 3933 additions and 322 deletions

View File

@@ -0,0 +1,68 @@
# This is basically the overall name of the project in Visual Studio this is the name of the Solution File
# For every executable you have with a main method you should have an add_executable line below.
# For every add executable line you should list every .cpp and .h file you have associated with that executable.
# You shouldn't have to modify anything below this line
########################################################
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexHull
${GLUT_INCLUDE_DIR}
)
ADD_LIBRARY(OpenGLSupport
GLDebugFont.cpp
GLDebugFont.h
GL_DialogDynamicsWorld.cpp
GL_DialogDynamicsWorld.h
GL_DialogWindow.cpp
GL_DialogWindow.h
GL_ShapeDrawer.cpp
GL_ShapeDrawer.h
GL_Simplex1to4.cpp
GL_Simplex1to4.h
GLDebugDrawer.cpp
GLDebugDrawer.h
RenderTexture.cpp
RenderTexture.h
DemoApplication.cpp
DemoApplication.h
GlutDemoApplication.cpp
GlutDemoApplication.h
GlutStuff.cpp
GlutStuff.h
stb_image.cpp
stb_image.h
Win32DemoApplication.cpp
Win32DemoApplication.h
)
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(OpenGLSupport BulletDynamics BulletCollision ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY})
ENDIF (BUILD_SHARED_LIBS)
#INSTALL of other files requires CMake 2.6
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF(INSTALL_EXTRA_LIBS)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS OpenGLSupport DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS OpenGLSupport DESTINATION lib)
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.h")
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (INSTALL_EXTRA_LIBS)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)

View File

@@ -0,0 +1,112 @@
/******************************************************************************
* Copyright 2010 Duane Merrill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For more information, see our Google Code project site:
* http://code.google.com/p/back40computing/
*
* Thanks!
******************************************************************************/
#ifndef COMMAND_LINE_ARGS_H
#define COMMAND_LINE_ARGS_H
/******************************************************************************
* Command-line parsing
******************************************************************************/
#include <map>
#include <algorithm>
#include <string>
#include <sstream>
class CommandLineArguments
{
protected:
std::map<std::string, std::string> pairs;
public:
// Constructor
CommandLineArguments(int argc, char **argv)
{
using namespace std;
for (int i = 1; i < argc; i++)
{
string arg = argv[i];
if ((arg[0] != '-') || (arg[1] != '-')) {
continue;
}
string::size_type pos;
string key, val;
if ((pos = arg.find( '=')) == string::npos) {
key = string(arg, 2, arg.length() - 2);
val = "";
} else {
key = string(arg, 2, pos - 2);
val = string(arg, pos + 1, arg.length() - 1);
}
pairs[key] = val;
}
}
bool CheckCmdLineFlag(const char* arg_name)
{
using namespace std;
map<string, string>::iterator itr;
if ((itr = pairs.find(arg_name)) != pairs.end()) {
return true;
}
return false;
}
template <typename T>
void GetCmdLineArgument(const char *arg_name, T &val);
int ParsedArgc()
{
return pairs.size();
}
};
template <typename T>
void CommandLineArguments::GetCmdLineArgument(const char *arg_name, T &val)
{
using namespace std;
map<string, string>::iterator itr;
if ((itr = pairs.find(arg_name)) != pairs.end()) {
istringstream strstream(itr->second);
strstream >> val;
}
}
template <>
void CommandLineArguments::GetCmdLineArgument<char*>(const char* arg_name, char* &val)
{
using namespace std;
map<string, string>::iterator itr;
if ((itr = pairs.find(arg_name)) != pairs.end()) {
string s = itr->second;
val = (char*) malloc(sizeof(char) * (s.length() + 1));
strcpy(val, s.c_str());
} else {
val = NULL;
}
}
#endif //COMMAND_LINE_ARGS_H

View File

@@ -0,0 +1,88 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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 DEBUG_CAST_RESULT_H
#define DEBUG_CAST_RESULT_H
#include "BulletCollision/NarrowPhaseCollision/btConvexCast.h"
#include "LinearMath/btTransform.h"
#include "GL_ShapeDrawer.h"
#include "GlutStuff.h"
#ifdef WIN32
#include <windows.h>
#endif
//think different
#if defined(__APPLE__) && !defined (VMDMESA)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#endif
struct btDebugCastResult : public btConvexCast::CastResult
{
btTransform m_fromTrans;
const btPolyhedralConvexShape* m_shape;
btVector3 m_linVel;
btVector3 m_angVel;
GL_ShapeDrawer* m_shapeDrawer;
btDebugCastResult(const btTransform& fromTrans,const btPolyhedralConvexShape* shape,
const btVector3& linVel,const btVector3& angVel,GL_ShapeDrawer* drawer)
:m_fromTrans(fromTrans),
m_shape(shape),
m_linVel(linVel),
m_angVel(angVel),
m_shapeDrawer(drawer)
{
}
virtual void drawCoordSystem(const btTransform& tr)
{
btScalar m[16];
tr.getOpenGLMatrix(m);
glPushMatrix();
btglLoadMatrix(m);
glBegin(GL_LINES);
btglColor3(1, 0, 0);
btglVertex3(0, 0, 0);
btglVertex3(1, 0, 0);
btglColor3(0, 1, 0);
btglVertex3(0, 0, 0);
btglVertex3(0, 1, 0);
btglColor3(0, 0, 1);
btglVertex3(0, 0, 0);
btglVertex3(0, 0, 1);
glEnd();
glPopMatrix();
}
virtual void DebugDraw(btScalar fraction)
{
btVector3 worldBoundsMin(-1000,-1000,-1000);
btVector3 worldBoundsMax(1000,1000,1000);
ATTRIBUTE_ALIGNED16(btScalar) m[16];
btTransform hitTrans;
btTransformUtil::integrateTransform(m_fromTrans,m_linVel,m_angVel,fraction,hitTrans);
hitTrans.getOpenGLMatrix(m);
if (m_shapeDrawer)
m_shapeDrawer->drawOpenGL(m,m_shape,btVector3(1,0,0),btIDebugDraw::DBG_NoDebug,worldBoundsMin,worldBoundsMax);
}
};
#endif //DEBUG_CAST_RESULT_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,266 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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 DEMO_APPLICATION_H
#define DEMO_APPLICATION_H
#include "GlutStuff.h"
#include "GL_ShapeDrawer.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btQuickprof.h"
#include "LinearMath/btAlignedObjectArray.h"
class btCollisionShape;
class btDynamicsWorld;
class btRigidBody;
class btTypedConstraint;
class DemoApplication
{
protected:
void displayProfileString(int xOffset,int yStart,char* message);
class CProfileIterator* m_profileIterator;
protected:
#ifdef USE_BT_CLOCK
btClock m_clock;
#endif //USE_BT_CLOCK
///this is the most important class
btDynamicsWorld* m_dynamicsWorld;
///constraint for mouse picking
btTypedConstraint* m_pickConstraint;
virtual void removePickingConstraint();
virtual void pickObject(const btVector3& pickPos, const class btCollisionObject* hitObj);
btCollisionShape* m_shootBoxShape;
float m_cameraDistance;
int m_debugMode;
float m_ele;
float m_azi;
btVector3 m_cameraPosition;
btVector3 m_cameraTargetPosition;//look at
int m_mouseOldX;
int m_mouseOldY;
int m_mouseButtons;
public:
int m_modifierKeys;
protected:
float m_scaleBottom;
float m_scaleFactor;
btVector3 m_cameraUp;
int m_forwardAxis;
float m_zoomStepSize;
int m_glutScreenWidth;
int m_glutScreenHeight;
float m_frustumZNear;
float m_frustumZFar;
int m_ortho;
float m_ShootBoxInitialSpeed;
bool m_stepping;
bool m_singleStep;
bool m_idle;
int m_lastKey;
void showProfileInfo(int& xOffset,int& yStart, int yIncr);
void renderscene(int pass);
GL_ShapeDrawer* m_shapeDrawer;
bool m_enableshadows;
btVector3 m_sundirection;
btScalar m_defaultContactProcessingThreshold;
public:
DemoApplication();
virtual ~DemoApplication();
btDynamicsWorld* getDynamicsWorld()
{
return m_dynamicsWorld;
}
virtual void initPhysics() = 0;
virtual void setDrawClusters(bool drawClusters)
{
}
void overrideGLShapeDrawer (GL_ShapeDrawer* shapeDrawer);
void setOrthographicProjection();
void resetPerspectiveProjection();
bool setTexturing(bool enable) { return(m_shapeDrawer->enableTexture(enable)); }
bool setShadows(bool enable) { bool p=m_enableshadows;m_enableshadows=enable;return(p); }
bool getTexturing() const
{
return m_shapeDrawer->hasTextureEnabled();
}
bool getShadows() const
{
return m_enableshadows;
}
int getDebugMode()
{
return m_debugMode ;
}
void setDebugMode(int mode);
void setAzi(float azi)
{
m_azi = azi;
}
void setEle(float ele)
{
m_ele = ele;
}
void setCameraUp(const btVector3& camUp)
{
m_cameraUp = camUp;
}
void setCameraForwardAxis(int axis)
{
m_forwardAxis = axis;
}
virtual void myinit();
void toggleIdle();
virtual void updateCamera();
btVector3 getCameraPosition()
{
return m_cameraPosition;
}
btVector3 getCameraTargetPosition()
{
return m_cameraTargetPosition;
}
btScalar getDeltaTimeMicroseconds()
{
#ifdef USE_BT_CLOCK
btScalar dt = (btScalar)m_clock.getTimeMicroseconds();
m_clock.reset();
return dt;
#else
return btScalar(16666.);
#endif
}
void setFrustumZPlanes(float zNear, float zFar)
{
m_frustumZNear = zNear;
m_frustumZFar = zFar;
}
///glut callbacks
float getCameraDistance();
void setCameraDistance(float dist);
void moveAndDisplay();
virtual void clientMoveAndDisplay() = 0;
virtual void clientResetScene();
///Demo functions
virtual void setShootBoxShape ();
virtual void shootBox(const btVector3& destination);
btVector3 getRayTo(int x,int y);
btRigidBody* localCreateRigidBody(float mass, const btTransform& startTransform,btCollisionShape* shape);
///callback methods by glut
virtual void keyboardCallback(unsigned char key, int x, int y);
virtual void keyboardUpCallback(unsigned char key, int x, int y) {}
virtual void specialKeyboard(int key, int x, int y){}
virtual void specialKeyboardUp(int key, int x, int y){}
virtual void reshape(int w, int h);
virtual void mouseFunc(int button, int state, int x, int y);
virtual void mouseMotionFunc(int x,int y);
virtual void displayCallback();
virtual void renderme();
virtual void swapBuffers() = 0;
virtual void updateModifierKeys() = 0;
void stepLeft();
void stepRight();
void stepFront();
void stepBack();
void zoomIn();
void zoomOut();
bool isIdle() const
{
return m_idle;
}
void setIdle(bool idle)
{
m_idle = idle;
}
};
#endif //DEMO_APPLICATION_H

View File

@@ -0,0 +1,130 @@
#include "GLDebugDrawer.h"
#include "GLDebugFont.h"
#include "GlutStuff.h"
#include <stdio.h> //printf debugging
GLDebugDrawer::GLDebugDrawer()
:m_debugMode(0)
{
}
GLDebugDrawer::~GLDebugDrawer()
{
}
void GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor)
{
glBegin(GL_LINES);
glColor3f(fromColor.getX(), fromColor.getY(), fromColor.getZ());
glVertex3d(from.getX(), from.getY(), from.getZ());
glColor3f(toColor.getX(), toColor.getY(), toColor.getZ());
glVertex3d(to.getX(), to.getY(), to.getZ());
glEnd();
}
void GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
{
drawLine(from,to,color,color);
}
void GLDebugDrawer::drawSphere (const btVector3& p, btScalar radius, const btVector3& color)
{
glColor4f (color.getX(), color.getY(), color.getZ(), btScalar(1.0f));
glPushMatrix ();
glTranslatef (p.getX(), p.getY(), p.getZ());
int lats = 5;
int longs = 5;
int i, j;
for(i = 0; i <= lats; i++) {
btScalar lat0 = SIMD_PI * (-btScalar(0.5) + (btScalar) (i - 1) / lats);
btScalar z0 = radius*sin(lat0);
btScalar zr0 = radius*cos(lat0);
btScalar lat1 = SIMD_PI * (-btScalar(0.5) + (btScalar) i / lats);
btScalar z1 = radius*sin(lat1);
btScalar zr1 = radius*cos(lat1);
glBegin(GL_QUAD_STRIP);
for(j = 0; j <= longs; j++) {
btScalar lng = 2 * SIMD_PI * (btScalar) (j - 1) / longs;
btScalar x = cos(lng);
btScalar y = sin(lng);
glNormal3f(x * zr0, y * zr0, z0);
glVertex3f(x * zr0, y * zr0, z0);
glNormal3f(x * zr1, y * zr1, z1);
glVertex3f(x * zr1, y * zr1, z1);
}
glEnd();
}
glPopMatrix();
}
void GLDebugDrawer::drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha)
{
// if (m_debugMode > 0)
{
const btVector3 n=btCross(b-a,c-a).normalized();
glBegin(GL_TRIANGLES);
glColor4f(color.getX(), color.getY(), color.getZ(),alpha);
glNormal3d(n.getX(),n.getY(),n.getZ());
glVertex3d(a.getX(),a.getY(),a.getZ());
glVertex3d(b.getX(),b.getY(),b.getZ());
glVertex3d(c.getX(),c.getY(),c.getZ());
glEnd();
}
}
void GLDebugDrawer::setDebugMode(int debugMode)
{
m_debugMode = debugMode;
}
void GLDebugDrawer::draw3dText(const btVector3& location,const char* textString)
{
glRasterPos3f(location.x(), location.y(), location.z());
//BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),textString);
}
void GLDebugDrawer::reportErrorWarning(const char* warningString)
{
printf("%s\n",warningString);
}
void GLDebugDrawer::drawContactPoint(const btVector3& pointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)
{
{
btVector3 to=pointOnB+normalOnB*1;//distance;
const btVector3&from = pointOnB;
glColor4f(color.getX(), color.getY(), color.getZ(),1.f);
//glColor4f(0,0,0,1.f);
glBegin(GL_LINES);
glVertex3d(from.getX(), from.getY(), from.getZ());
glVertex3d(to.getX(), to.getY(), to.getZ());
glEnd();
// glRasterPos3f(from.x(), from.y(), from.z());
// char buf[12];
// sprintf(buf," %d",lifeTime);
//BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);
}
}

View File

@@ -0,0 +1,37 @@
#ifndef GL_DEBUG_DRAWER_H
#define GL_DEBUG_DRAWER_H
#include "LinearMath/btIDebugDraw.h"
class GLDebugDrawer : public btIDebugDraw
{
int m_debugMode;
public:
GLDebugDrawer();
virtual ~GLDebugDrawer();
virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor);
virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color);
virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color);
virtual void drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha);
virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color);
virtual void reportErrorWarning(const char* warningString);
virtual void draw3dText(const btVector3& location,const char* textString);
virtual void setDebugMode(int debugMode);
virtual int getDebugMode() const { return m_debugMode;}
};
#endif//GL_DEBUG_DRAWER_H

1000
Demos/OpenGL/GLDebugFont.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
/*
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 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, bool enableBlend, int spacing);
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);
#endif //BT_DEBUG_FONT_H

View File

@@ -0,0 +1,761 @@
/*
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)
{
int i;
for ( i=0;i<m_dynamicsWorld->getCollisionObjectArray().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(btScalar(m_screenWidth/2.),btScalar(m_screenHeight/2),btScalar(0))-btVector3(btScalar(width/2.),btScalar(height/2.),btScalar(0));
colObj->getWorldTransform().setOrigin(newPos);
m_dynamicsWorld->addRigidBody(body);
} else
{
m_dynamicsWorld->removeCollisionObject(colObj);
btVector3 newPos = colObj->getWorldTransform().getOrigin() + btVector3(btScalar(m_screenWidth/2.),btScalar(m_screenHeight/2.),btScalar(0))-btVector3(btScalar(width/2.),btScalar(height/2.),btScalar(0));
colObj->getWorldTransform().setOrigin(newPos);
m_dynamicsWorld->addCollisionObject(colObj);
}
}
for ( i=0;i<m_dialogs.size();i++)
{
m_dialogs[i]->setScreenSize(width,height);
}
if (width && height)
{
if (m_upperBorder)
{
m_dynamicsWorld->removeCollisionObject(m_upperBorder);
btTransform tr;
tr.setIdentity();
tr.setOrigin(btVector3(btScalar(0),btScalar(-height/2.),btScalar(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(btScalar(0),btScalar(height/2.),btScalar(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(btScalar(-width/2.),btScalar(0),btScalar(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(btScalar(width/2.),btScalar(0),btScalar(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.f,dialogHeight/2.f,0.4f));
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(btScalar(horPos-m_screenWidth/2+dialogWidth/2), btScalar(vertPos+m_screenHeight/2.+dialogHeight/2),btScalar(0.)));
trans.setOrigin(btVector3(btScalar(horPos-m_screenWidth/2+dialogWidth/2), btScalar(vertPos-m_screenHeight/2.+dialogHeight/2),btScalar(0.)));
body->setWorldTransform(trans);
body->setDamping(0.999f,0.99f);
//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, btScalar initialFraction)
{
btBox2dShape* boxShape = new btBox2dShape(btVector3(6.f,6.f,0.4f));
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();
int sliderX = dialog->getDialogHorPos() - m_screenWidth/2 + dialog->getDialogWidth()/2;
// int sliderY = dialog->getDialogVertPos() + m_screenHeight/2 + dialog->getDialogHeight()/2 + dialog->getNumControls()*20;
int sliderY = dialog->getDialogVertPos() - m_screenHeight/2 + dialog->getDialogHeight()/2 + dialog->getNumControls()*20;
trans.setOrigin(btVector3((btScalar)sliderX, (btScalar)sliderY,(btScalar)-0.2f));
body->setWorldTransform(trans);
//body->setDamping(0.999,0.99);
//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);
body->setCollisionFlags(body->getFlags()|btCollisionObject::CF_NO_CONTACT_RESPONSE);
btRigidBody* dialogBody = btRigidBody::upcast(dialog->getCollisionObject());
btAssert(dialogBody);
btTransform frameInA;
frameInA.setIdentity();
int offsX = -dialog->getDialogWidth()/2 + 16;
int offsY = -dialog->getDialogHeight()/2 + dialog->getNumControls()*20 + 36;
btVector3 offset(btVector3((btScalar)offsX, (btScalar)offsY, (btScalar)0.2f));
frameInA.setOrigin(offset);
btTransform frameInB;
frameInB.setIdentity();
//frameInB.setOrigin(-offset/2);
// btScalar lowerLimit = 80.f;
// btScalar upperLimit = 170.f;
btScalar lowerLimit = 141.f;
btScalar upperLimit = 227.f;
btScalar actualLimit = lowerLimit+initialFraction*(upperLimit-lowerLimit);
#if 0
bool useFrameA = false;
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(actualLimit);
sliderConstraint->setUpperLinLimit(actualLimit);
m_dynamicsWorld->addConstraint(sliderConstraint,true);
#endif
GL_SliderControl* slider = new GL_SliderControl(sliderText, body,dialog,lowerLimit,upperLimit, sliderConstraint);
body->setUserPointer(slider);
dialog->addControl(slider);
slider->m_fraction = initialFraction;
return slider;
}
GL_ToggleControl* GL_DialogDynamicsWorld::createToggle(GL_DialogWindow* dialog, const char* toggleText)
{
btBox2dShape* boxShape = new btBox2dShape(btVector3(6.f,6.f,0.4f));
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();
int toggleX = dialog->getDialogHorPos() - m_screenWidth/2 + dialog->getDialogWidth()/2;
// int toggleY = dialog->getDialogVertPos() + m_screenHeight/2 + dialog->getDialogHeight()/2 + dialog->getNumControls()*20;
int toggleY = dialog->getDialogVertPos() - m_screenHeight/2 + dialog->getDialogHeight()/2 + dialog->getNumControls()*20;
trans.setOrigin(btVector3((btScalar)toggleX, (btScalar)toggleY,(btScalar) -0.2f));
body->setWorldTransform(trans);
body->setDamping(0.999f,0.99f);
//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);
body->setCollisionFlags(body->getFlags()|btCollisionObject::CF_NO_CONTACT_RESPONSE);
btRigidBody* dialogBody = btRigidBody::upcast(dialog->getCollisionObject());
btAssert(dialogBody);
btTransform frameInA;
frameInA.setIdentity();
btVector3 offset(btVector3(+dialog->getDialogWidth()/2.f-32.f,-dialog->getDialogHeight()/2.f+dialog->getNumControls()*20.f+36.f,0.2f));
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;i<m_dialogs.size();i++)
{
m_dialogs[i]->draw(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 btScalar gOldPickingDist = 0.f;
bool GL_DialogDynamicsWorld::mouseFunc(int button, int state, int x, int y)
{
if (state == 0)
{
m_mouseButtons |= 1<<button;
} else
{
m_mouseButtons = 0;
}
m_mouseOldX = x;
m_mouseOldY = y;
//printf("button %i, state %i, x=%i,y=%i\n",button,state,x,y);
//button 0, state 0 means left mouse down
btVector3 rayTo = getRayTo(x,y);
switch (button)
{
case 1:
{
if (state==0)
{
#if 0
//apply an impulse
if (m_dynamicsWorld)
{
btCollisionWorld::ClosestRayResultCallback rayCallback(m_cameraPosition,rayTo);
m_dynamicsWorld->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*)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.f;//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.f;
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 * 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 += btScalar(x) * dHor;
rayTo -= btScalar(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<btPoint2PointConstraint*>(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);
}
}
btScalar dx, dy;
dx = btScalar(x) - m_mouseOldX;
dy = btScalar(y) - m_mouseOldY;
m_mouseOldX = x;
m_mouseOldY = y;
// updateCamera();
}

View File

@@ -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<GL_DialogWindow*> 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, btScalar initialFraction = btScalar(0.5f));
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

View File

@@ -0,0 +1,358 @@
/*
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 "GLDebugFont.h"
#include "btBulletDynamicsCommon.h"
#include <stdio.h> // for sprintf()
#define USE_ARRAYS 1
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_dialogTitle(dialogTitle),
m_MaxClipPlanes(-1),
m_collisionObject(collisionObject)
{
}
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;
GLfloat vVertices[] = {(GLfloat)_X0+dx,(GLfloat)_Y0+dy,(GLfloat)_X1+dx,(GLfloat)_Y1+dy};
bool antiAliased = false;
if( antiAliased )
glEnable(GL_LINE_SMOOTH);
else
glDisable(GL_LINE_SMOOTH);
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#ifdef USE_ARRAYS
glColor4ub(GLubyte(_Color0>>16), GLubyte(_Color0>>8), GLubyte(_Color0), GLubyte(_Color0>>24));
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glLineWidth(2.0f);
glVertexPointer(2, GL_FLOAT, 0, vVertices);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_LINES,0,2);
#else
glLineWidth(13.0f);
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();
#endif
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();
#ifdef USE_ARRAYS
GLfloat verts[] ={
0.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.f,0.f,0.f
};
glColor4ub(GLubyte(argbColor00>>16), GLubyte(argbColor00>>8), GLubyte(argbColor00), GLubyte(argbColor00>>24));
verts[0] = (GLfloat)horStart+dx; verts[1] = (GLfloat)vertStart+dy;
verts[2] = (GLfloat)horEnd+dx; verts[3] = (GLfloat)vertStart+dy;
verts[4] = (GLfloat)horEnd+dx; verts[5] = (GLfloat)vertEnd+dy;
verts[6] = (GLfloat)horStart+dx; verts[7] = (GLfloat)vertEnd+dy;
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, verts);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
#else
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();
#endif
}
void GL_DialogWindow::draw(btScalar deltaTime)
{
if (!m_screenWidth || !m_screenHeight)
return;
m_dialogHorPos = int(m_collisionObject->getWorldTransform().getOrigin()[0]+m_screenWidth/2.f-m_dialogWidth/2.f);
m_dialogVertPos = int(m_collisionObject->getWorldTransform().getOrigin()[1]+m_screenHeight/2.f-m_dialogHeight/2.f);
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-((int(strlen(m_dialogTitle)/2))*charWidth),m_dialogVertPos+yInc ,m_dialogTitle);
curVertPos += 20;
for (int i=0;i<m_controls.size();i++)
{
m_controls[i]->draw(curHorPos,curVertPos,deltaTime);
}
restoreOpenGLState();
}
void GL_DialogWindow::saveOpenGLState()
{
#if 0
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
#endif
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
GLint Vp[4];
glGetIntegerv(GL_VIEWPORT, Vp);
if( m_screenWidth>0 && 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);
glDisable(GL_TEXTURE_2D);
}
void GL_DialogWindow::restoreOpenGLState()
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m_PrevTexEnv);
glLineWidth(m_PrevLineWidth);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glPopClientAttrib();
glPopAttrib();
}
void GL_TextControl::draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime)
{
for (int i=0;i<m_textLines.size();i++)
{
GLDebugDrawString(parentHorPos,parentVertPos,m_textLines[i]);
parentVertPos+=20;
}
}
void GL_ToggleControl::draw(int& parentHorPos2,int& parentVertPos2,btScalar deltaTime)
{
int controlHorPos = int(m_toggleBody->getWorldTransform().getOrigin()[0]+m_parentWindow->getScreenWidth()/2);
int controlVertPos = int(m_toggleBody->getWorldTransform().getOrigin()[1]+m_parentWindow->getScreenHeight()/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,1);
GLDebugDrawStringInternal(parentHorPos2,parentVertPos+16,m_toggleText,rgb);
parentVertPos2+=20;
}
void GL_SliderControl::draw(int& parentHorPos2,int& parentVertPos2,btScalar deltaTime)
{
int controlHorPos = int(m_sliderBody->getWorldTransform().getOrigin()[0]+m_parentWindow->getScreenWidth()/2);
int controlVertPos = int(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;
int sliderPosS = parentHorPos2+150+borderSize;
int sliderPosE = parentHorPos2+m_parentWindow->getDialogWidth()-40-borderSize;
int sliderPos = controlHorPos;
if(sliderPos < sliderPosS) sliderPos = sliderPosS;
if(sliderPos > sliderPosE) sliderPos = sliderPosE;
// drawRect(parentHorPos2+80+borderSize, parentVertPos2+borderSize, parentHorPos2+m_parentWindow->getDialogWidth()-16-borderSize, parentVertPos2+2-borderSize, white,white,white,white);
drawRect( sliderPosS,
parentVertPos2+borderSize,
sliderPosE,
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);
// btSliderConstraint* pSlider = (btSliderConstraint*)m_constraint;
// btScalar currPos = pSlider->getLinearPos();
// if(currPos < pSlider->getLowerLinLimit()) currPos = pSlider->getLowerLinLimit();
// if(currPos > pSlider->getUpperLinLimit()) currPos = pSlider->getUpperLinLimit();
// m_fraction = (currPos - pSlider->getLowerLinLimit()) / (pSlider->getUpperLinLimit() - pSlider->getLowerLinLimit());
m_fraction = (btScalar)(sliderPos - sliderPosS) / (btScalar)(sliderPosE - sliderPosS);
char tmpBuf[256];
sprintf(tmpBuf, "%s %3d%%", m_sliderText, (int)(m_fraction * 100.f));
// GLDebugDrawStringInternal(parentHorPos2,parentVertPos2+8,m_sliderText,rgb);
GLDebugDrawStringInternal(parentHorPos2,parentVertPos2+8, tmpBuf, rgb);
parentVertPos2+=20;
}

View File

@@ -0,0 +1,285 @@
/*
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;
//think different
#if defined(__APPLE__) && !defined (VMDMESA)
#include <TargetConditionals.h>
#if (defined (TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || (defined (TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR)
#import <OpenGLES/ES1/gl.h>
#define glOrtho glOrthof
#else
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#endif
#else
#ifdef _WIN32
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glut.h>
#endif
#endif
#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<const char*> m_textLines;
GL_TextControl()
{
m_type = GL_TEXT_CONTROL;
}
virtual ~GL_TextControl() {}
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;
btScalar m_fraction;
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_lowerLimit(lowerLimit),
m_upperLimit(upperLimit),
m_constraint(constaint),
m_sliderText(sliderText)
{
m_type = GL_SLIDER_CONTROL;
}
virtual void draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime);
btScalar btGetFraction() { return m_fraction; }
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<GL_DialogControl*> 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

View File

@@ -0,0 +1,987 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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.
*/
#ifdef _WIN32 //needed for glut.h
#include <windows.h>
#endif
#include "GLDebugFont.h"
#include "GlutStuff.h"
#include "GL_ShapeDrawer.h"
#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btConeShape.h"
#include "BulletCollision/CollisionShapes/btCylinderShape.h"
#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btUniformScalingShape.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
///
#include "BulletCollision/CollisionShapes/btShapeHull.h"
#include "LinearMath/btTransformUtil.h"
#include "LinearMath/btIDebugDraw.h"
//for debugmodes
#include <stdio.h> //printf debugging
//#define USE_DISPLAY_LISTS 1
#ifdef USE_DISPLAY_LISTS
#include <map>
using namespace std;
//Set for storing Display list per trimesh
struct TRIMESH_KEY
{
btCollisionShape* m_shape;
GLuint m_dlist;//OpenGL display list
};
typedef map<unsigned long,TRIMESH_KEY> TRIMESH_KEY_MAP;
typedef pair<unsigned long,TRIMESH_KEY> TRIMESH_KEY_PAIR;
TRIMESH_KEY_MAP g_display_lists;
class GlDisplaylistDrawcallback : public btTriangleCallback
{
public:
virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex)
{
btVector3 diff1 = triangle[1] - triangle[0];
btVector3 diff2 = triangle[2] - triangle[0];
btVector3 normal = diff1.cross(diff2);
normal.normalize();
glBegin(GL_TRIANGLES);
glColor3f(1, 1, 1);
glNormal3d(normal.getX(),normal.getY(),normal.getZ());
glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
//glColor3f(0, 1, 0);
glNormal3d(normal.getX(),normal.getY(),normal.getZ());
glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
//glColor3f(0, 1, 0);
glNormal3d(normal.getX(),normal.getY(),normal.getZ());
glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
glEnd();
/*glBegin(GL_LINES);
glColor3f(1, 1, 0);
glNormal3d(normal.getX(),normal.getY(),normal.getZ());
glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
glNormal3d(normal.getX(),normal.getY(),normal.getZ());
glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
glColor3f(1, 1, 0);
glNormal3d(normal.getX(),normal.getY(),normal.getZ());
glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
glNormal3d(normal.getX(),normal.getY(),normal.getZ());
glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
glColor3f(1, 1, 0);
glNormal3d(normal.getX(),normal.getY(),normal.getZ());
glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
glNormal3d(normal.getX(),normal.getY(),normal.getZ());
glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
glEnd();*/
}
};
GLuint OGL_get_displaylist_for_shape(btCollisionShape * shape)
{
TRIMESH_KEY_MAP::iterator map_iter;
unsigned long key = (unsigned long)shape;
map_iter = g_display_lists.find(key);
if(map_iter!=g_display_lists.end())
{
return map_iter->second.m_dlist;
}
return 0;
}
void OGL_displaylist_clean()
{
TRIMESH_KEY_MAP::iterator map_iter,map_itend;
map_iter = g_display_lists.begin();
while(map_iter!=map_itend)
{
glDeleteLists(map_iter->second.m_dlist,1);
map_iter++;
}
g_display_lists.clear();
}
void OGL_displaylist_register_shape(btCollisionShape * shape)
{
btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
btVector3 aabbMin(-btScalar(BT_LARGE_FLOAT),-btScalar(BT_LARGE_FLOAT),-btScalar(BT_LARGE_FLOAT));
GlDisplaylistDrawcallback drawCallback;
TRIMESH_KEY dlist;
dlist.m_dlist = glGenLists(1);
dlist.m_shape = shape;
unsigned long key = (unsigned long)shape;
g_display_lists.insert(TRIMESH_KEY_PAIR(key,dlist));
glNewList(dlist.m_dlist,GL_COMPILE);
// glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
if (shape->isConcave())
{
btConcaveShape* concaveMesh = (btConcaveShape*) shape;
//todo pass camera, for some culling
concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax);
}
// glDisable(GL_CULL_FACE);
glEndList();
}
#endif //USE_DISPLAY_LISTS
void GL_ShapeDrawer::drawCoordSystem() {
glBegin(GL_LINES);
glColor3f(1, 0, 0);
glVertex3d(0, 0, 0);
glVertex3d(1, 0, 0);
glColor3f(0, 1, 0);
glVertex3d(0, 0, 0);
glVertex3d(0, 1, 0);
glColor3f(0, 0, 1);
glVertex3d(0, 0, 0);
glVertex3d(0, 0, 1);
glEnd();
}
class GlDrawcallback : public btTriangleCallback
{
public:
bool m_wireframe;
GlDrawcallback()
:m_wireframe(false)
{
}
virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex)
{
(void)triangleIndex;
(void)partId;
if (m_wireframe)
{
glBegin(GL_LINES);
glColor3f(1, 0, 0);
glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
glColor3f(0, 1, 0);
glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
glColor3f(0, 0, 1);
glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
glEnd();
} else
{
glBegin(GL_TRIANGLES);
//glColor3f(1, 1, 1);
glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
glEnd();
}
}
};
class TriangleGlDrawcallback : public btInternalTriangleIndexCallback
{
public:
virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
{
(void)triangleIndex;
(void)partId;
glBegin(GL_TRIANGLES);//LINES);
glColor3f(1, 0, 0);
glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
glColor3f(0, 1, 0);
glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
glColor3f(0, 0, 1);
glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
glEnd();
}
};
void GL_ShapeDrawer::drawSphere(btScalar radius, int lats, int longs)
{
int i, j;
for(i = 0; i <= lats; i++) {
btScalar lat0 = SIMD_PI * (-btScalar(0.5) + (btScalar) (i - 1) / lats);
btScalar z0 = radius*sin(lat0);
btScalar zr0 = radius*cos(lat0);
btScalar lat1 = SIMD_PI * (-btScalar(0.5) + (btScalar) i / lats);
btScalar z1 = radius*sin(lat1);
btScalar zr1 = radius*cos(lat1);
glBegin(GL_QUAD_STRIP);
for(j = 0; j <= longs; j++) {
btScalar lng = 2 * SIMD_PI * (btScalar) (j - 1) / longs;
btScalar x = cos(lng);
btScalar y = sin(lng);
glNormal3f(x * zr1, y * zr1, z1);
glVertex3f(x * zr1, y * zr1, z1);
glNormal3f(x * zr0, y * zr0, z0);
glVertex3f(x * zr0, y * zr0, z0);
}
glEnd();
}
}
void GL_ShapeDrawer::drawCylinder(float radius,float halfHeight, int upAxis)
{
glPushMatrix();
switch (upAxis)
{
case 0:
glRotatef(-90.0, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -halfHeight);
break;
case 1:
glRotatef(-90.0, 1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, -halfHeight);
break;
case 2:
glTranslatef(0.0, 0.0, -halfHeight);
break;
default:
{
btAssert(0);
}
}
GLUquadricObj *quadObj = gluNewQuadric();
//The gluCylinder subroutine draws a cylinder that is oriented along the z axis.
//The base of the cylinder is placed at z = 0; the top of the cylinder is placed at z=height.
//Like a sphere, the cylinder is subdivided around the z axis into slices and along the z axis into stacks.
gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
gluDisk(quadObj,0,radius,15, 10);
gluCylinder(quadObj, radius, radius, 2.f*halfHeight, 15, 10);
glTranslatef(0.0f, 0.0f, 2.f*halfHeight);
glRotatef(-180.0f, 0.0f, 1.0f, 0.0f);
gluDisk(quadObj,0.f,radius,15, 10);
glPopMatrix();
gluDeleteQuadric(quadObj);
}
GL_ShapeDrawer::ShapeCache* GL_ShapeDrawer::cache(btConvexShape* shape)
{
ShapeCache* sc=(ShapeCache*)shape->getUserPointer();
if(!sc)
{
sc=new(btAlignedAlloc(sizeof(ShapeCache),16)) ShapeCache(shape);
sc->m_shapehull.buildHull(shape->getMargin());
m_shapecaches.push_back(sc);
shape->setUserPointer(sc);
/* Build edges */
const int ni=sc->m_shapehull.numIndices();
const int nv=sc->m_shapehull.numVertices();
const unsigned int* pi=sc->m_shapehull.getIndexPointer();
const btVector3* pv=sc->m_shapehull.getVertexPointer();
btAlignedObjectArray<ShapeCache::Edge*> edges;
sc->m_edges.reserve(ni);
edges.resize(nv*nv,0);
for(int i=0;i<ni;i+=3)
{
const unsigned int* ti=pi+i;
const btVector3 nrm=btCross(pv[ti[1]]-pv[ti[0]],pv[ti[2]]-pv[ti[0]]).normalized();
for(int j=2,k=0;k<3;j=k++)
{
const unsigned int a=ti[j];
const unsigned int b=ti[k];
ShapeCache::Edge*& e=edges[btMin(a,b)*nv+btMax(a,b)];
if(!e)
{
sc->m_edges.push_back(ShapeCache::Edge());
e=&sc->m_edges[sc->m_edges.size()-1];
e->n[0]=nrm;e->n[1]=-nrm;
e->v[0]=a;e->v[1]=b;
}
else
{
e->n[1]=nrm;
}
}
}
}
return(sc);
}
void renderSquareA(float x, float y, float z)
{
glBegin(GL_LINE_LOOP);
glVertex3f(x, y, z);
glVertex3f(x + 10.f, y, z);
glVertex3f(x + 10.f, y + 10.f, z);
glVertex3f(x, y + 10.f, z);
glEnd();
}
inline void glDrawVector(const btVector3& v) { glVertex3d(v[0], v[1], v[2]); }
void GL_ShapeDrawer::drawOpenGL(btScalar* m, const btCollisionShape* shape, const btVector3& color,int debugMode,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax)
{
if (shape->getShapeType() == CUSTOM_CONVEX_SHAPE_TYPE)
{
btVector3 org(m[12], m[13], m[14]);
btVector3 dx(m[0], m[1], m[2]);
btVector3 dy(m[4], m[5], m[6]);
// btVector3 dz(m[8], m[9], m[10]);
const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
btVector3 halfExtent = boxShape->getHalfExtentsWithMargin();
dx *= halfExtent[0];
dy *= halfExtent[1];
// dz *= halfExtent[2];
glColor3f(1,1,1);
glDisable(GL_LIGHTING);
glLineWidth(2);
glBegin(GL_LINE_LOOP);
glDrawVector(org - dx - dy);
glDrawVector(org - dx + dy);
glDrawVector(org + dx + dy);
glDrawVector(org + dx - dy);
glEnd();
return;
}
else if((shape->getShapeType() == BOX_SHAPE_PROXYTYPE) && (debugMode & btIDebugDraw::DBG_FastWireframe))
{
btVector3 org(m[12], m[13], m[14]);
btVector3 dx(m[0], m[1], m[2]);
btVector3 dy(m[4], m[5], m[6]);
btVector3 dz(m[8], m[9], m[10]);
const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
btVector3 halfExtent = boxShape->getHalfExtentsWithMargin();
dx *= halfExtent[0];
dy *= halfExtent[1];
dz *= halfExtent[2];
glBegin(GL_LINE_LOOP);
glDrawVector(org - dx - dy - dz);
glDrawVector(org + dx - dy - dz);
glDrawVector(org + dx + dy - dz);
glDrawVector(org - dx + dy - dz);
glDrawVector(org - dx + dy + dz);
glDrawVector(org + dx + dy + dz);
glDrawVector(org + dx - dy + dz);
glDrawVector(org - dx - dy + dz);
glEnd();
glBegin(GL_LINES);
glDrawVector(org + dx - dy - dz);
glDrawVector(org + dx - dy + dz);
glDrawVector(org + dx + dy - dz);
glDrawVector(org + dx + dy + dz);
glDrawVector(org - dx - dy - dz);
glDrawVector(org - dx + dy - dz);
glDrawVector(org - dx - dy + dz);
glDrawVector(org - dx + dy + dz);
glEnd();
return;
}
glPushMatrix();
btglMultMatrix(m);
if (shape->getShapeType() == UNIFORM_SCALING_SHAPE_PROXYTYPE)
{
const btUniformScalingShape* scalingShape = static_cast<const btUniformScalingShape*>(shape);
const btConvexShape* convexShape = scalingShape->getChildShape();
float scalingFactor = (float)scalingShape->getUniformScalingFactor();
{
btScalar tmpScaling[4][4]={{scalingFactor,0,0,0},
{0,scalingFactor,0,0},
{0,0,scalingFactor,0},
{0,0,0,1}};
drawOpenGL( (btScalar*)tmpScaling,convexShape,color,debugMode,worldBoundsMin,worldBoundsMax);
}
glPopMatrix();
return;
}
if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
{
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--)
{
btTransform childTrans = compoundShape->getChildTransform(i);
const btCollisionShape* colShape = compoundShape->getChildShape(i);
ATTRIBUTE_ALIGNED16(btScalar) childMat[16];
childTrans.getOpenGLMatrix(childMat);
drawOpenGL(childMat,colShape,color,debugMode,worldBoundsMin,worldBoundsMax);
}
} else
{
if(m_textureenabled&&(!m_textureinitialized))
{
GLubyte* image=new GLubyte[256*256*3];
for(int y=0;y<256;++y)
{
const int t=y>>4;
GLubyte* pi=image+y*256*3;
for(int x=0;x<256;++x)
{
const int s=x>>4;
const GLubyte b=180;
GLubyte c=b+((s+t&1)&1)*(255-b);
pi[0]=pi[1]=pi[2]=c;pi+=3;
}
}
glGenTextures(1,(GLuint*)&m_texturehandle);
glBindTexture(GL_TEXTURE_2D,m_texturehandle);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,256,256,GL_RGB,GL_UNSIGNED_BYTE,image);
delete[] image;
}
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(0.025f,0.025f,0.025f);
glMatrixMode(GL_MODELVIEW);
static const GLfloat planex[]={1,0,0,0};
// static const GLfloat planey[]={0,1,0,0};
static const GLfloat planez[]={0,0,1,0};
glTexGenfv(GL_S,GL_OBJECT_PLANE,planex);
glTexGenfv(GL_T,GL_OBJECT_PLANE,planez);
glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
m_textureinitialized=true;
//drawCoordSystem();
//glPushMatrix();
glEnable(GL_COLOR_MATERIAL);
if(m_textureenabled)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,m_texturehandle);
} else
{
glDisable(GL_TEXTURE_2D);
}
glColor3f(color.x(),color.y(), color.z());
bool useWireframeFallback = true;
if (!(debugMode & btIDebugDraw::DBG_DrawWireframe))
{
///you can comment out any of the specific cases, and use the default
///the benefit of 'default' is that it approximates the actual collision shape including collision margin
//int shapetype=m_textureenabled?MAX_BROADPHASE_COLLISION_TYPES:shape->getShapeType();
int shapetype=shape->getShapeType();
switch (shapetype)
{
case SPHERE_SHAPE_PROXYTYPE:
{
const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
float radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin
drawSphere(radius,10,10);
useWireframeFallback = false;
break;
}
case BOX_SHAPE_PROXYTYPE:
{
const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
btVector3 halfExtent = boxShape->getHalfExtentsWithMargin();
static int indices[36] = {
0,1,2,
3,2,1,
4,0,6,
6,0,2,
5,1,4,
4,1,0,
7,3,1,
7,1,5,
5,4,7,
7,4,6,
7,2,3,
7,6,2};
btVector3 vertices[8]={
btVector3(halfExtent[0],halfExtent[1],halfExtent[2]),
btVector3(-halfExtent[0],halfExtent[1],halfExtent[2]),
btVector3(halfExtent[0],-halfExtent[1],halfExtent[2]),
btVector3(-halfExtent[0],-halfExtent[1],halfExtent[2]),
btVector3(halfExtent[0],halfExtent[1],-halfExtent[2]),
btVector3(-halfExtent[0],halfExtent[1],-halfExtent[2]),
btVector3(halfExtent[0],-halfExtent[1],-halfExtent[2]),
btVector3(-halfExtent[0],-halfExtent[1],-halfExtent[2])};
#if 1
glBegin (GL_TRIANGLES);
int si=36;
for (int i=0;i<si;i+=3)
{
const btVector3& v1 = vertices[indices[i]];;
const btVector3& v2 = vertices[indices[i+1]];
const btVector3& v3 = vertices[indices[i+2]];
btVector3 normal = (v3-v1).cross(v2-v1);
normal.normalize ();
glNormal3f(normal.getX(),normal.getY(),normal.getZ());
glVertex3f (v1.x(), v1.y(), v1.z());
glVertex3f (v2.x(), v2.y(), v2.z());
glVertex3f (v3.x(), v3.y(), v3.z());
}
glEnd();
#endif
useWireframeFallback = false;
break;
}
#if 0
case CONE_SHAPE_PROXYTYPE:
{
const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
int upIndex = coneShape->getConeUpIndex();
float radius = coneShape->getRadius();//+coneShape->getMargin();
float height = coneShape->getHeight();//+coneShape->getMargin();
switch (upIndex)
{
case 0:
glRotatef(90.0, 0.0, 1.0, 0.0);
break;
case 1:
glRotatef(-90.0, 1.0, 0.0, 0.0);
break;
case 2:
break;
default:
{
}
};
glTranslatef(0.0, 0.0, -0.5*height);
glutSolidCone(radius,height,10,10);
useWireframeFallback = false;
break;
}
#endif
case STATIC_PLANE_PROXYTYPE:
{
const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
btScalar planeConst = staticPlaneShape->getPlaneConstant();
const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
btVector3 planeOrigin = planeNormal * planeConst;
btVector3 vec0,vec1;
btPlaneSpace1(planeNormal,vec0,vec1);
btScalar vecLen = 100.f;
btVector3 pt0 = planeOrigin + vec0*vecLen;
btVector3 pt1 = planeOrigin - vec0*vecLen;
btVector3 pt2 = planeOrigin + vec1*vecLen;
btVector3 pt3 = planeOrigin - vec1*vecLen;
glBegin(GL_LINES);
glVertex3f(pt0.getX(),pt0.getY(),pt0.getZ());
glVertex3f(pt1.getX(),pt1.getY(),pt1.getZ());
glVertex3f(pt2.getX(),pt2.getY(),pt2.getZ());
glVertex3f(pt3.getX(),pt3.getY(),pt3.getZ());
glEnd();
break;
}
/*
case CYLINDER_SHAPE_PROXYTYPE:
{
const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
int upAxis = cylinder->getUpAxis();
float radius = cylinder->getRadius();
float halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
drawCylinder(radius,halfHeight,upAxis);
break;
}
*/
case MULTI_SPHERE_SHAPE_PROXYTYPE:
{
const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
btTransform childTransform;
childTransform.setIdentity();
for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--)
{
btSphereShape sc(multiSphereShape->getSphereRadius(i));
childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
ATTRIBUTE_ALIGNED16(btScalar) childMat[16];
childTransform.getOpenGLMatrix(childMat);
drawOpenGL(childMat,&sc,color,debugMode,worldBoundsMin,worldBoundsMax);
}
break;
}
default:
{
if (shape->isConvex())
{
const btConvexPolyhedron* poly = shape->isPolyhedral() ? ((btPolyhedralConvexShape*) shape)->getConvexPolyhedron() : 0;
if (poly)
{
int i;
glBegin (GL_TRIANGLES);
for (i=0;i<poly->m_faces.size();i++)
{
btVector3 centroid(0,0,0);
int numVerts = poly->m_faces[i].m_indices.size();
if (numVerts>2)
{
btVector3 v1 = poly->m_vertices[poly->m_faces[i].m_indices[0]];
for (int v=0;v<poly->m_faces[i].m_indices.size()-2;v++)
{
btVector3 v2 = poly->m_vertices[poly->m_faces[i].m_indices[v+1]];
btVector3 v3 = poly->m_vertices[poly->m_faces[i].m_indices[v+2]];
btVector3 normal = (v3-v1).cross(v2-v1);
normal.normalize ();
glNormal3f(normal.getX(),normal.getY(),normal.getZ());
glVertex3f (v1.x(), v1.y(), v1.z());
glVertex3f (v2.x(), v2.y(), v2.z());
glVertex3f (v3.x(), v3.y(), v3.z());
}
}
}
glEnd ();
} else
{
ShapeCache* sc=cache((btConvexShape*)shape);
//glutSolidCube(1.0);
btShapeHull* hull = &sc->m_shapehull/*(btShapeHull*)shape->getUserPointer()*/;
if (hull->numTriangles () > 0)
{
int index = 0;
const unsigned int* idx = hull->getIndexPointer();
const btVector3* vtx = hull->getVertexPointer();
glBegin (GL_TRIANGLES);
for (int i = 0; i < hull->numTriangles (); i++)
{
int i1 = index++;
int i2 = index++;
int i3 = index++;
btAssert(i1 < hull->numIndices () &&
i2 < hull->numIndices () &&
i3 < hull->numIndices ());
int index1 = idx[i1];
int index2 = idx[i2];
int index3 = idx[i3];
btAssert(index1 < hull->numVertices () &&
index2 < hull->numVertices () &&
index3 < hull->numVertices ());
btVector3 v1 = vtx[index1];
btVector3 v2 = vtx[index2];
btVector3 v3 = vtx[index3];
btVector3 normal = (v3-v1).cross(v2-v1);
normal.normalize ();
glNormal3f(normal.getX(),normal.getY(),normal.getZ());
glVertex3f (v1.x(), v1.y(), v1.z());
glVertex3f (v2.x(), v2.y(), v2.z());
glVertex3f (v3.x(), v3.y(), v3.z());
}
glEnd ();
}
}
}
}
}
}
glNormal3f(0,1,0);
/// for polyhedral shapes
if (debugMode==btIDebugDraw::DBG_DrawFeaturesText && (shape->isPolyhedral()))
{
btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape;
{
glColor3f(1.f, 1.f, 1.f);
int i;
for (i=0;i<polyshape->getNumVertices();i++)
{
btVector3 vtx;
polyshape->getVertex(i,vtx);
char buf[12];
sprintf(buf," %d",i);
//btDrawString(BMF_GetFont(BMF_kHelvetica10),buf);
}
for (i=0;i<polyshape->getNumPlanes();i++)
{
btVector3 normal;
btVector3 vtx;
polyshape->getPlane(normal,vtx,i);
//btScalar d = vtx.dot(normal);
//char buf[12];
//sprintf(buf," plane %d",i);
//btDrawString(BMF_GetFont(BMF_kHelvetica10),buf);
}
}
}
#ifdef USE_DISPLAY_LISTS
if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
{
GLuint dlist = OGL_get_displaylist_for_shape((btCollisionShape * )shape);
if (dlist)
{
glCallList(dlist);
}
else
{
#else
if (shape->isConcave() && !shape->isInfinite())
{
btConcaveShape* concaveMesh = (btConcaveShape*) shape;
GlDrawcallback drawCallback;
drawCallback.m_wireframe = (debugMode & btIDebugDraw::DBG_DrawWireframe)!=0;
concaveMesh->processAllTriangles(&drawCallback,worldBoundsMin,worldBoundsMax);
}
#endif
#ifdef USE_DISPLAY_LISTS
}
}
#endif
}
glPopMatrix();
}
//
void GL_ShapeDrawer::drawShadow(btScalar* m,const btVector3& extrusion,const btCollisionShape* shape,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax)
{
glPushMatrix();
btglMultMatrix(m);
if(shape->getShapeType() == UNIFORM_SCALING_SHAPE_PROXYTYPE)
{
const btUniformScalingShape* scalingShape = static_cast<const btUniformScalingShape*>(shape);
const btConvexShape* convexShape = scalingShape->getChildShape();
float scalingFactor = (float)scalingShape->getUniformScalingFactor();
btScalar tmpScaling[4][4]={ {scalingFactor,0,0,0},
{0,scalingFactor,0,0},
{0,0,scalingFactor,0},
{0,0,0,1}};
drawShadow((btScalar*)tmpScaling,extrusion,convexShape,worldBoundsMin,worldBoundsMax);
glPopMatrix();
return;
}
else if(shape->getShapeType()==COMPOUND_SHAPE_PROXYTYPE)
{
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--)
{
btTransform childTrans = compoundShape->getChildTransform(i);
const btCollisionShape* colShape = compoundShape->getChildShape(i);
ATTRIBUTE_ALIGNED16(btScalar) childMat[16];
childTrans.getOpenGLMatrix(childMat);
drawShadow(childMat,extrusion*childTrans.getBasis(),colShape,worldBoundsMin,worldBoundsMax);
}
}
else
{
// bool useWireframeFallback = true;
if (shape->isConvex())
{
ShapeCache* sc=cache((btConvexShape*)shape);
btShapeHull* hull =&sc->m_shapehull;
glBegin(GL_QUADS);
for(int i=0;i<sc->m_edges.size();++i)
{
const btScalar d=btDot(sc->m_edges[i].n[0],extrusion);
if((d*btDot(sc->m_edges[i].n[1],extrusion))<0)
{
const int q= d<0?1:0;
const btVector3& a= hull->getVertexPointer()[sc->m_edges[i].v[q]];
const btVector3& b= hull->getVertexPointer()[sc->m_edges[i].v[1-q]];
glVertex3f(a[0],a[1],a[2]);
glVertex3f(b[0],b[1],b[2]);
glVertex3f(b[0]+extrusion[0],b[1]+extrusion[1],b[2]+extrusion[2]);
glVertex3f(a[0]+extrusion[0],a[1]+extrusion[1],a[2]+extrusion[2]);
}
}
glEnd();
}
}
if (shape->isConcave())//>getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
// if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
btConcaveShape* concaveMesh = (btConcaveShape*) shape;
GlDrawcallback drawCallback;
drawCallback.m_wireframe = false;
concaveMesh->processAllTriangles(&drawCallback,worldBoundsMin,worldBoundsMax);
}
glPopMatrix();
}
//
GL_ShapeDrawer::GL_ShapeDrawer()
{
m_texturehandle = 0;
m_textureenabled = false;
m_textureinitialized = false;
}
GL_ShapeDrawer::~GL_ShapeDrawer()
{
int i;
for (i=0;i<m_shapecaches.size();i++)
{
m_shapecaches[i]->~ShapeCache();
btAlignedFree(m_shapecaches[i]);
}
m_shapecaches.clear();
if(m_textureinitialized)
{
glDeleteTextures(1,(const GLuint*) &m_texturehandle);
}
}

View File

@@ -0,0 +1,70 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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_SHAPE_DRAWER_H
#define GL_SHAPE_DRAWER_H
class btCollisionShape;
class btShapeHull;
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btVector3.h"
#include "BulletCollision/CollisionShapes/btShapeHull.h"
/// OpenGL shape drawing
class GL_ShapeDrawer
{
protected:
struct ShapeCache
{
struct Edge { btVector3 n[2];int v[2]; };
ShapeCache(btConvexShape* s) : m_shapehull(s) {}
btShapeHull m_shapehull;
btAlignedObjectArray<Edge> m_edges;
};
//clean-up memory of dynamically created shape hulls
btAlignedObjectArray<ShapeCache*> m_shapecaches;
unsigned int m_texturehandle;
bool m_textureenabled;
bool m_textureinitialized;
ShapeCache* cache(btConvexShape*);
public:
GL_ShapeDrawer();
virtual ~GL_ShapeDrawer();
///drawOpenGL might allocate temporary memoty, stores pointer in shape userpointer
virtual void drawOpenGL(btScalar* m, const btCollisionShape* shape, const btVector3& color,int debugMode,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax);
virtual void drawShadow(btScalar* m, const btVector3& extrusion,const btCollisionShape* shape,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax);
bool enableTexture(bool enable) { bool p=m_textureenabled;m_textureenabled=enable;return(p); }
bool hasTextureEnabled() const
{
return m_textureenabled;
}
static void drawCylinder(float radius,float halfHeight, int upAxis);
void drawSphere(btScalar r, int lats, int longs);
static void drawCoordSystem();
};
void OGL_displaylist_register_shape(btCollisionShape * shape);
void OGL_displaylist_clean();
#endif //GL_SHAPE_DRAWER_H

View File

@@ -0,0 +1,80 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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_Simplex1to4.h"
#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
#include "GL_ShapeDrawer.h"
#ifdef _WIN32
#include <windows.h>
#endif
//think different
#if defined(__APPLE__) && !defined (VMDMESA)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#endif
#include "GlutStuff.h"
#include "LinearMath/btTransform.h"
GL_Simplex1to4::GL_Simplex1to4()
:m_simplexSolver(0)
{
}
GL_Simplex1to4::~GL_Simplex1to4()
{
}
///
/// Debugging method calcClosest calculates the closest point to the origin, using m_simplexSolver
///
void GL_Simplex1to4::calcClosest(btScalar* m)
{
btTransform tr;
tr.setFromOpenGLMatrix(m);
GL_ShapeDrawer::drawCoordSystem();
if (m_simplexSolver)
{
m_simplexSolver->reset();
bool res;
btVector3 v;
for (int i=0;i<m_numVertices;i++)
{
v = tr(m_vertices[i]);
m_simplexSolver->addVertex(v,v,btVector3(0.f,0.f,0.f));
res = m_simplexSolver->closest(v);
}
//draw v?
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
btglColor3(1.f, 0.f, 0.f);
btglVertex3(0.f, 0.f, 0.f);
btglVertex3(v.x(),v.y(),v.z());
glEnd();
glEnable(GL_LIGHTING);
}
}

View File

@@ -0,0 +1,41 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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_SIMPLEX_1TO4_H
#define GL_SIMPLEX_1TO4_H
#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
///GL_Simplex1to4 is a class to debug a Simplex Solver with 1 to 4 points.
///Can be used by GJK.
class GL_Simplex1to4 : public btBU_Simplex1to4
{
btSimplexSolverInterface* m_simplexSolver;
public:
GL_Simplex1to4();
virtual ~GL_Simplex1to4();
void calcClosest(btScalar* m);
void setSimplexSolver(btSimplexSolverInterface* simplexSolver) {
m_simplexSolver = simplexSolver;
}
};
#endif //GL_SIMPLEX_1TO4_H

View File

@@ -0,0 +1,87 @@
#ifndef _WINDOWS
#include "GlutDemoApplication.h"
#include "GlutStuff.h"
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
void GlutDemoApplication::updateModifierKeys()
{
m_modifierKeys = 0;
if (glutGetModifiers() & GLUT_ACTIVE_ALT)
m_modifierKeys |= BT_ACTIVE_ALT;
if (glutGetModifiers() & GLUT_ACTIVE_CTRL)
m_modifierKeys |= BT_ACTIVE_CTRL;
if (glutGetModifiers() & GLUT_ACTIVE_SHIFT)
m_modifierKeys |= BT_ACTIVE_SHIFT;
}
void GlutDemoApplication::specialKeyboard(int key, int x, int y)
{
(void)x;
(void)y;
switch (key)
{
case GLUT_KEY_F1:
{
break;
}
case GLUT_KEY_F2:
{
break;
}
case GLUT_KEY_END:
{
int numObj = getDynamicsWorld()->getNumCollisionObjects();
if (numObj)
{
btCollisionObject* obj = getDynamicsWorld()->getCollisionObjectArray()[numObj-1];
getDynamicsWorld()->removeCollisionObject(obj);
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
delete body->getMotionState();
}
delete obj;
}
break;
}
case GLUT_KEY_LEFT : stepLeft(); break;
case GLUT_KEY_RIGHT : stepRight(); break;
case GLUT_KEY_UP : stepFront(); break;
case GLUT_KEY_DOWN : stepBack(); break;
case GLUT_KEY_PAGE_UP : zoomIn(); break;
case GLUT_KEY_PAGE_DOWN : zoomOut(); break;
case GLUT_KEY_HOME : toggleIdle(); break;
default:
// std::cout << "unused (special) key : " << key << std::endl;
break;
}
glutPostRedisplay();
}
void GlutDemoApplication::swapBuffers()
{
glutSwapBuffers();
}
#endif //_WINDOWS

View File

@@ -0,0 +1,36 @@
/*
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 GLUT_DEMO_APPLICATION_H
#define GLUT_DEMO_APPLICATION_H
#include "DemoApplication.h"
ATTRIBUTE_ALIGNED16(class) GlutDemoApplication : public DemoApplication
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
void specialKeyboard(int key, int x, int y);
virtual void swapBuffers();
virtual void updateModifierKeys();
};
#endif //GLUT_DEMO_APPLICATION_H

120
Demos/OpenGL/GlutStuff.cpp Normal file
View File

@@ -0,0 +1,120 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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 _WINDOWS
#include "DemoApplication.h"
//glut is C code, this global gDemoApplication links glut to the C++ demo
static DemoApplication* gDemoApplication = 0;
#include "GlutStuff.h"
static void glutKeyboardCallback(unsigned char key, int x, int y)
{
gDemoApplication->keyboardCallback(key,x,y);
}
static void glutKeyboardUpCallback(unsigned char key, int x, int y)
{
gDemoApplication->keyboardUpCallback(key,x,y);
}
static void glutSpecialKeyboardCallback(int key, int x, int y)
{
gDemoApplication->specialKeyboard(key,x,y);
}
static void glutSpecialKeyboardUpCallback(int key, int x, int y)
{
gDemoApplication->specialKeyboardUp(key,x,y);
}
static void glutReshapeCallback(int w, int h)
{
gDemoApplication->reshape(w,h);
}
static void glutMoveAndDisplayCallback()
{
gDemoApplication->moveAndDisplay();
}
static void glutMouseFuncCallback(int button, int state, int x, int y)
{
gDemoApplication->mouseFunc(button,state,x,y);
}
static void glutMotionFuncCallback(int x,int y)
{
gDemoApplication->mouseMotionFunc(x,y);
}
static void glutDisplayCallback(void)
{
gDemoApplication->displayCallback();
}
int glutmain(int argc, char **argv,int width,int height,const char* title,DemoApplication* demoApp) {
gDemoApplication = demoApp;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
glutInitWindowPosition(width/2, height/2);
glutInitWindowSize(width, height);
glutCreateWindow(title);
#ifdef BT_USE_FREEGLUT
glutSetOption (GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
#endif
gDemoApplication->myinit();
glutKeyboardFunc(glutKeyboardCallback);
glutKeyboardUpFunc(glutKeyboardUpCallback);
glutSpecialFunc(glutSpecialKeyboardCallback);
glutSpecialUpFunc(glutSpecialKeyboardUpCallback);
glutReshapeFunc(glutReshapeCallback);
//createMenu();
glutIdleFunc(glutMoveAndDisplayCallback);
glutMouseFunc(glutMouseFuncCallback);
glutPassiveMotionFunc(glutMotionFuncCallback);
glutMotionFunc(glutMotionFuncCallback);
glutDisplayFunc( glutDisplayCallback );
glutMoveAndDisplayCallback();
//enable vsync to avoid tearing on Apple (todo: for Windows)
#if defined(__APPLE__) && !defined (VMDMESA)
int swap_interval = 1;
CGLContextObj cgl_context = CGLGetCurrentContext();
CGLSetParameter(cgl_context, kCGLCPSwapInterval, &swap_interval);
#endif
glutMainLoop();
return 0;
}
#endif //_WINDOWS

86
Demos/OpenGL/GlutStuff.h Normal file
View File

@@ -0,0 +1,86 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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 GLUT_STUFF_H
#define GLUT_STUFF_H
#ifdef _WIN32//for glut.h
#include <windows.h>
#endif
//think different
#if defined(__APPLE__) && !defined (VMDMESA)
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#else
#ifdef _WINDOWS
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glut.h>
#endif //_WINDOWS
#endif //APPLE
#ifdef _WINDOWS
#define BT_ACTIVE_ALT VK_LMENU
#define BT_ACTIVE_SHIFT VK_LSHIFT
#else
#define BT_KEY_K 'k'
#define BT_KEY_LEFT GLUT_KEY_LEFT
#define BT_KEY_RIGHT GLUT_KEY_RIGHT
#define BT_KEY_UP GLUT_KEY_UP
#define BT_KEY_DOWN GLUT_KEY_DOWN
#define BT_KEY_F1 GLUT_KEY_F1
#define BT_KEY_F2 GLUT_KEY_F2
#define BT_KEY_F3 GLUT_KEY_F3
#define BT_KEY_F4 GLUT_KEY_F4
#define BT_KEY_F5 GLUT_KEY_F5
#define BT_KEY_PAGEUP GLUT_KEY_PAGE_UP
#define BT_KEY_PAGEDOWN GLUT_KEY_PAGE_DOWN
#define BT_KEY_END GLUT_KEY_END
#define BT_KEY_HOME GLUT_KEY_HOME
#define BT_ACTIVE_ALT GLUT_ACTIVE_ALT
#define BT_ACTIVE_CTRL GLUT_ACTIVE_ALT
#define BT_ACTIVE_SHIFT GLUT_ACTIVE_SHIFT
#endif
#if BT_USE_FREEGLUT
#include "GL/freeglut_ext.h" //to be able to return from glutMainLoop()
#endif
class DemoApplication;
int glutmain(int argc, char **argv,int width,int height,const char* title,DemoApplication* demoApp);
#if defined(BT_USE_DOUBLE_PRECISION)
#define btglLoadMatrix glLoadMatrixd
#define btglMultMatrix glMultMatrixd
#define btglColor3 glColor3d
#define btglVertex3 glVertex3d
#else
#define btglLoadMatrix glLoadMatrixf
#define btglMultMatrix glMultMatrixf
#define btglColor3 glColor3f
#define btglVertex3 glVertex3d
#endif
#endif //GLUT_STUFF_H

12
Demos/OpenGL/Makefile.am Normal file
View File

@@ -0,0 +1,12 @@
noinst_LIBRARIES = libbulletopenglsupport.a
libbulletopenglsupport_a_SOURCES = \
DemoApplication.cpp GLDebugDrawer.h GL_Simplex1to4.cpp \
GLDebugFont.cpp GLDebugFont.h GlutDemoApplication.cpp GlutDemoApplication.h \
GlutStuff.h \
DemoApplication.h GL_ShapeDrawer.cpp \
GL_Simplex1to4.h RenderTexture.cpp \
DebugCastResult.h GLDebugDrawer.cpp \
GL_ShapeDrawer.h GlutStuff.cpp RenderTexture.h
INCLUDES=-I../../src

View File

@@ -0,0 +1,86 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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 "RenderTexture.h"
#include <memory.h>
renderTexture::renderTexture(int width,int height)
:m_height(height),m_width(width)
{
m_buffer = new unsigned char[m_width*m_height*4];
//clear screen
memset(m_buffer,0,m_width*m_height*4);
//clear screen version 2
for (int x=0;x<m_width;x++)
{
for (int y=0;y<m_height;y++)
{
setPixel(x,y,btVector4(float(x),float(y),0.f,1.f));
}
}
}
void renderTexture::grapicalPrintf(char* str, void* fontData, int rasterposx,int rasterposy)
{
unsigned char c;
int x=0;
int xx=0;
while ((c = (unsigned char) *str++)) {
x=xx;
unsigned char* fontPtr = (unsigned char*) fontData;
char ch = c-32;
int sx=ch%16;
int sy=ch/16;
for (int i=sx*16;i<(sx*16+16);i++)
{
int y=0;
for (int j=sy*16;j<(sy*16+16);j++)
{
unsigned char packedColor = (fontPtr[i*3+255*256*3-(256*j)*3]);
//float colorf = packedColor ? 0.f : 1.f;
float colorf = packedColor/255.f;// ? 0.f : 1.f;
btVector4 rgba(colorf,colorf,colorf,1.f);
//if (colorf)
{
//setPixel(rasterposx+x,rasterposy+y,rgba);
addPixel(rasterposx+x,rasterposy+y,rgba);
}
//bit >>=1;
y++;
}
x++;
}
//xx+=16;
xx+=10;
}
}
renderTexture::~renderTexture()
{
delete [] m_buffer;
}

View File

@@ -0,0 +1,73 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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 RENDER_TEXTURE_H
#define RENDER_TEXTURE_H
#include "LinearMath/btVector3.h"
#include "GLDebugFont.h"
///
///renderTexture provides a software-render context (setpixel/printf)
///
class renderTexture
{
int m_height;
int m_width;
unsigned char* m_buffer;
public:
renderTexture(int width,int height);
~renderTexture();
///rgba input is in range [0..1] for each component
inline void setPixel(int x,int y,const btVector4& rgba)
{
unsigned char* pixel = &m_buffer[ (x+y*m_width) * 4];
pixel[0] = (unsigned char)(255.*rgba.getX());
pixel[1] = (unsigned char)(255.*rgba.getY());
pixel[2] = (unsigned char)(255.*rgba.getZ());
pixel[3] = (unsigned char)(255.*rgba.getW());
}
inline void addPixel(int x,int y,const btVector4& rgba)
{
unsigned char* pixel = &m_buffer[ (x+y*m_width) * 4];
pixel[0] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[0] + btScalar(255.f)*rgba.getX()));
pixel[1] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[1] + btScalar(255.f)*rgba.getY()));
pixel[2] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[2] + btScalar(255.f)*rgba.getZ()));
// pixel[3] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[3] + btScalar(255.f)*rgba.getW()));
}
inline btVector4 getPixel(int x,int y)
{
unsigned char* pixel = &m_buffer[ (x+y*m_width) * 4];
return btVector4(pixel[0]*1.f/255.f,
pixel[1]*1.f/255.f,
pixel[2]*1.f/255.f,
pixel[3]*1.f/255.f);
}
const unsigned char* getBuffer() const { return m_buffer;}
int getWidth() const { return m_width;}
int getHeight() const { return m_height;}
void grapicalPrintf(char* str, void* fontData, int startx = 0,int starty=0);
};
#endif //RENDER_TEXTURE_H

View File

@@ -0,0 +1,473 @@
#ifdef _WINDOWS
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2010 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 <windows.h>
#include <gl/gl.h>
#include "DemoApplication.h"
#include "GLDebugDrawer.h"
#include "GLDebugFont.h"
#include "BulletDynamics/Dynamics/btDynamicsWorld.h"
/// This Win32AppMain is shared code between all demos.
/// The actual demo, derived from DemoApplication is created using 'createDemo', in a separate .cpp file
DemoApplication* gDemoApplication = 0;
DemoApplication* createDemo();
// Function Declarations
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC);
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC);
static bool sOpenGLInitialized = false;
static int sWidth = 0;
static int sHeight =0;
static int quitRequest = 0;
// WinMain
#ifdef USE_AMD_OPENCL
#include "btOpenCLUtils.h"
#include <LinearMath/btScalar.h>
cl_context g_cxMainContext;
cl_device_id g_cdDevice;
cl_command_queue g_cqCommandQue;
// Returns true if OpenCL is initialized properly, false otherwise.
bool initCL( void* glCtx, void* glDC )
{
const char* vendorSDK = btOpenCLUtils::getSdkVendorName();
printf("This program was compiled using the %s OpenCL SDK\n",vendorSDK);
int ciErrNum = 0;
#ifdef BT_USE_CLEW
ciErrNum = clewInit( "OpenCL.dll" );
if ( ciErrNum != CLEW_SUCCESS ) {
return false;
}
#endif
#if defined(CL_PLATFORM_MINI_CL)
cl_device_type deviceType = CL_DEVICE_TYPE_CPU;
#elif defined(CL_PLATFORM_AMD)
cl_device_type deviceType = CL_DEVICE_TYPE_GPU;
#elif defined(CL_PLATFORM_NVIDIA)
cl_device_type deviceType = CL_DEVICE_TYPE_GPU;
#else
cl_device_type deviceType = CL_DEVICE_TYPE_CPU;
#endif
g_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC);
oclCHECKERROR(ciErrNum, CL_SUCCESS);
int numDev = btOpenCLUtils::getNumDevices(g_cxMainContext);
if (!numDev)
return false;
g_cdDevice = btOpenCLUtils::getDevice(g_cxMainContext,0);
btOpenCLDeviceInfo clInfo;
btOpenCLUtils::getDeviceInfo(g_cdDevice,clInfo);
btOpenCLUtils::printDeviceInfo(g_cdDevice);
// create a command-queue
g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_cdDevice, 0, &ciErrNum);
oclCHECKERROR(ciErrNum, CL_SUCCESS);
return true;
}
#endif //#ifdef USE_AMD_OPENCL
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int iCmdShow)
{
WNDCLASS wc;
HWND hWnd;
HDC hDC;
HGLRC hRC;
MSG msg;
BOOL quit = FALSE;
float theta = 0.0f;
gDemoApplication = createDemo();
#ifdef USE_AMD_OPENCL
bool initialized = initCL(0,0);
btAssert(initialized);
#endif //USE_AMD_OPENCL
// register window class
wc.style = CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
wc.lpszMenuName = NULL;
wc.lpszClassName = "BulletPhysics";
RegisterClass( &wc );
// create main window
hWnd = CreateWindow(
"BulletPhysics", "Bullet Physics Sample. http://bulletphysics.org",
WS_CAPTION | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
// 0, 0, 640, 480,
0, 0, 1024, 768,
NULL, NULL, hInstance, NULL );
// enable OpenGL for the window
EnableOpenGL( hWnd, &hDC, &hRC );
GLDebugDrawer debugDraw;
gDemoApplication->myinit();
//gDemoApplication->reshape(1024, 768);
gDemoApplication->initPhysics();
if (gDemoApplication->getDynamicsWorld())
gDemoApplication->getDynamicsWorld()->setDebugDrawer(&debugDraw);
gDemoApplication->reshape(sWidth,sHeight);
// program main loop
while ( !quit )
{
// check for messages
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
// handle or dispatch messages
if ( msg.message == WM_QUIT )
{
quit = TRUE;
}
else
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
// gDemoApplication->displayCallback();
};
// OpenGL animation code goes here
glClearColor( .7f, 0.7f, 0.7f, 1.f );
gDemoApplication->moveAndDisplay();
SwapBuffers( hDC );
theta += 1.0f;
}
// shutdown OpenGL
DisableOpenGL( hWnd, hDC, hRC );
// destroy the window explicitly
DestroyWindow( hWnd );
delete gDemoApplication;
return msg.wParam;
}
// Window Procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SYSKEYDOWN:
{
if (lParam & 1<<29)
{
gDemoApplication->m_modifierKeys = VK_LMENU;
}
break;
}
case WM_SYSKEYUP:
{
if (lParam & 1<<29)
{
gDemoApplication->m_modifierKeys = VK_LMENU;
} else
{
gDemoApplication->m_modifierKeys = 0;
}
break;
}
case WM_SIZE: // Size Action Has Taken Place
switch (wParam) // Evaluate Size Action
{
case SIZE_MINIMIZED: // Was Window Minimized?
return 0; // Return
case SIZE_MAXIMIZED: // Was Window Maximized?
sWidth = LOWORD (lParam);
sHeight = HIWORD (lParam);
if (sOpenGLInitialized)
{
gDemoApplication->reshape(sWidth,sHeight);
}
return 0; // Return
case SIZE_RESTORED: // Was Window Restored?
sWidth = LOWORD (lParam);
sHeight = HIWORD (lParam);
if (sOpenGLInitialized)
{
gDemoApplication->reshape(sWidth,sHeight);
}
return 0; // Return
}
break;
case WM_CREATE:
return 0;
case WM_MBUTTONUP:
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
gDemoApplication->mouseFunc(1,1,xPos,yPos);
break;
}
case WM_MBUTTONDOWN:
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
gDemoApplication->mouseFunc(1,0,xPos,yPos);
break;
}
case WM_LBUTTONUP:
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
gDemoApplication->mouseFunc(0,1,xPos,yPos);
break;
}
case 0x020A://WM_MOUSEWHEEL:
{
int zDelta = (short)HIWORD(wParam);
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
if (zDelta>0)
gDemoApplication->zoomIn();
else
gDemoApplication->zoomOut();
break;
}
case WM_MOUSEMOVE:
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
gDemoApplication->mouseMotionFunc(xPos,yPos);
break;
}
case WM_RBUTTONUP:
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
gDemoApplication->mouseFunc(2,1,xPos,yPos);
break;
}
case WM_RBUTTONDOWN:
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
gDemoApplication->mouseFunc(2,0,xPos,yPos);
break;
}
case WM_LBUTTONDOWN:
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
gDemoApplication->mouseFunc(0,0,xPos,yPos);
break;
}
/*#define WM_LBUTTONUP 0x0202
#define WM_LBUTTONDBLCLK 0x0203
#define WM_RBUTTONDOWN 0x0204
#define WM_RBUTTONUP 0x0205
#define WM_RBUTTONDBLCLK 0x0206
#define WM_MBUTTONDOWN 0x0207
#define WM_MBUTTONUP 0x0208
#define WM_MBUTTONDBLCLK 0x0209
*/
case WM_CLOSE:
PostQuitMessage( 0 );
return 0;
case WM_DESTROY:
return 0;
case WM_KEYUP:
switch ( wParam )
{
case VK_PRIOR:
case VK_NEXT:
case VK_END:
case VK_HOME:
case VK_LEFT:
case VK_UP:
case VK_RIGHT:
case VK_DOWN:
{
if (gDemoApplication)
gDemoApplication->specialKeyboardUp(wParam,0,0);
return 0;
}
default:
{
gDemoApplication->keyboardUpCallback(tolower(wParam),0,0);
}
return DefWindowProc( hWnd, message, wParam, lParam );
}
case WM_KEYDOWN:
printf("bla\n");
switch ( wParam )
{
case VK_CONTROL:
case VK_PRIOR:
case VK_NEXT:
case VK_END:
case VK_HOME:
case VK_LEFT:
case VK_UP:
case VK_RIGHT:
case VK_DOWN:
{
if (gDemoApplication)
gDemoApplication->specialKeyboard(wParam,0,0);
break;
}
case ' ':
{
if (gDemoApplication)
gDemoApplication->clientResetScene();
break;
}
case 'Q':
case VK_ESCAPE:
{
quitRequest = 1;
PostQuitMessage(0);
}
return 0;
}
return 0;
case WM_CHAR:
if (!quitRequest)
gDemoApplication->keyboardCallback(wParam,0,0);
break;
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0;
}
// Enable OpenGL
void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int format;
// get the device context (DC)
*hDC = GetDC( hWnd );
// set the pixel format for the DC
ZeroMemory( &pfd, sizeof( pfd ) );
pfd.nSize = sizeof( pfd );
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.cStencilBits = 1;
pfd.iLayerType = PFD_MAIN_PLANE;
format = ChoosePixelFormat( *hDC, &pfd );
SetPixelFormat( *hDC, format, &pfd );
// create and enable the render context (RC)
*hRC = wglCreateContext( *hDC );
wglMakeCurrent( *hDC, *hRC );
sOpenGLInitialized = true;
}
// Disable OpenGL
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC)
{
sOpenGLInitialized = false;
wglMakeCurrent( NULL, NULL );
wglDeleteContext( hRC );
ReleaseDC( hWnd, hDC );
}
#endif //_WINDOWS

View File

@@ -0,0 +1,79 @@
/*
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.
*/
#ifdef _WINDOWS
#include "Win32DemoApplication.h"
#if 0
void Win32DemoApplication::renderme()
{
}
void Win32DemoApplication::setTexturing(bool useTexture)
{
}
void Win32DemoApplication::setShadows(bool useShadows)
{
}
void Win32DemoApplication::setCameraDistance(float camDist)
{
}
void Win32DemoApplication::clientResetScene()
{
}
#endif
void Win32DemoApplication::updateModifierKeys()
{
//not yet
}
void Win32DemoApplication::specialKeyboard(int key, int x, int y)
{
(void)x;
(void)y;
switch (key)
{
case VK_LEFT : stepLeft(); break;
case VK_RIGHT : stepRight(); break;
case VK_UP : stepFront(); break;
case VK_DOWN : stepBack(); break;
// case GLUT_KEY_PAGE_UP : zoomIn(); break;
// case GLUT_KEY_PAGE_DOWN : zoomOut(); break;
// case GLUT_KEY_HOME : toggleIdle(); break;
default:
// std::cout << "unused (special) key : " << key << std::endl;
break;
}
}
void Win32DemoApplication::swapBuffers()
{
}
#endif

View File

@@ -0,0 +1,41 @@
/*
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 WIN32_DEMO_APPLICATION_H
#define WIN32_DEMO_APPLICATION_H
#include "DemoApplication.h"
ATTRIBUTE_ALIGNED16(class) Win32DemoApplication : public DemoApplication
{
protected:
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
virtual void swapBuffers();
void specialKeyboard(int key, int x, int y);
virtual void updateModifierKeys();
};
#endif //WIN32_DEMO_APPLICATION_H

18
Demos/OpenGL/premake4.lua Normal file
View File

@@ -0,0 +1,18 @@
project "OpenGLSupport"
kind "StaticLib"
targetdir "../../lib"
includedirs {
".",
"../../src"
}
configuration {"Windows"}
includedirs {
"../Glut"
}
configuration{}
files {
"**.cpp",
"**.h"
}

4341
Demos/OpenGL/stb_image.cpp Normal file

File diff suppressed because it is too large Load Diff

332
Demos/OpenGL/stb_image.h Normal file
View File

@@ -0,0 +1,332 @@
/* stbi-1.33 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
when you control the images you're loading
no warranty implied; use at your own risk
QUICK NOTES:
Primarily of interest to game developers and other people who can
avoid problematic images and only need the trivial interface
JPEG baseline (no JPEG progressive)
PNG 8-bit only
TGA (not sure what subset, if a subset)
BMP non-1bpp, non-RLE
PSD (composited view only, no extra channels)
GIF (*comp always reports as 4-channel)
HDR (radiance rgbE format)
PIC (Softimage PIC)
- decode from memory or through FILE (define STBI_NO_STDIO to remove code)
- decode from arbitrary I/O callbacks
- overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
Latest revisions:
1.33 (2011-07-14) minor fixes suggested by Dave Moore
1.32 (2011-07-13) info support for all filetypes (SpartanJ)
1.31 (2011-06-19) a few more leak fixes, bug in PNG handling (SpartanJ)
1.30 (2011-06-11) added ability to load files via io callbacks (Ben Wenger)
1.29 (2010-08-16) various warning fixes from Aurelien Pocheville
1.28 (2010-08-01) fix bug in GIF palette transparency (SpartanJ)
1.27 (2010-08-01) cast-to-uint8 to fix warnings (Laurent Gomila)
allow trailing 0s at end of image data (Laurent Gomila)
1.26 (2010-07-24) fix bug in file buffering for PNG reported by SpartanJ
See end of file for full revision history.
TODO:
stbi_info support for BMP,PSD,HDR,PIC
============================ Contributors =========================
Image formats Optimizations & bugfixes
Sean Barrett (jpeg, png, bmp) Fabian "ryg" Giesen
Nicolas Schulz (hdr, psd)
Jonathan Dummer (tga) Bug fixes & warning fixes
Jean-Marc Lienher (gif) Marc LeBlanc
Tom Seddon (pic) Christpher Lloyd
Thatcher Ulrich (psd) Dave Moore
Won Chun
the Horde3D community
Extensions, features Janez Zemva
Jetro Lauha (stbi_info) Jonathan Blow
James "moose2000" Brown (iPhone PNG) Laurent Gomila
Ben "Disch" Wenger (io callbacks) Aruelien Pocheville
Martin "SpartanJ" Golini Ryamond Barbiero
David Woo
If your name should be here but isn't, let Sean know.
*/
#ifndef STBI_INCLUDE_STB_IMAGE_H
#define STBI_INCLUDE_STB_IMAGE_H
// To get a header file for this, either cut and paste the header,
// or create stb_image.h, #define STBI_HEADER_FILE_ONLY, and
// then include stb_image.c from it.
//// begin header file ////////////////////////////////////////////////////
//
// Limitations:
// - no jpeg progressive support
// - non-HDR formats support 8-bit samples only (jpeg, png)
// - no delayed line count (jpeg) -- IJG doesn't support either
// - no 1-bit BMP
// - GIF always returns *comp=4
//
// Basic usage (see HDR discussion below):
// int x,y,n;
// unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
// // ... process data if not NULL ...
// // ... x = width, y = height, n = # 8-bit components per pixel ...
// // ... replace '0' with '1'..'4' to force that many components per pixel
// // ... but 'n' will always be the number that it would have been if you said 0
// stbi_image_free(data)
//
// Standard parameters:
// int *x -- outputs image width in pixels
// int *y -- outputs image height in pixels
// int *comp -- outputs # of image components in image file
// int req_comp -- if non-zero, # of image components requested in result
//
// The return value from an image loader is an 'unsigned char *' which points
// to the pixel data. The pixel data consists of *y scanlines of *x pixels,
// with each pixel consisting of N interleaved 8-bit components; the first
// pixel pointed to is top-left-most in the image. There is no padding between
// image scanlines or between pixels, regardless of format. The number of
// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise.
// If req_comp is non-zero, *comp has the number of components that _would_
// have been output otherwise. E.g. if you set req_comp to 4, you will always
// get RGBA output, but you can check *comp to easily see if it's opaque.
//
// An output image with N components has the following components interleaved
// in this order in each pixel:
//
// N=#comp components
// 1 grey
// 2 grey, alpha
// 3 red, green, blue
// 4 red, green, blue, alpha
//
// If image loading fails for any reason, the return value will be NULL,
// and *x, *y, *comp will be unchanged. The function stbi_failure_reason()
// can be queried for an extremely brief, end-user unfriendly explanation
// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid
// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
// more user-friendly ones.
//
// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
//
// ===========================================================================
//
// iPhone PNG support:
//
// By default we convert iphone-formatted PNGs back to RGB; nominally they
// would silently load as BGR, except the existing code should have just
// failed on such iPhone PNGs. But you can disable this conversion by
// by calling stbi_convert_iphone_png_to_rgb(0), in which case
// you will always just get the native iphone "format" through.
//
// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per
// pixel to remove any premultiplied alpha *only* if the image file explicitly
// says there's premultiplied data (currently only happens in iPhone images,
// and only if iPhone convert-to-rgb processing is on).
//
// ===========================================================================
//
// HDR image support (disable by defining STBI_NO_HDR)
//
// stb_image now supports loading HDR images in general, and currently
// the Radiance .HDR file format, although the support is provided
// generically. You can still load any file through the existing interface;
// if you attempt to load an HDR file, it will be automatically remapped to
// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
// both of these constants can be reconfigured through this interface:
//
// stbi_hdr_to_ldr_gamma(2.2f);
// stbi_hdr_to_ldr_scale(1.0f);
//
// (note, do not use _inverse_ constants; stbi_image will invert them
// appropriately).
//
// Additionally, there is a new, parallel interface for loading files as
// (linear) floats to preserve the full dynamic range:
//
// float *data = stbi_loadf(filename, &x, &y, &n, 0);
//
// If you load LDR images through this interface, those images will
// be promoted to floating point values, run through the inverse of
// constants corresponding to the above:
//
// stbi_ldr_to_hdr_scale(1.0f);
// stbi_ldr_to_hdr_gamma(2.2f);
//
// Finally, given a filename (or an open file or memory block--see header
// file for details) containing image data, you can query for the "most
// appropriate" interface to use (that is, whether the image is HDR or
// not), using:
//
// stbi_is_hdr(char *filename);
//
// ===========================================================================
//
// I/O callbacks
//
// I/O callbacks allow you to read from arbitrary sources, like packaged
// files or some other source. Data read from callbacks are processed
// through a small internal buffer (currently 128 bytes) to try to reduce
// overhead.
//
// The three functions you must define are "read" (reads some bytes of data),
// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end).
#ifndef STBI_NO_STDIO
#if defined(_MSC_VER) && _MSC_VER >= 0x1400
#define _CRT_SECURE_NO_WARNINGS // suppress bogus warnings about fopen()
#endif
#include <stdio.h>
#endif
#define STBI_VERSION 1
enum
{
STBI_default = 0, // only used for req_comp
STBI_grey = 1,
STBI_grey_alpha = 2,
STBI_rgb = 3,
STBI_rgb_alpha = 4
};
typedef unsigned char stbi_uc;
#ifdef __cplusplus
extern "C" {
#endif
//////////////////////////////////////////////////////////////////////////////
//
// PRIMARY API - works on images of any type
//
//
// load image by filename, open file, or memory buffer
//
extern stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
#ifndef STBI_NO_STDIO
extern stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp);
extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
// for stbi_load_from_file, file pointer is left pointing immediately after image
#endif
typedef struct
{
int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read
void (*skip) (void *user,unsigned n); // skip the next 'n' bytes
int (*eof) (void *user); // returns nonzero if we are at end of file/data
} stbi_io_callbacks;
extern stbi_uc *stbi_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp);
#ifndef STBI_NO_HDR
extern float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
#ifndef STBI_NO_STDIO
extern float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp);
extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
#endif
extern float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp);
extern void stbi_hdr_to_ldr_gamma(float gamma);
extern void stbi_hdr_to_ldr_scale(float scale);
extern void stbi_ldr_to_hdr_gamma(float gamma);
extern void stbi_ldr_to_hdr_scale(float scale);
#endif // STBI_NO_HDR
// stbi_is_hdr is always defined
extern int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
#ifndef STBI_NO_STDIO
extern int stbi_is_hdr (char const *filename);
extern int stbi_is_hdr_from_file(FILE *f);
#endif // STBI_NO_STDIO
// get a VERY brief reason for failure
// NOT THREADSAFE
extern const char *stbi_failure_reason (void);
// free the loaded image -- this is just free()
extern void stbi_image_free (void *retval_from_stbi_load);
// get image dimensions & components without fully decoding
extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
extern int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
#ifndef STBI_NO_STDIO
extern int stbi_info (char const *filename, int *x, int *y, int *comp);
extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
#endif
// for image formats that explicitly notate that they have premultiplied alpha,
// we just return the colors as stored in the file. set this flag to force
// unpremultiplication. results are undefined if the unpremultiply overflow.
extern void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply);
// indicate whether we should process iphone images back to canonical format,
// or just pass them through "as-is"
extern void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
// ZLIB client - used by PNG, available for other purposes
extern char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
extern char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
extern int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
extern char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
// define faster low-level operations (typically SIMD support)
#ifdef STBI_SIMD
typedef void (*stbi_idct_8x8)(stbi_uc *out, int out_stride, short data[64], unsigned short *dequantize);
// compute an integer IDCT on "input"
// input[x] = data[x] * dequantize[x]
// write results to 'out': 64 samples, each run of 8 spaced by 'out_stride'
// CLAMP results to 0..255
typedef void (*stbi_YCbCr_to_RGB_run)(stbi_uc *output, stbi_uc const *y, stbi_uc const *cb, stbi_uc const *cr, int count, int step);
// compute a conversion from YCbCr to RGB
// 'count' pixels
// write pixels to 'output'; each pixel is 'step' bytes (either 3 or 4; if 4, write '255' as 4th), order R,G,B
// y: Y input channel
// cb: Cb input channel; scale/biased to be 0..255
// cr: Cr input channel; scale/biased to be 0..255
extern void stbi_install_idct(stbi_idct_8x8 func);
extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func);
#endif // STBI_SIMD
#ifdef __cplusplus
}
#endif
//
//
//// end header file /////////////////////////////////////////////////////
#endif // STBI_INCLUDE_STB_IMAGE_H