add initial examples, replacing the 'Demos/Demos3'. Will make it work cross-platform, OpenGL3/OpenGL2 and add more examples to it.
This commit is contained in:
115
examples/BasicDemo/BasicExample.cpp
Normal file
115
examples/BasicDemo/BasicExample.cpp
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#include "BasicExample.h"
|
||||||
|
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
#define ARRAY_SIZE_Y 5
|
||||||
|
#define ARRAY_SIZE_X 5
|
||||||
|
#define ARRAY_SIZE_Z 5
|
||||||
|
|
||||||
|
#include "LinearMath/btVector3.h"
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/CommonRigidBodyBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct BasicExample : public CommonRigidBodyBase
|
||||||
|
{
|
||||||
|
BasicExample(struct GUIHelperInterface* helper)
|
||||||
|
:CommonRigidBodyBase(helper)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~BasicExample(){}
|
||||||
|
virtual void initPhysics();
|
||||||
|
};
|
||||||
|
|
||||||
|
void BasicExample::initPhysics()
|
||||||
|
{
|
||||||
|
m_guiHelper->setUpAxis(1);
|
||||||
|
|
||||||
|
createEmptyDynamicsWorld();
|
||||||
|
|
||||||
|
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
|
||||||
|
|
||||||
|
if (m_dynamicsWorld->getDebugDrawer())
|
||||||
|
m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints);
|
||||||
|
|
||||||
|
///create a few basic rigid bodies
|
||||||
|
btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
|
||||||
|
m_guiHelper->createCollisionShapeGraphicsObject(groundShape);
|
||||||
|
|
||||||
|
//groundShape->initializePolyhedralFeatures();
|
||||||
|
// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);
|
||||||
|
|
||||||
|
m_collisionShapes.push_back(groundShape);
|
||||||
|
|
||||||
|
btTransform groundTransform;
|
||||||
|
groundTransform.setIdentity();
|
||||||
|
groundTransform.setOrigin(btVector3(0,-50,0));
|
||||||
|
|
||||||
|
{
|
||||||
|
btScalar mass(0.);
|
||||||
|
btRigidBody* body = createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1));
|
||||||
|
m_guiHelper->createRigidBodyGraphicsObject(body, btVector3(0, 1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
//create a few dynamic rigidbodies
|
||||||
|
// Re-using the same collision is better for memory usage and performance
|
||||||
|
|
||||||
|
btBoxShape* colShape = createBoxShape(btVector3(1,1,1));
|
||||||
|
m_guiHelper->createCollisionShapeGraphicsObject(colShape);
|
||||||
|
|
||||||
|
//btCollisionShape* colShape = new btSphereShape(btScalar(1.));
|
||||||
|
m_collisionShapes.push_back(colShape);
|
||||||
|
|
||||||
|
/// Create Dynamic Objects
|
||||||
|
btTransform startTransform;
|
||||||
|
startTransform.setIdentity();
|
||||||
|
|
||||||
|
btScalar mass(1.f);
|
||||||
|
|
||||||
|
//rigidbody is dynamic if and only if mass is non zero, otherwise static
|
||||||
|
bool isDynamic = (mass != 0.f);
|
||||||
|
|
||||||
|
btVector3 localInertia(0,0,0);
|
||||||
|
if (isDynamic)
|
||||||
|
colShape->calculateLocalInertia(mass,localInertia);
|
||||||
|
|
||||||
|
|
||||||
|
for (int k=0;k<ARRAY_SIZE_Y;k++)
|
||||||
|
{
|
||||||
|
for (int i=0;i<ARRAY_SIZE_X;i++)
|
||||||
|
{
|
||||||
|
for(int j = 0;j<ARRAY_SIZE_Z;j++)
|
||||||
|
{
|
||||||
|
startTransform.setOrigin(btVector3(
|
||||||
|
btScalar(2.0*i),
|
||||||
|
btScalar(20+2.0*k),
|
||||||
|
btScalar(2.0*j)));
|
||||||
|
|
||||||
|
|
||||||
|
btRigidBody* body = createRigidBody(mass,startTransform,colShape);
|
||||||
|
m_guiHelper->createRigidBodyGraphicsObject(body, btVector3(1, 1, 0));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ExampleInterface* BasicExampleCreateFunc(PhysicsInterface* pint, GUIHelperInterface* helper, int option)
|
||||||
|
{
|
||||||
|
return new BasicExample(helper);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
7
examples/BasicDemo/BasicExample.h
Normal file
7
examples/BasicDemo/BasicExample.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef BASIC_EXAMPLE_H
|
||||||
|
#define BASIC_EXAMPLE_H
|
||||||
|
|
||||||
|
class ExampleInterface* BasicExampleCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //BASIC_DEMO_PHYSICS_SETUP_H
|
||||||
43
examples/BasicDemo/main.cpp
Normal file
43
examples/BasicDemo/main.cpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2015 Google Inc. 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 "BasicExample.h"
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/ExampleInterface.h"
|
||||||
|
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
struct PhysicsInterface* pint = 0;
|
||||||
|
|
||||||
|
DummyGUIHelper noGfx;
|
||||||
|
|
||||||
|
int option = 0;
|
||||||
|
|
||||||
|
ExampleInterface* example = BasicExampleCreateFunc(pint, &noGfx, option);
|
||||||
|
|
||||||
|
example->initPhysics();
|
||||||
|
example->stepSimulation(1.f/60.f);
|
||||||
|
example->exitPhysics();
|
||||||
|
|
||||||
|
delete example;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
22
examples/BasicDemo/premake4.lua
Normal file
22
examples/BasicDemo/premake4.lua
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
project "App_BasicExample"
|
||||||
|
|
||||||
|
if _OPTIONS["ios"] then
|
||||||
|
kind "WindowedApp"
|
||||||
|
else
|
||||||
|
kind "ConsoleApp"
|
||||||
|
end
|
||||||
|
|
||||||
|
includedirs {"../../src"}
|
||||||
|
|
||||||
|
links {
|
||||||
|
"BulletDynamics","BulletCollision", "LinearMath"
|
||||||
|
}
|
||||||
|
|
||||||
|
language "C++"
|
||||||
|
|
||||||
|
files {
|
||||||
|
"**.cpp",
|
||||||
|
"**.h",
|
||||||
|
}
|
||||||
|
|
||||||
1240
examples/Benchmarks/BenchmarkDemo.cpp
Normal file
1240
examples/Benchmarks/BenchmarkDemo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
23
examples/Benchmarks/BenchmarkDemo.h
Normal file
23
examples/Benchmarks/BenchmarkDemo.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
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 BENCHMARK_EXAMPLE_H
|
||||||
|
#define BENCHMARK_EXAMPLE_H
|
||||||
|
|
||||||
|
struct ExampleInterface* BenchmarkCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //BENCHMARK_EXAMPLE_H
|
||||||
|
|
||||||
49
examples/Benchmarks/TaruData.h
Normal file
49
examples/Benchmarks/TaruData.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#define TaruVtxCount 43
|
||||||
|
#define TaruIdxCount 132
|
||||||
|
|
||||||
|
static float TaruVtx[] = {
|
||||||
|
1.08664f,-1.99237f,0.0f,
|
||||||
|
0.768369f,-1.99237f,-0.768369f,
|
||||||
|
1.28852f,1.34412e-007f,-1.28852f,
|
||||||
|
1.82224f,1.90735e-007f,0.0f,
|
||||||
|
0.0f,-1.99237f,-1.08664f,
|
||||||
|
0.0f,0.0f,-1.82224f,
|
||||||
|
0.0f,-1.99237f,-1.08664f,
|
||||||
|
-0.768369f,-1.99237f,-0.768369f,
|
||||||
|
-1.28852f,1.34412e-007f,-1.28852f,
|
||||||
|
0.0f,0.0f,-1.82224f,
|
||||||
|
-1.08664f,-1.99237f,1.82086e-007f,
|
||||||
|
-1.82224f,1.90735e-007f,1.59305e-007f,
|
||||||
|
-0.768369f,-1.99237f,0.76837f,
|
||||||
|
-1.28852f,2.47058e-007f,1.28852f,
|
||||||
|
1.42495e-007f,-1.99237f,1.08664f,
|
||||||
|
2.38958e-007f,2.70388e-007f,1.82224f,
|
||||||
|
0.768369f,-1.99237f,0.768369f,
|
||||||
|
1.28852f,2.47058e-007f,1.28852f,
|
||||||
|
0.768369f,1.99237f,-0.768369f,
|
||||||
|
1.08664f,1.99237f,0.0f,
|
||||||
|
0.0f,1.99237f,-1.08664f,
|
||||||
|
-0.768369f,1.99237f,-0.768369f,
|
||||||
|
0.0f,1.99237f,-1.08664f,
|
||||||
|
-1.08664f,1.99237f,0.0f,
|
||||||
|
-0.768369f,1.99237f,0.768369f,
|
||||||
|
1.42495e-007f,1.99237f,1.08664f,
|
||||||
|
0.768369f,1.99237f,0.768369f,
|
||||||
|
1.42495e-007f,-1.99237f,1.08664f,
|
||||||
|
-0.768369f,-1.99237f,0.76837f,
|
||||||
|
-1.08664f,-1.99237f,1.82086e-007f,
|
||||||
|
-0.768369f,-1.99237f,-0.768369f,
|
||||||
|
0.0f,-1.99237f,-1.08664f,
|
||||||
|
0.768369f,-1.99237f,-0.768369f,
|
||||||
|
1.08664f,-1.99237f,0.0f,
|
||||||
|
0.768369f,-1.99237f,0.768369f,
|
||||||
|
0.768369f,1.99237f,-0.768369f,
|
||||||
|
0.0f,1.99237f,-1.08664f,
|
||||||
|
-0.768369f,1.99237f,-0.768369f,
|
||||||
|
-1.08664f,1.99237f,0.0f,
|
||||||
|
-0.768369f,1.99237f,0.768369f,
|
||||||
|
1.42495e-007f,1.99237f,1.08664f,
|
||||||
|
0.768369f,1.99237f,0.768369f,
|
||||||
|
1.08664f,1.99237f,0.0f,
|
||||||
|
};
|
||||||
|
|
||||||
84369
examples/Benchmarks/landscapeData.h
Normal file
84369
examples/Benchmarks/landscapeData.h
Normal file
File diff suppressed because it is too large
Load Diff
15
examples/CommonInterfaces/Common2dCanvasInterface.h
Normal file
15
examples/CommonInterfaces/Common2dCanvasInterface.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef COMMON_2D_CANVAS_INTERFACE_H
|
||||||
|
#define COMMON_2D_CANVAS_INTERFACE_H
|
||||||
|
|
||||||
|
struct Common2dCanvasInterface
|
||||||
|
{
|
||||||
|
virtual ~Common2dCanvasInterface() {}
|
||||||
|
virtual int createCanvas(const char* canvasName, int width, int height)=0;
|
||||||
|
virtual void destroyCanvas(int canvasId)=0;
|
||||||
|
virtual void setPixel(int canvasId, int x, int y, unsigned char red, unsigned char green,unsigned char blue, unsigned char alpha)=0;
|
||||||
|
virtual void refreshImageData(int canvasId)=0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //COMMON_2D_CANVAS_INTERFACE_H
|
||||||
|
|
||||||
108
examples/CommonInterfaces/CommonGUIHelperInterface.h
Normal file
108
examples/CommonInterfaces/CommonGUIHelperInterface.h
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
#ifndef GUI_HELPER_INTERFACE_H
|
||||||
|
#define GUI_HELPER_INTERFACE_H
|
||||||
|
|
||||||
|
|
||||||
|
class btRigidBody;
|
||||||
|
class btVector3;
|
||||||
|
class btCollisionObject;
|
||||||
|
class btDiscreteDynamicsWorld;
|
||||||
|
class btCollisionShape;
|
||||||
|
struct Common2dCanvasInterface;
|
||||||
|
struct CommonParameterInterface;
|
||||||
|
struct CommonRenderInterface;
|
||||||
|
struct CommonGraphicsApp;
|
||||||
|
|
||||||
|
///The Bullet 2 GraphicsPhysicsBridge let's the graphics engine create graphics representation and synchronize
|
||||||
|
struct GUIHelperInterface
|
||||||
|
{
|
||||||
|
virtual ~GUIHelperInterface() {}
|
||||||
|
|
||||||
|
virtual void createRigidBodyGraphicsObject(btRigidBody* body,const btVector3& color) = 0;
|
||||||
|
|
||||||
|
virtual void createCollisionObjectGraphicsObject(btCollisionObject* obj,const btVector3& color) = 0;
|
||||||
|
|
||||||
|
virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape)=0;
|
||||||
|
|
||||||
|
virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld)=0;
|
||||||
|
|
||||||
|
virtual void createPhysicsDebugDrawer( btDiscreteDynamicsWorld* rbWorld)=0;
|
||||||
|
|
||||||
|
virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices) =0;
|
||||||
|
|
||||||
|
virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) =0;
|
||||||
|
|
||||||
|
virtual Common2dCanvasInterface* get2dCanvasInterface()=0;
|
||||||
|
|
||||||
|
virtual CommonParameterInterface* getParameterInterface()=0;
|
||||||
|
|
||||||
|
virtual CommonRenderInterface* getRenderInterface()=0;
|
||||||
|
|
||||||
|
virtual CommonGraphicsApp* getAppInterface()=0;
|
||||||
|
|
||||||
|
virtual void setUpAxis(int axis)=0;
|
||||||
|
|
||||||
|
virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld) =0;
|
||||||
|
|
||||||
|
virtual void drawText3D( const char* txt, float posX, float posZY, float posZ, float size)=0;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///the DummyGUIHelper does nothing, so we can test the examples without GUI/graphics (in 'console mode')
|
||||||
|
struct DummyGUIHelper : public GUIHelperInterface
|
||||||
|
{
|
||||||
|
DummyGUIHelper() {}
|
||||||
|
virtual ~DummyGUIHelper() {}
|
||||||
|
|
||||||
|
virtual void createRigidBodyGraphicsObject(btRigidBody* body,const btVector3& color){}
|
||||||
|
|
||||||
|
virtual void createCollisionObjectGraphicsObject(btCollisionObject* obj,const btVector3& color) {}
|
||||||
|
|
||||||
|
virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape){}
|
||||||
|
|
||||||
|
virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld){}
|
||||||
|
|
||||||
|
virtual void createPhysicsDebugDrawer( btDiscreteDynamicsWorld* rbWorld){}
|
||||||
|
|
||||||
|
virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices) { return -1; }
|
||||||
|
|
||||||
|
virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) { return -1;}
|
||||||
|
|
||||||
|
virtual Common2dCanvasInterface* get2dCanvasInterface()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual CommonParameterInterface* getParameterInterface()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual CommonRenderInterface* getRenderInterface()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual CommonGraphicsApp* getAppInterface()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setUpAxis(int axis)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void drawText3D( const char* txt, float posX, float posZY, float posZ, float size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //GUI_HELPER_INTERFACE_H
|
||||||
|
|
||||||
54
examples/CommonInterfaces/CommonGraphicsAppInterface.h
Normal file
54
examples/CommonInterfaces/CommonGraphicsAppInterface.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#ifndef COMMON_GRAPHICS_APP_H
|
||||||
|
#define COMMON_GRAPHICS_APP_H
|
||||||
|
|
||||||
|
struct DrawGridData
|
||||||
|
{
|
||||||
|
int gridSize;
|
||||||
|
float upOffset;
|
||||||
|
int upAxis;
|
||||||
|
float gridColor[4];
|
||||||
|
|
||||||
|
DrawGridData()
|
||||||
|
:gridSize(10),
|
||||||
|
upOffset(0.001f),
|
||||||
|
upAxis(1)
|
||||||
|
{
|
||||||
|
gridColor[0] = 0.6f;
|
||||||
|
gridColor[1] = 0.6f;
|
||||||
|
gridColor[2] = 0.6f;
|
||||||
|
gridColor[3] = 1.f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommonGraphicsApp
|
||||||
|
{
|
||||||
|
CommonGraphicsApp()
|
||||||
|
:m_window(0),
|
||||||
|
m_renderer(0),
|
||||||
|
m_parameterInterface(0),
|
||||||
|
m_2dCanvasInterface(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~CommonGraphicsApp()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
class b3gWindowInterface* m_window;
|
||||||
|
struct CommonRenderInterface* m_renderer;
|
||||||
|
struct CommonParameterInterface* m_parameterInterface;
|
||||||
|
struct Common2dCanvasInterface* m_2dCanvasInterface;
|
||||||
|
|
||||||
|
virtual void drawGrid(DrawGridData data=DrawGridData()) = 0;
|
||||||
|
virtual void setUpAxis(int axis) = 0;
|
||||||
|
virtual int getUpAxis() const = 0;
|
||||||
|
|
||||||
|
virtual void swapBuffer() = 0;
|
||||||
|
virtual void drawText( const char* txt, int posX, int posY) = 0;
|
||||||
|
virtual void drawText3D( const char* txt, float posX, float posZY, float posZ, float size)=0;
|
||||||
|
virtual int registerCubeShape(float halfExtentsX,float halfExtentsY, float halfExtentsZ)=0;
|
||||||
|
virtual int registerGraphicsSphereShape(float radius, bool usePointSprites=true, int largeSphereThreshold=100, int mediumSphereThreshold=10)=0;
|
||||||
|
virtual void registerGrid(int xres, int yres, float color0[4], float color1[4])=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //COMMON_GRAPHICS_APP_H
|
||||||
451
examples/CommonInterfaces/CommonMultiBodyBase.h
Normal file
451
examples/CommonInterfaces/CommonMultiBodyBase.h
Normal file
@@ -0,0 +1,451 @@
|
|||||||
|
|
||||||
|
#ifndef COMMON_MULTI_BODY_SETUP_H
|
||||||
|
#define COMMON_MULTI_BODY_SETUP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
|
||||||
|
#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
|
||||||
|
#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
|
||||||
|
#include "BulletDynamics/Featherstone/btMultiBodyPoint2Point.h"
|
||||||
|
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
|
||||||
|
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
#include "ExampleInterface.h"
|
||||||
|
#include "CommonGUIHelperInterface.h"
|
||||||
|
#include "CommonRenderInterface.h"
|
||||||
|
#include "CommonGraphicsAppInterface.h"
|
||||||
|
#include "CommonWindowInterface.h"
|
||||||
|
|
||||||
|
struct CommonMultiBodyBase : public ExampleInterface
|
||||||
|
{
|
||||||
|
//keep the collision shapes, for deletion/cleanup
|
||||||
|
btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
|
||||||
|
btBroadphaseInterface* m_broadphase;
|
||||||
|
btCollisionDispatcher* m_dispatcher;
|
||||||
|
btMultiBodyConstraintSolver* m_solver;
|
||||||
|
btDefaultCollisionConfiguration* m_collisionConfiguration;
|
||||||
|
btMultiBodyDynamicsWorld* m_dynamicsWorld;
|
||||||
|
|
||||||
|
//data for picking objects
|
||||||
|
class btRigidBody* m_pickedBody;
|
||||||
|
class btTypedConstraint* m_pickedConstraint;
|
||||||
|
class btMultiBodyPoint2Point* m_pickingMultiBodyPoint2Point;
|
||||||
|
|
||||||
|
btVector3 m_oldPickingPos;
|
||||||
|
btVector3 m_hitPos;
|
||||||
|
btScalar m_oldPickingDist;
|
||||||
|
bool m_prevCanSleep;
|
||||||
|
|
||||||
|
struct GUIHelperInterface* m_guiHelper;
|
||||||
|
|
||||||
|
CommonMultiBodyBase(GUIHelperInterface* helper)
|
||||||
|
:m_broadphase(0),
|
||||||
|
m_dispatcher(0),
|
||||||
|
m_solver(0),
|
||||||
|
m_collisionConfiguration(0),
|
||||||
|
m_dynamicsWorld(0),
|
||||||
|
m_pickedBody(0),
|
||||||
|
m_pickedConstraint(0),
|
||||||
|
m_pickingMultiBodyPoint2Point(0),
|
||||||
|
m_prevCanSleep(false),
|
||||||
|
m_guiHelper(helper)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void createEmptyDynamicsWorld()
|
||||||
|
{
|
||||||
|
///collision configuration contains default setup for memory, collision setup
|
||||||
|
m_collisionConfiguration = new btDefaultCollisionConfiguration();
|
||||||
|
//m_collisionConfiguration->setConvexConvexMultipointIterations();
|
||||||
|
|
||||||
|
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
|
||||||
|
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
|
||||||
|
|
||||||
|
m_broadphase = new btDbvtBroadphase();
|
||||||
|
|
||||||
|
m_solver = new btMultiBodyConstraintSolver;
|
||||||
|
|
||||||
|
m_dynamicsWorld = new btMultiBodyDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
|
||||||
|
|
||||||
|
m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void stepSimulation(float deltaTime)
|
||||||
|
{
|
||||||
|
if (m_dynamicsWorld)
|
||||||
|
{
|
||||||
|
m_dynamicsWorld->stepSimulation(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void exitPhysics()
|
||||||
|
{
|
||||||
|
removePickingConstraint();
|
||||||
|
//cleanup in the reverse order of creation/initialization
|
||||||
|
|
||||||
|
//remove the rigidbodies from the dynamics world and delete them
|
||||||
|
|
||||||
|
if (m_dynamicsWorld)
|
||||||
|
{
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = m_dynamicsWorld->getNumConstraints() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
m_dynamicsWorld->removeConstraint(m_dynamicsWorld->getConstraint(i));
|
||||||
|
}
|
||||||
|
for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
|
||||||
|
btRigidBody* body = btRigidBody::upcast(obj);
|
||||||
|
if (body && body->getMotionState())
|
||||||
|
{
|
||||||
|
delete body->getMotionState();
|
||||||
|
}
|
||||||
|
m_dynamicsWorld->removeCollisionObject(obj);
|
||||||
|
delete obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//delete collision shapes
|
||||||
|
for (int j = 0; j<m_collisionShapes.size(); j++)
|
||||||
|
{
|
||||||
|
btCollisionShape* shape = m_collisionShapes[j];
|
||||||
|
delete shape;
|
||||||
|
}
|
||||||
|
m_collisionShapes.clear();
|
||||||
|
|
||||||
|
delete m_dynamicsWorld;
|
||||||
|
|
||||||
|
delete m_solver;
|
||||||
|
|
||||||
|
delete m_broadphase;
|
||||||
|
|
||||||
|
delete m_dispatcher;
|
||||||
|
|
||||||
|
delete m_collisionConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void syncPhysicsToGraphics()
|
||||||
|
{
|
||||||
|
if (m_dynamicsWorld)
|
||||||
|
{
|
||||||
|
m_guiHelper->syncPhysicsToGraphics(m_dynamicsWorld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void renderScene()
|
||||||
|
{
|
||||||
|
m_guiHelper->syncPhysicsToGraphics(m_dynamicsWorld);
|
||||||
|
|
||||||
|
if (m_guiHelper->getRenderInterface())
|
||||||
|
{
|
||||||
|
m_guiHelper->getRenderInterface()->renderScene();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void physicsDebugDraw(int debugDrawFlags)
|
||||||
|
{
|
||||||
|
if (m_dynamicsWorld)
|
||||||
|
{
|
||||||
|
if (m_dynamicsWorld->getDebugDrawer())
|
||||||
|
{
|
||||||
|
m_dynamicsWorld->getDebugDrawer()->setDebugMode(debugDrawFlags);
|
||||||
|
}
|
||||||
|
m_dynamicsWorld->debugDrawWorld();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool keyboardCallback(int key, int state)
|
||||||
|
{
|
||||||
|
return false;//don't handle this key
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 getRayTo(int x,int y)
|
||||||
|
{
|
||||||
|
CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
|
||||||
|
|
||||||
|
if (!renderer)
|
||||||
|
{
|
||||||
|
btAssert(0);
|
||||||
|
return btVector3(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float top = 1.f;
|
||||||
|
float bottom = -1.f;
|
||||||
|
float nearPlane = 1.f;
|
||||||
|
float tanFov = (top-bottom)*0.5f / nearPlane;
|
||||||
|
float fov = btScalar(2.0) * btAtan(tanFov);
|
||||||
|
|
||||||
|
btVector3 camPos,camTarget;
|
||||||
|
renderer->getCameraPosition(camPos);
|
||||||
|
renderer->getCameraTargetPosition(camTarget);
|
||||||
|
|
||||||
|
btVector3 rayFrom = camPos;
|
||||||
|
btVector3 rayForward = (camTarget-camPos);
|
||||||
|
rayForward.normalize();
|
||||||
|
float farPlane = 10000.f;
|
||||||
|
rayForward*= farPlane;
|
||||||
|
|
||||||
|
btVector3 rightOffset;
|
||||||
|
btVector3 cameraUp=btVector3(0,0,0);
|
||||||
|
cameraUp[m_guiHelper->getAppInterface()->getUpAxis()]=1;
|
||||||
|
|
||||||
|
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;
|
||||||
|
float width = float(renderer->getScreenWidth());
|
||||||
|
float height = float (renderer->getScreenHeight());
|
||||||
|
|
||||||
|
aspect = width / height;
|
||||||
|
|
||||||
|
hor*=aspect;
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 rayToCenter = rayFrom + rayForward;
|
||||||
|
btVector3 dHor = hor * 1.f/width;
|
||||||
|
btVector3 dVert = vertical * 1.f/height;
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
|
||||||
|
rayTo += btScalar(x) * dHor;
|
||||||
|
rayTo -= btScalar(y) * dVert;
|
||||||
|
return rayTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool mouseMoveCallback(float x,float y)
|
||||||
|
{
|
||||||
|
CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
|
||||||
|
|
||||||
|
if (!renderer)
|
||||||
|
{
|
||||||
|
btAssert(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
btVector3 rayTo = getRayTo(int(x), int(y));
|
||||||
|
btVector3 rayFrom;
|
||||||
|
renderer->getCameraPosition(rayFrom);
|
||||||
|
movePickedBody(rayFrom,rayTo);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool mouseButtonCallback(int button, int state, float x, float y)
|
||||||
|
{
|
||||||
|
|
||||||
|
CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
|
||||||
|
|
||||||
|
if (!renderer)
|
||||||
|
{
|
||||||
|
btAssert(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
b3gWindowInterface* window = m_guiHelper->getAppInterface()->m_window;
|
||||||
|
|
||||||
|
if (state==1)
|
||||||
|
{
|
||||||
|
if(button==0 && (!window->isModifiedKeyPressed(B3G_ALT) && !window->isModifiedKeyPressed(B3G_CONTROL) ))
|
||||||
|
{
|
||||||
|
btVector3 camPos;
|
||||||
|
renderer->getCameraPosition(camPos);
|
||||||
|
|
||||||
|
btVector3 rayFrom = camPos;
|
||||||
|
btVector3 rayTo = getRayTo(int(x),int(y));
|
||||||
|
|
||||||
|
pickBody(rayFrom, rayTo);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (button==0)
|
||||||
|
{
|
||||||
|
removePickingConstraint();
|
||||||
|
//remove p2p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("button=%d, state=%d\n",button,state);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual bool pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld)
|
||||||
|
{
|
||||||
|
if (m_dynamicsWorld==0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
btCollisionWorld::ClosestRayResultCallback rayCallback(rayFromWorld, rayToWorld);
|
||||||
|
|
||||||
|
m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
|
||||||
|
if (rayCallback.hasHit())
|
||||||
|
{
|
||||||
|
|
||||||
|
btVector3 pickPos = rayCallback.m_hitPointWorld;
|
||||||
|
btRigidBody* body = (btRigidBody*)btRigidBody::upcast(rayCallback.m_collisionObject);
|
||||||
|
if (body)
|
||||||
|
{
|
||||||
|
//other exclusions?
|
||||||
|
if (!(body->isStaticObject() || body->isKinematicObject()))
|
||||||
|
{
|
||||||
|
m_pickedBody = body;
|
||||||
|
m_pickedBody->setActivationState(DISABLE_DEACTIVATION);
|
||||||
|
//printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ());
|
||||||
|
btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos;
|
||||||
|
btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body, localPivot);
|
||||||
|
m_dynamicsWorld->addConstraint(p2p, true);
|
||||||
|
m_pickedConstraint = p2p;
|
||||||
|
btScalar mousePickClamping = 30.f;
|
||||||
|
p2p->m_setting.m_impulseClamp = mousePickClamping;
|
||||||
|
//very weak constraint for picking
|
||||||
|
p2p->m_setting.m_tau = 0.001f;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
btMultiBodyLinkCollider* multiCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(rayCallback.m_collisionObject);
|
||||||
|
if (multiCol && multiCol->m_multiBody)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_prevCanSleep = multiCol->m_multiBody->getCanSleep();
|
||||||
|
multiCol->m_multiBody->setCanSleep(false);
|
||||||
|
|
||||||
|
btVector3 pivotInA = multiCol->m_multiBody->worldPosToLocal(multiCol->m_link, pickPos);
|
||||||
|
|
||||||
|
btMultiBodyPoint2Point* p2p = new btMultiBodyPoint2Point(multiCol->m_multiBody,multiCol->m_link,0,pivotInA,pickPos);
|
||||||
|
//if you add too much energy to the system, causing high angular velocities, simulation 'explodes'
|
||||||
|
//see also http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=4&t=949
|
||||||
|
//so we try to avoid it by clamping the maximum impulse (force) that the mouse pick can apply
|
||||||
|
//it is not satisfying, hopefully we find a better solution (higher order integrator, using joint friction using a zero-velocity target motor with limited force etc?)
|
||||||
|
btScalar scaling=1;
|
||||||
|
p2p->setMaxAppliedImpulse(2*scaling);
|
||||||
|
|
||||||
|
btMultiBodyDynamicsWorld* world = (btMultiBodyDynamicsWorld*) m_dynamicsWorld;
|
||||||
|
world->addMultiBodyConstraint(p2p);
|
||||||
|
m_pickingMultiBodyPoint2Point =p2p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// pickObject(pickPos, rayCallback.m_collisionObject);
|
||||||
|
m_oldPickingPos = rayToWorld;
|
||||||
|
m_hitPos = pickPos;
|
||||||
|
m_oldPickingDist = (pickPos - rayFromWorld).length();
|
||||||
|
// printf("hit !\n");
|
||||||
|
//add p2p
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld)
|
||||||
|
{
|
||||||
|
if (m_pickedBody && m_pickedConstraint)
|
||||||
|
{
|
||||||
|
btPoint2PointConstraint* pickCon = static_cast<btPoint2PointConstraint*>(m_pickedConstraint);
|
||||||
|
if (pickCon)
|
||||||
|
{
|
||||||
|
//keep it at the same picking distance
|
||||||
|
|
||||||
|
btVector3 dir = rayToWorld-rayFromWorld;
|
||||||
|
dir.normalize();
|
||||||
|
dir *= m_oldPickingDist;
|
||||||
|
|
||||||
|
btVector3 newPivotB = rayFromWorld + dir;
|
||||||
|
pickCon->setPivotB(newPivotB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_pickingMultiBodyPoint2Point)
|
||||||
|
{
|
||||||
|
//keep it at the same picking distance
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 dir = rayToWorld-rayFromWorld;
|
||||||
|
dir.normalize();
|
||||||
|
dir *= m_oldPickingDist;
|
||||||
|
|
||||||
|
btVector3 newPivotB = rayFromWorld + dir;
|
||||||
|
|
||||||
|
m_pickingMultiBodyPoint2Point->setPivotInB(newPivotB);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual void removePickingConstraint()
|
||||||
|
{
|
||||||
|
if (m_pickedConstraint)
|
||||||
|
{
|
||||||
|
m_dynamicsWorld->removeConstraint(m_pickedConstraint);
|
||||||
|
delete m_pickedConstraint;
|
||||||
|
m_pickedConstraint = 0;
|
||||||
|
m_pickedBody = 0;
|
||||||
|
}
|
||||||
|
if (m_pickingMultiBodyPoint2Point)
|
||||||
|
{
|
||||||
|
m_pickingMultiBodyPoint2Point->getMultiBodyA()->setCanSleep(m_prevCanSleep);
|
||||||
|
btMultiBodyDynamicsWorld* world = (btMultiBodyDynamicsWorld*) m_dynamicsWorld;
|
||||||
|
world->removeMultiBodyConstraint(m_pickingMultiBodyPoint2Point);
|
||||||
|
delete m_pickingMultiBodyPoint2Point;
|
||||||
|
m_pickingMultiBodyPoint2Point = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
btBoxShape* createBoxShape(const btVector3& halfExtents)
|
||||||
|
{
|
||||||
|
btBoxShape* box = new btBoxShape(halfExtents);
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
btRigidBody* createRigidBody(float mass, const btTransform& startTransform, btCollisionShape* shape, const btVector4& color = btVector4(1, 0, 0, 1))
|
||||||
|
{
|
||||||
|
btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
|
||||||
|
|
||||||
|
//rigidbody is dynamic if and only if mass is non zero, otherwise static
|
||||||
|
bool isDynamic = (mass != 0.f);
|
||||||
|
|
||||||
|
btVector3 localInertia(0, 0, 0);
|
||||||
|
if (isDynamic)
|
||||||
|
shape->calculateLocalInertia(mass, localInertia);
|
||||||
|
|
||||||
|
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
|
||||||
|
|
||||||
|
#define USE_MOTIONSTATE 1
|
||||||
|
#ifdef USE_MOTIONSTATE
|
||||||
|
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
|
||||||
|
|
||||||
|
btRigidBody::btRigidBodyConstructionInfo cInfo(mass, myMotionState, shape, localInertia);
|
||||||
|
|
||||||
|
btRigidBody* body = new btRigidBody(cInfo);
|
||||||
|
//body->setContactProcessingThreshold(m_defaultContactProcessingThreshold);
|
||||||
|
|
||||||
|
#else
|
||||||
|
btRigidBody* body = new btRigidBody(mass, 0, shape, localInertia);
|
||||||
|
body->setWorldTransform(startTransform);
|
||||||
|
#endif//
|
||||||
|
|
||||||
|
body->setUserIndex(-1);
|
||||||
|
m_dynamicsWorld->addRigidBody(body);
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //COMMON_MULTI_BODY_SETUP_H
|
||||||
|
|
||||||
47
examples/CommonInterfaces/CommonParameterInterface.h
Normal file
47
examples/CommonInterfaces/CommonParameterInterface.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
#ifndef PARAM_INTERFACE_H
|
||||||
|
#define PARAM_INTERFACE_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef void (*SliderParamChangedCallback) (float newVal);
|
||||||
|
#include "LinearMath/btScalar.h"
|
||||||
|
|
||||||
|
struct SliderParams
|
||||||
|
{
|
||||||
|
const char* m_name;
|
||||||
|
float m_minVal;
|
||||||
|
float m_maxVal;
|
||||||
|
SliderParamChangedCallback m_callback;
|
||||||
|
btScalar* m_paramValuePointer;
|
||||||
|
void* m_userPointer;
|
||||||
|
bool m_clampToNotches;
|
||||||
|
bool m_showValues;
|
||||||
|
|
||||||
|
SliderParams(const char* name, btScalar* targetValuePointer)
|
||||||
|
:m_name(name),
|
||||||
|
m_minVal(-100),
|
||||||
|
m_maxVal(100),
|
||||||
|
m_callback(0),
|
||||||
|
m_paramValuePointer(targetValuePointer),
|
||||||
|
m_userPointer(0),
|
||||||
|
m_clampToNotches(false),
|
||||||
|
m_showValues(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct CommonParameterInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
virtual ~CommonParameterInterface() {}
|
||||||
|
virtual void registerSliderFloatParameter(SliderParams& params)=0;
|
||||||
|
virtual void syncParameters()=0;
|
||||||
|
virtual void removeAllParameters()=0;
|
||||||
|
virtual void setSliderValue(int sliderIndex, double sliderValue)=0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //PARAM_INTERFACE_H
|
||||||
111
examples/CommonInterfaces/CommonRenderInterface.h
Normal file
111
examples/CommonInterfaces/CommonRenderInterface.h
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
#ifndef COMMON_RENDER_INTERFACE_H
|
||||||
|
#define COMMON_RENDER_INTERFACE_H
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
B3_GL_TRIANGLES = 1,
|
||||||
|
B3_GL_POINTS
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
B3_DEFAULT_RENDERMODE=1,
|
||||||
|
//B3_WIREFRAME_RENDERMODE,
|
||||||
|
B3_CREATE_SHADOWMAP_RENDERMODE,
|
||||||
|
B3_USE_SHADOWMAP_RENDERMODE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommonRenderInterface
|
||||||
|
{
|
||||||
|
virtual void init()=0;
|
||||||
|
virtual void updateCamera(int upAxis)=0;
|
||||||
|
virtual void removeAllInstances() = 0;
|
||||||
|
virtual void setCameraDistance(float dist) = 0;
|
||||||
|
virtual void setCameraPitch(float pitch) = 0;
|
||||||
|
virtual void setCameraTargetPosition(float x, float y, float z)=0;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void getCameraPosition(float cameraPos[4])=0;
|
||||||
|
virtual void getCameraPosition(double cameraPos[4])=0;
|
||||||
|
|
||||||
|
virtual void setCameraTargetPosition(float cameraPos[4])=0;
|
||||||
|
virtual void getCameraTargetPosition(float cameraPos[4]) const=0;
|
||||||
|
virtual void getCameraTargetPosition(double cameraPos[4]) const=0;
|
||||||
|
|
||||||
|
virtual void getCameraViewMatrix(float viewMat[16]) const=0;
|
||||||
|
virtual void getCameraProjectionMatrix(float projMat[16]) const=0;
|
||||||
|
|
||||||
|
virtual void renderScene()=0;
|
||||||
|
|
||||||
|
virtual int getScreenWidth() = 0;
|
||||||
|
virtual int getScreenHeight() = 0;
|
||||||
|
|
||||||
|
virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling)=0;
|
||||||
|
virtual int registerGraphicsInstance(int shapeIndex, const double* position, const double* quaternion, const double* color, const double* scaling)=0;
|
||||||
|
virtual void drawLines(const float* positions, const float color[4], int numPoints, int pointStrideInBytes, const unsigned int* indices, int numIndices, float pointDrawSize)=0;
|
||||||
|
virtual void drawLine(const float from[4], const float to[4], const float color[4], float lineWidth) = 0;
|
||||||
|
virtual void drawLine(const double from[4], const double to[4], const double color[4], double lineWidth) = 0;
|
||||||
|
virtual void drawPoint(const float* position, const float color[4], float pointDrawSize)=0;
|
||||||
|
virtual void drawPoint(const double* position, const double color[4], double pointDrawSize)=0;
|
||||||
|
virtual int registerShape(const float* vertices, int numvertices, const int* indices, int numIndices,int primitiveType=B3_GL_TRIANGLES, int textureIndex=-1)=0;
|
||||||
|
virtual void updateShape(int shapeIndex, const float* vertices)=0;
|
||||||
|
|
||||||
|
virtual void writeSingleInstanceTransformToCPU(const float* position, const float* orientation, int srcIndex)=0;
|
||||||
|
virtual void writeSingleInstanceTransformToCPU(const double* position, const double* orientation, int srcIndex)=0;
|
||||||
|
virtual void writeSingleInstanceColorToCPU(float* color, int srcIndex)=0;
|
||||||
|
virtual void writeSingleInstanceColorToCPU(double* color, int srcIndex)=0;
|
||||||
|
|
||||||
|
virtual void writeTransforms()=0;
|
||||||
|
virtual void enableBlend(bool blend)=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline int projectWorldCoordToScreen(T objx, T objy, T objz,
|
||||||
|
const T modelMatrix[16],
|
||||||
|
const T projMatrix[16],
|
||||||
|
const int viewport[4],
|
||||||
|
T *winx, T *winy, T *winz)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
T in2[4];
|
||||||
|
T tmp[4];
|
||||||
|
|
||||||
|
in2[0]=objx;
|
||||||
|
in2[1]=objy;
|
||||||
|
in2[2]=objz;
|
||||||
|
in2[3]=T(1.0);
|
||||||
|
|
||||||
|
for (i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
tmp[i] = in2[0] * modelMatrix[0*4+i] + in2[1] * modelMatrix[1*4+i] +
|
||||||
|
in2[2] * modelMatrix[2*4+i] + in2[3] * modelMatrix[3*4+i];
|
||||||
|
}
|
||||||
|
|
||||||
|
T out[4];
|
||||||
|
for (i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
out[i] = tmp[0] * projMatrix[0*4+i] + tmp[1] * projMatrix[1*4+i] + tmp[2] * projMatrix[2*4+i] + tmp[3] * projMatrix[3*4+i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out[3] == T(0.0))
|
||||||
|
return 0;
|
||||||
|
out[0] /= out[3];
|
||||||
|
out[1] /= out[3];
|
||||||
|
out[2] /= out[3];
|
||||||
|
/* Map x, y and z to range 0-1 */
|
||||||
|
out[0] = out[0] * T(0.5) + T(0.5);
|
||||||
|
out[1] = out[1] * T(0.5) + T(0.5);
|
||||||
|
out[2] = out[2] * T(0.5) + T(0.5);
|
||||||
|
|
||||||
|
/* Map x,y to viewport */
|
||||||
|
out[0] = out[0] * viewport[2] + viewport[0];
|
||||||
|
out[1] = out[1] * viewport[3] + viewport[1];
|
||||||
|
|
||||||
|
*winx=out[0];
|
||||||
|
*winy=out[1];
|
||||||
|
*winz=out[2];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif//COMMON_RENDER_INTERFACE_H
|
||||||
|
|
||||||
407
examples/CommonInterfaces/CommonRigidBodyBase.h
Normal file
407
examples/CommonInterfaces/CommonRigidBodyBase.h
Normal file
@@ -0,0 +1,407 @@
|
|||||||
|
|
||||||
|
#ifndef COMMON_RIGID_BODY_BASE_H
|
||||||
|
#define COMMON_RIGID_BODY_BASE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
#include "ExampleInterface.h"
|
||||||
|
#include "CommonGUIHelperInterface.h"
|
||||||
|
#include "CommonRenderInterface.h"
|
||||||
|
#include "CommonGraphicsAppInterface.h"
|
||||||
|
#include "CommonWindowInterface.h"
|
||||||
|
|
||||||
|
struct CommonRigidBodyBase : public ExampleInterface
|
||||||
|
{
|
||||||
|
//keep the collision shapes, for deletion/cleanup
|
||||||
|
btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
|
||||||
|
btBroadphaseInterface* m_broadphase;
|
||||||
|
btCollisionDispatcher* m_dispatcher;
|
||||||
|
btConstraintSolver* m_solver;
|
||||||
|
btDefaultCollisionConfiguration* m_collisionConfiguration;
|
||||||
|
btDiscreteDynamicsWorld* m_dynamicsWorld;
|
||||||
|
|
||||||
|
//data for picking objects
|
||||||
|
class btRigidBody* m_pickedBody;
|
||||||
|
class btTypedConstraint* m_pickedConstraint;
|
||||||
|
btVector3 m_oldPickingPos;
|
||||||
|
btVector3 m_hitPos;
|
||||||
|
btScalar m_oldPickingDist;
|
||||||
|
struct GUIHelperInterface* m_guiHelper;
|
||||||
|
|
||||||
|
CommonRigidBodyBase(struct GUIHelperInterface* helper)
|
||||||
|
:m_broadphase(0),
|
||||||
|
m_dispatcher(0),
|
||||||
|
m_solver(0),
|
||||||
|
m_collisionConfiguration(0),
|
||||||
|
m_dynamicsWorld(0),
|
||||||
|
m_pickedBody(0),
|
||||||
|
m_pickedConstraint(0),
|
||||||
|
m_guiHelper(helper)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~CommonRigidBodyBase()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void createEmptyDynamicsWorld()
|
||||||
|
{
|
||||||
|
///collision configuration contains default setup for memory, collision setup
|
||||||
|
m_collisionConfiguration = new btDefaultCollisionConfiguration();
|
||||||
|
//m_collisionConfiguration->setConvexConvexMultipointIterations();
|
||||||
|
|
||||||
|
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
|
||||||
|
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
|
||||||
|
|
||||||
|
m_broadphase = new btDbvtBroadphase();
|
||||||
|
|
||||||
|
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
|
||||||
|
btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
|
||||||
|
m_solver = sol;
|
||||||
|
|
||||||
|
m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
|
||||||
|
|
||||||
|
m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void stepSimulation(float deltaTime)
|
||||||
|
{
|
||||||
|
if (m_dynamicsWorld)
|
||||||
|
{
|
||||||
|
m_dynamicsWorld->stepSimulation(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void physicsDebugDraw(int debugFlags)
|
||||||
|
{
|
||||||
|
if (m_dynamicsWorld && m_dynamicsWorld->getDebugDrawer())
|
||||||
|
{
|
||||||
|
m_dynamicsWorld->getDebugDrawer()->setDebugMode(debugFlags);
|
||||||
|
m_dynamicsWorld->debugDrawWorld();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void exitPhysics()
|
||||||
|
{
|
||||||
|
removePickingConstraint();
|
||||||
|
//cleanup in the reverse order of creation/initialization
|
||||||
|
|
||||||
|
//remove the rigidbodies from the dynamics world and delete them
|
||||||
|
|
||||||
|
if (m_dynamicsWorld)
|
||||||
|
{
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = m_dynamicsWorld->getNumConstraints() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
m_dynamicsWorld->removeConstraint(m_dynamicsWorld->getConstraint(i));
|
||||||
|
}
|
||||||
|
for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
|
||||||
|
btRigidBody* body = btRigidBody::upcast(obj);
|
||||||
|
if (body && body->getMotionState())
|
||||||
|
{
|
||||||
|
delete body->getMotionState();
|
||||||
|
}
|
||||||
|
m_dynamicsWorld->removeCollisionObject(obj);
|
||||||
|
delete obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//delete collision shapes
|
||||||
|
for (int j = 0; j<m_collisionShapes.size(); j++)
|
||||||
|
{
|
||||||
|
btCollisionShape* shape = m_collisionShapes[j];
|
||||||
|
delete shape;
|
||||||
|
}
|
||||||
|
m_collisionShapes.clear();
|
||||||
|
|
||||||
|
delete m_dynamicsWorld;
|
||||||
|
m_dynamicsWorld=0;
|
||||||
|
|
||||||
|
delete m_solver;
|
||||||
|
m_solver=0;
|
||||||
|
|
||||||
|
delete m_broadphase;
|
||||||
|
m_broadphase=0;
|
||||||
|
|
||||||
|
delete m_dispatcher;
|
||||||
|
m_dispatcher=0;
|
||||||
|
|
||||||
|
delete m_collisionConfiguration;
|
||||||
|
m_collisionConfiguration=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void debugDraw(int debugDrawFlags)
|
||||||
|
{
|
||||||
|
if (m_dynamicsWorld)
|
||||||
|
{
|
||||||
|
if (m_dynamicsWorld->getDebugDrawer())
|
||||||
|
{
|
||||||
|
m_dynamicsWorld->getDebugDrawer()->setDebugMode(debugDrawFlags);
|
||||||
|
}
|
||||||
|
m_dynamicsWorld->debugDrawWorld();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool keyboardCallback(int key, int state)
|
||||||
|
{
|
||||||
|
return false;//don't handle this key
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 getRayTo(int x,int y)
|
||||||
|
{
|
||||||
|
CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
|
||||||
|
|
||||||
|
if (!renderer)
|
||||||
|
{
|
||||||
|
btAssert(0);
|
||||||
|
return btVector3(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float top = 1.f;
|
||||||
|
float bottom = -1.f;
|
||||||
|
float nearPlane = 1.f;
|
||||||
|
float tanFov = (top-bottom)*0.5f / nearPlane;
|
||||||
|
float fov = btScalar(2.0) * btAtan(tanFov);
|
||||||
|
|
||||||
|
btVector3 camPos,camTarget;
|
||||||
|
renderer->getCameraPosition(camPos);
|
||||||
|
renderer->getCameraTargetPosition(camTarget);
|
||||||
|
|
||||||
|
btVector3 rayFrom = camPos;
|
||||||
|
btVector3 rayForward = (camTarget-camPos);
|
||||||
|
rayForward.normalize();
|
||||||
|
float farPlane = 10000.f;
|
||||||
|
rayForward*= farPlane;
|
||||||
|
|
||||||
|
btVector3 rightOffset;
|
||||||
|
btVector3 cameraUp=btVector3(0,0,0);
|
||||||
|
cameraUp[m_guiHelper->getAppInterface()->getUpAxis()]=1;
|
||||||
|
|
||||||
|
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;
|
||||||
|
float width = float(renderer->getScreenWidth());
|
||||||
|
float height = float (renderer->getScreenHeight());
|
||||||
|
|
||||||
|
aspect = width / height;
|
||||||
|
|
||||||
|
hor*=aspect;
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 rayToCenter = rayFrom + rayForward;
|
||||||
|
btVector3 dHor = hor * 1.f/width;
|
||||||
|
btVector3 dVert = vertical * 1.f/height;
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
|
||||||
|
rayTo += btScalar(x) * dHor;
|
||||||
|
rayTo -= btScalar(y) * dVert;
|
||||||
|
return rayTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool mouseMoveCallback(float x,float y)
|
||||||
|
{
|
||||||
|
CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
|
||||||
|
|
||||||
|
if (!renderer)
|
||||||
|
{
|
||||||
|
btAssert(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
btVector3 rayTo = getRayTo(int(x), int(y));
|
||||||
|
btVector3 rayFrom;
|
||||||
|
renderer->getCameraPosition(rayFrom);
|
||||||
|
movePickedBody(rayFrom,rayTo);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool mouseButtonCallback(int button, int state, float x, float y)
|
||||||
|
{
|
||||||
|
|
||||||
|
CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
|
||||||
|
|
||||||
|
if (!renderer)
|
||||||
|
{
|
||||||
|
btAssert(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
b3gWindowInterface* window = m_guiHelper->getAppInterface()->m_window;
|
||||||
|
|
||||||
|
if (state==1)
|
||||||
|
{
|
||||||
|
if(button==0 && (!window->isModifiedKeyPressed(B3G_ALT) && !window->isModifiedKeyPressed(B3G_CONTROL) ))
|
||||||
|
{
|
||||||
|
btVector3 camPos;
|
||||||
|
renderer->getCameraPosition(camPos);
|
||||||
|
|
||||||
|
btVector3 rayFrom = camPos;
|
||||||
|
btVector3 rayTo = getRayTo(int(x),int(y));
|
||||||
|
|
||||||
|
pickBody(rayFrom, rayTo);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (button==0)
|
||||||
|
{
|
||||||
|
removePickingConstraint();
|
||||||
|
//remove p2p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("button=%d, state=%d\n",button,state);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual bool pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld)
|
||||||
|
{
|
||||||
|
if (m_dynamicsWorld==0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
btCollisionWorld::ClosestRayResultCallback rayCallback(rayFromWorld, rayToWorld);
|
||||||
|
|
||||||
|
m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
|
||||||
|
if (rayCallback.hasHit())
|
||||||
|
{
|
||||||
|
|
||||||
|
btVector3 pickPos = rayCallback.m_hitPointWorld;
|
||||||
|
btRigidBody* body = (btRigidBody*)btRigidBody::upcast(rayCallback.m_collisionObject);
|
||||||
|
if (body)
|
||||||
|
{
|
||||||
|
//other exclusions?
|
||||||
|
if (!(body->isStaticObject() || body->isKinematicObject()))
|
||||||
|
{
|
||||||
|
m_pickedBody = body;
|
||||||
|
m_pickedBody->setActivationState(DISABLE_DEACTIVATION);
|
||||||
|
//printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ());
|
||||||
|
btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos;
|
||||||
|
btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body, localPivot);
|
||||||
|
m_dynamicsWorld->addConstraint(p2p, true);
|
||||||
|
m_pickedConstraint = p2p;
|
||||||
|
btScalar mousePickClamping = 30.f;
|
||||||
|
p2p->m_setting.m_impulseClamp = mousePickClamping;
|
||||||
|
//very weak constraint for picking
|
||||||
|
p2p->m_setting.m_tau = 0.001f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// pickObject(pickPos, rayCallback.m_collisionObject);
|
||||||
|
m_oldPickingPos = rayToWorld;
|
||||||
|
m_hitPos = pickPos;
|
||||||
|
m_oldPickingDist = (pickPos - rayFromWorld).length();
|
||||||
|
// printf("hit !\n");
|
||||||
|
//add p2p
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld)
|
||||||
|
{
|
||||||
|
if (m_pickedBody && m_pickedConstraint)
|
||||||
|
{
|
||||||
|
btPoint2PointConstraint* pickCon = static_cast<btPoint2PointConstraint*>(m_pickedConstraint);
|
||||||
|
if (pickCon)
|
||||||
|
{
|
||||||
|
//keep it at the same picking distance
|
||||||
|
|
||||||
|
btVector3 newPivotB;
|
||||||
|
|
||||||
|
btVector3 dir = rayToWorld - rayFromWorld;
|
||||||
|
dir.normalize();
|
||||||
|
dir *= m_oldPickingDist;
|
||||||
|
|
||||||
|
newPivotB = rayFromWorld + dir;
|
||||||
|
pickCon->setPivotB(newPivotB);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual void removePickingConstraint()
|
||||||
|
{
|
||||||
|
if (m_pickedConstraint)
|
||||||
|
{
|
||||||
|
m_dynamicsWorld->removeConstraint(m_pickedConstraint);
|
||||||
|
delete m_pickedConstraint;
|
||||||
|
m_pickedConstraint = 0;
|
||||||
|
m_pickedBody = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
btBoxShape* createBoxShape(const btVector3& halfExtents)
|
||||||
|
{
|
||||||
|
btBoxShape* box = new btBoxShape(halfExtents);
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
btRigidBody* createRigidBody(float mass, const btTransform& startTransform, btCollisionShape* shape, const btVector4& color = btVector4(1, 0, 0, 1))
|
||||||
|
{
|
||||||
|
btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
|
||||||
|
|
||||||
|
//rigidbody is dynamic if and only if mass is non zero, otherwise static
|
||||||
|
bool isDynamic = (mass != 0.f);
|
||||||
|
|
||||||
|
btVector3 localInertia(0, 0, 0);
|
||||||
|
if (isDynamic)
|
||||||
|
shape->calculateLocalInertia(mass, localInertia);
|
||||||
|
|
||||||
|
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
|
||||||
|
|
||||||
|
#define USE_MOTIONSTATE 1
|
||||||
|
#ifdef USE_MOTIONSTATE
|
||||||
|
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
|
||||||
|
|
||||||
|
btRigidBody::btRigidBodyConstructionInfo cInfo(mass, myMotionState, shape, localInertia);
|
||||||
|
|
||||||
|
btRigidBody* body = new btRigidBody(cInfo);
|
||||||
|
//body->setContactProcessingThreshold(m_defaultContactProcessingThreshold);
|
||||||
|
|
||||||
|
#else
|
||||||
|
btRigidBody* body = new btRigidBody(mass, 0, shape, localInertia);
|
||||||
|
body->setWorldTransform(startTransform);
|
||||||
|
#endif//
|
||||||
|
|
||||||
|
body->setUserIndex(-1);
|
||||||
|
m_dynamicsWorld->addRigidBody(body);
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
virtual void renderScene()
|
||||||
|
{
|
||||||
|
m_guiHelper->syncPhysicsToGraphics(m_dynamicsWorld);
|
||||||
|
|
||||||
|
if (m_guiHelper->getRenderInterface())
|
||||||
|
{
|
||||||
|
m_guiHelper->getRenderInterface()->renderScene();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //COMMON_RIGID_BODY_SETUP_H
|
||||||
|
|
||||||
126
examples/CommonInterfaces/CommonWindowInterface.h
Normal file
126
examples/CommonInterfaces/CommonWindowInterface.h
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#ifndef B3G_WINDOW_INTERFACE_H
|
||||||
|
#define B3G_WINDOW_INTERFACE_H
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (*b3WheelCallback)(float deltax, float deltay);
|
||||||
|
typedef void (*b3ResizeCallback)( float width, float height);
|
||||||
|
typedef void (*b3MouseMoveCallback)( float x, float y);
|
||||||
|
typedef void (*b3MouseButtonCallback)(int button, int state, float x, float y);
|
||||||
|
typedef void (*b3KeyboardCallback)(int keycode, int state);
|
||||||
|
typedef void (*b3RenderCallback) ();
|
||||||
|
|
||||||
|
enum {
|
||||||
|
B3G_ESCAPE = 27,
|
||||||
|
B3G_F1 = 0xff00,
|
||||||
|
B3G_F2,
|
||||||
|
B3G_F3,
|
||||||
|
B3G_F4,
|
||||||
|
B3G_F5,
|
||||||
|
B3G_F6,
|
||||||
|
B3G_F7,
|
||||||
|
B3G_F8,
|
||||||
|
B3G_F9,
|
||||||
|
B3G_F10,
|
||||||
|
B3G_F11,
|
||||||
|
B3G_F12,
|
||||||
|
B3G_F13,
|
||||||
|
B3G_F14,
|
||||||
|
B3G_F15,
|
||||||
|
B3G_LEFT_ARROW,
|
||||||
|
B3G_RIGHT_ARROW,
|
||||||
|
B3G_UP_ARROW,
|
||||||
|
B3G_DOWN_ARROW,
|
||||||
|
B3G_PAGE_UP,
|
||||||
|
B3G_PAGE_DOWN,
|
||||||
|
B3G_END,
|
||||||
|
B3G_HOME,
|
||||||
|
B3G_INSERT,
|
||||||
|
B3G_DELETE,
|
||||||
|
B3G_BACKSPACE,
|
||||||
|
B3G_SHIFT,
|
||||||
|
B3G_CONTROL,
|
||||||
|
B3G_ALT,
|
||||||
|
B3G_RETURN
|
||||||
|
};
|
||||||
|
|
||||||
|
struct b3gWindowConstructionInfo
|
||||||
|
{
|
||||||
|
int m_width;
|
||||||
|
int m_height;
|
||||||
|
bool m_fullscreen;
|
||||||
|
int m_colorBitsPerPixel;
|
||||||
|
void* m_windowHandle;
|
||||||
|
const char* m_title;
|
||||||
|
int m_openglVersion;
|
||||||
|
|
||||||
|
|
||||||
|
b3gWindowConstructionInfo(int width=1024, int height=768)
|
||||||
|
:m_width(width),
|
||||||
|
m_height(height),
|
||||||
|
m_fullscreen(false),
|
||||||
|
m_colorBitsPerPixel(32),
|
||||||
|
m_windowHandle(0),
|
||||||
|
m_title("title"),
|
||||||
|
m_openglVersion(3)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class b3gWindowInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~b3gWindowInterface()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void createDefaultWindow(int width, int height, const char* title)
|
||||||
|
{
|
||||||
|
b3gWindowConstructionInfo ci(width,height);
|
||||||
|
ci.m_title = title;
|
||||||
|
createWindow(ci);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void createWindow(const b3gWindowConstructionInfo& ci)=0;
|
||||||
|
|
||||||
|
virtual void closeWindow()=0;
|
||||||
|
|
||||||
|
virtual void runMainLoop()=0;
|
||||||
|
virtual float getTimeInSeconds()=0;
|
||||||
|
|
||||||
|
virtual bool requestedExit() const = 0;
|
||||||
|
virtual void setRequestExit() = 0;
|
||||||
|
|
||||||
|
virtual void startRendering()=0;
|
||||||
|
|
||||||
|
virtual void endRendering()=0;
|
||||||
|
|
||||||
|
virtual bool isModifiedKeyPressed(int key) = 0;
|
||||||
|
|
||||||
|
virtual void setMouseMoveCallback(b3MouseMoveCallback mouseCallback)=0;
|
||||||
|
virtual b3MouseMoveCallback getMouseMoveCallback()=0;
|
||||||
|
|
||||||
|
virtual void setMouseButtonCallback(b3MouseButtonCallback mouseCallback)=0;
|
||||||
|
virtual b3MouseButtonCallback getMouseButtonCallback()=0;
|
||||||
|
|
||||||
|
virtual void setResizeCallback(b3ResizeCallback resizeCallback)=0;
|
||||||
|
virtual b3ResizeCallback getResizeCallback()=0;
|
||||||
|
|
||||||
|
virtual void setWheelCallback(b3WheelCallback wheelCallback)=0;
|
||||||
|
virtual b3WheelCallback getWheelCallback()=0;
|
||||||
|
|
||||||
|
virtual void setKeyboardCallback( b3KeyboardCallback keyboardCallback)=0;
|
||||||
|
virtual b3KeyboardCallback getKeyboardCallback()=0;
|
||||||
|
|
||||||
|
virtual void setRenderCallback( b3RenderCallback renderCallback) = 0;
|
||||||
|
|
||||||
|
virtual void setWindowTitle(const char* title)=0;
|
||||||
|
|
||||||
|
virtual float getRetinaScale() const =0;
|
||||||
|
|
||||||
|
virtual int fileOpenDialog(char* fileName, int maxFileNameLength) = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //B3G_WINDOW_INTERFACE_H
|
||||||
28
examples/CommonInterfaces/ExampleInterface.h
Normal file
28
examples/CommonInterfaces/ExampleInterface.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef EXAMPLE_INTERFACE_H
|
||||||
|
#define EXAMPLE_INTERFACE_H
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef class ExampleInterface* (CreateFunc)(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option);
|
||||||
|
|
||||||
|
virtual ~ExampleInterface()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void initPhysics()=0;
|
||||||
|
virtual void exitPhysics()=0;
|
||||||
|
virtual void stepSimulation(float deltaTime)=0;
|
||||||
|
virtual void renderScene()=0;
|
||||||
|
virtual void physicsDebugDraw(int debugFlags)=0;//for now we reuse the flags in Bullet/src/LinearMath/btIDebugDraw.h
|
||||||
|
virtual bool mouseMoveCallback(float x,float y)=0;
|
||||||
|
virtual bool mouseButtonCallback(int button, int state, float x, float y)=0;
|
||||||
|
virtual bool keyboardCallback(int key, int state)=0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //EXAMPLE_INTERFACE_H
|
||||||
131
examples/ExampleBrowser/CMakeLists.txt
Normal file
131
examples/ExampleBrowser/CMakeLists.txt
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(
|
||||||
|
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||||
|
${BULLET_PHYSICS_SOURCE_DIR}/btgui
|
||||||
|
${BULLET_PHYSICS_SOURCE_DIR}/btgui/lua-5.2.3/src
|
||||||
|
${BULLET_PHYSICS_SOURCE_DIR}/Demos3/FiniteElementMethod
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(App_AllBullet2Demos_SRCS
|
||||||
|
main.cpp
|
||||||
|
BulletDemoEntries.h
|
||||||
|
../../Demos/BasicDemo/BasicDemoPhysicsSetup.cpp
|
||||||
|
../../Demos/BasicDemo/BasicDemoPhysicsSetup.h
|
||||||
|
../../Demos/CcdPhysicsDemo/CcdPhysicsSetup.cpp
|
||||||
|
../../Demos/CcdPhysicsDemo/CcdPhysicsSetup.h
|
||||||
|
../../Demos/Raytracer/RaytracerSetup.cpp
|
||||||
|
../../Demos/Raytracer/RaytracerSetup.h
|
||||||
|
../../Demos/GyroscopicDemo/GyroscopicSetup.cpp
|
||||||
|
../../Demos/GyroscopicDemo/GyroscopicSetup.h
|
||||||
|
../../Demos/ForkLiftDemo/ForkLiftPhysicsSetup.cpp
|
||||||
|
../../Demos/ForkLiftDemo/ForkLiftPhysicsSetup.h
|
||||||
|
../../Demos/SerializeDemo/SerializeSetup.cpp
|
||||||
|
../../Extras/Serialize/BulletFileLoader/bChunk.cpp
|
||||||
|
../../Extras/Serialize/BulletFileLoader/bDNA.cpp
|
||||||
|
../../Extras/Serialize/BulletFileLoader/bFile.cpp
|
||||||
|
../../Extras/Serialize/BulletFileLoader/btBulletFile.cpp
|
||||||
|
../../Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.cpp
|
||||||
|
../../Extras/Serialize/BulletWorldImporter/btWorldImporter.cpp
|
||||||
|
../bullet2/MultiBodyDemo/TestJointTorqueSetup.cpp
|
||||||
|
../bullet2/MultiBodyDemo/MultiBodyVehicle.cpp
|
||||||
|
../bullet2/ConstraintDemo/ConstraintPhysicsSetup.cpp
|
||||||
|
../bullet2/ConstraintDemo/ConstraintPhysicsSetup.h
|
||||||
|
../bullet2/ConstraintDemo/Dof6Spring2Setup.cpp
|
||||||
|
../bullet2/ConstraintDemo/Dof6Spring2Setup.h
|
||||||
|
../bullet2/CoordinateFrameDemo/CoordinateFrameDemoPhysicsSetup.cpp
|
||||||
|
../bullet2/CoordinateFrameDemo/CoordinateFrameDemoPhysicsSetup.h
|
||||||
|
../bullet2/FeatherstoneMultiBodyDemo/BulletMultiBodyDemos.cpp
|
||||||
|
../bullet2/FeatherstoneMultiBodyDemo/BulletMultiBodyDemos.h
|
||||||
|
../bullet2/FeatherstoneMultiBodyDemo/MultiDofDemo.cpp
|
||||||
|
../bullet2/FeatherstoneMultiBodyDemo/MultiDofDemo.h
|
||||||
|
../bullet2/BasicDemo/BasicDemo.cpp
|
||||||
|
../bullet2/BasicDemo/BasicDemo.h
|
||||||
|
# ../bullet2/SoftDemo/SoftDemo.cpp
|
||||||
|
# the next few demos are not converted to 'newer' structure yet
|
||||||
|
# target is to convert all Bullet 2 demos in new structure but need to settle down on features
|
||||||
|
# ../bullet2/BasicDemo/HingeDemo.cpp
|
||||||
|
# ../bullet2/BasicDemo/HingeDemo.h
|
||||||
|
# ../bullet2/ChainDemo/ChainDemo.cpp
|
||||||
|
# ../bullet2/ChainDemo/ChainDemo.h
|
||||||
|
# ../bullet2/RagdollDemo/RagdollDemo.cpp
|
||||||
|
# ../bullet2/RagdollDemo/RagdollDemo.h
|
||||||
|
../bullet2/LuaDemo/LuaPhysicsSetup.cpp
|
||||||
|
../bullet2/LuaDemo/LuaPhysicsSetup.h
|
||||||
|
../ImportURDFDemo/URDF2Bullet.cpp
|
||||||
|
../ImportURDFDemo/ImportURDFSetup.cpp
|
||||||
|
../ImportURDFDemo/ImportURDFSetup.h
|
||||||
|
../ImportObjDemo/ImportObjSetup.cpp
|
||||||
|
../ImportObjDemo/LoadMeshFromObj.cpp
|
||||||
|
../ImportObjDemo/LoadMeshFromObj.h
|
||||||
|
../ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp
|
||||||
|
../ImportColladaDemo/ImportColladaSetup.cpp
|
||||||
|
../ImportColladaDemo/LoadMeshFromCollada.cpp
|
||||||
|
../ImportSTLDemo/ImportSTLSetup.cpp
|
||||||
|
../Wavefront/tiny_obj_loader.cpp
|
||||||
|
../Wavefront/tiny_obj_loader.h
|
||||||
|
../FiniteElementMethod/FiniteElementDemo.cpp
|
||||||
|
../../btgui/Bullet3AppSupport/b3Clock.cpp
|
||||||
|
../../btgui/Bullet3AppSupport/b3Clock.h
|
||||||
|
../../btgui/urdf/urdfdom/urdf_parser/src/pose.cpp
|
||||||
|
../../btgui/urdf/urdfdom/urdf_parser/src/model.cpp
|
||||||
|
../../btgui/urdf/urdfdom/urdf_parser/src/link.cpp
|
||||||
|
../../btgui/urdf/urdfdom/urdf_parser/src/joint.cpp
|
||||||
|
../../btgui/urdf/urdfdom/urdf_parser/include/urdf_parser/urdf_parser.h
|
||||||
|
../../btgui/urdf/urdfdom_headers/urdf_exception/include/urdf_exception/exception.h
|
||||||
|
../../btgui/urdf/urdfdom_headers/urdf_model/include/urdf_model/pose.h
|
||||||
|
../../btgui/urdf/urdfdom_headers/urdf_model/include/urdf_model/model.h
|
||||||
|
../../btgui/urdf/urdfdom_headers/urdf_model/include/urdf_model/link.h
|
||||||
|
../../btgui/urdf/urdfdom_headers/urdf_model/include/urdf_model/joint.h
|
||||||
|
../../btgui/tinyxml/tinystr.cpp
|
||||||
|
../../btgui/tinyxml/tinyxml.cpp
|
||||||
|
../../btgui/tinyxml/tinyxmlerror.cpp
|
||||||
|
../../btgui/tinyxml/tinyxmlparser.cpp
|
||||||
|
../../btgui/urdf/boost_replacement/lexical_cast.h
|
||||||
|
../../btgui/urdf/boost_replacement/shared_ptr.h
|
||||||
|
../../btgui/urdf/boost_replacement/printf_console.cpp
|
||||||
|
../../btgui/urdf/boost_replacement/printf_console.h
|
||||||
|
../../btgui/urdf/boost_replacement/string_split.cpp
|
||||||
|
../../btgui/urdf/boost_replacement/string_split.h
|
||||||
|
${BULLET_PHYSICS_SOURCE_DIR}/build3/bullet.rc
|
||||||
|
)
|
||||||
|
|
||||||
|
LINK_LIBRARIES(
|
||||||
|
Bullet3AppSupport lua-5.2.3 Bullet3Common BulletSoftBody BulletDynamics BulletCollision LinearMath OpenGLWindow gwen ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}
|
||||||
|
)
|
||||||
|
|
||||||
|
IF (WIN32)
|
||||||
|
SET(App_AllBullet2Demos_SRCS ${App_AllBullet2Demos_SRCS} ${App_AllBullet2Demos_Common_SRCS})
|
||||||
|
INCLUDE_DIRECTORIES(
|
||||||
|
${BULLET_PHYSICS_SOURCE_DIR}/btgui/OpenGLWindow/GlewWindows
|
||||||
|
)
|
||||||
|
ADD_DEFINITIONS(-DGLEW_STATIC)
|
||||||
|
ELSE(WIN32)
|
||||||
|
IF(APPLE)
|
||||||
|
find_library(COCOA NAMES Cocoa)
|
||||||
|
MESSAGE(${COCOA})
|
||||||
|
link_libraries(${COCOA})
|
||||||
|
ELSE(APPLE)
|
||||||
|
ADD_DEFINITIONS("-DGLEW_INIT_OPENGL11_FUNCTIONS=1")
|
||||||
|
ADD_DEFINITIONS("-DGLEW_STATIC")
|
||||||
|
ADD_DEFINITIONS("-DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1")
|
||||||
|
INCLUDE_DIRECTORIES(
|
||||||
|
${BULLET_PHYSICS_SOURCE_DIR}/btgui/OpenGLWindow/GlewWindows
|
||||||
|
)
|
||||||
|
LINK_LIBRARIES( pthread dl)
|
||||||
|
ENDIF(APPLE)
|
||||||
|
ENDIF(WIN32)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(App_AllBullet2Demos
|
||||||
|
${App_AllBullet2Demos_SRCS}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
|
||||||
|
SET_TARGET_PROPERTIES(App_AllBullet2Demos PROPERTIES DEBUG_POSTFIX "_Debug")
|
||||||
|
SET_TARGET_PROPERTIES(App_AllBullet2Demos PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel")
|
||||||
|
SET_TARGET_PROPERTIES(App_AllBullet2Demos PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo")
|
||||||
|
ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
|
||||||
38
examples/ExampleBrowser/EmptyBrowser.h
Normal file
38
examples/ExampleBrowser/EmptyBrowser.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef EMPTY_BROWSER
|
||||||
|
#define EMPTY_BROWSER
|
||||||
|
|
||||||
|
#include "ExampleBrowserInterface.h"
|
||||||
|
#include "EmptyExample.h"
|
||||||
|
|
||||||
|
class EmptyBrowser : public ExampleBrowserInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
EmptyExample m_emptyExample;
|
||||||
|
|
||||||
|
virtual ExampleInterface* getCurrentExample()
|
||||||
|
{
|
||||||
|
return &m_emptyExample;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmptyBrowser(class ExampleEntries* examples)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool init(int /*argc*/, char* argv[])
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void update(float deltaTime)
|
||||||
|
{
|
||||||
|
m_emptyExample.stepSimulation(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool requestedExit()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EMPTY_BROWSER
|
||||||
32
examples/ExampleBrowser/EmptyExample.h
Normal file
32
examples/ExampleBrowser/EmptyExample.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef EMPTY_EXAMPLE_H
|
||||||
|
#define EMPTY_EXAMPLE_H
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/ExampleInterface.h"
|
||||||
|
|
||||||
|
class EmptyExample : public ExampleInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
EmptyExample() {}
|
||||||
|
virtual ~EmptyExample(){}
|
||||||
|
|
||||||
|
static ExampleInterface* CreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option)
|
||||||
|
{
|
||||||
|
return new EmptyExample;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void initPhysics(){}
|
||||||
|
virtual void exitPhysics(){}
|
||||||
|
virtual void stepSimulation(float deltaTime){}
|
||||||
|
virtual void renderScene(){}
|
||||||
|
virtual void physicsDebugDraw(int debugFlags){}
|
||||||
|
virtual bool mouseMoveCallback(float x,float y){ return false;}
|
||||||
|
virtual bool mouseButtonCallback(int button, int state, float x, float y){return false;}
|
||||||
|
virtual bool keyboardCallback(int key, int state){return false;}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //EMPTY_EXAMPLE_H
|
||||||
|
|
||||||
23
examples/ExampleBrowser/ExampleBrowserInterface.h
Normal file
23
examples/ExampleBrowser/ExampleBrowserInterface.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef EXAMPLE_BROWSER_GUI_H
|
||||||
|
#define EXAMPLE_BROWSER_GUI_H
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/ExampleInterface.h"
|
||||||
|
|
||||||
|
class ExampleBrowserInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~ExampleBrowserInterface() {}
|
||||||
|
|
||||||
|
virtual ExampleInterface* getCurrentExample() = 0;
|
||||||
|
|
||||||
|
virtual bool init(int argc, char* argv[])=0;
|
||||||
|
|
||||||
|
virtual void update(float deltaTime)=0;
|
||||||
|
|
||||||
|
virtual bool requestedExit()=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //EXAMPLE_BROWSER_GUI_H
|
||||||
136
examples/ExampleBrowser/ExampleEntries.cpp
Normal file
136
examples/ExampleBrowser/ExampleEntries.cpp
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#include "ExampleEntries.h"
|
||||||
|
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
#include "EmptyExample.h"
|
||||||
|
#include "../RenderingExamples/RenderInstancingDemo.h"
|
||||||
|
#include "../RenderingExamples/CoordinateSystemDemo.h"
|
||||||
|
#include "../RenderingExamples/RaytracerSetup.h"
|
||||||
|
#include "../ForkLift/ForkLiftDemo.h"
|
||||||
|
#include "../BasicDemo/BasicExample.h"
|
||||||
|
#include "../Planar2D/Planar2D.h"
|
||||||
|
#include "../Benchmarks/BenchmarkDemo.h"
|
||||||
|
#include "../Importers/ImportObjDemo/ImportObjExample.h"
|
||||||
|
#include "../Importers/ImportBsp/ImportBspExample.h"
|
||||||
|
#include "../Importers/ImportColladaDemo/ImportColladaSetup.h"
|
||||||
|
#include "../Importers/ImportSTLDemo/ImportSTLSetup.h"
|
||||||
|
#include "../Importers/ImportURDFDemo/ImportURDFSetup.h"
|
||||||
|
#include "../GyroscopicDemo/GyroscopicSetup.h"
|
||||||
|
|
||||||
|
struct ExampleEntry
|
||||||
|
{
|
||||||
|
int m_menuLevel;
|
||||||
|
const char* m_name;
|
||||||
|
ExampleInterface::CreateFunc* m_createFunc;
|
||||||
|
int m_option;
|
||||||
|
|
||||||
|
ExampleEntry(int menuLevel, const char* name,ExampleInterface::CreateFunc* createFunc, int option=0)
|
||||||
|
:m_menuLevel(menuLevel), m_name(name), m_createFunc(createFunc), m_option(option)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ExampleEntry gDefaultExamples[]=
|
||||||
|
{
|
||||||
|
ExampleEntry(0,"Rendering",0),
|
||||||
|
ExampleEntry(1,"Instanced Rendering", RenderInstancingCreateFunc),
|
||||||
|
ExampleEntry(1,"CoordinateSystemDemo",CoordinateSystemCreateFunc),
|
||||||
|
ExampleEntry(1,"Raytracer",RayTracerCreateFunc),
|
||||||
|
|
||||||
|
ExampleEntry(0,"API",0),
|
||||||
|
ExampleEntry(1,"Basic Example",BasicExampleCreateFunc),
|
||||||
|
ExampleEntry(1,"Gyroscopic", GyroscopicCreateFunc),
|
||||||
|
ExampleEntry(1,"Planar 2D",Planar2DCreateFunc),
|
||||||
|
|
||||||
|
ExampleEntry(0,"Benchmarks", 0),
|
||||||
|
ExampleEntry(1,"3000 boxes", BenchmarkCreateFunc, 1),
|
||||||
|
ExampleEntry(1,"1000 stack", BenchmarkCreateFunc, 2),
|
||||||
|
ExampleEntry(1,"Ragdolls", BenchmarkCreateFunc, 3),
|
||||||
|
ExampleEntry(1,"Convex stack", BenchmarkCreateFunc, 4),
|
||||||
|
ExampleEntry(1,"Prim vs Mesh", BenchmarkCreateFunc, 5),
|
||||||
|
ExampleEntry(1,"Convex vs Mesh", BenchmarkCreateFunc, 6),
|
||||||
|
ExampleEntry(1,"7", BenchmarkCreateFunc, 7),
|
||||||
|
|
||||||
|
ExampleEntry(0,"Importers", 0),
|
||||||
|
ExampleEntry(1,"Wavefront Obj", ImportObjCreateFunc, 0),
|
||||||
|
ExampleEntry(1,"Quake BSP", ImportBspCreateFunc, 0),
|
||||||
|
ExampleEntry(1,"COLLADA dae", ImportColladaCreateFunc, 0),
|
||||||
|
ExampleEntry(1,"STL", ImportSTLCreateFunc, 0),
|
||||||
|
ExampleEntry(1,"URDF (RigidBody)", ImportURDFCreateFunc, 0),
|
||||||
|
ExampleEntry(1,"URDF (MultiBody)", ImportURDFCreateFunc, 1),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ExampleEntry(0,"Vehicles",0),
|
||||||
|
ExampleEntry(1,"ForkLift",ForkLiftCreateFunc),
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static btAlignedObjectArray<ExampleEntry> gAdditionalRegisteredExamples;
|
||||||
|
|
||||||
|
|
||||||
|
struct ExampleEntriesInternalData
|
||||||
|
{
|
||||||
|
btAlignedObjectArray<ExampleEntry> m_allExamples;
|
||||||
|
};
|
||||||
|
|
||||||
|
ExampleEntries::ExampleEntries()
|
||||||
|
{
|
||||||
|
m_data = new ExampleEntriesInternalData;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExampleEntries::~ExampleEntries()
|
||||||
|
{
|
||||||
|
delete m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExampleEntries::initExampleEntries()
|
||||||
|
{
|
||||||
|
m_data->m_allExamples.clear();
|
||||||
|
|
||||||
|
{
|
||||||
|
ExampleEntry e(0,"Basic Concepts", 0);
|
||||||
|
m_data->m_allExamples.push_back(e);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ExampleEntry e(1,"Empty",EmptyExample::CreateFunc);
|
||||||
|
m_data->m_allExamples.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numDefaultEntries = sizeof(gDefaultExamples)/sizeof(ExampleEntry);
|
||||||
|
for (int i=0;i<numDefaultEntries;i++)
|
||||||
|
{
|
||||||
|
m_data->m_allExamples.push_back(gDefaultExamples[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExampleEntries::registerExampleEntry(int menuLevel, const char* name,ExampleInterface::CreateFunc* createFunc, int option)
|
||||||
|
{
|
||||||
|
ExampleEntry e( menuLevel,name,createFunc, option);
|
||||||
|
gAdditionalRegisteredExamples.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExampleEntries::getNumRegisteredExamples()
|
||||||
|
{
|
||||||
|
return m_data->m_allExamples.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
ExampleInterface::CreateFunc* ExampleEntries::getExampleCreateFunc(int index)
|
||||||
|
{
|
||||||
|
return m_data->m_allExamples[index].m_createFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExampleEntries::getExampleOption(int index)
|
||||||
|
{
|
||||||
|
return m_data->m_allExamples[index].m_option;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* ExampleEntries::getExampleName(int index)
|
||||||
|
{
|
||||||
|
return m_data->m_allExamples[index].m_name;
|
||||||
|
}
|
||||||
36
examples/ExampleBrowser/ExampleEntries.h
Normal file
36
examples/ExampleBrowser/ExampleEntries.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
#ifndef EXAMPLE_ENTRIES_H
|
||||||
|
#define EXAMPLE_ENTRIES_H
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/ExampleInterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleEntries
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ExampleEntriesInternalData* m_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ExampleEntries();
|
||||||
|
virtual ~ExampleEntries();
|
||||||
|
|
||||||
|
static void registerExampleEntry(int menuLevel, const char* name,ExampleInterface::CreateFunc* createFunc, int option=0);
|
||||||
|
|
||||||
|
void initExampleEntries();
|
||||||
|
|
||||||
|
int getNumRegisteredExamples();
|
||||||
|
|
||||||
|
ExampleInterface::CreateFunc* getExampleCreateFunc(int index);
|
||||||
|
|
||||||
|
const char* getExampleName(int index);
|
||||||
|
|
||||||
|
int getExampleOption(int index);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //EXAMPLE_ENTRIES_H
|
||||||
2
examples/ExampleBrowser/GUIHelperInterface.cpp
Normal file
2
examples/ExampleBrowser/GUIHelperInterface.cpp
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#include "GUIHelperInterface.h"
|
||||||
|
|
||||||
75
examples/ExampleBrowser/GUIHelperInterface.h
Normal file
75
examples/ExampleBrowser/GUIHelperInterface.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#ifndef GUI_HELPER_INTERFACE_H
|
||||||
|
#define GUI_HELPER_INTERFACE_H
|
||||||
|
|
||||||
|
|
||||||
|
class btRigidBody;
|
||||||
|
class btVector3;
|
||||||
|
class btCollisionObject;
|
||||||
|
class btDiscreteDynamicsWorld;
|
||||||
|
class btCollisionShape;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///The Bullet 2 GraphicsPhysicsBridge let's the graphics engine create graphics representation and synchronize
|
||||||
|
struct GUIHelperInterface
|
||||||
|
{
|
||||||
|
virtual ~GUIHelperInterface() {}
|
||||||
|
|
||||||
|
virtual void createRigidBodyGraphicsObject(btRigidBody* body,const btVector3& color)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void createCollisionObjectGraphicsObject(btCollisionObject* obj,const btVector3& color)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual void createPhysicsDebugDrawer( btDiscreteDynamicsWorld* rbWorld)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices) { return -1; }//, int primitiveType = B3_GL_TRIANGLES, int textureIndex = -1);
|
||||||
|
|
||||||
|
virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) { return -1;}
|
||||||
|
|
||||||
|
virtual struct Common2dCanvasInterface* get2dCanvasInterface()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual struct CommonParameterInterface* getParameterInterface()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual struct CommonRenderInterface* getRenderInterface()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual struct CommonGraphicsApp* getAppInterface()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setUpAxis(int axis)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void drawText3D( const char* txt, float posX, float posZY, float posZ, float size)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //GUI_HELPER_INTERFACE_H
|
||||||
|
|
||||||
189
examples/ExampleBrowser/GwenGUISupport/GraphingTexture.cpp
Normal file
189
examples/ExampleBrowser/GwenGUISupport/GraphingTexture.cpp
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
#include "GraphingTexture.h"
|
||||||
|
#include "../OpenGLWindow/OpenGLInclude.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
GraphingTexture::GraphingTexture()
|
||||||
|
:m_textureId(0),
|
||||||
|
m_width(0),
|
||||||
|
m_height(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphingTexture::~GraphingTexture()
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphingTexture::destroy()
|
||||||
|
{
|
||||||
|
//TODO(erwincoumans) release memory etc...
|
||||||
|
m_width = 0;
|
||||||
|
m_height=0;
|
||||||
|
glDeleteTextures(1,(GLuint*)&m_textureId);
|
||||||
|
m_textureId=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphingTexture::create(int texWidth, int texHeight)
|
||||||
|
{
|
||||||
|
m_width = texWidth;
|
||||||
|
m_height = texHeight;
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
m_imageData.resize(texWidth*texHeight*4);
|
||||||
|
for(int y=0;y<texHeight;++y)
|
||||||
|
{
|
||||||
|
// const int t=y>>5;
|
||||||
|
GLubyte* pi=&m_imageData[y*texWidth*4];
|
||||||
|
for(int x=0;x<texWidth;++x)
|
||||||
|
{
|
||||||
|
if (x>=y)//x<2||y<2||x>253||y>253)
|
||||||
|
{
|
||||||
|
pi[0]=0;
|
||||||
|
pi[1]=0;
|
||||||
|
pi[2]=255;
|
||||||
|
pi[3]=255;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
pi[0]=255;
|
||||||
|
pi[1]=0;
|
||||||
|
pi[2]=0;
|
||||||
|
pi[3]=255;
|
||||||
|
}
|
||||||
|
|
||||||
|
pi+=4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
glGenTextures(1,(GLuint*)&m_textureId);
|
||||||
|
|
||||||
|
uploadImageData();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphingTexture::uploadImageData()
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D,m_textureId);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width,m_height,0,GL_RGBA,GL_UNSIGNED_BYTE,&m_imageData[0]);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
//shift the image one pixel
|
||||||
|
for(int y=0;y<texHeight;++y)
|
||||||
|
{
|
||||||
|
// const int t=y>>5;
|
||||||
|
for(int x=1;x<texWidth;++x)
|
||||||
|
{
|
||||||
|
GLubyte* org=image+(x+y*texWidth)*4;
|
||||||
|
|
||||||
|
GLubyte* dst=image+(x-1+y*texWidth)*4;
|
||||||
|
|
||||||
|
dst[0] = org[0];
|
||||||
|
dst[1] = org[1];
|
||||||
|
dst[2] = org[2];
|
||||||
|
dst[3] = org[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//render a new row at the right
|
||||||
|
for(int y=0;y<texHeight;++y)
|
||||||
|
{
|
||||||
|
GLubyte* pi=image+(texWidth-1+y*texWidth)*4;
|
||||||
|
pi[0]=255;
|
||||||
|
pi[1]=255;
|
||||||
|
pi[2]=255;
|
||||||
|
pi[3]=255;
|
||||||
|
if (y==texHeight*0.5)
|
||||||
|
{
|
||||||
|
pi[0]=200;
|
||||||
|
pi[1]=200;
|
||||||
|
pi[2]=200;
|
||||||
|
pi[3]=255;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
static float timer = 0.f;
|
||||||
|
static int prevValue=0;
|
||||||
|
timer+= 0.01;
|
||||||
|
float value = 128+100*sinf(timer);
|
||||||
|
MyClamp(value,0.f,float(texHeight-1));
|
||||||
|
GLubyte* org=image+(texWidth-1+(int)value*texWidth)*4;
|
||||||
|
org[0] = 0;
|
||||||
|
org[1] = 0;
|
||||||
|
org[2] = 0;
|
||||||
|
org[3] = 255;
|
||||||
|
|
||||||
|
if (prevValue<value)
|
||||||
|
{
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
static float timer = 1.4f;
|
||||||
|
timer+= 0.04;
|
||||||
|
float value = 128+150*sinf(timer);
|
||||||
|
MyClamp(value,0.f,float(texHeight-1));
|
||||||
|
|
||||||
|
GLubyte* org=image+(texWidth-1+(int)value*texWidth)*4;
|
||||||
|
org[0] = 0;
|
||||||
|
org[1] = 255;
|
||||||
|
org[2] = 0;
|
||||||
|
org[3] = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
static float timer = 1.4f;
|
||||||
|
timer+= 0.02;
|
||||||
|
float value =256+400*sinf(timer);
|
||||||
|
MyClamp(value,0.f,float(texHeight-1));
|
||||||
|
static int prevValue = 0;
|
||||||
|
|
||||||
|
GLubyte* org=image+(texWidth-1+(int)value*texWidth)*4;
|
||||||
|
org[0] = 0;
|
||||||
|
org[1] = 0;
|
||||||
|
org[2] = 255;
|
||||||
|
org[3] = 255;
|
||||||
|
|
||||||
|
if (prevValue<value)
|
||||||
|
{
|
||||||
|
for (int i=prevValue;i<value;i++)
|
||||||
|
{
|
||||||
|
GLubyte* org=image+(texHeight-1+(int)i*texWidth)*4;
|
||||||
|
org[0] = 0;
|
||||||
|
org[1] = 0;
|
||||||
|
org[2] = 255;
|
||||||
|
org[3] = 255;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
for (int i=value;i<prevValue;i++)
|
||||||
|
{
|
||||||
|
GLubyte* org=image+(texHeight-1+(int)i*texWidth)*4;
|
||||||
|
org[0] = 0;
|
||||||
|
org[1] = 0;
|
||||||
|
org[2] = 255;
|
||||||
|
org[3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth,texHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,image);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
36
examples/ExampleBrowser/GwenGUISupport/GraphingTexture.h
Normal file
36
examples/ExampleBrowser/GwenGUISupport/GraphingTexture.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef GRAPHING_TEXTURE_H
|
||||||
|
#define GRAPHING_TEXTURE_H
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
struct GraphingTexture
|
||||||
|
{
|
||||||
|
int m_textureId;
|
||||||
|
//assume rgba (8 bit per component, total of 32bit per pixel, for m_width*m_height pixels)
|
||||||
|
btAlignedObjectArray<unsigned char> m_imageData;
|
||||||
|
int m_width;
|
||||||
|
int m_height;
|
||||||
|
|
||||||
|
GraphingTexture();
|
||||||
|
virtual ~GraphingTexture();
|
||||||
|
|
||||||
|
bool create(int texWidth, int texHeight);
|
||||||
|
void destroy();
|
||||||
|
|
||||||
|
void setPixel(int x, int y, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
|
||||||
|
{
|
||||||
|
m_imageData[x*4+y*4*m_width+0] = red;
|
||||||
|
m_imageData[x*4+y*4*m_width+1] = green;
|
||||||
|
m_imageData[x*4+y*4*m_width+2] = blue;
|
||||||
|
m_imageData[x*4+y*4*m_width+3] = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uploadImageData();
|
||||||
|
|
||||||
|
int getTextureId()
|
||||||
|
{
|
||||||
|
return m_textureId;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //GRAPHING_TEXTURE_H
|
||||||
|
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
#include "GwenParameterInterface.h"
|
||||||
|
#include "gwenInternalData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct MySliderEventHandler : public Gwen::Event::Handler
|
||||||
|
{
|
||||||
|
Gwen::Controls::TextBox* m_label;
|
||||||
|
Gwen::Controls::Slider* m_pSlider;
|
||||||
|
char m_variableName[1024];
|
||||||
|
T* m_targetValue;
|
||||||
|
bool m_showValue;
|
||||||
|
|
||||||
|
MySliderEventHandler(const char* varName, Gwen::Controls::TextBox* label, Gwen::Controls::Slider* pSlider,T* target)
|
||||||
|
:m_label(label),
|
||||||
|
m_pSlider(pSlider),
|
||||||
|
m_targetValue(target),
|
||||||
|
m_showValue(true)
|
||||||
|
{
|
||||||
|
memcpy(m_variableName,varName,strlen(varName)+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SliderMoved( Gwen::Controls::Base* pControl )
|
||||||
|
{
|
||||||
|
Gwen::Controls::Slider* pSlider = (Gwen::Controls::Slider*)pControl;
|
||||||
|
//printf("value = %f\n", pSlider->GetValue());//UnitPrint( Utility::Format( L"Slider Value: %.2f", pSlider->GetValue() ) );
|
||||||
|
float bla = pSlider->GetValue();
|
||||||
|
T v = T(bla);
|
||||||
|
SetValue(v);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetValue(T v)
|
||||||
|
{
|
||||||
|
if (v < m_pSlider->GetRangeMin())
|
||||||
|
{
|
||||||
|
printf("?\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v > m_pSlider->GetRangeMax())
|
||||||
|
{
|
||||||
|
printf("?\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
m_pSlider->SetValue(v,true);
|
||||||
|
(*m_targetValue) = v;
|
||||||
|
float val = float(v);//todo: specialize on template type
|
||||||
|
if (m_showValue)
|
||||||
|
{
|
||||||
|
char txt[1024];
|
||||||
|
sprintf(txt,"%s : %.3f", m_variableName,val);
|
||||||
|
m_label->SetText(txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct GwenParameters
|
||||||
|
{
|
||||||
|
b3AlignedObjectArray<MySliderEventHandler<btScalar>*> m_sliderEventHandlers;
|
||||||
|
b3AlignedObjectArray<Gwen::Controls::HorizontalSlider*> m_sliders;
|
||||||
|
b3AlignedObjectArray<Gwen::Controls::TextBox*> m_textLabels;
|
||||||
|
int m_savedYposition;
|
||||||
|
};
|
||||||
|
|
||||||
|
GwenParameterInterface::GwenParameterInterface(GwenInternalData* gwenInternalData)
|
||||||
|
:m_gwenInternalData(gwenInternalData)
|
||||||
|
{
|
||||||
|
m_paramInternalData = new GwenParameters;
|
||||||
|
m_paramInternalData->m_savedYposition = m_gwenInternalData->m_curYposition;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GwenParameterInterface::~GwenParameterInterface()
|
||||||
|
{
|
||||||
|
|
||||||
|
removeAllParameters();
|
||||||
|
delete m_paramInternalData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GwenParameterInterface::setSliderValue(int sliderIndex, double sliderValue)
|
||||||
|
{
|
||||||
|
int sliderCapped = sliderValue+4;
|
||||||
|
sliderCapped /= 8;
|
||||||
|
sliderCapped *= 8;
|
||||||
|
|
||||||
|
if (sliderIndex>=0 && sliderIndex<m_paramInternalData->m_sliders.size())
|
||||||
|
{
|
||||||
|
m_paramInternalData->m_sliders[sliderIndex]->GetRangeMin();
|
||||||
|
|
||||||
|
m_paramInternalData->m_sliders[sliderIndex]->GetRangeMax();
|
||||||
|
float mappedValue =m_paramInternalData->m_sliders[sliderIndex]->GetRangeMin()+
|
||||||
|
(m_paramInternalData->m_sliders[sliderIndex]->GetRangeMax()-
|
||||||
|
m_paramInternalData->m_sliders[sliderIndex]->GetRangeMin())*sliderCapped/128.f;
|
||||||
|
printf("mappedValue = %f\n",mappedValue);
|
||||||
|
m_paramInternalData->m_sliders[sliderIndex]->SetValue(mappedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
void GwenParameterInterface::registerSliderFloatParameter(SliderParams& params)
|
||||||
|
{
|
||||||
|
Gwen::Controls::TextBox* label = new Gwen::Controls::TextBox(m_gwenInternalData->m_demoPage->GetPage());
|
||||||
|
m_paramInternalData->m_textLabels.push_back(label);
|
||||||
|
//m_data->m_myControls.push_back(label);
|
||||||
|
label->SetText( params.m_name);
|
||||||
|
label->SetPos( 10, 10 + 25 );
|
||||||
|
label->SetWidth(110);
|
||||||
|
label->SetPos(10,m_gwenInternalData->m_curYposition);
|
||||||
|
m_gwenInternalData->m_curYposition+=22;
|
||||||
|
|
||||||
|
Gwen::Controls::HorizontalSlider* pSlider = new Gwen::Controls::HorizontalSlider( m_gwenInternalData->m_demoPage->GetPage());
|
||||||
|
m_paramInternalData->m_sliders.push_back(pSlider);
|
||||||
|
//m_data->m_myControls.push_back(pSlider);
|
||||||
|
pSlider->SetPos( 10, m_gwenInternalData->m_curYposition );
|
||||||
|
pSlider->SetSize( 100, 20 );
|
||||||
|
pSlider->SetRange( params.m_minVal, params.m_maxVal);
|
||||||
|
pSlider->SetNotchCount(128);//float(params.m_maxVal-params.m_minVal)/100.f);
|
||||||
|
pSlider->SetClampToNotches( params.m_clampToNotches );
|
||||||
|
pSlider->SetValue( *params.m_paramValuePointer);//dimensions[i] );
|
||||||
|
char labelName[1024];
|
||||||
|
sprintf(labelName,"%s",params.m_name);//axisNames[0]);
|
||||||
|
MySliderEventHandler<btScalar>* handler = new MySliderEventHandler<btScalar>(labelName,label,pSlider,params.m_paramValuePointer);
|
||||||
|
handler->m_showValue = params.m_showValues;
|
||||||
|
m_paramInternalData->m_sliderEventHandlers.push_back(handler);
|
||||||
|
|
||||||
|
pSlider->onValueChanged.Add( handler, &MySliderEventHandler<btScalar>::SliderMoved );
|
||||||
|
handler->SliderMoved(pSlider);
|
||||||
|
// float v = pSlider->GetValue();
|
||||||
|
m_gwenInternalData->m_curYposition+=22;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwenParameterInterface::syncParameters()
|
||||||
|
{
|
||||||
|
for (int i=0;i<m_paramInternalData->m_sliderEventHandlers.size();i++)
|
||||||
|
{
|
||||||
|
MySliderEventHandler<btScalar>* handler = m_paramInternalData->m_sliderEventHandlers[i];
|
||||||
|
handler->m_pSlider->SetValue(*handler->m_targetValue,true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwenParameterInterface::removeAllParameters()
|
||||||
|
{
|
||||||
|
for (int i=0;i<m_paramInternalData->m_sliders.size();i++)
|
||||||
|
{
|
||||||
|
delete m_paramInternalData->m_sliders[i];
|
||||||
|
}
|
||||||
|
m_paramInternalData->m_sliders.clear();
|
||||||
|
|
||||||
|
for (int i=0;i<m_paramInternalData->m_sliderEventHandlers.size();i++)
|
||||||
|
{
|
||||||
|
delete m_paramInternalData->m_sliderEventHandlers[i];
|
||||||
|
}
|
||||||
|
m_paramInternalData->m_sliderEventHandlers.clear();
|
||||||
|
|
||||||
|
for (int i=0;i<m_paramInternalData->m_textLabels.size();i++)
|
||||||
|
{
|
||||||
|
delete m_paramInternalData->m_textLabels[i];
|
||||||
|
}
|
||||||
|
m_paramInternalData->m_textLabels.clear();
|
||||||
|
|
||||||
|
m_gwenInternalData->m_curYposition = this->m_paramInternalData->m_savedYposition;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef GWEN_PARAMETER_INTERFACE_H
|
||||||
|
#define GWEN_PARAMETER_INTERFACE_H
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/CommonParameterInterface.h"
|
||||||
|
|
||||||
|
struct GwenParameterInterface : public CommonParameterInterface
|
||||||
|
{
|
||||||
|
struct GwenInternalData* m_gwenInternalData;
|
||||||
|
|
||||||
|
struct GwenParameters* m_paramInternalData;
|
||||||
|
|
||||||
|
GwenParameterInterface(struct GwenInternalData* gwenInternalData);
|
||||||
|
virtual ~GwenParameterInterface();
|
||||||
|
virtual void registerSliderFloatParameter(SliderParams& params);
|
||||||
|
virtual void setSliderValue(int sliderIndex, double sliderValue);
|
||||||
|
virtual void syncParameters();
|
||||||
|
virtual void removeAllParameters();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif//GWEN_PARAMETER_INTERFACE_H
|
||||||
292
examples/ExampleBrowser/GwenGUISupport/GwenProfileWindow.cpp
Normal file
292
examples/ExampleBrowser/GwenGUISupport/GwenProfileWindow.cpp
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
#include "GwenProfileWindow.h"
|
||||||
|
#include "gwenUserInterface.h"
|
||||||
|
#include "gwenInternalData.h"
|
||||||
|
#include "LinearMath/btQuickprof.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MyProfileWindow : public Gwen::Controls::WindowControl
|
||||||
|
{
|
||||||
|
|
||||||
|
// Gwen::Controls::TabControl* m_TabControl;
|
||||||
|
//Gwen::Controls::ListBox* m_TextOutput;
|
||||||
|
unsigned int m_iFrames;
|
||||||
|
float m_fLastSecond;
|
||||||
|
|
||||||
|
Gwen::Controls::TreeNode* m_node;
|
||||||
|
Gwen::Controls::TreeControl* m_ctrl;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void onButtonA( Gwen::Controls::Base* pControl )
|
||||||
|
{
|
||||||
|
// OpenTissue::glut::toggleIdle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SliderMoved(Gwen::Controls::Base* pControl )
|
||||||
|
{
|
||||||
|
// Gwen::Controls::Slider* pSlider = (Gwen::Controls::Slider*)pControl;
|
||||||
|
//this->m_app->scaleYoungModulus(pSlider->GetValue());
|
||||||
|
// printf("Slider Value: %.2f", pSlider->GetValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OnCheckChangedStiffnessWarping (Gwen::Controls::Base* pControl)
|
||||||
|
{
|
||||||
|
// Gwen::Controls::CheckBox* labeled = (Gwen::Controls::CheckBox* )pControl;
|
||||||
|
// bool checked = labeled->IsChecked();
|
||||||
|
//m_app->m_stiffness_warp_on = checked;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
CProfileIterator* profIter;
|
||||||
|
|
||||||
|
MyProfileWindow ( Gwen::Controls::Base* pParent)
|
||||||
|
: Gwen::Controls::WindowControl( pParent ),
|
||||||
|
profIter(0)
|
||||||
|
{
|
||||||
|
SetTitle( L"Time Profiler" );
|
||||||
|
|
||||||
|
SetSize( 450, 450 );
|
||||||
|
this->SetPos(10,400);
|
||||||
|
|
||||||
|
// this->Dock( Gwen::Pos::Bottom);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
m_ctrl = new Gwen::Controls::TreeControl( this );
|
||||||
|
m_node = m_ctrl->AddNode( L"Total Parent Time" );
|
||||||
|
|
||||||
|
|
||||||
|
//Gwen::Controls::TreeNode* pNode = ctrl->AddNode( L"Node Two" );
|
||||||
|
//pNode->AddNode( L"Node Two Inside" );
|
||||||
|
//pNode->AddNode( L"Eyes" );
|
||||||
|
//pNode->AddNode( L"Brown" )->AddNode( L"Node Two Inside" )->AddNode( L"Eyes" )->AddNode( L"Brown" );
|
||||||
|
//Gwen::Controls::TreeNode* node = ctrl->AddNode( L"Node Three" );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//m_ctrl->Dock(Gwen::Pos::Bottom);
|
||||||
|
|
||||||
|
m_ctrl->ExpandAll();
|
||||||
|
m_ctrl->SetKeyboardInputEnabled(true);
|
||||||
|
m_ctrl->SetBounds( this->GetInnerBounds().x,this->GetInnerBounds().y,this->GetInnerBounds().w,this->GetInnerBounds().h);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float dumpRecursive(CProfileIterator* profileIterator, Gwen::Controls::TreeNode* parentNode)
|
||||||
|
{
|
||||||
|
profileIterator->First();
|
||||||
|
if (profileIterator->Is_Done())
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
|
||||||
|
int i;
|
||||||
|
int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
|
||||||
|
|
||||||
|
//printf("Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time );
|
||||||
|
float totalTime = 0.f;
|
||||||
|
|
||||||
|
|
||||||
|
int numChildren = 0;
|
||||||
|
Gwen::UnicodeString txt;
|
||||||
|
std::vector<Gwen::Controls::TreeNode*> nodes;
|
||||||
|
|
||||||
|
for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next())
|
||||||
|
{
|
||||||
|
numChildren++;
|
||||||
|
float current_total_time = profileIterator->Get_Current_Total_Time();
|
||||||
|
accumulated_time += current_total_time;
|
||||||
|
double fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
|
||||||
|
|
||||||
|
Gwen::String name(profileIterator->Get_Current_Name());
|
||||||
|
#ifdef _WIN32
|
||||||
|
Gwen::UnicodeString uname = Gwen::Utility::StringToUnicode(name);
|
||||||
|
|
||||||
|
txt = Gwen::Utility::Format(L"%s (%.2f %%) :: %.3f ms / frame (%d calls)",uname.c_str(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
|
||||||
|
|
||||||
|
#else
|
||||||
|
txt = Gwen::Utility::Format(L"%s (%.2f %%) :: %.3f ms / frame (%d calls)",name.c_str(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Gwen::Controls::TreeNode* childNode = (Gwen::Controls::TreeNode*)profileIterator->Get_Current_UserPointer();
|
||||||
|
if (!childNode)
|
||||||
|
{
|
||||||
|
childNode = parentNode->AddNode(L"");
|
||||||
|
profileIterator->Set_Current_UserPointer(childNode);
|
||||||
|
}
|
||||||
|
childNode->SetText(txt);
|
||||||
|
nodes.push_back(childNode);
|
||||||
|
|
||||||
|
totalTime += current_total_time;
|
||||||
|
//recurse into children
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<numChildren;i++)
|
||||||
|
{
|
||||||
|
profileIterator->Enter_Child(i);
|
||||||
|
Gwen::Controls::TreeNode* curNode = nodes[i];
|
||||||
|
|
||||||
|
dumpRecursive(profileIterator, curNode);
|
||||||
|
|
||||||
|
profileIterator->Enter_Parent();
|
||||||
|
}
|
||||||
|
return accumulated_time;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateText(CProfileIterator* profileIterator, bool idle)
|
||||||
|
{
|
||||||
|
|
||||||
|
// static bool update=true;
|
||||||
|
|
||||||
|
m_ctrl->SetBounds(0,0,this->GetInnerBounds().w,this->GetInnerBounds().h);
|
||||||
|
|
||||||
|
// if (!update)
|
||||||
|
// return;
|
||||||
|
// update=false;
|
||||||
|
|
||||||
|
|
||||||
|
static int test = 1;
|
||||||
|
test++;
|
||||||
|
|
||||||
|
static double time_since_reset = 0.f;
|
||||||
|
if (!idle)
|
||||||
|
{
|
||||||
|
time_since_reset = CProfileManager::Get_Time_Since_Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Gwen::UnicodeString txt = Gwen::Utility::Format( L"FEM Settings %i fps", test );
|
||||||
|
{
|
||||||
|
//recompute profiling data, and store profile strings
|
||||||
|
|
||||||
|
// char blockTime[128];
|
||||||
|
|
||||||
|
// double totalTime = 0;
|
||||||
|
|
||||||
|
// int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
|
||||||
|
|
||||||
|
profileIterator->First();
|
||||||
|
|
||||||
|
double parent_time = profileIterator->Is_Root() ? time_since_reset : profileIterator->Get_Current_Parent_Total_Time();
|
||||||
|
|
||||||
|
|
||||||
|
// Gwen::Controls::TreeNode* curParent = m_node;
|
||||||
|
|
||||||
|
double accumulated_time = dumpRecursive(profileIterator,m_node);
|
||||||
|
|
||||||
|
const char* name = profileIterator->Get_Current_Parent_Name();
|
||||||
|
#ifdef _WIN32
|
||||||
|
Gwen::UnicodeString uname = Gwen::Utility::StringToUnicode(name);
|
||||||
|
Gwen::UnicodeString txt = Gwen::Utility::Format( L"Profiling: %s total time: %.3f ms, unaccounted %.3f %% :: %.3f ms", uname.c_str(), parent_time ,
|
||||||
|
parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
|
||||||
|
#else
|
||||||
|
Gwen::UnicodeString txt = Gwen::Utility::Format( L"Profiling: %s total time: %.3f ms, unaccounted %.3f %% :: %.3f ms", name, parent_time ,
|
||||||
|
parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
|
||||||
|
#endif
|
||||||
|
//sprintf(blockTime,"--- Profiling: %s (total running time: %.3f ms) ---", profileIterator->Get_Current_Parent_Name(), parent_time );
|
||||||
|
//displayProfileString(xOffset,yStart,blockTime);
|
||||||
|
m_node->SetText(txt);
|
||||||
|
|
||||||
|
|
||||||
|
//printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:",);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int counter=10;
|
||||||
|
if (counter)
|
||||||
|
{
|
||||||
|
counter--;
|
||||||
|
m_ctrl->ExpandAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
void PrintText( const Gwen::UnicodeString& str )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render( Gwen::Skin::Base* skin )
|
||||||
|
{
|
||||||
|
m_iFrames++;
|
||||||
|
|
||||||
|
if ( m_fLastSecond < Gwen::Platform::GetTimeInSeconds() )
|
||||||
|
{
|
||||||
|
SetTitle( Gwen::Utility::Format( L"Profiler %i fps", m_iFrames ) );
|
||||||
|
|
||||||
|
m_fLastSecond = Gwen::Platform::GetTimeInSeconds() + 1.0f;
|
||||||
|
m_iFrames = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gwen::Controls::WindowControl::Render( skin );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class MyMenuItems : public Gwen::Controls::Base
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class MyProfileWindow* m_profWindow;
|
||||||
|
MyMenuItems() :Gwen::Controls::Base(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuItemSelect(Gwen::Controls::Base* pControl)
|
||||||
|
{
|
||||||
|
if (m_profWindow->Hidden())
|
||||||
|
{
|
||||||
|
m_profWindow->SetHidden(false);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_profWindow->SetHidden(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MyProfileWindow* setupProfileWindow(GwenInternalData* data)
|
||||||
|
{
|
||||||
|
MyMenuItems* menuItems = new MyMenuItems;
|
||||||
|
MyProfileWindow* profWindow = new MyProfileWindow(data->pCanvas);
|
||||||
|
//profWindow->SetHidden(true);
|
||||||
|
profWindow->profIter = CProfileManager::Get_Iterator();
|
||||||
|
data->m_viewMenu->GetMenu()->AddItem( L"Profiler", menuItems,(Gwen::Event::Handler::Function)&MyMenuItems::MenuItemSelect);
|
||||||
|
menuItems->m_profWindow = profWindow;
|
||||||
|
return profWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void processProfileData( MyProfileWindow* profWindow, bool idle)
|
||||||
|
{
|
||||||
|
if (profWindow)
|
||||||
|
{
|
||||||
|
|
||||||
|
profWindow->UpdateText(profWindow->profIter, idle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void profileWindowSetVisible(MyProfileWindow* window, bool visible)
|
||||||
|
{
|
||||||
|
window->SetHidden(!visible);
|
||||||
|
}
|
||||||
|
void destroyProfileWindow(MyProfileWindow* window)
|
||||||
|
{
|
||||||
|
delete window;
|
||||||
|
}
|
||||||
11
examples/ExampleBrowser/GwenGUISupport/GwenProfileWindow.h
Normal file
11
examples/ExampleBrowser/GwenGUISupport/GwenProfileWindow.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef GWEN_PROFILE_WINDOW_H
|
||||||
|
#define GWEN_PROFILE_WINDOW_H
|
||||||
|
|
||||||
|
class MyProfileWindow* setupProfileWindow(struct GwenInternalData* data);
|
||||||
|
void processProfileData(MyProfileWindow* window, bool idle);
|
||||||
|
void profileWindowSetVisible(MyProfileWindow* window, bool visible);
|
||||||
|
void destroyProfileWindow(MyProfileWindow* window);
|
||||||
|
|
||||||
|
#endif//GWEN_PROFILE_WINDOW_H
|
||||||
|
|
||||||
|
|
||||||
100
examples/ExampleBrowser/GwenGUISupport/GwenTextureWindow.cpp
Normal file
100
examples/ExampleBrowser/GwenGUISupport/GwenTextureWindow.cpp
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
#include "GwenTextureWindow.h"
|
||||||
|
#include "gwenUserInterface.h"
|
||||||
|
#include "gwenInternalData.h"
|
||||||
|
#include "Gwen/Controls/ImagePanel.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MyGraphWindow : public Gwen::Controls::WindowControl
|
||||||
|
{
|
||||||
|
Gwen::Controls::ImagePanel* m_imgPanel;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class MyMenuItems2* m_menuItems;
|
||||||
|
|
||||||
|
MyGraphWindow ( const MyGraphInput& input)
|
||||||
|
: Gwen::Controls::WindowControl( input.m_data->pCanvas ),
|
||||||
|
m_menuItems(0)
|
||||||
|
{
|
||||||
|
Gwen::UnicodeString str = Gwen::Utility::StringToUnicode(input.m_name);
|
||||||
|
SetTitle( str );
|
||||||
|
|
||||||
|
|
||||||
|
SetPos(input.m_xPos,input.m_yPos);
|
||||||
|
SetSize( 12+input.m_width+2*input.m_borderWidth, 30+input.m_height+2*input.m_borderWidth );
|
||||||
|
|
||||||
|
m_imgPanel = new Gwen::Controls::ImagePanel( this );
|
||||||
|
if (input.m_texName)
|
||||||
|
{
|
||||||
|
Gwen::UnicodeString texName = Gwen::Utility::StringToUnicode(input.m_texName);
|
||||||
|
m_imgPanel->SetImage( texName );
|
||||||
|
}
|
||||||
|
m_imgPanel->SetBounds( input.m_borderWidth, input.m_borderWidth,
|
||||||
|
input.m_width,
|
||||||
|
input.m_height );
|
||||||
|
// this->Dock( Gwen::Pos::Bottom);
|
||||||
|
}
|
||||||
|
virtual ~MyGraphWindow()
|
||||||
|
{
|
||||||
|
delete m_imgPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class MyMenuItems2 : public Gwen::Controls::Base
|
||||||
|
{
|
||||||
|
MyGraphWindow* m_graphWindow;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Gwen::Controls::MenuItem* m_item;
|
||||||
|
|
||||||
|
MyMenuItems2(MyGraphWindow* graphWindow)
|
||||||
|
:Gwen::Controls::Base(0),
|
||||||
|
m_graphWindow(graphWindow),
|
||||||
|
m_item(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuItemSelect(Gwen::Controls::Base* pControl)
|
||||||
|
{
|
||||||
|
if (m_graphWindow->Hidden())
|
||||||
|
{
|
||||||
|
m_graphWindow->SetHidden(false);
|
||||||
|
//@TODO(erwincoumans) setCheck/SetCheckable drawing is broken, need to see what's wrong
|
||||||
|
// if (m_item)
|
||||||
|
// m_item->SetCheck(false);
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_graphWindow->SetHidden(true);
|
||||||
|
// if (m_item)
|
||||||
|
// m_item->SetCheck(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MyGraphWindow* setupTextureWindow(const MyGraphInput& input)
|
||||||
|
{
|
||||||
|
MyGraphWindow* graphWindow = new MyGraphWindow(input);
|
||||||
|
MyMenuItems2* menuItems = new MyMenuItems2(graphWindow);
|
||||||
|
graphWindow->m_menuItems = menuItems;
|
||||||
|
|
||||||
|
Gwen::UnicodeString str = Gwen::Utility::StringToUnicode(input.m_name);
|
||||||
|
menuItems->m_item = input.m_data->m_viewMenu->GetMenu()->AddItem( str, menuItems,(Gwen::Event::Handler::Function)&MyMenuItems2::MenuItemSelect);
|
||||||
|
// menuItems->m_item->SetCheckable(true);
|
||||||
|
|
||||||
|
return graphWindow;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroyTextureWindow(MyGraphWindow* window)
|
||||||
|
{
|
||||||
|
delete window->m_menuItems->m_item;
|
||||||
|
delete window->m_menuItems;
|
||||||
|
delete window;
|
||||||
|
}
|
||||||
32
examples/ExampleBrowser/GwenGUISupport/GwenTextureWindow.h
Normal file
32
examples/ExampleBrowser/GwenGUISupport/GwenTextureWindow.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#ifndef GWEN_TEXTURE_WINDOW_H
|
||||||
|
#define GWEN_TEXTURE_WINDOW_H
|
||||||
|
|
||||||
|
struct MyGraphInput
|
||||||
|
{
|
||||||
|
struct GwenInternalData* m_data;
|
||||||
|
int m_xPos;
|
||||||
|
int m_yPos;
|
||||||
|
int m_width;
|
||||||
|
int m_height;
|
||||||
|
int m_borderWidth;
|
||||||
|
const char* m_name;
|
||||||
|
const char* m_texName;
|
||||||
|
MyGraphInput(struct GwenInternalData* data)
|
||||||
|
:m_data(data),
|
||||||
|
m_xPos(0),
|
||||||
|
m_yPos(0),
|
||||||
|
m_width(400),
|
||||||
|
m_height(400),
|
||||||
|
m_borderWidth(0),
|
||||||
|
m_name("GraphWindow"),
|
||||||
|
m_texName(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class MyGraphWindow* setupTextureWindow(const MyGraphInput& input);
|
||||||
|
void destroyTextureWindow(MyGraphWindow* window);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GWEN_TEXTURE_WINDOW_H
|
||||||
57
examples/ExampleBrowser/GwenGUISupport/gwenInternalData.h
Normal file
57
examples/ExampleBrowser/GwenGUISupport/gwenInternalData.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#ifndef GWEN_INTERNAL_DATA_H
|
||||||
|
#define GWEN_INTERNAL_DATA_H
|
||||||
|
|
||||||
|
#include "../OpenGLWindow/GwenOpenGL3CoreRenderer.h"
|
||||||
|
#include "../OpenGLWindow/GLPrimitiveRenderer.h"
|
||||||
|
#include "Gwen/Platform.h"
|
||||||
|
#include "Gwen/Controls/TreeControl.h"
|
||||||
|
#include "Gwen/Controls/RadioButtonController.h"
|
||||||
|
#include "Gwen/Controls/VerticalSlider.h"
|
||||||
|
#include "Gwen/Controls/HorizontalSlider.h"
|
||||||
|
#include "Gwen/Controls/GroupBox.h"
|
||||||
|
#include "Gwen/Controls/CheckBox.h"
|
||||||
|
#include "Gwen/Controls/StatusBar.h"
|
||||||
|
#include "Gwen/Controls/Button.h"
|
||||||
|
#include "Gwen/Controls/ComboBox.h"
|
||||||
|
#include "Gwen/Controls/MenuStrip.h"
|
||||||
|
#include "Gwen/Controls/Slider.h"
|
||||||
|
#include "Gwen/Controls/Property/Text.h"
|
||||||
|
#include "Gwen/Controls/SplitterBar.h"
|
||||||
|
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||||
|
#include "Gwen/Gwen.h"
|
||||||
|
#include "Gwen/Align.h"
|
||||||
|
#include "Gwen/Utility.h"
|
||||||
|
#include "Gwen/Controls/WindowControl.h"
|
||||||
|
#include "Gwen/Controls/TabControl.h"
|
||||||
|
#include "Gwen/Controls/ListBox.h"
|
||||||
|
#include "Gwen/Skins/Simple.h"
|
||||||
|
//#include "Gwen/Skins/TexturedBase.h"
|
||||||
|
#include "gwenUserInterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct GwenInternalData
|
||||||
|
{
|
||||||
|
//struct sth_stash;
|
||||||
|
//class GwenOpenGL3CoreRenderer* pRenderer;
|
||||||
|
Gwen::Renderer::Base* pRenderer;
|
||||||
|
Gwen::Skin::Simple skin;
|
||||||
|
Gwen::Controls::Canvas* pCanvas;
|
||||||
|
//GLPrimitiveRenderer* m_primRenderer;
|
||||||
|
Gwen::Controls::TabButton* m_demoPage;
|
||||||
|
Gwen::Controls::TabButton* m_explorerPage;
|
||||||
|
Gwen::Controls::TreeControl* m_explorerTreeCtrl;
|
||||||
|
Gwen::Controls::MenuItem* m_viewMenu;
|
||||||
|
class MyMenuItems* m_menuItems;
|
||||||
|
|
||||||
|
int m_curYposition;
|
||||||
|
|
||||||
|
Gwen::Controls::Label* m_rightStatusBar;
|
||||||
|
Gwen::Controls::Label* m_leftStatusBar;
|
||||||
|
b3AlignedObjectArray<class Gwen::Event::Handler*> m_handlers;
|
||||||
|
b3ToggleButtonCallback m_toggleButtonCallback;
|
||||||
|
b3ComboBoxCallback m_comboBoxCallback;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif//GWEN_INTERNAL_DATA_H
|
||||||
463
examples/ExampleBrowser/GwenGUISupport/gwenUserInterface.cpp
Normal file
463
examples/ExampleBrowser/GwenGUISupport/gwenUserInterface.cpp
Normal file
@@ -0,0 +1,463 @@
|
|||||||
|
|
||||||
|
#include "gwenUserInterface.h"
|
||||||
|
#include "gwenInternalData.h"
|
||||||
|
#include "Gwen/Controls/ImagePanel.h"
|
||||||
|
|
||||||
|
class MyGraphWindow* graphWindow = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GwenUserInterface::GwenUserInterface()
|
||||||
|
{
|
||||||
|
m_data = new GwenInternalData();
|
||||||
|
m_data->m_toggleButtonCallback = 0;
|
||||||
|
m_data->m_comboBoxCallback = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GwenUserInterface::~GwenUserInterface()
|
||||||
|
{
|
||||||
|
for (int i=0;i<m_data->m_handlers.size();i++)
|
||||||
|
{
|
||||||
|
delete m_data->m_handlers[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
m_data->m_handlers.clear();
|
||||||
|
|
||||||
|
|
||||||
|
delete m_data->pCanvas;
|
||||||
|
|
||||||
|
|
||||||
|
delete m_data;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MyMenuItems : public Gwen::Controls::Base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
b3FileOpenCallback m_fileOpenCallback;
|
||||||
|
|
||||||
|
MyMenuItems() :Gwen::Controls::Base(0),m_fileOpenCallback(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void myQuitApp( Gwen::Controls::Base* pControl )
|
||||||
|
{
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
void fileOpen( Gwen::Controls::Base* pControl )
|
||||||
|
{
|
||||||
|
if (m_fileOpenCallback)
|
||||||
|
{
|
||||||
|
(*m_fileOpenCallback)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyTestMenuBar : public Gwen::Controls::MenuStrip
|
||||||
|
{
|
||||||
|
|
||||||
|
Gwen::Controls::MenuItem* m_fileMenu;
|
||||||
|
Gwen::Controls::MenuItem* m_viewMenu;
|
||||||
|
MyMenuItems* m_menuItems;
|
||||||
|
|
||||||
|
MyTestMenuBar(Gwen::Controls::Base* pParent)
|
||||||
|
:Gwen::Controls::MenuStrip(pParent)
|
||||||
|
{
|
||||||
|
// Gwen::Controls::MenuStrip* menu = new Gwen::Controls::MenuStrip( pParent );
|
||||||
|
{
|
||||||
|
m_menuItems = new MyMenuItems();
|
||||||
|
m_menuItems->m_fileOpenCallback = 0;
|
||||||
|
|
||||||
|
m_fileMenu = AddItem( L"File" );
|
||||||
|
|
||||||
|
m_fileMenu->GetMenu()->AddItem(L"Open",m_menuItems,(Gwen::Event::Handler::Function)&MyMenuItems::fileOpen);
|
||||||
|
m_fileMenu->GetMenu()->AddItem(L"Quit",m_menuItems,(Gwen::Event::Handler::Function)&MyMenuItems::myQuitApp);
|
||||||
|
m_viewMenu = AddItem( L"View" );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void GwenUserInterface::resize(int width, int height)
|
||||||
|
{
|
||||||
|
m_data->pCanvas->SetSize(width,height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct MyComboBoxHander :public Gwen::Event::Handler
|
||||||
|
{
|
||||||
|
GwenInternalData* m_data;
|
||||||
|
int m_buttonId;
|
||||||
|
|
||||||
|
MyComboBoxHander (GwenInternalData* data, int buttonId)
|
||||||
|
:m_data(data),
|
||||||
|
m_buttonId(buttonId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSelect( Gwen::Controls::Base* pControl )
|
||||||
|
{
|
||||||
|
Gwen::Controls::ComboBox* but = (Gwen::Controls::ComboBox*) pControl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Gwen::String str = Gwen::Utility::UnicodeToString( but->GetSelectedItem()->GetText());
|
||||||
|
|
||||||
|
if (m_data->m_comboBoxCallback)
|
||||||
|
(*m_data->m_comboBoxCallback)(m_buttonId,str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyButtonHander :public Gwen::Event::Handler
|
||||||
|
{
|
||||||
|
GwenInternalData* m_data;
|
||||||
|
int m_buttonId;
|
||||||
|
|
||||||
|
MyButtonHander (GwenInternalData* data, int buttonId)
|
||||||
|
:m_data(data),
|
||||||
|
m_buttonId(buttonId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void onButtonA( Gwen::Controls::Base* pControl )
|
||||||
|
{
|
||||||
|
Gwen::Controls::Button* but = (Gwen::Controls::Button*) pControl;
|
||||||
|
// int dep = but->IsDepressed();
|
||||||
|
int tog = but->GetToggleState();
|
||||||
|
if (m_data->m_toggleButtonCallback)
|
||||||
|
(*m_data->m_toggleButtonCallback)(m_buttonId,tog);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void GwenUserInterface::setStatusBarMessage(const char* message, bool isLeft)
|
||||||
|
{
|
||||||
|
Gwen::UnicodeString msg = Gwen::Utility::StringToUnicode(message);
|
||||||
|
if (isLeft)
|
||||||
|
{
|
||||||
|
m_data->m_leftStatusBar->SetText( msg);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_data->m_rightStatusBar->SetText( msg);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwenUserInterface::registerFileOpenCallback(b3FileOpenCallback callback)
|
||||||
|
{
|
||||||
|
m_data->m_menuItems->m_fileOpenCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwenUserInterface::init(int width, int height,Gwen::Renderer::Base* renderer,float retinaScale)
|
||||||
|
{
|
||||||
|
m_data->m_curYposition = 20;
|
||||||
|
//m_data->m_primRenderer = new GLPrimitiveRenderer(width,height);
|
||||||
|
m_data->pRenderer = renderer;//new GwenOpenGL3CoreRenderer(m_data->m_primRenderer,stash,width,height,retinaScale);
|
||||||
|
|
||||||
|
m_data->skin.SetRender( m_data->pRenderer );
|
||||||
|
|
||||||
|
m_data->pCanvas= new Gwen::Controls::Canvas( &m_data->skin );
|
||||||
|
m_data->pCanvas->SetSize( width,height);
|
||||||
|
m_data->pCanvas->SetDrawBackground( false);
|
||||||
|
m_data->pCanvas->SetBackgroundColor( Gwen::Color( 150, 170, 170, 255 ) );
|
||||||
|
|
||||||
|
MyTestMenuBar* menubar = new MyTestMenuBar(m_data->pCanvas);
|
||||||
|
m_data->m_viewMenu = menubar->m_viewMenu;
|
||||||
|
m_data->m_menuItems = menubar->m_menuItems;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Gwen::Controls::StatusBar* bar = new Gwen::Controls::StatusBar(m_data->pCanvas);
|
||||||
|
m_data->m_rightStatusBar = new Gwen::Controls::Label( bar );
|
||||||
|
m_data->m_rightStatusBar->SetWidth(width/2);
|
||||||
|
//m_data->m_rightStatusBar->SetText( L"Label Added to Right" );
|
||||||
|
bar->AddControl( m_data->m_rightStatusBar, true );
|
||||||
|
|
||||||
|
m_data->m_leftStatusBar = new Gwen::Controls::Label( bar );
|
||||||
|
//m_data->m_leftStatusBar->SetText( L"Label Added to Left" );
|
||||||
|
m_data->m_leftStatusBar->SetWidth(width/2);
|
||||||
|
bar->AddControl( m_data->m_leftStatusBar,false);
|
||||||
|
//Gwen::KeyboardFocus
|
||||||
|
/*Gwen::Controls::GroupBox* box = new Gwen::Controls::GroupBox(m_data->pCanvas);
|
||||||
|
box->SetText("text");
|
||||||
|
box->SetName("name");
|
||||||
|
box->SetHeight(500);
|
||||||
|
*/
|
||||||
|
Gwen::Controls::ScrollControl* windowRight= new Gwen::Controls::ScrollControl(m_data->pCanvas);
|
||||||
|
windowRight->Dock(Gwen::Pos::Right);
|
||||||
|
windowRight->SetWidth(150);
|
||||||
|
windowRight->SetHeight(250);
|
||||||
|
windowRight->SetScroll(false,true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//windowLeft->SetSkin(
|
||||||
|
Gwen::Controls::TabControl* tab = new Gwen::Controls::TabControl(windowRight);
|
||||||
|
|
||||||
|
//tab->SetHeight(300);
|
||||||
|
tab->SetWidth(140);
|
||||||
|
tab->SetHeight(250);
|
||||||
|
//tab->Dock(Gwen::Pos::Left);
|
||||||
|
tab->Dock( Gwen::Pos::Fill );
|
||||||
|
//tab->SetMargin( Gwen::Margin( 2, 2, 2, 2 ) );
|
||||||
|
|
||||||
|
Gwen::UnicodeString str1(L"Params");
|
||||||
|
m_data->m_demoPage = tab->AddPage(str1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Gwen::UnicodeString str2(L"OpenCL");
|
||||||
|
// tab->AddPage(str2);
|
||||||
|
//Gwen::UnicodeString str3(L"page3");
|
||||||
|
// tab->AddPage(str3);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//but->onPress.Add(handler, &MyHander::onButtonA);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//box->Dock(Gwen::Pos::Left);
|
||||||
|
|
||||||
|
/*Gwen::Controls::WindowControl* windowBottom = new Gwen::Controls::WindowControl(m_data->pCanvas);
|
||||||
|
windowBottom->SetHeight(100);
|
||||||
|
windowBottom->Dock(Gwen::Pos::Bottom);
|
||||||
|
windowBottom->SetTitle("bottom");
|
||||||
|
*/
|
||||||
|
// Gwen::Controls::Property::Text* prop = new Gwen::Controls::Property::Text(m_data->pCanvas);
|
||||||
|
//prop->Dock(Gwen::Pos::Bottom);
|
||||||
|
/*Gwen::Controls::SplitterBar* split = new Gwen::Controls::SplitterBar(m_data->pCanvas);
|
||||||
|
split->Dock(Gwen::Pos::Center);
|
||||||
|
split->SetHeight(300);
|
||||||
|
split->SetWidth(300);
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Gwen::Controls::ScrollControl* windowLeft = new Gwen::Controls::ScrollControl(m_data->pCanvas);
|
||||||
|
windowLeft->Dock(Gwen::Pos::Left);
|
||||||
|
// windowLeft->SetTitle("title");
|
||||||
|
windowLeft->SetScroll(false, false);
|
||||||
|
windowLeft->SetWidth(250);
|
||||||
|
windowLeft->SetPos(50, 50);
|
||||||
|
windowLeft->SetHeight(500);
|
||||||
|
//windowLeft->SetClosable(false);
|
||||||
|
// windowLeft->SetShouldDrawBackground(true);
|
||||||
|
windowLeft->SetTabable(true);
|
||||||
|
|
||||||
|
Gwen::Controls::TabControl* explorerTab = new Gwen::Controls::TabControl(windowLeft);
|
||||||
|
|
||||||
|
//tab->SetHeight(300);
|
||||||
|
// explorerTab->SetWidth(230);
|
||||||
|
explorerTab->SetHeight(250);
|
||||||
|
//tab->Dock(Gwen::Pos::Left);
|
||||||
|
explorerTab->Dock(Gwen::Pos::Fill);
|
||||||
|
|
||||||
|
Gwen::UnicodeString explorerStr1(L"Explorer");
|
||||||
|
m_data->m_explorerPage = explorerTab->AddPage(explorerStr1);
|
||||||
|
Gwen::UnicodeString shapesStr1(L"Shapes");
|
||||||
|
explorerTab->AddPage(shapesStr1);
|
||||||
|
Gwen::UnicodeString testStr1(L"Test");
|
||||||
|
explorerTab->AddPage(testStr1);
|
||||||
|
|
||||||
|
Gwen::Controls::TreeControl* ctrl = new Gwen::Controls::TreeControl(m_data->m_explorerPage->GetPage());
|
||||||
|
m_data->m_explorerTreeCtrl = ctrl;
|
||||||
|
ctrl->SetKeyboardInputEnabled(true);
|
||||||
|
ctrl->Focus();
|
||||||
|
ctrl->SetBounds(2, 10, 236, 400);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwenUserInterface::forceUpdateScrollBars()
|
||||||
|
{
|
||||||
|
b3Assert(m_data);
|
||||||
|
b3Assert(m_data->m_explorerTreeCtrl);
|
||||||
|
if (m_data && m_data->m_explorerTreeCtrl)
|
||||||
|
{
|
||||||
|
m_data->m_explorerTreeCtrl->ForceUpdateScrollBars();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwenUserInterface::setFocus()
|
||||||
|
{
|
||||||
|
b3Assert(m_data);
|
||||||
|
b3Assert(m_data->m_explorerTreeCtrl);
|
||||||
|
if (m_data && m_data->m_explorerTreeCtrl)
|
||||||
|
{
|
||||||
|
m_data->m_explorerTreeCtrl->Focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b3ToggleButtonCallback GwenUserInterface::getToggleButtonCallback()
|
||||||
|
{
|
||||||
|
return m_data->m_toggleButtonCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwenUserInterface::setToggleButtonCallback(b3ToggleButtonCallback callback)
|
||||||
|
{
|
||||||
|
m_data->m_toggleButtonCallback = callback;
|
||||||
|
}
|
||||||
|
void GwenUserInterface::registerToggleButton(int buttonId, const char* name)
|
||||||
|
{
|
||||||
|
assert(m_data);
|
||||||
|
assert(m_data->m_demoPage);
|
||||||
|
|
||||||
|
Gwen::Controls::Button* but = new Gwen::Controls::Button(m_data->m_demoPage->GetPage());
|
||||||
|
|
||||||
|
///some heuristic to find the button location
|
||||||
|
int ypos = m_data->m_curYposition;
|
||||||
|
but->SetPos(10, ypos );
|
||||||
|
but->SetWidth( 100 );
|
||||||
|
//but->SetBounds( 200, 30, 300, 200 );
|
||||||
|
|
||||||
|
MyButtonHander* handler = new MyButtonHander(m_data, buttonId);
|
||||||
|
m_data->m_handlers.push_back(handler);
|
||||||
|
m_data->m_curYposition+=22;
|
||||||
|
but->onToggle.Add(handler, &MyButtonHander::onButtonA);
|
||||||
|
but->SetIsToggle(true);
|
||||||
|
but->SetToggleState(false);
|
||||||
|
but->SetText(name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwenUserInterface::setComboBoxCallback(b3ComboBoxCallback callback)
|
||||||
|
{
|
||||||
|
m_data->m_comboBoxCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
b3ComboBoxCallback GwenUserInterface::getComboBoxCallback()
|
||||||
|
{
|
||||||
|
return m_data->m_comboBoxCallback;
|
||||||
|
}
|
||||||
|
void GwenUserInterface::registerComboBox(int comboboxId, int numItems, const char** items, int startItem)
|
||||||
|
{
|
||||||
|
Gwen::Controls::ComboBox* combobox = new Gwen::Controls::ComboBox(m_data->m_demoPage->GetPage());
|
||||||
|
MyComboBoxHander* handler = new MyComboBoxHander(m_data, comboboxId);
|
||||||
|
m_data->m_handlers.push_back(handler);
|
||||||
|
|
||||||
|
combobox->onSelection.Add(handler,&MyComboBoxHander::onSelect);
|
||||||
|
int ypos = m_data->m_curYposition;
|
||||||
|
combobox->SetPos(10, ypos );
|
||||||
|
combobox->SetWidth( 100 );
|
||||||
|
//box->SetPos(120,130);
|
||||||
|
for (int i=0;i<numItems;i++)
|
||||||
|
{
|
||||||
|
Gwen::Controls::MenuItem* item = combobox->AddItem(Gwen::Utility::StringToUnicode(items[i]));
|
||||||
|
if (i==startItem)
|
||||||
|
combobox->OnItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_data->m_curYposition+=22;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwenUserInterface::draw(int width, int height)
|
||||||
|
{
|
||||||
|
|
||||||
|
// printf("width = %d, height=%d\n", width,height);
|
||||||
|
if (m_data->pCanvas)
|
||||||
|
{
|
||||||
|
m_data->pCanvas->SetSize(width,height);
|
||||||
|
//m_data->m_primRenderer->setScreenSize(width,height);
|
||||||
|
m_data->pRenderer->Resize(width,height);
|
||||||
|
m_data->pCanvas->RenderCanvas();
|
||||||
|
//restoreOpenGLState();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GwenUserInterface::mouseMoveCallback( float x, float y)
|
||||||
|
{
|
||||||
|
bool handled = false;
|
||||||
|
|
||||||
|
static int m_lastmousepos[2] = {0,0};
|
||||||
|
static bool isInitialized = false;
|
||||||
|
if (m_data->pCanvas)
|
||||||
|
{
|
||||||
|
if (!isInitialized)
|
||||||
|
{
|
||||||
|
isInitialized = true;
|
||||||
|
m_lastmousepos[0] = x+1;
|
||||||
|
m_lastmousepos[1] = y+1;
|
||||||
|
}
|
||||||
|
handled = m_data->pCanvas->InputMouseMoved(x,y,m_lastmousepos[0],m_lastmousepos[1]);
|
||||||
|
}
|
||||||
|
return handled;
|
||||||
|
|
||||||
|
}
|
||||||
|
#include "../CommonInterfaces/CommonWindowInterface.h"
|
||||||
|
|
||||||
|
bool GwenUserInterface::keyboardCallback(int bulletKey, int state)
|
||||||
|
{
|
||||||
|
int key = -1;
|
||||||
|
if (m_data->pCanvas)
|
||||||
|
{
|
||||||
|
//convert 'Bullet' keys into 'Gwen' keys
|
||||||
|
switch (bulletKey)
|
||||||
|
{
|
||||||
|
case B3G_RETURN:
|
||||||
|
{
|
||||||
|
key = Gwen::Key::Return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case B3G_LEFT_ARROW:
|
||||||
|
key = Gwen::Key::Left;
|
||||||
|
break;
|
||||||
|
case B3G_RIGHT_ARROW:
|
||||||
|
key = Gwen::Key::Right;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B3G_UP_ARROW:
|
||||||
|
key = Gwen::Key::Up;
|
||||||
|
break;
|
||||||
|
case B3G_DOWN_ARROW:
|
||||||
|
key = Gwen::Key::Down;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bool bDown = (state == 1);
|
||||||
|
|
||||||
|
return m_data->pCanvas->InputKey(key, bDown);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GwenUserInterface::mouseButtonCallback(int button, int state, float x, float y)
|
||||||
|
{
|
||||||
|
bool handled = false;
|
||||||
|
if (m_data->pCanvas)
|
||||||
|
{
|
||||||
|
handled = m_data->pCanvas->InputMouseMoved(x,y,x, y);
|
||||||
|
|
||||||
|
if (button>=0)
|
||||||
|
{
|
||||||
|
handled = m_data->pCanvas->InputMouseButton(button,(bool)state);
|
||||||
|
if (handled)
|
||||||
|
{
|
||||||
|
//if (!state)
|
||||||
|
// return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
63
examples/ExampleBrowser/GwenGUISupport/gwenUserInterface.h
Normal file
63
examples/ExampleBrowser/GwenGUISupport/gwenUserInterface.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#ifndef _GWEN_USER_INTERFACE_H
|
||||||
|
#define _GWEN_USER_INTERFACE_H
|
||||||
|
|
||||||
|
struct GwenInternalData;
|
||||||
|
|
||||||
|
typedef void (*b3ComboBoxCallback) (int combobox, const char* item);
|
||||||
|
typedef void (*b3ToggleButtonCallback)(int button, int state);
|
||||||
|
typedef void (*b3FileOpenCallback)();
|
||||||
|
|
||||||
|
namespace Gwen
|
||||||
|
{
|
||||||
|
namespace Renderer
|
||||||
|
{
|
||||||
|
class Base;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
class GwenUserInterface
|
||||||
|
{
|
||||||
|
GwenInternalData* m_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
GwenUserInterface();
|
||||||
|
|
||||||
|
virtual ~GwenUserInterface();
|
||||||
|
|
||||||
|
void init(int width, int height,Gwen::Renderer::Base* gwenRenderer,float retinaScale);
|
||||||
|
void setFocus();
|
||||||
|
void forceUpdateScrollBars();
|
||||||
|
|
||||||
|
void draw(int width, int height);
|
||||||
|
|
||||||
|
void resize(int width, int height);
|
||||||
|
|
||||||
|
bool mouseMoveCallback( float x, float y);
|
||||||
|
bool mouseButtonCallback(int button, int state, float x, float y);
|
||||||
|
bool keyboardCallback(int key, int state);
|
||||||
|
|
||||||
|
|
||||||
|
void setToggleButtonCallback(b3ToggleButtonCallback callback);
|
||||||
|
b3ToggleButtonCallback getToggleButtonCallback();
|
||||||
|
|
||||||
|
void registerToggleButton(int buttonId, const char* name);
|
||||||
|
|
||||||
|
void setComboBoxCallback(b3ComboBoxCallback callback);
|
||||||
|
b3ComboBoxCallback getComboBoxCallback();
|
||||||
|
void registerComboBox(int buttonId, int numItems, const char** items, int startItem = 0);
|
||||||
|
|
||||||
|
void setStatusBarMessage(const char* message, bool isLeft=true);
|
||||||
|
|
||||||
|
void registerFileOpenCallback(b3FileOpenCallback callback);
|
||||||
|
|
||||||
|
GwenInternalData* getInternalData()
|
||||||
|
{
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //_GWEN_USER_INTERFACE_H
|
||||||
|
|
||||||
780
examples/ExampleBrowser/OpenGLExampleBrowser.cpp
Normal file
780
examples/ExampleBrowser/OpenGLExampleBrowser.cpp
Normal file
@@ -0,0 +1,780 @@
|
|||||||
|
#include "OpenGLExampleBrowser.h"
|
||||||
|
#include "LinearMath/btQuickprof.h"
|
||||||
|
#include "../OpenGLWindow/OpenGLInclude.h"
|
||||||
|
#include "../OpenGLWindow/SimpleOpenGL2App.h"
|
||||||
|
#include "../OpenGLWindow/SimpleOpenGL3App.h"
|
||||||
|
#include "../CommonInterfaces/CommonRenderInterface.h"
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include "OpenGLWindow/MacOpenGLWindow.h"
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "GL/glew.h"
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "../OpenGLWindow/Win32OpenGLWindow.h"
|
||||||
|
#else
|
||||||
|
//let's cross the fingers it is Linux/X11
|
||||||
|
#include "../OpenGLWindow/X11OpenGLWindow.h"
|
||||||
|
#endif //_WIN32
|
||||||
|
#endif//__APPLE__
|
||||||
|
#include "../ThirdPartyLibs/Gwen/Renderers/OpenGL_DebugFont.h"
|
||||||
|
|
||||||
|
#include "Bullet3Common/b3Vector3.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "GwenGUISupport/gwenInternalData.h"
|
||||||
|
#include "GwenGUISupport/gwenUserInterface.h"
|
||||||
|
#include "../Utils/b3Clock.h"
|
||||||
|
#include "GwenGUISupport/GwenParameterInterface.h"
|
||||||
|
#include "GwenGUISupport/GwenProfileWindow.h"
|
||||||
|
#include "GwenGUISupport/GwenTextureWindow.h"
|
||||||
|
#include "GwenGUISupport/GraphingTexture.h"
|
||||||
|
#include "../CommonInterfaces/Common2dCanvasInterface.h"
|
||||||
|
#include "../CommonInterfaces/ExampleInterface.h"
|
||||||
|
#include "Bullet3Common/b3CommandLineArgs.h"
|
||||||
|
#include "../OpenGLWindow/SimpleCamera.h"
|
||||||
|
#include "../OpenGLWindow/SimpleOpenGL2Renderer.h"
|
||||||
|
#include "ExampleEntries.h"
|
||||||
|
#include "OpenGLGuiHelper.h"
|
||||||
|
#include "LinearMath/btIDebugDraw.h"
|
||||||
|
CommonGraphicsApp* s_app=0;
|
||||||
|
|
||||||
|
b3gWindowInterface* s_window = 0;
|
||||||
|
CommonParameterInterface* s_parameterInterface=0;
|
||||||
|
CommonRenderInterface* s_instancingRenderer=0;
|
||||||
|
OpenGLGuiHelper* s_guiHelper=0;
|
||||||
|
|
||||||
|
#define DEMO_SELECTION_COMBOBOX 13
|
||||||
|
const char* startFileName = "bulletDemo.txt";
|
||||||
|
|
||||||
|
static GwenUserInterface* gui = 0;
|
||||||
|
static int sCurrentDemoIndex = 0;
|
||||||
|
static int sCurrentHightlighted = 0;
|
||||||
|
static ExampleInterface* sCurrentDemo = 0;
|
||||||
|
static b3AlignedObjectArray<const char*> allNames;
|
||||||
|
|
||||||
|
static class ExampleEntries* gAllExamples=0;
|
||||||
|
|
||||||
|
bool drawGUI=true;
|
||||||
|
extern bool useShadowMap;
|
||||||
|
static bool visualWireframe=false;
|
||||||
|
static bool renderVisualGeometry=true;
|
||||||
|
static bool renderGrid = true;
|
||||||
|
int gDebugDrawFlags = btIDebugDraw::DBG_DrawWireframe;
|
||||||
|
static bool pauseSimulation=false;
|
||||||
|
int midiBaseIndex = 176;
|
||||||
|
extern bool gDisableDeactivation;
|
||||||
|
|
||||||
|
//#include <float.h>
|
||||||
|
//unsigned int fp_control_state = _controlfp(_EM_INEXACT, _MCW_EM);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
b3KeyboardCallback prevKeyboardCallback = 0;
|
||||||
|
|
||||||
|
void MyKeyboardCallback(int key, int state)
|
||||||
|
{
|
||||||
|
|
||||||
|
//printf("key=%d, state=%d\n", key, state);
|
||||||
|
bool handled = false;
|
||||||
|
|
||||||
|
if (!handled && sCurrentDemo)
|
||||||
|
{
|
||||||
|
handled = sCurrentDemo->keyboardCallback(key,state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gui && !handled )
|
||||||
|
{
|
||||||
|
handled = gui->keyboardCallback(key, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//checkout: is it desired to ignore keys, if the demo already handles them?
|
||||||
|
//if (handled)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
if (key=='a' && state)
|
||||||
|
{
|
||||||
|
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawAabb;
|
||||||
|
}
|
||||||
|
if (key=='c' && state)
|
||||||
|
{
|
||||||
|
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawConstraints;
|
||||||
|
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawContactPoints;
|
||||||
|
}
|
||||||
|
if (key == 'd' && state)
|
||||||
|
{
|
||||||
|
gDebugDrawFlags ^= btIDebugDraw::DBG_NoDeactivation;
|
||||||
|
gDisableDeactivation = ((gDebugDrawFlags & btIDebugDraw::DBG_NoDeactivation) != 0);
|
||||||
|
}
|
||||||
|
if (key=='l' && state)
|
||||||
|
{
|
||||||
|
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawConstraintLimits;
|
||||||
|
}
|
||||||
|
if (key=='w' && state)
|
||||||
|
{
|
||||||
|
visualWireframe=!visualWireframe;
|
||||||
|
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawWireframe;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (key=='v' && state)
|
||||||
|
{
|
||||||
|
renderVisualGeometry = !renderVisualGeometry;
|
||||||
|
}
|
||||||
|
if (key=='g' && state)
|
||||||
|
{
|
||||||
|
renderGrid = !renderGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (key=='i' && state)
|
||||||
|
{
|
||||||
|
pauseSimulation = !pauseSimulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key=='s' && state)
|
||||||
|
{
|
||||||
|
useShadowMap=!useShadowMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key==B3G_ESCAPE && s_window)
|
||||||
|
{
|
||||||
|
s_window->setRequestExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevKeyboardCallback)
|
||||||
|
prevKeyboardCallback(key,state);
|
||||||
|
}
|
||||||
|
|
||||||
|
b3MouseMoveCallback prevMouseMoveCallback = 0;
|
||||||
|
static void MyMouseMoveCallback( float x, float y)
|
||||||
|
{
|
||||||
|
bool handled = false;
|
||||||
|
if (sCurrentDemo)
|
||||||
|
handled = sCurrentDemo->mouseMoveCallback(x,y);
|
||||||
|
if (!handled && gui)
|
||||||
|
handled = gui->mouseMoveCallback(x,y);
|
||||||
|
if (!handled)
|
||||||
|
{
|
||||||
|
if (prevMouseMoveCallback)
|
||||||
|
prevMouseMoveCallback(x,y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b3MouseButtonCallback prevMouseButtonCallback = 0;
|
||||||
|
|
||||||
|
static void MyMouseButtonCallback(int button, int state, float x, float y)
|
||||||
|
{
|
||||||
|
bool handled = false;
|
||||||
|
//try picking first
|
||||||
|
if (sCurrentDemo)
|
||||||
|
handled = sCurrentDemo->mouseButtonCallback(button,state,x,y);
|
||||||
|
|
||||||
|
if (!handled && gui)
|
||||||
|
handled = gui->mouseButtonCallback(button,state,x,y);
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
{
|
||||||
|
if (prevMouseButtonCallback )
|
||||||
|
prevMouseButtonCallback (button,state,x,y);
|
||||||
|
}
|
||||||
|
// b3DefaultMouseButtonCallback(button,state,x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void openURDFDemo(const char* filename)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if (sCurrentDemo)
|
||||||
|
{
|
||||||
|
sCurrentDemo->exitPhysics();
|
||||||
|
s_instancingRenderer->removeAllInstances();
|
||||||
|
delete sCurrentDemo;
|
||||||
|
sCurrentDemo=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_parameterInterface->removeAllParameters();
|
||||||
|
|
||||||
|
ImportUrdfSetup* physicsSetup = new ImportUrdfSetup();
|
||||||
|
physicsSetup->setFileName(filename);
|
||||||
|
|
||||||
|
sCurrentDemo = new BasicDemo(s_app, physicsSetup);
|
||||||
|
s_app->setUpAxis(2);
|
||||||
|
|
||||||
|
if (sCurrentDemo)
|
||||||
|
{
|
||||||
|
sCurrentDemo->initPhysics();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void selectDemo(int demoIndex)
|
||||||
|
{
|
||||||
|
sCurrentDemoIndex = demoIndex;
|
||||||
|
sCurrentHightlighted = demoIndex;
|
||||||
|
int numDemos = gAllExamples->getNumRegisteredExamples();
|
||||||
|
if (demoIndex>numDemos)
|
||||||
|
{
|
||||||
|
demoIndex = 0;
|
||||||
|
}
|
||||||
|
if (sCurrentDemo)
|
||||||
|
{
|
||||||
|
sCurrentDemo->exitPhysics();
|
||||||
|
s_instancingRenderer->removeAllInstances();
|
||||||
|
delete sCurrentDemo;
|
||||||
|
sCurrentDemo=0;
|
||||||
|
delete s_guiHelper;
|
||||||
|
s_guiHelper = 0;
|
||||||
|
}
|
||||||
|
ExampleInterface::CreateFunc* func = gAllExamples->getExampleCreateFunc(demoIndex);
|
||||||
|
if (func)
|
||||||
|
{
|
||||||
|
s_parameterInterface->removeAllParameters();
|
||||||
|
int option = gAllExamples->getExampleOption(demoIndex);
|
||||||
|
s_guiHelper= new OpenGLGuiHelper(s_app);
|
||||||
|
sCurrentDemo = (*func)(0,s_guiHelper, option);
|
||||||
|
if (sCurrentDemo)
|
||||||
|
{
|
||||||
|
if (gui)
|
||||||
|
{
|
||||||
|
bool isLeft = true;
|
||||||
|
gui->setStatusBarMessage("Status: OK", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
sCurrentDemo->initPhysics();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
static void saveCurrentDemoEntry(int currentEntry,const char* startFileName)
|
||||||
|
{
|
||||||
|
FILE* f = fopen(startFileName,"w");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
fprintf(f,"%d\n",currentEntry);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int loadCurrentDemoEntry(const char* startFileName)
|
||||||
|
{
|
||||||
|
int currentEntry= 0;
|
||||||
|
FILE* f = fopen(startFileName,"r");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
result = fscanf(f,"%d",¤tEntry);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return currentEntry;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void MyComboBoxCallback(int comboId, const char* item)
|
||||||
|
{
|
||||||
|
//printf("comboId = %d, item = %s\n",comboId, item);
|
||||||
|
if (comboId==DEMO_SELECTION_COMBOBOX)
|
||||||
|
{
|
||||||
|
//find selected item
|
||||||
|
for (int i=0;i<allNames.size();i++)
|
||||||
|
{
|
||||||
|
if (strcmp(item,allNames[i])==0)
|
||||||
|
{
|
||||||
|
selectDemo(i);
|
||||||
|
saveCurrentDemoEntry(sCurrentDemoIndex,startFileName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void MyStatusBarPrintf(const char* msg)
|
||||||
|
{
|
||||||
|
printf("b3Printf: %s\n", msg);
|
||||||
|
if (gui)
|
||||||
|
{
|
||||||
|
bool isLeft = true;
|
||||||
|
gui->setStatusBarMessage(msg,isLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MyStatusBarWarning(const char* msg)
|
||||||
|
{
|
||||||
|
printf("Warning: %s\n", msg);
|
||||||
|
if (gui)
|
||||||
|
{
|
||||||
|
bool isLeft = false;
|
||||||
|
gui->setStatusBarMessage(msg,isLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyMenuItemHander :public Gwen::Event::Handler
|
||||||
|
{
|
||||||
|
int m_buttonId;
|
||||||
|
|
||||||
|
MyMenuItemHander( int buttonId)
|
||||||
|
:m_buttonId(buttonId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void onButtonA(Gwen::Controls::Base* pControl)
|
||||||
|
{
|
||||||
|
//const Gwen::String& name = pControl->GetName();
|
||||||
|
Gwen::Controls::TreeNode* node = (Gwen::Controls::TreeNode*)pControl;
|
||||||
|
// Gwen::Controls::Label* l = node->GetButton();
|
||||||
|
|
||||||
|
Gwen::UnicodeString la = node->GetButton()->GetText();// node->GetButton()->GetName();// GetText();
|
||||||
|
Gwen::String laa = Gwen::Utility::UnicodeToString(la);
|
||||||
|
// const char* ha = laa.c_str();
|
||||||
|
|
||||||
|
//printf("selected %s\n", ha);
|
||||||
|
//int dep = but->IsDepressed();
|
||||||
|
//int tog = but->GetToggleState();
|
||||||
|
// if (m_data->m_toggleButtonCallback)
|
||||||
|
// (*m_data->m_toggleButtonCallback)(m_buttonId, tog);
|
||||||
|
}
|
||||||
|
void onButtonB(Gwen::Controls::Base* pControl)
|
||||||
|
{
|
||||||
|
Gwen::Controls::Label* label = (Gwen::Controls::Label*) pControl;
|
||||||
|
Gwen::UnicodeString la = label->GetText();// node->GetButton()->GetName();// GetText();
|
||||||
|
Gwen::String laa = Gwen::Utility::UnicodeToString(la);
|
||||||
|
//const char* ha = laa.c_str();
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
|
||||||
|
selectDemo(sCurrentHightlighted);
|
||||||
|
saveCurrentDemoEntry(sCurrentDemoIndex, startFileName);
|
||||||
|
}
|
||||||
|
void onButtonC(Gwen::Controls::Base* pControl)
|
||||||
|
{
|
||||||
|
// Gwen::Controls::Label* label = (Gwen::Controls::Label*) pControl;
|
||||||
|
// Gwen::UnicodeString la = label->GetText();// node->GetButton()->GetName();// GetText();
|
||||||
|
// Gwen::String laa = Gwen::Utility::UnicodeToString(la);
|
||||||
|
// const char* ha = laa.c_str();
|
||||||
|
|
||||||
|
|
||||||
|
// printf("onButtonC ! %s\n", ha);
|
||||||
|
}
|
||||||
|
void onButtonD(Gwen::Controls::Base* pControl)
|
||||||
|
{
|
||||||
|
/* Gwen::Controls::Label* label = (Gwen::Controls::Label*) pControl;
|
||||||
|
Gwen::UnicodeString la = label->GetText();// node->GetButton()->GetName();// GetText();
|
||||||
|
Gwen::String laa = Gwen::Utility::UnicodeToString(la);
|
||||||
|
const char* ha = laa.c_str();
|
||||||
|
*/
|
||||||
|
|
||||||
|
// printf("onKeyReturn ! \n");
|
||||||
|
selectDemo(sCurrentHightlighted);
|
||||||
|
saveCurrentDemoEntry(sCurrentDemoIndex, startFileName);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void onButtonE(Gwen::Controls::Base* pControl)
|
||||||
|
{
|
||||||
|
// printf("select %d\n",m_buttonId);
|
||||||
|
sCurrentHightlighted = m_buttonId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onButtonF(Gwen::Controls::Base* pControl)
|
||||||
|
{
|
||||||
|
//printf("selection changed!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void onButtonG(Gwen::Controls::Base* pControl)
|
||||||
|
{
|
||||||
|
//printf("onButtonG !\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
#include "Bullet3Common/b3HashMap.h"
|
||||||
|
|
||||||
|
struct GL3TexLoader : public MyTextureLoader
|
||||||
|
{
|
||||||
|
b3HashMap<b3HashString,GLint> m_hashMap;
|
||||||
|
|
||||||
|
virtual void LoadTexture( Gwen::Texture* pTexture )
|
||||||
|
{
|
||||||
|
Gwen::String namestr = pTexture->name.Get();
|
||||||
|
const char* n = namestr.c_str();
|
||||||
|
GLint* texIdPtr = m_hashMap[n];
|
||||||
|
if (texIdPtr)
|
||||||
|
{
|
||||||
|
pTexture->m_intData = *texIdPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void FreeTexture( Gwen::Texture* pTexture )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void fileOpenCallback()
|
||||||
|
{
|
||||||
|
|
||||||
|
char filename[1024];
|
||||||
|
int len = s_window->fileOpenDialog(filename,1024);
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
//todo(erwincoumans) check if it is actually URDF
|
||||||
|
//printf("file open:%s\n", filename);
|
||||||
|
openURDFDemo(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_GRAPH_WINDOWS 5
|
||||||
|
|
||||||
|
struct QuickCanvas : public Common2dCanvasInterface
|
||||||
|
{
|
||||||
|
GL3TexLoader* m_myTexLoader;
|
||||||
|
|
||||||
|
MyGraphWindow* m_gw[MAX_GRAPH_WINDOWS];
|
||||||
|
GraphingTexture* m_gt[MAX_GRAPH_WINDOWS];
|
||||||
|
int m_curNumGraphWindows;
|
||||||
|
|
||||||
|
QuickCanvas(GL3TexLoader* myTexLoader)
|
||||||
|
:m_myTexLoader(myTexLoader),
|
||||||
|
m_curNumGraphWindows(0)
|
||||||
|
{
|
||||||
|
for (int i=0;i<MAX_GRAPH_WINDOWS;i++)
|
||||||
|
{
|
||||||
|
m_gw[i] = 0;
|
||||||
|
m_gt[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual ~QuickCanvas() {}
|
||||||
|
virtual int createCanvas(const char* canvasName, int width, int height)
|
||||||
|
{
|
||||||
|
if (m_curNumGraphWindows<MAX_GRAPH_WINDOWS)
|
||||||
|
{
|
||||||
|
//find a slot
|
||||||
|
int slot = 0;//hardcoded for now
|
||||||
|
m_curNumGraphWindows++;
|
||||||
|
|
||||||
|
MyGraphInput input(gui->getInternalData());
|
||||||
|
input.m_width=width;
|
||||||
|
input.m_height=height;
|
||||||
|
input.m_xPos = 300;
|
||||||
|
input.m_yPos = height-input.m_height;
|
||||||
|
input.m_name=canvasName;
|
||||||
|
input.m_texName = canvasName;
|
||||||
|
m_gt[slot] = new GraphingTexture;
|
||||||
|
m_gt[slot]->create(width,height);
|
||||||
|
int texId = m_gt[slot]->getTextureId();
|
||||||
|
m_myTexLoader->m_hashMap.insert(canvasName, texId);
|
||||||
|
m_gw[slot] = setupTextureWindow(input);
|
||||||
|
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
virtual void destroyCanvas(int canvasId)
|
||||||
|
{
|
||||||
|
btAssert(canvasId==0);//hardcoded to zero for now, only a single canvas
|
||||||
|
btAssert(m_curNumGraphWindows==1);
|
||||||
|
destroyTextureWindow(m_gw[canvasId]);
|
||||||
|
m_curNumGraphWindows--;
|
||||||
|
}
|
||||||
|
virtual void setPixel(int canvasId, int x, int y, unsigned char red, unsigned char green,unsigned char blue, unsigned char alpha)
|
||||||
|
{
|
||||||
|
btAssert(canvasId==0);//hardcoded
|
||||||
|
btAssert(m_curNumGraphWindows==1);
|
||||||
|
m_gt[canvasId]->setPixel(x,y,red,green,blue,alpha);
|
||||||
|
}
|
||||||
|
virtual void refreshImageData(int canvasId)
|
||||||
|
{
|
||||||
|
m_gt[canvasId]->uploadImageData();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
OpenGLExampleBrowser::OpenGLExampleBrowser(class ExampleEntries* examples)
|
||||||
|
{
|
||||||
|
gAllExamples = examples;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLExampleBrowser::~OpenGLExampleBrowser()
|
||||||
|
{
|
||||||
|
gAllExamples = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "EmptyExample.h"
|
||||||
|
|
||||||
|
bool OpenGLExampleBrowser::init(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
b3CommandLineArgs args(argc,argv);
|
||||||
|
|
||||||
|
int width = 1024;
|
||||||
|
int height=768;
|
||||||
|
|
||||||
|
SimpleOpenGL3App* simpleApp=0;
|
||||||
|
bool useOpenGL2=false;
|
||||||
|
if (useOpenGL2)
|
||||||
|
{
|
||||||
|
s_app = new SimpleOpenGL2App("AllBullet2Demos",width,height);
|
||||||
|
s_app->m_renderer = new SimpleOpenGL2Renderer(width,height);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
simpleApp = new SimpleOpenGL3App("AllBullet2Demos",width,height);
|
||||||
|
s_app = simpleApp;
|
||||||
|
}
|
||||||
|
char* gVideoFileName = 0;
|
||||||
|
args.GetCmdLineArgument("mp4",gVideoFileName);
|
||||||
|
|
||||||
|
if (gVideoFileName)
|
||||||
|
simpleApp->dumpFramesToVideo(gVideoFileName);
|
||||||
|
|
||||||
|
|
||||||
|
s_instancingRenderer = s_app->m_renderer;
|
||||||
|
s_window = s_app->m_window;
|
||||||
|
prevMouseMoveCallback = s_window->getMouseMoveCallback();
|
||||||
|
s_window->setMouseMoveCallback(MyMouseMoveCallback);
|
||||||
|
|
||||||
|
prevMouseButtonCallback = s_window->getMouseButtonCallback();
|
||||||
|
s_window->setMouseButtonCallback(MyMouseButtonCallback);
|
||||||
|
prevKeyboardCallback = s_window->getKeyboardCallback();
|
||||||
|
s_window->setKeyboardCallback(MyKeyboardCallback);
|
||||||
|
|
||||||
|
s_app->m_renderer->setCameraDistance(13);
|
||||||
|
s_app->m_renderer->setCameraPitch(0);
|
||||||
|
s_app->m_renderer->setCameraTargetPosition(0,0,0);
|
||||||
|
|
||||||
|
b3SetCustomWarningMessageFunc(MyStatusBarWarning);
|
||||||
|
b3SetCustomPrintfFunc(MyStatusBarPrintf);
|
||||||
|
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
gui = new GwenUserInterface;
|
||||||
|
GL3TexLoader* myTexLoader = new GL3TexLoader;
|
||||||
|
|
||||||
|
Gwen::Renderer::Base* gwenRenderer = 0;
|
||||||
|
if (useOpenGL2)
|
||||||
|
{
|
||||||
|
gwenRenderer = new Gwen::Renderer::OpenGL_DebugFont();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
sth_stash* fontstash=simpleApp->getFontStash();
|
||||||
|
gwenRenderer = new GwenOpenGL3CoreRenderer(simpleApp->m_primRenderer,fontstash,width,height,s_window->getRetinaScale(),myTexLoader);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
|
gui->init(width,height,gwenRenderer,s_window->getRetinaScale());
|
||||||
|
// gui->getInternalData()->m_explorerPage
|
||||||
|
Gwen::Controls::TreeControl* tree = gui->getInternalData()->m_explorerTreeCtrl;
|
||||||
|
|
||||||
|
|
||||||
|
//gui->getInternalData()->pRenderer->setTextureLoader(myTexLoader);
|
||||||
|
|
||||||
|
|
||||||
|
MyProfileWindow* profWindow = setupProfileWindow(gui->getInternalData());
|
||||||
|
profileWindowSetVisible(profWindow,false);
|
||||||
|
gui->setFocus();
|
||||||
|
|
||||||
|
s_parameterInterface = s_app->m_parameterInterface = new GwenParameterInterface(gui->getInternalData());
|
||||||
|
s_app->m_2dCanvasInterface = new QuickCanvas(myTexLoader);
|
||||||
|
|
||||||
|
|
||||||
|
///add some demos to the gAllExamples
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int numDemos = gAllExamples->getNumRegisteredExamples();
|
||||||
|
|
||||||
|
//char nodeText[1024];
|
||||||
|
//int curDemo = 0;
|
||||||
|
int selectedDemo = loadCurrentDemoEntry(startFileName);
|
||||||
|
Gwen::Controls::TreeNode* curNode = tree;
|
||||||
|
MyMenuItemHander* handler2 = new MyMenuItemHander(-1);
|
||||||
|
|
||||||
|
tree->onReturnKeyDown.Add(handler2, &MyMenuItemHander::onButtonD);
|
||||||
|
int firstAvailableDemoIndex=-1;
|
||||||
|
Gwen::Controls::TreeNode* firstNode=0;
|
||||||
|
|
||||||
|
for (int d = 0; d<numDemos; d++)
|
||||||
|
{
|
||||||
|
// sprintf(nodeText, "Node %d", i);
|
||||||
|
Gwen::UnicodeString nodeUText = Gwen::Utility::StringToUnicode(gAllExamples->getExampleName(d));
|
||||||
|
if (gAllExamples->getExampleCreateFunc(d))//was test for gAllExamples[d].m_menuLevel==1
|
||||||
|
{
|
||||||
|
Gwen::Controls::TreeNode* pNode = curNode->AddNode(nodeUText);
|
||||||
|
|
||||||
|
if (firstAvailableDemoIndex<0)
|
||||||
|
{
|
||||||
|
firstAvailableDemoIndex = d;
|
||||||
|
firstNode = pNode;
|
||||||
|
}
|
||||||
|
if (d == selectedDemo)
|
||||||
|
{
|
||||||
|
pNode->SetSelected(true);
|
||||||
|
tree->ExpandAll();
|
||||||
|
selectDemo(d);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
MyMenuItemHander* handler = new MyMenuItemHander(d);
|
||||||
|
pNode->onNamePress.Add(handler, &MyMenuItemHander::onButtonA);
|
||||||
|
pNode->GetButton()->onDoubleClick.Add(handler, &MyMenuItemHander::onButtonB);
|
||||||
|
pNode->GetButton()->onDown.Add(handler, &MyMenuItemHander::onButtonC);
|
||||||
|
pNode->onSelect.Add(handler, &MyMenuItemHander::onButtonE);
|
||||||
|
pNode->onReturnKeyDown.Add(handler, &MyMenuItemHander::onButtonG);
|
||||||
|
pNode->onSelectChange.Add(handler, &MyMenuItemHander::onButtonF);
|
||||||
|
// pNode->onKeyReturn.Add(handler, &MyMenuItemHander::onButtonD);
|
||||||
|
// pNode->GetButton()->onKeyboardReturn.Add(handler, &MyMenuItemHander::onButtonD);
|
||||||
|
// pNode->onNamePress.Add(handler, &MyMenuItemHander::onButtonD);
|
||||||
|
// pNode->onKeyboardPressed.Add(handler, &MyMenuItemHander::onButtonD);
|
||||||
|
// pNode->OnKeyPress
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curNode = tree->AddNode(nodeUText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sCurrentDemo==0)
|
||||||
|
{
|
||||||
|
if (firstAvailableDemoIndex>=0)
|
||||||
|
{
|
||||||
|
firstNode->SetSelected(true);
|
||||||
|
tree->ExpandAll();
|
||||||
|
selectDemo(firstAvailableDemoIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
btAssert(sCurrentDemo!=0);
|
||||||
|
if (sCurrentDemo==0)
|
||||||
|
{
|
||||||
|
printf("Error, no demo/example\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
gui->registerFileOpenCallback(fileOpenCallback);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ExampleInterface* OpenGLExampleBrowser::getCurrentExample()
|
||||||
|
{
|
||||||
|
btAssert(sCurrentDemo);
|
||||||
|
return sCurrentDemo;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenGLExampleBrowser::requestedExit()
|
||||||
|
{
|
||||||
|
return s_window->requestedExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLExampleBrowser::update(float deltaTime)
|
||||||
|
{
|
||||||
|
/* if (sCurrentDemo)
|
||||||
|
{
|
||||||
|
sCurrentDemo->stepSimulation(deltaTime);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
s_instancingRenderer->init();
|
||||||
|
DrawGridData dg;
|
||||||
|
dg.upAxis = s_app->getUpAxis();
|
||||||
|
|
||||||
|
{
|
||||||
|
BT_PROFILE("Update Camera");
|
||||||
|
s_instancingRenderer->updateCamera(dg.upAxis);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderGrid)
|
||||||
|
{
|
||||||
|
BT_PROFILE("Draw Grid");
|
||||||
|
s_app->drawGrid(dg);
|
||||||
|
}
|
||||||
|
static int frameCount = 0;
|
||||||
|
frameCount++;
|
||||||
|
|
||||||
|
if (0)
|
||||||
|
{
|
||||||
|
BT_PROFILE("Draw frame counter");
|
||||||
|
char bla[1024];
|
||||||
|
sprintf(bla,"Frame %d", frameCount);
|
||||||
|
s_app->drawText(bla,10,10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sCurrentDemo)
|
||||||
|
{
|
||||||
|
if (!pauseSimulation)
|
||||||
|
{
|
||||||
|
//printf("---------------------------------------------------\n");
|
||||||
|
//printf("Framecount = %d\n",frameCount);
|
||||||
|
|
||||||
|
sCurrentDemo->stepSimulation(deltaTime);//1./60.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderVisualGeometry)
|
||||||
|
{
|
||||||
|
if (visualWireframe)
|
||||||
|
{
|
||||||
|
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
||||||
|
}
|
||||||
|
BT_PROFILE("Render Scene");
|
||||||
|
sCurrentDemo->renderScene();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||||
|
sCurrentDemo->physicsDebugDraw(gDebugDrawFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int toggle = 1;
|
||||||
|
if (1)
|
||||||
|
{
|
||||||
|
//if (!pauseSimulation)
|
||||||
|
// processProfileData(profWindow,false);
|
||||||
|
|
||||||
|
{
|
||||||
|
// if (useOpenGL2)
|
||||||
|
//{
|
||||||
|
// saveOpenGLState(width,height);
|
||||||
|
//}
|
||||||
|
BT_PROFILE("Draw Gwen GUI");
|
||||||
|
gui->draw(s_instancingRenderer->getScreenWidth(),s_instancingRenderer->getScreenHeight());
|
||||||
|
//if (useOpenGL2)
|
||||||
|
//{
|
||||||
|
// restoreOpenGLState();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toggle=1-toggle;
|
||||||
|
{
|
||||||
|
BT_PROFILE("Sync Parameters");
|
||||||
|
s_parameterInterface->syncParameters();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
BT_PROFILE("Swap Buffers");
|
||||||
|
s_app->swapBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
gui->forceUpdateScrollBars();
|
||||||
|
|
||||||
|
}
|
||||||
23
examples/ExampleBrowser/OpenGLExampleBrowser.h
Normal file
23
examples/ExampleBrowser/OpenGLExampleBrowser.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef OPENGL_BROWSER_GUI_H
|
||||||
|
#define OPENGL_BROWSER_GUI_H
|
||||||
|
|
||||||
|
#include "ExampleBrowserInterface.h"
|
||||||
|
|
||||||
|
class OpenGLExampleBrowser : public ExampleBrowserInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
OpenGLExampleBrowser(class ExampleEntries* examples);
|
||||||
|
virtual ~OpenGLExampleBrowser();
|
||||||
|
|
||||||
|
virtual ExampleInterface* getCurrentExample();
|
||||||
|
|
||||||
|
virtual bool init(int argc, char* argv[]);
|
||||||
|
|
||||||
|
virtual void update(float deltaTime);
|
||||||
|
|
||||||
|
virtual bool requestedExit();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //OPENGL_BROWSER_GUI_H
|
||||||
518
examples/ExampleBrowser/OpenGLGuiHelper.cpp
Normal file
518
examples/ExampleBrowser/OpenGLGuiHelper.cpp
Normal file
@@ -0,0 +1,518 @@
|
|||||||
|
#include "OpenGLGuiHelper.h"
|
||||||
|
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/CommonGraphicsAppInterface.h"
|
||||||
|
#include "../CommonInterfaces/CommonRenderInterface.h"
|
||||||
|
#include "Bullet3Common/b3Scalar.h"
|
||||||
|
|
||||||
|
#include "BulletCollision/CollisionShapes/btShapeHull.h"//to create a tesselation of a generic btConvexShape
|
||||||
|
|
||||||
|
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define BT_LINE_BATCH_SIZE 512
|
||||||
|
|
||||||
|
struct MyDebugVec3
|
||||||
|
{
|
||||||
|
MyDebugVec3(const btVector3& org)
|
||||||
|
:x(org.x()),
|
||||||
|
y(org.y()),
|
||||||
|
z(org.z())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
};
|
||||||
|
class MyDebugDrawer : public btIDebugDraw
|
||||||
|
{
|
||||||
|
CommonGraphicsApp* m_glApp;
|
||||||
|
int m_debugMode;
|
||||||
|
|
||||||
|
btAlignedObjectArray<MyDebugVec3> m_linePoints;
|
||||||
|
btAlignedObjectArray<unsigned int> m_lineIndices;
|
||||||
|
btVector3 m_currentLineColor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MyDebugDrawer(CommonGraphicsApp* app)
|
||||||
|
: m_glApp(app)
|
||||||
|
,m_debugMode(btIDebugDraw::DBG_DrawWireframe|btIDebugDraw::DBG_DrawAabb),
|
||||||
|
m_currentLineColor(-1,-1,-1)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
virtual void drawLine(const btVector3& from1,const btVector3& to1,const btVector3& color1)
|
||||||
|
{
|
||||||
|
//float from[4] = {from1[0],from1[1],from1[2],from1[3]};
|
||||||
|
//float to[4] = {to1[0],to1[1],to1[2],to1[3]};
|
||||||
|
//float color[4] = {color1[0],color1[1],color1[2],color1[3]};
|
||||||
|
//m_glApp->m_instancingRenderer->drawLine(from,to,color);
|
||||||
|
if (m_currentLineColor!=color1 || m_linePoints.size() >= BT_LINE_BATCH_SIZE)
|
||||||
|
{
|
||||||
|
flushLines();
|
||||||
|
m_currentLineColor = color1;
|
||||||
|
}
|
||||||
|
MyDebugVec3 from(from1);
|
||||||
|
MyDebugVec3 to(to1);
|
||||||
|
|
||||||
|
m_linePoints.push_back(from);
|
||||||
|
m_linePoints.push_back(to);
|
||||||
|
|
||||||
|
m_lineIndices.push_back(m_lineIndices.size());
|
||||||
|
m_lineIndices.push_back(m_lineIndices.size());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)
|
||||||
|
{
|
||||||
|
drawLine(PointOnB,PointOnB+normalOnB,color);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void reportErrorWarning(const char* warningString)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void draw3dText(const btVector3& location,const char* textString)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setDebugMode(int debugMode)
|
||||||
|
{
|
||||||
|
m_debugMode = debugMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getDebugMode() const
|
||||||
|
{
|
||||||
|
return m_debugMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void flushLines()
|
||||||
|
{
|
||||||
|
int sz = m_linePoints.size();
|
||||||
|
if (sz)
|
||||||
|
{
|
||||||
|
float debugColor[4];
|
||||||
|
debugColor[0] = m_currentLineColor.x();
|
||||||
|
debugColor[1] = m_currentLineColor.y();
|
||||||
|
debugColor[2] = m_currentLineColor.z();
|
||||||
|
debugColor[3] = 1.f;
|
||||||
|
m_glApp->m_renderer->drawLines(&m_linePoints[0].x,debugColor,
|
||||||
|
m_linePoints.size(),sizeof(MyDebugVec3),
|
||||||
|
&m_lineIndices[0],
|
||||||
|
m_lineIndices.size(),
|
||||||
|
1);
|
||||||
|
m_linePoints.clear();
|
||||||
|
m_lineIndices.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static btVector4 sColors[4] =
|
||||||
|
{
|
||||||
|
btVector4(0.3,0.3,1,1),
|
||||||
|
btVector4(1,0,0,1),
|
||||||
|
btVector4(0,1,0,1),
|
||||||
|
btVector4(0,1,1,1),
|
||||||
|
//btVector4(1,1,0,1),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct OpenGLGuiHelperInternalData
|
||||||
|
{
|
||||||
|
struct CommonGraphicsApp* m_glApp;
|
||||||
|
class MyDebugDrawer* m_debugDraw;
|
||||||
|
int m_curColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OpenGLGuiHelper::OpenGLGuiHelper(CommonGraphicsApp* glApp)
|
||||||
|
{
|
||||||
|
m_data = new OpenGLGuiHelperInternalData;
|
||||||
|
m_data->m_glApp = glApp;
|
||||||
|
m_data->m_debugDraw = 0;
|
||||||
|
m_data->m_curColor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLGuiHelper::~OpenGLGuiHelper()
|
||||||
|
{
|
||||||
|
delete m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CommonRenderInterface* OpenGLGuiHelper::getRenderInterface()
|
||||||
|
{
|
||||||
|
return m_data->m_glApp->m_renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLGuiHelper::createRigidBodyGraphicsObject(btRigidBody* body, const btVector3& color)
|
||||||
|
{
|
||||||
|
createCollisionObjectGraphicsObject(body,color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLGuiHelper::createCollisionObjectGraphicsObject(btCollisionObject* body, const btVector3& color)
|
||||||
|
{
|
||||||
|
btCollisionShape* shape = body->getCollisionShape();
|
||||||
|
btTransform startTransform = body->getWorldTransform();
|
||||||
|
int graphicsShapeId = shape->getUserIndex();
|
||||||
|
if (graphicsShapeId>=0)
|
||||||
|
{
|
||||||
|
// btAssert(graphicsShapeId >= 0);
|
||||||
|
btVector3 localScaling = shape->getLocalScaling();
|
||||||
|
int graphicsInstanceId = m_data->m_glApp->m_renderer->registerGraphicsInstance(graphicsShapeId, startTransform.getOrigin(), startTransform.getRotation(), color, localScaling);
|
||||||
|
body->setUserIndex(graphicsInstanceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenGLGuiHelper::registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices)
|
||||||
|
{
|
||||||
|
int shapeId = m_data->m_glApp->m_renderer->registerShape(vertices, numvertices,indices,numIndices);
|
||||||
|
return shapeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenGLGuiHelper::registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling)
|
||||||
|
{
|
||||||
|
return m_data->m_glApp->m_renderer->registerGraphicsInstance(shapeIndex,position,quaternion,color,scaling);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createCollisionShapeGraphicsObjectInternal(btCollisionShape* collisionShape, const btTransform& parentTransform, btAlignedObjectArray<GLInstanceVertex>& verticesOut, btAlignedObjectArray<int>& indicesOut)
|
||||||
|
{
|
||||||
|
//todo: support all collision shape types
|
||||||
|
switch (collisionShape->getShapeType())
|
||||||
|
{
|
||||||
|
case STATIC_PLANE_PROXYTYPE:
|
||||||
|
{
|
||||||
|
//draw a box, oriented along the plane normal
|
||||||
|
const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(collisionShape);
|
||||||
|
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 verts[4];
|
||||||
|
|
||||||
|
verts[0] = planeOrigin + vec0*vecLen + vec1*vecLen;
|
||||||
|
verts[1] = planeOrigin - vec0*vecLen + vec1*vecLen;
|
||||||
|
verts[2] = planeOrigin - vec0*vecLen - vec1*vecLen;
|
||||||
|
verts[3] = planeOrigin + vec0*vecLen - vec1*vecLen;
|
||||||
|
|
||||||
|
int startIndex = verticesOut.size();
|
||||||
|
indicesOut.push_back(startIndex+0);
|
||||||
|
indicesOut.push_back(startIndex+1);
|
||||||
|
indicesOut.push_back(startIndex+2);
|
||||||
|
indicesOut.push_back(startIndex+0);
|
||||||
|
indicesOut.push_back(startIndex+2);
|
||||||
|
indicesOut.push_back(startIndex+3);
|
||||||
|
|
||||||
|
btVector3 triNormal = parentTransform.getBasis()*planeNormal;
|
||||||
|
|
||||||
|
|
||||||
|
for (int i=0;i<4;i++)
|
||||||
|
{
|
||||||
|
GLInstanceVertex vtx;
|
||||||
|
btVector3 pos =parentTransform*verts[i];
|
||||||
|
vtx.xyzw[0] = pos.x();
|
||||||
|
vtx.xyzw[1] = pos.y();
|
||||||
|
vtx.xyzw[2] = pos.z();
|
||||||
|
vtx.xyzw[3] = 0.f;
|
||||||
|
|
||||||
|
vtx.normal[0] =triNormal.x();
|
||||||
|
vtx.normal[1] =triNormal.y();
|
||||||
|
vtx.normal[2] =triNormal.z();
|
||||||
|
|
||||||
|
vtx.uv[0] = 0.5f;
|
||||||
|
vtx.uv[1] = 0.5f;
|
||||||
|
verticesOut.push_back(vtx);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TRIANGLE_MESH_SHAPE_PROXYTYPE:
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*) collisionShape;
|
||||||
|
btVector3 trimeshScaling = trimesh->getLocalScaling();
|
||||||
|
btStridingMeshInterface* meshInterface = trimesh->getMeshInterface();
|
||||||
|
btAlignedObjectArray<btVector3> vertices;
|
||||||
|
btAlignedObjectArray<int> indices;
|
||||||
|
|
||||||
|
for (int partId=0;partId<meshInterface->getNumSubParts();partId++)
|
||||||
|
{
|
||||||
|
|
||||||
|
const unsigned char *vertexbase = 0;
|
||||||
|
int numverts = 0;
|
||||||
|
PHY_ScalarType type = PHY_INTEGER;
|
||||||
|
int stride = 0;
|
||||||
|
const unsigned char *indexbase = 0;
|
||||||
|
int indexstride = 0;
|
||||||
|
int numfaces = 0;
|
||||||
|
PHY_ScalarType indicestype = PHY_INTEGER;
|
||||||
|
//PHY_ScalarType indexType=0;
|
||||||
|
|
||||||
|
btVector3 triangleVerts[3];
|
||||||
|
meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,partId);
|
||||||
|
btVector3 aabbMin,aabbMax;
|
||||||
|
|
||||||
|
for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++)
|
||||||
|
{
|
||||||
|
unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride);
|
||||||
|
|
||||||
|
for (int j=2;j>=0;j--)
|
||||||
|
{
|
||||||
|
|
||||||
|
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
|
||||||
|
if (type == PHY_FLOAT)
|
||||||
|
{
|
||||||
|
float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
|
||||||
|
triangleVerts[j] = btVector3(
|
||||||
|
graphicsbase[0]*trimeshScaling.getX(),
|
||||||
|
graphicsbase[1]*trimeshScaling.getY(),
|
||||||
|
graphicsbase[2]*trimeshScaling.getZ());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
|
||||||
|
triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*trimeshScaling.getX()),
|
||||||
|
btScalar(graphicsbase[1]*trimeshScaling.getY()),
|
||||||
|
btScalar(graphicsbase[2]*trimeshScaling.getZ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indices.push_back(vertices.size());
|
||||||
|
vertices.push_back(triangleVerts[0]);
|
||||||
|
indices.push_back(vertices.size());
|
||||||
|
vertices.push_back(triangleVerts[1]);
|
||||||
|
indices.push_back(vertices.size());
|
||||||
|
vertices.push_back(triangleVerts[2]);
|
||||||
|
|
||||||
|
btVector3 triNormal = (triangleVerts[1]-triangleVerts[0]).cross(triangleVerts[2]-triangleVerts[0]);
|
||||||
|
triNormal.normalize();
|
||||||
|
|
||||||
|
for (int v=0;v<3;v++)
|
||||||
|
{
|
||||||
|
GLInstanceVertex vtx;
|
||||||
|
btVector3 pos =parentTransform*triangleVerts[v];
|
||||||
|
vtx.xyzw[0] = pos.x();
|
||||||
|
vtx.xyzw[1] = pos.y();
|
||||||
|
vtx.xyzw[2] = pos.z();
|
||||||
|
vtx.xyzw[3] = 0.f;
|
||||||
|
|
||||||
|
|
||||||
|
vtx.normal[0] =triNormal.x();
|
||||||
|
vtx.normal[1] =triNormal.y();
|
||||||
|
vtx.normal[2] =triNormal.z();
|
||||||
|
|
||||||
|
vtx.uv[0] = 0.5f;
|
||||||
|
vtx.uv[1] = 0.5f;
|
||||||
|
|
||||||
|
indicesOut.push_back(verticesOut.size());
|
||||||
|
verticesOut.push_back(vtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (collisionShape->isConvex())
|
||||||
|
{
|
||||||
|
btConvexShape* convex = (btConvexShape*)collisionShape;
|
||||||
|
{
|
||||||
|
btShapeHull* hull = new btShapeHull(convex);
|
||||||
|
hull->buildHull(0.0);
|
||||||
|
|
||||||
|
{
|
||||||
|
//int strideInBytes = 9*sizeof(float);
|
||||||
|
//int numVertices = hull->numVertices();
|
||||||
|
//int numIndices =hull->numIndices();
|
||||||
|
|
||||||
|
for (int t=0;t<hull->numTriangles();t++)
|
||||||
|
{
|
||||||
|
|
||||||
|
btVector3 triNormal;
|
||||||
|
|
||||||
|
int index0 = hull->getIndexPointer()[t*3+0];
|
||||||
|
int index1 = hull->getIndexPointer()[t*3+1];
|
||||||
|
int index2 = hull->getIndexPointer()[t*3+2];
|
||||||
|
btVector3 pos0 =parentTransform*hull->getVertexPointer()[index0];
|
||||||
|
btVector3 pos1 =parentTransform*hull->getVertexPointer()[index1];
|
||||||
|
btVector3 pos2 =parentTransform*hull->getVertexPointer()[index2];
|
||||||
|
triNormal = (pos1-pos0).cross(pos2-pos0);
|
||||||
|
triNormal.normalize();
|
||||||
|
|
||||||
|
for (int v=0;v<3;v++)
|
||||||
|
{
|
||||||
|
int index = hull->getIndexPointer()[t*3+v];
|
||||||
|
GLInstanceVertex vtx;
|
||||||
|
btVector3 pos =parentTransform*hull->getVertexPointer()[index];
|
||||||
|
vtx.xyzw[0] = pos.x();
|
||||||
|
vtx.xyzw[1] = pos.y();
|
||||||
|
vtx.xyzw[2] = pos.z();
|
||||||
|
vtx.xyzw[3] = 0.f;
|
||||||
|
|
||||||
|
vtx.normal[0] =triNormal.x();
|
||||||
|
vtx.normal[1] =triNormal.y();
|
||||||
|
vtx.normal[2] =triNormal.z();
|
||||||
|
|
||||||
|
vtx.uv[0] = 0.5f;
|
||||||
|
vtx.uv[1] = 0.5f;
|
||||||
|
|
||||||
|
indicesOut.push_back(verticesOut.size());
|
||||||
|
verticesOut.push_back(vtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (collisionShape->isCompound())
|
||||||
|
{
|
||||||
|
btCompoundShape* compound = (btCompoundShape*) collisionShape;
|
||||||
|
for (int i=0;i<compound->getNumChildShapes();i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
btTransform childWorldTrans = parentTransform * compound->getChildTransform(i);
|
||||||
|
createCollisionShapeGraphicsObjectInternal(compound->getChildShape(i),childWorldTrans,verticesOut,indicesOut);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
btAssert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLGuiHelper::createCollisionShapeGraphicsObject(btCollisionShape* collisionShape)
|
||||||
|
{
|
||||||
|
//already has a graphics object?
|
||||||
|
if (collisionShape->getUserIndex()>=0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
btAlignedObjectArray<GLInstanceVertex> vertices;
|
||||||
|
btAlignedObjectArray<int> indices;
|
||||||
|
btTransform startTrans;startTrans.setIdentity();
|
||||||
|
|
||||||
|
createCollisionShapeGraphicsObjectInternal(collisionShape,startTrans,vertices,indices);
|
||||||
|
|
||||||
|
if (vertices.size() && indices.size())
|
||||||
|
{
|
||||||
|
int shapeId = m_data->m_glApp->m_renderer->registerShape(&vertices[0].xyzw[0],vertices.size(),&indices[0],indices.size());
|
||||||
|
collisionShape->setUserIndex(shapeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
void OpenGLGuiHelper::syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld)
|
||||||
|
{
|
||||||
|
int numCollisionObjects = rbWorld->getNumCollisionObjects();
|
||||||
|
for (int i = 0; i<numCollisionObjects; i++)
|
||||||
|
{
|
||||||
|
btCollisionObject* colObj = rbWorld->getCollisionObjectArray()[i];
|
||||||
|
btVector3 pos = colObj->getWorldTransform().getOrigin();
|
||||||
|
btQuaternion orn = colObj->getWorldTransform().getRotation();
|
||||||
|
int index = colObj->getUserIndex();
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
m_data->m_glApp->m_renderer->writeSingleInstanceTransformToCPU(pos, orn, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_data->m_glApp->m_renderer->writeTransforms();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLGuiHelper::createPhysicsDebugDrawer(btDiscreteDynamicsWorld* rbWorld)
|
||||||
|
{
|
||||||
|
btAssert(rbWorld);
|
||||||
|
m_data->m_debugDraw = new MyDebugDrawer(m_data->m_glApp);
|
||||||
|
rbWorld->setDebugDrawer(m_data->m_debugDraw );
|
||||||
|
|
||||||
|
|
||||||
|
m_data->m_debugDraw->setDebugMode(
|
||||||
|
btIDebugDraw::DBG_DrawWireframe
|
||||||
|
+btIDebugDraw::DBG_DrawAabb
|
||||||
|
//btIDebugDraw::DBG_DrawContactPoints
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Common2dCanvasInterface* OpenGLGuiHelper::get2dCanvasInterface()
|
||||||
|
{
|
||||||
|
return m_data->m_glApp->m_2dCanvasInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonParameterInterface* OpenGLGuiHelper::getParameterInterface()
|
||||||
|
{
|
||||||
|
return m_data->m_glApp->m_parameterInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLGuiHelper::setUpAxis(int axis)
|
||||||
|
{
|
||||||
|
m_data->m_glApp->setUpAxis(axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 OpenGLGuiHelper::selectColor()
|
||||||
|
{
|
||||||
|
btVector4 color = sColors[m_data->m_curColor];
|
||||||
|
m_data->m_curColor++;
|
||||||
|
m_data->m_curColor&=3;
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyConvertPointerSizeT
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
const void* m_ptr;
|
||||||
|
size_t m_int;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
bool shapePointerCompareFunc(const btCollisionObject* colA, const btCollisionObject* colB)
|
||||||
|
{
|
||||||
|
MyConvertPointerSizeT a,b;
|
||||||
|
a.m_ptr = colA->getCollisionShape();
|
||||||
|
b.m_ptr = colB->getCollisionShape();
|
||||||
|
return (a.m_int<b.m_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLGuiHelper::autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld)
|
||||||
|
{
|
||||||
|
//sort the collision objects based on collision shape, the gfx library requires instances that re-use a shape to be added after eachother
|
||||||
|
|
||||||
|
btAlignedObjectArray<btCollisionObject*> sortedObjects;
|
||||||
|
sortedObjects.reserve(rbWorld->getNumCollisionObjects());
|
||||||
|
for (int i=0;i<rbWorld->getNumCollisionObjects();i++)
|
||||||
|
{
|
||||||
|
btCollisionObject* colObj = rbWorld->getCollisionObjectArray()[i];
|
||||||
|
sortedObjects.push_back(colObj);
|
||||||
|
}
|
||||||
|
sortedObjects.quickSort(shapePointerCompareFunc);
|
||||||
|
for (int i=0;i<sortedObjects.size();i++)
|
||||||
|
{
|
||||||
|
btCollisionObject* colObj = sortedObjects[i];
|
||||||
|
//btRigidBody* body = btRigidBody::upcast(colObj);
|
||||||
|
//does this also work for btMultiBody/btMultiBodyLinkCollider?
|
||||||
|
createCollisionShapeGraphicsObject(colObj->getCollisionShape());
|
||||||
|
btVector3 color= selectColor();
|
||||||
|
createCollisionObjectGraphicsObject(colObj,color);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLGuiHelper::drawText3D( const char* txt, float posX, float posY, float posZ, float size)
|
||||||
|
{
|
||||||
|
btAssert(m_data->m_glApp);
|
||||||
|
m_data->m_glApp->drawText3D(txt,posX,posY,posZ,size);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CommonGraphicsApp* OpenGLGuiHelper::getAppInterface()
|
||||||
|
{
|
||||||
|
return m_data->m_glApp;
|
||||||
|
}
|
||||||
52
examples/ExampleBrowser/OpenGLGuiHelper.h
Normal file
52
examples/ExampleBrowser/OpenGLGuiHelper.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef OPENGL_GUI_HELPER_H
|
||||||
|
#define OPENGL_GUI_HELPER_H
|
||||||
|
#include "GUIHelperInterface.h"
|
||||||
|
|
||||||
|
class btCollisionShape;
|
||||||
|
class btTransform;
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
struct OpenGLGuiHelper : public GUIHelperInterface
|
||||||
|
{
|
||||||
|
struct OpenGLGuiHelperInternalData* m_data;
|
||||||
|
|
||||||
|
OpenGLGuiHelper(struct CommonGraphicsApp* glApp);
|
||||||
|
|
||||||
|
virtual ~OpenGLGuiHelper();
|
||||||
|
|
||||||
|
virtual struct CommonRenderInterface* getRenderInterface();
|
||||||
|
|
||||||
|
virtual void createRigidBodyGraphicsObject(btRigidBody* body, const btVector3& color);
|
||||||
|
|
||||||
|
virtual void createCollisionObjectGraphicsObject(btCollisionObject* body, const btVector3& color);
|
||||||
|
|
||||||
|
virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices);
|
||||||
|
|
||||||
|
virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape);
|
||||||
|
|
||||||
|
virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld);
|
||||||
|
|
||||||
|
virtual void createPhysicsDebugDrawer(btDiscreteDynamicsWorld* rbWorld);
|
||||||
|
|
||||||
|
virtual struct Common2dCanvasInterface* get2dCanvasInterface();
|
||||||
|
|
||||||
|
virtual CommonParameterInterface* getParameterInterface();
|
||||||
|
|
||||||
|
virtual struct CommonGraphicsApp* getAppInterface();
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setUpAxis(int axis);
|
||||||
|
|
||||||
|
btVector3 selectColor();
|
||||||
|
|
||||||
|
virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld) ;
|
||||||
|
|
||||||
|
virtual void drawText3D( const char* txt, float posX, float posY, float posZ, float size);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //OPENGL_GUI_HELPER_H
|
||||||
|
|
||||||
39
examples/ExampleBrowser/main.cpp
Normal file
39
examples/ExampleBrowser/main.cpp
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
//#define EXAMPLE_CONSOLE_ONLY
|
||||||
|
#ifdef EXAMPLE_CONSOLE_ONLY
|
||||||
|
#include "EmptyBrowser.h"
|
||||||
|
typedef EmptyBrowser DefaultBrowser;
|
||||||
|
#else
|
||||||
|
#include "OpenGLExampleBrowser.h"
|
||||||
|
typedef OpenGLExampleBrowser DefaultBrowser;
|
||||||
|
#endif //EXAMPLE_CONSOLE_ONLY
|
||||||
|
|
||||||
|
#include "Bullet3Common/b3CommandLineArgs.h"
|
||||||
|
#include "../Utils/b3Clock.h"
|
||||||
|
|
||||||
|
#include "ExampleEntries.h"
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
b3CommandLineArgs args(argc,argv);
|
||||||
|
b3Clock clock;
|
||||||
|
|
||||||
|
ExampleEntries examples;
|
||||||
|
examples.initExampleEntries();
|
||||||
|
|
||||||
|
ExampleBrowserInterface* exampleBrowser = new DefaultBrowser(&examples);
|
||||||
|
bool init = exampleBrowser->init(argc,argv);
|
||||||
|
if (init)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
float deltaTimeInSeconds = 1./120.f;
|
||||||
|
exampleBrowser->update(deltaTimeInSeconds);
|
||||||
|
|
||||||
|
} while (!exampleBrowser->requestedExit());
|
||||||
|
}
|
||||||
|
delete exampleBrowser;
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
64
examples/ExampleBrowser/premake4.lua
Normal file
64
examples/ExampleBrowser/premake4.lua
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
project "App_ExampleBrowser"
|
||||||
|
|
||||||
|
language "C++"
|
||||||
|
|
||||||
|
kind "ConsoleApp"
|
||||||
|
|
||||||
|
includedirs {
|
||||||
|
".",
|
||||||
|
"../../src",
|
||||||
|
"../ThirdPartyLibs",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
links{"gwen", "OpenGL_Window","BulletDynamics","BulletCollision","LinearMath","Bullet3Common"}
|
||||||
|
initOpenGL()
|
||||||
|
initGlew()
|
||||||
|
|
||||||
|
|
||||||
|
files {
|
||||||
|
"**.cpp",
|
||||||
|
"**.h",
|
||||||
|
"../BasicDemo/BasicExample.*",
|
||||||
|
"../Benchmarks/*",
|
||||||
|
"../CommonInterfaces/*",
|
||||||
|
"../ForkLift/ForkLiftDemo.*",
|
||||||
|
"../Importers/**",
|
||||||
|
"../Planar2D/Planar2D.*",
|
||||||
|
"../RenderingExamples/*",
|
||||||
|
"../ThirdPartyLibs/Wavefront/tiny_obj_loader.*",
|
||||||
|
"../ThirdPartyLibs/tinyxml/*",
|
||||||
|
"../Utils/b3Clock.*",
|
||||||
|
"../GyroscopicDemo/GyroscopicSetup.cpp",
|
||||||
|
"../GyroscopicDemo/GyroscopicSetup.h",
|
||||||
|
"../ThirdPartyLibs/urdf/urdfdom/urdf_parser/src/pose.cpp",
|
||||||
|
"../ThirdPartyLibs/urdf/urdfdom/urdf_parser/src/model.cpp",
|
||||||
|
"../ThirdPartyLibs/urdf/urdfdom/urdf_parser/src/link.cpp",
|
||||||
|
"../ThirdPartyLibs/urdf/urdfdom/urdf_parser/src/joint.cpp",
|
||||||
|
"../ThirdPartyLibs/urdf/urdfdom/urdf_parser/include/urdf_parser/urdf_parser.h",
|
||||||
|
"../ThirdPartyLibs/urdf/urdfdom_headers/urdf_exception/include/urdf_exception/exception.h",
|
||||||
|
"../ThirdPartyLibs/urdf/urdfdom_headers/urdf_model/include/urdf_model/pose.h",
|
||||||
|
"../ThirdPartyLibs/urdf/urdfdom_headers/urdf_model/include/urdf_model/model.h",
|
||||||
|
"../ThirdPartyLibs/urdf/urdfdom_headers/urdf_model/include/urdf_model/link.h",
|
||||||
|
"../ThirdPartyLibs/urdf/urdfdom_headers/urdf_model/include/urdf_model/joint.h",
|
||||||
|
"../ThirdPartyLibs/tinyxml/tinystr.cpp",
|
||||||
|
"../ThirdPartyLibs/tinyxml/tinyxml.cpp",
|
||||||
|
"../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp",
|
||||||
|
"../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp",
|
||||||
|
"../ThirdPartyLibs/urdf/boost_replacement/lexical_cast.h",
|
||||||
|
"../ThirdPartyLibs/urdf/boost_replacement/shared_ptr.h",
|
||||||
|
"../ThirdPartyLibs/urdf/boost_replacement/printf_console.cpp",
|
||||||
|
"../ThirdPartyLibs/urdf/boost_replacement/printf_console.h",
|
||||||
|
"../ThirdPartyLibs/urdf/boost_replacement/string_split.cpp",
|
||||||
|
"../ThirdPartyLibs/urdf/boost_replacement/string_split.h",
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.is("Linux") then
|
||||||
|
initX11()
|
||||||
|
end
|
||||||
|
|
||||||
|
if os.is("MacOSX") then
|
||||||
|
links{"Cocoa.framework"}
|
||||||
|
end
|
||||||
1311
examples/ForkLift/ForkLiftDemo.cpp
Normal file
1311
examples/ForkLift/ForkLiftDemo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
22
examples/ForkLift/ForkLiftDemo.h
Normal file
22
examples/ForkLift/ForkLiftDemo.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
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 FORKLIFT_DEMO_H
|
||||||
|
#define FORKLIFT_DEMO_H
|
||||||
|
|
||||||
|
struct ExampleInterface* ForkLiftCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option);
|
||||||
|
|
||||||
|
#endif // FORKLIFT_DEMO_H
|
||||||
|
|
||||||
|
|
||||||
129
examples/GyroscopicDemo/GyroscopicSetup.cpp
Normal file
129
examples/GyroscopicDemo/GyroscopicSetup.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#include "GyroscopicSetup.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/CommonRigidBodyBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct GyroscopicSetup : public CommonRigidBodyBase
|
||||||
|
{
|
||||||
|
|
||||||
|
GyroscopicSetup(struct GUIHelperInterface* helper);
|
||||||
|
|
||||||
|
virtual ~GyroscopicSetup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual void initPhysics();
|
||||||
|
|
||||||
|
|
||||||
|
virtual void physicsDebugDraw(int debugFlags);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int gyroflags[4] = {
|
||||||
|
0,//none, no gyroscopic term
|
||||||
|
BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT,
|
||||||
|
BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD,
|
||||||
|
BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* gyroNames[4] = {
|
||||||
|
"No Gyroscopic",
|
||||||
|
"Explicit",
|
||||||
|
"Implicit (World)",
|
||||||
|
"Implicit (Body)"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GyroscopicSetup::GyroscopicSetup(struct GUIHelperInterface* helper)
|
||||||
|
:CommonRigidBodyBase(helper)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GyroscopicSetup::initPhysics()
|
||||||
|
{
|
||||||
|
m_guiHelper->setUpAxis(2);
|
||||||
|
createEmptyDynamicsWorld();
|
||||||
|
m_dynamicsWorld->setGravity(btVector3(0, 0, 0));
|
||||||
|
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 positions[4] = {
|
||||||
|
btVector3( -10, 8,4),
|
||||||
|
btVector3( -5, 8,4),
|
||||||
|
btVector3( 0, 8,4),
|
||||||
|
btVector3( 5, 8,4),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i<4; i++)
|
||||||
|
{
|
||||||
|
btCylinderShapeZ* pin = new btCylinderShapeZ(btVector3(0.1,0.1, 0.2));
|
||||||
|
btBoxShape* box = new btBoxShape(btVector3(1,0.1,0.1));
|
||||||
|
box->setMargin(0.01);
|
||||||
|
pin->setMargin(0.01);
|
||||||
|
btCompoundShape* compound = new btCompoundShape();
|
||||||
|
compound->addChildShape(btTransform::getIdentity(), pin);
|
||||||
|
btTransform offsetBox(btMatrix3x3::getIdentity(),btVector3(0,0,0.2));
|
||||||
|
compound->addChildShape(offsetBox, box);
|
||||||
|
btScalar masses[2] = {0.3,0.1};
|
||||||
|
btVector3 localInertia;
|
||||||
|
btTransform principal;
|
||||||
|
compound->calculatePrincipalAxisTransform(masses,principal,localInertia);
|
||||||
|
|
||||||
|
btRigidBody* body = new btRigidBody(1, 0, compound, localInertia);
|
||||||
|
btTransform tr;
|
||||||
|
tr.setIdentity();
|
||||||
|
tr.setOrigin(positions[i]);
|
||||||
|
body->setCenterOfMassTransform(tr);
|
||||||
|
body->setAngularVelocity(btVector3(0, 0.1, 10));//51));
|
||||||
|
//body->setLinearVelocity(btVector3(3, 0, 0));
|
||||||
|
body->setFriction(btSqrt(1));
|
||||||
|
m_dynamicsWorld->addRigidBody(body);
|
||||||
|
body->setFlags(gyroflags[i]);
|
||||||
|
m_dynamicsWorld->getSolverInfo().m_maxGyroscopicForce = 10.f;
|
||||||
|
body->setDamping(0.0000f, 0.000f);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
//btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(0.5)));
|
||||||
|
btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0, 0, 1), 0);
|
||||||
|
|
||||||
|
m_collisionShapes.push_back(groundShape);
|
||||||
|
btTransform groundTransform;
|
||||||
|
groundTransform.setIdentity();
|
||||||
|
groundTransform.setOrigin(btVector3(0, 0, 0));
|
||||||
|
btRigidBody* groundBody;
|
||||||
|
groundBody = createRigidBody(0, groundTransform, groundShape);
|
||||||
|
groundBody->setFriction(btSqrt(2));
|
||||||
|
}
|
||||||
|
m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GyroscopicSetup::physicsDebugDraw(int debugFlags)
|
||||||
|
{
|
||||||
|
CommonRigidBodyBase::physicsDebugDraw(debugFlags);
|
||||||
|
|
||||||
|
//render method names above objects
|
||||||
|
for (int i=0;i<m_dynamicsWorld->getNumCollisionObjects();i++)
|
||||||
|
{
|
||||||
|
btRigidBody* body = btRigidBody::upcast(m_dynamicsWorld->getCollisionObjectArray()[i]);
|
||||||
|
if (body && body->getInvMass()>0)
|
||||||
|
{
|
||||||
|
btTransform tr = body->getWorldTransform();
|
||||||
|
btVector3 pos = tr.getOrigin()+btVector3(0,0,2);
|
||||||
|
btScalar size=1;
|
||||||
|
m_guiHelper->drawText3D(gyroNames[i],pos.x(),pos.y(),pos.z(),size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleInterface* GyroscopicCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option)
|
||||||
|
{
|
||||||
|
return new GyroscopicSetup(helper);
|
||||||
|
}
|
||||||
7
examples/GyroscopicDemo/GyroscopicSetup.h
Normal file
7
examples/GyroscopicDemo/GyroscopicSetup.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
#ifndef GYROSCOPIC_SETUP_H
|
||||||
|
#define GYROSCOPIC_SETUP_H
|
||||||
|
|
||||||
|
class ExampleInterface* GyroscopicCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option);
|
||||||
|
|
||||||
|
#endif //GYROSCOPIC_SETUP_H
|
||||||
29
examples/HelloWorld/CMakeLists.txt
Normal file
29
examples/HelloWorld/CMakeLists.txt
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# HelloWorld is a minimal sample creating, stepping and deleting a Bullet dynamics world
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(
|
||||||
|
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||||
|
)
|
||||||
|
|
||||||
|
LINK_LIBRARIES(
|
||||||
|
BulletDynamics BulletCollision LinearMath
|
||||||
|
)
|
||||||
|
|
||||||
|
IF (WIN32)
|
||||||
|
ADD_EXECUTABLE(AppHelloWorld
|
||||||
|
HelloWorld.cpp
|
||||||
|
${BULLET_PHYSICS_SOURCE_DIR}/build3/bullet.rc
|
||||||
|
)
|
||||||
|
ELSE()
|
||||||
|
ADD_EXECUTABLE(AppHelloWorld
|
||||||
|
HelloWorld.cpp
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
|
||||||
|
SET_TARGET_PROPERTIES(AppHelloWorld PROPERTIES DEBUG_POSTFIX "_Debug")
|
||||||
|
SET_TARGET_PROPERTIES(AppHelloWorld PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel")
|
||||||
|
SET_TARGET_PROPERTIES(AppHelloWorld PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo")
|
||||||
|
ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
|
||||||
180
examples/HelloWorld/HelloWorld.cpp
Normal file
180
examples/HelloWorld/HelloWorld.cpp
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2007 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
///-----includes_start-----
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/// This is a Hello World program for running a basic Bullet physics simulation
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
///-----includes_end-----
|
||||||
|
|
||||||
|
int i;
|
||||||
|
///-----initialization_start-----
|
||||||
|
|
||||||
|
///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
|
||||||
|
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
|
||||||
|
|
||||||
|
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
|
||||||
|
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
|
||||||
|
|
||||||
|
///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
|
||||||
|
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
|
||||||
|
|
||||||
|
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
|
||||||
|
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
|
||||||
|
|
||||||
|
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration);
|
||||||
|
|
||||||
|
dynamicsWorld->setGravity(btVector3(0,-10,0));
|
||||||
|
|
||||||
|
///-----initialization_end-----
|
||||||
|
|
||||||
|
///create a few basic rigid bodies
|
||||||
|
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
|
||||||
|
|
||||||
|
//keep track of the shapes, we release memory at exit.
|
||||||
|
//make sure to re-use collision shapes among rigid bodies whenever possible!
|
||||||
|
btAlignedObjectArray<btCollisionShape*> collisionShapes;
|
||||||
|
|
||||||
|
collisionShapes.push_back(groundShape);
|
||||||
|
|
||||||
|
btTransform groundTransform;
|
||||||
|
groundTransform.setIdentity();
|
||||||
|
groundTransform.setOrigin(btVector3(0,-56,0));
|
||||||
|
|
||||||
|
{
|
||||||
|
btScalar mass(0.);
|
||||||
|
|
||||||
|
//rigidbody is dynamic if and only if mass is non zero, otherwise static
|
||||||
|
bool isDynamic = (mass != 0.f);
|
||||||
|
|
||||||
|
btVector3 localInertia(0,0,0);
|
||||||
|
if (isDynamic)
|
||||||
|
groundShape->calculateLocalInertia(mass,localInertia);
|
||||||
|
|
||||||
|
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
|
||||||
|
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
|
||||||
|
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
|
||||||
|
btRigidBody* body = new btRigidBody(rbInfo);
|
||||||
|
|
||||||
|
//add the body to the dynamics world
|
||||||
|
dynamicsWorld->addRigidBody(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
//create a dynamic rigidbody
|
||||||
|
|
||||||
|
//btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
|
||||||
|
btCollisionShape* colShape = new btSphereShape(btScalar(1.));
|
||||||
|
collisionShapes.push_back(colShape);
|
||||||
|
|
||||||
|
/// Create Dynamic Objects
|
||||||
|
btTransform startTransform;
|
||||||
|
startTransform.setIdentity();
|
||||||
|
|
||||||
|
btScalar mass(1.f);
|
||||||
|
|
||||||
|
//rigidbody is dynamic if and only if mass is non zero, otherwise static
|
||||||
|
bool isDynamic = (mass != 0.f);
|
||||||
|
|
||||||
|
btVector3 localInertia(0,0,0);
|
||||||
|
if (isDynamic)
|
||||||
|
colShape->calculateLocalInertia(mass,localInertia);
|
||||||
|
|
||||||
|
startTransform.setOrigin(btVector3(2,10,0));
|
||||||
|
|
||||||
|
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
|
||||||
|
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
|
||||||
|
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
|
||||||
|
btRigidBody* body = new btRigidBody(rbInfo);
|
||||||
|
|
||||||
|
dynamicsWorld->addRigidBody(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Do some simulation
|
||||||
|
|
||||||
|
|
||||||
|
///-----stepsimulation_start-----
|
||||||
|
for (i=0;i<100;i++)
|
||||||
|
{
|
||||||
|
dynamicsWorld->stepSimulation(1.f/60.f,10);
|
||||||
|
|
||||||
|
//print positions of all objects
|
||||||
|
for (int j=dynamicsWorld->getNumCollisionObjects()-1; j>=0 ;j--)
|
||||||
|
{
|
||||||
|
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
|
||||||
|
btRigidBody* body = btRigidBody::upcast(obj);
|
||||||
|
if (body && body->getMotionState())
|
||||||
|
{
|
||||||
|
btTransform trans;
|
||||||
|
body->getMotionState()->getWorldTransform(trans);
|
||||||
|
printf("world pos = %f,%f,%f\n",float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///-----stepsimulation_end-----
|
||||||
|
|
||||||
|
//cleanup in the reverse order of creation/initialization
|
||||||
|
|
||||||
|
///-----cleanup_start-----
|
||||||
|
|
||||||
|
//remove the rigidbodies from the dynamics world and delete them
|
||||||
|
for (i=dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
|
||||||
|
{
|
||||||
|
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[i];
|
||||||
|
btRigidBody* body = btRigidBody::upcast(obj);
|
||||||
|
if (body && body->getMotionState())
|
||||||
|
{
|
||||||
|
delete body->getMotionState();
|
||||||
|
}
|
||||||
|
dynamicsWorld->removeCollisionObject( obj );
|
||||||
|
delete obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
//delete collision shapes
|
||||||
|
for (int j=0;j<collisionShapes.size();j++)
|
||||||
|
{
|
||||||
|
btCollisionShape* shape = collisionShapes[j];
|
||||||
|
collisionShapes[j] = 0;
|
||||||
|
delete shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
//delete dynamics world
|
||||||
|
delete dynamicsWorld;
|
||||||
|
|
||||||
|
//delete solver
|
||||||
|
delete solver;
|
||||||
|
|
||||||
|
//delete broadphase
|
||||||
|
delete overlappingPairCache;
|
||||||
|
|
||||||
|
//delete dispatcher
|
||||||
|
delete dispatcher;
|
||||||
|
|
||||||
|
delete collisionConfiguration;
|
||||||
|
|
||||||
|
//next line is optional: it will be cleared by the destructor when the array goes out of scope
|
||||||
|
collisionShapes.clear();
|
||||||
|
|
||||||
|
///-----cleanup_end-----
|
||||||
|
}
|
||||||
|
|
||||||
22
examples/HelloWorld/premake4.lua
Normal file
22
examples/HelloWorld/premake4.lua
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
project "AppHelloWorld"
|
||||||
|
|
||||||
|
if _OPTIONS["ios"] then
|
||||||
|
kind "WindowedApp"
|
||||||
|
else
|
||||||
|
kind "ConsoleApp"
|
||||||
|
end
|
||||||
|
|
||||||
|
includedirs {"../../src"}
|
||||||
|
|
||||||
|
links {
|
||||||
|
"BulletDynamics","BulletCollision", "LinearMath"
|
||||||
|
}
|
||||||
|
|
||||||
|
language "C++"
|
||||||
|
|
||||||
|
files {
|
||||||
|
"**.cpp",
|
||||||
|
"**.h",
|
||||||
|
}
|
||||||
|
|
||||||
207
examples/Importers/ImportBsp/BspConverter.cpp
Normal file
207
examples/Importers/ImportBsp/BspConverter.cpp
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
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 "BspConverter.h"
|
||||||
|
#include "BspLoader.h"
|
||||||
|
#include "LinearMath/btVector3.h"
|
||||||
|
#include "LinearMath/btGeometryUtil.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
void BspConverter::convertBsp(BspLoader& bspLoader,float scaling)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
|
||||||
|
float playstartf[3] = {0,0,100};
|
||||||
|
|
||||||
|
if (bspLoader.findVectorByName(&playstartf[0],"info_player_start"))
|
||||||
|
{
|
||||||
|
printf("found playerstart\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bspLoader.findVectorByName(&playstartf[0],"info_player_deathmatch"))
|
||||||
|
{
|
||||||
|
printf("found deatchmatch start\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btVector3 playerStart (playstartf[0],playstartf[1],playstartf[2]);
|
||||||
|
|
||||||
|
|
||||||
|
playerStart[2] += 20.f; //start a bit higher
|
||||||
|
|
||||||
|
playerStart *= scaling;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//progressBegin("Loading bsp");
|
||||||
|
|
||||||
|
for (int i=0;i<bspLoader.m_numleafs;i++)
|
||||||
|
{
|
||||||
|
printf("Reading bspLeaf %i from total %i (%f procent)\n",i, bspLoader.m_numleafs,(100.f*(float)i/float(bspLoader.m_numleafs)) );
|
||||||
|
|
||||||
|
bool isValidBrush = false;
|
||||||
|
|
||||||
|
BSPLeaf& leaf = bspLoader.m_dleafs[i];
|
||||||
|
|
||||||
|
for (int b=0;b<leaf.numLeafBrushes;b++)
|
||||||
|
{
|
||||||
|
btAlignedObjectArray<btVector3> planeEquations;
|
||||||
|
|
||||||
|
int brushid = bspLoader.m_dleafbrushes[leaf.firstLeafBrush+b];
|
||||||
|
|
||||||
|
BSPBrush& brush = bspLoader.m_dbrushes[brushid];
|
||||||
|
if (brush.shaderNum!=-1)
|
||||||
|
{
|
||||||
|
if (bspLoader.m_dshaders[ brush.shaderNum ].contentFlags & BSPCONTENTS_SOLID)
|
||||||
|
{
|
||||||
|
brush.shaderNum = -1;
|
||||||
|
|
||||||
|
for (int p=0;p<brush.numSides;p++)
|
||||||
|
{
|
||||||
|
int sideid = brush.firstSide+p;
|
||||||
|
BSPBrushSide& brushside = bspLoader.m_dbrushsides[sideid];
|
||||||
|
int planeid = brushside.planeNum;
|
||||||
|
BSPPlane& plane = bspLoader.m_dplanes[planeid];
|
||||||
|
btVector3 planeEq;
|
||||||
|
planeEq.setValue(
|
||||||
|
plane.normal[0],
|
||||||
|
plane.normal[1],
|
||||||
|
plane.normal[2]);
|
||||||
|
planeEq[3] = scaling*-plane.dist;
|
||||||
|
|
||||||
|
planeEquations.push_back(planeEq);
|
||||||
|
isValidBrush=true;
|
||||||
|
}
|
||||||
|
if (isValidBrush)
|
||||||
|
{
|
||||||
|
|
||||||
|
btAlignedObjectArray<btVector3> vertices;
|
||||||
|
btGeometryUtil::getVerticesFromPlaneEquations(planeEquations,vertices);
|
||||||
|
|
||||||
|
bool isEntity = false;
|
||||||
|
btVector3 entityTarget(0.f,0.f,0.f);
|
||||||
|
addConvexVerticesCollider(vertices,isEntity,entityTarget);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define USE_ENTITIES
|
||||||
|
#ifdef USE_ENTITIES
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0;i<bspLoader.m_num_entities;i++)
|
||||||
|
{
|
||||||
|
const BSPEntity& entity = bspLoader.m_entities[i];
|
||||||
|
const char* cl = bspLoader.getValueForKey(&entity,"classname");
|
||||||
|
if ( !strcmp( cl, "trigger_push" ) ) {
|
||||||
|
btVector3 targetLocation(0.f,0.f,0.f);
|
||||||
|
|
||||||
|
cl = bspLoader.getValueForKey(&entity,"target");
|
||||||
|
if ( strcmp( cl, "" ) ) {
|
||||||
|
//its not empty so ...
|
||||||
|
|
||||||
|
/*
|
||||||
|
//lookup the target position for the jumppad:
|
||||||
|
const BSPEntity* targetentity = bspLoader.getEntityByValue( "targetname" , cl );
|
||||||
|
if (targetentity)
|
||||||
|
{
|
||||||
|
if (bspLoader.getVectorForKey( targetentity , "origin",&targetLocation[0]))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
cl = bspLoader.getValueForKey(&entity,"model");
|
||||||
|
if ( strcmp( cl, "" ) ) {
|
||||||
|
// add the model as a brush
|
||||||
|
if (cl[0] == '*')
|
||||||
|
{
|
||||||
|
int modelnr = atoi(&cl[1]);
|
||||||
|
if ((modelnr >=0) && (modelnr < bspLoader.m_nummodels))
|
||||||
|
{
|
||||||
|
const BSPModel& model = bspLoader.m_dmodels[modelnr];
|
||||||
|
for (int n=0;n<model.numBrushes;n++)
|
||||||
|
{
|
||||||
|
btAlignedObjectArray<btVector3> planeEquations;
|
||||||
|
bool isValidBrush = false;
|
||||||
|
|
||||||
|
//convert brush
|
||||||
|
const BSPBrush& brush = bspLoader.m_dbrushes[model.firstBrush+n];
|
||||||
|
{
|
||||||
|
for (int p=0;p<brush.numSides;p++)
|
||||||
|
{
|
||||||
|
int sideid = brush.firstSide+p;
|
||||||
|
BSPBrushSide& brushside = bspLoader.m_dbrushsides[sideid];
|
||||||
|
int planeid = brushside.planeNum;
|
||||||
|
BSPPlane& plane = bspLoader.m_dplanes[planeid];
|
||||||
|
btVector3 planeEq;
|
||||||
|
planeEq.setValue(
|
||||||
|
plane.normal[0],
|
||||||
|
plane.normal[1],
|
||||||
|
plane.normal[2]);
|
||||||
|
planeEq[3] = scaling*-plane.dist;
|
||||||
|
planeEquations.push_back(planeEq);
|
||||||
|
isValidBrush=true;
|
||||||
|
}
|
||||||
|
if (isValidBrush)
|
||||||
|
{
|
||||||
|
|
||||||
|
btAlignedObjectArray<btVector3> vertices;
|
||||||
|
btGeometryUtil::getVerticesFromPlaneEquations(planeEquations,vertices);
|
||||||
|
|
||||||
|
bool isEntity=true;
|
||||||
|
addConvexVerticesCollider(vertices,isEntity,targetLocation);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("unsupported trigger_push model, md3 ?\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //USE_ENTITIES
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//progressEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
39
examples/Importers/ImportBsp/BspConverter.h
Normal file
39
examples/Importers/ImportBsp/BspConverter.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
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 BSP_CONVERTER_H
|
||||||
|
#define BSP_CONVERTER_H
|
||||||
|
|
||||||
|
class BspLoader;
|
||||||
|
#include "LinearMath/btVector3.h"
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
///BspConverter turns a loaded bsp level into convex parts (vertices)
|
||||||
|
class BspConverter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void convertBsp(BspLoader& bspLoader,float scaling);
|
||||||
|
virtual ~BspConverter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
///this callback is called for each brush that succesfully converted into vertices
|
||||||
|
virtual void addConvexVerticesCollider(btAlignedObjectArray<btVector3>& vertices, bool isEntity, const btVector3& entityTargetLocation) = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BSP_CONVERTER_H
|
||||||
|
|
||||||
730
examples/Importers/ImportBsp/BspLoader.cpp
Normal file
730
examples/Importers/ImportBsp/BspLoader.cpp
Normal file
@@ -0,0 +1,730 @@
|
|||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU bteral Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code is distributed in the hope that it will be
|
||||||
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU bteral Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU bteral Public License
|
||||||
|
along with Foobar; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "BspLoader.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char filename[1024];
|
||||||
|
char *buffer,*script_p,*end_p;
|
||||||
|
int line;
|
||||||
|
} BSPScript;
|
||||||
|
|
||||||
|
#define MAX_INCLUDES 8
|
||||||
|
BSPScript scriptstack[MAX_INCLUDES];
|
||||||
|
BSPScript *script;
|
||||||
|
int scriptline;
|
||||||
|
|
||||||
|
char token[BSPMAXTOKEN];
|
||||||
|
bool endofscript;
|
||||||
|
bool tokenready; // only true if UnGetToken was just called
|
||||||
|
|
||||||
|
//
|
||||||
|
//loadBSPFile
|
||||||
|
//
|
||||||
|
|
||||||
|
int extrasize = 100;
|
||||||
|
|
||||||
|
BspLoader::BspLoader()
|
||||||
|
:m_num_entities(0)
|
||||||
|
{
|
||||||
|
m_Endianness = getMachineEndianness();
|
||||||
|
if (m_Endianness == BSP_BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
printf("Machine is BIG_ENDIAN\n");
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
printf("Machine is Little Endian\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool BspLoader::loadBSPFile( void* memoryBuffer) {
|
||||||
|
|
||||||
|
BSPHeader *header = (BSPHeader*) memoryBuffer;
|
||||||
|
|
||||||
|
// load the file header
|
||||||
|
if (header)
|
||||||
|
{
|
||||||
|
// swap the header
|
||||||
|
swapBlock( (int *)header, sizeof(*header) );
|
||||||
|
|
||||||
|
int length = (header->lumps[BSPLUMP_SHADERS].filelen) / sizeof(BSPShader);
|
||||||
|
m_dshaders.resize(length+extrasize);
|
||||||
|
m_numShaders = copyLump( header, BSPLUMP_SHADERS, &m_dshaders[0], sizeof(BSPShader) );
|
||||||
|
|
||||||
|
length = (header->lumps[LUMP_MODELS].filelen) / sizeof(BSPModel);
|
||||||
|
m_dmodels.resize(length+extrasize);
|
||||||
|
m_nummodels = copyLump( header, LUMP_MODELS, &m_dmodels[0], sizeof(BSPModel) );
|
||||||
|
|
||||||
|
length = (header->lumps[BSPLUMP_PLANES].filelen) / sizeof(BSPPlane);
|
||||||
|
m_dplanes.resize(length+extrasize);
|
||||||
|
m_numplanes = copyLump( header, BSPLUMP_PLANES, &m_dplanes[0], sizeof(BSPPlane) );
|
||||||
|
|
||||||
|
length = (header->lumps[BSPLUMP_LEAFS].filelen) / sizeof(BSPLeaf);
|
||||||
|
m_dleafs.resize(length+extrasize);
|
||||||
|
m_numleafs = copyLump( header, BSPLUMP_LEAFS, &m_dleafs[0], sizeof(BSPLeaf) );
|
||||||
|
|
||||||
|
length = (header->lumps[BSPLUMP_NODES].filelen) / sizeof(BSPNode);
|
||||||
|
m_dnodes.resize(length+extrasize);
|
||||||
|
m_numnodes = copyLump( header, BSPLUMP_NODES, &m_dnodes[0], sizeof(BSPNode) );
|
||||||
|
|
||||||
|
length = (header->lumps[BSPLUMP_LEAFSURFACES].filelen) / sizeof(m_dleafsurfaces[0]);
|
||||||
|
m_dleafsurfaces.resize(length+extrasize);
|
||||||
|
m_numleafsurfaces = copyLump( header, BSPLUMP_LEAFSURFACES, &m_dleafsurfaces[0], sizeof(m_dleafsurfaces[0]) );
|
||||||
|
|
||||||
|
length = (header->lumps[BSPLUMP_LEAFBRUSHES].filelen) / sizeof(m_dleafbrushes[0]) ;
|
||||||
|
m_dleafbrushes.resize(length+extrasize);
|
||||||
|
m_numleafbrushes = copyLump( header, BSPLUMP_LEAFBRUSHES, &m_dleafbrushes[0], sizeof(m_dleafbrushes[0]) );
|
||||||
|
|
||||||
|
length = (header->lumps[LUMP_BRUSHES].filelen) / sizeof(BSPBrush);
|
||||||
|
m_dbrushes.resize(length+extrasize);
|
||||||
|
m_numbrushes = copyLump( header, LUMP_BRUSHES, &m_dbrushes[0], sizeof(BSPBrush) );
|
||||||
|
|
||||||
|
|
||||||
|
length = (header->lumps[LUMP_BRUSHSIDES].filelen) / sizeof(BSPBrushSide);
|
||||||
|
m_dbrushsides.resize(length+extrasize);
|
||||||
|
m_numbrushsides = copyLump( header, LUMP_BRUSHSIDES, &m_dbrushsides[0], sizeof(BSPBrushSide) );
|
||||||
|
|
||||||
|
|
||||||
|
length = (header->lumps[LUMP_SURFACES].filelen) / sizeof(BSPSurface);
|
||||||
|
m_drawSurfaces.resize(length+extrasize);
|
||||||
|
m_numDrawSurfaces = copyLump( header, LUMP_SURFACES, &m_drawSurfaces[0], sizeof(BSPSurface) );
|
||||||
|
|
||||||
|
|
||||||
|
length = (header->lumps[LUMP_DRAWINDEXES].filelen) / sizeof(m_drawIndexes[0]);
|
||||||
|
m_drawIndexes.resize(length+extrasize);
|
||||||
|
m_numDrawIndexes = copyLump( header, LUMP_DRAWINDEXES, &m_drawIndexes[0], sizeof(m_drawIndexes[0]) );
|
||||||
|
|
||||||
|
length = (header->lumps[LUMP_VISIBILITY].filelen) / 1;
|
||||||
|
m_visBytes.resize(length+extrasize);
|
||||||
|
m_numVisBytes = copyLump( header, LUMP_VISIBILITY, &m_visBytes[0], 1 );
|
||||||
|
|
||||||
|
length = (header->lumps[LUMP_LIGHTMAPS].filelen) / 1;
|
||||||
|
m_lightBytes.resize(length+extrasize);
|
||||||
|
m_numLightBytes = copyLump( header, LUMP_LIGHTMAPS, &m_lightBytes[0], 1 );
|
||||||
|
|
||||||
|
length = (header->lumps[BSPLUMP_ENTITIES].filelen) / 1;
|
||||||
|
m_dentdata.resize(length+extrasize);
|
||||||
|
m_entdatasize = copyLump( header, BSPLUMP_ENTITIES, &m_dentdata[0], 1);
|
||||||
|
|
||||||
|
length = (header->lumps[LUMP_LIGHTGRID].filelen) / 1;
|
||||||
|
m_gridData.resize(length+extrasize);
|
||||||
|
m_numGridPoints = copyLump( header, LUMP_LIGHTGRID, &m_gridData[0], 8 );
|
||||||
|
|
||||||
|
// swap everything
|
||||||
|
swapBSPFile();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char* BspLoader::getValueForKey( const BSPEntity* ent, const char* key ) const {
|
||||||
|
|
||||||
|
const BSPKeyValuePair* ep;
|
||||||
|
|
||||||
|
for (ep=ent->epairs ; ep ; ep=ep->next) {
|
||||||
|
if (!strcmp(ep->key, key) ) {
|
||||||
|
return ep->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
float BspLoader::getFloatForKey( const BSPEntity *ent, const char *key ) {
|
||||||
|
const char *k;
|
||||||
|
|
||||||
|
k = getValueForKey( ent, key );
|
||||||
|
return float(atof(k));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BspLoader::getVectorForKey( const BSPEntity *ent, const char *key, BSPVector3 vec ) {
|
||||||
|
|
||||||
|
const char *k;
|
||||||
|
k = getValueForKey (ent, key);
|
||||||
|
if (strcmp(k, ""))
|
||||||
|
{
|
||||||
|
sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
parseFromMemory
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
void BspLoader::parseFromMemory (char *buffer, int size)
|
||||||
|
{
|
||||||
|
script = scriptstack;
|
||||||
|
script++;
|
||||||
|
if (script == &scriptstack[MAX_INCLUDES])
|
||||||
|
{
|
||||||
|
//printf("script file exceeded MAX_INCLUDES");
|
||||||
|
}
|
||||||
|
strcpy (script->filename, "memory buffer" );
|
||||||
|
|
||||||
|
script->buffer = buffer;
|
||||||
|
script->line = 1;
|
||||||
|
script->script_p = script->buffer;
|
||||||
|
script->end_p = script->buffer + size;
|
||||||
|
|
||||||
|
endofscript = false;
|
||||||
|
tokenready = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool BspLoader::isEndOfScript (bool crossline)
|
||||||
|
{
|
||||||
|
if (!crossline)
|
||||||
|
//printf("Line %i is incomplete\n",scriptline);
|
||||||
|
|
||||||
|
if (!strcmp (script->filename, "memory buffer"))
|
||||||
|
{
|
||||||
|
endofscript = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//free (script->buffer);
|
||||||
|
if (script == scriptstack+1)
|
||||||
|
{
|
||||||
|
endofscript = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
script--;
|
||||||
|
scriptline = script->line;
|
||||||
|
//printf ("returning to %s\n", script->filename);
|
||||||
|
return getToken (crossline);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
==============
|
||||||
|
getToken
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
bool BspLoader::getToken (bool crossline)
|
||||||
|
{
|
||||||
|
char *token_p;
|
||||||
|
|
||||||
|
if (tokenready) // is a token allready waiting?
|
||||||
|
{
|
||||||
|
tokenready = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script->script_p >= script->end_p)
|
||||||
|
return isEndOfScript (crossline);
|
||||||
|
|
||||||
|
//
|
||||||
|
// skip space
|
||||||
|
//
|
||||||
|
skipspace:
|
||||||
|
while (*script->script_p <= 32)
|
||||||
|
{
|
||||||
|
if (script->script_p >= script->end_p)
|
||||||
|
return isEndOfScript (crossline);
|
||||||
|
if (*script->script_p++ == '\n')
|
||||||
|
{
|
||||||
|
if (!crossline)
|
||||||
|
{
|
||||||
|
//printf("Line %i is incomplete\n",scriptline);
|
||||||
|
}
|
||||||
|
scriptline = script->line++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script->script_p >= script->end_p)
|
||||||
|
return isEndOfScript (crossline);
|
||||||
|
|
||||||
|
// ; # // comments
|
||||||
|
if (*script->script_p == ';' || *script->script_p == '#'
|
||||||
|
|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
|
||||||
|
{
|
||||||
|
if (!crossline)
|
||||||
|
{
|
||||||
|
//printf("Line %i is incomplete\n",scriptline);
|
||||||
|
}
|
||||||
|
while (*script->script_p++ != '\n')
|
||||||
|
if (script->script_p >= script->end_p)
|
||||||
|
return isEndOfScript (crossline);
|
||||||
|
scriptline = script->line++;
|
||||||
|
goto skipspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /* */ comments
|
||||||
|
if (script->script_p[0] == '/' && script->script_p[1] == '*')
|
||||||
|
{
|
||||||
|
if (!crossline)
|
||||||
|
{
|
||||||
|
//printf("Line %i is incomplete\n",scriptline);
|
||||||
|
}
|
||||||
|
script->script_p+=2;
|
||||||
|
while (script->script_p[0] != '*' && script->script_p[1] != '/')
|
||||||
|
{
|
||||||
|
if ( *script->script_p == '\n' ) {
|
||||||
|
scriptline = script->line++;
|
||||||
|
}
|
||||||
|
script->script_p++;
|
||||||
|
if (script->script_p >= script->end_p)
|
||||||
|
return isEndOfScript (crossline);
|
||||||
|
}
|
||||||
|
script->script_p += 2;
|
||||||
|
goto skipspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy token
|
||||||
|
//
|
||||||
|
token_p = token;
|
||||||
|
|
||||||
|
if (*script->script_p == '"')
|
||||||
|
{
|
||||||
|
// quoted token
|
||||||
|
script->script_p++;
|
||||||
|
while (*script->script_p != '"')
|
||||||
|
{
|
||||||
|
*token_p++ = *script->script_p++;
|
||||||
|
if (script->script_p == script->end_p)
|
||||||
|
break;
|
||||||
|
if (token_p == &token[BSPMAXTOKEN])
|
||||||
|
{
|
||||||
|
//printf ("Token too large on line %i\n",scriptline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
script->script_p++;
|
||||||
|
}
|
||||||
|
else // regular token
|
||||||
|
while ( *script->script_p > 32 && *script->script_p != ';')
|
||||||
|
{
|
||||||
|
*token_p++ = *script->script_p++;
|
||||||
|
if (script->script_p == script->end_p)
|
||||||
|
break;
|
||||||
|
if (token_p == &token[BSPMAXTOKEN])
|
||||||
|
{
|
||||||
|
//printf ("Token too large on line %i\n",scriptline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*token_p = 0;
|
||||||
|
|
||||||
|
if (!strcmp (token, "$include"))
|
||||||
|
{
|
||||||
|
//getToken (false);
|
||||||
|
//AddScriptToStack (token);
|
||||||
|
return false;//getToken (crossline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *BspLoader::copystring(const char *s)
|
||||||
|
{
|
||||||
|
char *b;
|
||||||
|
b = (char*) malloc( strlen(s)+1);
|
||||||
|
strcpy (b, s);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BspLoader::stripTrailing( char *e ) {
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
s = e + strlen(e)-1;
|
||||||
|
while (s >= e && *s <= 32)
|
||||||
|
{
|
||||||
|
*s = 0;
|
||||||
|
s--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
parseEpair
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
BSPKeyValuePair *BspLoader::parseEpair( void ) {
|
||||||
|
BSPKeyValuePair *e;
|
||||||
|
|
||||||
|
e = (struct BSPPair*) malloc( sizeof(BSPKeyValuePair));
|
||||||
|
memset( e, 0, sizeof(BSPKeyValuePair) );
|
||||||
|
|
||||||
|
if ( strlen(token) >= BSPMAX_KEY-1 ) {
|
||||||
|
//printf ("ParseEpar: token too long");
|
||||||
|
}
|
||||||
|
e->key = copystring( token );
|
||||||
|
getToken( false );
|
||||||
|
if ( strlen(token) >= BSPMAX_VALUE-1 ) {
|
||||||
|
|
||||||
|
//printf ("ParseEpar: token too long");
|
||||||
|
}
|
||||||
|
e->value = copystring( token );
|
||||||
|
|
||||||
|
// strip trailing spaces that sometimes get accidentally
|
||||||
|
// added in the editor
|
||||||
|
stripTrailing( e->key );
|
||||||
|
stripTrailing( e->value );
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
parseEntity
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
bool BspLoader::parseEntity( void ) {
|
||||||
|
BSPKeyValuePair *e;
|
||||||
|
BSPEntity *mapent;
|
||||||
|
|
||||||
|
if ( !getToken (true) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( strcmp (token, "{") ) {
|
||||||
|
|
||||||
|
//printf ("parseEntity: { not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
BSPEntity bla;
|
||||||
|
bla.brushes = 0;
|
||||||
|
bla.epairs = 0;
|
||||||
|
bla.firstDrawSurf = 0;
|
||||||
|
bla.origin[0] = 0.f;
|
||||||
|
bla.origin[1] = 0.f;
|
||||||
|
bla.origin[2] = 0.f;
|
||||||
|
bla.patches = 0;
|
||||||
|
|
||||||
|
m_entities.push_back(bla);
|
||||||
|
mapent = &m_entities[m_entities.size()-1];
|
||||||
|
m_num_entities++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ( !getToken (true) ) {
|
||||||
|
//printf("parseEntity: EOF without closing brace");
|
||||||
|
}
|
||||||
|
if ( !strcmp (token, "}") ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e = (struct BSPPair*)parseEpair ();
|
||||||
|
e->next = mapent->epairs;
|
||||||
|
mapent->epairs = e;
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
parseEntities
|
||||||
|
|
||||||
|
Parses the dentdata string into entities
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void BspLoader::parseEntities( void ) {
|
||||||
|
m_num_entities = 0;
|
||||||
|
m_entities.clear();
|
||||||
|
|
||||||
|
parseFromMemory( &m_dentdata[0], m_entdatasize );
|
||||||
|
|
||||||
|
while ( parseEntity () ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int BspLoader::getMachineEndianness()
|
||||||
|
{
|
||||||
|
long int i = 1;
|
||||||
|
const char *p = (const char *) &i;
|
||||||
|
if (p[0] == 1) // Lowest address contains the least significant byte
|
||||||
|
return BSP_LITTLE_ENDIAN;
|
||||||
|
else
|
||||||
|
return BSP_BIG_ENDIAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
short BspLoader::isLittleShort (short l)
|
||||||
|
{
|
||||||
|
if (machineEndianness() == BSP_BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
unsigned char b1,b2;
|
||||||
|
|
||||||
|
b1 = l&255;
|
||||||
|
b2 = (l>>8)&255;
|
||||||
|
|
||||||
|
return (b1<<8) + b2;
|
||||||
|
}
|
||||||
|
//little endian
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
short BspLoader::isBigShort (short l)
|
||||||
|
{
|
||||||
|
if (machineEndianness() == BSP_BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char b1,b2;
|
||||||
|
|
||||||
|
b1 = l&255;
|
||||||
|
b2 = (l>>8)&255;
|
||||||
|
|
||||||
|
return (b1<<8) + b2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int BspLoader::isLittleLong (int l)
|
||||||
|
{
|
||||||
|
if (machineEndianness() == BSP_BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
unsigned char b1,b2,b3,b4;
|
||||||
|
|
||||||
|
b1 = l&255;
|
||||||
|
b2 = (l>>8)&255;
|
||||||
|
b3 = (l>>16)&255;
|
||||||
|
b4 = (l>>24)&255;
|
||||||
|
|
||||||
|
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
//little endian
|
||||||
|
return l;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int BspLoader::isBigLong (int l)
|
||||||
|
{
|
||||||
|
if (machineEndianness() == BSP_BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char b1,b2,b3,b4;
|
||||||
|
|
||||||
|
b1 = l&255;
|
||||||
|
b2 = (l>>8)&255;
|
||||||
|
b3 = (l>>16)&255;
|
||||||
|
b4 = (l>>24)&255;
|
||||||
|
|
||||||
|
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float BspLoader::isLittleFloat (float l)
|
||||||
|
{
|
||||||
|
if (machineEndianness() == BSP_BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
union {unsigned char b[4]; float f;} in, out;
|
||||||
|
|
||||||
|
in.f = l;
|
||||||
|
out.b[0] = in.b[3];
|
||||||
|
out.b[1] = in.b[2];
|
||||||
|
out.b[2] = in.b[1];
|
||||||
|
out.b[3] = in.b[0];
|
||||||
|
|
||||||
|
return out.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//little endian
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
float BspLoader::isBigFloat (float l)
|
||||||
|
{
|
||||||
|
if (machineEndianness() == BSP_BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
//little endian
|
||||||
|
union {unsigned char b[4]; float f;} in, out;
|
||||||
|
|
||||||
|
in.f = l;
|
||||||
|
out.b[0] = in.b[3];
|
||||||
|
out.b[1] = in.b[2];
|
||||||
|
out.b[2] = in.b[1];
|
||||||
|
out.b[3] = in.b[0];
|
||||||
|
|
||||||
|
return out.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// swapBlock
|
||||||
|
// If all values are 32 bits, this can be used to swap everything
|
||||||
|
//
|
||||||
|
|
||||||
|
void BspLoader::swapBlock( int *block, int sizeOfBlock ) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sizeOfBlock >>= 2;
|
||||||
|
for ( i = 0 ; i < sizeOfBlock ; i++ ) {
|
||||||
|
block[i] = isLittleLong( block[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// copyLump
|
||||||
|
//
|
||||||
|
|
||||||
|
int BspLoader::copyLump( BSPHeader *header, int lump, void *dest, int size ) {
|
||||||
|
int length, ofs;
|
||||||
|
|
||||||
|
length = header->lumps[lump].filelen;
|
||||||
|
ofs = header->lumps[lump].fileofs;
|
||||||
|
|
||||||
|
//if ( length % size ) {
|
||||||
|
// printf ("loadBSPFile: odd lump size");
|
||||||
|
//}
|
||||||
|
|
||||||
|
memcpy( dest, (unsigned char *)header + ofs, length );
|
||||||
|
|
||||||
|
return length / size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// swapBSPFile
|
||||||
|
//
|
||||||
|
|
||||||
|
void BspLoader::swapBSPFile( void ) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// models
|
||||||
|
swapBlock( (int *) &m_dmodels[0], m_nummodels * sizeof( m_dmodels[0] ) );
|
||||||
|
|
||||||
|
// shaders (don't swap the name)
|
||||||
|
for ( i = 0 ; i < m_numShaders ; i++ ) {
|
||||||
|
m_dshaders[i].contentFlags = isLittleLong( m_dshaders[i].contentFlags );
|
||||||
|
m_dshaders[i].surfaceFlags = isLittleLong( m_dshaders[i].surfaceFlags );
|
||||||
|
}
|
||||||
|
|
||||||
|
// planes
|
||||||
|
swapBlock( (int *)&m_dplanes[0], m_numplanes * sizeof( m_dplanes[0] ) );
|
||||||
|
|
||||||
|
// nodes
|
||||||
|
swapBlock( (int *)&m_dnodes[0], m_numnodes * sizeof( m_dnodes[0] ) );
|
||||||
|
|
||||||
|
// leafs
|
||||||
|
swapBlock( (int *)&m_dleafs[0], m_numleafs * sizeof( m_dleafs[0] ) );
|
||||||
|
|
||||||
|
// leaffaces
|
||||||
|
swapBlock( (int *)&m_dleafsurfaces[0], m_numleafsurfaces * sizeof( m_dleafsurfaces[0] ) );
|
||||||
|
|
||||||
|
// leafbrushes
|
||||||
|
swapBlock( (int *)&m_dleafbrushes[0], m_numleafbrushes * sizeof( m_dleafbrushes[0] ) );
|
||||||
|
|
||||||
|
// brushes
|
||||||
|
swapBlock( (int *)&m_dbrushes[0], m_numbrushes * sizeof( m_dbrushes[0] ) );
|
||||||
|
|
||||||
|
// brushsides
|
||||||
|
swapBlock( (int *)&m_dbrushsides[0], m_numbrushsides * sizeof( m_dbrushsides[0] ) );
|
||||||
|
|
||||||
|
// vis
|
||||||
|
((int *)&m_visBytes)[0] = isLittleLong( ((int *)&m_visBytes)[0] );
|
||||||
|
((int *)&m_visBytes)[1] = isLittleLong( ((int *)&m_visBytes)[1] );
|
||||||
|
|
||||||
|
|
||||||
|
// drawindexes
|
||||||
|
swapBlock( (int *)&m_drawIndexes[0], m_numDrawIndexes * sizeof( m_drawIndexes[0] ) );
|
||||||
|
|
||||||
|
// drawsurfs
|
||||||
|
swapBlock( (int *)&m_drawSurfaces[0], m_numDrawSurfaces * sizeof( m_drawSurfaces[0] ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool BspLoader::findVectorByName(float* outvec,const char* name)
|
||||||
|
{
|
||||||
|
const char *cl;
|
||||||
|
BSPVector3 origin;
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
parseEntities();
|
||||||
|
|
||||||
|
for ( int i = 1; i < m_num_entities; i++ ) {
|
||||||
|
cl = getValueForKey (&m_entities[i], "classname");
|
||||||
|
if ( !strcmp( cl, "info_player_start" ) ) {
|
||||||
|
getVectorForKey( &m_entities[i], "origin", origin );
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( !strcmp( cl, "info_player_deathmatch" ) ) {
|
||||||
|
getVectorForKey( &m_entities[i], "origin", origin );
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
outvec[0] = origin[0];
|
||||||
|
outvec[1] = origin[1];
|
||||||
|
outvec[2] = origin[2];
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const BSPEntity * BspLoader::getEntityByValue( const char* name, const char* value)
|
||||||
|
{
|
||||||
|
const BSPEntity* entity = NULL;
|
||||||
|
|
||||||
|
for ( int i = 1; i < m_num_entities; i++ ) {
|
||||||
|
|
||||||
|
const BSPEntity& ent = m_entities[i];
|
||||||
|
|
||||||
|
const char* cl = getValueForKey (&m_entities[i], name);
|
||||||
|
if ( !strcmp( cl, value ) ) {
|
||||||
|
entity = &ent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
295
examples/Importers/ImportBsp/BspLoader.h
Normal file
295
examples/Importers/ImportBsp/BspLoader.h
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU bteral Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code is distributed in the hope that it will be
|
||||||
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU bteral Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU bteral Public License
|
||||||
|
along with Foobar; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef BSP_LOADER_H
|
||||||
|
#define BSP_LOADER_H
|
||||||
|
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
#define BSPMAXTOKEN 1024
|
||||||
|
#define BSPMAX_KEY 32
|
||||||
|
#define BSPMAX_VALUE 1024
|
||||||
|
#define BSPCONTENTS_SOLID 1
|
||||||
|
#define BSPCONTENTS_AREAPORTAL 0x8000
|
||||||
|
#define BSPLUMP_ENTITIES 0
|
||||||
|
#define BSPLUMP_SHADERS 1
|
||||||
|
#define BSPLUMP_PLANES 2
|
||||||
|
#define BSPLUMP_NODES 3
|
||||||
|
#define BSPLUMP_LEAFS 4
|
||||||
|
#define BSPLUMP_LEAFSURFACES 5
|
||||||
|
#define BSPLUMP_LEAFBRUSHES 6
|
||||||
|
#define LUMP_MODELS 7
|
||||||
|
#define LUMP_BRUSHES 8
|
||||||
|
#define LUMP_BRUSHSIDES 9
|
||||||
|
#define LUMP_DRAWVERTS 10
|
||||||
|
#define LUMP_DRAWINDEXES 11
|
||||||
|
#define LUMP_SURFACES 13
|
||||||
|
#define LUMP_LIGHTMAPS 14
|
||||||
|
#define LUMP_LIGHTGRID 15
|
||||||
|
#define LUMP_VISIBILITY 16
|
||||||
|
#define HEADER_LUMPS 17
|
||||||
|
#define MAX_QPATH 64
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int fileofs, filelen;
|
||||||
|
} BSPLump;
|
||||||
|
|
||||||
|
typedef float BSPVector3[3];
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int ident;
|
||||||
|
int version;
|
||||||
|
|
||||||
|
BSPLump lumps[HEADER_LUMPS];
|
||||||
|
} BSPHeader;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float mins[3], maxs[3];
|
||||||
|
int firstSurface, numSurfaces;
|
||||||
|
int firstBrush, numBrushes;
|
||||||
|
} BSPModel;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char shader[MAX_QPATH];
|
||||||
|
int surfaceFlags;
|
||||||
|
int contentFlags;
|
||||||
|
} BSPShader;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float normal[3];
|
||||||
|
float dist;
|
||||||
|
} BSPPlane;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int planeNum;
|
||||||
|
int children[2];
|
||||||
|
int mins[3];
|
||||||
|
int maxs[3];
|
||||||
|
} BSPNode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int cluster;
|
||||||
|
int area;
|
||||||
|
|
||||||
|
int mins[3];
|
||||||
|
int maxs[3];
|
||||||
|
|
||||||
|
int firstLeafSurface;
|
||||||
|
int numLeafSurfaces;
|
||||||
|
|
||||||
|
int firstLeafBrush;
|
||||||
|
int numLeafBrushes;
|
||||||
|
} BSPLeaf;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int planeNum;
|
||||||
|
int shaderNum;
|
||||||
|
} BSPBrushSide;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int firstSide;
|
||||||
|
int numSides;
|
||||||
|
int shaderNum;
|
||||||
|
} BSPBrush;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct BSPPair {
|
||||||
|
struct BSPPair *next;
|
||||||
|
char *key;
|
||||||
|
char *value;
|
||||||
|
} BSPKeyValuePair;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BSPVector3 origin;
|
||||||
|
struct bspbrush_s *brushes;
|
||||||
|
struct parseMesh_s *patches;
|
||||||
|
int firstDrawSurf;
|
||||||
|
BSPKeyValuePair *epairs;
|
||||||
|
} BSPEntity;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MST_BAD,
|
||||||
|
MST_PLANAR,
|
||||||
|
MST_PATCH,
|
||||||
|
MST_TRIANGLE_SOUP,
|
||||||
|
MST_FLARE
|
||||||
|
} BSPMapSurface;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int shaderNum;
|
||||||
|
int fogNum;
|
||||||
|
int surfaceType;
|
||||||
|
|
||||||
|
int firstVert;
|
||||||
|
int numVerts;
|
||||||
|
|
||||||
|
int firstIndex;
|
||||||
|
int numIndexes;
|
||||||
|
|
||||||
|
int lightmapNum;
|
||||||
|
int lightmapX, lightmapY;
|
||||||
|
int lightmapWidth, lightmapHeight;
|
||||||
|
|
||||||
|
BSPVector3 lightmapOrigin;
|
||||||
|
BSPVector3 lightmapVecs[3];
|
||||||
|
|
||||||
|
int patchWidth;
|
||||||
|
int patchHeight;
|
||||||
|
} BSPSurface;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///GPL code from IdSofware to parse a Quake 3 BSP file
|
||||||
|
///check that your platform define __BIG_ENDIAN__ correctly (in BspLoader.cpp)
|
||||||
|
class BspLoader
|
||||||
|
{
|
||||||
|
int m_Endianness;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
BspLoader();
|
||||||
|
|
||||||
|
bool loadBSPFile( void* memoryBuffer);
|
||||||
|
|
||||||
|
const char* getValueForKey( const BSPEntity *ent, const char *key ) const;
|
||||||
|
|
||||||
|
bool getVectorForKey( const BSPEntity *ent, const char *key, BSPVector3 vec );
|
||||||
|
|
||||||
|
float getFloatForKey( const BSPEntity *ent, const char *key );
|
||||||
|
|
||||||
|
void parseEntities( void );
|
||||||
|
|
||||||
|
bool findVectorByName(float* outvec,const char* name);
|
||||||
|
|
||||||
|
const BSPEntity * getEntityByValue( const char* name, const char* value);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void parseFromMemory (char *buffer, int size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool isEndOfScript (bool crossline);
|
||||||
|
|
||||||
|
bool getToken (bool crossline);
|
||||||
|
|
||||||
|
char *copystring(const char *s);
|
||||||
|
|
||||||
|
void stripTrailing( char *e );
|
||||||
|
|
||||||
|
BSPKeyValuePair * parseEpair( void );
|
||||||
|
|
||||||
|
bool parseEntity( void );
|
||||||
|
|
||||||
|
short isLittleShort (short l);
|
||||||
|
int isLittleLong (int l);
|
||||||
|
float isLittleFloat (float l);
|
||||||
|
|
||||||
|
int isBigLong (int l);
|
||||||
|
short isBigShort (short l);
|
||||||
|
float isBigFloat (float l);
|
||||||
|
|
||||||
|
void swapBlock( int *block, int sizeOfBlock );
|
||||||
|
|
||||||
|
int copyLump( BSPHeader *header, int lump, void *dest, int size );
|
||||||
|
|
||||||
|
void swapBSPFile( void );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public: //easier for conversion
|
||||||
|
int m_num_entities;
|
||||||
|
btAlignedObjectArray<BSPEntity> m_entities;
|
||||||
|
|
||||||
|
int m_nummodels;
|
||||||
|
btAlignedObjectArray<BSPModel> m_dmodels;
|
||||||
|
|
||||||
|
int m_numShaders;
|
||||||
|
btAlignedObjectArray<BSPShader> m_dshaders;
|
||||||
|
|
||||||
|
int m_entdatasize;
|
||||||
|
btAlignedObjectArray<char> m_dentdata;
|
||||||
|
|
||||||
|
int m_numleafs;
|
||||||
|
btAlignedObjectArray<BSPLeaf> m_dleafs;
|
||||||
|
|
||||||
|
int m_numplanes;
|
||||||
|
btAlignedObjectArray<BSPPlane> m_dplanes;
|
||||||
|
|
||||||
|
int m_numnodes;
|
||||||
|
btAlignedObjectArray<BSPNode> m_dnodes;
|
||||||
|
|
||||||
|
int m_numleafsurfaces;
|
||||||
|
btAlignedObjectArray<int> m_dleafsurfaces;
|
||||||
|
|
||||||
|
int m_numleafbrushes;
|
||||||
|
btAlignedObjectArray<int> m_dleafbrushes;
|
||||||
|
|
||||||
|
int m_numbrushes;
|
||||||
|
btAlignedObjectArray<BSPBrush> m_dbrushes;
|
||||||
|
|
||||||
|
int m_numbrushsides;
|
||||||
|
btAlignedObjectArray<BSPBrushSide> m_dbrushsides;
|
||||||
|
|
||||||
|
int m_numLightBytes;
|
||||||
|
btAlignedObjectArray<unsigned char> m_lightBytes;
|
||||||
|
|
||||||
|
int m_numGridPoints;
|
||||||
|
btAlignedObjectArray<unsigned char> m_gridData;
|
||||||
|
|
||||||
|
int m_numVisBytes;
|
||||||
|
btAlignedObjectArray<unsigned char> m_visBytes;
|
||||||
|
|
||||||
|
|
||||||
|
int m_numDrawIndexes;
|
||||||
|
btAlignedObjectArray<int> m_drawIndexes;
|
||||||
|
|
||||||
|
int m_numDrawSurfaces;
|
||||||
|
btAlignedObjectArray<BSPSurface> m_drawSurfaces;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
BSP_LITTLE_ENDIAN = 0,
|
||||||
|
BSP_BIG_ENDIAN = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
//returns machines big endian / little endian
|
||||||
|
//
|
||||||
|
int getMachineEndianness();
|
||||||
|
|
||||||
|
inline int machineEndianness()
|
||||||
|
{
|
||||||
|
return m_Endianness;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BSP_LOADER_H
|
||||||
295
examples/Importers/ImportBsp/ImportBspExample.cpp
Normal file
295
examples/Importers/ImportBsp/ImportBspExample.cpp
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
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 "ImportBspExample.h"
|
||||||
|
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
|
||||||
|
#include "LinearMath/btQuickprof.h"
|
||||||
|
#include "LinearMath/btIDebugDraw.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define QUAKE_BSP_IMPORTING 1
|
||||||
|
|
||||||
|
#ifdef QUAKE_BSP_IMPORTING
|
||||||
|
#include "BspLoader.h"
|
||||||
|
#include "BspConverter.h"
|
||||||
|
#endif //QUAKE_BSP_IMPORTING
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h> //printf debugging
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/CommonRigidBodyBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
///BspDemo shows the convex collision detection, by converting a Quake BSP file into convex objects and allowing interaction with boxes.
|
||||||
|
class BspDemo : public CommonRigidBodyBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//keep the collision shapes, for deletion/cleanup
|
||||||
|
|
||||||
|
|
||||||
|
BspDemo(struct GUIHelperInterface* helper)
|
||||||
|
:CommonRigidBodyBase(helper)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~BspDemo();
|
||||||
|
|
||||||
|
virtual void initPhysics();
|
||||||
|
|
||||||
|
void initPhysics(const char* bspfilename);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define CUBE_HALF_EXTENTS 1
|
||||||
|
#define EXTRA_HEIGHT -20.f
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///BspToBulletConverter extends the BspConverter to convert to Bullet datastructures
|
||||||
|
class BspToBulletConverter : public BspConverter
|
||||||
|
{
|
||||||
|
BspDemo* m_demoApp;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
BspToBulletConverter(BspDemo* demoApp)
|
||||||
|
:m_demoApp(demoApp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void addConvexVerticesCollider(btAlignedObjectArray<btVector3>& vertices, bool isEntity, const btVector3& entityTargetLocation)
|
||||||
|
{
|
||||||
|
///perhaps we can do something special with entities (isEntity)
|
||||||
|
///like adding a collision Triggering (as example)
|
||||||
|
|
||||||
|
if (vertices.size() > 0)
|
||||||
|
{
|
||||||
|
float mass = 0.f;
|
||||||
|
btTransform startTransform;
|
||||||
|
//can use a shift
|
||||||
|
startTransform.setIdentity();
|
||||||
|
startTransform.setOrigin(btVector3(0,0,-10.f));
|
||||||
|
//this create an internal copy of the vertices
|
||||||
|
|
||||||
|
btCollisionShape* shape = new btConvexHullShape(&(vertices[0].getX()),vertices.size());
|
||||||
|
m_demoApp->m_collisionShapes.push_back(shape);
|
||||||
|
|
||||||
|
//btRigidBody* body = m_demoApp->localCreateRigidBody(mass, startTransform,shape);
|
||||||
|
m_demoApp->createRigidBody(mass, startTransform,shape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BspDemo::~BspDemo()
|
||||||
|
{
|
||||||
|
exitPhysics(); //will delete all default data
|
||||||
|
}
|
||||||
|
|
||||||
|
void BspDemo::initPhysics()
|
||||||
|
{
|
||||||
|
const char* bspfilename = "BspDemo.bsp";
|
||||||
|
|
||||||
|
initPhysics(bspfilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void BspDemo::initPhysics(const char* bspfilename)
|
||||||
|
{
|
||||||
|
|
||||||
|
int cameraUpAxis =2;
|
||||||
|
btVector3 grav(0,0,0);
|
||||||
|
grav[cameraUpAxis] = -10;
|
||||||
|
m_guiHelper->setUpAxis(cameraUpAxis);
|
||||||
|
|
||||||
|
//_cameraUp = btVector3(0,0,1);
|
||||||
|
//_forwardAxis = 1;
|
||||||
|
|
||||||
|
//etCameraDistance(22.f);
|
||||||
|
|
||||||
|
///Setup a Physics Simulation Environment
|
||||||
|
|
||||||
|
m_collisionConfiguration = new btDefaultCollisionConfiguration();
|
||||||
|
// btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50));
|
||||||
|
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
|
||||||
|
btVector3 worldMin(-1000,-1000,-1000);
|
||||||
|
btVector3 worldMax(1000,1000,1000);
|
||||||
|
m_broadphase = new btDbvtBroadphase();
|
||||||
|
//m_broadphase = new btAxisSweep3(worldMin,worldMax);
|
||||||
|
//btOverlappingPairCache* broadphase = new btSimpleBroadphase();
|
||||||
|
m_solver = new btSequentialImpulseConstraintSolver();
|
||||||
|
//ConstraintSolver* solver = new OdeConstraintSolver;
|
||||||
|
m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
|
||||||
|
|
||||||
|
m_dynamicsWorld->setGravity(grav);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef QUAKE_BSP_IMPORTING
|
||||||
|
|
||||||
|
void* memoryBuffer = 0;
|
||||||
|
|
||||||
|
const char* filename = "BspDemo.bsp";
|
||||||
|
|
||||||
|
const char* prefix[]={"./","./data/","../data/","../../data/","../../../data/","../../../../data/"};
|
||||||
|
int numPrefixes = sizeof(prefix)/sizeof(const char*);
|
||||||
|
char relativeFileName[1024];
|
||||||
|
FILE* file=0;
|
||||||
|
|
||||||
|
for (int i=0;i<numPrefixes;i++)
|
||||||
|
{
|
||||||
|
sprintf(relativeFileName,"%s%s",prefix[i],filename);
|
||||||
|
file = fopen(relativeFileName,"r");
|
||||||
|
if (file)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
BspLoader bspLoader;
|
||||||
|
int size=0;
|
||||||
|
if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */
|
||||||
|
printf("Error: cannot get filesize from %s\n", bspfilename);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//how to detect file size?
|
||||||
|
memoryBuffer = malloc(size+1);
|
||||||
|
fread(memoryBuffer,1,size,file);
|
||||||
|
bspLoader.loadBSPFile( memoryBuffer);
|
||||||
|
|
||||||
|
BspToBulletConverter bsp2bullet(this);
|
||||||
|
float bspScaling = 0.1f;
|
||||||
|
bsp2bullet.convertBsp(bspLoader,bspScaling);
|
||||||
|
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//some code that de-mangles the windows filename passed in as argument
|
||||||
|
char cleaned_filename[512];
|
||||||
|
char* getLastFileName()
|
||||||
|
{
|
||||||
|
return cleaned_filename;
|
||||||
|
}
|
||||||
|
char* makeExeToBspFilename(const char* lpCmdLine)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// We might get a windows-style path on the command line, this can mess up the DOM which expects
|
||||||
|
// all paths to be URI's. This block of code does some conversion to try and make the input
|
||||||
|
// compliant without breaking the ability to accept a properly formatted URI. Right now this only
|
||||||
|
// displays the first filename
|
||||||
|
const char *in = lpCmdLine;
|
||||||
|
char* out = cleaned_filename;
|
||||||
|
*out = '\0';
|
||||||
|
// If the first character is a ", skip it (filenames with spaces in them are quoted)
|
||||||
|
if(*in == '\"')
|
||||||
|
{
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
for(i =0; i<512; i++)
|
||||||
|
{
|
||||||
|
//if we get '.' we stop as well, unless it's the first character. Then we add .bsp as extension
|
||||||
|
// If we hit a null or a quote, stop copying. This will get just the first filename.
|
||||||
|
if(i && (in[0] == '.') && (in[1] == 'e') && (in[2] == 'x') && (in[3] == 'e'))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// If we hit a null or a quote, stop copying. This will get just the first filename.
|
||||||
|
if(*in == '\0' || *in == '\"')
|
||||||
|
break;
|
||||||
|
// Copy while swapping backslashes for forward ones
|
||||||
|
if(*in == '\\')
|
||||||
|
{
|
||||||
|
*out = '/';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*out = *in;
|
||||||
|
}
|
||||||
|
in++;
|
||||||
|
out++;
|
||||||
|
}
|
||||||
|
*(out++) = '.';
|
||||||
|
*(out++) = 'b';
|
||||||
|
*(out++) = 's';
|
||||||
|
*(out++) = 'p';
|
||||||
|
*(out++) = 0;
|
||||||
|
|
||||||
|
return cleaned_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ExampleInterface* ImportBspCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option)
|
||||||
|
{
|
||||||
|
BspDemo* demo = new BspDemo(helper);
|
||||||
|
|
||||||
|
demo->initPhysics("BspDemo.bsp");
|
||||||
|
return demo;
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
static DemoApplication* Create()
|
||||||
|
{
|
||||||
|
BspDemo* demo = new BspDemo;
|
||||||
|
demo->myinit();
|
||||||
|
demo->initPhysics("BspDemo.bsp");
|
||||||
|
return demo;
|
||||||
|
}
|
||||||
|
*/
|
||||||
23
examples/Importers/ImportBsp/ImportBspExample.h
Normal file
23
examples/Importers/ImportBsp/ImportBspExample.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
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 BSP_DEMO_H
|
||||||
|
#define BSP_DEMO_H
|
||||||
|
|
||||||
|
struct ExampleInterface* ImportBspCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //BSP_DEMO_H
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Bullet Collision Detection and Physics Library http://bulletphysics.org
|
||||||
|
This file is Copyright (c) 2014 Google Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
//original author: Erwin Coumans
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COLLADA_GRAPHICS_INSTANCE_H
|
||||||
|
#define COLLADA_GRAPHICS_INSTANCE_H
|
||||||
|
|
||||||
|
#include "btMatrix4x4.h"
|
||||||
|
|
||||||
|
struct ColladaGraphicsInstance
|
||||||
|
{
|
||||||
|
ColladaGraphicsInstance()
|
||||||
|
:m_shapeIndex(-1)
|
||||||
|
{
|
||||||
|
m_worldTransform.setIdentity();
|
||||||
|
}
|
||||||
|
btMatrix4x4 m_worldTransform;
|
||||||
|
int m_shapeIndex;//could be index into array of GLInstanceGraphicsShape
|
||||||
|
float m_color[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //COLLADA_GRAPHICS_INSTANCE_H
|
||||||
203
examples/Importers/ImportColladaDemo/ImportColladaSetup.cpp
Normal file
203
examples/Importers/ImportColladaDemo/ImportColladaSetup.cpp
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
Bullet Collision Detection and Physics Library http://bulletphysics.org
|
||||||
|
This file is Copyright (c) 2014 Google Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
//original author: Erwin Coumans
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ImportColladaSetup.h"
|
||||||
|
#include <vector>
|
||||||
|
#include "../OpenGLWindow/GLInstancingRenderer.h"
|
||||||
|
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
#include "../OpenGLWindow/SimpleOpenGL3App.h"
|
||||||
|
#include "LoadMeshFromCollada.h"
|
||||||
|
#include "Bullet3Common/b3FileUtils.h"
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/CommonRigidBodyBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ImportColladaSetup : public CommonRigidBodyBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
ImportColladaSetup(struct GUIHelperInterface* helper);
|
||||||
|
virtual ~ImportColladaSetup();
|
||||||
|
|
||||||
|
virtual void initPhysics();
|
||||||
|
};
|
||||||
|
|
||||||
|
ImportColladaSetup::ImportColladaSetup(struct GUIHelperInterface* helper)
|
||||||
|
:CommonRigidBodyBase(helper)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportColladaSetup::~ImportColladaSetup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ColladaGraphicsInstanceSortfnc(const ColladaGraphicsInstance& a,const ColladaGraphicsInstance& b)
|
||||||
|
{
|
||||||
|
if (a.m_shapeIndex<b.m_shapeIndex) return +1;
|
||||||
|
if (a.m_shapeIndex>b.m_shapeIndex) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ImportColladaSetup::initPhysics()
|
||||||
|
{
|
||||||
|
int upAxis=1;
|
||||||
|
m_guiHelper->setUpAxis(upAxis);
|
||||||
|
this->createEmptyDynamicsWorld();
|
||||||
|
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
|
||||||
|
m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
|
||||||
|
|
||||||
|
static int fileIndex = 0;
|
||||||
|
|
||||||
|
const char* fileNames[] = {
|
||||||
|
"duck.dae",
|
||||||
|
"seymourplane_triangulate.dae",
|
||||||
|
};
|
||||||
|
const char* fileName = fileNames[fileIndex];
|
||||||
|
int numFiles = sizeof(fileNames)/sizeof(const char*);
|
||||||
|
|
||||||
|
char relativeFileName[1024];
|
||||||
|
|
||||||
|
b3FileUtils f;
|
||||||
|
if (!f.findFile(fileName,relativeFileName,1024))
|
||||||
|
return;
|
||||||
|
|
||||||
|
btVector3 shift(0,0,0);
|
||||||
|
btVector3 scaling(1,1,1);
|
||||||
|
// int index=10;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
btAlignedObjectArray<GLInstanceGraphicsShape> visualShapes;
|
||||||
|
btAlignedObjectArray<ColladaGraphicsInstance> visualShapeInstances;
|
||||||
|
|
||||||
|
float unitMeterScaling(1);
|
||||||
|
btTransform upAxisTrans;
|
||||||
|
upAxisTrans.setIdentity();
|
||||||
|
|
||||||
|
btVector3 color(0,0,1);
|
||||||
|
|
||||||
|
#ifdef COMPARE_WITH_ASSIMP
|
||||||
|
static int useAssimp = 0;
|
||||||
|
if (useAssimp)
|
||||||
|
{
|
||||||
|
|
||||||
|
LoadMeshFromColladaAssimp(relativeFileName, visualShapes, visualShapeInstances,upAxisTrans,unitMeterScaling);
|
||||||
|
fileIndex++;
|
||||||
|
if (fileIndex>=numFiles)
|
||||||
|
{
|
||||||
|
fileIndex = 0;
|
||||||
|
}
|
||||||
|
color.setValue(1,0,0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoadMeshFromCollada(relativeFileName, visualShapes, visualShapeInstances,upAxisTrans,unitMeterScaling);
|
||||||
|
|
||||||
|
}
|
||||||
|
useAssimp=1-useAssimp;
|
||||||
|
#else
|
||||||
|
fileIndex++;
|
||||||
|
if (fileIndex>=numFiles)
|
||||||
|
{
|
||||||
|
fileIndex = 0;
|
||||||
|
}
|
||||||
|
LoadMeshFromCollada(relativeFileName, visualShapes, visualShapeInstances,upAxisTrans,unitMeterScaling, upAxis);
|
||||||
|
#endif// COMPARE_WITH_ASSIMP
|
||||||
|
|
||||||
|
|
||||||
|
//at the moment our graphics engine requires instances that share the same visual shape to be added right after registering the shape
|
||||||
|
//so perform a sort, just to be sure
|
||||||
|
visualShapeInstances.quickSort(ColladaGraphicsInstanceSortfnc);
|
||||||
|
|
||||||
|
for (int i=0;i<visualShapeInstances.size();i++)
|
||||||
|
{
|
||||||
|
ColladaGraphicsInstance* instance = &visualShapeInstances[i];
|
||||||
|
GLInstanceGraphicsShape* gfxShape = &visualShapes[instance->m_shapeIndex];
|
||||||
|
btVector3 position(0,0,0);// = scaling*btVector3(instance->m_pos[0],instance->m_pos[1],instance->m_pos[2]);
|
||||||
|
btQuaternion orn(0,0,0,1);//instance->m_orn[0],instance->m_orn[1],instance->m_orn[2],instance->m_orn[3]);
|
||||||
|
|
||||||
|
//sort the visualShapeInstances, then iterate etc
|
||||||
|
//void LoadMeshFromCollada(const char* relativeFileName,
|
||||||
|
//btAlignedObjectArray<GLInstanceGraphicsShape>& visualShapes,
|
||||||
|
//btAlignedObjectArray<GLInstanceGraphicsInstance> visualShapeInstances);
|
||||||
|
|
||||||
|
if (gfxShape)
|
||||||
|
{
|
||||||
|
//btTransform trans;
|
||||||
|
//trans.setIdentity();
|
||||||
|
//trans.setRotation(btQuaternion(btVector3(1,0,0),SIMD_HALF_PI));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
b3AlignedObjectArray<GLInstanceVertex> verts;
|
||||||
|
verts.resize(gfxShape->m_vertices->size());
|
||||||
|
|
||||||
|
for (int i=0;i<gfxShape->m_vertices->size();i++)
|
||||||
|
{
|
||||||
|
verts[i].normal[0] = gfxShape->m_vertices->at(i).normal[0];
|
||||||
|
verts[i].normal[1] = gfxShape->m_vertices->at(i).normal[1];
|
||||||
|
verts[i].normal[2] = gfxShape->m_vertices->at(i).normal[2];
|
||||||
|
verts[i].uv[0] = gfxShape->m_vertices->at(i).uv[0];
|
||||||
|
verts[i].uv[1] = gfxShape->m_vertices->at(i).uv[1];
|
||||||
|
verts[i].xyzw[0] = gfxShape->m_vertices->at(i).xyzw[0];
|
||||||
|
verts[i].xyzw[1] = gfxShape->m_vertices->at(i).xyzw[1];
|
||||||
|
verts[i].xyzw[2] = gfxShape->m_vertices->at(i).xyzw[2];
|
||||||
|
verts[i].xyzw[3] = gfxShape->m_vertices->at(i).xyzw[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
//compensate upAxisTrans and unitMeterScaling here
|
||||||
|
btMatrix4x4 upAxisMat;
|
||||||
|
upAxisMat.setPureRotation(upAxisTrans.getRotation());
|
||||||
|
btMatrix4x4 unitMeterScalingMat;
|
||||||
|
unitMeterScalingMat.setPureScaling(btVector3(unitMeterScaling,unitMeterScaling,unitMeterScaling));
|
||||||
|
btMatrix4x4 worldMat = unitMeterScalingMat*upAxisMat*instance->m_worldTransform;
|
||||||
|
//btMatrix4x4 worldMat = instance->m_worldTransform;
|
||||||
|
for(int v=0;v<verts.size();v++)
|
||||||
|
{
|
||||||
|
btVector3 pos(verts[v].xyzw[0],verts[v].xyzw[1],verts[v].xyzw[2]);
|
||||||
|
pos = worldMat*pos;
|
||||||
|
verts[v].xyzw[0] = float(pos[0]);
|
||||||
|
verts[v].xyzw[1] = float(pos[1]);
|
||||||
|
verts[v].xyzw[2] = float(pos[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int shapeId = m_guiHelper->getRenderInterface()->registerShape(&verts[0].xyzw[0], gfxShape->m_numvertices, &gfxShape->m_indices->at(0), gfxShape->m_numIndices);
|
||||||
|
|
||||||
|
//btVector3 instanceScaling(instance->m_scaling[0],instance->m_scaling[1],instance->m_scaling[2]);
|
||||||
|
m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleInterface* ImportColladaCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option)
|
||||||
|
{
|
||||||
|
return new ImportColladaSetup(helper);
|
||||||
|
}
|
||||||
25
examples/Importers/ImportColladaDemo/ImportColladaSetup.h
Normal file
25
examples/Importers/ImportColladaDemo/ImportColladaSetup.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
Bullet Collision Detection and Physics Library http://bulletphysics.org
|
||||||
|
This file is Copyright (c) 2014 Google Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
//original author: Erwin Coumans
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IMPORT_COLLADA_SETUP_H
|
||||||
|
#define IMPORT_COLLADA_SETUP_H
|
||||||
|
|
||||||
|
class ExampleInterface* ImportColladaCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //IMPORT_COLLADA_SETUP_H
|
||||||
748
examples/Importers/ImportColladaDemo/LoadMeshFromCollada.cpp
Normal file
748
examples/Importers/ImportColladaDemo/LoadMeshFromCollada.cpp
Normal file
@@ -0,0 +1,748 @@
|
|||||||
|
/*
|
||||||
|
Bullet Collision Detection and Physics Library http://bulletphysics.org
|
||||||
|
This file is Copyright (c) 2014 Google Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
//original author: Erwin Coumans
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "LoadMeshFromCollada.h"
|
||||||
|
#include <stdio.h> //fopen
|
||||||
|
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||||
|
#include <string>
|
||||||
|
#include "tinyxml/tinyxml.h"
|
||||||
|
|
||||||
|
#include "Bullet3Common/b3FileUtils.h"
|
||||||
|
#include "LinearMath/btHashMap.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include "btMatrix4x4.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct VertexSource
|
||||||
|
{
|
||||||
|
std::string m_positionArrayId;
|
||||||
|
std::string m_normalArrayId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TokenFloatArray
|
||||||
|
{
|
||||||
|
btAlignedObjectArray<float>& m_values;
|
||||||
|
TokenFloatArray(btAlignedObjectArray<float>& floatArray)
|
||||||
|
:m_values(floatArray) {
|
||||||
|
}
|
||||||
|
inline void add(const char* token)
|
||||||
|
{
|
||||||
|
float v = atof(token);
|
||||||
|
m_values.push_back(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct TokenIntArray
|
||||||
|
{
|
||||||
|
btAlignedObjectArray<int>& m_values;
|
||||||
|
TokenIntArray(btAlignedObjectArray<int>& intArray)
|
||||||
|
:m_values(intArray) {
|
||||||
|
}
|
||||||
|
inline void add(const char* token)
|
||||||
|
{
|
||||||
|
float v = atoi(token);
|
||||||
|
m_values.push_back(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename AddToken>
|
||||||
|
void tokenize(const std::string& str, AddToken& tokenAdder, const std::string& delimiters = " ")
|
||||||
|
{
|
||||||
|
std::string::size_type pos, lastPos = 0;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
pos = str.find_first_of(delimiters, lastPos);
|
||||||
|
if(pos == std::string::npos)
|
||||||
|
{
|
||||||
|
pos = str.length();
|
||||||
|
if(pos != lastPos)
|
||||||
|
{
|
||||||
|
tokenAdder.add(str.data()+lastPos);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(pos != lastPos)
|
||||||
|
{
|
||||||
|
tokenAdder.add(str.data()+lastPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastPos = pos + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void readFloatArray(TiXmlElement* source, btAlignedObjectArray<float>& floatArray, int& componentStride)
|
||||||
|
{
|
||||||
|
int numVals, stride;
|
||||||
|
TiXmlElement* array = source->FirstChildElement("float_array");
|
||||||
|
if(array)
|
||||||
|
{
|
||||||
|
componentStride = 1;
|
||||||
|
if (source->FirstChildElement("technique_common")->FirstChildElement("accessor")->QueryIntAttribute("stride", &stride)!= TIXML_NO_ATTRIBUTE)
|
||||||
|
{
|
||||||
|
componentStride = stride;
|
||||||
|
}
|
||||||
|
array->QueryIntAttribute("count", &numVals);
|
||||||
|
TokenFloatArray adder(floatArray);
|
||||||
|
floatArray.reserve(numVals);
|
||||||
|
tokenize(array->GetText(),adder);
|
||||||
|
assert(floatArray.size() == numVals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btVector3 getVector3FromXmlText(const char* text)
|
||||||
|
{
|
||||||
|
btVector3 vec(0,0,0);
|
||||||
|
btAlignedObjectArray<float> floatArray;
|
||||||
|
TokenFloatArray adder(floatArray);
|
||||||
|
floatArray.reserve(3);
|
||||||
|
tokenize(text,adder);
|
||||||
|
assert(floatArray.size() == 3);
|
||||||
|
if (floatArray.size()==3)
|
||||||
|
{
|
||||||
|
vec.setValue(floatArray[0],floatArray[1],floatArray[2]);
|
||||||
|
}
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
btVector4 getVector4FromXmlText(const char* text)
|
||||||
|
{
|
||||||
|
btVector4 vec(0,0,0,0);
|
||||||
|
btAlignedObjectArray<float> floatArray;
|
||||||
|
TokenFloatArray adder(floatArray);
|
||||||
|
floatArray.reserve(4);
|
||||||
|
tokenize(text,adder);
|
||||||
|
assert(floatArray.size() == 4);
|
||||||
|
if (floatArray.size()==4)
|
||||||
|
{
|
||||||
|
vec.setValue(floatArray[0],floatArray[1],floatArray[2],floatArray[3]);
|
||||||
|
}
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void readLibraryGeometries(TiXmlDocument& doc, btAlignedObjectArray<GLInstanceGraphicsShape>& visualShapes, btHashMap<btHashString,int>& name2Shape, float extraScaling)
|
||||||
|
{
|
||||||
|
btHashMap<btHashString,TiXmlElement* > allSources;
|
||||||
|
btHashMap<btHashString,VertexSource> vertexSources;
|
||||||
|
for(TiXmlElement* geometry = doc.RootElement()->FirstChildElement("library_geometries")->FirstChildElement("geometry");
|
||||||
|
geometry != NULL; geometry = geometry->NextSiblingElement("geometry"))
|
||||||
|
{
|
||||||
|
btAlignedObjectArray<btVector3> vertexPositions;
|
||||||
|
btAlignedObjectArray<btVector3> vertexNormals;
|
||||||
|
btAlignedObjectArray<int> indices;
|
||||||
|
|
||||||
|
const char* geometryName = geometry->Attribute("id");
|
||||||
|
for (TiXmlElement* mesh = geometry->FirstChildElement("mesh");(mesh != NULL); mesh = mesh->NextSiblingElement("mesh"))
|
||||||
|
{
|
||||||
|
TiXmlElement* vertices2 = mesh->FirstChildElement("vertices");
|
||||||
|
|
||||||
|
for (TiXmlElement* source = mesh->FirstChildElement("source");source != NULL;source = source->NextSiblingElement("source"))
|
||||||
|
{
|
||||||
|
const char* srcId= source->Attribute("id");
|
||||||
|
// printf("source id=%s\n",srcId);
|
||||||
|
allSources.insert(srcId,source);
|
||||||
|
}
|
||||||
|
const char* vertexId = vertices2->Attribute("id");
|
||||||
|
//printf("vertices id=%s\n",vertexId);
|
||||||
|
VertexSource vs;
|
||||||
|
for(TiXmlElement* input = vertices2->FirstChildElement("input");input != NULL;input = input->NextSiblingElement("input"))
|
||||||
|
{
|
||||||
|
const char* sem = input->Attribute("semantic");
|
||||||
|
std::string semName(sem);
|
||||||
|
// printf("sem=%s\n",sem);
|
||||||
|
const char* src = input->Attribute("source");
|
||||||
|
// printf("src=%s\n",src);
|
||||||
|
const char* srcIdRef = input->Attribute("source");
|
||||||
|
std::string source_name;
|
||||||
|
source_name = std::string(srcIdRef);
|
||||||
|
source_name = source_name.erase(0, 1);
|
||||||
|
if (semName=="POSITION")
|
||||||
|
{
|
||||||
|
vs.m_positionArrayId = source_name;
|
||||||
|
}
|
||||||
|
if (semName=="NORMAL")
|
||||||
|
{
|
||||||
|
vs.m_normalArrayId = source_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vertexSources.insert(vertexId,vs);
|
||||||
|
|
||||||
|
for (TiXmlElement* primitive = mesh->FirstChildElement("triangles"); primitive; primitive = primitive->NextSiblingElement("triangles"))
|
||||||
|
{
|
||||||
|
std::string positionSourceName;
|
||||||
|
std::string normalSourceName;
|
||||||
|
int primitiveCount;
|
||||||
|
primitive->QueryIntAttribute("count", &primitiveCount);
|
||||||
|
bool positionAndNormalInVertex=false;
|
||||||
|
int indexStride=1;
|
||||||
|
int posOffset = 0;
|
||||||
|
int normalOffset = 0;
|
||||||
|
int numIndices = 0;
|
||||||
|
{
|
||||||
|
for (TiXmlElement* input = primitive->FirstChildElement("input");input != NULL;input = input->NextSiblingElement("input"))
|
||||||
|
{
|
||||||
|
const char* sem = input->Attribute("semantic");
|
||||||
|
std::string semName(sem);
|
||||||
|
int offset = atoi(input->Attribute("offset"));
|
||||||
|
if ((offset+1)>indexStride)
|
||||||
|
indexStride=offset+1;
|
||||||
|
//printf("sem=%s\n",sem);
|
||||||
|
const char* src = input->Attribute("source");
|
||||||
|
//printf("src=%s\n",src);
|
||||||
|
const char* srcIdRef = input->Attribute("source");
|
||||||
|
std::string source_name;
|
||||||
|
source_name = std::string(srcIdRef);
|
||||||
|
source_name = source_name.erase(0, 1);
|
||||||
|
|
||||||
|
if (semName=="VERTEX")
|
||||||
|
{
|
||||||
|
//now we have POSITION and possibly NORMAL too, using same index array (<p>)
|
||||||
|
VertexSource* vs = vertexSources[source_name.c_str()];
|
||||||
|
if (vs->m_positionArrayId.length())
|
||||||
|
{
|
||||||
|
positionSourceName = vs->m_positionArrayId;
|
||||||
|
posOffset = offset;
|
||||||
|
}
|
||||||
|
if (vs->m_normalArrayId.length())
|
||||||
|
{
|
||||||
|
normalSourceName = vs->m_normalArrayId;
|
||||||
|
normalOffset = offset;
|
||||||
|
positionAndNormalInVertex = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (semName=="NORMAL")
|
||||||
|
{
|
||||||
|
btAssert(normalSourceName.length()==0);
|
||||||
|
normalSourceName = source_name;
|
||||||
|
normalOffset = offset;
|
||||||
|
positionAndNormalInVertex = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
numIndices = primitiveCount * 3;
|
||||||
|
}
|
||||||
|
btAlignedObjectArray<float> positionFloatArray;
|
||||||
|
int posStride=1;
|
||||||
|
TiXmlElement** sourcePtr = allSources[positionSourceName.c_str()];
|
||||||
|
if (sourcePtr)
|
||||||
|
{
|
||||||
|
readFloatArray(*sourcePtr,positionFloatArray, posStride);
|
||||||
|
}
|
||||||
|
btAlignedObjectArray<float> normalFloatArray;
|
||||||
|
int normalStride=1;
|
||||||
|
sourcePtr = allSources[normalSourceName.c_str()];
|
||||||
|
if (sourcePtr)
|
||||||
|
{
|
||||||
|
readFloatArray(*sourcePtr,normalFloatArray,normalStride);
|
||||||
|
}
|
||||||
|
btAlignedObjectArray<int> curIndices;
|
||||||
|
curIndices.reserve(numIndices*indexStride);
|
||||||
|
TokenIntArray adder(curIndices);
|
||||||
|
tokenize(primitive->FirstChildElement("p")->GetText(),adder);
|
||||||
|
assert(curIndices.size() == numIndices*indexStride);
|
||||||
|
int indexOffset = vertexPositions.size();
|
||||||
|
|
||||||
|
for(int index=0; index<numIndices; index++)
|
||||||
|
{
|
||||||
|
int posIndex = curIndices[index*indexStride+posOffset];
|
||||||
|
int normalIndex = curIndices[index*indexStride+normalOffset];
|
||||||
|
vertexPositions.push_back(btVector3(extraScaling*positionFloatArray[posIndex*3+0],
|
||||||
|
extraScaling*positionFloatArray[posIndex*3+1],
|
||||||
|
extraScaling*positionFloatArray[posIndex*3+2]));
|
||||||
|
|
||||||
|
if (normalFloatArray.size() && (normalFloatArray.size()>normalIndex))
|
||||||
|
{
|
||||||
|
vertexNormals.push_back(btVector3(normalFloatArray[normalIndex*3+0],
|
||||||
|
normalFloatArray[normalIndex*3+1],
|
||||||
|
normalFloatArray[normalIndex*3+2]));
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//add a dummy normal of length zero, so it is easy to detect that it is an invalid normal
|
||||||
|
vertexNormals.push_back(btVector3(0,0,0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int curNumIndices = indices.size();
|
||||||
|
indices.resize(curNumIndices+numIndices);
|
||||||
|
for(int index=0; index<numIndices; index++)
|
||||||
|
{
|
||||||
|
indices[curNumIndices+index] = index+indexOffset;
|
||||||
|
}
|
||||||
|
}//if(primitive != NULL)
|
||||||
|
}//for each mesh
|
||||||
|
|
||||||
|
int shapeIndex = visualShapes.size();
|
||||||
|
GLInstanceGraphicsShape& visualShape = visualShapes.expand();
|
||||||
|
{
|
||||||
|
visualShape.m_vertices = new b3AlignedObjectArray<GLInstanceVertex>;
|
||||||
|
visualShape.m_indices = new b3AlignedObjectArray<int>;
|
||||||
|
int indexBase = 0;
|
||||||
|
|
||||||
|
btAssert(vertexNormals.size()==vertexPositions.size());
|
||||||
|
for (int v=0;v<vertexPositions.size();v++)
|
||||||
|
{
|
||||||
|
GLInstanceVertex vtx;
|
||||||
|
vtx.xyzw[0] = vertexPositions[v].x();
|
||||||
|
vtx.xyzw[1] = vertexPositions[v].y();
|
||||||
|
vtx.xyzw[2] = vertexPositions[v].z();
|
||||||
|
vtx.xyzw[3] = 1.f;
|
||||||
|
vtx.normal[0] = vertexNormals[v].x();
|
||||||
|
vtx.normal[1] = vertexNormals[v].y();
|
||||||
|
vtx.normal[2] = vertexNormals[v].z();
|
||||||
|
vtx.uv[0] = 0.5f;
|
||||||
|
vtx.uv[1] = 0.5f;
|
||||||
|
visualShape.m_vertices->push_back(vtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index=0;index<indices.size();index++)
|
||||||
|
{
|
||||||
|
visualShape.m_indices->push_back(indices[index]+indexBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
printf(" index_count =%dand vertexPositions.size=%d\n",indices.size(), vertexPositions.size());
|
||||||
|
indexBase=visualShape.m_vertices->size();
|
||||||
|
visualShape.m_numIndices = visualShape.m_indices->size();
|
||||||
|
visualShape.m_numvertices = visualShape.m_vertices->size();
|
||||||
|
}
|
||||||
|
printf("geometry name=%s\n",geometryName);
|
||||||
|
name2Shape.insert(geometryName,shapeIndex);
|
||||||
|
|
||||||
|
|
||||||
|
}//for each geometry
|
||||||
|
}
|
||||||
|
|
||||||
|
void readNodeHierarchy(TiXmlElement* node,btHashMap<btHashString,int>& name2Shape, btAlignedObjectArray<ColladaGraphicsInstance>& visualShapeInstances, const btMatrix4x4& parentTransMat)
|
||||||
|
{
|
||||||
|
const char* nodeName = node->Attribute("id");
|
||||||
|
printf("processing node %s\n", nodeName);
|
||||||
|
|
||||||
|
|
||||||
|
btMatrix4x4 nodeTrans;
|
||||||
|
nodeTrans.setIdentity();
|
||||||
|
|
||||||
|
///todo(erwincoumans) we probably have to read the elements 'translate', 'scale', 'rotate' and 'matrix' in-order and accumulate them...
|
||||||
|
{
|
||||||
|
for (TiXmlElement* transElem = node->FirstChildElement("matrix");transElem;transElem=node->NextSiblingElement("matrix"))
|
||||||
|
{
|
||||||
|
if (transElem->GetText())
|
||||||
|
{
|
||||||
|
btAlignedObjectArray<float> floatArray;
|
||||||
|
TokenFloatArray adder(floatArray);
|
||||||
|
tokenize(transElem->GetText(),adder);
|
||||||
|
if (floatArray.size()==16)
|
||||||
|
{
|
||||||
|
btMatrix4x4 t(floatArray[0],floatArray[1],floatArray[2],floatArray[3],
|
||||||
|
floatArray[4],floatArray[5],floatArray[6],floatArray[7],
|
||||||
|
floatArray[8],floatArray[9],floatArray[10],floatArray[11],
|
||||||
|
floatArray[12],floatArray[13],floatArray[14],floatArray[15]);
|
||||||
|
|
||||||
|
nodeTrans = nodeTrans*t;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
printf("Error: expected 16 elements in a <matrix> element, skipping\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
for (TiXmlElement* transElem = node->FirstChildElement("translate");transElem;transElem=node->NextSiblingElement("translate"))
|
||||||
|
{
|
||||||
|
if (transElem->GetText())
|
||||||
|
{
|
||||||
|
btVector3 pos = getVector3FromXmlText(transElem->GetText());
|
||||||
|
//nodePos+= unitScaling*parentScaling*pos;
|
||||||
|
btMatrix4x4 t;
|
||||||
|
t.setPureTranslation(pos);
|
||||||
|
nodeTrans = nodeTrans*t;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
for(TiXmlElement* scaleElem = node->FirstChildElement("scale");
|
||||||
|
scaleElem!= NULL; scaleElem= node->NextSiblingElement("scale"))
|
||||||
|
{
|
||||||
|
if (scaleElem->GetText())
|
||||||
|
{
|
||||||
|
btVector3 scaling = getVector3FromXmlText(scaleElem->GetText());
|
||||||
|
btMatrix4x4 t;
|
||||||
|
t.setPureScaling(scaling);
|
||||||
|
nodeTrans = nodeTrans*t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
for(TiXmlElement* rotateElem = node->FirstChildElement("rotate");
|
||||||
|
rotateElem!= NULL; rotateElem= node->NextSiblingElement("rotate"))
|
||||||
|
{
|
||||||
|
if (rotateElem->GetText())
|
||||||
|
{
|
||||||
|
//accumulate orientation
|
||||||
|
btVector4 rotate = getVector4FromXmlText(rotateElem->GetText());
|
||||||
|
btQuaternion orn(btVector3(rotate),btRadians(rotate[3]));//COLLADA DAE rotate is in degrees, convert to radians
|
||||||
|
btMatrix4x4 t;
|
||||||
|
t.setPureRotation(orn);
|
||||||
|
nodeTrans = nodeTrans*t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeTrans = parentTransMat*nodeTrans;
|
||||||
|
|
||||||
|
for (TiXmlElement* instanceGeom = node->FirstChildElement("instance_geometry");
|
||||||
|
instanceGeom!=0;
|
||||||
|
instanceGeom=instanceGeom->NextSiblingElement("instance_geometry"))
|
||||||
|
{
|
||||||
|
const char* geomUrl = instanceGeom->Attribute("url");
|
||||||
|
printf("node referring to geom %s\n", geomUrl);
|
||||||
|
geomUrl++;
|
||||||
|
int* shapeIndexPtr = name2Shape[geomUrl];
|
||||||
|
if (shapeIndexPtr)
|
||||||
|
{
|
||||||
|
int index = *shapeIndexPtr;
|
||||||
|
printf("found geom with index %d\n", *shapeIndexPtr);
|
||||||
|
ColladaGraphicsInstance& instance = visualShapeInstances.expand();
|
||||||
|
instance.m_shapeIndex = *shapeIndexPtr;
|
||||||
|
instance.m_worldTransform = nodeTrans;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
printf("geom not found\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(TiXmlElement* childNode = node->FirstChildElement("node");
|
||||||
|
childNode!= NULL; childNode = childNode->NextSiblingElement("node"))
|
||||||
|
{
|
||||||
|
readNodeHierarchy(childNode,name2Shape,visualShapeInstances, nodeTrans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void readVisualSceneInstanceGeometries(TiXmlDocument& doc, btHashMap<btHashString,int>& name2Shape, btAlignedObjectArray<ColladaGraphicsInstance>& visualShapeInstances)
|
||||||
|
{
|
||||||
|
btHashMap<btHashString,TiXmlElement* > allVisualScenes;
|
||||||
|
|
||||||
|
TiXmlElement* libVisualScenes = doc.RootElement()->FirstChildElement("library_visual_scenes");
|
||||||
|
if (libVisualScenes==0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
{
|
||||||
|
for(TiXmlElement* scene = libVisualScenes->FirstChildElement("visual_scene");
|
||||||
|
scene != NULL; scene = scene->NextSiblingElement("visual_scene"))
|
||||||
|
{
|
||||||
|
const char* sceneName = scene->Attribute("id");
|
||||||
|
allVisualScenes.insert(sceneName,scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TiXmlElement* scene = 0;
|
||||||
|
{
|
||||||
|
TiXmlElement* scenes = doc.RootElement()->FirstChildElement("scene");
|
||||||
|
if (scenes)
|
||||||
|
{
|
||||||
|
TiXmlElement* instanceSceneReference = scenes->FirstChildElement("instance_visual_scene");
|
||||||
|
if (instanceSceneReference)
|
||||||
|
{
|
||||||
|
const char* instanceSceneUrl = instanceSceneReference->Attribute("url");
|
||||||
|
TiXmlElement** sceneInstancePtr = allVisualScenes[instanceSceneUrl+1];//skip #
|
||||||
|
if (sceneInstancePtr)
|
||||||
|
{
|
||||||
|
scene = *sceneInstancePtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scene)
|
||||||
|
{
|
||||||
|
for(TiXmlElement* node = scene->FirstChildElement("node");
|
||||||
|
node != NULL; node = node->NextSiblingElement("node"))
|
||||||
|
{
|
||||||
|
btMatrix4x4 identity;
|
||||||
|
identity.setIdentity();
|
||||||
|
btVector3 identScaling(1,1,1);
|
||||||
|
readNodeHierarchy(node,name2Shape,visualShapeInstances, identity);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getUnitMeterScalingAndUpAxisTransform(TiXmlDocument& doc, btTransform& tr, float& unitMeterScaling, int clientUpAxis)
|
||||||
|
{
|
||||||
|
///todo(erwincoumans) those up-axis transformations have been quickly coded without rigorous testing
|
||||||
|
|
||||||
|
TiXmlElement* unitMeter = doc.RootElement()->FirstChildElement("asset")->FirstChildElement("unit");
|
||||||
|
if (unitMeter)
|
||||||
|
{
|
||||||
|
const char* meterText = unitMeter->Attribute("meter");
|
||||||
|
printf("meterText=%s\n", meterText);
|
||||||
|
unitMeterScaling = atof(meterText);
|
||||||
|
}
|
||||||
|
|
||||||
|
TiXmlElement* upAxisElem = doc.RootElement()->FirstChildElement("asset")->FirstChildElement("up_axis");
|
||||||
|
if (upAxisElem)
|
||||||
|
{
|
||||||
|
switch (clientUpAxis)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
std::string upAxisTxt = upAxisElem->GetText();
|
||||||
|
if (upAxisTxt == "X_UP")
|
||||||
|
{
|
||||||
|
btQuaternion x2y(btVector3(0,0,1),SIMD_HALF_PI);
|
||||||
|
tr.setRotation(x2y);
|
||||||
|
}
|
||||||
|
if (upAxisTxt == "Y_UP")
|
||||||
|
{
|
||||||
|
//assume Y_UP for now, to be compatible with assimp?
|
||||||
|
//client and COLLADA are both Z_UP so no transform needed (identity)
|
||||||
|
}
|
||||||
|
if (upAxisTxt == "Z_UP")
|
||||||
|
{
|
||||||
|
btQuaternion z2y(btVector3(1,0,0),-SIMD_HALF_PI);
|
||||||
|
tr.setRotation(z2y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
std::string upAxisTxt = upAxisElem->GetText();
|
||||||
|
if (upAxisTxt == "X_UP")
|
||||||
|
{
|
||||||
|
btQuaternion x2z(btVector3(0,1,0),-SIMD_HALF_PI);
|
||||||
|
tr.setRotation(x2z);
|
||||||
|
}
|
||||||
|
if (upAxisTxt == "Y_UP")
|
||||||
|
{
|
||||||
|
btQuaternion y2z(btVector3(1,0,0),SIMD_HALF_PI);
|
||||||
|
tr.setRotation(y2z);
|
||||||
|
}
|
||||||
|
if (upAxisTxt == "Z_UP")
|
||||||
|
{
|
||||||
|
//client and COLLADA are both Z_UP so no transform needed (identity)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
//we don't support X or other up axis
|
||||||
|
btAssert(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadMeshFromCollada(const char* relativeFileName, btAlignedObjectArray<GLInstanceGraphicsShape>& visualShapes, btAlignedObjectArray<ColladaGraphicsInstance>& visualShapeInstances, btTransform& upAxisTransform, float& unitMeterScaling,int clientUpAxis)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLInstanceGraphicsShape* instance = 0;
|
||||||
|
|
||||||
|
//usually COLLADA files don't have that many visual geometries/shapes
|
||||||
|
visualShapes.reserve(32);
|
||||||
|
|
||||||
|
float extraScaling = 1;//0.01;
|
||||||
|
btHashMap<btHashString, int> name2ShapeIndex;
|
||||||
|
b3FileUtils f;
|
||||||
|
char filename[1024];
|
||||||
|
if (!f.findFile(relativeFileName,filename,1024))
|
||||||
|
{
|
||||||
|
printf("File not found: %s\n", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TiXmlDocument doc(filename);
|
||||||
|
if (!doc.LoadFile())
|
||||||
|
return;
|
||||||
|
|
||||||
|
//We need units to be in meter, so apply a scaling using the asset/units meter
|
||||||
|
unitMeterScaling=1;
|
||||||
|
upAxisTransform.setIdentity();
|
||||||
|
|
||||||
|
//Also we can optionally compensate all transforms using the asset/up_axis as well as unit meter scaling
|
||||||
|
getUnitMeterScalingAndUpAxisTransform(doc, upAxisTransform, unitMeterScaling,clientUpAxis);
|
||||||
|
|
||||||
|
btMatrix4x4 ident;
|
||||||
|
ident.setIdentity();
|
||||||
|
|
||||||
|
readLibraryGeometries(doc, visualShapes, name2ShapeIndex, extraScaling);
|
||||||
|
|
||||||
|
readVisualSceneInstanceGeometries(doc, name2ShapeIndex, visualShapeInstances);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef COMPARE_WITH_ASSIMP
|
||||||
|
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/mesh.h>
|
||||||
|
#include <assimp/postprocess.h>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
|
||||||
|
|
||||||
|
# include "assimp/ColladaLoader.h"
|
||||||
|
//# include "STLLoader.h"
|
||||||
|
# include "assimp/SortByPTypeProcess.h"
|
||||||
|
# include "assimp/LimitBoneWeightsProcess.h"
|
||||||
|
# include "assimp/TriangulateProcess.h"
|
||||||
|
# include "assimp/JoinVerticesProcess.h"
|
||||||
|
# include "assimp/RemoveVCProcess.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void GetImporterInstanceList(std::vector< BaseImporter* >& out)
|
||||||
|
{
|
||||||
|
out.push_back( new ColladaLoader());
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
|
||||||
|
{
|
||||||
|
out.push_back( new SortByPTypeProcess());
|
||||||
|
out.push_back( new LimitBoneWeightsProcess());
|
||||||
|
out.push_back( new TriangulateProcess());
|
||||||
|
out.push_back( new JoinVerticesProcess());
|
||||||
|
//out.push_back( new RemoveVCProcess());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addMeshParts(const aiScene* scene, const aiNode* node, GLInstanceGraphicsShape* outverts, const aiMatrix4x4& parentTr)
|
||||||
|
{
|
||||||
|
aiMatrix4x4 const& nodeTrans(node->mTransformation);
|
||||||
|
|
||||||
|
aiMatrix4x4 trans;
|
||||||
|
trans = parentTr * nodeTrans;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < node->mNumMeshes; ++i)
|
||||||
|
{
|
||||||
|
aiMesh const* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||||
|
size_t num_vertices = mesh->mNumVertices;
|
||||||
|
if (mesh->mPrimitiveTypes==aiPrimitiveType_TRIANGLE)
|
||||||
|
{
|
||||||
|
int curVertexBase = outverts->m_vertices->size();
|
||||||
|
|
||||||
|
for (int v=0;v<mesh->mNumVertices;v++)
|
||||||
|
{
|
||||||
|
GLInstanceVertex vtx;
|
||||||
|
aiVector3D vWorld = trans*mesh->mVertices[v];
|
||||||
|
vtx.xyzw[0] = vWorld.x;
|
||||||
|
vtx.xyzw[1] = vWorld.y;
|
||||||
|
vtx.xyzw[2] = vWorld.z;
|
||||||
|
vtx.xyzw[3] = 1;
|
||||||
|
if (mesh->HasNormals())
|
||||||
|
{
|
||||||
|
vtx.normal[0] = mesh->mNormals[v].x;
|
||||||
|
vtx.normal[1] = mesh->mNormals[v].y;
|
||||||
|
vtx.normal[2] = mesh->mNormals[v].z;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
vtx.normal[0] = 0;
|
||||||
|
vtx.normal[1] = 0;
|
||||||
|
vtx.normal[2] = 1;
|
||||||
|
}
|
||||||
|
if (mesh->HasTextureCoords(0))
|
||||||
|
{
|
||||||
|
vtx.uv[0] = mesh->mTextureCoords[0][v].x;
|
||||||
|
vtx.uv[1] = mesh->mTextureCoords[0][v].y;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
vtx.uv[0]=0.5f;
|
||||||
|
vtx.uv[1]=0.5f;
|
||||||
|
}
|
||||||
|
outverts->m_vertices->push_back(vtx);
|
||||||
|
}
|
||||||
|
for (int f=0;f<mesh->mNumFaces;f++)
|
||||||
|
{
|
||||||
|
b3Assert(mesh->mFaces[f].mNumIndices == 3);
|
||||||
|
int i0 = mesh->mFaces[f].mIndices[0];
|
||||||
|
int i1 = mesh->mFaces[f].mIndices[1];
|
||||||
|
int i2 = mesh->mFaces[f].mIndices[2];
|
||||||
|
outverts->m_indices->push_back(i0+curVertexBase);
|
||||||
|
outverts->m_indices->push_back(i1+curVertexBase);
|
||||||
|
outverts->m_indices->push_back(i2+curVertexBase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i=0 ; i<node->mNumChildren ; ++i) {
|
||||||
|
addMeshParts(scene,node->mChildren[i], outverts, trans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LoadMeshFromColladaAssimp(const char* relativeFileName, btAlignedObjectArray<GLInstanceGraphicsShape>& visualShapes, btAlignedObjectArray<ColladaGraphicsInstance>& visualShapeInstances,btTransform& upAxisTrans, float& unitMeterScaling)
|
||||||
|
{
|
||||||
|
upAxisTrans.setIdentity();
|
||||||
|
unitMeterScaling=1;
|
||||||
|
|
||||||
|
GLInstanceGraphicsShape* shape = 0;
|
||||||
|
|
||||||
|
|
||||||
|
FILE* file = fopen(relativeFileName,"rb");
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
int size=0;
|
||||||
|
if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET))
|
||||||
|
{
|
||||||
|
printf("Error: Cannot access file to determine size of %s\n", relativeFileName);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
printf("Open DAE file of %d bytes\n",size);
|
||||||
|
|
||||||
|
Assimp::Importer importer;
|
||||||
|
//importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, aiComponent_NORMALS | aiComponent_COLORS);
|
||||||
|
importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT);
|
||||||
|
// importer.SetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION, 1);
|
||||||
|
aiScene const* scene = importer.ReadFile(relativeFileName,
|
||||||
|
aiProcess_JoinIdenticalVertices |
|
||||||
|
//aiProcess_RemoveComponent |
|
||||||
|
aiProcess_SortByPType |
|
||||||
|
aiProcess_Triangulate);
|
||||||
|
if (scene)
|
||||||
|
{
|
||||||
|
shape = &visualShapes.expand();
|
||||||
|
shape->m_scaling[0] = 1;
|
||||||
|
shape->m_scaling[1] = 1;
|
||||||
|
shape->m_scaling[2] = 1;
|
||||||
|
shape->m_scaling[3] = 1;
|
||||||
|
int index = 0;
|
||||||
|
shape->m_indices = new b3AlignedObjectArray<int>();
|
||||||
|
shape->m_vertices = new b3AlignedObjectArray<GLInstanceVertex>();
|
||||||
|
|
||||||
|
aiMatrix4x4 ident;
|
||||||
|
addMeshParts(scene, scene->mRootNode, shape, ident);
|
||||||
|
shape->m_numIndices = shape->m_indices->size();
|
||||||
|
shape->m_numvertices = shape->m_vertices->size();
|
||||||
|
ColladaGraphicsInstance& instance = visualShapeInstances.expand();
|
||||||
|
instance.m_shapeIndex = visualShapes.size()-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //COMPARE_WITH_ASSIMP
|
||||||
45
examples/Importers/ImportColladaDemo/LoadMeshFromCollada.h
Normal file
45
examples/Importers/ImportColladaDemo/LoadMeshFromCollada.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Bullet Collision Detection and Physics Library http://bulletphysics.org
|
||||||
|
This file is Copyright (c) 2014 Google Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
//original author: Erwin Coumans
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LOAD_MESH_FROM_COLLADA_H
|
||||||
|
#define LOAD_MESH_FROM_COLLADA_H
|
||||||
|
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
#include "LinearMath/btTransform.h"
|
||||||
|
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
|
||||||
|
#include "ColladaGraphicsInstance.h"
|
||||||
|
|
||||||
|
|
||||||
|
void LoadMeshFromCollada(const char* relativeFileName,
|
||||||
|
btAlignedObjectArray<GLInstanceGraphicsShape>& visualShapes,
|
||||||
|
btAlignedObjectArray<ColladaGraphicsInstance>& visualShapeInstances,
|
||||||
|
btTransform& upAxisTrans,
|
||||||
|
float& unitMeterScaling,
|
||||||
|
int clientUpAxis);
|
||||||
|
|
||||||
|
//#define COMPARE_WITH_ASSIMP
|
||||||
|
#ifdef COMPARE_WITH_ASSIMP
|
||||||
|
void LoadMeshFromColladaAssimp(const char* relativeFileName,
|
||||||
|
btAlignedObjectArray<GLInstanceGraphicsShape>& visualShapes,
|
||||||
|
btAlignedObjectArray<ColladaGraphicsInstance>& visualShapeInstances,
|
||||||
|
btTransform& upAxisTrans,
|
||||||
|
float& unitMeterScaling
|
||||||
|
);
|
||||||
|
#endif //COMPARE_WITH_ASSIMP
|
||||||
|
|
||||||
|
#endif //LOAD_MESH_FROM_COLLADA_H
|
||||||
156
examples/Importers/ImportColladaDemo/btMatrix4x4.h
Normal file
156
examples/Importers/ImportColladaDemo/btMatrix4x4.h
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
Bullet Collision Detection and Physics Library http://bulletphysics.org
|
||||||
|
This file is Copyright (c) 2014 Google Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
//original author: Erwin Coumans
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MATRIX4x4_H
|
||||||
|
#define MATRIX4x4_H
|
||||||
|
|
||||||
|
#include "LinearMath/btVector3.h"
|
||||||
|
#include "LinearMath/btQuaternion.h"
|
||||||
|
|
||||||
|
///This 4x4 matrix class is extremely limited, just created for the purpose of accumulating transform matrices in COLLADA .dae files
|
||||||
|
ATTRIBUTE_ALIGNED16(class) btMatrix4x4
|
||||||
|
{
|
||||||
|
btVector4 m_el[4];
|
||||||
|
public:
|
||||||
|
|
||||||
|
btMatrix4x4()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
btMatrix4x4(const btScalar& xx, const btScalar& xy, const btScalar& xz,const btScalar& xw,
|
||||||
|
const btScalar& yx, const btScalar& yy, const btScalar& yz,const btScalar& yw,
|
||||||
|
const btScalar& zx, const btScalar& zy, const btScalar& zz, const btScalar& zw,
|
||||||
|
const btScalar& wx, const btScalar& wy, const btScalar& wz, const btScalar& ww)
|
||||||
|
{
|
||||||
|
setValue(xx, xy, xz, xw,
|
||||||
|
yx, yy, yz, yw,
|
||||||
|
zx, zy, zz,zw,
|
||||||
|
wx, wy, wz,ww);
|
||||||
|
}
|
||||||
|
|
||||||
|
~btMatrix4x4()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz,const btScalar& xw,
|
||||||
|
const btScalar& yx, const btScalar& yy, const btScalar& yz,const btScalar& yw,
|
||||||
|
const btScalar& zx, const btScalar& zy, const btScalar& zz, const btScalar& zw,
|
||||||
|
const btScalar& wx, const btScalar& wy, const btScalar& wz, const btScalar& ww)
|
||||||
|
{
|
||||||
|
m_el[0].setValue(xx,xy,xz,xw);
|
||||||
|
m_el[1].setValue(yx,yy,yz,yw);
|
||||||
|
m_el[2].setValue(zx,zy,zz,zw);
|
||||||
|
m_el[3].setValue(wx,wy,wz,ww);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setIdentity()
|
||||||
|
{
|
||||||
|
m_el[0].setValue(1,0,0,0);
|
||||||
|
m_el[1].setValue(0,1,0,0);
|
||||||
|
m_el[2].setValue(0,0,1,0);
|
||||||
|
m_el[3].setValue(0,0,0,1);
|
||||||
|
}
|
||||||
|
inline void setPureRotation(const btQuaternion& orn)
|
||||||
|
{
|
||||||
|
setIdentity();
|
||||||
|
|
||||||
|
btMatrix3x3 m3(orn);
|
||||||
|
for (int i=0;i<3;i++)
|
||||||
|
{
|
||||||
|
for (int j=0;j<3;j++)
|
||||||
|
{
|
||||||
|
m_el[i][j] = m3[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setPureScaling(const btVector3& scale)
|
||||||
|
{
|
||||||
|
m_el[0].setValue(scale[0],0,0,0);
|
||||||
|
m_el[1].setValue(0,scale[1],0,0);
|
||||||
|
m_el[2].setValue(0,0,scale[2],0);
|
||||||
|
m_el[3].setValue(0,0,0,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setPureTranslation(const btVector3& pos)
|
||||||
|
{
|
||||||
|
m_el[0].setValue(1,0,0,pos[0]);
|
||||||
|
m_el[1].setValue(0,1,0,pos[1]);
|
||||||
|
m_el[2].setValue(0,0,1,pos[2]);
|
||||||
|
m_el[3].setValue(0,0,0,1);
|
||||||
|
|
||||||
|
}
|
||||||
|
SIMD_FORCE_INLINE const btVector4& operator[](int i) const
|
||||||
|
{
|
||||||
|
btFullAssert(0 <= i && i < 3);
|
||||||
|
return m_el[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE btScalar tdotx(const btVector4& v) const
|
||||||
|
{
|
||||||
|
return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z() + m_el[3].x()* v.w();
|
||||||
|
}
|
||||||
|
SIMD_FORCE_INLINE btScalar tdoty(const btVector4& v) const
|
||||||
|
{
|
||||||
|
return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z() + m_el[3].y() * v.w();
|
||||||
|
}
|
||||||
|
SIMD_FORCE_INLINE btScalar tdotz(const btVector4& v) const
|
||||||
|
{
|
||||||
|
return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z() + m_el[3].z() * v.w();
|
||||||
|
}
|
||||||
|
SIMD_FORCE_INLINE btScalar tdotw(const btVector4& v) const
|
||||||
|
{
|
||||||
|
return m_el[0].w() * v.x() + m_el[1].w() * v.y() + m_el[2].w() * v.z() + m_el[3].w() * v.w();
|
||||||
|
}
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE btMatrix4x4
|
||||||
|
operator*=(const btMatrix4x4& m)
|
||||||
|
{
|
||||||
|
setValue(
|
||||||
|
m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),m.tdotw(m_el[0]),
|
||||||
|
m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),m.tdotw(m_el[1]),
|
||||||
|
m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]),m.tdotw(m_el[2]),
|
||||||
|
m.tdotx(m_el[3]), m.tdoty(m_el[3]), m.tdotz(m_el[3]),m.tdotw(m_el[3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline btScalar btDot4(const btVector4& v0, const btVector4& v1)
|
||||||
|
{
|
||||||
|
return v0.x()*v1.x()+v0.y()*v1.y()+v0.z()*v1.z()+v0.w()*v1.w();
|
||||||
|
}
|
||||||
|
SIMD_FORCE_INLINE btVector3
|
||||||
|
operator*(const btMatrix4x4& m, const btVector3& v1)
|
||||||
|
{
|
||||||
|
btVector4 v(v1[0],v1[1],v1[2],1);
|
||||||
|
return btVector3(btDot4(m[0],v), btDot4(m[1],v), btDot4(m[2],v));
|
||||||
|
}
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE btMatrix4x4
|
||||||
|
operator*(const btMatrix4x4& m1, btMatrix4x4& m2)
|
||||||
|
{
|
||||||
|
return btMatrix4x4(
|
||||||
|
m2.tdotx(m1[0]), m2.tdoty(m1[0]), m2.tdotz(m1[0]),m2.tdotw(m1[0]),
|
||||||
|
m2.tdotx(m1[1]), m2.tdoty(m1[1]), m2.tdotz(m1[1]),m2.tdotw(m1[1]),
|
||||||
|
m2.tdotx(m1[2]), m2.tdoty(m1[2]), m2.tdotz(m1[2]),m2.tdotw(m1[2]),
|
||||||
|
m2.tdotx(m1[3]), m2.tdoty(m1[3]), m2.tdotz(m1[3]),m2.tdotw(m1[3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MATRIX4x4_H
|
||||||
105
examples/Importers/ImportObjDemo/ImportObjExample.cpp
Normal file
105
examples/Importers/ImportObjDemo/ImportObjExample.cpp
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#include "ImportObjExample.h"
|
||||||
|
#include <vector>
|
||||||
|
#include "../OpenGLWindow/GLInstancingRenderer.h"
|
||||||
|
#include"../Wavefront/tiny_obj_loader.h"
|
||||||
|
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
#include "../OpenGLWindow/SimpleOpenGL3App.h"
|
||||||
|
#include "Wavefront2GLInstanceGraphicsShape.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "../CommonInterfaces/CommonRigidBodyBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
class ImportObjSetup : public CommonRigidBodyBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
ImportObjSetup(struct GUIHelperInterface* helper);
|
||||||
|
virtual ~ImportObjSetup();
|
||||||
|
|
||||||
|
virtual void initPhysics();
|
||||||
|
};
|
||||||
|
|
||||||
|
ImportObjSetup::ImportObjSetup(struct GUIHelperInterface* helper)
|
||||||
|
:CommonRigidBodyBase(helper)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportObjSetup::~ImportObjSetup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ImportObjSetup::initPhysics()
|
||||||
|
{
|
||||||
|
m_guiHelper->setUpAxis(2);
|
||||||
|
this->createEmptyDynamicsWorld();
|
||||||
|
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
|
||||||
|
m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
|
||||||
|
const char* fileName = "samurai_monastry.obj";
|
||||||
|
char relativeFileName[1024];
|
||||||
|
const char* prefix[]={"./data/","../data/","../../data/","../../../data/","../../../../data/"};
|
||||||
|
int prefixIndex=-1;
|
||||||
|
{
|
||||||
|
|
||||||
|
int numPrefixes = sizeof(prefix)/sizeof(char*);
|
||||||
|
|
||||||
|
for (int i=0;i<numPrefixes;i++)
|
||||||
|
{
|
||||||
|
FILE* f = 0;
|
||||||
|
sprintf(relativeFileName,"%s%s",prefix[i],fileName);
|
||||||
|
f = fopen(relativeFileName,"r");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
fclose(f);
|
||||||
|
prefixIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefixIndex<0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
btVector3 shift(0,0,0);
|
||||||
|
btVector3 scaling(10,10,10);
|
||||||
|
// int index=10;
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::string err = tinyobj::LoadObj(shapes, relativeFileName, prefix[prefixIndex]);
|
||||||
|
|
||||||
|
GLInstanceGraphicsShape* gfxShape = btgCreateGraphicsShapeFromWavefrontObj(shapes);
|
||||||
|
|
||||||
|
btTransform trans;
|
||||||
|
trans.setIdentity();
|
||||||
|
trans.setRotation(btQuaternion(btVector3(1,0,0),SIMD_HALF_PI));
|
||||||
|
|
||||||
|
btVector3 position = trans.getOrigin();
|
||||||
|
btQuaternion orn = trans.getRotation();
|
||||||
|
|
||||||
|
btVector3 color(0,0,1);
|
||||||
|
|
||||||
|
|
||||||
|
int shapeId = m_guiHelper->getRenderInterface()->registerShape(&gfxShape->m_vertices->at(0).xyzw[0], gfxShape->m_numvertices, &gfxShape->m_indices->at(0), gfxShape->m_numIndices);
|
||||||
|
|
||||||
|
//int id =
|
||||||
|
m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ExampleInterface* ImportObjCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option)
|
||||||
|
{
|
||||||
|
return new ImportObjSetup(helper);
|
||||||
|
}
|
||||||
7
examples/Importers/ImportObjDemo/ImportObjExample.h
Normal file
7
examples/Importers/ImportObjDemo/ImportObjExample.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef IMPORT_OBJ_EXAMPLE_H
|
||||||
|
#define IMPORT_OBJ_EXAMPLE_H
|
||||||
|
|
||||||
|
struct ExampleInterface* ImportObjCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //IMPORT_OBJ_EXAMPLE_H
|
||||||
17
examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp
Normal file
17
examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include "LoadMeshFromObj.h"
|
||||||
|
#include"../Wavefront/tiny_obj_loader.h"
|
||||||
|
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
|
||||||
|
#include <stdio.h> //fopen
|
||||||
|
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "Wavefront2GLInstanceGraphicsShape.h"
|
||||||
|
|
||||||
|
GLInstanceGraphicsShape* LoadMeshFromObj(const char* relativeFileName, const char* materialPrefixPath)
|
||||||
|
{
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::string err = tinyobj::LoadObj(shapes, relativeFileName, materialPrefixPath);
|
||||||
|
|
||||||
|
GLInstanceGraphicsShape* gfxShape = btgCreateGraphicsShapeFromWavefrontObj(shapes);
|
||||||
|
return gfxShape;
|
||||||
|
}
|
||||||
11
examples/Importers/ImportObjDemo/LoadMeshFromObj.h
Normal file
11
examples/Importers/ImportObjDemo/LoadMeshFromObj.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef LOAD_MESH_FROM_OBJ_H
|
||||||
|
#define LOAD_MESH_FROM_OBJ_H
|
||||||
|
|
||||||
|
|
||||||
|
struct GLInstanceGraphicsShape;
|
||||||
|
|
||||||
|
|
||||||
|
GLInstanceGraphicsShape* LoadMeshFromObj(const char* relativeFileName, const char* materialPrefixPath);
|
||||||
|
|
||||||
|
#endif //LOAD_MESH_FROM_OBJ_H
|
||||||
|
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
#include "Wavefront2GLInstanceGraphicsShape.h"
|
||||||
|
|
||||||
|
#include "../OpenGLWindow/GLInstancingRenderer.h"
|
||||||
|
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
#include "../OpenGLWindow/SimpleOpenGL3App.h"
|
||||||
|
#include "Wavefront2GLInstanceGraphicsShape.h"
|
||||||
|
#include "../OpenGLWindow/GLInstancingRenderer.h"
|
||||||
|
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
|
||||||
|
|
||||||
|
GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tinyobj::shape_t>& shapes)
|
||||||
|
{
|
||||||
|
|
||||||
|
b3AlignedObjectArray<GLInstanceVertex>* vertices = new b3AlignedObjectArray<GLInstanceVertex>;
|
||||||
|
{
|
||||||
|
// int numVertices = obj->vertexCount;
|
||||||
|
// int numIndices = 0;
|
||||||
|
b3AlignedObjectArray<int>* indicesPtr = new b3AlignedObjectArray<int>;
|
||||||
|
|
||||||
|
for (int s=0;s<(int)shapes.size();s++)
|
||||||
|
{
|
||||||
|
tinyobj::shape_t& shape = shapes[s];
|
||||||
|
int faceCount = shape.mesh.indices.size();
|
||||||
|
|
||||||
|
|
||||||
|
for (int f=0;f<faceCount;f+=3)
|
||||||
|
{
|
||||||
|
|
||||||
|
//btVector3 normal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
|
||||||
|
if (1)
|
||||||
|
{
|
||||||
|
btVector3 normal(0,1,0);
|
||||||
|
int vtxBaseIndex = vertices->size();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GLInstanceVertex vtx0;
|
||||||
|
vtx0.xyzw[0] = shape.mesh.positions[shape.mesh.indices[f]*3+0];
|
||||||
|
vtx0.xyzw[1] = shape.mesh.positions[shape.mesh.indices[f]*3+1];
|
||||||
|
vtx0.xyzw[2] = shape.mesh.positions[shape.mesh.indices[f]*3+2];
|
||||||
|
vtx0.xyzw[3] = 0.f;
|
||||||
|
|
||||||
|
vtx0.uv[0] = 0.5f;//shape.mesh.positions[shape.mesh.indices[f]*3+2];?
|
||||||
|
vtx0.uv[1] = 0.5f;
|
||||||
|
|
||||||
|
GLInstanceVertex vtx1;
|
||||||
|
vtx1.xyzw[0] = shape.mesh.positions[shape.mesh.indices[f+1]*3+0];
|
||||||
|
vtx1.xyzw[1] = shape.mesh.positions[shape.mesh.indices[f+1]*3+1];
|
||||||
|
vtx1.xyzw[2] = shape.mesh.positions[shape.mesh.indices[f+1]*3+2];
|
||||||
|
vtx1.xyzw[3]= 0.f;
|
||||||
|
vtx1.uv[0] = 0.5f;//obj->textureList[face->vertex_index[1]]->e[0];
|
||||||
|
vtx1.uv[1] = 0.5f;//obj->textureList[face->vertex_index[1]]->e[1];
|
||||||
|
|
||||||
|
GLInstanceVertex vtx2;
|
||||||
|
vtx2.xyzw[0] = shape.mesh.positions[shape.mesh.indices[f+2]*3+0];
|
||||||
|
vtx2.xyzw[1] = shape.mesh.positions[shape.mesh.indices[f+2]*3+1];
|
||||||
|
vtx2.xyzw[2] = shape.mesh.positions[shape.mesh.indices[f+2]*3+2];
|
||||||
|
vtx2.xyzw[3] = 0.f;
|
||||||
|
vtx2.uv[0] = 0.5f;
|
||||||
|
vtx2.uv[1] = 0.5f;
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 v0(vtx0.xyzw[0],vtx0.xyzw[1],vtx0.xyzw[2]);
|
||||||
|
btVector3 v1(vtx1.xyzw[0],vtx1.xyzw[1],vtx1.xyzw[2]);
|
||||||
|
btVector3 v2(vtx2.xyzw[0],vtx2.xyzw[1],vtx2.xyzw[2]);
|
||||||
|
|
||||||
|
normal = (v1-v0).cross(v2-v0);
|
||||||
|
btScalar len2 = normal.length2();
|
||||||
|
//skip degenerate triangles
|
||||||
|
if (len2 > SIMD_EPSILON)
|
||||||
|
{
|
||||||
|
normal.normalize();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
normal.setValue(0,0,0);
|
||||||
|
}
|
||||||
|
vtx0.normal[0] = normal[0];
|
||||||
|
vtx0.normal[1] = normal[1];
|
||||||
|
vtx0.normal[2] = normal[2];
|
||||||
|
vtx1.normal[0] = normal[0];
|
||||||
|
vtx1.normal[1] = normal[1];
|
||||||
|
vtx1.normal[2] = normal[2];
|
||||||
|
vtx2.normal[0] = normal[0];
|
||||||
|
vtx2.normal[1] = normal[1];
|
||||||
|
vtx2.normal[2] = normal[2];
|
||||||
|
vertices->push_back(vtx0);
|
||||||
|
vertices->push_back(vtx1);
|
||||||
|
vertices->push_back(vtx2);
|
||||||
|
indicesPtr->push_back(vtxBaseIndex);
|
||||||
|
indicesPtr->push_back(vtxBaseIndex+1);
|
||||||
|
indicesPtr->push_back(vtxBaseIndex+2);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLInstanceGraphicsShape* gfxShape = new GLInstanceGraphicsShape;
|
||||||
|
gfxShape->m_vertices = vertices;
|
||||||
|
gfxShape->m_numvertices = vertices->size();
|
||||||
|
gfxShape->m_indices = indicesPtr;
|
||||||
|
gfxShape->m_numIndices = indicesPtr->size();
|
||||||
|
for (int i=0;i<4;i++)
|
||||||
|
gfxShape->m_scaling[i] = 1;//bake the scaling into the vertices
|
||||||
|
return gfxShape;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef WAVEFRONT2GRAPHICS_H
|
||||||
|
#define WAVEFRONT2GRAPHICS_H
|
||||||
|
|
||||||
|
#include"../Wavefront/tiny_obj_loader.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tinyobj::shape_t>& shapes);
|
||||||
|
|
||||||
|
#endif //WAVEFRONT2GRAPHICS_H
|
||||||
98
examples/Importers/ImportSTLDemo/ImportSTLSetup.cpp
Normal file
98
examples/Importers/ImportSTLDemo/ImportSTLSetup.cpp
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#include "ImportSTLSetup.h"
|
||||||
|
#include <vector>
|
||||||
|
#include "../OpenGLWindow/GLInstancingRenderer.h"
|
||||||
|
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
|
||||||
|
#include "btBulletDynamicsCommon.h"
|
||||||
|
#include "../OpenGLWindow/SimpleOpenGL3App.h"
|
||||||
|
#include "LoadMeshFromSTL.h"
|
||||||
|
#include "../CommonInterfaces/CommonRigidBodyBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ImportSTLSetup : public CommonRigidBodyBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
ImportSTLSetup(struct GUIHelperInterface* helper);
|
||||||
|
virtual ~ImportSTLSetup();
|
||||||
|
|
||||||
|
virtual void initPhysics();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ImportSTLSetup::ImportSTLSetup(struct GUIHelperInterface* helper)
|
||||||
|
:CommonRigidBodyBase(helper)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportSTLSetup::~ImportSTLSetup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ImportSTLSetup::initPhysics()
|
||||||
|
{
|
||||||
|
m_guiHelper->setUpAxis(2);
|
||||||
|
this->createEmptyDynamicsWorld();
|
||||||
|
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
|
||||||
|
m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
|
||||||
|
|
||||||
|
const char* fileName = "l_finger_tip.stl";
|
||||||
|
char relativeFileName[1024];
|
||||||
|
const char* prefix[]={"./data/","../data/","../../data/","../../../data/","../../../../data/"};
|
||||||
|
int prefixIndex=-1;
|
||||||
|
{
|
||||||
|
|
||||||
|
int numPrefixes = sizeof(prefix)/sizeof(char*);
|
||||||
|
|
||||||
|
for (int i=0;i<numPrefixes;i++)
|
||||||
|
{
|
||||||
|
FILE* f = 0;
|
||||||
|
sprintf(relativeFileName,"%s%s",prefix[i],fileName);
|
||||||
|
f = fopen(relativeFileName,"r");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
fclose(f);
|
||||||
|
prefixIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefixIndex<0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
btVector3 shift(0,0,0);
|
||||||
|
btVector3 scaling(10,10,10);
|
||||||
|
// int index=10;
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
GLInstanceGraphicsShape* gfxShape = LoadMeshFromSTL(relativeFileName);
|
||||||
|
|
||||||
|
btTransform trans;
|
||||||
|
trans.setIdentity();
|
||||||
|
trans.setRotation(btQuaternion(btVector3(1,0,0),SIMD_HALF_PI));
|
||||||
|
|
||||||
|
btVector3 position = trans.getOrigin();
|
||||||
|
btQuaternion orn = trans.getRotation();
|
||||||
|
|
||||||
|
btVector3 color(0,0,1);
|
||||||
|
|
||||||
|
int shapeId = m_guiHelper->getRenderInterface()->registerShape(&gfxShape->m_vertices->at(0).xyzw[0], gfxShape->m_numvertices, &gfxShape->m_indices->at(0), gfxShape->m_numIndices);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleInterface* ImportSTLCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option)
|
||||||
|
{
|
||||||
|
return new ImportSTLSetup(helper);
|
||||||
|
}
|
||||||
6
examples/Importers/ImportSTLDemo/ImportSTLSetup.h
Normal file
6
examples/Importers/ImportSTLDemo/ImportSTLSetup.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef IMPORT_STL_SETUP_H
|
||||||
|
#define IMPORT_STL_SETUP_H
|
||||||
|
|
||||||
|
class ExampleInterface* ImportSTLCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option);
|
||||||
|
|
||||||
|
#endif //IMPORT_OBJ_SETUP_H
|
||||||
109
examples/Importers/ImportSTLDemo/LoadMeshFromSTL.h
Normal file
109
examples/Importers/ImportSTLDemo/LoadMeshFromSTL.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
#ifndef LOAD_MESH_FROM_STL_H
|
||||||
|
#define LOAD_MESH_FROM_STL_H
|
||||||
|
|
||||||
|
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
|
||||||
|
#include <stdio.h> //fopen
|
||||||
|
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||||
|
|
||||||
|
struct MySTLTriangle
|
||||||
|
{
|
||||||
|
float normal[3];
|
||||||
|
float vertex0[3];
|
||||||
|
float vertex1[3];
|
||||||
|
float vertex2[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLInstanceGraphicsShape* LoadMeshFromSTL(const char* relativeFileName)
|
||||||
|
{
|
||||||
|
GLInstanceGraphicsShape* shape = 0;
|
||||||
|
|
||||||
|
FILE* file = fopen(relativeFileName,"rb");
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
int size=0;
|
||||||
|
if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET))
|
||||||
|
{
|
||||||
|
printf("Error: Cannot access file to determine size of %s\n", relativeFileName);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
printf("Open STL file of %d bytes\n",size);
|
||||||
|
char* memoryBuffer = new char[size+1];
|
||||||
|
int actualBytesRead = fread(memoryBuffer,1,size,file);
|
||||||
|
if (actualBytesRead!=size)
|
||||||
|
{
|
||||||
|
printf("Error reading from file %s",relativeFileName);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
int numTriangles = *(int*)&memoryBuffer[80];
|
||||||
|
|
||||||
|
if (numTriangles)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
//perform a sanity check instead of crashing on invalid triangles/STL files
|
||||||
|
int expectedBinaryFileSize = numTriangles* 50 + 84;
|
||||||
|
if (expectedBinaryFileSize != size)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
shape = new GLInstanceGraphicsShape;
|
||||||
|
// b3AlignedObjectArray<GLInstanceVertex>* m_vertices;
|
||||||
|
// int m_numvertices;
|
||||||
|
// b3AlignedObjectArray<int>* m_indices;
|
||||||
|
// int m_numIndices;
|
||||||
|
// float m_scaling[4];
|
||||||
|
shape->m_scaling[0] = 1;
|
||||||
|
shape->m_scaling[1] = 1;
|
||||||
|
shape->m_scaling[2] = 1;
|
||||||
|
shape->m_scaling[3] = 1;
|
||||||
|
int index = 0;
|
||||||
|
shape->m_indices = new b3AlignedObjectArray<int>();
|
||||||
|
shape->m_vertices = new b3AlignedObjectArray<GLInstanceVertex>();
|
||||||
|
for (int i=0;i<numTriangles;i++)
|
||||||
|
{
|
||||||
|
char* curPtr = &memoryBuffer[84+i*50];
|
||||||
|
MySTLTriangle* tri = (MySTLTriangle*) curPtr;
|
||||||
|
|
||||||
|
GLInstanceVertex v0,v1,v2;
|
||||||
|
if (i==numTriangles-2)
|
||||||
|
{
|
||||||
|
printf("!\n");
|
||||||
|
}
|
||||||
|
v0.uv[0] = v1.uv[0] = v2.uv[0] = 0.5;
|
||||||
|
v0.uv[1] = v1.uv[1] = v2.uv[1] = 0.5;
|
||||||
|
for (int v=0;v<3;v++)
|
||||||
|
{
|
||||||
|
v0.xyzw[v] = tri->vertex0[v];
|
||||||
|
v1.xyzw[v] = tri->vertex1[v];
|
||||||
|
v2.xyzw[v] = tri->vertex2[v];
|
||||||
|
v0.normal[v] = v1.normal[v] = v2.normal[v] = tri->normal[v];
|
||||||
|
}
|
||||||
|
v0.xyzw[3] = v1.xyzw[3] = v2.xyzw[3] = 0.f;
|
||||||
|
|
||||||
|
shape->m_vertices->push_back(v0);
|
||||||
|
shape->m_vertices->push_back(v1);
|
||||||
|
shape->m_vertices->push_back(v2);
|
||||||
|
|
||||||
|
shape->m_indices->push_back(index++);
|
||||||
|
shape->m_indices->push_back(index++);
|
||||||
|
shape->m_indices->push_back(index++);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] memoryBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
shape->m_numIndices = shape->m_indices->size();
|
||||||
|
shape->m_numvertices = shape->m_vertices->size();
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //LOAD_MESH_FROM_STL_H
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef CONVERT_RIGIDBODIES_2_MULTIBODY_H
|
||||||
|
#define CONVERT_RIGIDBODIES_2_MULTIBODY_H
|
||||||
|
|
||||||
|
struct ConvertRigidBodies2MultiBody
|
||||||
|
{
|
||||||
|
btAlignedObjectArray<btRigidBody*> m_bodies;
|
||||||
|
btAlignedObjectArray<btTypedConstraint*> m_constraints;
|
||||||
|
|
||||||
|
virtual void addRigidBody(btRigidBody* body);
|
||||||
|
virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false);
|
||||||
|
virtual btMultiBody* convertToMultiBody();
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif //CONVERT_RIGIDBODIES_2_MULTIBODY_H
|
||||||
1702
examples/Importers/ImportURDFDemo/ImportURDFSetup.cpp
Normal file
1702
examples/Importers/ImportURDFDemo/ImportURDFSetup.cpp
Normal file
File diff suppressed because it is too large
Load Diff
7
examples/Importers/ImportURDFDemo/ImportURDFSetup.h
Normal file
7
examples/Importers/ImportURDFDemo/ImportURDFSetup.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef IMPORT_URDF_SETUP_H
|
||||||
|
#define IMPORT_URDF_SETUP_H
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleInterface* ImportURDFCreateFunc(struct PhysicsInterface* pint, struct GUIHelperInterface* helper, int option);
|
||||||
|
|
||||||
|
#endif //IMPORT_URDF_SETUP_H
|
||||||
507
examples/Importers/ImportURDFDemo/URDF2Bullet.cpp
Normal file
507
examples/Importers/ImportURDFDemo/URDF2Bullet.cpp
Normal file
@@ -0,0 +1,507 @@
|
|||||||
|
#include "URDF2Bullet.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "LinearMath/btTransform.h"
|
||||||
|
#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
|
||||||
|
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||||
|
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
|
||||||
|
#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
|
||||||
|
|
||||||
|
static int bodyCollisionFilterGroup=btBroadphaseProxy::CharacterFilter;
|
||||||
|
static int bodyCollisionFilterMask=btBroadphaseProxy::AllFilter&(~btBroadphaseProxy::CharacterFilter);
|
||||||
|
static bool enableConstraints = true;
|
||||||
|
|
||||||
|
static btVector4 colors[4] =
|
||||||
|
{
|
||||||
|
btVector4(1,0,0,1),
|
||||||
|
btVector4(0,1,0,1),
|
||||||
|
btVector4(0,1,1,1),
|
||||||
|
btVector4(1,1,0,1),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static btVector3 selectColor2()
|
||||||
|
{
|
||||||
|
|
||||||
|
static int curColor = 0;
|
||||||
|
btVector4 color = colors[curColor];
|
||||||
|
curColor++;
|
||||||
|
curColor&=3;
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printTree(const URDF2Bullet& u2b, int linkIndex, int indentationLevel)
|
||||||
|
{
|
||||||
|
btAlignedObjectArray<int> childIndices;
|
||||||
|
u2b.getLinkChildIndices(linkIndex,childIndices);
|
||||||
|
|
||||||
|
int numChildren = childIndices.size();
|
||||||
|
|
||||||
|
indentationLevel+=2;
|
||||||
|
int count = 0;
|
||||||
|
for (int i=0;i<numChildren;i++)
|
||||||
|
{
|
||||||
|
int childLinkIndex = childIndices[i];
|
||||||
|
std::string name = u2b.getLinkName(childLinkIndex);
|
||||||
|
for(int j=0;j<indentationLevel;j++) printf(" "); //indent
|
||||||
|
printf("child(%d).name=%s with childIndex=%d\n",(count++)+1, name.c_str(),childLinkIndex);
|
||||||
|
// first grandchild
|
||||||
|
printTree(u2b,childLinkIndex,indentationLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct URDF2BulletCachedData
|
||||||
|
{
|
||||||
|
URDF2BulletCachedData()
|
||||||
|
:m_totalNumJoints1(0),
|
||||||
|
m_currentMultiBodyLinkIndex(-1),
|
||||||
|
m_bulletMultiBody(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
//these arrays will be initialized in the 'InitURDF2BulletCache'
|
||||||
|
|
||||||
|
btAlignedObjectArray<int> m_urdfLinkParentIndices;
|
||||||
|
btAlignedObjectArray<int> m_urdfLinkIndices2BulletLinkIndices;
|
||||||
|
btAlignedObjectArray<class btRigidBody*> m_urdfLink2rigidBodies;
|
||||||
|
btAlignedObjectArray<btTransform> m_urdfLinkLocalInertialFrames;
|
||||||
|
|
||||||
|
int m_currentMultiBodyLinkIndex;
|
||||||
|
|
||||||
|
class btMultiBody* m_bulletMultiBody;
|
||||||
|
|
||||||
|
//this will be initialized in the constructor
|
||||||
|
int m_totalNumJoints1;
|
||||||
|
int getParentUrdfIndex(int linkIndex) const
|
||||||
|
{
|
||||||
|
return m_urdfLinkParentIndices[linkIndex];
|
||||||
|
}
|
||||||
|
int getMbIndexFromUrdfIndex(int urdfIndex) const
|
||||||
|
{
|
||||||
|
if (urdfIndex==-2)
|
||||||
|
return -2;
|
||||||
|
return m_urdfLinkIndices2BulletLinkIndices[urdfIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void registerMultiBody( int urdfLinkIndex, class btMultiBody* body, const btTransform& worldTransform, btScalar mass, const btVector3& localInertiaDiagonal, const class btCompoundShape* compound, const btTransform& localInertialFrame)
|
||||||
|
{
|
||||||
|
m_urdfLinkLocalInertialFrames[urdfLinkIndex] = localInertialFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
class btRigidBody* getRigidBodyFromLink(int urdfLinkIndex)
|
||||||
|
{
|
||||||
|
return m_urdfLink2rigidBodies[urdfLinkIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerRigidBody( int urdfLinkIndex, class btRigidBody* body, const btTransform& worldTransform, btScalar mass, const btVector3& localInertiaDiagonal, const class btCompoundShape* compound, const btTransform& localInertialFrame)
|
||||||
|
{
|
||||||
|
btAssert(m_urdfLink2rigidBodies[urdfLinkIndex]==0);
|
||||||
|
|
||||||
|
m_urdfLink2rigidBodies[urdfLinkIndex] = body;
|
||||||
|
m_urdfLinkLocalInertialFrames[urdfLinkIndex] = localInertialFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void ComputeTotalNumberOfJoints(const URDF2Bullet& u2b, URDF2BulletCachedData& cache, int linkIndex)
|
||||||
|
{
|
||||||
|
btAlignedObjectArray<int> childIndices;
|
||||||
|
u2b.getLinkChildIndices(linkIndex,childIndices);
|
||||||
|
printf("link %s has %d children\n", u2b.getLinkName(linkIndex).c_str(),childIndices.size());
|
||||||
|
for (int i=0;i<childIndices.size();i++)
|
||||||
|
{
|
||||||
|
printf("child %d has childIndex%d=%s\n",i,childIndices[i],u2b.getLinkName(childIndices[i]).c_str());
|
||||||
|
}
|
||||||
|
cache.m_totalNumJoints1 += childIndices.size();
|
||||||
|
for (int i=0;i<childIndices.size();i++)
|
||||||
|
{
|
||||||
|
int childIndex =childIndices[i];
|
||||||
|
ComputeTotalNumberOfJoints(u2b,cache,childIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeParentIndices(const URDF2Bullet& u2b, URDF2BulletCachedData& cache, int urdfLinkIndex, int urdfParentIndex)
|
||||||
|
{
|
||||||
|
cache.m_urdfLinkParentIndices[urdfLinkIndex]=urdfParentIndex;
|
||||||
|
cache.m_urdfLinkIndices2BulletLinkIndices[urdfLinkIndex]=cache.m_currentMultiBodyLinkIndex++;
|
||||||
|
|
||||||
|
btAlignedObjectArray<int> childIndices;
|
||||||
|
u2b.getLinkChildIndices(urdfLinkIndex,childIndices);
|
||||||
|
for (int i=0;i<childIndices.size();i++)
|
||||||
|
{
|
||||||
|
ComputeParentIndices(u2b,cache,childIndices[i],urdfLinkIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitURDF2BulletCache(const URDF2Bullet& u2b, URDF2BulletCachedData& cache)
|
||||||
|
{
|
||||||
|
//compute the number of links, and compute parent indices array (and possibly other cached data?)
|
||||||
|
cache.m_totalNumJoints1 = 0;
|
||||||
|
|
||||||
|
int rootLinkIndex = u2b.getRootLinkIndex();
|
||||||
|
if (rootLinkIndex>=0)
|
||||||
|
{
|
||||||
|
ComputeTotalNumberOfJoints(u2b,cache,rootLinkIndex);
|
||||||
|
int numTotalLinksIncludingBase = 1+cache.m_totalNumJoints1;
|
||||||
|
|
||||||
|
cache.m_urdfLinkParentIndices.resize(numTotalLinksIncludingBase);
|
||||||
|
cache.m_urdfLinkIndices2BulletLinkIndices.resize(numTotalLinksIncludingBase);
|
||||||
|
cache.m_urdfLink2rigidBodies.resize(numTotalLinksIncludingBase);
|
||||||
|
cache.m_urdfLinkLocalInertialFrames.resize(numTotalLinksIncludingBase);
|
||||||
|
|
||||||
|
cache.m_currentMultiBodyLinkIndex = -1;//multi body base has 'link' index -1
|
||||||
|
ComputeParentIndices(u2b,cache,rootLinkIndex,-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConvertURDF2BulletInternal(const URDF2Bullet& u2b, URDF2BulletCachedData& cache, int urdfLinkIndex, const btTransform& parentTransformInWorldSpace, btMultiBodyDynamicsWorld* world1,bool createMultiBody, const char* pathPrefix)
|
||||||
|
{
|
||||||
|
printf("start converting/extracting data from URDF interface\n");
|
||||||
|
|
||||||
|
btTransform linkTransformInWorldSpace;
|
||||||
|
linkTransformInWorldSpace.setIdentity();
|
||||||
|
|
||||||
|
|
||||||
|
int mbLinkIndex =cache.getMbIndexFromUrdfIndex(urdfLinkIndex);
|
||||||
|
|
||||||
|
int urdfParentIndex = cache.getParentUrdfIndex(urdfLinkIndex);
|
||||||
|
int mbParentIndex = cache.getMbIndexFromUrdfIndex(urdfParentIndex);
|
||||||
|
btRigidBody* parentRigidBody = 0;
|
||||||
|
|
||||||
|
std::string name = u2b.getLinkName(urdfLinkIndex);
|
||||||
|
printf("link name=%s urdf link index=%d\n",name.c_str(),urdfLinkIndex);
|
||||||
|
printf("mb link index = %d\n",mbLinkIndex);
|
||||||
|
|
||||||
|
btTransform parentLocalInertialFrame;
|
||||||
|
parentLocalInertialFrame.setIdentity();
|
||||||
|
btScalar parentMass(1);
|
||||||
|
btVector3 parentLocalInertiaDiagonal(1,1,1);
|
||||||
|
|
||||||
|
if (urdfParentIndex==-2)
|
||||||
|
{
|
||||||
|
printf("root link has no parent\n");
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
printf("urdf parent index = %d\n",urdfParentIndex);
|
||||||
|
printf("mb parent index = %d\n",mbParentIndex);
|
||||||
|
parentRigidBody = cache.getRigidBodyFromLink(urdfParentIndex);
|
||||||
|
u2b.getMassAndInertia(urdfParentIndex, parentMass,parentLocalInertiaDiagonal,parentLocalInertialFrame);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
btScalar mass = 0;
|
||||||
|
btTransform localInertialFrame;
|
||||||
|
localInertialFrame.setIdentity();
|
||||||
|
btVector3 localInertiaDiagonal(0,0,0);
|
||||||
|
u2b.getMassAndInertia(urdfLinkIndex, mass,localInertiaDiagonal,localInertialFrame);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
btTransform parent2joint;
|
||||||
|
parent2joint.setIdentity();
|
||||||
|
|
||||||
|
int jointType;
|
||||||
|
btVector3 jointAxisInJointSpace;
|
||||||
|
btScalar jointLowerLimit;
|
||||||
|
btScalar jointUpperLimit;
|
||||||
|
|
||||||
|
|
||||||
|
bool hasParentJoint = u2b.getJointInfo(urdfLinkIndex, parent2joint, jointAxisInJointSpace, jointType,jointLowerLimit,jointUpperLimit);
|
||||||
|
|
||||||
|
|
||||||
|
linkTransformInWorldSpace =parentTransformInWorldSpace*parent2joint;
|
||||||
|
|
||||||
|
int graphicsIndex = u2b.convertLinkVisualShapes(urdfLinkIndex,pathPrefix,localInertialFrame);
|
||||||
|
|
||||||
|
btCompoundShape* compoundShape = u2b.convertLinkCollisionShapes(urdfLinkIndex,pathPrefix,localInertialFrame);
|
||||||
|
|
||||||
|
if (compoundShape)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 color = selectColor2();
|
||||||
|
/*
|
||||||
|
if (visual->material.get())
|
||||||
|
{
|
||||||
|
color.setValue(visual->material->color.r,visual->material->color.g,visual->material->color.b);//,visual->material->color.a);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//btVector3 localInertiaDiagonal(0, 0, 0);
|
||||||
|
//if (mass)
|
||||||
|
//{
|
||||||
|
// shape->calculateLocalInertia(mass, localInertiaDiagonal);
|
||||||
|
//}
|
||||||
|
|
||||||
|
btRigidBody* linkRigidBody = 0;
|
||||||
|
btTransform inertialFrameInWorldSpace = linkTransformInWorldSpace*localInertialFrame;
|
||||||
|
|
||||||
|
if (!createMultiBody)
|
||||||
|
{
|
||||||
|
btRigidBody* body = u2b.allocateRigidBody(urdfLinkIndex, mass, localInertiaDiagonal, inertialFrameInWorldSpace, compoundShape);
|
||||||
|
linkRigidBody = body;
|
||||||
|
|
||||||
|
world1->addRigidBody(body, bodyCollisionFilterGroup, bodyCollisionFilterMask);
|
||||||
|
|
||||||
|
compoundShape->setUserIndex(graphicsIndex);
|
||||||
|
|
||||||
|
u2b.createRigidBodyGraphicsInstance(urdfLinkIndex, body, color, graphicsIndex);
|
||||||
|
cache.registerRigidBody(urdfLinkIndex, body, inertialFrameInWorldSpace, mass, localInertiaDiagonal, compoundShape, localInertialFrame);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (cache.m_bulletMultiBody==0)
|
||||||
|
{
|
||||||
|
bool multiDof = true;
|
||||||
|
bool canSleep = false;
|
||||||
|
bool isFixedBase = (mass==0);//todo: figure out when base is fixed
|
||||||
|
int totalNumJoints = cache.m_totalNumJoints1;
|
||||||
|
cache.m_bulletMultiBody = u2b.allocateMultiBody(urdfLinkIndex, totalNumJoints,mass, localInertiaDiagonal, isFixedBase, canSleep, multiDof);
|
||||||
|
|
||||||
|
cache.registerMultiBody(urdfLinkIndex, cache.m_bulletMultiBody, inertialFrameInWorldSpace, mass, localInertiaDiagonal, compoundShape, localInertialFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//create a joint if necessary
|
||||||
|
if (hasParentJoint) {
|
||||||
|
|
||||||
|
btTransform offsetInA,offsetInB;
|
||||||
|
offsetInA = parentLocalInertialFrame.inverse()*parent2joint;
|
||||||
|
offsetInB = localInertialFrame.inverse();
|
||||||
|
|
||||||
|
bool disableParentCollision = true;
|
||||||
|
switch (jointType)
|
||||||
|
{
|
||||||
|
case URDF2Bullet::FixedJoint:
|
||||||
|
{
|
||||||
|
if (createMultiBody)
|
||||||
|
{
|
||||||
|
//todo: adjust the center of mass transform and pivot axis properly
|
||||||
|
|
||||||
|
printf("Fixed joint (btMultiBody)\n");
|
||||||
|
btQuaternion rot = offsetInA.inverse().getRotation();//parent2joint.inverse().getRotation();
|
||||||
|
cache.m_bulletMultiBody->setupFixed(mbLinkIndex, mass, localInertiaDiagonal, mbParentIndex,
|
||||||
|
rot*offsetInB.getRotation(), offsetInA.getOrigin(),-offsetInB.getOrigin(),disableParentCollision);
|
||||||
|
u2b.addLinkMapping(urdfLinkIndex,mbLinkIndex);
|
||||||
|
|
||||||
|
btMatrix3x3 rm(rot);
|
||||||
|
btScalar y,p,r;
|
||||||
|
rm.getEulerZYX(y,p,r);
|
||||||
|
printf("y=%f,p=%f,r=%f\n", y,p,r);
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
printf("Fixed joint\n");
|
||||||
|
|
||||||
|
btMatrix3x3 rm(offsetInA.getBasis());
|
||||||
|
btScalar y,p,r;
|
||||||
|
rm.getEulerZYX(y,p,r);
|
||||||
|
printf("y=%f,p=%f,r=%f\n", y,p,r);
|
||||||
|
|
||||||
|
//we could also use btFixedConstraint but it has some issues
|
||||||
|
btGeneric6DofSpring2Constraint* dof6 = u2b.allocateGeneric6DofSpring2Constraint(urdfLinkIndex, *parentRigidBody, *linkRigidBody, offsetInA, offsetInB);
|
||||||
|
|
||||||
|
dof6->setLinearLowerLimit(btVector3(0,0,0));
|
||||||
|
dof6->setLinearUpperLimit(btVector3(0,0,0));
|
||||||
|
|
||||||
|
dof6->setAngularLowerLimit(btVector3(0,0,0));
|
||||||
|
dof6->setAngularUpperLimit(btVector3(0,0,0));
|
||||||
|
|
||||||
|
if (enableConstraints)
|
||||||
|
world1->addConstraint(dof6,true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case URDF2Bullet::ContinuousJoint:
|
||||||
|
case URDF2Bullet::RevoluteJoint:
|
||||||
|
{
|
||||||
|
if (createMultiBody)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
cache.m_bulletMultiBody->setupRevolute(mbLinkIndex, mass, localInertiaDiagonal, mbParentIndex,
|
||||||
|
offsetInA.inverse().getRotation()*offsetInB.getRotation(), quatRotate(offsetInB.inverse().getRotation(),jointAxisInJointSpace), offsetInA.getOrigin(),//parent2joint.getOrigin(),
|
||||||
|
-offsetInB.getOrigin(),
|
||||||
|
disableParentCollision);
|
||||||
|
u2b.addLinkMapping(urdfLinkIndex,mbLinkIndex);
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//only handle principle axis at the moment,
|
||||||
|
//@todo(erwincoumans) orient the constraint for non-principal axis
|
||||||
|
int principleAxis = jointAxisInJointSpace.closestAxis();
|
||||||
|
switch (principleAxis)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
btGeneric6DofSpring2Constraint* dof6 = u2b.allocateGeneric6DofSpring2Constraint(urdfLinkIndex,*parentRigidBody, *linkRigidBody, offsetInA, offsetInB,RO_ZYX);
|
||||||
|
dof6->setLinearLowerLimit(btVector3(0,0,0));
|
||||||
|
dof6->setLinearUpperLimit(btVector3(0,0,0));
|
||||||
|
|
||||||
|
dof6->setAngularUpperLimit(btVector3(-1,0,0));
|
||||||
|
dof6->setAngularLowerLimit(btVector3(1,0,0));
|
||||||
|
|
||||||
|
if (enableConstraints)
|
||||||
|
world1->addConstraint(dof6,true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
btGeneric6DofSpring2Constraint* dof6 = u2b.allocateGeneric6DofSpring2Constraint(urdfLinkIndex,*parentRigidBody, *linkRigidBody, offsetInA, offsetInB,RO_XZY);
|
||||||
|
dof6->setLinearLowerLimit(btVector3(0,0,0));
|
||||||
|
dof6->setLinearUpperLimit(btVector3(0,0,0));
|
||||||
|
|
||||||
|
dof6->setAngularUpperLimit(btVector3(0,-1,0));
|
||||||
|
dof6->setAngularLowerLimit(btVector3(0,1,0));
|
||||||
|
|
||||||
|
if (enableConstraints)
|
||||||
|
world1->addConstraint(dof6,true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
btGeneric6DofSpring2Constraint* dof6 = u2b.allocateGeneric6DofSpring2Constraint(urdfLinkIndex,*parentRigidBody, *linkRigidBody, offsetInA, offsetInB,RO_XYZ);
|
||||||
|
dof6->setLinearLowerLimit(btVector3(0,0,0));
|
||||||
|
dof6->setLinearUpperLimit(btVector3(0,0,0));
|
||||||
|
|
||||||
|
dof6->setAngularUpperLimit(btVector3(0,0,-1));
|
||||||
|
dof6->setAngularLowerLimit(btVector3(0,0,0));
|
||||||
|
|
||||||
|
if (enableConstraints)
|
||||||
|
world1->addConstraint(dof6,true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
printf("Revolute/Continuous joint\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case URDF2Bullet::PrismaticJoint:
|
||||||
|
{
|
||||||
|
if (createMultiBody)
|
||||||
|
{
|
||||||
|
|
||||||
|
cache.m_bulletMultiBody->setupPrismatic(mbLinkIndex, mass, localInertiaDiagonal, mbParentIndex,
|
||||||
|
offsetInA.inverse().getRotation()*offsetInB.getRotation(), quatRotate(offsetInB.inverse().getRotation(),jointAxisInJointSpace), offsetInA.getOrigin(),//parent2joint.getOrigin(),
|
||||||
|
-offsetInB.getOrigin(),
|
||||||
|
disableParentCollision);
|
||||||
|
|
||||||
|
u2b.addLinkMapping(urdfLinkIndex,mbLinkIndex);
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
btGeneric6DofSpring2Constraint* dof6 = u2b.allocateGeneric6DofSpring2Constraint(urdfLinkIndex,*parentRigidBody, *linkRigidBody, offsetInA, offsetInB);
|
||||||
|
//todo(erwincoumans) for now, we only support principle axis along X, Y or Z
|
||||||
|
int principleAxis = jointAxisInJointSpace.closestAxis();
|
||||||
|
switch (principleAxis)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
dof6->setLinearLowerLimit(btVector3(jointLowerLimit,0,0));
|
||||||
|
dof6->setLinearUpperLimit(btVector3(jointUpperLimit,0,0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
dof6->setLinearLowerLimit(btVector3(0,jointLowerLimit,0));
|
||||||
|
dof6->setLinearUpperLimit(btVector3(0,jointUpperLimit,0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
dof6->setLinearLowerLimit(btVector3(0,0,jointLowerLimit));
|
||||||
|
dof6->setLinearUpperLimit(btVector3(0,0,jointUpperLimit));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dof6->setAngularLowerLimit(btVector3(0,0,0));
|
||||||
|
dof6->setAngularUpperLimit(btVector3(0,0,0));
|
||||||
|
if (enableConstraints)
|
||||||
|
world1->addConstraint(dof6,true);
|
||||||
|
|
||||||
|
printf("Prismatic\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
printf("Error: unsupported joint type in URDF (%d)\n", jointType);
|
||||||
|
btAssert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createMultiBody)
|
||||||
|
{
|
||||||
|
if (compoundShape->getNumChildShapes()>0)
|
||||||
|
{
|
||||||
|
btMultiBodyLinkCollider* col= u2b.allocateMultiBodyLinkCollider(urdfLinkIndex, mbLinkIndex, cache.m_bulletMultiBody);
|
||||||
|
|
||||||
|
compoundShape->setUserIndex(graphicsIndex);
|
||||||
|
|
||||||
|
col->setCollisionShape(compoundShape);
|
||||||
|
|
||||||
|
btTransform tr;
|
||||||
|
tr.setIdentity();
|
||||||
|
tr = linkTransformInWorldSpace;
|
||||||
|
//if we don't set the initial pose of the btCollisionObject, the simulator will do this
|
||||||
|
//when syncing the btMultiBody link transforms to the btMultiBodyLinkCollider
|
||||||
|
|
||||||
|
col->setWorldTransform(tr);
|
||||||
|
|
||||||
|
bool isDynamic = true;
|
||||||
|
short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter);
|
||||||
|
short collisionFilterMask = isDynamic? short(btBroadphaseProxy::AllFilter) : short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
|
||||||
|
|
||||||
|
world1->addCollisionObject(col,collisionFilterGroup,collisionFilterMask);
|
||||||
|
|
||||||
|
btVector3 color = selectColor2();//(0.0,0.0,0.5);
|
||||||
|
|
||||||
|
u2b.createCollisionObjectGraphicsInstance(urdfLinkIndex,col,color);
|
||||||
|
|
||||||
|
btScalar friction = 0.5f;
|
||||||
|
|
||||||
|
col->setFriction(friction);
|
||||||
|
|
||||||
|
if (mbLinkIndex>=0) //???? double-check +/- 1
|
||||||
|
{
|
||||||
|
cache.m_bulletMultiBody->getLink(mbLinkIndex).m_collider=col;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cache.m_bulletMultiBody->setBaseCollider(col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btAlignedObjectArray<int> urdfChildIndices;
|
||||||
|
u2b.getLinkChildIndices(urdfLinkIndex,urdfChildIndices);
|
||||||
|
|
||||||
|
int numChildren = urdfChildIndices.size();
|
||||||
|
|
||||||
|
for (int i=0;i<numChildren;i++)
|
||||||
|
{
|
||||||
|
int urdfChildLinkIndex = urdfChildIndices[i];
|
||||||
|
|
||||||
|
ConvertURDF2BulletInternal(u2b,cache,urdfChildLinkIndex,linkTransformInWorldSpace,world1,createMultiBody,pathPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConvertURDF2Bullet(const URDF2Bullet& u2b, const btTransform& rootTransformInWorldSpace, btMultiBodyDynamicsWorld* world1,bool createMultiBody, const char* pathPrefix)
|
||||||
|
{
|
||||||
|
URDF2BulletCachedData cache;
|
||||||
|
|
||||||
|
InitURDF2BulletCache(u2b,cache);
|
||||||
|
int urdfLinkIndex = u2b.getRootLinkIndex();
|
||||||
|
ConvertURDF2BulletInternal(u2b, cache, urdfLinkIndex,rootTransformInWorldSpace,world1,createMultiBody,pathPrefix);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
71
examples/Importers/ImportURDFDemo/URDF2Bullet.h
Normal file
71
examples/Importers/ImportURDFDemo/URDF2Bullet.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#ifndef _URDF2BULLET_H
|
||||||
|
#define _URDF2BULLET_H
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
#include "LinearMath/btTransform.h"
|
||||||
|
#include <string>
|
||||||
|
class btVector3;
|
||||||
|
class btTransform;
|
||||||
|
class btMultiBodyDynamicsWorld;
|
||||||
|
class btTransform;
|
||||||
|
|
||||||
|
class URDF2Bullet
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum {
|
||||||
|
RevoluteJoint=1,
|
||||||
|
PrismaticJoint,
|
||||||
|
ContinuousJoint,
|
||||||
|
FloatingJoint,
|
||||||
|
PlanarJoint,
|
||||||
|
FixedJoint,
|
||||||
|
};
|
||||||
|
|
||||||
|
///return >=0 for the root link index, -1 if there is no root link
|
||||||
|
virtual int getRootLinkIndex() const = 0;
|
||||||
|
|
||||||
|
///pure virtual interfaces, precondition is a valid linkIndex (you can assert/terminate if the linkIndex is out of range)
|
||||||
|
virtual std::string getLinkName(int linkIndex) const =0;
|
||||||
|
|
||||||
|
virtual std::string getJointName(int linkIndex) const = 0;
|
||||||
|
|
||||||
|
//fill mass and inertial data. If inertial data is missing, please initialize mass, inertia to sensitive values, and inertialFrame to identity.
|
||||||
|
virtual void getMassAndInertia(int urdfLinkIndex, btScalar& mass,btVector3& localInertiaDiagonal, btTransform& inertialFrame) const =0;
|
||||||
|
|
||||||
|
///fill an array of child link indices for this link, btAlignedObjectArray behaves like a std::vector so just use push_back and resize(0) if needed
|
||||||
|
virtual void getLinkChildIndices(int urdfLinkIndex, btAlignedObjectArray<int>& childLinkIndices) const =0;
|
||||||
|
|
||||||
|
virtual bool getJointInfo(int urdfLinkIndex, btTransform& parent2joint, btVector3& jointAxisInJointSpace, int& jointType, btScalar& jointLowerLimit, btScalar& jointUpperLimit) const =0;
|
||||||
|
|
||||||
|
virtual int convertLinkVisualShapes(int linkIndex, const char* pathPrefix, const btTransform& localInertialFrame) const=0;
|
||||||
|
|
||||||
|
///create Bullet collision shapes from URDF 'Collision' objects, specified in inertial frame of the link.
|
||||||
|
virtual class btCompoundShape* convertLinkCollisionShapes(int linkIndex, const char* pathPrefix, const btTransform& localInertiaFrame) const = 0;
|
||||||
|
|
||||||
|
virtual void createRigidBodyGraphicsInstance(int linkIndex, class btRigidBody* body, const btVector3& colorRgba, int graphicsIndex) const = 0;
|
||||||
|
|
||||||
|
///optionally create some graphical representation from a collision object, usually for visual debugging purposes.
|
||||||
|
virtual void createCollisionObjectGraphicsInstance(int linkIndex, class btCollisionObject* col, const btVector3& colorRgba) const = 0;
|
||||||
|
|
||||||
|
virtual class btMultiBody* allocateMultiBody(int urdfLinkIndex, int totalNumJoints,btScalar mass, const btVector3& localInertiaDiagonal, bool isFixedBase, bool canSleep, bool multiDof) const =0;
|
||||||
|
|
||||||
|
virtual class btRigidBody* allocateRigidBody(int urdfLinkIndex, btScalar mass, const btVector3& localInertiaDiagonal, const btTransform& initialWorldTrans, class btCollisionShape* colShape) const = 0;
|
||||||
|
|
||||||
|
virtual class btGeneric6DofSpring2Constraint* allocateGeneric6DofSpring2Constraint(int urdfLinkIndex, btRigidBody& rbA /*parent*/, btRigidBody& rbB, const btTransform& offsetInA, const btTransform& offsetInB, int rotateOrder=0) const = 0;
|
||||||
|
|
||||||
|
virtual class btMultiBodyLinkCollider* allocateMultiBodyLinkCollider(int urdfLinkIndex, int mbLinkIndex, btMultiBody* body) const = 0;
|
||||||
|
|
||||||
|
virtual void addLinkMapping(int urdfLinkIndex, int mbLinkIndex) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void printTree(const URDF2Bullet& u2b, int linkIndex, int identationLevel=0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ConvertURDF2Bullet(const URDF2Bullet& u2b, const btTransform& rootTransformInWorldSpace, btMultiBodyDynamicsWorld* world,bool createMultiBody, const char* pathPrefix);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //_URDF2BULLET_H
|
||||||
|
|
||||||
825
examples/Importers/ImportURDFDemo/urdf_samples.h
Normal file
825
examples/Importers/ImportURDFDemo/urdf_samples.h
Normal file
@@ -0,0 +1,825 @@
|
|||||||
|
#ifndef URDF_SAMPLES_H
|
||||||
|
#define URDF_SAMPLES_H
|
||||||
|
|
||||||
|
#define MSTRINGIFY(A) #A
|
||||||
|
|
||||||
|
|
||||||
|
const char* urdf_char2 = MSTRINGIFY(
|
||||||
|
<robot name="test_robot">
|
||||||
|
<link name="link1" />
|
||||||
|
<link name="link2" />
|
||||||
|
<link name="link3" />
|
||||||
|
<link name="link4" />
|
||||||
|
|
||||||
|
<joint name="joint1" type="continuous">
|
||||||
|
<parent link="link1"/>
|
||||||
|
<child link="link2"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<joint name="joint2" type="continuous">
|
||||||
|
<parent link="link1"/>
|
||||||
|
<child link="link3"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<joint name="joint3" type="continuous">
|
||||||
|
<parent link="link3"/>
|
||||||
|
<child link="link4"/>
|
||||||
|
</joint>
|
||||||
|
</robot>);
|
||||||
|
|
||||||
|
const char* urdf_char1 = MSTRINGIFY(
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<robot name="myfirst">
|
||||||
|
<link name="base_link">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length="0.6" radius="0.2"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
</robot>
|
||||||
|
);
|
||||||
|
|
||||||
|
const char* urdf_char3 = MSTRINGIFY(<?xml version="1.0"?>
|
||||||
|
<robot name="multipleshapes">
|
||||||
|
<link name="base_link">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length="0.6" radius="0.2"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<link name="right_leg">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size="0.6 .2 .1"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="base_to_right_leg" type="fixed">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="right_leg"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
</robot>);
|
||||||
|
|
||||||
|
const char* urdf_char4 = MSTRINGIFY(
|
||||||
|
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<robot name="materials">
|
||||||
|
<link name="base_link">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length="0.6" radius="0.2"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="blue">
|
||||||
|
<color rgba="0 0 .8 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<link name="right_leg">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size="0.6 .2 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
|
||||||
|
<material name="white">
|
||||||
|
<color rgba="1 1 1 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="base_to_right_leg" type="fixed">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="right_leg"/>
|
||||||
|
<origin xyz="0.22 0 .25"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_leg">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size="0.6 .2 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
|
||||||
|
<material name="white"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="base_to_left_leg" type="fixed">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="left_leg"/>
|
||||||
|
<origin xyz="-0.22 0 .25"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="head">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<sphere radius="0.2"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="white"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="head_swivel" type="fixed">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="head"/>
|
||||||
|
<origin xyz="0 0 0.3"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="box">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size=".08 .08 .08"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="blue"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="tobox" type="fixed">
|
||||||
|
<parent link="head"/>
|
||||||
|
<child link="box"/>
|
||||||
|
<origin xyz="0 0.1414 0.1414"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
</robot>
|
||||||
|
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
const char* urdf_char_r2d2 = MSTRINGIFY(
|
||||||
|
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<robot name="visual">
|
||||||
|
<link name="base_link">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length="0.6" radius="0.2"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="blue">
|
||||||
|
<color rgba="0 0 .8 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<link name="right_leg">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size="0.6 .2 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
|
||||||
|
<material name="white">
|
||||||
|
<color rgba="1 1 1 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="base_to_right_leg" type="fixed">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="right_leg"/>
|
||||||
|
<origin xyz="0.22 0 .25"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="right_base">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size=".1 0.4 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="white"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="right_base_joint" type="fixed">
|
||||||
|
<parent link="right_leg"/>
|
||||||
|
<child link="right_base"/>
|
||||||
|
<origin xyz="0 0 -0.6"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="right_front_wheel">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="black">
|
||||||
|
<color rgba="0 0 0 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="right_front_wheel_joint" type="fixed">
|
||||||
|
<parent link="right_base"/>
|
||||||
|
<child link="right_front_wheel"/>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0.133333333333 -0.085"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="right_back_wheel">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="black"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="right_back_wheel_joint" type="fixed">
|
||||||
|
<parent link="right_base"/>
|
||||||
|
<child link="right_back_wheel"/>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 -0.133333333333 -0.085"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_leg">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size="0.6 .2 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
|
||||||
|
<material name="white"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="base_to_left_leg" type="fixed">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="left_leg"/>
|
||||||
|
<origin xyz="-0.22 0 .25"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_base">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size=".1 0.4 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="white"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="left_base_joint" type="fixed">
|
||||||
|
<parent link="left_leg"/>
|
||||||
|
<child link="left_base"/>
|
||||||
|
<origin xyz="0 0 -0.6"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_front_wheel">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="black"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="left_front_wheel_joint" type="fixed">
|
||||||
|
<parent link="left_base"/>
|
||||||
|
<child link="left_front_wheel"/>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0.133333333333 -0.085"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_back_wheel">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="black"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="left_back_wheel_joint" type="fixed">
|
||||||
|
<parent link="left_base"/>
|
||||||
|
<child link="left_back_wheel"/>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 -0.133333333333 -0.085"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<joint name="gripper_extension" type="fixed">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="gripper_pole"/>
|
||||||
|
<origin rpy="0 0 1.57075" xyz="0 0.19 .2"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="gripper_pole">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length="0.2" radius=".01"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0 " xyz="0.1 0 0"/>
|
||||||
|
<material name="Gray">
|
||||||
|
<color rgba=".7 .7 .7 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="left_gripper_joint" type="fixed">
|
||||||
|
<origin rpy="0 0 0" xyz="0.2 0.01 0"/>
|
||||||
|
<parent link="gripper_pole"/>
|
||||||
|
<child link="left_gripper"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_gripper">
|
||||||
|
<visual>
|
||||||
|
<origin rpy="0.0 0 0" xyz="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger.dae"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="left_tip_joint" type="fixed">
|
||||||
|
<parent link="left_gripper"/>
|
||||||
|
<child link="left_tip"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_tip">
|
||||||
|
<visual>
|
||||||
|
<origin rpy="0.0 0 0" xyz="0.09137 0.00495 0"/>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger_tip.dae"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="right_gripper_joint" type="fixed">
|
||||||
|
<origin rpy="0 0 0" xyz="0.2 -0.01 0"/>
|
||||||
|
<parent link="gripper_pole"/>
|
||||||
|
<child link="right_gripper"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="right_gripper">
|
||||||
|
<visual>
|
||||||
|
<origin rpy="-3.1415 0 0" xyz="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger.dae"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="right_tip_joint" type="fixed">
|
||||||
|
<parent link="right_gripper"/>
|
||||||
|
<child link="right_tip"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="right_tip">
|
||||||
|
<visual>
|
||||||
|
<origin rpy="-3.1415 0 0" xyz="0.09137 0.00495 0"/>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="package://pr2_description/meshes/gripper_v0/l_finger_tip.dae"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<link name="head">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<sphere radius="0.2"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="white"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="head_swivel" type="fixed">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="head"/>
|
||||||
|
<origin xyz="0 0 0.3"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="box">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size=".08 .08 .08"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="blue"/>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="tobox" type="fixed">
|
||||||
|
<parent link="head"/>
|
||||||
|
<child link="box"/>
|
||||||
|
<origin xyz="0 0.1414 0.1414"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
</robot>
|
||||||
|
);
|
||||||
|
|
||||||
|
const char* urdf_char = MSTRINGIFY(
|
||||||
|
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<robot name="physics">
|
||||||
|
<link name="base_link">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length="0.6" radius="0.2"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="blue">
|
||||||
|
<color rgba="0 0 .8 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length="0.6" radius="0.2"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="10"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<link name="right_leg">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size="0.6 .2 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
|
||||||
|
<material name="white">
|
||||||
|
<color rgba="1 1 1 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<box size="0.6 .2 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="10"/>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="base_to_right_leg" type="fixed">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="right_leg"/>
|
||||||
|
<origin xyz="0.22 0 .25"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="right_base">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size=".1 0.4 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="white"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<box size=".1 0.4 .1"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="10"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="right_base_joint" type="fixed">
|
||||||
|
<parent link="right_leg"/>
|
||||||
|
<child link="right_base"/>
|
||||||
|
<origin xyz="0 0 -0.6"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="right_front_wheel">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="black">
|
||||||
|
<color rgba="0 0 0 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="1"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="right_front_wheel_joint" type="continuous">
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
<parent link="right_base"/>
|
||||||
|
<child link="right_front_wheel"/>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0.133333333333 -0.085"/>
|
||||||
|
<limit effort="100" velocity="100"/>
|
||||||
|
<joint_properties damping="0.0" friction="0.0"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="right_back_wheel">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="black"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="1"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="right_back_wheel_joint" type="continuous">
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
<parent link="right_base"/>
|
||||||
|
<child link="right_back_wheel"/>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 -0.133333333333 -0.085"/>
|
||||||
|
<limit effort="100" velocity="100"/>
|
||||||
|
<joint_properties damping="0.0" friction="0.0"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_leg">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size="0.6 .2 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
|
||||||
|
<material name="white"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<box size="0.6 .2 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="10"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="base_to_left_leg" type="fixed">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="left_leg"/>
|
||||||
|
<origin xyz="-0.22 0 .25"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_base">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size=".1 0.4 .1"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="white"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<box size=".1 0.4 .1"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="10"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="left_base_joint" type="fixed">
|
||||||
|
<parent link="left_leg"/>
|
||||||
|
<child link="left_base"/>
|
||||||
|
<origin xyz="0 0 -0.6"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_front_wheel">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="black"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="1"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="left_front_wheel_joint" type="continuous">
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
<parent link="left_base"/>
|
||||||
|
<child link="left_front_wheel"/>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 0.133333333333 -0.085"/>
|
||||||
|
<limit effort="100" velocity="100"/>
|
||||||
|
<joint_properties damping="0.0" friction="0.0"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_back_wheel">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="black"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length=".1" radius="0.035"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="1"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="left_back_wheel_joint" type="continuous">
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
<parent link="left_base"/>
|
||||||
|
<child link="left_back_wheel"/>
|
||||||
|
<origin rpy="0 1.57075 0" xyz="0 -0.133333333333 -0.085"/>
|
||||||
|
<limit effort="100" velocity="100"/>
|
||||||
|
<joint_properties damping="0.0" friction="0.0"/>
|
||||||
|
</joint>
|
||||||
|
<joint name="gripper_extension" type="prismatic">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="gripper_pole"/>
|
||||||
|
<limit effort="1000.0" lower="-0.38" upper="0" velocity="0.5"/>
|
||||||
|
<origin rpy="0 0 1.57075" xyz="0 0.19 .2"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="gripper_pole">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length="0.2" radius=".01"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0 " xyz="0.1 0 0"/>
|
||||||
|
<material name="Gray">
|
||||||
|
<color rgba=".7 .7 .7 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<cylinder length="0.2" radius=".01"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0 1.57075 0 " xyz="0.1 0 0"/>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="0.05"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="left_gripper_joint" type="revolute">
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
<limit effort="1000.0" lower="0.0" upper="0.548" velocity="0.5"/>
|
||||||
|
<origin rpy="0 0 0" xyz="0.2 0.01 0"/>
|
||||||
|
<parent link="gripper_pole"/>
|
||||||
|
<child link="left_gripper"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_gripper">
|
||||||
|
<visual>
|
||||||
|
<origin rpy="0.0 0 0" xyz="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="l_finger.stl"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="l_finger.stl"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0.0 0 0" xyz="0 0 0"/>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="0.05"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="left_tip_joint" type="fixed">
|
||||||
|
<parent link="left_gripper"/>
|
||||||
|
<child link="left_tip"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="left_tip">
|
||||||
|
<visual>
|
||||||
|
<origin rpy="0.0 0 0" xyz="0.09137 0.00495 0"/>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="l_finger_tip.stl"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="l_finger_tip.stl"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="0.0 0 0" xyz="0.09137 0.00495 0"/>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="0.05"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="right_gripper_joint" type="revolute">
|
||||||
|
<axis xyz="0 0 -1"/>
|
||||||
|
<limit effort="1000.0" lower="0.0" upper="0.548" velocity="0.5"/>
|
||||||
|
<origin rpy="0 0 0" xyz="0.2 -0.01 0"/>
|
||||||
|
<parent link="gripper_pole"/>
|
||||||
|
<child link="right_gripper"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="right_gripper">
|
||||||
|
<visual>
|
||||||
|
<origin rpy="-3.1415 0 0" xyz="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="l_finger.stl"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="l_finger.stl"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="-3.1415 0 0" xyz="0 0 0"/>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="0.05"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="right_tip_joint" type="fixed">
|
||||||
|
<parent link="right_gripper"/>
|
||||||
|
<child link="right_tip"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="right_tip">
|
||||||
|
<visual>
|
||||||
|
<origin rpy="-3.1415 0 0" xyz="0.09137 0.00495 0"/>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="l_finger_tip.stl"/>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="l_finger_tip.stl"/>
|
||||||
|
</geometry>
|
||||||
|
<origin rpy="-3.1415 0 0" xyz="0.09137 0.00495 0"/>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="0.05"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<link name="head">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<sphere radius="0.2"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="white"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<sphere radius="0.2"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="10"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="head_swivel" type="continuous">
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="head"/>
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
<origin xyz="0 0 0.3"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="box">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<box size=".08 .08 .08"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="blue"/>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<box size=".08 .08 .08"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
<inertial>
|
||||||
|
<mass value="1"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="tobox" type="fixed">
|
||||||
|
<parent link="head"/>
|
||||||
|
<child link="box"/>
|
||||||
|
<origin xyz="0 0.1414 0.1414"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
</robot>
|
||||||
|
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif //URDF_SAMPLES_H
|
||||||
|
|
||||||
65
examples/OpenGLWindow/CMakeLists.txt
Normal file
65
examples/OpenGLWindow/CMakeLists.txt
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(
|
||||||
|
..
|
||||||
|
../../src
|
||||||
|
)
|
||||||
|
|
||||||
|
FILE(GLOB OpenGLWindow_HDRS "*.h" )
|
||||||
|
|
||||||
|
FILE(GLOB OpenGLWindowMac_CPP "Mac*.mm")
|
||||||
|
FILE(GLOB OpenGLWindowWin32_CPP "Win32*.cpp")
|
||||||
|
FILE(GLOB OpenGLWindowLinux_CPP "X11*.cpp")
|
||||||
|
|
||||||
|
FILE(GLOB OpenGLWindowCommon_CPP "*.cpp" )
|
||||||
|
|
||||||
|
LIST(REMOVE_ITEM OpenGLWindowCommon_CPP ${OpenGLWindowMac_CPP} )
|
||||||
|
LIST(REMOVE_ITEM OpenGLWindowCommon_CPP ${OpenGLWindowWin32_CPP} )
|
||||||
|
LIST(REMOVE_ITEM OpenGLWindowCommon_CPP ${OpenGLWindowLinux_CPP} )
|
||||||
|
LIST(REMOVE_ITEM OpenGLWindowCommon_CPP X11OpenGLWindow.cpp )
|
||||||
|
#MESSAGE (${OpenGLWindowCommon_CPP})
|
||||||
|
|
||||||
|
IF (WIN32)
|
||||||
|
SET(OpenGLWindow_SRCS GlewWindows/glew.c ${OpenGLWindowWin32_CPP} ${OpenGLWindowCommon_CPP})
|
||||||
|
INCLUDE_DIRECTORIES(
|
||||||
|
GlewWindows
|
||||||
|
)
|
||||||
|
ADD_DEFINITIONS(-DGLEW_STATIC)
|
||||||
|
ENDIF(WIN32)
|
||||||
|
|
||||||
|
IF (APPLE)
|
||||||
|
SET(OpenGLWindow_SRCS ${OpenGLWindowMac_CPP} ${OpenGLWindowCommon_CPP} )
|
||||||
|
ENDIF(APPLE)
|
||||||
|
|
||||||
|
#no Linux detection?
|
||||||
|
IF(NOT WIN32 AND NOT APPLE)
|
||||||
|
INCLUDE_DIRECTORIES(
|
||||||
|
GlewWindows
|
||||||
|
)
|
||||||
|
ADD_DEFINITIONS(-DGLEW_STATIC)
|
||||||
|
ADD_DEFINITIONS("-DGLEW_INIT_OPENGL11_FUNCTIONS=1")
|
||||||
|
ADD_DEFINITIONS("-DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1")
|
||||||
|
|
||||||
|
SET(OpenGLWindow_SRCS ${OpenGLWindowLinux_CPP} GlewWindows/glew.c ${OpenGLWindowCommon_CPP} )
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ADD_LIBRARY(OpenGLWindow ${OpenGLWindow_SRCS} ${OpenGLWindow_HDRS})
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
target_link_libraries(OpenGLWindow X11)
|
||||||
|
elseif (APPLE)
|
||||||
|
target_link_libraries(OpenGLWindow ${COCOA_LIBRARY})
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
target_link_libraries(OpenGLWindow Bullet3Common)
|
||||||
|
if (WIN32 OR APPLE)
|
||||||
|
target_link_libraries(OpenGLWindow ${OPENGL_gl_LIBRARY})
|
||||||
|
else()
|
||||||
|
set (CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||||
|
FIND_PACKAGE(Threads)
|
||||||
|
target_link_libraries(OpenGLWindow ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#target_link_libraries(OpenGLWindow ${OPENGL_gl_LIBRARY})
|
||||||
22
examples/OpenGLWindow/GLInstanceGraphicsShape.h
Normal file
22
examples/OpenGLWindow/GLInstanceGraphicsShape.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef GL_INSTANCE_GRAPHICS_SHAPE_H
|
||||||
|
#define GL_INSTANCE_GRAPHICS_SHAPE_H
|
||||||
|
|
||||||
|
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||||
|
|
||||||
|
struct GLInstanceVertex
|
||||||
|
{
|
||||||
|
float xyzw[4];
|
||||||
|
float normal[3];
|
||||||
|
float uv[2];
|
||||||
|
};
|
||||||
|
struct GLInstanceGraphicsShape
|
||||||
|
{
|
||||||
|
b3AlignedObjectArray<GLInstanceVertex>* m_vertices;
|
||||||
|
int m_numvertices;
|
||||||
|
b3AlignedObjectArray<int>* m_indices;
|
||||||
|
int m_numIndices;
|
||||||
|
float m_scaling[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //GL_INSTANCE_GRAPHICS_SHAPE_H
|
||||||
|
|
||||||
20
examples/OpenGLWindow/GLInstanceRendererInternalData.h
Normal file
20
examples/OpenGLWindow/GLInstanceRendererInternalData.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef GL_INSTANCE_RENDERER_INTERNAL_DATA_H
|
||||||
|
#define GL_INSTANCE_RENDERER_INTERNAL_DATA_H
|
||||||
|
|
||||||
|
#include "OpenGLInclude.h"
|
||||||
|
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||||
|
|
||||||
|
struct GLInstanceRendererInternalData
|
||||||
|
{
|
||||||
|
|
||||||
|
b3AlignedObjectArray<GLfloat> m_instance_positions_ptr;
|
||||||
|
b3AlignedObjectArray<GLfloat> m_instance_quaternion_ptr;
|
||||||
|
b3AlignedObjectArray<GLfloat> m_instance_colors_ptr;
|
||||||
|
b3AlignedObjectArray<GLfloat> m_instance_scale_ptr;
|
||||||
|
|
||||||
|
int m_vboSize;
|
||||||
|
GLuint m_vbo;
|
||||||
|
int m_totalNumInstances;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //GL_INSTANCE_RENDERER_INTERNAL_DATA_H
|
||||||
1929
examples/OpenGLWindow/GLInstancingRenderer.cpp
Normal file
1929
examples/OpenGLWindow/GLInstancingRenderer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
174
examples/OpenGLWindow/GLInstancingRenderer.h
Normal file
174
examples/OpenGLWindow/GLInstancingRenderer.h
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
//Originally written by Erwin Coumans
|
||||||
|
|
||||||
|
#ifndef GL_INSTANCING_RENDERER_H
|
||||||
|
#define GL_INSTANCING_RENDERER_H
|
||||||
|
|
||||||
|
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||||
|
#include "../CommonInterfaces/CommonRenderInterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
void b3DefaultMouseButtonCallback( int button, int state, float x, float y);
|
||||||
|
void b3DefaultMouseMoveCallback( float x, float y);
|
||||||
|
void b3DefaultKeyboardCallback(int key, int state);
|
||||||
|
void b3DefaultWheelCallback( float deltax, float deltay);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class GLInstancingRenderer : public CommonRenderInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
b3AlignedObjectArray<struct b3GraphicsInstance*> m_graphicsInstances;
|
||||||
|
|
||||||
|
int m_maxNumObjectCapacity;
|
||||||
|
int m_maxShapeCapacityInBytes;
|
||||||
|
struct InternalDataRenderer* m_data;
|
||||||
|
|
||||||
|
bool m_textureenabled;
|
||||||
|
bool m_textureinitialized;
|
||||||
|
|
||||||
|
int m_screenWidth;
|
||||||
|
int m_screenHeight;
|
||||||
|
|
||||||
|
int m_upAxis;
|
||||||
|
bool m_enableBlend;
|
||||||
|
|
||||||
|
void renderSceneInternal(int renderMode=B3_DEFAULT_RENDERMODE);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
GLInstancingRenderer(int m_maxObjectCapacity, int maxShapeCapacityInBytes = 56*1024*1024);
|
||||||
|
virtual ~GLInstancingRenderer();
|
||||||
|
|
||||||
|
virtual void init();
|
||||||
|
|
||||||
|
virtual void renderScene();
|
||||||
|
|
||||||
|
void InitShaders();
|
||||||
|
void CleanupShaders();
|
||||||
|
void removeAllInstances();
|
||||||
|
|
||||||
|
virtual void updateShape(int shapeIndex, const float* vertices);
|
||||||
|
|
||||||
|
///vertices must be in the format x,y,z, nx,ny,nz, u,v
|
||||||
|
virtual int registerShape(const float* vertices, int numvertices, const int* indices, int numIndices, int primitiveType=B3_GL_TRIANGLES, int textureIndex=-1);
|
||||||
|
|
||||||
|
virtual int registerTexture(const unsigned char* texels, int width, int height);
|
||||||
|
|
||||||
|
///position x,y,z, quaternion x,y,z,w, color r,g,b,a, scaling x,y,z
|
||||||
|
virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling);
|
||||||
|
virtual int registerGraphicsInstance(int shapeIndex, const double* position, const double* quaternion, const double* color, const double* scaling);
|
||||||
|
|
||||||
|
void writeTransforms();
|
||||||
|
|
||||||
|
virtual void writeSingleInstanceTransformToCPU(const float* position, const float* orientation, int srcIndex);
|
||||||
|
virtual void writeSingleInstanceTransformToCPU(const double* position, const double* orientation, int srcIndex)
|
||||||
|
{
|
||||||
|
float pos[4];
|
||||||
|
float orn[4];
|
||||||
|
pos[0] = (float)position[0];
|
||||||
|
pos[1] = (float)position[1];
|
||||||
|
pos[2] = (float)position[2];
|
||||||
|
pos[3] = (float)position[3];
|
||||||
|
orn[0] =(float)orientation[0];
|
||||||
|
orn[1] =(float)orientation[1];
|
||||||
|
orn[2] =(float)orientation[2];
|
||||||
|
orn[3] =(float)orientation[3];
|
||||||
|
writeSingleInstanceTransformToCPU(pos,orn,srcIndex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void writeSingleInstanceTransformToGPU(float* position, float* orientation, int srcIndex);
|
||||||
|
|
||||||
|
virtual void writeSingleInstanceColorToCPU(float* color, int srcIndex);
|
||||||
|
virtual void writeSingleInstanceColorToCPU(double* color, int srcIndex);
|
||||||
|
|
||||||
|
virtual void getMouseDirection(float* dir, int mouseX, int mouseY);
|
||||||
|
|
||||||
|
struct GLInstanceRendererInternalData* getInternalData();
|
||||||
|
|
||||||
|
virtual void drawLine(const float from[4], const float to[4], const float color[4], float lineWidth=1);
|
||||||
|
virtual void drawLine(const double from[4], const double to[4], const double color[4], double lineWidth=1);
|
||||||
|
virtual void drawLines(const float* positions, const float color[4], int numPoints, int pointStrideInBytes, const unsigned int* indices, int numIndices, float pointDrawSize);
|
||||||
|
virtual void drawPoints(const float* positions, const float color[4], int numPoints, int pointStrideInBytes, float pointDrawSize);
|
||||||
|
virtual void drawPoint(const float* position, const float color[4], float pointSize=1);
|
||||||
|
virtual void drawPoint(const double* position, const double color[4], double pointDrawSize=1);
|
||||||
|
virtual void updateCamera(int upAxis=1);
|
||||||
|
|
||||||
|
virtual void getCameraPosition(float cameraPos[4]);
|
||||||
|
virtual void getCameraPosition(double cameraPos[4])
|
||||||
|
{
|
||||||
|
float campos[4];
|
||||||
|
getCameraPosition(campos);
|
||||||
|
cameraPos[0] = campos[0];
|
||||||
|
cameraPos[1] = campos[1];
|
||||||
|
cameraPos[2] = campos[2];
|
||||||
|
cameraPos[3] = campos[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setCameraDistance(float dist);
|
||||||
|
virtual float getCameraDistance() const;
|
||||||
|
|
||||||
|
//set the camera 'target'
|
||||||
|
virtual void setCameraTargetPosition(float x, float y, float z);
|
||||||
|
virtual void setCameraTargetPosition(float cameraPos[4]);
|
||||||
|
virtual void getCameraTargetPosition(float cameraPos[4]) const;
|
||||||
|
virtual void getCameraTargetPosition(double cameraPos[4]) const
|
||||||
|
{
|
||||||
|
float campos[4];
|
||||||
|
getCameraTargetPosition(campos);
|
||||||
|
cameraPos[0] = campos[0];
|
||||||
|
cameraPos[1] = campos[1];
|
||||||
|
cameraPos[2] = campos[2];
|
||||||
|
cameraPos[3] = campos[3];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setCameraYaw(float yaw);
|
||||||
|
virtual void setCameraPitch(float pitch);
|
||||||
|
virtual float getCameraYaw() const;
|
||||||
|
virtual float getCameraPitch() const;
|
||||||
|
|
||||||
|
virtual void getCameraViewMatrix(float viewMat[16]) const;
|
||||||
|
virtual void getCameraProjectionMatrix(float projMat[16]) const;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void resize(int width, int height);
|
||||||
|
virtual int getScreenWidth()
|
||||||
|
{
|
||||||
|
return m_screenWidth;
|
||||||
|
}
|
||||||
|
virtual int getScreenHeight()
|
||||||
|
{
|
||||||
|
return m_screenHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getMaxShapeCapacity() const
|
||||||
|
{
|
||||||
|
return m_maxShapeCapacityInBytes;
|
||||||
|
}
|
||||||
|
virtual int getInstanceCapacity() const
|
||||||
|
{
|
||||||
|
return m_maxNumObjectCapacity;
|
||||||
|
}
|
||||||
|
virtual void enableShadowMap();
|
||||||
|
virtual void enableBlend(bool blend)
|
||||||
|
{
|
||||||
|
m_enableBlend = blend;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //GL_INSTANCING_RENDERER_H
|
||||||
21
examples/OpenGLWindow/GLPrimInternalData.h
Normal file
21
examples/OpenGLWindow/GLPrimInternalData.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef PRIM_INTERNAL_DATA
|
||||||
|
#define PRIM_INTERNAL_DATA
|
||||||
|
|
||||||
|
#include "OpenGLInclude.h"
|
||||||
|
|
||||||
|
struct PrimInternalData
|
||||||
|
{
|
||||||
|
GLuint m_shaderProg;
|
||||||
|
GLint m_viewmatUniform;
|
||||||
|
GLint m_projMatUniform;
|
||||||
|
GLint m_positionUniform;
|
||||||
|
GLint m_colourAttribute;
|
||||||
|
GLint m_positionAttribute;
|
||||||
|
GLint m_textureAttribute;
|
||||||
|
GLuint m_vertexBuffer;
|
||||||
|
GLuint m_vertexArrayObject;
|
||||||
|
GLuint m_indexBuffer;
|
||||||
|
GLuint m_texturehandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //PRIM_INTERNAL_DATA
|
||||||
322
examples/OpenGLWindow/GLPrimitiveRenderer.cpp
Normal file
322
examples/OpenGLWindow/GLPrimitiveRenderer.cpp
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
#include "GLPrimitiveRenderer.h"
|
||||||
|
#include "GLPrimInternalData.h"
|
||||||
|
|
||||||
|
#include "LoadShader.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
static const char* vertexShader3D= \
|
||||||
|
"#version 150 \n"
|
||||||
|
"\n"
|
||||||
|
"uniform mat4 viewMatrix, projMatrix;\n"
|
||||||
|
"in vec4 position;\n"
|
||||||
|
"in vec4 colour;\n"
|
||||||
|
"out vec4 colourV;\n"
|
||||||
|
"\n"
|
||||||
|
"in vec2 texuv;\n"
|
||||||
|
"out vec2 texuvV;\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"void main (void)\n"
|
||||||
|
"{\n"
|
||||||
|
" colourV = colour;\n"
|
||||||
|
" gl_Position = projMatrix * viewMatrix * position ;\n"
|
||||||
|
" texuvV=texuv;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static const char* fragmentShader3D= \
|
||||||
|
"#version 150\n"
|
||||||
|
"\n"
|
||||||
|
"uniform vec2 p;\n"
|
||||||
|
"in vec4 colourV;\n"
|
||||||
|
"out vec4 fragColour;\n"
|
||||||
|
"in vec2 texuvV;\n"
|
||||||
|
"\n"
|
||||||
|
"uniform sampler2D Diffuse;\n"
|
||||||
|
"\n"
|
||||||
|
"void main(void)\n"
|
||||||
|
"{\n"
|
||||||
|
" vec4 texcolor = texture(Diffuse,texuvV);\n"
|
||||||
|
" if (p.x==0.f)\n"
|
||||||
|
" {\n"
|
||||||
|
" texcolor = vec4(1,1,1,texcolor.x);\n"
|
||||||
|
" }\n"
|
||||||
|
" fragColour = colourV*texcolor;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int s_indexData[6] = {0,1,2,0,2,3};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GLPrimitiveRenderer::GLPrimitiveRenderer(int screenWidth, int screenHeight)
|
||||||
|
:m_screenWidth(screenWidth),
|
||||||
|
m_screenHeight(screenHeight)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_data = new PrimInternalData;
|
||||||
|
|
||||||
|
m_data->m_shaderProg = gltLoadShaderPair(vertexShader3D,fragmentShader3D);
|
||||||
|
|
||||||
|
m_data->m_viewmatUniform = glGetUniformLocation(m_data->m_shaderProg,"viewMatrix");
|
||||||
|
if (m_data->m_viewmatUniform < 0) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
m_data->m_projMatUniform = glGetUniformLocation(m_data->m_shaderProg,"projMatrix");
|
||||||
|
if (m_data->m_projMatUniform < 0) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
m_data->m_positionUniform = glGetUniformLocation(m_data->m_shaderProg, "p");
|
||||||
|
if (m_data->m_positionUniform < 0) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
m_data->m_colourAttribute = glGetAttribLocation(m_data->m_shaderProg, "colour");
|
||||||
|
if (m_data->m_colourAttribute < 0) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
m_data->m_positionAttribute = glGetAttribLocation(m_data->m_shaderProg, "position");
|
||||||
|
if (m_data->m_positionAttribute < 0) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
m_data->m_textureAttribute = glGetAttribLocation(m_data->m_shaderProg,"texuv");
|
||||||
|
if (m_data->m_textureAttribute < 0) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadBufferData();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLPrimitiveRenderer::loadBufferData()
|
||||||
|
{
|
||||||
|
|
||||||
|
PrimVertex vertexData[4] = {
|
||||||
|
{ PrimVec4(-1, -1, 0.0, 1.0 ), PrimVec4( 1.0, 0.0, 0.0, 1.0 ) ,PrimVec2(0,0)},
|
||||||
|
{ PrimVec4(-1, 1, 0.0, 1.0 ), PrimVec4( 0.0, 1.0, 0.0, 1.0 ) ,PrimVec2(0,1)},
|
||||||
|
{ PrimVec4( 1, 1, 0.0, 1.0 ), PrimVec4( 0.0, 0.0, 1.0, 1.0 ) ,PrimVec2(1,1)},
|
||||||
|
{ PrimVec4( 1, -1, 0.0, 1.0 ), PrimVec4( 1.0, 1.0, 1.0, 1.0 ) ,PrimVec2(1,0)}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &m_data->m_vertexArrayObject);
|
||||||
|
glBindVertexArray(m_data->m_vertexArrayObject);
|
||||||
|
|
||||||
|
glGenBuffers(1, &m_data->m_vertexBuffer);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vertexBuffer);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(PrimVertex), vertexData, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
glGenBuffers(1, &m_data->m_indexBuffer);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_data->m_indexBuffer);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER,6*sizeof(int), s_indexData,GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(m_data->m_positionAttribute);
|
||||||
|
glEnableVertexAttribArray(m_data->m_colourAttribute);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(m_data->m_textureAttribute);
|
||||||
|
|
||||||
|
glVertexAttribPointer(m_data->m_positionAttribute, 4, GL_FLOAT, GL_FALSE, sizeof(PrimVertex), (const GLvoid *)0);
|
||||||
|
glVertexAttribPointer(m_data->m_colourAttribute , 4, GL_FLOAT, GL_FALSE, sizeof(PrimVertex), (const GLvoid *)sizeof(PrimVec4));
|
||||||
|
glVertexAttribPointer(m_data->m_textureAttribute , 2, GL_FLOAT, GL_FALSE, sizeof(PrimVertex), (const GLvoid *)(sizeof(PrimVec4)+sizeof(PrimVec4)));
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
GLubyte* image=new GLubyte[256*256*3];
|
||||||
|
for(int y=0;y<256;++y)
|
||||||
|
{
|
||||||
|
// const int t=y>>5;
|
||||||
|
GLubyte* pi=image+y*256*3;
|
||||||
|
for(int x=0;x<256;++x)
|
||||||
|
{
|
||||||
|
if (x<y)//x<2||y<2||x>253||y>253)
|
||||||
|
{
|
||||||
|
pi[0]=255;
|
||||||
|
pi[1]=0;
|
||||||
|
pi[2]=0;
|
||||||
|
} else
|
||||||
|
|
||||||
|
{
|
||||||
|
pi[0]=255;
|
||||||
|
pi[1]=255;
|
||||||
|
pi[2]=255;
|
||||||
|
}
|
||||||
|
|
||||||
|
pi+=3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenTextures(1,(GLuint*)&m_data->m_texturehandle);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,m_data->m_texturehandle);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256,256,0,GL_RGB,GL_UNSIGNED_BYTE,image);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
delete[] image;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GLPrimitiveRenderer::~GLPrimitiveRenderer()
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D,0);
|
||||||
|
glUseProgram(0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,0);
|
||||||
|
glDeleteProgram(m_data->m_shaderProg);
|
||||||
|
delete m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLPrimitiveRenderer::drawLine()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLPrimitiveRenderer::drawRect(float x0, float y0, float x1, float y1, float color[4])
|
||||||
|
{
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D,m_data->m_texturehandle);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
drawTexturedRect(x0,y0,x1,y1,color,0,0,1,1);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GLPrimitiveRenderer::drawTexturedRect3D(const PrimVertex& v0,const PrimVertex& v1,const PrimVertex& v2,const PrimVertex& v3,float viewMat[16],float projMat[16], bool useRGBA)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
glUseProgram(m_data->m_shaderProg);
|
||||||
|
|
||||||
|
glUniformMatrix4fv(m_data->m_viewmatUniform, 1, false, viewMat);
|
||||||
|
glUniformMatrix4fv(m_data->m_projMatUniform, 1, false, projMat);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vertexBuffer);
|
||||||
|
glBindVertexArray(m_data->m_vertexArrayObject);
|
||||||
|
|
||||||
|
bool useFiltering = false;
|
||||||
|
if (useFiltering)
|
||||||
|
{
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimVertex vertexData[4] = {
|
||||||
|
v0,v1,v2,v3
|
||||||
|
};
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0,4 * sizeof(PrimVertex), vertexData);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
PrimVec2 p( 0.f,0.f);//?b?0.5f * sinf(timeValue), 0.5f * cosf(timeValue) );
|
||||||
|
if (useRGBA)
|
||||||
|
{
|
||||||
|
p.p[0] = 1.f;
|
||||||
|
p.p[1] = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
glUniform2fv(m_data->m_positionUniform, 1, (const GLfloat *)&p);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(m_data->m_positionAttribute);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(m_data->m_colourAttribute);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(m_data->m_textureAttribute);
|
||||||
|
|
||||||
|
glVertexAttribPointer(m_data->m_positionAttribute, 4, GL_FLOAT, GL_FALSE, sizeof(PrimVertex), (const GLvoid *)0);
|
||||||
|
glVertexAttribPointer(m_data->m_colourAttribute , 4, GL_FLOAT, GL_FALSE, sizeof(PrimVertex), (const GLvoid *)sizeof(PrimVec4));
|
||||||
|
glVertexAttribPointer(m_data->m_textureAttribute , 2, GL_FLOAT, GL_FALSE, sizeof(PrimVertex), (const GLvoid *)(sizeof(PrimVec4)+sizeof(PrimVec4)));
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_data->m_indexBuffer);
|
||||||
|
|
||||||
|
//glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
|
int indexCount = 6;
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
//glDisableVertexAttribArray(m_data->m_textureAttribute);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glUseProgram(0);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GLPrimitiveRenderer::drawTexturedRect(float x0, float y0, float x1, float y1, float color[4], float u0,float v0, float u1, float v1, int useRGBA)
|
||||||
|
{
|
||||||
|
float identity[16]={1,0,0,0,
|
||||||
|
0,1,0,0,
|
||||||
|
0,0,1,0,
|
||||||
|
0,0,0,1};
|
||||||
|
PrimVertex vertexData[4] = {
|
||||||
|
{ PrimVec4(-1.f+2.f*x0/float(m_screenWidth), 1.f-2.f*y0/float(m_screenHeight), 0.f, 1.f ), PrimVec4( color[0], color[1], color[2], color[3] ) ,PrimVec2(u0,v0)},
|
||||||
|
{ PrimVec4(-1.f+2.f*x0/float(m_screenWidth), 1.f-2.f*y1/float(m_screenHeight), 0.f, 1.f ), PrimVec4( color[0], color[1], color[2], color[3] ) ,PrimVec2(u0,v1)},
|
||||||
|
{ PrimVec4( -1.f+2.f*x1/float(m_screenWidth), 1.f-2.f*y1/float(m_screenHeight), 0.f, 1.f ), PrimVec4(color[0], color[1], color[2], color[3]) ,PrimVec2(u1,v1)},
|
||||||
|
{ PrimVec4( -1.f+2.f*x1/float(m_screenWidth), 1.f-2.f*y0/float(m_screenHeight), 0.f, 1.f ), PrimVec4( color[0], color[1], color[2], color[3] ) ,PrimVec2(u1,v0)}
|
||||||
|
};
|
||||||
|
|
||||||
|
drawTexturedRect3D(vertexData[0],vertexData[1],vertexData[2],vertexData[3],identity,identity,useRGBA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLPrimitiveRenderer::setScreenSize(int width, int height)
|
||||||
|
{
|
||||||
|
m_screenWidth = width;
|
||||||
|
m_screenHeight = height;
|
||||||
|
|
||||||
|
}
|
||||||
67
examples/OpenGLWindow/GLPrimitiveRenderer.h
Normal file
67
examples/OpenGLWindow/GLPrimitiveRenderer.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#ifndef _GL_PRIMITIVE_RENDERER_H
|
||||||
|
#define _GL_PRIMITIVE_RENDERER_H
|
||||||
|
|
||||||
|
//#include "OpenGLInclude.h"
|
||||||
|
|
||||||
|
struct PrimVec2
|
||||||
|
{
|
||||||
|
PrimVec2(float x, float y)
|
||||||
|
{
|
||||||
|
p[0] = x;
|
||||||
|
p[1] = y;
|
||||||
|
}
|
||||||
|
float p[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PrimVec4
|
||||||
|
{
|
||||||
|
PrimVec4() {}
|
||||||
|
PrimVec4(float x,float y, float z, float w)
|
||||||
|
{
|
||||||
|
p[0] = x;
|
||||||
|
p[1] = y;
|
||||||
|
p[2] = z;
|
||||||
|
p[3] = w;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float p[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PrimVec4 position;
|
||||||
|
PrimVec4 colour;
|
||||||
|
PrimVec2 uv;
|
||||||
|
} PrimVertex;
|
||||||
|
|
||||||
|
|
||||||
|
class GLPrimitiveRenderer
|
||||||
|
{
|
||||||
|
int m_screenWidth;
|
||||||
|
int m_screenHeight;
|
||||||
|
|
||||||
|
struct PrimInternalData* m_data;
|
||||||
|
|
||||||
|
void loadBufferData();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
GLPrimitiveRenderer(int screenWidth, int screenHeight);
|
||||||
|
virtual ~GLPrimitiveRenderer();
|
||||||
|
|
||||||
|
void drawRect(float x0, float y0, float x1, float y1, float color[4]);
|
||||||
|
void drawTexturedRect(float x0, float y0, float x1, float y1, float color[4], float u0,float v0, float u1, float v1, int useRGBA=0);
|
||||||
|
void drawTexturedRect3D(const PrimVertex& v0,const PrimVertex& v1,const PrimVertex& v2,const PrimVertex& v3,float viewMat[16],float projMat[16], bool useRGBA = true);
|
||||||
|
void drawLine();//float from[4], float to[4], float color[4]);
|
||||||
|
void setScreenSize(int width, int height);
|
||||||
|
|
||||||
|
PrimInternalData* getData()
|
||||||
|
{
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif//_GL_PRIMITIVE_RENDERER_H
|
||||||
|
|
||||||
135
examples/OpenGLWindow/GLRenderToTexture.cpp
Normal file
135
examples/OpenGLWindow/GLRenderToTexture.cpp
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
|
||||||
|
///See http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/
|
||||||
|
|
||||||
|
|
||||||
|
#include "GLRenderToTexture.h"
|
||||||
|
#include "Bullet3Common/b3Scalar.h" // for b3Assert
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
bool gIntelLinuxglDrawBufferWorkaround=false;
|
||||||
|
|
||||||
|
GLRenderToTexture::GLRenderToTexture()
|
||||||
|
:m_framebufferName(0)
|
||||||
|
{
|
||||||
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||||
|
const GLubyte* ven = glGetString(GL_VENDOR);
|
||||||
|
printf("ven = %s\n",ven);
|
||||||
|
|
||||||
|
if (strncmp((const char*)ven,"Intel",5)==0)
|
||||||
|
{
|
||||||
|
printf("Workaround for some crash in the Intel OpenGL driver on Linux/Ubuntu\n");
|
||||||
|
gIntelLinuxglDrawBufferWorkaround=true;
|
||||||
|
}
|
||||||
|
#endif//!defined(_WIN32) && !defined(__APPLE__)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLRenderToTexture::init(int width, int height, GLuint textureId, int renderTextureType)
|
||||||
|
{
|
||||||
|
m_renderTextureType = renderTextureType;
|
||||||
|
|
||||||
|
glGenFramebuffers(1, &m_framebufferName);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_framebufferName);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The depth buffer
|
||||||
|
// glGenRenderbuffers(1, &m_depthrenderbuffer);
|
||||||
|
|
||||||
|
// glBindRenderbuffer(GL_RENDERBUFFER, m_depthrenderbuffer);
|
||||||
|
// glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
|
||||||
|
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthrenderbuffer);
|
||||||
|
|
||||||
|
switch (m_renderTextureType)
|
||||||
|
{
|
||||||
|
case RENDERTEXTURE_COLOR:
|
||||||
|
{
|
||||||
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureId, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RENDERTEXTURE_DEPTH:
|
||||||
|
{
|
||||||
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, textureId, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
b3Assert(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLRenderToTexture::enable()
|
||||||
|
{
|
||||||
|
bool status = false;
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_framebufferName);
|
||||||
|
|
||||||
|
|
||||||
|
switch (m_renderTextureType)
|
||||||
|
{
|
||||||
|
case RENDERTEXTURE_COLOR:
|
||||||
|
{
|
||||||
|
// Set the list of draw buffers.
|
||||||
|
GLenum drawBuffers[2] = {GL_COLOR_ATTACHMENT0,0};
|
||||||
|
glDrawBuffers(1, drawBuffers);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RENDERTEXTURE_DEPTH:
|
||||||
|
{
|
||||||
|
//Intel OpenGL driver crashes when using GL_NONE for glDrawBuffer on Linux, so use a workaround
|
||||||
|
if (gIntelLinuxglDrawBufferWorkaround)
|
||||||
|
{
|
||||||
|
GLenum drawBuffers[2] = { GL_COLOR_ATTACHMENT0,0};
|
||||||
|
glDrawBuffers(1, drawBuffers);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
glDrawBuffer(GL_NONE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
b3Assert(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Always check that our framebuffer is ok
|
||||||
|
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
{
|
||||||
|
status = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLRenderToTexture::disable()
|
||||||
|
{
|
||||||
|
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
GLRenderToTexture::~GLRenderToTexture()
|
||||||
|
{
|
||||||
|
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
|
||||||
|
|
||||||
|
if (m_depthrenderbuffer)
|
||||||
|
{
|
||||||
|
glDeleteRenderbuffers(1,&m_depthrenderbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( m_framebufferName)
|
||||||
|
{
|
||||||
|
glDeleteFramebuffers(1, &m_framebufferName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
32
examples/OpenGLWindow/GLRenderToTexture.h
Normal file
32
examples/OpenGLWindow/GLRenderToTexture.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
#ifndef GL_RENDER_TO_TEXTURE_H
|
||||||
|
#define GL_RENDER_TO_TEXTURE_H
|
||||||
|
|
||||||
|
///See http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/
|
||||||
|
#include "OpenGLInclude.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RENDERTEXTURE_COLOR=1,
|
||||||
|
RENDERTEXTURE_DEPTH,
|
||||||
|
};
|
||||||
|
struct GLRenderToTexture
|
||||||
|
{
|
||||||
|
GLuint m_framebufferName;
|
||||||
|
GLuint m_depthrenderbuffer;
|
||||||
|
bool m_initialized;
|
||||||
|
int m_renderTextureType;
|
||||||
|
public:
|
||||||
|
GLRenderToTexture();
|
||||||
|
|
||||||
|
void init(int width, int height, GLuint textureId, int renderTextureType=RENDERTEXTURE_COLOR);
|
||||||
|
bool enable();
|
||||||
|
void disable();
|
||||||
|
|
||||||
|
virtual ~GLRenderToTexture();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GL_RENDER_TO_TEXTURE_H
|
||||||
|
|
||||||
393
examples/OpenGLWindow/GwenOpenGL3CoreRenderer.h
Normal file
393
examples/OpenGLWindow/GwenOpenGL3CoreRenderer.h
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
|
||||||
|
#ifndef __GWEN_OPENGL3_CORE_RENDERER_H
|
||||||
|
#define __GWEN_OPENGL3_CORE_RENDERER_H
|
||||||
|
|
||||||
|
#include "Gwen/Gwen.h"
|
||||||
|
#include "Gwen/BaseRender.h"
|
||||||
|
#include "GLPrimitiveRenderer.h"
|
||||||
|
#include "../OpenGLWindow/OpenGLInclude.h"
|
||||||
|
|
||||||
|
struct sth_stash;
|
||||||
|
#include "fontstash.h"
|
||||||
|
#include "Gwen/Texture.h"
|
||||||
|
|
||||||
|
#include "TwFonts.h"
|
||||||
|
static float extraSpacing = 0.;//6f;
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void MyClamp(T& a, const T& lb, const T& ub)
|
||||||
|
{
|
||||||
|
if (a < lb)
|
||||||
|
{
|
||||||
|
a = lb;
|
||||||
|
}
|
||||||
|
else if (ub < a)
|
||||||
|
{
|
||||||
|
a = ub;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GLuint BindFont(const CTexFont *_Font)
|
||||||
|
{
|
||||||
|
GLuint TexID = 0;
|
||||||
|
glGenTextures(1, &TexID);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, TexID);
|
||||||
|
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||||
|
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
|
||||||
|
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_RED, GL_UNSIGNED_BYTE, _Font->m_TexBytes);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
return TexID;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyTextureLoader
|
||||||
|
{
|
||||||
|
virtual ~MyTextureLoader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual void LoadTexture( Gwen::Texture* pTexture ) = 0;
|
||||||
|
virtual void FreeTexture( Gwen::Texture* pTexture )=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GwenOpenGL3CoreRenderer : public Gwen::Renderer::Base
|
||||||
|
{
|
||||||
|
GLPrimitiveRenderer* m_primitiveRenderer;
|
||||||
|
float m_currentColor[4];
|
||||||
|
float m_yOffset;
|
||||||
|
sth_stash* m_font;
|
||||||
|
float m_screenWidth;
|
||||||
|
float m_screenHeight;
|
||||||
|
float m_fontScaling;
|
||||||
|
float m_retinaScale;
|
||||||
|
bool m_useTrueTypeFont;
|
||||||
|
const CTexFont* m_currentFont;
|
||||||
|
|
||||||
|
GLuint m_fontTextureId;
|
||||||
|
MyTextureLoader* m_textureLoader;
|
||||||
|
public:
|
||||||
|
GwenOpenGL3CoreRenderer (GLPrimitiveRenderer* primRender, sth_stash* font,float screenWidth, float screenHeight, float retinaScale, MyTextureLoader* loader=0)
|
||||||
|
:m_primitiveRenderer(primRender),
|
||||||
|
m_font(font),
|
||||||
|
m_screenWidth(screenWidth),
|
||||||
|
m_screenHeight(screenHeight),
|
||||||
|
m_retinaScale(retinaScale),
|
||||||
|
m_useTrueTypeFont(false),
|
||||||
|
m_textureLoader(loader)
|
||||||
|
{
|
||||||
|
///only enable true type fonts on Macbook Retina, it looks gorgeous
|
||||||
|
if (retinaScale==2.0f)
|
||||||
|
{
|
||||||
|
m_useTrueTypeFont = true;
|
||||||
|
}
|
||||||
|
m_currentColor[0] = 1;
|
||||||
|
m_currentColor[1] = 1;
|
||||||
|
m_currentColor[2] = 1;
|
||||||
|
m_currentColor[3] = 1;
|
||||||
|
|
||||||
|
m_fontScaling = 16.f*m_retinaScale;
|
||||||
|
|
||||||
|
TwGenerateDefaultFonts();
|
||||||
|
|
||||||
|
m_currentFont = g_DefaultNormalFont;
|
||||||
|
//m_currentFont = g_DefaultNormalFontAA;
|
||||||
|
|
||||||
|
//m_currentFont = g_DefaultLargeFont;
|
||||||
|
m_fontTextureId = BindFont(m_currentFont);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~GwenOpenGL3CoreRenderer()
|
||||||
|
{
|
||||||
|
TwDeleteDefaultFonts();
|
||||||
|
}
|
||||||
|
virtual void Resize(int width, int height)
|
||||||
|
{
|
||||||
|
m_screenWidth = width;
|
||||||
|
m_screenHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Begin()
|
||||||
|
{
|
||||||
|
m_yOffset=0;
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
//glColor4ub(255,0,0,255);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// saveOpenGLState(width,height);//m_glutScreenWidth,m_glutScreenHeight);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
}
|
||||||
|
virtual void End()
|
||||||
|
{
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void StartClip()
|
||||||
|
{
|
||||||
|
if (m_useTrueTypeFont)
|
||||||
|
sth_flush_draw(m_font);
|
||||||
|
Gwen::Rect rect = ClipRegion();
|
||||||
|
|
||||||
|
// OpenGL's coords are from the bottom left
|
||||||
|
// so we need to translate them here.
|
||||||
|
{
|
||||||
|
GLint view[4];
|
||||||
|
glGetIntegerv( GL_VIEWPORT, &view[0] );
|
||||||
|
rect.y = view[3]/m_retinaScale - (rect.y + rect.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
glScissor( m_retinaScale * rect.x * Scale(), m_retinaScale * rect.y * Scale(), m_retinaScale * rect.w * Scale(), m_retinaScale * rect.h * Scale() );
|
||||||
|
glEnable( GL_SCISSOR_TEST );
|
||||||
|
//glDisable( GL_SCISSOR_TEST );
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void EndClip()
|
||||||
|
{
|
||||||
|
if (m_useTrueTypeFont)
|
||||||
|
sth_flush_draw(m_font);
|
||||||
|
glDisable( GL_SCISSOR_TEST );
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void SetDrawColor( Gwen::Color color )
|
||||||
|
{
|
||||||
|
m_currentColor[0] = color.r/256.f;
|
||||||
|
m_currentColor[1] = color.g/256.f;
|
||||||
|
m_currentColor[2] = color.b/256.f;
|
||||||
|
m_currentColor[3] = color.a/256.f;
|
||||||
|
|
||||||
|
}
|
||||||
|
virtual void DrawFilledRect( Gwen::Rect rect )
|
||||||
|
{
|
||||||
|
Translate( rect );
|
||||||
|
|
||||||
|
m_primitiveRenderer->drawRect(rect.x, rect.y+m_yOffset, rect.x+rect.w, rect.y+rect.h+m_yOffset, m_currentColor);
|
||||||
|
// m_yOffset+=rect.h+10;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderText( Gwen::Font* pFont, Gwen::Point rasterPos, const Gwen::UnicodeString& text )
|
||||||
|
{
|
||||||
|
|
||||||
|
Gwen::String str = Gwen::Utility::UnicodeToString(text);
|
||||||
|
const char* unicodeText = (const char*)str.c_str();
|
||||||
|
|
||||||
|
Gwen::Rect r;
|
||||||
|
r.x = rasterPos.x;
|
||||||
|
r.y = rasterPos.y;
|
||||||
|
r.w = 0;
|
||||||
|
r.h = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//printf("str = %s\n",unicodeText);
|
||||||
|
//int xpos=0;
|
||||||
|
//int ypos=0;
|
||||||
|
float dx;
|
||||||
|
|
||||||
|
int measureOnly=0;
|
||||||
|
|
||||||
|
if (m_useTrueTypeFont)
|
||||||
|
{
|
||||||
|
|
||||||
|
float yoffset = 0.f;
|
||||||
|
if (m_retinaScale==2.0f)
|
||||||
|
{
|
||||||
|
yoffset = -12;
|
||||||
|
}
|
||||||
|
Translate(r);
|
||||||
|
sth_draw_text(m_font,
|
||||||
|
1,m_fontScaling,
|
||||||
|
r.x,r.y+yoffset,
|
||||||
|
unicodeText,&dx, m_screenWidth,m_screenHeight,measureOnly,m_retinaScale);
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//float width = 0.f;
|
||||||
|
int pos=0;
|
||||||
|
//float color[]={0.2f,0.2,0.2f,1.f};
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D,m_fontTextureId);
|
||||||
|
float width = r.x;
|
||||||
|
while (unicodeText[pos])
|
||||||
|
{
|
||||||
|
int c = unicodeText[pos];
|
||||||
|
r.h = m_currentFont->m_CharHeight;
|
||||||
|
r.w = m_currentFont->m_CharWidth[c]+extraSpacing;
|
||||||
|
Gwen::Rect rect = r;
|
||||||
|
Translate( rect );
|
||||||
|
|
||||||
|
m_primitiveRenderer->drawTexturedRect(rect.x, rect.y+m_yOffset, rect.x+rect.w, rect.y+rect.h+m_yOffset, m_currentColor,m_currentFont->m_CharU0[c],m_currentFont->m_CharV0[c],m_currentFont->m_CharU1[c],m_currentFont->m_CharV1[c]);
|
||||||
|
|
||||||
|
//DrawTexturedRect(0,r,m_currentFont->m_CharU0[c],m_currentFont->m_CharV0[c],m_currentFont->m_CharU1[c],m_currentFont->m_CharV1[c]);
|
||||||
|
// DrawFilledRect(r);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
width += r.w;
|
||||||
|
r.x = width;
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Gwen::Point MeasureText( Gwen::Font* pFont, const Gwen::UnicodeString& text )
|
||||||
|
{
|
||||||
|
Gwen::String str = Gwen::Utility::UnicodeToString(text);
|
||||||
|
const char* unicodeText = (const char*)str.c_str();
|
||||||
|
|
||||||
|
// printf("str = %s\n",unicodeText);
|
||||||
|
int xpos=0;
|
||||||
|
int ypos=0;
|
||||||
|
|
||||||
|
|
||||||
|
int measureOnly=1;
|
||||||
|
float dx=0;
|
||||||
|
if (m_useTrueTypeFont)
|
||||||
|
{
|
||||||
|
sth_draw_text(m_font,
|
||||||
|
1,m_fontScaling,
|
||||||
|
xpos,ypos,
|
||||||
|
unicodeText,&dx, m_screenWidth,m_screenHeight,measureOnly);
|
||||||
|
|
||||||
|
Gwen::Point pt;
|
||||||
|
|
||||||
|
if (m_retinaScale==2.0f)
|
||||||
|
{
|
||||||
|
pt.x = dx*Scale()/2.f;
|
||||||
|
pt.y = m_fontScaling/2*Scale()+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pt.x = dx*Scale();
|
||||||
|
pt.y = m_fontScaling*Scale()+1;
|
||||||
|
}
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float width = 0.f;
|
||||||
|
int pos=0;
|
||||||
|
while (unicodeText[pos])
|
||||||
|
{
|
||||||
|
width += m_currentFont->m_CharWidth[(int)unicodeText[pos]]+extraSpacing;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
Gwen::Point pt;
|
||||||
|
int fontHeight = m_currentFont->m_CharHeight;
|
||||||
|
|
||||||
|
|
||||||
|
pt.x = width*Scale();
|
||||||
|
pt.y = (fontHeight+2) * Scale();
|
||||||
|
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Gwen::Renderer::Base::MeasureText(pFont,text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void LoadTexture( Gwen::Texture* pTexture )
|
||||||
|
{
|
||||||
|
if (m_textureLoader)
|
||||||
|
m_textureLoader->LoadTexture(pTexture);
|
||||||
|
}
|
||||||
|
virtual void FreeTexture( Gwen::Texture* pTexture )
|
||||||
|
{
|
||||||
|
if (m_textureLoader)
|
||||||
|
m_textureLoader->FreeTexture(pTexture);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void DrawTexturedRect( Gwen::Texture* pTexture, Gwen::Rect rect, float u1=0.0f, float v1=0.0f, float u2=1.0f, float v2=1.0f )
|
||||||
|
{
|
||||||
|
|
||||||
|
Translate( rect );
|
||||||
|
|
||||||
|
//float eraseColor[4] = {0,0,0,0};
|
||||||
|
//m_primitiveRenderer->drawRect(rect.x, rect.y+m_yOffset, rect.x+rect.w, rect.y+rect.h+m_yOffset, eraseColor);
|
||||||
|
|
||||||
|
GLint texHandle = (GLint) pTexture->m_intData;
|
||||||
|
//if (!texHandle)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,texHandle);
|
||||||
|
// glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
/* bool useFiltering = true;
|
||||||
|
if (useFiltering)
|
||||||
|
{
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
*/
|
||||||
|
|
||||||
|
//glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE );
|
||||||
|
static float add=0.0;
|
||||||
|
//add+=1./512.;//0.01;
|
||||||
|
float color[4]={1,1,1,1};
|
||||||
|
|
||||||
|
m_primitiveRenderer->drawTexturedRect(rect.x, rect.y+m_yOffset, rect.x+rect.w, rect.y+rect.h+m_yOffset, color,0+add,0,1+add,1,true);
|
||||||
|
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif //__GWEN_OPENGL3_CORE_RENDERER_H
|
||||||
111
examples/OpenGLWindow/LoadShader.cpp
Normal file
111
examples/OpenGLWindow/LoadShader.cpp
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
#include "LoadShader.h"
|
||||||
|
#include "OpenGLInclude.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Load the shader from the source text
|
||||||
|
void gltLoadShaderSrc(const char *szShaderSrc, GLuint shader)
|
||||||
|
{
|
||||||
|
GLchar *fsStringPtr[1];
|
||||||
|
|
||||||
|
fsStringPtr[0] = (GLchar *)szShaderSrc;
|
||||||
|
glShaderSource(shader, 1, (const GLchar **)fsStringPtr, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLuint gltLoadShaderPair(const char *szVertexProg, const char *szFragmentProg)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
// Temporary Shader objects
|
||||||
|
GLuint hVertexShader;
|
||||||
|
GLuint hFragmentShader;
|
||||||
|
GLuint hReturn = 0;
|
||||||
|
GLint testVal;
|
||||||
|
|
||||||
|
// Create shader objects
|
||||||
|
hVertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
gltLoadShaderSrc(szVertexProg, hVertexShader);
|
||||||
|
gltLoadShaderSrc(szFragmentProg, hFragmentShader);
|
||||||
|
|
||||||
|
// Compile them
|
||||||
|
glCompileShader(hVertexShader);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &testVal);
|
||||||
|
if(testVal == GL_FALSE)
|
||||||
|
{
|
||||||
|
char temp[256] = "";
|
||||||
|
glGetShaderInfoLog( hVertexShader, 256, NULL, temp);
|
||||||
|
fprintf( stderr, "Compile failed:\n%s\n", temp);
|
||||||
|
assert(0);
|
||||||
|
return 0;
|
||||||
|
glDeleteShader(hVertexShader);
|
||||||
|
glDeleteShader(hFragmentShader);
|
||||||
|
return (GLuint)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glCompileShader(hFragmentShader);
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
glGetShaderiv(hFragmentShader, GL_COMPILE_STATUS, &testVal);
|
||||||
|
if(testVal == GL_FALSE)
|
||||||
|
{
|
||||||
|
char temp[256] = "";
|
||||||
|
glGetShaderInfoLog( hFragmentShader, 256, NULL, temp);
|
||||||
|
fprintf( stderr, "Compile failed:\n%s\n", temp);
|
||||||
|
assert(0);
|
||||||
|
exit(0);
|
||||||
|
glDeleteShader(hVertexShader);
|
||||||
|
glDeleteShader(hFragmentShader);
|
||||||
|
return (GLuint)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(glGetError()==GL_NO_ERROR);
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Link them - assuming it works...
|
||||||
|
hReturn = glCreateProgram();
|
||||||
|
glAttachShader(hReturn, hVertexShader);
|
||||||
|
glAttachShader(hReturn, hFragmentShader);
|
||||||
|
|
||||||
|
glLinkProgram(hReturn);
|
||||||
|
|
||||||
|
// These are no longer needed
|
||||||
|
glDeleteShader(hVertexShader);
|
||||||
|
glDeleteShader(hFragmentShader);
|
||||||
|
|
||||||
|
// Make sure link worked too
|
||||||
|
glGetProgramiv(hReturn, GL_LINK_STATUS, &testVal);
|
||||||
|
if(testVal == GL_FALSE)
|
||||||
|
{
|
||||||
|
GLsizei maxLen = 4096;
|
||||||
|
GLchar infoLog[4096];
|
||||||
|
GLsizei actualLen;
|
||||||
|
|
||||||
|
glGetProgramInfoLog( hReturn,
|
||||||
|
maxLen,
|
||||||
|
&actualLen,
|
||||||
|
infoLog);
|
||||||
|
|
||||||
|
printf("Warning/Error in GLSL shader:\n");
|
||||||
|
printf("%s\n",infoLog);
|
||||||
|
glDeleteProgram(hReturn);
|
||||||
|
return (GLuint)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
18
examples/OpenGLWindow/LoadShader.h
Normal file
18
examples/OpenGLWindow/LoadShader.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _LOAD_SHADER_H
|
||||||
|
#define _LOAD_SHADER_H
|
||||||
|
|
||||||
|
#include "OpenGLInclude.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif//__cplusplus
|
||||||
|
|
||||||
|
GLuint gltLoadShaderPair(const char *szVertexProg, const char *szFragmentProg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif//__cplusplus
|
||||||
|
|
||||||
|
#endif//_LOAD_SHADER_H
|
||||||
|
|
||||||
|
|
||||||
105
examples/OpenGLWindow/MacOpenGLWindow.h
Normal file
105
examples/OpenGLWindow/MacOpenGLWindow.h
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#ifndef MAC_OPENGL_WINDOW_H
|
||||||
|
#define MAC_OPENGL_WINDOW_H
|
||||||
|
|
||||||
|
#include "b3gWindowInterface.h"
|
||||||
|
|
||||||
|
#define b3gDefaultOpenGLWindow MacOpenGLWindow
|
||||||
|
|
||||||
|
class MacOpenGLWindow : public b3gWindowInterface
|
||||||
|
{
|
||||||
|
struct MacOpenGLWindowInternalData* m_internalData;
|
||||||
|
float m_mouseX;
|
||||||
|
float m_mouseY;
|
||||||
|
int m_modifierFlags;
|
||||||
|
|
||||||
|
b3MouseButtonCallback m_mouseButtonCallback;
|
||||||
|
b3MouseMoveCallback m_mouseMoveCallback;
|
||||||
|
b3WheelCallback m_wheelCallback;
|
||||||
|
b3KeyboardCallback m_keyboardCallback;
|
||||||
|
b3RenderCallback m_renderCallback;
|
||||||
|
|
||||||
|
float m_retinaScaleFactor;
|
||||||
|
public:
|
||||||
|
|
||||||
|
MacOpenGLWindow();
|
||||||
|
virtual ~MacOpenGLWindow();
|
||||||
|
|
||||||
|
void init(int width, int height, const char* windowTitle);
|
||||||
|
|
||||||
|
void closeWindow();
|
||||||
|
|
||||||
|
void startRendering();
|
||||||
|
|
||||||
|
void endRendering();//swap buffers
|
||||||
|
|
||||||
|
virtual bool requestedExit() const;
|
||||||
|
|
||||||
|
virtual void setRequestExit();
|
||||||
|
|
||||||
|
void getMouseCoordinates(int& x, int& y);
|
||||||
|
|
||||||
|
void runMainLoop();
|
||||||
|
|
||||||
|
void setMouseButtonCallback(b3MouseButtonCallback mouseCallback)
|
||||||
|
{
|
||||||
|
m_mouseButtonCallback = mouseCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMouseMoveCallback(b3MouseMoveCallback mouseCallback)
|
||||||
|
{
|
||||||
|
m_mouseMoveCallback = mouseCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setResizeCallback(b3ResizeCallback resizeCallback);
|
||||||
|
|
||||||
|
void setKeyboardCallback( b3KeyboardCallback keyboardCallback)
|
||||||
|
{
|
||||||
|
m_keyboardCallback = keyboardCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual b3MouseMoveCallback getMouseMoveCallback()
|
||||||
|
{
|
||||||
|
return m_mouseMoveCallback;
|
||||||
|
}
|
||||||
|
virtual b3MouseButtonCallback getMouseButtonCallback()
|
||||||
|
{
|
||||||
|
return m_mouseButtonCallback;
|
||||||
|
}
|
||||||
|
virtual b3ResizeCallback getResizeCallback();
|
||||||
|
virtual b3WheelCallback getWheelCallback()
|
||||||
|
{
|
||||||
|
return m_wheelCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
b3KeyboardCallback getKeyboardCallback()
|
||||||
|
{
|
||||||
|
return m_keyboardCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setWheelCallback (b3WheelCallback wheelCallback)
|
||||||
|
{
|
||||||
|
m_wheelCallback = wheelCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getRetinaScale() const
|
||||||
|
{
|
||||||
|
return m_retinaScaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void createWindow(const b3gWindowConstructionInfo& ci);
|
||||||
|
|
||||||
|
virtual float getTimeInSeconds();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setRenderCallback( b3RenderCallback renderCallback);
|
||||||
|
|
||||||
|
virtual void setWindowTitle(const char* title);
|
||||||
|
|
||||||
|
int fileOpenDialog(char* filename, int maxNameLength);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
1079
examples/OpenGLWindow/MacOpenGLWindow.mm
Normal file
1079
examples/OpenGLWindow/MacOpenGLWindow.mm
Normal file
File diff suppressed because it is too large
Load Diff
55
examples/OpenGLWindow/OpenGL2Include.h
Normal file
55
examples/OpenGLWindow/OpenGL2Include.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
//Originally written by Erwin Coumans
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __OPENGL_INCLUDE_H
|
||||||
|
#define __OPENGL_INCLUDE_H
|
||||||
|
|
||||||
|
|
||||||
|
//think different
|
||||||
|
#if defined(__APPLE__) && !defined (VMDMESA)
|
||||||
|
#include <OpenGL/OpenGL.h>
|
||||||
|
#include <OpenGL/gl.h>
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "GL/glew.h"
|
||||||
|
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
#include <windows.h>
|
||||||
|
//#include <GL/gl.h>
|
||||||
|
//#include <GL/glu.h>
|
||||||
|
#else
|
||||||
|
//#include <GL/gl.h>
|
||||||
|
//#include <GL/glu.h>
|
||||||
|
#endif //_WINDOWS
|
||||||
|
#endif //APPLE
|
||||||
|
|
||||||
|
//disable glGetError
|
||||||
|
//#undef glGetError
|
||||||
|
//#define glGetError MyGetError
|
||||||
|
//
|
||||||
|
//GLenum inline MyGetError()
|
||||||
|
//{
|
||||||
|
// return 0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
///on Linux only glDrawElementsInstancedARB is defined?!?
|
||||||
|
//#ifdef __linux
|
||||||
|
//#define glDrawElementsInstanced glDrawElementsInstancedARB
|
||||||
|
//
|
||||||
|
//#endif //__linux
|
||||||
|
|
||||||
|
#endif //__OPENGL_INCLUDE_H
|
||||||
|
|
||||||
62
examples/OpenGLWindow/OpenGLInclude.h
Normal file
62
examples/OpenGLWindow/OpenGLInclude.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
//Originally written by Erwin Coumans
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __OPENGL_INCLUDE_H
|
||||||
|
#define __OPENGL_INCLUDE_H
|
||||||
|
|
||||||
|
|
||||||
|
//think different
|
||||||
|
#if defined(__APPLE__) && !defined (VMDMESA)
|
||||||
|
#include <OpenGL/OpenGL.h>
|
||||||
|
//#include <OpenGL/gl.h>
|
||||||
|
//#include <OpenGL/glu.h>
|
||||||
|
//#import <Cocoa/Cocoa.h>
|
||||||
|
#ifdef USE_OPENGL2
|
||||||
|
#include <OpenGL/gl.h>
|
||||||
|
#else
|
||||||
|
#include <OpenGL/gl3.h>
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "GL/glew.h"
|
||||||
|
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
#include <windows.h>
|
||||||
|
//#include <GL/gl.h>
|
||||||
|
//#include <GL/glu.h>
|
||||||
|
#else
|
||||||
|
//#include <GL/gl.h>
|
||||||
|
//#include <GL/glu.h>
|
||||||
|
#endif //_WINDOWS
|
||||||
|
#endif //APPLE
|
||||||
|
|
||||||
|
//disable glGetError
|
||||||
|
//#undef glGetError
|
||||||
|
//#define glGetError MyGetError
|
||||||
|
//
|
||||||
|
//GLenum inline MyGetError()
|
||||||
|
//{
|
||||||
|
// return 0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
///on Linux only glDrawElementsInstancedARB is defined?!?
|
||||||
|
//#ifdef __linux
|
||||||
|
//#define glDrawElementsInstanced glDrawElementsInstancedARB
|
||||||
|
//
|
||||||
|
//#endif //__linux
|
||||||
|
|
||||||
|
#endif //__OPENGL_INCLUDE_H
|
||||||
|
|
||||||
21738
examples/OpenGLWindow/OpenSans.cpp
Normal file
21738
examples/OpenGLWindow/OpenSans.cpp
Normal file
File diff suppressed because it is too large
Load Diff
BIN
examples/OpenGLWindow/OpenSans.ttf
Normal file
BIN
examples/OpenGLWindow/OpenSans.ttf
Normal file
Binary file not shown.
@@ -0,0 +1,10 @@
|
|||||||
|
#version 330
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
|
||||||
|
layout(location = 0) out float fragmentdepth;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
fragmentdepth = gl_FragCoord.z;
|
||||||
|
}
|
||||||
10
examples/OpenGLWindow/Shaders/createShadowMapInstancingPS.h
Normal file
10
examples/OpenGLWindow/Shaders/createShadowMapInstancingPS.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||||
|
static const char* createShadowMapInstancingFragmentShader= \
|
||||||
|
"#version 330\n"
|
||||||
|
"precision highp float;\n"
|
||||||
|
"layout(location = 0) out float fragmentdepth;\n"
|
||||||
|
"void main(void)\n"
|
||||||
|
"{\n"
|
||||||
|
" fragmentdepth = gl_FragCoord.z;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#version 330
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
|
||||||
|
layout (location = 0) in vec4 position;
|
||||||
|
layout (location = 1) in vec4 instance_position;
|
||||||
|
layout (location = 2) in vec4 instance_quaternion;
|
||||||
|
layout (location = 3) in vec2 uvcoords;
|
||||||
|
layout (location = 4) in vec3 vertexnormal;
|
||||||
|
layout (location = 5) in vec4 instance_color;
|
||||||
|
layout (location = 6) in vec3 instance_scale;
|
||||||
|
|
||||||
|
|
||||||
|
uniform mat4 depthMVP;
|
||||||
|
|
||||||
|
|
||||||
|
vec4 quatMul ( in vec4 q1, in vec4 q2 )
|
||||||
|
{
|
||||||
|
vec3 im = q1.w * q2.xyz + q1.xyz * q2.w + cross ( q1.xyz, q2.xyz );
|
||||||
|
vec4 dt = q1 * q2;
|
||||||
|
float re = dot ( dt, vec4 ( -1.0, -1.0, -1.0, 1.0 ) );
|
||||||
|
return vec4 ( im, re );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 quatFromAxisAngle(vec4 axis, in float angle)
|
||||||
|
{
|
||||||
|
float cah = cos(angle*0.5);
|
||||||
|
float sah = sin(angle*0.5);
|
||||||
|
float d = inversesqrt(dot(axis,axis));
|
||||||
|
vec4 q = vec4(axis.x*sah*d,axis.y*sah*d,axis.z*sah*d,cah);
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// vector rotation via quaternion
|
||||||
|
//
|
||||||
|
vec4 quatRotate3 ( in vec3 p, in vec4 q )
|
||||||
|
{
|
||||||
|
vec4 temp = quatMul ( q, vec4 ( p, 0.0 ) );
|
||||||
|
return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );
|
||||||
|
}
|
||||||
|
vec4 quatRotate ( in vec4 p, in vec4 q )
|
||||||
|
{
|
||||||
|
vec4 temp = quatMul ( q, p );
|
||||||
|
return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec4 q = instance_quaternion;
|
||||||
|
vec4 localcoord = quatRotate3( position.xyz*instance_scale,q);
|
||||||
|
vec4 vertexPos = depthMVP * vec4( (instance_position+localcoord).xyz,1);
|
||||||
|
gl_Position = vertexPos;
|
||||||
|
}
|
||||||
|
|
||||||
48
examples/OpenGLWindow/Shaders/createShadowMapInstancingVS.h
Normal file
48
examples/OpenGLWindow/Shaders/createShadowMapInstancingVS.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||||
|
static const char* createShadowMapInstancingVertexShader= \
|
||||||
|
"#version 330\n"
|
||||||
|
"precision highp float;\n"
|
||||||
|
"layout (location = 0) in vec4 position;\n"
|
||||||
|
"layout (location = 1) in vec4 instance_position;\n"
|
||||||
|
"layout (location = 2) in vec4 instance_quaternion;\n"
|
||||||
|
"layout (location = 3) in vec2 uvcoords;\n"
|
||||||
|
"layout (location = 4) in vec3 vertexnormal;\n"
|
||||||
|
"layout (location = 5) in vec4 instance_color;\n"
|
||||||
|
"layout (location = 6) in vec3 instance_scale;\n"
|
||||||
|
"uniform mat4 depthMVP;\n"
|
||||||
|
"vec4 quatMul ( in vec4 q1, in vec4 q2 )\n"
|
||||||
|
"{\n"
|
||||||
|
" vec3 im = q1.w * q2.xyz + q1.xyz * q2.w + cross ( q1.xyz, q2.xyz );\n"
|
||||||
|
" vec4 dt = q1 * q2;\n"
|
||||||
|
" float re = dot ( dt, vec4 ( -1.0, -1.0, -1.0, 1.0 ) );\n"
|
||||||
|
" return vec4 ( im, re );\n"
|
||||||
|
"}\n"
|
||||||
|
"vec4 quatFromAxisAngle(vec4 axis, in float angle)\n"
|
||||||
|
"{\n"
|
||||||
|
" float cah = cos(angle*0.5);\n"
|
||||||
|
" float sah = sin(angle*0.5);\n"
|
||||||
|
" float d = inversesqrt(dot(axis,axis));\n"
|
||||||
|
" vec4 q = vec4(axis.x*sah*d,axis.y*sah*d,axis.z*sah*d,cah);\n"
|
||||||
|
" return q;\n"
|
||||||
|
"}\n"
|
||||||
|
"//\n"
|
||||||
|
"// vector rotation via quaternion\n"
|
||||||
|
"//\n"
|
||||||
|
"vec4 quatRotate3 ( in vec3 p, in vec4 q )\n"
|
||||||
|
"{\n"
|
||||||
|
" vec4 temp = quatMul ( q, vec4 ( p, 0.0 ) );\n"
|
||||||
|
" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n"
|
||||||
|
"}\n"
|
||||||
|
"vec4 quatRotate ( in vec4 p, in vec4 q )\n"
|
||||||
|
"{\n"
|
||||||
|
" vec4 temp = quatMul ( q, p );\n"
|
||||||
|
" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n"
|
||||||
|
"}\n"
|
||||||
|
"void main(void)\n"
|
||||||
|
"{\n"
|
||||||
|
" vec4 q = instance_quaternion;\n"
|
||||||
|
" vec4 localcoord = quatRotate3( position.xyz*instance_scale,q);\n"
|
||||||
|
" vec4 vertexPos = depthMVP * vec4( (instance_position+localcoord).xyz,1);\n"
|
||||||
|
" gl_Position = vertexPos;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
36
examples/OpenGLWindow/Shaders/instancingPS.glsl
Normal file
36
examples/OpenGLWindow/Shaders/instancingPS.glsl
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#version 330
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
in Fragment
|
||||||
|
{
|
||||||
|
vec4 color;
|
||||||
|
} fragment;
|
||||||
|
|
||||||
|
in Vert
|
||||||
|
{
|
||||||
|
vec2 texcoord;
|
||||||
|
} vert;
|
||||||
|
|
||||||
|
uniform sampler2D Diffuse;
|
||||||
|
in vec3 lightDir,normal,ambient;
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main_textured(void)
|
||||||
|
{
|
||||||
|
color = vec4(0.1,0.2,0.3,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec4 texel = fragment.color*texture(Diffuse,vert.texcoord);//fragment.color;
|
||||||
|
vec3 ct,cf;
|
||||||
|
float intensity,at,af;
|
||||||
|
intensity = max(dot(lightDir,normalize(normal)),0);
|
||||||
|
cf = intensity*vec3(1.0,1.0,1.0)+ambient;
|
||||||
|
af = 1.0;
|
||||||
|
|
||||||
|
ct = texel.rgb;
|
||||||
|
at = texel.a;
|
||||||
|
|
||||||
|
color = vec4(ct * cf, at * af);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user