From da948a072901272651ef9ab0612ce773465a2790 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 19 Apr 2016 18:21:53 -0700 Subject: [PATCH 01/50] fix text rendering (uninitialized uniforms) --- examples/OpenGLWindow/opengl_fontstashcallbacks.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/examples/OpenGLWindow/opengl_fontstashcallbacks.cpp b/examples/OpenGLWindow/opengl_fontstashcallbacks.cpp index be104f2b6..eceeb6bfb 100644 --- a/examples/OpenGLWindow/opengl_fontstashcallbacks.cpp +++ b/examples/OpenGLWindow/opengl_fontstashcallbacks.cpp @@ -44,7 +44,17 @@ void InternalOpenGL2RenderCallbacks::display2() PrimInternalData* data = getData(); glUseProgram(data->m_shaderProg); + + float identity[16]={1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1}; + glUniformMatrix4fv(data->m_viewmatUniform, 1, false, identity); + glUniformMatrix4fv(data->m_projMatUniform, 1, false, identity); + + glBindBuffer(GL_ARRAY_BUFFER, s_vertexBuffer); + glBindVertexArray(s_vertexArrayObject); assert(glGetError()==GL_NO_ERROR); From 4e61f0cab9eef0e42a31fc830f68a74748db81ac Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 20 Apr 2016 12:55:21 -0700 Subject: [PATCH 02/50] add function to CommonRenderInterface to update/activate a texture add example how to render a texture 2d quad in SimpleOpenGL3 --- .../CommonInterfaces/CommonRenderInterface.h | 6 ++- .../OpenGLWindow/GLInstancingRenderer.cpp | 54 ++++++++++++++++--- examples/OpenGLWindow/GLInstancingRenderer.h | 3 ++ .../opengl_fontstashcallbacks.cpp | 10 ---- examples/SimpleOpenGL3/main.cpp | 46 +++++++++++++--- 5 files changed, 93 insertions(+), 26 deletions(-) diff --git a/examples/CommonInterfaces/CommonRenderInterface.h b/examples/CommonInterfaces/CommonRenderInterface.h index a3d1d0f8b..e1d6170ef 100644 --- a/examples/CommonInterfaces/CommonRenderInterface.h +++ b/examples/CommonInterfaces/CommonRenderInterface.h @@ -43,7 +43,11 @@ struct CommonRenderInterface 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 int registerTexture(const unsigned char* texels, int width, int height)=0; + + virtual int registerTexture(const unsigned char* texels, int width, int height)=0; + virtual void updateTexture(int textureIndex, const unsigned char* texels)=0; + virtual void activateTexture(int textureIndex)=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; diff --git a/examples/OpenGLWindow/GLInstancingRenderer.cpp b/examples/OpenGLWindow/GLInstancingRenderer.cpp index 8d2bac643..65c054e5c 100644 --- a/examples/OpenGLWindow/GLInstancingRenderer.cpp +++ b/examples/OpenGLWindow/GLInstancingRenderer.cpp @@ -134,7 +134,12 @@ extern int gShapeIndex; - +struct InternalTextureHandle +{ + GLuint m_glTexture; + int m_width; + int m_height; +}; @@ -148,7 +153,7 @@ struct InternalDataRenderer : public GLInstanceRendererInternalData GLuint m_defaultTexturehandle; - b3AlignedObjectArray m_textureHandles; + b3AlignedObjectArray m_textureHandles; GLRenderToTexture* m_shadowMap; GLuint m_shadowTexture; @@ -518,9 +523,9 @@ int GLInstancingRenderer::registerGraphicsInstance(int shapeIndex, const float* int GLInstancingRenderer::registerTexture(const unsigned char* texels, int width, int height) { b3Assert(glGetError() ==GL_NO_ERROR); - + glActiveTexture(GL_TEXTURE0); int textureIndex = m_data->m_textureHandles.size(); - const GLubyte* image= (const GLubyte*)texels; + const GLubyte* image= (const GLubyte*)texels; GLuint textureHandle; glGenTextures(1,(GLuint*)&textureHandle); glBindTexture(GL_TEXTURE_2D,textureHandle); @@ -528,18 +533,51 @@ int GLInstancingRenderer::registerTexture(const unsigned char* texels, int width b3Assert(glGetError() ==GL_NO_ERROR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width,height,0,GL_RGB,GL_UNSIGNED_BYTE,image); - - b3Assert(glGetError() ==GL_NO_ERROR); glGenerateMipmap(GL_TEXTURE_2D); b3Assert(glGetError() ==GL_NO_ERROR); + InternalTextureHandle h; + h.m_glTexture = textureHandle; + h.m_width = width; + h.m_height = height; - m_data->m_textureHandles.push_back(textureHandle); + m_data->m_textureHandles.push_back(h); return textureIndex; } + +void GLInstancingRenderer::updateTexture(int textureIndex, const unsigned char* texels) +{ + if (textureIndex>=0) + { + glActiveTexture(GL_TEXTURE0); + b3Assert(glGetError() ==GL_NO_ERROR); + InternalTextureHandle& h = m_data->m_textureHandles[textureIndex]; + glBindTexture(GL_TEXTURE_2D,h.m_glTexture); + b3Assert(glGetError() ==GL_NO_ERROR); + const GLubyte* image= (const GLubyte*)texels; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, h.m_width,h.m_height,0,GL_RGB,GL_UNSIGNED_BYTE,image); + b3Assert(glGetError() ==GL_NO_ERROR); + glGenerateMipmap(GL_TEXTURE_2D); + b3Assert(glGetError() ==GL_NO_ERROR); + } +} + +void GLInstancingRenderer::activateTexture(int textureIndex) +{ + glActiveTexture(GL_TEXTURE0); + + if (textureIndex>=0) + { + glBindTexture(GL_TEXTURE_2D,m_data->m_textureHandles[textureIndex].m_glTexture); + } else + { + glBindTexture(GL_TEXTURE_2D,0); + } +} + void GLInstancingRenderer::updateShape(int shapeIndex, const float* vertices) { b3GraphicsInstance* gfxObj = m_graphicsInstances[shapeIndex]; @@ -559,7 +597,7 @@ int GLInstancingRenderer::registerShape(const float* vertices, int numvertices, if (textureId>=0) { - gfxObj->m_texturehandle = m_data->m_textureHandles[textureId]; + gfxObj->m_texturehandle = m_data->m_textureHandles[textureId].m_glTexture; } gfxObj->m_primitiveType = primitiveType; diff --git a/examples/OpenGLWindow/GLInstancingRenderer.h b/examples/OpenGLWindow/GLInstancingRenderer.h index abdadb9e9..34df83637 100644 --- a/examples/OpenGLWindow/GLInstancingRenderer.h +++ b/examples/OpenGLWindow/GLInstancingRenderer.h @@ -63,6 +63,9 @@ public: 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); + virtual void updateTexture(int textureIndex, const unsigned char* texels); + virtual void activateTexture(int textureIndex); + ///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); diff --git a/examples/OpenGLWindow/opengl_fontstashcallbacks.cpp b/examples/OpenGLWindow/opengl_fontstashcallbacks.cpp index eceeb6bfb..be104f2b6 100644 --- a/examples/OpenGLWindow/opengl_fontstashcallbacks.cpp +++ b/examples/OpenGLWindow/opengl_fontstashcallbacks.cpp @@ -44,17 +44,7 @@ void InternalOpenGL2RenderCallbacks::display2() PrimInternalData* data = getData(); glUseProgram(data->m_shaderProg); - - float identity[16]={1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1}; - glUniformMatrix4fv(data->m_viewmatUniform, 1, false, identity); - glUniformMatrix4fv(data->m_projMatUniform, 1, false, identity); - - glBindBuffer(GL_ARRAY_BUFFER, s_vertexBuffer); - glBindVertexArray(s_vertexArrayObject); assert(glGetError()==GL_NO_ERROR); diff --git a/examples/SimpleOpenGL3/main.cpp b/examples/SimpleOpenGL3/main.cpp index 97caf8b91..300dfa79e 100644 --- a/examples/SimpleOpenGL3/main.cpp +++ b/examples/SimpleOpenGL3/main.cpp @@ -1,10 +1,8 @@ #include "OpenGLWindow/SimpleOpenGL3App.h" - #include "Bullet3Common/b3Vector3.h" #include "Bullet3Common/b3CommandLineArgs.h" #include "assert.h" #include -#include "OpenGLWindow/OpenGLInclude.h" char* gVideoFileName = 0; char* gPngFileName = 0; @@ -16,6 +14,8 @@ static b3MouseButtonCallback sOldMouseButtonCB = 0; static b3KeyboardCallback sOldKeyboardCB = 0; //static b3RenderCallback sOldRenderCB = 0; +float gWidth = 0 ; +float gHeight = 0; void MyWheelCallback(float deltax, float deltay) { @@ -24,6 +24,9 @@ void MyWheelCallback(float deltax, float deltay) } void MyResizeCallback( float width, float height) { + gWidth = width; + gHeight = height; + if (sOldResizeCB) sOldResizeCB(width,height); } @@ -59,6 +62,7 @@ int main(int argc, char* argv[]) SimpleOpenGL3App* app = new SimpleOpenGL3App("SimpleOpenGL3App",1024,768,true); + app->m_instancingRenderer->getActiveCamera()->setCameraDistance(13); app->m_instancingRenderer->getActiveCamera()->setCameraPitch(0); app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(0,0,0); @@ -74,16 +78,22 @@ int main(int argc, char* argv[]) app->m_window->setResizeCallback(MyResizeCallback); - - assert(glGetError()==GL_NO_ERROR); - myArgs.GetCmdLineArgument("mp4_file",gVideoFileName); if (gVideoFileName) app->dumpFramesToVideo(gVideoFileName); myArgs.GetCmdLineArgument("png_file",gPngFileName); char fileName[1024]; - + + int textureIndex = -1; + int textureWidth = 128; + int textureHeight = 128; + + unsigned char* image=new unsigned char[textureWidth*textureHeight*4]; + + + int textureHandle = app->m_renderer->registerTexture(image,textureWidth,textureHeight); + do { static int frameCount = 0; @@ -96,7 +106,29 @@ int main(int argc, char* argv[]) app->dumpNextFrameToPng(fileName); } - assert(glGetError()==GL_NO_ERROR); + + + //update the texels of the texture using a simple pattern, animated using frame index + for(int y=0;y>4; + unsigned char* pi=image+y*textureWidth*3; + for(int x=0;x>4; + const unsigned char b=180; + unsigned char c=b+((s+(t&1))&1)*(255-b); + pi[0]=pi[1]=pi[2]=pi[3]=c;pi+=3; + } + } + + app->m_renderer->activateTexture(textureHandle); + app->m_renderer->updateTexture(textureHandle,image); + + float color[4] = {255,1,1,1}; + app->m_primRenderer->drawTexturedRect(100,200,gWidth/2-50,gHeight/2-50,color,0,0,1,1,true); + + app->m_instancingRenderer->init(); app->m_instancingRenderer->updateCamera(); From 67426ecee91fc5d1316deca518d547a33f2e2291 Mon Sep 17 00:00:00 2001 From: "Erwin Coumans (Google)" Date: Thu, 21 Apr 2016 14:10:45 -0700 Subject: [PATCH 03/50] add missing stubs for the obsolete SimpleOpenGL2Renderer --- examples/OpenGLWindow/SimpleOpenGL2Renderer.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/OpenGLWindow/SimpleOpenGL2Renderer.h b/examples/OpenGLWindow/SimpleOpenGL2Renderer.h index b1e64483c..5fcd08d3e 100644 --- a/examples/OpenGLWindow/SimpleOpenGL2Renderer.h +++ b/examples/OpenGLWindow/SimpleOpenGL2Renderer.h @@ -50,6 +50,10 @@ struct SimpleOpenGL2Renderer : public CommonRenderInterface { return -1; } + virtual void updateTexture(int textureIndex, const unsigned char* texels) {} + virtual void activateTexture(int textureIndex) {} + + virtual int registerGraphicsInstance(int shapeIndex, const double* position, const double* quaternion, const double* color, const double* scaling); virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling); From d8da00aa352156ace3dfef564c019c892e67f122 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sat, 23 Apr 2016 11:06:34 -0700 Subject: [PATCH 04/50] re-enable Wavefront .obj loader --- examples/ExampleBrowser/ExampleEntries.cpp | 4 ---- examples/ExampleBrowser/premake4.lua | 1 - 2 files changed, 5 deletions(-) diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index c8377c7fb..36611663f 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -9,9 +9,7 @@ #include "../BasicDemo/BasicExample.h" #include "../Planar2D/Planar2D.h" #include "../Benchmarks/BenchmarkDemo.h" -#ifdef ENABLE_URDF_OBJ #include "../Importers/ImportObjDemo/ImportObjExample.h" -#endif #include "../Importers/ImportBsp/ImportBspExample.h" #include "../Importers/ImportColladaDemo/ImportColladaSetup.h" #include "../Importers/ImportSTLDemo/ImportSTLSetup.h" @@ -194,9 +192,7 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(0,"Importers"), ExampleEntry(1,"Import .bullet", "Load a binary .bullet file. The serialization mechanism can deal with versioning, differences in endianess, 32 and 64bit, double/single precision. It is easy to save a .bullet file, see the examples/Importers/ImportBullet/SerializeDemo.cpp for a code example how to export a .bullet file.", SerializeBulletCreateFunc), -#ifdef ENABLE_URDF_OBJ ExampleEntry(1,"Wavefront Obj", "Import a Wavefront .obj file", ImportObjCreateFunc, 0), -#endif ExampleEntry(1,"Quake BSP", "Import a Quake .bsp file", ImportBspCreateFunc, 0), ExampleEntry(1,"COLLADA dae", "Import the geometric mesh data from a COLLADA file. This is used as part of the URDF importer. This loader can also be used to import collision geometry in general. ", ImportColladaCreateFunc, 0), diff --git a/examples/ExampleBrowser/premake4.lua b/examples/ExampleBrowser/premake4.lua index d13b30228..9239b5924 100644 --- a/examples/ExampleBrowser/premake4.lua +++ b/examples/ExampleBrowser/premake4.lua @@ -78,7 +78,6 @@ project "BulletExampleBrowserLib" "../../src", "../ThirdPartyLibs", } - defines {"ENABLE_URDF_OBJ"} if _OPTIONS["lua"] then includedirs{"../ThirdPartyLibs/lua-5.2.3/src"} From f99d1c45aa922e74273cb8c715d18c1814d2320d Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sat, 23 Apr 2016 17:29:46 -0700 Subject: [PATCH 05/50] expose multibody link world transform in the shared memory API --- examples/SharedMemory/PhysicsClientC_API.cpp | 19 +++++++++++++++++++ examples/SharedMemory/PhysicsClientC_API.h | 1 + .../PhysicsServerCommandProcessor.cpp | 11 ++++++++++- examples/SharedMemory/SharedMemoryCommands.h | 2 ++ examples/SharedMemory/SharedMemoryPublic.h | 8 ++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/examples/SharedMemory/PhysicsClientC_API.cpp b/examples/SharedMemory/PhysicsClientC_API.cpp index 771e6eee7..b11c5ca65 100644 --- a/examples/SharedMemory/PhysicsClientC_API.cpp +++ b/examples/SharedMemory/PhysicsClientC_API.cpp @@ -222,6 +222,25 @@ void b3GetJointState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandl } } +void b3GetLinkState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandle statusHandle, int linkIndex, b3LinkState *state) +{ + const SharedMemoryStatus* status = (const SharedMemoryStatus* ) statusHandle; + b3Assert(status); + int bodyIndex = status->m_sendActualStateArgs.m_bodyUniqueId; + b3Assert(bodyIndex>=0); + if (bodyIndex>=0) + { + for (int i = 0; i < 7; ++i) + { + state->m_worldPosition[i] = status->m_sendActualStateArgs.m_linkState[7 * linkIndex + i]; + } + for (int i = 0; i < 4; ++i) + { + state->m_worldOrientation[i] = status->m_sendActualStateArgs.m_linkState[7 * linkIndex + 3 + i]; + } + } +} + b3SharedMemoryCommandHandle b3CreateBoxShapeCommandInit(b3PhysicsClientHandle physClient) { PhysicsClient* cl = (PhysicsClient* ) physClient; diff --git a/examples/SharedMemory/PhysicsClientC_API.h b/examples/SharedMemory/PhysicsClientC_API.h index d2fd34a5b..c6d465348 100644 --- a/examples/SharedMemory/PhysicsClientC_API.h +++ b/examples/SharedMemory/PhysicsClientC_API.h @@ -130,6 +130,7 @@ int b3CreateSensorEnableIMUForLink(b3SharedMemoryCommandHandle commandHandle, in b3SharedMemoryCommandHandle b3RequestActualStateCommandInit(b3PhysicsClientHandle physClient,int bodyUniqueId); void b3GetJointState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandle statusHandle, int jointIndex, struct b3JointSensorState *state); +void b3GetLinkState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandle statusHandle, int linkIndex, struct b3LinkState *state); b3SharedMemoryCommandHandle b3PickBody(b3PhysicsClientHandle physClient, double rayFromWorldX, double rayFromWorldY, double rayFromWorldZ, diff --git a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp index 116357390..f498fccaf 100644 --- a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp +++ b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp @@ -1349,9 +1349,18 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm //} } } + btVector3 linkOrigin = mb->getLink(l).m_cachedWorldTransform.getOrigin(); + btQuaternion linkRotation = mb->getLink(l).m_cachedWorldTransform.getRotation(); + serverCmd.m_sendActualStateArgs.m_linkState[l*7+0] = linkOrigin.getX(); + serverCmd.m_sendActualStateArgs.m_linkState[l*7+1] = linkOrigin.getY(); + serverCmd.m_sendActualStateArgs.m_linkState[l*7+2] = linkOrigin.getZ(); + serverCmd.m_sendActualStateArgs.m_linkState[l*7+3] = linkRotation.x(); + serverCmd.m_sendActualStateArgs.m_linkState[l*7+4] = linkRotation.y(); + serverCmd.m_sendActualStateArgs.m_linkState[l*7+5] = linkRotation.z(); + serverCmd.m_sendActualStateArgs.m_linkState[l*7+6] = linkRotation.w(); } - + serverCmd.m_sendActualStateArgs.m_numDegreeOfFreedomQ = totalDegreeOfFreedomQ; serverCmd.m_sendActualStateArgs.m_numDegreeOfFreedomU = totalDegreeOfFreedomU; diff --git a/examples/SharedMemory/SharedMemoryCommands.h b/examples/SharedMemory/SharedMemoryCommands.h index 94e0832be..eafe68fe0 100644 --- a/examples/SharedMemory/SharedMemoryCommands.h +++ b/examples/SharedMemory/SharedMemoryCommands.h @@ -31,6 +31,7 @@ #define MAX_NUM_SENSORS 256 #define MAX_URDF_FILENAME_LENGTH 1024 #define MAX_FILENAME_LENGTH MAX_URDF_FILENAME_LENGTH +#define MAX_NUM_LINKS MAX_DEGREE_OF_FREEDOM struct TmpFloat3 { @@ -196,6 +197,7 @@ struct SendActualStateArgs double m_jointReactionForces[6*MAX_DEGREE_OF_FREEDOM]; double m_jointMotorForce[MAX_DEGREE_OF_FREEDOM]; + double m_linkState[7*MAX_NUM_LINKS]; }; enum EnumSensorTypes diff --git a/examples/SharedMemory/SharedMemoryPublic.h b/examples/SharedMemory/SharedMemoryPublic.h index 315c15779..b5542a01c 100644 --- a/examples/SharedMemory/SharedMemoryPublic.h +++ b/examples/SharedMemory/SharedMemoryPublic.h @@ -105,6 +105,14 @@ struct b3DebugLines const float* m_linesColor;//float red,green,blue times 'm_numDebugLines'. }; +///b3LinkState provides extra information such as the Cartesian world coordinates of the link +///relative to the world reference frame. Orientation is a quaternion x,y,z,w +struct b3LinkState +{ + double m_worldPosition[3]; + double m_worldOrientation[4]; +}; + //todo: discuss and decide about control mode and combinations enum { // POSITION_CONTROL=0, From 66bfb7e7086e57066ca829bce184913e8987ccee Mon Sep 17 00:00:00 2001 From: erwincoumans Date: Mon, 25 Apr 2016 09:37:04 -0700 Subject: [PATCH 06/50] Update PhysicsClientC_API.cpp fix a copy/paste bug -> pos+quat = 7, but pos is just 3 --- examples/SharedMemory/PhysicsClientC_API.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/SharedMemory/PhysicsClientC_API.cpp b/examples/SharedMemory/PhysicsClientC_API.cpp index b11c5ca65..809413c16 100644 --- a/examples/SharedMemory/PhysicsClientC_API.cpp +++ b/examples/SharedMemory/PhysicsClientC_API.cpp @@ -230,7 +230,7 @@ void b3GetLinkState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandle b3Assert(bodyIndex>=0); if (bodyIndex>=0) { - for (int i = 0; i < 7; ++i) + for (int i = 0; i < 3; ++i) { state->m_worldPosition[i] = status->m_sendActualStateArgs.m_linkState[7 * linkIndex + i]; } From a080a568f2497db083772c882a1ee0f11c6f7073 Mon Sep 17 00:00:00 2001 From: erwincoumans Date: Mon, 25 Apr 2016 09:42:16 -0700 Subject: [PATCH 07/50] Update main.cpp remove unused variable --- examples/SimpleOpenGL3/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/SimpleOpenGL3/main.cpp b/examples/SimpleOpenGL3/main.cpp index 300dfa79e..604eb3920 100644 --- a/examples/SimpleOpenGL3/main.cpp +++ b/examples/SimpleOpenGL3/main.cpp @@ -85,7 +85,6 @@ int main(int argc, char* argv[]) myArgs.GetCmdLineArgument("png_file",gPngFileName); char fileName[1024]; - int textureIndex = -1; int textureWidth = 128; int textureHeight = 128; From 778ce5296d4495cb75788266c23c1678476d90ea Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 25 Apr 2016 13:21:56 -0700 Subject: [PATCH 08/50] add example of rendering a cube in SimpleOpenGL3 --- data/multibody.bullet | Bin 14584 -> 14584 bytes examples/SimpleOpenGL3/main.cpp | 12 +++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/data/multibody.bullet b/data/multibody.bullet index 04455f0d581801063808b200d0285610993fd875..1074b55dc5e60dafd11b59406edb7842bdfc57dd 100644 GIT binary patch delta 617 zcmZ9JyGz4R7{zZ)Qd8|Cpthh6RXRzLfFL;7R_G{b*ZPX@wXprYVk;NaqG>7dX-jOXSWrM>Xu<~!%y@4Mud&9b?3B6kr&+UdB|L*Hua@?VCe z?nOkJ7vh1E6B1#P^vkbsU=+`ppoXJvB5qtq+=LE+8Q#)fxxR@#Z#L3IO+sOw@#fYE z^_}}(Uf<`FZ1|qW_H+P)teQ+9O~S6B#iFcX#xC*$URV!u->A}KpFH<)R+(4NL#$6+ z6ZknDwbzU7#wo7{>)E^}@xqPMV^Pak_^ycF@;eV!>DDvXAA*(tri5G}CTW7uQpn0- zL1?3b+(6fSO=z2<+rF!|gYM2GA)Bdx2)V!OPkuX&WA;ATeblVoQlJ#si_lj8D9tIC zbXN$`N2N7l*|;C$ZygUJybgknpuk9aW-tD<2Np;hUcHkYV}N z @@ -93,6 +93,15 @@ int main(int argc, char* argv[]) int textureHandle = app->m_renderer->registerTexture(image,textureWidth,textureHeight); + + int cubeIndex = app->registerCubeShape(1,1,1); + + b3Vector3 pos = b3MakeVector3(0,0,0); + b3Quaternion orn(0,0,0,1); + b3Vector3 color=b3MakeVector3(1,0,0); + b3Vector3 scaling=b3MakeVector3 (1,1,1); + app->m_renderer->registerGraphicsInstance(cubeIndex,pos,orn,color,scaling); + app->m_renderer->writeTransforms(); do { @@ -132,6 +141,7 @@ int main(int argc, char* argv[]) app->m_instancingRenderer->init(); app->m_instancingRenderer->updateCamera(); + app->m_renderer->renderScene(); app->drawGrid(); char bla[1024]; sprintf(bla,"Simple test frame %d", frameCount); From edba85bab3a9ac55451e963712f1f03309e4c5dc Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 25 Apr 2016 19:19:19 -0700 Subject: [PATCH 09/50] fix issue in X11OpenGLWindow (uninitialized variable causing issue at exit) --- examples/OpenGLWindow/X11OpenGLWindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/OpenGLWindow/X11OpenGLWindow.cpp b/examples/OpenGLWindow/X11OpenGLWindow.cpp index 681c3f423..e6d0f666d 100644 --- a/examples/OpenGLWindow/X11OpenGLWindow.cpp +++ b/examples/OpenGLWindow/X11OpenGLWindow.cpp @@ -461,6 +461,7 @@ void X11OpenGLWindow::enableOpenGL() printf( "Making context current\n" ); glXMakeCurrent( m_data->m_dpy, m_data->m_win, ctx ); + m_data->m_glc = ctx; } else { @@ -1090,7 +1091,7 @@ int X11OpenGLWindow::fileOpenDialog(char* filename, int maxNameLength) { filename[len-1]=0; printf("file open (length=%d) = %s\n", len,filename); - } + } } pclose(output); } else @@ -1099,5 +1100,5 @@ int X11OpenGLWindow::fileOpenDialog(char* filename, int maxNameLength) } MyXRaiseWindow(m_data->m_dpy, m_data->m_win); return len; - + } From 2cb39e358a075bcb017bcfe2d38a3c968ae64adc Mon Sep 17 00:00:00 2001 From: erwin coumans Date: Tue, 26 Apr 2016 20:47:10 -0700 Subject: [PATCH 10/50] add unmodified version of TinyRenderer, a 500 line software renderer with vertex and pixel shaders, texture mapping and Wavefront .obj support. --- examples/TinyRenderer/LICENSE.txt | 13 ++ examples/TinyRenderer/Makefile | 23 ++ examples/TinyRenderer/README.md | 55 +++++ examples/TinyRenderer/geometry.cpp | 7 + examples/TinyRenderer/geometry.h | 221 ++++++++++++++++++ examples/TinyRenderer/main.cpp | 94 ++++++++ examples/TinyRenderer/model.cpp | 108 +++++++++ examples/TinyRenderer/model.h | 33 +++ examples/TinyRenderer/our_gl.cpp | 86 +++++++ examples/TinyRenderer/our_gl.h | 22 ++ examples/TinyRenderer/tgaimage.cpp | 356 +++++++++++++++++++++++++++++ examples/TinyRenderer/tgaimage.h | 98 ++++++++ 12 files changed, 1116 insertions(+) create mode 100644 examples/TinyRenderer/LICENSE.txt create mode 100644 examples/TinyRenderer/Makefile create mode 100644 examples/TinyRenderer/README.md create mode 100644 examples/TinyRenderer/geometry.cpp create mode 100644 examples/TinyRenderer/geometry.h create mode 100644 examples/TinyRenderer/main.cpp create mode 100644 examples/TinyRenderer/model.cpp create mode 100644 examples/TinyRenderer/model.h create mode 100644 examples/TinyRenderer/our_gl.cpp create mode 100644 examples/TinyRenderer/our_gl.h create mode 100644 examples/TinyRenderer/tgaimage.cpp create mode 100644 examples/TinyRenderer/tgaimage.h diff --git a/examples/TinyRenderer/LICENSE.txt b/examples/TinyRenderer/LICENSE.txt new file mode 100644 index 000000000..95dbe5b4e --- /dev/null +++ b/examples/TinyRenderer/LICENSE.txt @@ -0,0 +1,13 @@ +Tiny Renderer, https://github.com/ssloy/tinyrenderer +Copyright Dmitry V. Sokolov + +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. + diff --git a/examples/TinyRenderer/Makefile b/examples/TinyRenderer/Makefile new file mode 100644 index 000000000..0b0a469b0 --- /dev/null +++ b/examples/TinyRenderer/Makefile @@ -0,0 +1,23 @@ +SYSCONF_LINK = g++ +CPPFLAGS = -Wall -Wextra -Weffc++ -pedantic -std=c++98 +LDFLAGS = -O3 +LIBS = -lm + +DESTDIR = ./ +TARGET = main + +OBJECTS := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(OBJECTS) + $(SYSCONF_LINK) -Wall $(LDFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(LIBS) + +$(OBJECTS): %.o: %.cpp + $(SYSCONF_LINK) -Wall $(CPPFLAGS) -c $(CFLAGS) $< -o $@ + +clean: + -rm -f $(OBJECTS) + -rm -f $(TARGET) + -rm -f *.tga + diff --git a/examples/TinyRenderer/README.md b/examples/TinyRenderer/README.md new file mode 100644 index 000000000..84a125234 --- /dev/null +++ b/examples/TinyRenderer/README.md @@ -0,0 +1,55 @@ +# Tiny Renderer or how OpenGL works: software renderer in 500 lines of code + +*** + +**Check [the wiki](https://github.com/ssloy/tinyrenderer/wiki/Lesson-1:-Bresenham%E2%80%99s-Line-Drawing-Algorithm) for the detailed lessons. My source code is irrelevant. Read the wiki and implement your own renderer. Only when you suffer through all the tiny details you will learn what is going on.** + +**I do want to get emails for feedback (dmitry.sokolov@univ-lorraine.fr); do not hesitate to contact me if you have any questions.** + +**If you are a teacher and willing to adopt this material for teaching your class your are very welcome, no authorization is needed, simply inform me by mail, it will help me to improve the course.** + +*** + +In this series of articles, I want to show the way OpenGL works by writing its clone (a much simplified one). Surprisingly enough, I often meet people who cannot overcome the initial hurdle of learning OpenGL / DirectX. Thus, I have prepared a short series of lectures, after which my students show quite good renderers. + +So, the task is formulated as follows: using no third-party libraries (especially graphic ones), get something like this picture: + +![](http://haqr.eu/framebuffer.png) + +_Warning: this is a training material that will loosely repeat the structure of the OpenGL library. It will be a software renderer. **I do not want to show how to write applications for OpenGL. I want to show how OpenGL works.** I am deeply convinced that it is impossible to write efficient applications using 3D libraries without understanding this._ + +I will try to make the final code about 500 lines. My students need 10 to 20 programming hours to begin making such renderers. At the input, we get a test file with a polygonal wire + pictures with textures. At the output, we’ll get a rendered model. No graphical interface, the program simply generates an image. + + +Since the goal is to minimize external dependencies, I give my students just one class that allows working with [TGA](http://en.wikipedia.org/wiki/Truevision_TGA) files. It’s one of the simplest formats that supports images in RGB/RGBA/black and white formats. So, as a starting point, we’ll obtain a simple way to work with pictures. You should note that the only functionality available at the very beginning (in addition to loading and saving images) is the capability to set the color of one pixel. + +There are no functions for drawing line segments and triangles. We’ll have to do all of this by hand. I provide my source code that I write in parallel with students. But I would not recommend using it, as this doesn’t make sense. The entire code is available on github, and [here](https://github.com/ssloy/tinyrenderer/tree/909fe20934ba5334144d2c748805690a1fa4c89f) you will find the source code I give to my students. + +```C++ +#include "tgaimage.h" +const TGAColor white = TGAColor(255, 255, 255, 255); +const TGAColor red = TGAColor(255, 0, 0, 255); +int main(int argc, char** argv) { + TGAImage image(100, 100, TGAImage::RGB); + image.set(52, 41, red); + image.flip_vertically(); // i want to have the origin at the left bottom corner of the image + image.write_tga_file("output.tga");` + return 0; +} +``` + +output.tga should look something like this: + +![](http://www.loria.fr/~sokolovd/cg-course/img/2d3b12170b.png) + + + +# Teaser: few examples made with the renderer + +![](https://hsto.org/getpro/habr/post_images/50d/e2a/be9/50de2abe990efa345664f98c9464a4c8.png) + +![](https://hsto.org/getpro/habr/post_images/e3c/d70/492/e3cd704925f52b5466ab3c4f9fbab899.png) + +![](http://www.loria.fr/~sokolovd/cg-course/06-shaders/img/boggie.png) + +![](http://hsto.org/files/1ba/93f/a5a/1ba93fa5a48646e2a9614271c943b4da.png) diff --git a/examples/TinyRenderer/geometry.cpp b/examples/TinyRenderer/geometry.cpp new file mode 100644 index 000000000..3b6b2f251 --- /dev/null +++ b/examples/TinyRenderer/geometry.cpp @@ -0,0 +1,7 @@ +#include "geometry.h" + +template <> template <> vec<3,int> ::vec(const vec<3,float> &v) : x(int(v.x+.5f)),y(int(v.y+.5f)),z(int(v.z+.5f)) {} +template <> template <> vec<3,float>::vec(const vec<3,int> &v) : x(v.x),y(v.y),z(v.z) {} +template <> template <> vec<2,int> ::vec(const vec<2,float> &v) : x(int(v.x+.5f)),y(int(v.y+.5f)) {} +template <> template <> vec<2,float>::vec(const vec<2,int> &v) : x(v.x),y(v.y) {} + diff --git a/examples/TinyRenderer/geometry.h b/examples/TinyRenderer/geometry.h new file mode 100644 index 000000000..46ee7b354 --- /dev/null +++ b/examples/TinyRenderer/geometry.h @@ -0,0 +1,221 @@ +#ifndef __GEOMETRY_H__ +#define __GEOMETRY_H__ +#include +#include +#include +#include + +template class mat; + +template struct vec { + vec() { for (size_t i=DIM; i--; data_[i] = T()); } + T& operator[](const size_t i) { assert(i struct vec<2,T> { + vec() : x(T()), y(T()) {} + vec(T X, T Y) : x(X), y(Y) {} + template vec<2,T>(const vec<2,U> &v); + T& operator[](const size_t i) { assert(i<2); return i<=0 ? x : y; } + const T& operator[](const size_t i) const { assert(i<2); return i<=0 ? x : y; } + + T x,y; +}; + +///////////////////////////////////////////////////////////////////////////////// + +template struct vec<3,T> { + vec() : x(T()), y(T()), z(T()) {} + vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {} + template vec<3,T>(const vec<3,U> &v); + T& operator[](const size_t i) { assert(i<3); return i<=0 ? x : (1==i ? y : z); } + const T& operator[](const size_t i) const { assert(i<3); return i<=0 ? x : (1==i ? y : z); } + float norm() { return std::sqrt(x*x+y*y+z*z); } + vec<3,T> & normalize(T l=1) { *this = (*this)*(l/norm()); return *this; } + + T x,y,z; +}; + +///////////////////////////////////////////////////////////////////////////////// + +template T operator*(const vec& lhs, const vec& rhs) { + T ret = T(); + for (size_t i=DIM; i--; ret+=lhs[i]*rhs[i]); + return ret; +} + + +templatevec operator+(vec lhs, const vec& rhs) { + for (size_t i=DIM; i--; lhs[i]+=rhs[i]); + return lhs; +} + +templatevec operator-(vec lhs, const vec& rhs) { + for (size_t i=DIM; i--; lhs[i]-=rhs[i]); + return lhs; +} + +template vec operator*(vec lhs, const U& rhs) { + for (size_t i=DIM; i--; lhs[i]*=rhs); + return lhs; +} + +template vec operator/(vec lhs, const U& rhs) { + for (size_t i=DIM; i--; lhs[i]/=rhs); + return lhs; +} + +template vec embed(const vec &v, T fill=1) { + vec ret; + for (size_t i=LEN; i--; ret[i]=(i vec proj(const vec &v) { + vec ret; + for (size_t i=LEN; i--; ret[i]=v[i]); + return ret; +} + +template vec<3,T> cross(vec<3,T> v1, vec<3,T> v2) { + return vec<3,T>(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x); +} + +template std::ostream& operator<<(std::ostream& out, vec& v) { + for(unsigned int i=0; i struct dt { + static T det(const mat& src) { + T ret=0; + for (size_t i=DIM; i--; ret += src[0][i]*src.cofactor(0,i)); + return ret; + } +}; + +template struct dt<1,T> { + static T det(const mat<1,1,T>& src) { + return src[0][0]; + } +}; + +///////////////////////////////////////////////////////////////////////////////// + +template class mat { + vec rows[DimRows]; +public: + mat() {} + + vec& operator[] (const size_t idx) { + assert(idx& operator[] (const size_t idx) const { + assert(idx col(const size_t idx) const { + assert(idx ret; + for (size_t i=DimRows; i--; ret[i]=rows[i][idx]); + return ret; + } + + void set_col(size_t idx, vec v) { + assert(idx identity() { + mat ret; + for (size_t i=DimRows; i--; ) + for (size_t j=DimCols;j--; ret[i][j]=(i==j)); + return ret; + } + + T det() const { + return dt::det(*this); + } + + mat get_minor(size_t row, size_t col) const { + mat ret; + for (size_t i=DimRows-1; i--; ) + for (size_t j=DimCols-1;j--; ret[i][j]=rows[i adjugate() const { + mat ret; + for (size_t i=DimRows; i--; ) + for (size_t j=DimCols; j--; ret[i][j]=cofactor(i,j)); + return ret; + } + + mat invert_transpose() { + mat ret = adjugate(); + T tmp = ret[0]*rows[0]; + return ret/tmp; + } + + mat invert() { + return invert_transpose().transpose(); + } + + mat transpose() { + mat ret; + for (size_t i=DimCols; i--; ret[i]=this->col(i)); + return ret; + } +}; + +///////////////////////////////////////////////////////////////////////////////// + +template vec operator*(const mat& lhs, const vec& rhs) { + vec ret; + for (size_t i=DimRows; i--; ret[i]=lhs[i]*rhs); + return ret; +} + +templatemat operator*(const mat& lhs, const mat& rhs) { + mat result; + for (size_t i=R1; i--; ) + for (size_t j=C2; j--; result[i][j]=lhs[i]*rhs.col(j)); + return result; +} + +templatemat operator/(mat lhs, const T& rhs) { + for (size_t i=DimRows; i--; lhs[i]=lhs[i]/rhs); + return lhs; +} + +template std::ostream& operator<<(std::ostream& out, mat& m) { + for (size_t i=0; i Vec2f; +typedef vec<2, int> Vec2i; +typedef vec<3, float> Vec3f; +typedef vec<3, int> Vec3i; +typedef vec<4, float> Vec4f; +typedef mat<4,4,float> Matrix; +#endif //__GEOMETRY_H__ + diff --git a/examples/TinyRenderer/main.cpp b/examples/TinyRenderer/main.cpp new file mode 100644 index 000000000..8ce61dda2 --- /dev/null +++ b/examples/TinyRenderer/main.cpp @@ -0,0 +1,94 @@ +#include +#include +#include +#include "tgaimage.h" +#include "model.h" +#include "geometry.h" +#include "our_gl.h" + +Model *model = NULL; + +const int width = 800; +const int height = 800; + +Vec3f light_dir(1,1,1); +Vec3f eye(1,1,3); +Vec3f center(0,0,0); +Vec3f up(0,1,0); + +struct Shader : public IShader { + mat<2,3,float> varying_uv; // triangle uv coordinates, written by the vertex shader, read by the fragment shader + mat<4,3,float> varying_tri; // triangle coordinates (clip coordinates), written by VS, read by FS + mat<3,3,float> varying_nrm; // normal per vertex to be interpolated by FS + mat<3,3,float> ndc_tri; // triangle in normalized device coordinates + + virtual Vec4f vertex(int iface, int nthvert) { + varying_uv.set_col(nthvert, model->uv(iface, nthvert)); + varying_nrm.set_col(nthvert, proj<3>((Projection*ModelView).invert_transpose()*embed<4>(model->normal(iface, nthvert), 0.f))); + Vec4f gl_Vertex = Projection*ModelView*embed<4>(model->vert(iface, nthvert)); + varying_tri.set_col(nthvert, gl_Vertex); + ndc_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3])); + return gl_Vertex; + } + + virtual bool fragment(Vec3f bar, TGAColor &color) { + Vec3f bn = (varying_nrm*bar).normalize(); + Vec2f uv = varying_uv*bar; + + mat<3,3,float> A; + A[0] = ndc_tri.col(1) - ndc_tri.col(0); + A[1] = ndc_tri.col(2) - ndc_tri.col(0); + A[2] = bn; + + mat<3,3,float> AI = A.invert(); + + Vec3f i = AI * Vec3f(varying_uv[0][1] - varying_uv[0][0], varying_uv[0][2] - varying_uv[0][0], 0); + Vec3f j = AI * Vec3f(varying_uv[1][1] - varying_uv[1][0], varying_uv[1][2] - varying_uv[1][0], 0); + + mat<3,3,float> B; + B.set_col(0, i.normalize()); + B.set_col(1, j.normalize()); + B.set_col(2, bn); + + Vec3f n = (B*model->normal(uv)).normalize(); + + float diff = std::max(0.f, n*light_dir); + color = model->diffuse(uv)*diff; + + return false; + } +}; + +int main(int argc, char** argv) { + if (2>argc) { + std::cerr << "Usage: " << argv[0] << " obj/model.obj" << std::endl; + return 1; + } + + float *zbuffer = new float[width*height]; + for (int i=width*height; i--; zbuffer[i] = -std::numeric_limits::max()); + + TGAImage frame(width, height, TGAImage::RGB); + lookat(eye, center, up); + viewport(width/8, height/8, width*3/4, height*3/4); + projection(-1.f/(eye-center).norm()); + light_dir = proj<3>((Projection*ModelView*embed<4>(light_dir, 0.f))).normalize(); + + for (int m=1; mnfaces(); i++) { + for (int j=0; j<3; j++) { + shader.vertex(i, j); + } + triangle(shader.varying_tri, shader, frame, zbuffer); + } + delete model; + } + frame.flip_vertically(); // to place the origin in the bottom left corner of the image + frame.write_tga_file("framebuffer.tga"); + + delete [] zbuffer; + return 0; +} + diff --git a/examples/TinyRenderer/model.cpp b/examples/TinyRenderer/model.cpp new file mode 100644 index 000000000..bc7983dd5 --- /dev/null +++ b/examples/TinyRenderer/model.cpp @@ -0,0 +1,108 @@ +#include +#include +#include +#include "model.h" + +Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_() { + std::ifstream in; + in.open (filename, std::ifstream::in); + if (in.fail()) return; + std::string line; + while (!in.eof()) { + std::getline(in, line); + std::istringstream iss(line.c_str()); + char trash; + if (!line.compare(0, 2, "v ")) { + iss >> trash; + Vec3f v; + for (int i=0;i<3;i++) iss >> v[i]; + verts_.push_back(v); + } else if (!line.compare(0, 3, "vn ")) { + iss >> trash >> trash; + Vec3f n; + for (int i=0;i<3;i++) iss >> n[i]; + norms_.push_back(n); + } else if (!line.compare(0, 3, "vt ")) { + iss >> trash >> trash; + Vec2f uv; + for (int i=0;i<2;i++) iss >> uv[i]; + uv_.push_back(uv); + } else if (!line.compare(0, 2, "f ")) { + std::vector f; + Vec3i tmp; + iss >> trash; + while (iss >> tmp[0] >> trash >> tmp[1] >> trash >> tmp[2]) { + for (int i=0; i<3; i++) tmp[i]--; // in wavefront obj all indices start at 1, not zero + f.push_back(tmp); + } + faces_.push_back(f); + } + } + std::cerr << "# v# " << verts_.size() << " f# " << faces_.size() << " vt# " << uv_.size() << " vn# " << norms_.size() << std::endl; + load_texture(filename, "_diffuse.tga", diffusemap_); + load_texture(filename, "_nm_tangent.tga", normalmap_); + load_texture(filename, "_spec.tga", specularmap_); +} + +Model::~Model() {} + +int Model::nverts() { + return (int)verts_.size(); +} + +int Model::nfaces() { + return (int)faces_.size(); +} + +std::vector Model::face(int idx) { + std::vector face; + for (int i=0; i<(int)faces_[idx].size(); i++) face.push_back(faces_[idx][i][0]); + return face; +} + +Vec3f Model::vert(int i) { + return verts_[i]; +} + +Vec3f Model::vert(int iface, int nthvert) { + return verts_[faces_[iface][nthvert][0]]; +} + +void Model::load_texture(std::string filename, const char *suffix, TGAImage &img) { + std::string texfile(filename); + size_t dot = texfile.find_last_of("."); + if (dot!=std::string::npos) { + texfile = texfile.substr(0,dot) + std::string(suffix); + std::cerr << "texture file " << texfile << " loading " << (img.read_tga_file(texfile.c_str()) ? "ok" : "failed") << std::endl; + img.flip_vertically(); + } +} + +TGAColor Model::diffuse(Vec2f uvf) { + Vec2i uv(uvf[0]*diffusemap_.get_width(), uvf[1]*diffusemap_.get_height()); + return diffusemap_.get(uv[0], uv[1]); +} + +Vec3f Model::normal(Vec2f uvf) { + Vec2i uv(uvf[0]*normalmap_.get_width(), uvf[1]*normalmap_.get_height()); + TGAColor c = normalmap_.get(uv[0], uv[1]); + Vec3f res; + for (int i=0; i<3; i++) + res[2-i] = (float)c[i]/255.f*2.f - 1.f; + return res; +} + +Vec2f Model::uv(int iface, int nthvert) { + return uv_[faces_[iface][nthvert][1]]; +} + +float Model::specular(Vec2f uvf) { + Vec2i uv(uvf[0]*specularmap_.get_width(), uvf[1]*specularmap_.get_height()); + return specularmap_.get(uv[0], uv[1])[0]/1.f; +} + +Vec3f Model::normal(int iface, int nthvert) { + int idx = faces_[iface][nthvert][2]; + return norms_[idx].normalize(); +} + diff --git a/examples/TinyRenderer/model.h b/examples/TinyRenderer/model.h new file mode 100644 index 000000000..035cc119a --- /dev/null +++ b/examples/TinyRenderer/model.h @@ -0,0 +1,33 @@ +#ifndef __MODEL_H__ +#define __MODEL_H__ +#include +#include +#include "geometry.h" +#include "tgaimage.h" + +class Model { +private: + std::vector verts_; + std::vector > faces_; // attention, this Vec3i means vertex/uv/normal + std::vector norms_; + std::vector uv_; + TGAImage diffusemap_; + TGAImage normalmap_; + TGAImage specularmap_; + void load_texture(std::string filename, const char *suffix, TGAImage &img); +public: + Model(const char *filename); + ~Model(); + int nverts(); + int nfaces(); + Vec3f normal(int iface, int nthvert); + Vec3f normal(Vec2f uv); + Vec3f vert(int i); + Vec3f vert(int iface, int nthvert); + Vec2f uv(int iface, int nthvert); + TGAColor diffuse(Vec2f uv); + float specular(Vec2f uv); + std::vector face(int idx); +}; +#endif //__MODEL_H__ + diff --git a/examples/TinyRenderer/our_gl.cpp b/examples/TinyRenderer/our_gl.cpp new file mode 100644 index 000000000..3772c984a --- /dev/null +++ b/examples/TinyRenderer/our_gl.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include "our_gl.h" + +Matrix ModelView; +Matrix Viewport; +Matrix Projection; + +IShader::~IShader() {} + +void viewport(int x, int y, int w, int h) { + Viewport = Matrix::identity(); + Viewport[0][3] = x+w/2.f; + Viewport[1][3] = y+h/2.f; + Viewport[2][3] = 1.f; + Viewport[0][0] = w/2.f; + Viewport[1][1] = h/2.f; + Viewport[2][2] = 0; +} + +void projection(float coeff) { + Projection = Matrix::identity(); + Projection[3][2] = coeff; +} + +void lookat(Vec3f eye, Vec3f center, Vec3f up) { + Vec3f z = (eye-center).normalize(); + Vec3f x = cross(up,z).normalize(); + Vec3f y = cross(z,x).normalize(); + Matrix Minv = Matrix::identity(); + Matrix Tr = Matrix::identity(); + for (int i=0; i<3; i++) { + Minv[0][i] = x[i]; + Minv[1][i] = y[i]; + Minv[2][i] = z[i]; + Tr[i][3] = -center[i]; + } + ModelView = Minv*Tr; +} + +Vec3f barycentric(Vec2f A, Vec2f B, Vec2f C, Vec2f P) { + Vec3f s[2]; + for (int i=2; i--; ) { + s[i][0] = C[i]-A[i]; + s[i][1] = B[i]-A[i]; + s[i][2] = A[i]-P[i]; + } + Vec3f u = cross(s[0], s[1]); + if (std::abs(u[2])>1e-2) // dont forget that u[2] is integer. If it is zero then triangle ABC is degenerate + return Vec3f(1.f-(u.x+u.y)/u.z, u.y/u.z, u.x/u.z); + return Vec3f(-1,1,1); // in this case generate negative coordinates, it will be thrown away by the rasterizator +} + +void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zbuffer) { + mat<3,4,float> pts = (Viewport*clipc).transpose(); // transposed to ease access to each of the points + mat<3,2,float> pts2; + for (int i=0; i<3; i++) pts2[i] = proj<2>(pts[i]/pts[i][3]); + + Vec2f bboxmin( std::numeric_limits::max(), std::numeric_limits::max()); + Vec2f bboxmax(-std::numeric_limits::max(), -std::numeric_limits::max()); + Vec2f clamp(image.get_width()-1, image.get_height()-1); + for (int i=0; i<3; i++) { + for (int j=0; j<2; j++) { + bboxmin[j] = std::max(0.f, std::min(bboxmin[j], pts2[i][j])); + bboxmax[j] = std::min(clamp[j], std::max(bboxmax[j], pts2[i][j])); + } + } + Vec2i P; + TGAColor color; + for (P.x=bboxmin.x; P.x<=bboxmax.x; P.x++) { + for (P.y=bboxmin.y; P.y<=bboxmax.y; P.y++) { + Vec3f bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P); + Vec3f bc_clip = Vec3f(bc_screen.x/pts[0][3], bc_screen.y/pts[1][3], bc_screen.z/pts[2][3]); + bc_clip = bc_clip/(bc_clip.x+bc_clip.y+bc_clip.z); + float frag_depth = clipc[2]*bc_clip; + if (bc_screen.x<0 || bc_screen.y<0 || bc_screen.z<0 || zbuffer[P.x+P.y*image.get_width()]>frag_depth) continue; + bool discard = shader.fragment(bc_clip, color); + if (!discard) { + zbuffer[P.x+P.y*image.get_width()] = frag_depth; + image.set(P.x, P.y, color); + } + } + } +} + diff --git a/examples/TinyRenderer/our_gl.h b/examples/TinyRenderer/our_gl.h new file mode 100644 index 000000000..bc8ed7312 --- /dev/null +++ b/examples/TinyRenderer/our_gl.h @@ -0,0 +1,22 @@ +#ifndef __OUR_GL_H__ +#define __OUR_GL_H__ +#include "tgaimage.h" +#include "geometry.h" + +extern Matrix ModelView; +extern Matrix Projection; + +void viewport(int x, int y, int w, int h); +void projection(float coeff=0.f); // coeff = -1/c +void lookat(Vec3f eye, Vec3f center, Vec3f up); + +struct IShader { + virtual ~IShader(); + virtual Vec4f vertex(int iface, int nthvert) = 0; + virtual bool fragment(Vec3f bar, TGAColor &color) = 0; +}; + +//void triangle(Vec4f *pts, IShader &shader, TGAImage &image, float *zbuffer); +void triangle(mat<4,3,float> &pts, IShader &shader, TGAImage &image, float *zbuffer); +#endif //__OUR_GL_H__ + diff --git a/examples/TinyRenderer/tgaimage.cpp b/examples/TinyRenderer/tgaimage.cpp new file mode 100644 index 000000000..47e6ff833 --- /dev/null +++ b/examples/TinyRenderer/tgaimage.cpp @@ -0,0 +1,356 @@ +#include +#include +#include +#include +#include +#include "tgaimage.h" + +TGAImage::TGAImage() : data(NULL), width(0), height(0), bytespp(0) {} + +TGAImage::TGAImage(int w, int h, int bpp) : data(NULL), width(w), height(h), bytespp(bpp) { + unsigned long nbytes = width*height*bytespp; + data = new unsigned char[nbytes]; + memset(data, 0, nbytes); +} + +TGAImage::TGAImage(const TGAImage &img) : data(NULL), width(img.width), height(img.height), bytespp(img.bytespp) { + unsigned long nbytes = width*height*bytespp; + data = new unsigned char[nbytes]; + memcpy(data, img.data, nbytes); +} + +TGAImage::~TGAImage() { + if (data) delete [] data; +} + +TGAImage & TGAImage::operator =(const TGAImage &img) { + if (this != &img) { + if (data) delete [] data; + width = img.width; + height = img.height; + bytespp = img.bytespp; + unsigned long nbytes = width*height*bytespp; + data = new unsigned char[nbytes]; + memcpy(data, img.data, nbytes); + } + return *this; +} + +bool TGAImage::read_tga_file(const char *filename) { + if (data) delete [] data; + data = NULL; + std::ifstream in; + in.open (filename, std::ios::binary); + if (!in.is_open()) { + std::cerr << "can't open file " << filename << "\n"; + in.close(); + return false; + } + TGA_Header header; + in.read((char *)&header, sizeof(header)); + if (!in.good()) { + in.close(); + std::cerr << "an error occured while reading the header\n"; + return false; + } + width = header.width; + height = header.height; + bytespp = header.bitsperpixel>>3; + if (width<=0 || height<=0 || (bytespp!=GRAYSCALE && bytespp!=RGB && bytespp!=RGBA)) { + in.close(); + std::cerr << "bad bpp (or width/height) value\n"; + return false; + } + unsigned long nbytes = bytespp*width*height; + data = new unsigned char[nbytes]; + if (3==header.datatypecode || 2==header.datatypecode) { + in.read((char *)data, nbytes); + if (!in.good()) { + in.close(); + std::cerr << "an error occured while reading the data\n"; + return false; + } + } else if (10==header.datatypecode||11==header.datatypecode) { + if (!load_rle_data(in)) { + in.close(); + std::cerr << "an error occured while reading the data\n"; + return false; + } + } else { + in.close(); + std::cerr << "unknown file format " << (int)header.datatypecode << "\n"; + return false; + } + if (!(header.imagedescriptor & 0x20)) { + flip_vertically(); + } + if (header.imagedescriptor & 0x10) { + flip_horizontally(); + } + std::cerr << width << "x" << height << "/" << bytespp*8 << "\n"; + in.close(); + return true; +} + +bool TGAImage::load_rle_data(std::ifstream &in) { + unsigned long pixelcount = width*height; + unsigned long currentpixel = 0; + unsigned long currentbyte = 0; + TGAColor colorbuffer; + do { + unsigned char chunkheader = 0; + chunkheader = in.get(); + if (!in.good()) { + std::cerr << "an error occured while reading the data\n"; + return false; + } + if (chunkheader<128) { + chunkheader++; + for (int i=0; ipixelcount) { + std::cerr << "Too many pixels read\n"; + return false; + } + } + } else { + chunkheader -= 127; + in.read((char *)colorbuffer.bgra, bytespp); + if (!in.good()) { + std::cerr << "an error occured while reading the header\n"; + return false; + } + for (int i=0; ipixelcount) { + std::cerr << "Too many pixels read\n"; + return false; + } + } + } + } while (currentpixel < pixelcount); + return true; +} + +bool TGAImage::write_tga_file(const char *filename, bool rle) { + unsigned char developer_area_ref[4] = {0, 0, 0, 0}; + unsigned char extension_area_ref[4] = {0, 0, 0, 0}; + unsigned char footer[18] = {'T','R','U','E','V','I','S','I','O','N','-','X','F','I','L','E','.','\0'}; + std::ofstream out; + out.open (filename, std::ios::binary); + if (!out.is_open()) { + std::cerr << "can't open file " << filename << "\n"; + out.close(); + return false; + } + TGA_Header header; + memset((void *)&header, 0, sizeof(header)); + header.bitsperpixel = bytespp<<3; + header.width = width; + header.height = height; + header.datatypecode = (bytespp==GRAYSCALE?(rle?11:3):(rle?10:2)); + header.imagedescriptor = 0x20; // top-left origin + out.write((char *)&header, sizeof(header)); + if (!out.good()) { + out.close(); + std::cerr << "can't dump the tga file\n"; + return false; + } + if (!rle) { + out.write((char *)data, width*height*bytespp); + if (!out.good()) { + std::cerr << "can't unload raw data\n"; + out.close(); + return false; + } + } else { + if (!unload_rle_data(out)) { + out.close(); + std::cerr << "can't unload rle data\n"; + return false; + } + } + out.write((char *)developer_area_ref, sizeof(developer_area_ref)); + if (!out.good()) { + std::cerr << "can't dump the tga file\n"; + out.close(); + return false; + } + out.write((char *)extension_area_ref, sizeof(extension_area_ref)); + if (!out.good()) { + std::cerr << "can't dump the tga file\n"; + out.close(); + return false; + } + out.write((char *)footer, sizeof(footer)); + if (!out.good()) { + std::cerr << "can't dump the tga file\n"; + out.close(); + return false; + } + out.close(); + return true; +} + +// TODO: it is not necessary to break a raw chunk for two equal pixels (for the matter of the resulting size) +bool TGAImage::unload_rle_data(std::ofstream &out) { + const unsigned char max_chunk_length = 128; + unsigned long npixels = width*height; + unsigned long curpix = 0; + while (curpix=width || y>=height) { + return TGAColor(); + } + return TGAColor(data+(x+y*width)*bytespp, bytespp); +} + +bool TGAImage::set(int x, int y, TGAColor &c) { + if (!data || x<0 || y<0 || x>=width || y>=height) { + return false; + } + memcpy(data+(x+y*width)*bytespp, c.bgra, bytespp); + return true; +} + +bool TGAImage::set(int x, int y, const TGAColor &c) { + if (!data || x<0 || y<0 || x>=width || y>=height) { + return false; + } + memcpy(data+(x+y*width)*bytespp, c.bgra, bytespp); + return true; +} + +int TGAImage::get_bytespp() { + return bytespp; +} + +int TGAImage::get_width() { + return width; +} + +int TGAImage::get_height() { + return height; +} + +bool TGAImage::flip_horizontally() { + if (!data) return false; + int half = width>>1; + for (int i=0; i>1; + for (int j=0; j=(int)width) { + errx -= width; + nx += bytespp; + memcpy(tdata+nscanline+nx, data+oscanline+ox, bytespp); + } + } + erry += h; + oscanline += olinebytes; + while (erry>=(int)height) { + if (erry>=(int)height<<1) // it means we jump over a scanline + memcpy(tdata+nscanline+nlinebytes, tdata+nscanline, nlinebytes); + erry -= height; + nscanline += nlinebytes; + } + } + delete [] data; + data = tdata; + width = w; + height = h; + return true; +} + diff --git a/examples/TinyRenderer/tgaimage.h b/examples/TinyRenderer/tgaimage.h new file mode 100644 index 000000000..63a944bca --- /dev/null +++ b/examples/TinyRenderer/tgaimage.h @@ -0,0 +1,98 @@ +#ifndef __IMAGE_H__ +#define __IMAGE_H__ + +#include + +#pragma pack(push,1) +struct TGA_Header { + char idlength; + char colormaptype; + char datatypecode; + short colormaporigin; + short colormaplength; + char colormapdepth; + short x_origin; + short y_origin; + short width; + short height; + char bitsperpixel; + char imagedescriptor; +}; +#pragma pack(pop) + +struct TGAColor { + unsigned char bgra[4]; + unsigned char bytespp; + + TGAColor() : bgra(), bytespp(1) { + for (int i=0; i<4; i++) bgra[i] = 0; + } + + TGAColor(unsigned char R, unsigned char G, unsigned char B, unsigned char A=255) : bgra(), bytespp(4) { + bgra[0] = B; + bgra[1] = G; + bgra[2] = R; + bgra[3] = A; + } + + TGAColor(unsigned char v) : bgra(), bytespp(1) { + for (int i=0; i<4; i++) bgra[i] = 0; + bgra[0] = v; + } + + + TGAColor(const unsigned char *p, unsigned char bpp) : bgra(), bytespp(bpp) { + for (int i=0; i<(int)bpp; i++) { + bgra[i] = p[i]; + } + for (int i=bpp; i<4; i++) { + bgra[i] = 0; + } + } + + unsigned char& operator[](const int i) { return bgra[i]; } + + TGAColor operator *(float intensity) const { + TGAColor res = *this; + intensity = (intensity>1.f?1.f:(intensity<0.f?0.f:intensity)); + for (int i=0; i<4; i++) res.bgra[i] = bgra[i]*intensity; + return res; + } +}; + +class TGAImage { +protected: + unsigned char* data; + int width; + int height; + int bytespp; + + bool load_rle_data(std::ifstream &in); + bool unload_rle_data(std::ofstream &out); +public: + enum Format { + GRAYSCALE=1, RGB=3, RGBA=4 + }; + + TGAImage(); + TGAImage(int w, int h, int bpp); + TGAImage(const TGAImage &img); + bool read_tga_file(const char *filename); + bool write_tga_file(const char *filename, bool rle=true); + bool flip_horizontally(); + bool flip_vertically(); + bool scale(int w, int h); + TGAColor get(int x, int y); + bool set(int x, int y, TGAColor &c); + bool set(int x, int y, const TGAColor &c); + ~TGAImage(); + TGAImage & operator =(const TGAImage &img); + int get_width(); + int get_height(); + int get_bytespp(); + unsigned char *buffer(); + void clear(); +}; + +#endif //__IMAGE_H__ + From 03bdcc87379c9d72f7341df8f4d0a46cd8df8b85 Mon Sep 17 00:00:00 2001 From: erwin coumans Date: Tue, 26 Apr 2016 20:52:52 -0700 Subject: [PATCH 11/50] patch TinyRenderer so it software-renders in an OpenGL texture, for testing fix texture support: flip texture to make OpenGL happy (lower-left is origin) add path prefix to .obj loader, so materials/textures are loaded ok. --- build3/premake4.lua | 1 + data/floor.mtl | 13 + data/floor.obj | 18 ++ data/floor_diffuse.jpg | Bin 0 -> 29586 bytes data/floor_diffuse.tga | Bin 0 -> 34436 bytes data/floor_nm_tangent.tga | Bin 0 -> 8236 bytes .../ImportObjDemo/ImportObjExample.cpp | 2 +- .../OpenGLWindow/GLInstancingRenderer.cpp | 29 +- examples/TinyRenderer/Makefile | 23 -- examples/TinyRenderer/README.md | 55 ---- examples/TinyRenderer/TinyRenderer.cpp | 172 +++++++++++ examples/TinyRenderer/TinyRenderer.h | 39 +++ examples/TinyRenderer/geometry.h | 11 +- examples/TinyRenderer/main.cpp | 289 ++++++++++++------ examples/TinyRenderer/our_gl.cpp | 27 +- examples/TinyRenderer/our_gl.h | 12 +- 16 files changed, 496 insertions(+), 195 deletions(-) create mode 100644 data/floor.mtl create mode 100644 data/floor.obj create mode 100644 data/floor_diffuse.jpg create mode 100644 data/floor_diffuse.tga create mode 100644 data/floor_nm_tangent.tga delete mode 100644 examples/TinyRenderer/Makefile delete mode 100644 examples/TinyRenderer/README.md create mode 100644 examples/TinyRenderer/TinyRenderer.cpp create mode 100644 examples/TinyRenderer/TinyRenderer.h diff --git a/build3/premake4.lua b/build3/premake4.lua index 7f60a1d0e..108f33473 100644 --- a/build3/premake4.lua +++ b/build3/premake4.lua @@ -181,6 +181,7 @@ include "../examples/OpenGLWindow" include "../examples/ThirdPartyLibs/Gwen" include "../examples/SimpleOpenGL3" + include "../examples/TinyRenderer" include "../examples/HelloWorld" include "../examples/BasicDemo" diff --git a/data/floor.mtl b/data/floor.mtl new file mode 100644 index 000000000..966cc66cc --- /dev/null +++ b/data/floor.mtl @@ -0,0 +1,13 @@ +newmtl floor + Ns 10.0000 + Ni 1.5000 + d 1.0000 + Tr 0.0000 + Tf 1.0000 1.0000 1.0000 + illum 2 + Ka 0.0000 0.0000 0.0000 + Kd 0.5880 0.5880 0.5880 + Ks 0.0000 0.0000 0.0000 + Ke 0.0000 0.0000 0.0000 + map_Ka floor_diffuse.jpg + map_Kd cube.tga diff --git a/data/floor.obj b/data/floor.obj new file mode 100644 index 000000000..176c05363 --- /dev/null +++ b/data/floor.obj @@ -0,0 +1,18 @@ +o +mtllib floor.mtl +v -1 -1 -1 +v 1 -1 -1 +v 1 -1 1 +v -1 -1 1 + +vt 0 0 +vt .25 0 +vt .25 .25 +vt 0 .25 + +vn 0 1 0 +usemtl floor + +f 3/3/1 2/2/1 1/1/1 +f 4/4/1 3/3/1 1/1/1 + diff --git a/data/floor_diffuse.jpg b/data/floor_diffuse.jpg new file mode 100644 index 0000000000000000000000000000000000000000..36a26252dfc8b040d9ec4e716f6f6299a63f702f GIT binary patch literal 29586 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 literal 0 HcmV?d00001 diff --git a/data/floor_nm_tangent.tga b/data/floor_nm_tangent.tga new file mode 100644 index 0000000000000000000000000000000000000000..3b8474e8f3bde3ba8d48cafd553358f90d39bcdb GIT binary patch literal 8236 zcmeI&%L#xm6a>IWj#gk3+C_wbDEPx}Qn~0!dk|(}8(8MJ5lwtak=nSgTGa*&Fu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000RvC+raw<*p@vXWi9j6okJOO9}kiv B)@uL& literal 0 HcmV?d00001 diff --git a/examples/Importers/ImportObjDemo/ImportObjExample.cpp b/examples/Importers/ImportObjDemo/ImportObjExample.cpp index db6ef97e0..26b0e95e8 100644 --- a/examples/Importers/ImportObjDemo/ImportObjExample.cpp +++ b/examples/Importers/ImportObjDemo/ImportObjExample.cpp @@ -101,7 +101,7 @@ void ImportObjSetup::initPhysics() const char* filename = shape.material.diffuse_texname.c_str(); const unsigned char* image=0; - const char* prefix[]={"./","./data/","../data/","../../data/","../../../data/","../../../../data/"}; + const char* prefix[]={ pathPrefix,"./","./data/","../data/","../../data/","../../../data/","../../../../data/"}; int numprefix = sizeof(prefix)/sizeof(const char*); for (int i=0;!image && im_textureHandles.push_back(h); + updateTexture(textureIndex, texels); return textureIndex; } @@ -552,13 +547,31 @@ void GLInstancingRenderer::updateTexture(int textureIndex, const unsigned cha { if (textureIndex>=0) { + + + glActiveTexture(GL_TEXTURE0); b3Assert(glGetError() ==GL_NO_ERROR); InternalTextureHandle& h = m_data->m_textureHandles[textureIndex]; + + //textures need to be flipped for OpenGL... + b3AlignedObjectArray flippedTexels; + flippedTexels.resize(h.m_width* h.m_height * 3); + for (int i = 0; i < h.m_width; i++) + { + for (int j = 0; j < h.m_height; j++) + { + flippedTexels[(i + j*h.m_width) * 3] = texels[(i + (h.m_height-1-j)*h.m_width) * 3]; + flippedTexels[(i + j*h.m_width) * 3+1] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1]; + flippedTexels[(i + j*h.m_width) * 3+2] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1]; + } + } + + glBindTexture(GL_TEXTURE_2D,h.m_glTexture); b3Assert(glGetError() ==GL_NO_ERROR); const GLubyte* image= (const GLubyte*)texels; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, h.m_width,h.m_height,0,GL_RGB,GL_UNSIGNED_BYTE,image); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, h.m_width,h.m_height,0,GL_RGB,GL_UNSIGNED_BYTE,&flippedTexels[0]); b3Assert(glGetError() ==GL_NO_ERROR); glGenerateMipmap(GL_TEXTURE_2D); b3Assert(glGetError() ==GL_NO_ERROR); diff --git a/examples/TinyRenderer/Makefile b/examples/TinyRenderer/Makefile deleted file mode 100644 index 0b0a469b0..000000000 --- a/examples/TinyRenderer/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -SYSCONF_LINK = g++ -CPPFLAGS = -Wall -Wextra -Weffc++ -pedantic -std=c++98 -LDFLAGS = -O3 -LIBS = -lm - -DESTDIR = ./ -TARGET = main - -OBJECTS := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) - -all: $(DESTDIR)$(TARGET) - -$(DESTDIR)$(TARGET): $(OBJECTS) - $(SYSCONF_LINK) -Wall $(LDFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(LIBS) - -$(OBJECTS): %.o: %.cpp - $(SYSCONF_LINK) -Wall $(CPPFLAGS) -c $(CFLAGS) $< -o $@ - -clean: - -rm -f $(OBJECTS) - -rm -f $(TARGET) - -rm -f *.tga - diff --git a/examples/TinyRenderer/README.md b/examples/TinyRenderer/README.md deleted file mode 100644 index 84a125234..000000000 --- a/examples/TinyRenderer/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# Tiny Renderer or how OpenGL works: software renderer in 500 lines of code - -*** - -**Check [the wiki](https://github.com/ssloy/tinyrenderer/wiki/Lesson-1:-Bresenham%E2%80%99s-Line-Drawing-Algorithm) for the detailed lessons. My source code is irrelevant. Read the wiki and implement your own renderer. Only when you suffer through all the tiny details you will learn what is going on.** - -**I do want to get emails for feedback (dmitry.sokolov@univ-lorraine.fr); do not hesitate to contact me if you have any questions.** - -**If you are a teacher and willing to adopt this material for teaching your class your are very welcome, no authorization is needed, simply inform me by mail, it will help me to improve the course.** - -*** - -In this series of articles, I want to show the way OpenGL works by writing its clone (a much simplified one). Surprisingly enough, I often meet people who cannot overcome the initial hurdle of learning OpenGL / DirectX. Thus, I have prepared a short series of lectures, after which my students show quite good renderers. - -So, the task is formulated as follows: using no third-party libraries (especially graphic ones), get something like this picture: - -![](http://haqr.eu/framebuffer.png) - -_Warning: this is a training material that will loosely repeat the structure of the OpenGL library. It will be a software renderer. **I do not want to show how to write applications for OpenGL. I want to show how OpenGL works.** I am deeply convinced that it is impossible to write efficient applications using 3D libraries without understanding this._ - -I will try to make the final code about 500 lines. My students need 10 to 20 programming hours to begin making such renderers. At the input, we get a test file with a polygonal wire + pictures with textures. At the output, we’ll get a rendered model. No graphical interface, the program simply generates an image. - - -Since the goal is to minimize external dependencies, I give my students just one class that allows working with [TGA](http://en.wikipedia.org/wiki/Truevision_TGA) files. It’s one of the simplest formats that supports images in RGB/RGBA/black and white formats. So, as a starting point, we’ll obtain a simple way to work with pictures. You should note that the only functionality available at the very beginning (in addition to loading and saving images) is the capability to set the color of one pixel. - -There are no functions for drawing line segments and triangles. We’ll have to do all of this by hand. I provide my source code that I write in parallel with students. But I would not recommend using it, as this doesn’t make sense. The entire code is available on github, and [here](https://github.com/ssloy/tinyrenderer/tree/909fe20934ba5334144d2c748805690a1fa4c89f) you will find the source code I give to my students. - -```C++ -#include "tgaimage.h" -const TGAColor white = TGAColor(255, 255, 255, 255); -const TGAColor red = TGAColor(255, 0, 0, 255); -int main(int argc, char** argv) { - TGAImage image(100, 100, TGAImage::RGB); - image.set(52, 41, red); - image.flip_vertically(); // i want to have the origin at the left bottom corner of the image - image.write_tga_file("output.tga");` - return 0; -} -``` - -output.tga should look something like this: - -![](http://www.loria.fr/~sokolovd/cg-course/img/2d3b12170b.png) - - - -# Teaser: few examples made with the renderer - -![](https://hsto.org/getpro/habr/post_images/50d/e2a/be9/50de2abe990efa345664f98c9464a4c8.png) - -![](https://hsto.org/getpro/habr/post_images/e3c/d70/492/e3cd704925f52b5466ab3c4f9fbab899.png) - -![](http://www.loria.fr/~sokolovd/cg-course/06-shaders/img/boggie.png) - -![](http://hsto.org/files/1ba/93f/a5a/1ba93fa5a48646e2a9614271c943b4da.png) diff --git a/examples/TinyRenderer/TinyRenderer.cpp b/examples/TinyRenderer/TinyRenderer.cpp new file mode 100644 index 000000000..3370c86fd --- /dev/null +++ b/examples/TinyRenderer/TinyRenderer.cpp @@ -0,0 +1,172 @@ +#include "TinyRenderer.h" + +#include +#include +#include +#include "TinyRenderer/tgaimage.h" +#include "TinyRenderer/model.h" +#include "TinyRenderer/geometry.h" +#include "TinyRenderer/our_gl.h" +#include "../../Utils/b3ResourcePath.h" +#include "Bullet3Common/b3MinMax.h" + +Vec3f light_dir_world(1,1,1); + + +struct Shader : public IShader { + + Model* m_model; + Vec3f m_light_dir_local; + Matrix& m_modelView; + Matrix& m_projectionMatrix; + + mat<2,3,float> varying_uv; // triangle uv coordinates, written by the vertex shader, read by the fragment shader + mat<4,3,float> varying_tri; // triangle coordinates (clip coordinates), written by VS, read by FS + mat<3,3,float> varying_nrm; // normal per vertex to be interpolated by FS + mat<3,3,float> ndc_tri; // triangle in normalized device coordinates + + Shader(Model* model, Vec3f light_dir_local, Matrix& modelView, Matrix& projectionMatrix) + :m_model(model), + m_light_dir_local(light_dir_local), + m_modelView(modelView), + m_projectionMatrix(projectionMatrix) + { + + } + + virtual Vec4f vertex(int iface, int nthvert) { + varying_uv.set_col(nthvert, m_model->uv(iface, nthvert)); + varying_nrm.set_col(nthvert, proj<3>((m_projectionMatrix*m_modelView).invert_transpose()*embed<4>(m_model->normal(iface, nthvert), 0.f))); + Vec4f gl_Vertex = m_projectionMatrix*m_modelView*embed<4>(m_model->vert(iface, nthvert)); + varying_tri.set_col(nthvert, gl_Vertex); + ndc_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3])); + return gl_Vertex; + } + + virtual bool fragment(Vec3f bar, TGAColor &color) { + Vec3f bn = (varying_nrm*bar).normalize(); + Vec2f uv = varying_uv*bar; + + mat<3,3,float> A; + A[0] = ndc_tri.col(1) - ndc_tri.col(0); + A[1] = ndc_tri.col(2) - ndc_tri.col(0); + A[2] = bn; + + mat<3,3,float> AI = A.invert(); + + Vec3f i = AI * Vec3f(varying_uv[0][1] - varying_uv[0][0], varying_uv[0][2] - varying_uv[0][0], 0); + Vec3f j = AI * Vec3f(varying_uv[1][1] - varying_uv[1][0], varying_uv[1][2] - varying_uv[1][0], 0); + + mat<3,3,float> B; + B.set_col(0, i.normalize()); + B.set_col(1, j.normalize()); + B.set_col(2, bn); + + Vec3f n = (B*m_model->normal(uv)).normalize(); + + float diff = b3Min(b3Max(0.f, n*m_light_dir_local+0.6f),1.f); + color = m_model->diffuse(uv)*diff; + + return false; + } +}; + +/* +struct TinyRenderObjectData +{ + //Camera + Matrix m_viewMatrix; + Matrix m_projectionMatrix; + Matrix m_viewPortMatrix; + + //Model (vertices, indices, textures, shader) + Matrix m_modelMatrix; + class Model* m_model; + class IShader* m_shader; + + + //Output + TGAImage m_rgbColorBuffer; + b3AlignedObjectArray m_depthBuffer; +}; +*/ + +TinyRenderObjectData::TinyRenderObjectData(int width, int height, const char* fileName) +:m_width(width), +m_height(height), +m_rgbColorBuffer(width,height,TGAImage::RGB), +m_model(0) +{ + Vec3f eye(1,1,3); + Vec3f center(0,0,0); + Vec3f up(0,1,0); + + m_viewMatrix = lookat(eye, center, up); + m_viewportMatrix = viewport(width/8, height/8, width*3/4, height*3/4); + m_projectionMatrix = projection(-1.f/(eye-center).norm()); + + + m_depthBuffer.resize(width*height); + //todo(erwincoumans) move the file loading out of here + char relativeFileName[1024]; + if (!b3ResourcePath::findResourcePath(fileName, relativeFileName, 1024)) + { + printf("Cannot find file %s\n", fileName); + } else + { + m_model = new Model(relativeFileName); + } + + +} + +TinyRenderObjectData::~TinyRenderObjectData() +{ + delete m_model; +} + +void TinyRenderer::renderObject(TinyRenderObjectData& renderData) +{ + const char* fileName = "obj/floor.obj"; + + + +//new Model(relativeFileName);//argv[m]); + Model* model = renderData.m_model; + if (0==model) + return; + + const int width = renderData.m_width; + const int height = renderData.m_height; + b3AlignedObjectArray& zbuffer = renderData.m_depthBuffer; + + //todo(erwincoumans) make this a separate call + for (int i=width*height; i--; zbuffer[i] = -std::numeric_limits::max()); + + TGAImage& frame = renderData.m_rgbColorBuffer; + + //lookat(eye, center, up); + //viewport(width/8, height/8, width*3/4, height*3/4); + //projection(-1.f/(eye-center).norm()); + + Vec3f light_dir_local = proj<3>((renderData.m_projectionMatrix*renderData.m_viewMatrix*embed<4>(light_dir_world, 0.f))).normalize(); + + { + //for (int m=1; mnfaces(); i++) { + for (int j=0; j<3; j++) { + shader.vertex(i, j); + } + triangle(shader.varying_tri, shader, frame, &zbuffer[0], renderData.m_viewportMatrix); + } + + } + //frame.flip_vertically(); // to place the origin in the bottom left corner of the image + //frame.write_tga_file("framebuffer.tga"); + + +} + + diff --git a/examples/TinyRenderer/TinyRenderer.h b/examples/TinyRenderer/TinyRenderer.h new file mode 100644 index 000000000..1bcd49b95 --- /dev/null +++ b/examples/TinyRenderer/TinyRenderer.h @@ -0,0 +1,39 @@ +#ifndef TINY_RENDERER_H +#define TINY_RENDERER_H + +//#include "TinyRenderer/our_gl.h" +#include "TinyRenderer/geometry.h" +#include "Bullet3Common/b3AlignedObjectArray.h" +#include "TinyRenderer/tgaimage.h" + +struct TinyRenderObjectData +{ + //Camera + Matrix m_viewMatrix; + Matrix m_projectionMatrix; + Matrix m_viewportMatrix; + + //Model (vertices, indices, textures, shader) + Matrix m_modelMatrix; + class Model* m_model; + //class IShader* m_shader; todo(erwincoumans) expose the shader, for now we use a default shader + + //Output + int m_width; + int m_height; + TGAImage m_rgbColorBuffer; + b3AlignedObjectArray m_depthBuffer; + + TinyRenderObjectData(int width, int height, const char* objFileName); + virtual ~TinyRenderObjectData(); + +}; + + +class TinyRenderer +{ + public: + static void renderObject(TinyRenderObjectData& renderData); +}; + +#endif // TINY_RENDERER_Hbla diff --git a/examples/TinyRenderer/geometry.h b/examples/TinyRenderer/geometry.h index 46ee7b354..38bb4d935 100644 --- a/examples/TinyRenderer/geometry.h +++ b/examples/TinyRenderer/geometry.h @@ -1,9 +1,9 @@ #ifndef __GEOMETRY_H__ #define __GEOMETRY_H__ #include -#include #include -#include +#include + template class mat; @@ -85,14 +85,14 @@ template vec proj(const vec &v) template vec<3,T> cross(vec<3,T> v1, vec<3,T> v2) { return vec<3,T>(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x); } - +#if 0 template std::ostream& operator<<(std::ostream& out, vec& v) { for(unsigned int i=0; i struct dt { @@ -204,11 +204,12 @@ templatemat operato return lhs; } +#if 0 template std::ostream& operator<<(std::ostream& out, mat& m) { for (size_t i=0; i Vec2f; diff --git a/examples/TinyRenderer/main.cpp b/examples/TinyRenderer/main.cpp index 8ce61dda2..7a9de8fef 100644 --- a/examples/TinyRenderer/main.cpp +++ b/examples/TinyRenderer/main.cpp @@ -1,94 +1,209 @@ -#include -#include -#include -#include "tgaimage.h" -#include "model.h" -#include "geometry.h" -#include "our_gl.h" +#include "OpenGLWindow/SimpleOpenGL3App.h" +#include "Bullet3Common/b3Quaternion.h" +#include "Bullet3Common/b3CommandLineArgs.h" +#include "assert.h" +#include -Model *model = NULL; +char* gVideoFileName = 0; +char* gPngFileName = 0; -const int width = 800; -const int height = 800; +static b3WheelCallback sOldWheelCB = 0; +static b3ResizeCallback sOldResizeCB = 0; +static b3MouseMoveCallback sOldMouseMoveCB = 0; +static b3MouseButtonCallback sOldMouseButtonCB = 0; +static b3KeyboardCallback sOldKeyboardCB = 0; +//static b3RenderCallback sOldRenderCB = 0; -Vec3f light_dir(1,1,1); -Vec3f eye(1,1,3); -Vec3f center(0,0,0); -Vec3f up(0,1,0); +float gWidth = 0 ; +float gHeight = 0; -struct Shader : public IShader { - mat<2,3,float> varying_uv; // triangle uv coordinates, written by the vertex shader, read by the fragment shader - mat<4,3,float> varying_tri; // triangle coordinates (clip coordinates), written by VS, read by FS - mat<3,3,float> varying_nrm; // normal per vertex to be interpolated by FS - mat<3,3,float> ndc_tri; // triangle in normalized device coordinates +void MyWheelCallback(float deltax, float deltay) +{ + if (sOldWheelCB) + sOldWheelCB(deltax,deltay); +} +void MyResizeCallback( float width, float height) +{ + gWidth = width; + gHeight = height; + + if (sOldResizeCB) + sOldResizeCB(width,height); +} +void MyMouseMoveCallback( float x, float y) +{ + printf("Mouse Move: %f, %f\n", x,y); - virtual Vec4f vertex(int iface, int nthvert) { - varying_uv.set_col(nthvert, model->uv(iface, nthvert)); - varying_nrm.set_col(nthvert, proj<3>((Projection*ModelView).invert_transpose()*embed<4>(model->normal(iface, nthvert), 0.f))); - Vec4f gl_Vertex = Projection*ModelView*embed<4>(model->vert(iface, nthvert)); - varying_tri.set_col(nthvert, gl_Vertex); - ndc_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3])); - return gl_Vertex; - } - - virtual bool fragment(Vec3f bar, TGAColor &color) { - Vec3f bn = (varying_nrm*bar).normalize(); - Vec2f uv = varying_uv*bar; - - mat<3,3,float> A; - A[0] = ndc_tri.col(1) - ndc_tri.col(0); - A[1] = ndc_tri.col(2) - ndc_tri.col(0); - A[2] = bn; - - mat<3,3,float> AI = A.invert(); - - Vec3f i = AI * Vec3f(varying_uv[0][1] - varying_uv[0][0], varying_uv[0][2] - varying_uv[0][0], 0); - Vec3f j = AI * Vec3f(varying_uv[1][1] - varying_uv[1][0], varying_uv[1][2] - varying_uv[1][0], 0); - - mat<3,3,float> B; - B.set_col(0, i.normalize()); - B.set_col(1, j.normalize()); - B.set_col(2, bn); - - Vec3f n = (B*model->normal(uv)).normalize(); - - float diff = std::max(0.f, n*light_dir); - color = model->diffuse(uv)*diff; - - return false; - } -}; - -int main(int argc, char** argv) { - if (2>argc) { - std::cerr << "Usage: " << argv[0] << " obj/model.obj" << std::endl; - return 1; - } - - float *zbuffer = new float[width*height]; - for (int i=width*height; i--; zbuffer[i] = -std::numeric_limits::max()); - - TGAImage frame(width, height, TGAImage::RGB); - lookat(eye, center, up); - viewport(width/8, height/8, width*3/4, height*3/4); - projection(-1.f/(eye-center).norm()); - light_dir = proj<3>((Projection*ModelView*embed<4>(light_dir, 0.f))).normalize(); - - for (int m=1; mnfaces(); i++) { - for (int j=0; j<3; j++) { - shader.vertex(i, j); - } - triangle(shader.varying_tri, shader, frame, zbuffer); - } - delete model; - } - frame.flip_vertically(); // to place the origin in the bottom left corner of the image - frame.write_tga_file("framebuffer.tga"); - - delete [] zbuffer; - return 0; + if (sOldMouseMoveCB) + sOldMouseMoveCB(x,y); +} +void MyMouseButtonCallback(int button, int state, float x, float y) +{ + if (sOldMouseButtonCB) + sOldMouseButtonCB(button,state,x,y); } + +void MyKeyboardCallback(int keycode, int state) +{ + //keycodes are in examples/CommonInterfaces/CommonWindowInterface.h + //for example B3G_ESCAPE for escape key + //state == 1 for pressed, state == 0 for released. + // use app->m_window->isModifiedPressed(...) to check for shift, escape and alt keys + printf("MyKeyboardCallback received key:%c in state %d\n",keycode,state); + if (sOldKeyboardCB) + sOldKeyboardCB(keycode,state); +} +#include "TinyRenderer.h" + +int main(int argc, char* argv[]) +{ + b3CommandLineArgs myArgs(argc,argv); + + + + SimpleOpenGL3App* app = new SimpleOpenGL3App("SimpleOpenGL3App",640,480,true); + + app->m_instancingRenderer->getActiveCamera()->setCameraDistance(13); + app->m_instancingRenderer->getActiveCamera()->setCameraPitch(0); + app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(0,0,0); + sOldKeyboardCB = app->m_window->getKeyboardCallback(); + app->m_window->setKeyboardCallback(MyKeyboardCallback); + sOldMouseMoveCB = app->m_window->getMouseMoveCallback(); + app->m_window->setMouseMoveCallback(MyMouseMoveCallback); + sOldMouseButtonCB = app->m_window->getMouseButtonCallback(); + app->m_window->setMouseButtonCallback(MyMouseButtonCallback); + sOldWheelCB = app->m_window->getWheelCallback(); + app->m_window->setWheelCallback(MyWheelCallback); + sOldResizeCB = app->m_window->getResizeCallback(); + app->m_window->setResizeCallback(MyResizeCallback); + + int textureWidth = gWidth; + int textureHeight = gHeight; + + TinyRenderObjectData renderData(textureWidth, textureHeight, "african_head/african_head.obj");//floor.obj"); + + + + myArgs.GetCmdLineArgument("mp4_file",gVideoFileName); + if (gVideoFileName) + app->dumpFramesToVideo(gVideoFileName); + + myArgs.GetCmdLineArgument("png_file",gPngFileName); + char fileName[1024]; + + + + unsigned char* image=new unsigned char[textureWidth*textureHeight*4]; + + + int textureHandle = app->m_renderer->registerTexture(image,textureWidth,textureHeight); + + int cubeIndex = app->registerCubeShape(1,1,1); + + b3Vector3 pos = b3MakeVector3(0,0,0); + b3Quaternion orn(0,0,0,1); + b3Vector3 color=b3MakeVector3(1,0,0); + b3Vector3 scaling=b3MakeVector3 (1,1,1); + app->m_renderer->registerGraphicsInstance(cubeIndex,pos,orn,color,scaling); + app->m_renderer->writeTransforms(); + + do + { + static int frameCount = 0; + frameCount++; + if (gPngFileName) + { + printf("gPngFileName=%s\n",gPngFileName); + + sprintf(fileName,"%s%d.png",gPngFileName,frameCount++); + app->dumpNextFrameToPng(fileName); + } + + app->m_instancingRenderer->init(); + app->m_instancingRenderer->updateCamera(); + + float projMat[16]; + app->m_instancingRenderer->getActiveCamera()->getCameraProjectionMatrix(projMat); + float viewMat[16]; + app->m_instancingRenderer->getActiveCamera()->getCameraViewMatrix(viewMat); + for (int i=0;i<4;i++) + { + for (int j=0;j<4;j++) + { + renderData.m_viewMatrix[i][j] = viewMat[i+4*j]; + //renderData.m_projectionMatrix[i][j] = projMat[i+4*j]; + } + } + + for(int y=0;y>4; + unsigned char* pi=image+y*textureWidth*3; + for(int x=0;x>4; + const unsigned char b=180; + unsigned char c=b+((s+(t&1))&1)*(255-b); + pi[0]=pi[1]=pi[2]=pi[3]=c;pi+=3; + } + } + #endif + + + app->m_renderer->activateTexture(textureHandle); + app->m_renderer->updateTexture(textureHandle,image); + + float color[4] = {1,1,1,1}; + app->m_primRenderer->drawTexturedRect(0,0,gWidth/3,gHeight/3,color,0,0,1,1,true); + + + + app->m_renderer->renderScene(); + app->drawGrid(); + char bla[1024]; + sprintf(bla,"Simple test frame %d", frameCount); + + app->drawText(bla,10,10); + app->swapBuffer(); + } while (!app->m_window->requestedExit()); + + + delete app; + return 0; +} diff --git a/examples/TinyRenderer/our_gl.cpp b/examples/TinyRenderer/our_gl.cpp index 3772c984a..4c99c0685 100644 --- a/examples/TinyRenderer/our_gl.cpp +++ b/examples/TinyRenderer/our_gl.cpp @@ -2,14 +2,16 @@ #include #include #include "our_gl.h" +#include "Bullet3Common/b3MinMax.h" + + -Matrix ModelView; -Matrix Viewport; -Matrix Projection; IShader::~IShader() {} -void viewport(int x, int y, int w, int h) { +Matrix viewport(int x, int y, int w, int h) +{ + Matrix Viewport; Viewport = Matrix::identity(); Viewport[0][3] = x+w/2.f; Viewport[1][3] = y+h/2.f; @@ -17,14 +19,17 @@ void viewport(int x, int y, int w, int h) { Viewport[0][0] = w/2.f; Viewport[1][1] = h/2.f; Viewport[2][2] = 0; + return Viewport; } -void projection(float coeff) { +Matrix projection(float coeff) { + Matrix Projection; Projection = Matrix::identity(); Projection[3][2] = coeff; + return Projection; } -void lookat(Vec3f eye, Vec3f center, Vec3f up) { +Matrix lookat(Vec3f eye, Vec3f center, Vec3f up) { Vec3f z = (eye-center).normalize(); Vec3f x = cross(up,z).normalize(); Vec3f y = cross(z,x).normalize(); @@ -36,7 +41,9 @@ void lookat(Vec3f eye, Vec3f center, Vec3f up) { Minv[2][i] = z[i]; Tr[i][3] = -center[i]; } + Matrix ModelView; ModelView = Minv*Tr; + return ModelView; } Vec3f barycentric(Vec2f A, Vec2f B, Vec2f C, Vec2f P) { @@ -52,8 +59,8 @@ Vec3f barycentric(Vec2f A, Vec2f B, Vec2f C, Vec2f P) { return Vec3f(-1,1,1); // in this case generate negative coordinates, it will be thrown away by the rasterizator } -void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zbuffer) { - mat<3,4,float> pts = (Viewport*clipc).transpose(); // transposed to ease access to each of the points +void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix) { + mat<3,4,float> pts = (viewPortMatrix*clipc).transpose(); // transposed to ease access to each of the points mat<3,2,float> pts2; for (int i=0; i<3; i++) pts2[i] = proj<2>(pts[i]/pts[i][3]); @@ -62,8 +69,8 @@ void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zb Vec2f clamp(image.get_width()-1, image.get_height()-1); for (int i=0; i<3; i++) { for (int j=0; j<2; j++) { - bboxmin[j] = std::max(0.f, std::min(bboxmin[j], pts2[i][j])); - bboxmax[j] = std::min(clamp[j], std::max(bboxmax[j], pts2[i][j])); + bboxmin[j] = b3Max(0.f, b3Min(bboxmin[j], pts2[i][j])); + bboxmax[j] = b3Min(clamp[j], b3Max(bboxmax[j], pts2[i][j])); } } Vec2i P; diff --git a/examples/TinyRenderer/our_gl.h b/examples/TinyRenderer/our_gl.h index bc8ed7312..d80156904 100644 --- a/examples/TinyRenderer/our_gl.h +++ b/examples/TinyRenderer/our_gl.h @@ -3,12 +3,12 @@ #include "tgaimage.h" #include "geometry.h" -extern Matrix ModelView; -extern Matrix Projection; -void viewport(int x, int y, int w, int h); -void projection(float coeff=0.f); // coeff = -1/c -void lookat(Vec3f eye, Vec3f center, Vec3f up); + + +Matrix viewport(int x, int y, int w, int h); +Matrix projection(float coeff=0.f); // coeff = -1/c +Matrix lookat(Vec3f eye, Vec3f center, Vec3f up); struct IShader { virtual ~IShader(); @@ -17,6 +17,6 @@ struct IShader { }; //void triangle(Vec4f *pts, IShader &shader, TGAImage &image, float *zbuffer); -void triangle(mat<4,3,float> &pts, IShader &shader, TGAImage &image, float *zbuffer); +void triangle(mat<4,3,float> &pts, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix); #endif //__OUR_GL_H__ From 40841e907805e743e67e1192fd1f8f2d8ab555b0 Mon Sep 17 00:00:00 2001 From: erwin coumans Date: Tue, 26 Apr 2016 21:01:46 -0700 Subject: [PATCH 12/50] revert floor.obj test file, load it by default in TinyRenderer/main.cpp --- data/floor.mtl | 2 +- data/floor.obj | 6 +++--- data/floor_diffuse.tga | Bin 34436 -> 326988 bytes examples/TinyRenderer/main.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/data/floor.mtl b/data/floor.mtl index 966cc66cc..8a67048e1 100644 --- a/data/floor.mtl +++ b/data/floor.mtl @@ -10,4 +10,4 @@ newmtl floor Ks 0.0000 0.0000 0.0000 Ke 0.0000 0.0000 0.0000 map_Ka floor_diffuse.jpg - map_Kd cube.tga + map_Kd floor_diffuse.jpg diff --git a/data/floor.obj b/data/floor.obj index 176c05363..42e145867 100644 --- a/data/floor.obj +++ b/data/floor.obj @@ -6,9 +6,9 @@ v 1 -1 1 v -1 -1 1 vt 0 0 -vt .25 0 -vt .25 .25 -vt 0 .25 +vt 1 0 +vt 1 1 +vt 0 1 vn 0 1 0 usemtl floor diff --git a/data/floor_diffuse.tga b/data/floor_diffuse.tga index cf5e31f92c120b2cab997737569d544aafa2d241..7bb70dd10c100d6d7a2f29336d877af632ac5d82 100644 GIT binary patch literal 326988 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 literal 34436 zcmeI5OKc?9b%y)FM@M$zmKO$LWFf8sB1nK)&X#}!cn~DUI0*vo0&Wrzh=VXY?q(>7 zBU7W1L`frw(#Q|`DaudUmOSI^xa5+{Ms~gIWiKn=f6l#i>vmO<&6%-{AXA{atM2Rk z=Rc2o>sIxs(|N8_9^FoNrPD1qrp0H)r0Da_S8=4zLyG%;O%W&WQ_w4`Kk%zbad1#f zCSG?|6e~q>R@|emL!bMMqwhDY?YJne7sYDvn_{h4;Jdh~w%+4yS}Y>wv?%tAVxuT- zSmRr?T3WMH3O0-4z?#tTEgLd+cQ8jsMW<679pzwNvzEoED6SzLL2Ess(ADU5t7AAW z2F0g_cEFzX16HTt=mv7_4g8*-Qs(J5{3gG$j^(ymCcdu>-Z`9Z>3W{G*b=la-di1Cm3?!bqQPK)HlmBhWFH1XeH_h)2YWVf-Vgex7*!)DI22_DZ$Lp zZ~?c1pSb;L;?^soiwauM;D_SY;pd{&WGa9fNT&ECnL_#{l)~I4o1w|a!I>~IVVE~lG%Ob6i87U8 zmho7*hG0J`^@0D>QFaZ%*f zQ}$UbAlt$5iHROPQgN4=w5rVEp*KE0mI1vz6r7yMx{1ZdQO1nJ95yIEPR7Yy$Y8Tb zuvW!S`;dCmXU9WMMqi$k$y}6;h z%k}H%`Q%!qSo%>iS018Lp^LW>KtD&ZWfa76*e@J0{VConQPUS(yzB4~bD0Y(c80^< zl;Tv%3VNzUj+H9ersSL>ExQR;P4H0Xubq0cYSYl&}Wn{ZT>>ItHG zli)C&|-ty-ZK$mkQ+ zR?%?ZPll6^E>;caR{NE#M&EUhv8a_tfMxd=0l6UTUw_HQ3{O$sV#&2HSJquYs)_JE>g7Oo9m+TyTtAqG34Hm8A$KQHy=A z<`hFrr;iOd#mG^jx`r8Yq1Z6;&3Qv zT~T*(BHyUt0s)wWvKoti)PGiz;qAa z)tY=bJTPFm-Oi4Lwg5Z(sr4vtWfBl&l)%up6GNI05|)~Xf>VI za-O`zed%I=iKYjMrW_-%e+x~$bwb1JwFkgu&90b?+XwubEX}k+>BsqXq3~OBtZ0ryVGzR#uT%azv&E^cEioHpvShh=Q)I5J z2q<>x==<|BGo?-{?I6{s9b|eG&u#WFQHTA64-%`5NCzEU;Y?5jZUx zB@K{tP6$Hp?@x1|e>au=-ZRZ{kOPab;C@N-UTF!f1^=)<<1j5NJ4}3c(gL$|?LSf& z-ZN)1O7AC1E0fvyTvMur;q{m@{$M%H(HWDD&X}yABk5x3m~?MOfS&hHP6#{C`(&=u zQ%&4g&Qm_y8$rzW1fKbvfR#h(RxCo;jZ=?rsFQifn1ew%4U(3|whkzJ&l~m*gx0Ht z10fhE_Ru0t$=lhKd>W@@b+sEPGGb+Iu(g$`F)t8bW*8$ZGhhV&IIvYw0>VukJlWa+ z`;;pb*MYnkmrk}YuGn+_+~g>X4o6{hNI*h?Ex=|dNKGO2`-7gICR_4yWqCZQ}Y;cj5GetFuCM*oxh5 zD#{hRO(HK@4!5Zp=;d<7!?)VL!@Xy|P z`{S2*=dC9N9MOBkUAlKF_X)1PvtSGM%Gz;$P2K`Ru*BVD3E5{>6F_5A(**CtraGb~ zV$re|-W~Tya3gY9-1fnp;vNYV=jXSr2Ma0IRh4a@?d?nrvcftsrbl6M6Jf@&Zk6t4 zA=0fChO5T zYADv1eG>?Cprigc!8&oLm1X(rs_)NHasB$s)+KJ9q%LH<(dZ79iDaco5&^<4RnYGE zTrHlZM72n^;~BN&K;3OKob4Z@`SI-jv6x;i?{9-jxL@m*_{PSbbwO9QRcPr%xGVcE z`jcrzkl2&_AsZX=NKkK^71OY$81aR({uIC0UO!pH<0YC)^e*W}5R`5%KFJ&L@dfuX zad()Cg98z<$df0ZMx_-h9UMs6B>1XUdWYU@9BL|bWz0&lT^dty&^1H)gA0@*rt8Wq z`s1U346WvWs$^+g&X}Y=jwZ=6d&x3VF%4@EpGb9BCmzB%ZnL@iA&(id?$Xur!QES9ITE_idQddpDet z{PRi2!P&Y)kqE@o(#EMDx2^(zj?ehZ$JAm?Z&NXO!W$6v_LBBuY0KJ&3Cc8>u`*Mlr!?mG$s`}K5#hgn!m#Yo-S%7?2kc0Z3$K_O)sJ&e6= zuSups-=KPlB`ro=H=u4pTD}4xJqV)!{8VB~s1oI=yHmx&6-G`XRwW~+ebx^i@%@qHPbf8B-*Cxe?l4JUw(U-J^D#wtjtCLZ& zezVx#_p7`P9mo{t;}2*lZ95=%h|QJ%d^=Z5uP@*^SOZVx^$VEBUjfS>#QO<3opQ#; zi)bnPCI1lZ3)+OYtuW=K-QC<2-a?%j5zC_1iA-0ABl9lO4rwS{`srTqQ(&VxgU}Ac z%CQp;<(H*|18?Qe(Bzp%SIed=)G{Jt^NB2k+B?H_SPBTe3CzA1gp{!ECRmg~8-4_r zuVt{_wW~;v-wYWluYh$_IxFtetZ(f44GOO{#O;q8C@au)T#}^Mp-BKfbLb^k85fEO zy}Ks5Dxp{Mqs=9Iwz<12(TT=)>`L@1k+QDo^n&LWr-EEZVPa4nY7qS{5HvIJ2O|ul zxnp+tNXN?wh0Bd#<(J6C74U<>UWo#(PK39P!ocB>9$V|UYvR4ISTTeTA5pxTPpJ1VtadfNep+UV8;L#Np7>%n4 z;q?T;DSq(9HZZ}O~ZQX45CJ=7XM&G&(#fS3yH`g)Z&|~3{AG{*sxLd_xzYzcx z;|hmb)~OJV@Y3#U2>%lrBcD%#nLjwhGIZyha$!`n##?14A!2+dVf2cK@m0r&?r=4D z&$$X1)v}J!?$b{U)vE~qqGQB`w=BDo-LNIx`@z7Rlbpy8I0Hh+5@6>~y_I-qP6n@d zn)4Q+znh?YMHPD2-|Zr+hhQV8*vraw+{{@lQ!Lo_ksN+)0hvtY6e}q%u%hD|U4VsN zYS#gB4$moz@ZOK`_V>La!qb4jL+tRw5+3H8s96g<8YA|bh}B|-KPUs+J$m%PwjCWo zEwpt7skf+0bB2UkklND)p3>u)+?(xl7g=ql3=B33haWjM?17>aHLGKj{^6xdNmjOo zBe!VL1Ec$+*2sDxlPJRM;fQqj+yZNc>_I~26|tGJGRQRMw@YMX5_`3;1sR}`D(L|k z?zYD`9Z=kYzB`=jmJyWvshwW0#8Jahm7U1r{hCOgO%+=8(fusEiKZ3K@Vf{BEqv@t zjXFMAM^1++4Igqj1&h4#&!}Kf;Nup=Hk?xFpZFy-qB!13fS`$bh-;bzZ5OdvII7r^ z3cNQJRWJ@p6~s>0!gA$%r3%MVvqc4ucd4Lc112f92r2{v(lG%`%g+#5=t1HP!L7Yy zI%}5prHr5*W^AUE-m@qclpi{1Mjh=@5kboz!%HI) zp*zdysXziL2hIZ1G~`dW$Ld3)fXe)X5@{M<*i@$+MFh(WyAiCzt2VieRT08#%f0w`4#^fkfy6&?zVZYF0@upx1*!;_`|JP*(sX-w!@60W!Az zkfRMCK@$MVHIL2xRSSfc zUc$8usB%UGi<_#iw%Qt#yDsd?tmp+*mQTKZ%c)WT$jn)bQTc&^0u=qfjfr*ibQcJ z<>AAM1bU4{`z5Ld<-QXH3cz9#$PUh`-o}(bv+U+hMIcFM_$!wN)}vNwZce>%vXq&R z-E1~thePpa@1yd(0u`NHsk8eVMyK2Q978Xod&YhoU7lgDJu*7mzR@#mW?GeizL_^n zk&SdQGQjVFB+Ruy#8vpS6)Vc$;#|Ke9#kV#DsV&~3J?1+f&-x@Vc~4>DOh^t1k(nD zgrIwn@IxF=u1r{)W^s_ng3F)*B3Kv~*C|&qns=qbQAN18?Uf*vM{q8C1V6P>ckPG_z$GoJPRNvVd)hTK`h+^ZE~P%#126_g zTnTJ;qK7Fk*_{yIuxC>Uwx{3A2{DP#Dl{>BbN#wO10##3XTCZtSc21{Z zz{XIdgH~(`r+|%bt^}b66ey&ten78i#i}+d1D-26pe8vo8!bzCYLTeZ^q$~p*a&X~ zph1GCs%TSrSas@Tc%KF&Qb6F+NJ2x>qS(_~btAx|ssfMYsE)|qOPnWoS{@~Mf*#?G zaij`7g?NM~-*R|z1^ucyh!ZqG7&QDGYekPkx_KOcS&qmFv^K{7bVO)cc_nCCW+rHY z9idG%!T%OK0v0T2}eY^$8|!f z6?{S|4I;|PWh9H1oHqSG6G;E0uK2U$MrZ@3_*<-tF^+5I1WbycZcf)PB%pf zoPbAgWBEv+Pzj|499$q#Nly**!+QN27w{C0DE1YulUUtOCb5E4ip5tdA&IXvNH+JO z3W@Q(6}rjQ(#^kaL6g7-nLvSw0%wAZ0B#fLiO2-PGk%Z@)V)U%sNII7p}<6eJXxt~ zNcwLOXh}rzRTQ7VsbZI8Aa_U_zFHAD7-;Jy2^5%8Al6v<3@JUc72`ArRP=P6(vKw& z!5|aSN#I?(@)>h5&{mWQ0?ckm`>Z&p@Lp4ZN2!r%yw_t-P%t|UkNCUW#VB*78X894B>b{~n0W*nzOWq^8z;;wnbc{3=>FocYUsUB4c z6v2X@8-FFJw=z(ARFpso@a!A6MiW1&jJN6g0ss~mSV^T@w<)c2WoZFyxH53wOWuq* z4RQ&Kp(%g z3EK;d1Mi+gqibP-3O+q#O!ypoY#I2`B}S&1Mn}xV61VA1v_{ZJ0$qov*jYG_JJ}4t zU%Zdu6yJkB>@77?7RGxjAj_BiEepE>5v0roYnWk(r~r}-X&YEnfJ$$u1ZH;yy$(`7 zyaWj1m|4$l42$5?Ex%T`{83DBAqYyPRYFVXRnY1&cB0fZiD<H!O8PESw8j5yoc+H$CTB8d`d@_dyju4gVOY3&;DRG8Q4q9J3lvJ~3lE8@7KdCyIS z!pcz%+d}l{8)E6)qS6*B-4<$2~sncS$lk4ylG}~jO8HcIp zG`lcNV*diuVm=CR2Uom;?q@ILYmR^&*$t0 zovxmH9vPu@J})7|fMPyvWwhpLrQJpQq$1`_ObcRDB25-D7gvlbrh0s*x}~y?Vrn_W z7+>AP!$Z{4>B0s#H5_x$nsR{#8f?8qFxiz!kV(cC)`II-8R>;$KLfxvm3$oST1C=l4XXUrV^ENu_`i_V zK|eW!zULWn{-yK(kDDm%1_ZbJ7N_&m^YlAv&q1pP!j9m>(o7lnFmbP%i=sfTuc&_z z+p+dIvyF}}@l2AiJ06^dvC8d_mWXN}Yd}mRgip^34DBVP@Oeg6PM|+|)1rV=j+}HG z#+7GuH4BR|sF+8@G76HEi4dR07@$eaN0bMnUpA^1GcpRGz`*b=Lq4Fq2QP@D>1CrT zBP|law1$+HAvK87FpYTc){*WGASaAYQ%)HBGH152(G$9bxDm52I~e-`KrV`m`>Mwm0MI-VV^F~) zc-cszM00-gFf4zmfRW3F$+M~kRp!>3^DlFND4`q_r!)7UoEFEjJ~ zJ%RY~j7@3mD&(&FJE=wq%DzR$=wd>QG z%?7$nn|lD}4NV;6eV>21izUfZ!XoWzqiM~N7BhL@JJjX-yjuDU5$SU$AYg+H37@S% zKs5)P(7-2QZ%|oT+3E@X0lU7wu7_xM`7bPcY{!5}tDM6bgmX&tFfKI8ALyw|rFS^B zEidLF1i>+~_+)mbqyj}ZD9hAwaK=&Hn3nQs*{!QEw2&;h0;R@2h=%?g3&e7z?8RscvDzDCO&{e%& zaNk7+wIk5n5_bd|a|s&1WR2*3t604wKCk=kiqFdi&tU-CB8pJ* zf%)Xzg%eGWVUx6Z<~urVn`at&sfyIkVM32ka#yTS)kj@l42Qid-4Srmhr<{67{~8; z_~g9Wz|Y%dU+5Ok<8BOqTevh%xTMf8@s+A5N2&EJ)k#y&S~R3)#wLn!MHiJ=fZ^ne zeZJiu)Kt>QJo!j^=KHVB4;s|2VPD!_UMgpZN-|RWzCXdk$3uEcDpKpT2gE@rYEi@C zEVT%2wZ6z0;vV!ys13xw&#VVYFpV>ig=Q?^a`XT)Ctg#+Av32k2DmwsNS+Vp15VlZQ|+NVhz_0<7Oah`=|YMW_} zPjtTQ#)D?CGN><3pu`0@t3ZPx8u-@SjJCA&W(KxaNU9qo zG*dK%G~uf$EJG1afGY@J!*em{w;e=psz$9V3&ld8aHc8E&_{HHaOaG}B`JIsynr(f z7Ih|r)gQ%@A*3m~XD00Ynb{IcOJsqQerV4i@Mxk50#dQppdmq{;)?NlP){{ons~o_ z5|w$va2JyPr_!?1!9(#=z|xHaHjocwsvI~aLa4P`#oW~-_)b4a(M6W2$tV_b05M^;zft9;B0U>%r--<&6 zq?Oz6Bx&`$P#p?AoD;o^8!EJ%3a4{MIF@VIPr=!6AA&W?+hW*Pj0B+;F1RS(4>nkT zA~kI^gq6WJuckJcVL1#iqnudL^C$Bo807BO8UvLp35@eG)~tiyqpNPGyS}!q8%Pa0 zEC4Hhs!^)u@ve3AC<@XOQ$1S$0=a-8P=vM&g33|!z%xHmXI4c_kXHcFr#Ff-4D5c0tX%b;^9caOcUYa! zIHCyms9>>r$3%vl6M>rb32sL~0?N(ufa*YBDUeu&hzN*pt|*&Rp!`8w81z6hp7Ltk zq_PpSC^JB1tMAJi>>^rDj-m;83L^7bxjCNtn)~+uqZ?zEs<4+w2Ug$;c+yERuT%A;Eb@e z*FXtWlxfAaAhdI6y6Urih#Wd_ewo2Ru6R|qH2x>3ZQcw z7E{pJ2BM2>`dN;KC#H#9w5}FugY%#Y2M`%fZY@E2!GtPjm~n6-O7cLKn|1vLFef1n z01wV0!!Q^;?3hh2R9-{+f$G}~-pgaupkm9(66Uzqdg%-QZ) zvvvkL3!N`_{%84%eE;R#e0rMeeC=QU?ce|Fg|GkXH~!;=ul?sYE|Ad)dpDt9_O+v= g$ng(1|M4sT^wqC__3!`gum1UOzWTRc`RmUA0?hpQ;{X5v diff --git a/examples/TinyRenderer/main.cpp b/examples/TinyRenderer/main.cpp index 7a9de8fef..65a3352f6 100644 --- a/examples/TinyRenderer/main.cpp +++ b/examples/TinyRenderer/main.cpp @@ -81,7 +81,7 @@ int main(int argc, char* argv[]) int textureWidth = gWidth; int textureHeight = gHeight; - TinyRenderObjectData renderData(textureWidth, textureHeight, "african_head/african_head.obj");//floor.obj"); + TinyRenderObjectData renderData(textureWidth, textureHeight, "floor.obj"); From 924456548e3cea1c4310977cdf2a2a2445611a8c Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 26 Apr 2016 21:08:02 -0700 Subject: [PATCH 13/50] fix build, add premake4.lua --- examples/TinyRenderer/TinyRenderer.cpp | 2 +- examples/TinyRenderer/premake4.lua | 29 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 examples/TinyRenderer/premake4.lua diff --git a/examples/TinyRenderer/TinyRenderer.cpp b/examples/TinyRenderer/TinyRenderer.cpp index 3370c86fd..bbc9bbf16 100644 --- a/examples/TinyRenderer/TinyRenderer.cpp +++ b/examples/TinyRenderer/TinyRenderer.cpp @@ -7,7 +7,7 @@ #include "TinyRenderer/model.h" #include "TinyRenderer/geometry.h" #include "TinyRenderer/our_gl.h" -#include "../../Utils/b3ResourcePath.h" +#include "../Utils/b3ResourcePath.h" #include "Bullet3Common/b3MinMax.h" Vec3f light_dir_world(1,1,1); diff --git a/examples/TinyRenderer/premake4.lua b/examples/TinyRenderer/premake4.lua new file mode 100644 index 000000000..3eb417ff2 --- /dev/null +++ b/examples/TinyRenderer/premake4.lua @@ -0,0 +1,29 @@ + + project "App_TinyRenderer" + + language "C++" + + kind "ConsoleApp" + + includedirs { + ".", + "../../src", + ".." + } + + + links{ "OpenGL_Window","Bullet3Common"} + initOpenGL() + initGlew() + + files { + "*.cpp", + "*.h", + "../Utils/b3ResourcePath.cpp" + } + +if os.is("Linux") then initX11() end + +if os.is("MacOSX") then + links{"Cocoa.framework"} +end From a3767193cec04a068eda6d75fd86a2de5822e275 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 27 Apr 2016 09:43:49 -0700 Subject: [PATCH 14/50] add example to use BasicDemo with an OpenGL Window, without example browser --- examples/BasicDemo/main.cpp | 34 ++++++++++++++++++++++++++++++++ examples/BasicDemo/premake4.lua | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/examples/BasicDemo/main.cpp b/examples/BasicDemo/main.cpp index c6039fc63..fa576f451 100644 --- a/examples/BasicDemo/main.cpp +++ b/examples/BasicDemo/main.cpp @@ -20,7 +20,40 @@ subject to the following restrictions: #include "../CommonInterfaces/CommonGUIHelperInterface.h" +#ifdef USE_GUI +#include "../OpenGLWindow/SimpleOpenGL3App.h" +#include +#include "../ExampleBrowser/OpenGLGuiHelper.h" +int main(int argc, char* argv[]) +{ + + SimpleOpenGL3App* app = new SimpleOpenGL3App("BasicDemoGui",1024,768,true); + OpenGLGuiHelper gui(app,false); + CommonExampleOptions options(&gui); + CommonExampleInterface* example = BasicExampleCreateFunc(options); + + example->initPhysics(); + + int frameCount = 0; + do + { + app->m_instancingRenderer->init(); + app->m_instancingRenderer->updateCamera(); + example->stepSimulation(1./60.); + example->renderScene(); + app->drawGrid(); + app->swapBuffer(); + } while (!app->m_window->requestedExit()); + + example->exitPhysics(); + delete example; + delete app; + return 0; +} + + +#else int main(int argc, char* argv[]) { @@ -38,4 +71,5 @@ int main(int argc, char* argv[]) return 0; } +#endif diff --git a/examples/BasicDemo/premake4.lua b/examples/BasicDemo/premake4.lua index b4901e92b..c55bc2525 100644 --- a/examples/BasicDemo/premake4.lua +++ b/examples/BasicDemo/premake4.lua @@ -20,3 +20,38 @@ files { "**.h", } + +project "App_BasicExampleGui" + +if _OPTIONS["ios"] then + kind "WindowedApp" +else + kind "ConsoleApp" +end +defines {"USE_GUI"} + +includedirs {"../../src"} + +links { + "BulletDynamics","BulletCollision", "LinearMath", "OpenGL_Window","Bullet3Common" +} + + initOpenGL() + initGlew() + + +language "C++" + +files { + "**.cpp", + "**.h", + "../ExampleBrowser/OpenGLGuiHelper.cpp", + "../ExampleBrowser/GL_ShapeDrawer.cpp" +} + +if os.is("Linux") then initX11() end + +if os.is("MacOSX") then + links{"Cocoa.framework"} +end + From af442778a64a7c5ea94ee961ac1749d32069909b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 16 Nov 2015 14:38:14 -0800 Subject: [PATCH 15/50] Add early rejection tests during CCD against compound objects --- .../CollisionDispatch/btCollisionWorld.cpp | 136 +++++++++++++----- 1 file changed, 97 insertions(+), 39 deletions(-) diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index c505ed5d5..f407260e3 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -793,50 +793,108 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, ///@todo : use AABB tree or other BVH acceleration structure! if (collisionShape->isCompound()) { + struct btCompoundLeafCallback : btDbvt::ICollide + { + btCompoundLeafCallback( + const btConvexShape* castShape, + const btTransform& convexFromTrans, + const btTransform& convexToTrans, + btScalar allowedPenetration, + const btCompoundShape* compoundShape, + const btTransform& colObjWorldTransform, + ConvexResultCallback& resultCallback) + : + m_castShape(castShape), + m_convexFromTrans(convexFromTrans), + m_convexToTrans(convexToTrans), + m_allowedPenetration(allowedPenetration), + m_compoundShape(compoundShape), + m_colObjWorldTransform(colObjWorldTransform), + m_resultCallback(resultCallback) { + } + + const btConvexShape* m_castShape; + const btTransform& m_convexFromTrans; + const btTransform& m_convexToTrans; + btScalar m_allowedPenetration; + const btCompoundShape* m_compoundShape; + const btTransform& m_colObjWorldTransform; + ConvexResultCallback& m_resultCallback; + const btCollisionObjectWrapper* m_colObjWrap; + + public: + + void Process(const btDbvtNode* leaf) + { + // Processing leaf node + int index = leaf->dataAsInt; + + //const btCompoundShape* compoundShape = static_cast(m_compoundColObjWrap->getCollisionShape()); + btTransform childTrans = m_compoundShape->getChildTransform(index); + const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index); + btTransform childWorldTrans = m_colObjWorldTransform * childTrans; + + struct LocalInfoAdder : public ConvexResultCallback { + ConvexResultCallback* m_userCallback; + int m_i; + + LocalInfoAdder(int i, ConvexResultCallback *user) + : m_userCallback(user), m_i(i) + { + m_closestHitFraction = m_userCallback->m_closestHitFraction; + } + virtual bool needsCollision(btBroadphaseProxy* p) const + { + return m_userCallback->needsCollision(p); + } + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = -1; + shapeInfo.m_triangleIndex = m_i; + if (r.m_localShapeInfo == NULL) + r.m_localShapeInfo = &shapeInfo; + const btScalar result = m_userCallback->addSingleResult(r, b); + m_closestHitFraction = m_userCallback->m_closestHitFraction; + return result; + + } + }; + + LocalInfoAdder my_cb(index, &m_resultCallback); + + btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index); + + objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, + &tmpObj, my_cb, m_allowedPenetration); + } + }; + BT_PROFILE("convexSweepCompound"); const btCompoundShape* compoundShape = static_cast(collisionShape); - int i=0; - for (i=0;igetNumChildShapes();i++) - { - btTransform childTrans = compoundShape->getChildTransform(i); - const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); - btTransform childWorldTrans = colObjWorldTransform * childTrans; - - struct LocalInfoAdder : public ConvexResultCallback { - ConvexResultCallback* m_userCallback; - int m_i; - LocalInfoAdder (int i, ConvexResultCallback *user) - : m_userCallback(user), m_i(i) - { - m_closestHitFraction = m_userCallback->m_closestHitFraction; - } - virtual bool needsCollision(btBroadphaseProxy* p) const - { - return m_userCallback->needsCollision(p); - } - virtual btScalar addSingleResult (btCollisionWorld::LocalConvexResult& r, bool b) - { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = -1; - shapeInfo.m_triangleIndex = m_i; - if (r.m_localShapeInfo == NULL) - r.m_localShapeInfo = &shapeInfo; - const btScalar result = m_userCallback->addSingleResult(r, b); - m_closestHitFraction = m_userCallback->m_closestHitFraction; - return result; - - } - }; + btVector3 fromLocalAabbMin, fromLocalAabbMax; + btVector3 toLocalAabbMin, toLocalAabbMax; - LocalInfoAdder my_cb(i, &resultCallback); - - btCollisionObjectWrapper tmpObj(colObjWrap,childCollisionShape,colObjWrap->getCollisionObject(),childWorldTrans,-1,i); + castShape->getAabb(convexFromTrans, fromLocalAabbMin, fromLocalAabbMax); + castShape->getAabb(convexToTrans, toLocalAabbMin, toLocalAabbMax); - objectQuerySingleInternal(castShape, convexFromTrans,convexToTrans, - &tmpObj,my_cb, allowedPenetration); - - } + fromLocalAabbMin.setMin(toLocalAabbMin); + fromLocalAabbMax.setMax(toLocalAabbMax); + + const btDbvt* tree = compoundShape->getDynamicAabbTree(); + + if (tree) { + btCompoundLeafCallback callback { castShape, convexFromTrans, convexToTrans, + allowedPenetration, compoundShape, colObjWorldTransform, resultCallback }; + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax); + tree->collideTV(tree->m_root, bounds, callback); + } else { + int i; + for (i=0;igetNumChildShapes();i++) + { + } + } } } } From 25ee137390f57c8df97ebc3e3b3f5c80cd5c667d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 16 Nov 2015 15:48:08 -0800 Subject: [PATCH 16/50] Fix missing colObjWrap --- .../CollisionDispatch/btCollisionWorld.cpp | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index f407260e3..f0b57f0a2 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -796,14 +796,16 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, struct btCompoundLeafCallback : btDbvt::ICollide { btCompoundLeafCallback( - const btConvexShape* castShape, - const btTransform& convexFromTrans, - const btTransform& convexToTrans, - btScalar allowedPenetration, - const btCompoundShape* compoundShape, - const btTransform& colObjWorldTransform, - ConvexResultCallback& resultCallback) - : + const btCollisionObjectWrapper* colObjWrap, + const btConvexShape* castShape, + const btTransform& convexFromTrans, + const btTransform& convexToTrans, + btScalar allowedPenetration, + const btCompoundShape* compoundShape, + const btTransform& colObjWorldTransform, + ConvexResultCallback& resultCallback) + : + m_colObjWrap(colObjWrap), m_castShape(castShape), m_convexFromTrans(convexFromTrans), m_convexToTrans(convexToTrans), @@ -813,6 +815,7 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, m_resultCallback(resultCallback) { } + const btCollisionObjectWrapper* m_colObjWrap; const btConvexShape* m_castShape; const btTransform& m_convexFromTrans; const btTransform& m_convexToTrans; @@ -820,7 +823,6 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, const btCompoundShape* m_compoundShape; const btTransform& m_colObjWorldTransform; ConvexResultCallback& m_resultCallback; - const btCollisionObjectWrapper* m_colObjWrap; public: @@ -885,7 +887,7 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, const btDbvt* tree = compoundShape->getDynamicAabbTree(); if (tree) { - btCompoundLeafCallback callback { castShape, convexFromTrans, convexToTrans, + btCompoundLeafCallback callback { colObjWrap, castShape, convexFromTrans, convexToTrans, allowedPenetration, compoundShape, colObjWorldTransform, resultCallback }; const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax); tree->collideTV(tree->m_root, bounds, callback); From b1356993253e754146ea9dab44bc9929e868d10d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 17 Nov 2015 13:50:51 -0800 Subject: [PATCH 17/50] Fix errors in ccd against compound objects --- .../CollisionDispatch/btCollisionWorld.cpp | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index f0b57f0a2..4232cc927 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -826,15 +826,10 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, public: - void Process(const btDbvtNode* leaf) + void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape) { - // Processing leaf node - int index = leaf->dataAsInt; - - //const btCompoundShape* compoundShape = static_cast(m_compoundColObjWrap->getCollisionShape()); - btTransform childTrans = m_compoundShape->getChildTransform(index); - const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index); btTransform childWorldTrans = m_colObjWorldTransform * childTrans; + //btTransform childWorldTrans = childTrans; struct LocalInfoAdder : public ConvexResultCallback { ConvexResultCallback* m_userCallback; @@ -870,6 +865,18 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration); } + + void Process(const btDbvtNode* leaf) + { + // Processing leaf node + int index = leaf->dataAsInt; + + //const btCompoundShape* compoundShape = static_cast(m_compoundColObjWrap->getCollisionShape()); + btTransform childTrans = m_compoundShape->getChildTransform(index); + const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index); + + ProcessChild(index, childTrans, childCollisionShape); + } }; BT_PROFILE("convexSweepCompound"); @@ -878,23 +885,27 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, btVector3 fromLocalAabbMin, fromLocalAabbMax; btVector3 toLocalAabbMin, toLocalAabbMax; - castShape->getAabb(convexFromTrans, fromLocalAabbMin, fromLocalAabbMax); - castShape->getAabb(convexToTrans, toLocalAabbMin, toLocalAabbMax); + castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax); + castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax); fromLocalAabbMin.setMin(toLocalAabbMin); fromLocalAabbMax.setMax(toLocalAabbMax); const btDbvt* tree = compoundShape->getDynamicAabbTree(); + btCompoundLeafCallback callback { colObjWrap, castShape, convexFromTrans, convexToTrans, + allowedPenetration, compoundShape, colObjWorldTransform, resultCallback }; + if (tree) { - btCompoundLeafCallback callback { colObjWrap, castShape, convexFromTrans, convexToTrans, - allowedPenetration, compoundShape, colObjWorldTransform, resultCallback }; const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax); tree->collideTV(tree->m_root, bounds, callback); } else { int i; for (i=0;igetNumChildShapes();i++) { + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childTrans = compoundShape->getChildTransform(i); + callback.ProcessChild(i, childTrans, childCollisionShape); } } } From 7f0877339ebf93b75178cdf463aa681874aa881a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 17 Nov 2015 15:03:08 -0800 Subject: [PATCH 18/50] Replace spaces with tabs --- .../CollisionDispatch/btCollisionWorld.cpp | 188 +++++++++--------- 1 file changed, 93 insertions(+), 95 deletions(-) diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index 4232cc927..523d80113 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -790,124 +790,122 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, } } } else { - ///@todo : use AABB tree or other BVH acceleration structure! if (collisionShape->isCompound()) { - struct btCompoundLeafCallback : btDbvt::ICollide - { - btCompoundLeafCallback( - const btCollisionObjectWrapper* colObjWrap, - const btConvexShape* castShape, - const btTransform& convexFromTrans, - const btTransform& convexToTrans, - btScalar allowedPenetration, - const btCompoundShape* compoundShape, - const btTransform& colObjWorldTransform, - ConvexResultCallback& resultCallback) - : - m_colObjWrap(colObjWrap), - m_castShape(castShape), - m_convexFromTrans(convexFromTrans), - m_convexToTrans(convexToTrans), - m_allowedPenetration(allowedPenetration), - m_compoundShape(compoundShape), - m_colObjWorldTransform(colObjWorldTransform), - m_resultCallback(resultCallback) { - } + struct btCompoundLeafCallback : btDbvt::ICollide + { + btCompoundLeafCallback( + const btCollisionObjectWrapper* colObjWrap, + const btConvexShape* castShape, + const btTransform& convexFromTrans, + const btTransform& convexToTrans, + btScalar allowedPenetration, + const btCompoundShape* compoundShape, + const btTransform& colObjWorldTransform, + ConvexResultCallback& resultCallback) + : + m_colObjWrap(colObjWrap), + m_castShape(castShape), + m_convexFromTrans(convexFromTrans), + m_convexToTrans(convexToTrans), + m_allowedPenetration(allowedPenetration), + m_compoundShape(compoundShape), + m_colObjWorldTransform(colObjWorldTransform), + m_resultCallback(resultCallback) { + } - const btCollisionObjectWrapper* m_colObjWrap; - const btConvexShape* m_castShape; - const btTransform& m_convexFromTrans; - const btTransform& m_convexToTrans; - btScalar m_allowedPenetration; - const btCompoundShape* m_compoundShape; - const btTransform& m_colObjWorldTransform; - ConvexResultCallback& m_resultCallback; + const btCollisionObjectWrapper* m_colObjWrap; + const btConvexShape* m_castShape; + const btTransform& m_convexFromTrans; + const btTransform& m_convexToTrans; + btScalar m_allowedPenetration; + const btCompoundShape* m_compoundShape; + const btTransform& m_colObjWorldTransform; + ConvexResultCallback& m_resultCallback; - public: + public: - void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape) - { - btTransform childWorldTrans = m_colObjWorldTransform * childTrans; - //btTransform childWorldTrans = childTrans; + void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape) + { + btTransform childWorldTrans = m_colObjWorldTransform * childTrans; - struct LocalInfoAdder : public ConvexResultCallback { - ConvexResultCallback* m_userCallback; - int m_i; + struct LocalInfoAdder : public ConvexResultCallback { + ConvexResultCallback* m_userCallback; + int m_i; - LocalInfoAdder(int i, ConvexResultCallback *user) - : m_userCallback(user), m_i(i) - { - m_closestHitFraction = m_userCallback->m_closestHitFraction; - } - virtual bool needsCollision(btBroadphaseProxy* p) const - { - return m_userCallback->needsCollision(p); - } - virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b) - { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = -1; - shapeInfo.m_triangleIndex = m_i; - if (r.m_localShapeInfo == NULL) - r.m_localShapeInfo = &shapeInfo; - const btScalar result = m_userCallback->addSingleResult(r, b); - m_closestHitFraction = m_userCallback->m_closestHitFraction; - return result; + LocalInfoAdder(int i, ConvexResultCallback *user) + : m_userCallback(user), m_i(i) + { + m_closestHitFraction = m_userCallback->m_closestHitFraction; + } + virtual bool needsCollision(btBroadphaseProxy* p) const + { + return m_userCallback->needsCollision(p); + } + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = -1; + shapeInfo.m_triangleIndex = m_i; + if (r.m_localShapeInfo == NULL) + r.m_localShapeInfo = &shapeInfo; + const btScalar result = m_userCallback->addSingleResult(r, b); + m_closestHitFraction = m_userCallback->m_closestHitFraction; + return result; - } - }; + } + }; - LocalInfoAdder my_cb(index, &m_resultCallback); + LocalInfoAdder my_cb(index, &m_resultCallback); - btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index); + btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index); - objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, - &tmpObj, my_cb, m_allowedPenetration); - } + objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, + &tmpObj, my_cb, m_allowedPenetration); + } - void Process(const btDbvtNode* leaf) - { - // Processing leaf node - int index = leaf->dataAsInt; + void Process(const btDbvtNode* leaf) + { + // Processing leaf node + int index = leaf->dataAsInt; - //const btCompoundShape* compoundShape = static_cast(m_compoundColObjWrap->getCollisionShape()); - btTransform childTrans = m_compoundShape->getChildTransform(index); - const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index); + //const btCompoundShape* compoundShape = static_cast(m_compoundColObjWrap->getCollisionShape()); + btTransform childTrans = m_compoundShape->getChildTransform(index); + const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index); - ProcessChild(index, childTrans, childCollisionShape); - } - }; + ProcessChild(index, childTrans, childCollisionShape); + } + }; BT_PROFILE("convexSweepCompound"); const btCompoundShape* compoundShape = static_cast(collisionShape); - btVector3 fromLocalAabbMin, fromLocalAabbMax; - btVector3 toLocalAabbMin, toLocalAabbMax; + btVector3 fromLocalAabbMin, fromLocalAabbMax; + btVector3 toLocalAabbMin, toLocalAabbMax; - castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax); - castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax); + castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax); + castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax); - fromLocalAabbMin.setMin(toLocalAabbMin); - fromLocalAabbMax.setMax(toLocalAabbMax); + fromLocalAabbMin.setMin(toLocalAabbMin); + fromLocalAabbMax.setMax(toLocalAabbMax); - const btDbvt* tree = compoundShape->getDynamicAabbTree(); + const btDbvt* tree = compoundShape->getDynamicAabbTree(); - btCompoundLeafCallback callback { colObjWrap, castShape, convexFromTrans, convexToTrans, - allowedPenetration, compoundShape, colObjWorldTransform, resultCallback }; + btCompoundLeafCallback callback { colObjWrap, castShape, convexFromTrans, convexToTrans, + allowedPenetration, compoundShape, colObjWorldTransform, resultCallback }; - if (tree) { - const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax); - tree->collideTV(tree->m_root, bounds, callback); - } else { - int i; - for (i=0;igetNumChildShapes();i++) - { - const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); - btTransform childTrans = compoundShape->getChildTransform(i); - callback.ProcessChild(i, childTrans, childCollisionShape); - } - } + if (tree) { + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax); + tree->collideTV(tree->m_root, bounds, callback); + } else { + int i; + for (i=0;igetNumChildShapes();i++) + { + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childTrans = compoundShape->getChildTransform(i); + callback.ProcessChild(i, childTrans, childCollisionShape); + } + } } } } From 76d39d443966c3d8d008eb64d85efff984f98350 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Nov 2015 16:08:18 -0800 Subject: [PATCH 19/50] Fix build error on OSX + Linux --- src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index 523d80113..080f336df 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -891,8 +891,8 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, const btDbvt* tree = compoundShape->getDynamicAabbTree(); - btCompoundLeafCallback callback { colObjWrap, castShape, convexFromTrans, convexToTrans, - allowedPenetration, compoundShape, colObjWorldTransform, resultCallback }; + btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans, + allowedPenetration, compoundShape, colObjWorldTransform, resultCallback); if (tree) { const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax); From 8d970e5c044207b826276dda6722def53c9b1015 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 27 Apr 2016 13:41:42 -0700 Subject: [PATCH 20/50] minor cleanup --- src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index 080f336df..fa4cac660 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -860,8 +860,7 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index); - objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, - &tmpObj, my_cb, m_allowedPenetration); + objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration); } void Process(const btDbvtNode* leaf) @@ -869,7 +868,6 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, // Processing leaf node int index = leaf->dataAsInt; - //const btCompoundShape* compoundShape = static_cast(m_compoundColObjWrap->getCollisionShape()); btTransform childTrans = m_compoundShape->getChildTransform(index); const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index); @@ -889,11 +887,10 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, fromLocalAabbMin.setMin(toLocalAabbMin); fromLocalAabbMax.setMax(toLocalAabbMax); - const btDbvt* tree = compoundShape->getDynamicAabbTree(); - btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans, allowedPenetration, compoundShape, colObjWorldTransform, resultCallback); + const btDbvt* tree = compoundShape->getDynamicAabbTree(); if (tree) { const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax); tree->collideTV(tree->m_root, bounds, callback); From 615effa4d9cb3882c9d9561f7a803e37e8afd9ae Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Thu, 28 Apr 2016 12:28:04 -0700 Subject: [PATCH 21/50] fix typo in texels flip add support to create a cube in TinyRenderer (quick test) --- .../OpenGLWindow/GLInstancingRenderer.cpp | 6 +- examples/TinyRenderer/TinyRenderer.cpp | 58 +++++++++++++++++-- examples/TinyRenderer/TinyRenderer.h | 7 ++- examples/TinyRenderer/main.cpp | 22 ++++++- examples/TinyRenderer/model.cpp | 28 +++++++++ examples/TinyRenderer/model.h | 7 +++ examples/TinyRenderer/tgaimage.cpp | 2 +- 7 files changed, 115 insertions(+), 15 deletions(-) diff --git a/examples/OpenGLWindow/GLInstancingRenderer.cpp b/examples/OpenGLWindow/GLInstancingRenderer.cpp index 2bd7c92ad..e6304ad70 100644 --- a/examples/OpenGLWindow/GLInstancingRenderer.cpp +++ b/examples/OpenGLWindow/GLInstancingRenderer.cpp @@ -561,9 +561,9 @@ void GLInstancingRenderer::updateTexture(int textureIndex, const unsigned cha { for (int j = 0; j < h.m_height; j++) { - flippedTexels[(i + j*h.m_width) * 3] = texels[(i + (h.m_height-1-j)*h.m_width) * 3]; - flippedTexels[(i + j*h.m_width) * 3+1] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1]; - flippedTexels[(i + j*h.m_width) * 3+2] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1]; + flippedTexels[(i + j*h.m_width) * 3] = texels[(i + (h.m_height - 1 -j )*h.m_width) * 3]; + flippedTexels[(i + j*h.m_width) * 3+1] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1]; + flippedTexels[(i + j*h.m_width) * 3+2] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+2]; } } diff --git a/examples/TinyRenderer/TinyRenderer.cpp b/examples/TinyRenderer/TinyRenderer.cpp index bbc9bbf16..9d45963b7 100644 --- a/examples/TinyRenderer/TinyRenderer.cpp +++ b/examples/TinyRenderer/TinyRenderer.cpp @@ -9,7 +9,7 @@ #include "TinyRenderer/our_gl.h" #include "../Utils/b3ResourcePath.h" #include "Bullet3Common/b3MinMax.h" - +#include "../OpenGLWindow/ShapeData.h" Vec3f light_dir_world(1,1,1); @@ -64,7 +64,8 @@ struct Shader : public IShader { Vec3f n = (B*m_model->normal(uv)).normalize(); - float diff = b3Min(b3Max(0.f, n*m_light_dir_local+0.6f),1.f); + //float diff = b3Min(b3Max(0.f, n*m_light_dir_local+0.3f),1.f); + float diff = b3Max(0.f, n*m_light_dir_local); color = m_model->diffuse(uv)*diff; return false; @@ -91,7 +92,7 @@ struct TinyRenderObjectData }; */ -TinyRenderObjectData::TinyRenderObjectData(int width, int height, const char* fileName) +TinyRenderObjectData::TinyRenderObjectData(int width, int height) :m_width(width), m_height(height), m_rgbColorBuffer(width,height,TGAImage::RGB), @@ -101,12 +102,17 @@ m_model(0) Vec3f center(0,0,0); Vec3f up(0,1,0); + m_modelMatrix = Matrix::identity(); m_viewMatrix = lookat(eye, center, up); m_viewportMatrix = viewport(width/8, height/8, width*3/4, height*3/4); m_projectionMatrix = projection(-1.f/(eye-center).norm()); - m_depthBuffer.resize(width*height); + +} + +void TinyRenderObjectData::loadModel(const char* fileName) +{ //todo(erwincoumans) move the file loading out of here char relativeFileName[1024]; if (!b3ResourcePath::findResourcePath(fileName, relativeFileName, 1024)) @@ -115,8 +121,47 @@ m_model(0) } else { m_model = new Model(relativeFileName); + } +} + +void TinyRenderObjectData::createCube(float halfExtentsX,float halfExtentsY,float halfExtentsZ) +{ + m_model = new Model(); + + char relativeFileName[1024]; + if (b3ResourcePath::findResourcePath("floor_diffuse.tga", relativeFileName, 1024)) + { + m_model->loadDiffuseTexture(relativeFileName); } + + int strideInBytes = 9*sizeof(float); + int numVertices = sizeof(cube_vertices_textured)/strideInBytes; + int numIndices = sizeof(cube_indices)/sizeof(int); + + for (int i=0;iaddVertex(halfExtentsX*cube_vertices_textured[i*9], + halfExtentsY*cube_vertices_textured[i*9+1], + halfExtentsY*cube_vertices_textured[i*9+2], + cube_vertices_textured[i*9+4], + cube_vertices_textured[i*9+5], + cube_vertices_textured[i*9+6], + cube_vertices_textured[i*9+7], + cube_vertices_textured[i*9+8]); + } + for (int i=0;iaddTriangle(cube_indices[i],cube_indices[i],cube_indices[i], + cube_indices[i+1],cube_indices[i+1],cube_indices[i+1], + cube_indices[i+2],cube_indices[i+2],cube_indices[i+2]); + } + + //int shapeId = m_instancingRenderer->registerShape(&verts[0].x,numVertices,cube_indices,numIndices,B3_GL_TRIANGLES,textureIndex); + } @@ -149,12 +194,13 @@ void TinyRenderer::renderObject(TinyRenderObjectData& renderData) //viewport(width/8, height/8, width*3/4, height*3/4); //projection(-1.f/(eye-center).norm()); - Vec3f light_dir_local = proj<3>((renderData.m_projectionMatrix*renderData.m_viewMatrix*embed<4>(light_dir_world, 0.f))).normalize(); + Vec3f light_dir_local = proj<3>((renderData.m_projectionMatrix*renderData.m_viewMatrix*renderData.m_modelMatrix*embed<4>(light_dir_world, 0.f))).normalize(); { //for (int m=1; mnfaces(); i++) { for (int j=0; j<3; j++) { shader.vertex(i, j); diff --git a/examples/TinyRenderer/TinyRenderer.h b/examples/TinyRenderer/TinyRenderer.h index 1bcd49b95..0afd175fd 100644 --- a/examples/TinyRenderer/TinyRenderer.h +++ b/examples/TinyRenderer/TinyRenderer.h @@ -14,7 +14,7 @@ struct TinyRenderObjectData Matrix m_viewportMatrix; //Model (vertices, indices, textures, shader) - Matrix m_modelMatrix; + Matrix m_modelMatrix; class Model* m_model; //class IShader* m_shader; todo(erwincoumans) expose the shader, for now we use a default shader @@ -24,9 +24,12 @@ struct TinyRenderObjectData TGAImage m_rgbColorBuffer; b3AlignedObjectArray m_depthBuffer; - TinyRenderObjectData(int width, int height, const char* objFileName); + TinyRenderObjectData(int width, int height); virtual ~TinyRenderObjectData(); + void loadModel(const char* fileName); + void createCube(float HalfExtentsX,float HalfExtentsY,float HalfExtentsZ); + }; diff --git a/examples/TinyRenderer/main.cpp b/examples/TinyRenderer/main.cpp index 65a3352f6..7ec899320 100644 --- a/examples/TinyRenderer/main.cpp +++ b/examples/TinyRenderer/main.cpp @@ -1,6 +1,8 @@ #include "OpenGLWindow/SimpleOpenGL3App.h" #include "Bullet3Common/b3Quaternion.h" #include "Bullet3Common/b3CommandLineArgs.h" +#include "Bullet3Common/b3Transform.h" + #include "assert.h" #include @@ -81,8 +83,12 @@ int main(int argc, char* argv[]) int textureWidth = gWidth; int textureHeight = gHeight; - TinyRenderObjectData renderData(textureWidth, textureHeight, "floor.obj"); - + TinyRenderObjectData renderData(textureWidth, textureHeight);//, "african_head/african_head.obj");//floor.obj"); + + //renderData.loadModel("african_head/african_head.obj"); + //renderData.loadModel("floor.obj"); + + renderData.createCube(1,1,1); myArgs.GetCmdLineArgument("mp4_file",gVideoFileName); @@ -127,12 +133,22 @@ int main(int argc, char* argv[]) app->m_instancingRenderer->getActiveCamera()->getCameraProjectionMatrix(projMat); float viewMat[16]; app->m_instancingRenderer->getActiveCamera()->getCameraViewMatrix(viewMat); + B3_ATTRIBUTE_ALIGNED16(float modelMat[16]); + + b3Transform tr; + tr.setIdentity(); + static float posUp = 0.f; + posUp += 0.001; + b3Vector3 org = b3MakeVector3(0,posUp,0); + tr.setOrigin(org); + tr.getOpenGLMatrix(modelMat); + for (int i=0;i<4;i++) { for (int j=0;j<4;j++) { renderData.m_viewMatrix[i][j] = viewMat[i+4*j]; - //renderData.m_projectionMatrix[i][j] = projMat[i+4*j]; + renderData.m_modelMatrix[i][j] = modelMat[i+4*j]; } } diff --git a/examples/TinyRenderer/model.cpp b/examples/TinyRenderer/model.cpp index bc7983dd5..f52b01126 100644 --- a/examples/TinyRenderer/model.cpp +++ b/examples/TinyRenderer/model.cpp @@ -44,6 +44,34 @@ Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffus load_texture(filename, "_spec.tga", specularmap_); } +Model::Model():verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_() +{ +} + +void Model::loadDiffuseTexture(const char* relativeFileName) +{ + diffusemap_.read_tga_file(relativeFileName); +} + +void Model::addVertex(float x,float y,float z, float normalX, float normalY, float normalZ, float u, float v) +{ + verts_.push_back(Vec3f(x,y,z)); + norms_.push_back(Vec3f(normalX,normalY,normalZ)); + uv_.push_back(Vec2f(u,v)); + +} +void Model::addTriangle(int vertexposIndex0, int normalIndex0, int uvIndex0, + int vertexposIndex1, int normalIndex1, int uvIndex1, + int vertexposIndex2, int normalIndex2, int uvIndex2) +{ + std::vector f; + f.push_back(Vec3i(vertexposIndex0, normalIndex0, uvIndex0)); + f.push_back(Vec3i(vertexposIndex1, normalIndex1, uvIndex1)); + f.push_back(Vec3i(vertexposIndex2, normalIndex2, uvIndex2)); + faces_.push_back(f); +} + + Model::~Model() {} int Model::nverts() { diff --git a/examples/TinyRenderer/model.h b/examples/TinyRenderer/model.h index 035cc119a..72f505f9a 100644 --- a/examples/TinyRenderer/model.h +++ b/examples/TinyRenderer/model.h @@ -17,6 +17,13 @@ private: void load_texture(std::string filename, const char *suffix, TGAImage &img); public: Model(const char *filename); + Model(); + void loadDiffuseTexture(const char* relativeFileName); + void addVertex(float x,float y,float z, float normalX, float normalY, float normalZ, float u, float v); + void addTriangle(int vertexposIndex0, int normalIndex0, int uvIndex0, + int vertexposIndex1, int normalIndex1, int uvIndex1, + int vertexposIndex2, int normalIndex2, int uvIndex2); + ~Model(); int nverts(); int nfaces(); diff --git a/examples/TinyRenderer/tgaimage.cpp b/examples/TinyRenderer/tgaimage.cpp index 47e6ff833..6fe40f484 100644 --- a/examples/TinyRenderer/tgaimage.cpp +++ b/examples/TinyRenderer/tgaimage.cpp @@ -246,7 +246,7 @@ bool TGAImage::unload_rle_data(std::ofstream &out) { TGAColor TGAImage::get(int x, int y) { if (!data || x<0 || y<0 || x>=width || y>=height) { - return TGAColor(); + return TGAColor(128.f,128.f,128.f,255.f); } return TGAColor(data+(x+y*width)*bytespp, bytespp); } From aa9a276a71e0f40966fbfe14cca18bbacfc6ef91 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Thu, 28 Apr 2016 12:28:04 -0700 Subject: [PATCH 22/50] fix typo in texels flip add support to create a cube in TinyRenderer (quick test) --- examples/BasicDemo/BasicExample.cpp | 4 +- examples/BasicDemo/main.cpp | 240 +++++++++++++++++- examples/BasicDemo/premake4.lua | 8 +- examples/ExampleBrowser/OpenGLGuiHelper.cpp | 2 +- examples/ExampleBrowser/premake4.lua | 2 + .../OpenGLWindow/GLInstancingRenderer.cpp | 6 +- examples/TinyRenderer/TinyRenderer.cpp | 144 +++++++---- examples/TinyRenderer/TinyRenderer.h | 19 +- examples/TinyRenderer/main.cpp | 67 +++-- examples/TinyRenderer/model.cpp | 28 ++ examples/TinyRenderer/model.h | 7 + examples/TinyRenderer/our_gl.cpp | 17 +- examples/TinyRenderer/tgaimage.cpp | 8 +- examples/TinyRenderer/tgaimage.h | 7 +- 14 files changed, 452 insertions(+), 107 deletions(-) diff --git a/examples/BasicDemo/BasicExample.cpp b/examples/BasicDemo/BasicExample.cpp index d501b5109..775f6fbb6 100644 --- a/examples/BasicDemo/BasicExample.cpp +++ b/examples/BasicDemo/BasicExample.cpp @@ -52,7 +52,7 @@ void BasicExample::initPhysics() m_guiHelper->setUpAxis(1); createEmptyDynamicsWorld(); - + //m_dynamicsWorld->setGravity(btVector3(0,0,0)); m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); if (m_dynamicsWorld->getDebugDrawer()) @@ -63,7 +63,7 @@ void BasicExample::initPhysics() //groundShape->initializePolyhedralFeatures(); -// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + //btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); m_collisionShapes.push_back(groundShape); diff --git a/examples/BasicDemo/main.cpp b/examples/BasicDemo/main.cpp index fa576f451..eb5e6c958 100644 --- a/examples/BasicDemo/main.cpp +++ b/examples/BasicDemo/main.cpp @@ -18,38 +18,252 @@ subject to the following restrictions: #include "../CommonInterfaces/CommonExampleInterface.h" #include "../CommonInterfaces/CommonGUIHelperInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btHashMap.h" + #ifdef USE_GUI +#include "../TinyRenderer/TinyRenderer.h" #include "../OpenGLWindow/SimpleOpenGL3App.h" #include #include "../ExampleBrowser/OpenGLGuiHelper.h" +class SW_And_OpenGLGuiHelper : public OpenGLGuiHelper +{ + + btHashMap m_swRenderObjects; + btHashMap m_swInstances; + + + int m_swWidth; + int m_swHeight; + TGAImage m_rgbColorBuffer; + + b3AlignedObjectArray m_depthBuffer; + int m_textureHandle; + unsigned char* m_image; + GLPrimitiveRenderer* m_primRenderer; + +public: + SW_And_OpenGLGuiHelper (CommonGraphicsApp* glApp, bool useOpenGL2, int swWidth, int swHeight, GLPrimitiveRenderer* primRenderer) + :OpenGLGuiHelper(glApp,useOpenGL2), + m_swWidth(swWidth), + m_swHeight(swHeight), + m_rgbColorBuffer(swWidth,swHeight,TGAImage::RGB), + m_primRenderer(primRenderer) + { + + m_depthBuffer.resize(swWidth*swHeight); + CommonRenderInterface* render = getRenderInterface(); + m_image=new unsigned char[m_swWidth*m_swHeight*4]; + + m_textureHandle = render->registerTexture(m_image,m_swWidth,m_swHeight); + } + + void clearBuffers(TGAColor& clearColor) + { + for(int y=0;ygetUserIndex(); + int shapeIndex = obj->getCollisionShape()->getUserIndex(); + + if (colIndex>=0 && shapeIndex>=0) + { + m_swInstances.insert(colIndex,shapeIndex); + } + + } + + virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices) + { + int shapeIndex = OpenGLGuiHelper::registerGraphicsShape(vertices,numvertices,indices,numIndices); + if (shapeIndex>=0) + { + TinyRenderObjectData* swObj = new TinyRenderObjectData(m_swWidth,m_swHeight,m_rgbColorBuffer,m_depthBuffer); + //swObj->registerMeshShape(vertices,numvertices,indices,numIndices); + swObj->createCube(1,1,1);//MeshShape(vertices,numvertices,indices,numIndices); + + m_swRenderObjects.insert(shapeIndex,swObj); + } + return shapeIndex; + } + + virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) + { + int instanceId = OpenGLGuiHelper::registerGraphicsInstance(shapeIndex,position,quaternion,color,scaling); + return instanceId ; + } + + virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape) + { + OpenGLGuiHelper::createCollisionShapeGraphicsObject(collisionShape); + } + + virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld) + { + OpenGLGuiHelper::syncPhysicsToGraphics(rbWorld); + } + + virtual void render(const btDiscreteDynamicsWorld* rbWorld) + { + OpenGLGuiHelper::render(rbWorld); + + //clear the color buffer + TGAColor clearColor; + clearColor.bgra[0] = 255; + clearColor.bgra[1] = 255; + clearColor.bgra[2] = 255; + clearColor.bgra[3] = 255; + + clearBuffers(clearColor); + + + ATTRIBUTE_ALIGNED16(float modelMat[16]); + ATTRIBUTE_ALIGNED16(float viewMat[16]); + CommonRenderInterface* render = getRenderInterface(); + + render->getActiveCamera()->getCameraViewMatrix(viewMat); + + + for (int i=0;igetNumCollisionObjects();i++) + { + btCollisionObject* colObj = rbWorld->getCollisionObjectArray()[i]; + int colObjIndex = colObj->getUserIndex(); + int shapeIndex = colObj->getCollisionShape()->getUserIndex(); + if (colObjIndex>=0 && shapeIndex>=0) + { + + TinyRenderObjectData* renderObj = 0; + + int* cptr = m_swInstances[colObjIndex]; + if (cptr) + { + int c = *cptr; + TinyRenderObjectData** sptr = m_swRenderObjects[c]; + if (sptr) + { + renderObj = *sptr; + } + } + //sync the object transform + const btTransform& tr = colObj->getWorldTransform(); + tr.getOpenGLMatrix(modelMat); + + for (int i=0;i<4;i++) + { + for (int j=0;j<4;j++) + { + renderObj->m_modelMatrix[i][j] = modelMat[i+4*j]; + renderObj->m_viewMatrix[i][j] = viewMat[i+4*j]; + } + } + TinyRenderer::renderObject(*renderObj); + } + } + + for(int y=0;yactivateTexture(m_textureHandle); + render->updateTexture(m_textureHandle,m_image); + + static int counter=0; + counter++; + if (counter>10) + { + counter=0; + getFrameBuffer().write_tga_file("/Users/erwincoumans/develop/bullet3/framebuf.tga",true); + } + float color[4] = {1,1,1,1}; + m_primRenderer->drawTexturedRect(0,0,m_swWidth, m_swHeight,color,0,0,1,1,true); + + + } + + virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld) + { + OpenGLGuiHelper::autogenerateGraphicsObjects(rbWorld); + } + +}; + int main(int argc, char* argv[]) { SimpleOpenGL3App* app = new SimpleOpenGL3App("BasicDemoGui",1024,768,true); - OpenGLGuiHelper gui(app,false); - CommonExampleOptions options(&gui); - CommonExampleInterface* example = BasicExampleCreateFunc(options); + int textureWidth = 640; + int textureHeight = 480; + + + SW_And_OpenGLGuiHelper gui(app,false,textureWidth,textureHeight,app->m_primRenderer); + + CommonExampleOptions options(&gui); + CommonExampleInterface* example = BasicExampleCreateFunc(options); example->initPhysics(); - int frameCount = 0; do { app->m_instancingRenderer->init(); - app->m_instancingRenderer->updateCamera(); - example->stepSimulation(1./60.); - example->renderScene(); - app->drawGrid(); - app->swapBuffer(); - } while (!app->m_window->requestedExit()); + app->m_instancingRenderer->updateCamera(); - example->exitPhysics(); - delete example; + example->stepSimulation(1./60.); + + + example->renderScene(); + + app->drawGrid(); + app->swapBuffer(); + } while (!app->m_window->requestedExit()); + + example->exitPhysics(); + delete example; delete app; - return 0; + return 0; } diff --git a/examples/BasicDemo/premake4.lua b/examples/BasicDemo/premake4.lua index c55bc2525..8e9625e55 100644 --- a/examples/BasicDemo/premake4.lua +++ b/examples/BasicDemo/premake4.lua @@ -46,7 +46,13 @@ files { "**.cpp", "**.h", "../ExampleBrowser/OpenGLGuiHelper.cpp", - "../ExampleBrowser/GL_ShapeDrawer.cpp" + "../ExampleBrowser/GL_ShapeDrawer.cpp", + "../TinyRenderer/geometry.cpp", + "../TinyRenderer/model.cpp", + "../TinyRenderer/tgaimage.cpp", + "../TinyRenderer/our_gl.cpp", + "../TinyRenderer/TinyRenderer.cpp", + "../Utils/b3ResourcePath.cpp" } if os.is("Linux") then initX11() end diff --git a/examples/ExampleBrowser/OpenGLGuiHelper.cpp b/examples/ExampleBrowser/OpenGLGuiHelper.cpp index 19d392758..ec88c0c78 100644 --- a/examples/ExampleBrowser/OpenGLGuiHelper.cpp +++ b/examples/ExampleBrowser/OpenGLGuiHelper.cpp @@ -437,7 +437,7 @@ void OpenGLGuiHelper::createCollisionShapeGraphicsObject(btCollisionShape* colli if (vertices.size() && indices.size()) { - int shapeId = m_data->m_glApp->m_renderer->registerShape(&vertices[0].xyzw[0],vertices.size(),&indices[0],indices.size()); + int shapeId = registerGraphicsShape(&vertices[0].xyzw[0],vertices.size(),&indices[0],indices.size()); collisionShape->setUserIndex(shapeId); } diff --git a/examples/ExampleBrowser/premake4.lua b/examples/ExampleBrowser/premake4.lua index 9239b5924..f671d5a0d 100644 --- a/examples/ExampleBrowser/premake4.lua +++ b/examples/ExampleBrowser/premake4.lua @@ -46,6 +46,8 @@ project "App_BulletExampleBrowser" files {"../LuaDemo/LuaPhysicsSetup.cpp"} end + defines {"INCLUDE_CLOTH_DEMOS"} + files { "main.cpp", "ExampleEntries.cpp", diff --git a/examples/OpenGLWindow/GLInstancingRenderer.cpp b/examples/OpenGLWindow/GLInstancingRenderer.cpp index 2bd7c92ad..e6304ad70 100644 --- a/examples/OpenGLWindow/GLInstancingRenderer.cpp +++ b/examples/OpenGLWindow/GLInstancingRenderer.cpp @@ -561,9 +561,9 @@ void GLInstancingRenderer::updateTexture(int textureIndex, const unsigned cha { for (int j = 0; j < h.m_height; j++) { - flippedTexels[(i + j*h.m_width) * 3] = texels[(i + (h.m_height-1-j)*h.m_width) * 3]; - flippedTexels[(i + j*h.m_width) * 3+1] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1]; - flippedTexels[(i + j*h.m_width) * 3+2] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1]; + flippedTexels[(i + j*h.m_width) * 3] = texels[(i + (h.m_height - 1 -j )*h.m_width) * 3]; + flippedTexels[(i + j*h.m_width) * 3+1] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1]; + flippedTexels[(i + j*h.m_width) * 3+2] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+2]; } } diff --git a/examples/TinyRenderer/TinyRenderer.cpp b/examples/TinyRenderer/TinyRenderer.cpp index bbc9bbf16..a78e9d6ac 100644 --- a/examples/TinyRenderer/TinyRenderer.cpp +++ b/examples/TinyRenderer/TinyRenderer.cpp @@ -3,12 +3,13 @@ #include #include #include -#include "TinyRenderer/tgaimage.h" -#include "TinyRenderer/model.h" -#include "TinyRenderer/geometry.h" -#include "TinyRenderer/our_gl.h" +#include "tgaimage.h" +#include "model.h" +#include "geometry.h" +#include "our_gl.h" #include "../Utils/b3ResourcePath.h" #include "Bullet3Common/b3MinMax.h" +#include "../OpenGLWindow/ShapeData.h" Vec3f light_dir_world(1,1,1); @@ -35,7 +36,11 @@ struct Shader : public IShader { } virtual Vec4f vertex(int iface, int nthvert) { - varying_uv.set_col(nthvert, m_model->uv(iface, nthvert)); + + Vec2f uv = m_model->uv(iface, nthvert); + //printf("uv = %f,%f\n", uv.x,uv.y); + varying_uv.set_col(nthvert, uv); + varying_nrm.set_col(nthvert, proj<3>((m_projectionMatrix*m_modelView).invert_transpose()*embed<4>(m_model->normal(iface, nthvert), 0.f))); Vec4f gl_Vertex = m_projectionMatrix*m_modelView*embed<4>(m_model->vert(iface, nthvert)); varying_tri.set_col(nthvert, gl_Vertex); @@ -64,49 +69,37 @@ struct Shader : public IShader { Vec3f n = (B*m_model->normal(uv)).normalize(); - float diff = b3Min(b3Max(0.f, n*m_light_dir_local+0.6f),1.f); + //float diff = b3Min(b3Max(0.f, n*m_light_dir_local+0.3f),1.f); + float diff = b3Max(0.f, n*m_light_dir_local); color = m_model->diffuse(uv)*diff; return false; } }; -/* -struct TinyRenderObjectData -{ - //Camera - Matrix m_viewMatrix; - Matrix m_projectionMatrix; - Matrix m_viewPortMatrix; - //Model (vertices, indices, textures, shader) - Matrix m_modelMatrix; - class Model* m_model; - class IShader* m_shader; - - - //Output - TGAImage m_rgbColorBuffer; - b3AlignedObjectArray m_depthBuffer; -}; -*/ - -TinyRenderObjectData::TinyRenderObjectData(int width, int height, const char* fileName) +TinyRenderObjectData::TinyRenderObjectData(int width, int height,TGAImage& rgbColorBuffer,b3AlignedObjectArray&depthBuffer) :m_width(width), m_height(height), -m_rgbColorBuffer(width,height,TGAImage::RGB), -m_model(0) +m_rgbColorBuffer(rgbColorBuffer), +m_depthBuffer(depthBuffer), +m_model(0), +m_userData(0), +m_userIndex(-1) { Vec3f eye(1,1,3); Vec3f center(0,0,0); Vec3f up(0,1,0); + m_modelMatrix = Matrix::identity(); m_viewMatrix = lookat(eye, center, up); m_viewportMatrix = viewport(width/8, height/8, width*3/4, height*3/4); m_projectionMatrix = projection(-1.f/(eye-center).norm()); + +} - - m_depthBuffer.resize(width*height); +void TinyRenderObjectData::loadModel(const char* fileName) +{ //todo(erwincoumans) move the file loading out of here char relativeFileName[1024]; if (!b3ResourcePath::findResourcePath(fileName, relativeFileName, 1024)) @@ -115,9 +108,73 @@ m_model(0) } else { m_model = new Model(relativeFileName); + } +} + + +void TinyRenderObjectData::registerMeshShape(const float* vertices, int numVertices,const int* indices, int numIndices) +{ + if (0==m_model) + { + m_model = new Model(); + char relativeFileName[1024]; + if (b3ResourcePath::findResourcePath("floor_diffuse.tga", relativeFileName, 1024)) + { + m_model->loadDiffuseTexture(relativeFileName); + } + + for (int i=0;iaddVertex(vertices[i*9], + vertices[i*9+1], + vertices[i*9+2], + vertices[i*9+4], + vertices[i*9+5], + vertices[i*9+6], + vertices[i*9+7], + vertices[i*9+8]); + } + for (int i=0;iaddTriangle(indices[i],indices[i],indices[i], + indices[i+1],indices[i+1],indices[i+1], + indices[i+2],indices[i+2],indices[i+2]); + } + } +} +void TinyRenderObjectData::createCube(float halfExtentsX,float halfExtentsY,float halfExtentsZ) +{ + m_model = new Model(); + + char relativeFileName[1024]; + if (b3ResourcePath::findResourcePath("floor_diffuse.tga", relativeFileName, 1024)) + { + m_model->loadDiffuseTexture(relativeFileName); } - + + int strideInBytes = 9*sizeof(float); + int numVertices = sizeof(cube_vertices_textured)/strideInBytes; + int numIndices = sizeof(cube_indices)/sizeof(int); + + for (int i=0;iaddVertex(halfExtentsX*cube_vertices_textured[i*9], + halfExtentsY*cube_vertices_textured[i*9+1], + halfExtentsY*cube_vertices_textured[i*9+2], + cube_vertices_textured[i*9+4], + cube_vertices_textured[i*9+5], + cube_vertices_textured[i*9+6], + cube_vertices_textured[i*9+7], + cube_vertices_textured[i*9+8]); + } + for (int i=0;iaddTriangle(cube_indices[i],cube_indices[i],cube_indices[i], + cube_indices[i+1],cube_indices[i+1],cube_indices[i+1], + cube_indices[i+2],cube_indices[i+2],cube_indices[i+2]); + } + } TinyRenderObjectData::~TinyRenderObjectData() @@ -127,34 +184,20 @@ TinyRenderObjectData::~TinyRenderObjectData() void TinyRenderer::renderObject(TinyRenderObjectData& renderData) { - const char* fileName = "obj/floor.obj"; - - - -//new Model(relativeFileName);//argv[m]); Model* model = renderData.m_model; if (0==model) return; - const int width = renderData.m_width; - const int height = renderData.m_height; b3AlignedObjectArray& zbuffer = renderData.m_depthBuffer; - //todo(erwincoumans) make this a separate call - for (int i=width*height; i--; zbuffer[i] = -std::numeric_limits::max()); - TGAImage& frame = renderData.m_rgbColorBuffer; - - //lookat(eye, center, up); - //viewport(width/8, height/8, width*3/4, height*3/4); - //projection(-1.f/(eye-center).norm()); - - Vec3f light_dir_local = proj<3>((renderData.m_projectionMatrix*renderData.m_viewMatrix*embed<4>(light_dir_world, 0.f))).normalize(); + + Vec3f light_dir_local = proj<3>((renderData.m_projectionMatrix*renderData.m_viewMatrix*renderData.m_modelMatrix*embed<4>(light_dir_world, 0.f))).normalize(); { - //for (int m=1; mnfaces(); i++) { for (int j=0; j<3; j++) { shader.vertex(i, j); @@ -163,9 +206,6 @@ void TinyRenderer::renderObject(TinyRenderObjectData& renderData) } } - //frame.flip_vertically(); // to place the origin in the bottom left corner of the image - //frame.write_tga_file("framebuffer.tga"); - } diff --git a/examples/TinyRenderer/TinyRenderer.h b/examples/TinyRenderer/TinyRenderer.h index 1bcd49b95..86514b545 100644 --- a/examples/TinyRenderer/TinyRenderer.h +++ b/examples/TinyRenderer/TinyRenderer.h @@ -1,10 +1,9 @@ #ifndef TINY_RENDERER_H #define TINY_RENDERER_H -//#include "TinyRenderer/our_gl.h" -#include "TinyRenderer/geometry.h" +#include "geometry.h" #include "Bullet3Common/b3AlignedObjectArray.h" -#include "TinyRenderer/tgaimage.h" +#include "tgaimage.h" struct TinyRenderObjectData { @@ -14,19 +13,25 @@ struct TinyRenderObjectData Matrix m_viewportMatrix; //Model (vertices, indices, textures, shader) - Matrix m_modelMatrix; + Matrix m_modelMatrix; class Model* m_model; //class IShader* m_shader; todo(erwincoumans) expose the shader, for now we use a default shader //Output int m_width; int m_height; - TGAImage m_rgbColorBuffer; - b3AlignedObjectArray m_depthBuffer; + TGAImage& m_rgbColorBuffer; + b3AlignedObjectArray& m_depthBuffer; - TinyRenderObjectData(int width, int height, const char* objFileName); + TinyRenderObjectData(int width, int height,TGAImage& rgbColorBuffer,b3AlignedObjectArray& depthBuffer); virtual ~TinyRenderObjectData(); + void loadModel(const char* fileName); + void createCube(float HalfExtentsX,float HalfExtentsY,float HalfExtentsZ); + void registerMeshShape(const float* vertices, int numVertices,const int* indices, int numIndices); + + void* m_userData; + int m_userIndex; }; diff --git a/examples/TinyRenderer/main.cpp b/examples/TinyRenderer/main.cpp index 65a3352f6..b6ca73126 100644 --- a/examples/TinyRenderer/main.cpp +++ b/examples/TinyRenderer/main.cpp @@ -1,6 +1,8 @@ #include "OpenGLWindow/SimpleOpenGL3App.h" #include "Bullet3Common/b3Quaternion.h" #include "Bullet3Common/b3CommandLineArgs.h" +#include "Bullet3Common/b3Transform.h" + #include "assert.h" #include @@ -81,8 +83,16 @@ int main(int argc, char* argv[]) int textureWidth = gWidth; int textureHeight = gHeight; - TinyRenderObjectData renderData(textureWidth, textureHeight, "floor.obj"); - + TGAImage rgbColorBuffer(textureWidth,textureHeight,TGAImage::RGB); + b3AlignedObjectArray depthBuffer; + depthBuffer.resize(textureWidth*textureHeight); + + TinyRenderObjectData renderData(textureWidth, textureHeight,rgbColorBuffer,depthBuffer);//, "african_head/african_head.obj");//floor.obj"); + + //renderData.loadModel("african_head/african_head.obj"); + renderData.loadModel("floor.obj"); + + //renderData.createCube(1,1,1); myArgs.GetCmdLineArgument("mp4_file",gVideoFileName); @@ -123,19 +133,7 @@ int main(int argc, char* argv[]) app->m_instancingRenderer->init(); app->m_instancingRenderer->updateCamera(); - float projMat[16]; - app->m_instancingRenderer->getActiveCamera()->getCameraProjectionMatrix(projMat); - float viewMat[16]; - app->m_instancingRenderer->getActiveCamera()->getCameraViewMatrix(viewMat); - for (int i=0;i<4;i++) - { - for (int j=0;j<4;j++) - { - renderData.m_viewMatrix[i][j] = viewMat[i+4*j]; - //renderData.m_projectionMatrix[i][j] = projMat[i+4*j]; - } - } - + ///clear the color and z (depth) buffer for(int y=0;ym_instancingRenderer->getActiveCamera()->getCameraProjectionMatrix(projMat); + float viewMat[16]; + app->m_instancingRenderer->getActiveCamera()->getCameraViewMatrix(viewMat); + B3_ATTRIBUTE_ALIGNED16(float modelMat[16]); + + //sync the object transform + b3Transform tr; + tr.setIdentity(); + static float posUp = 0.f; + // posUp += 0.001; + b3Vector3 org = b3MakeVector3(0,posUp,0); + tr.setOrigin(org); + tr.getOpenGLMatrix(modelMat); + + for (int i=0;i<4;i++) + { + for (int j=0;j<4;j++) + { + renderData.m_viewMatrix[i][j] = viewMat[i+4*j]; + renderData.m_modelMatrix[i][j] = modelMat[i+4*j]; + } + } + + //render the object TinyRenderer::renderObject(renderData); #if 1 @@ -162,9 +187,10 @@ int main(int argc, char* argv[]) { TGAColor color = renderData.m_rgbColorBuffer.get(x,y); - pi[0] = color.bgra[2]; - pi[1] = color.bgra[1]; - pi[2] = color.bgra[0]; + pi[0] = color.bgra[2]; + pi[1] = color.bgra[1]; + pi[2] = color.bgra[0]; + pi[3] = 255; pi+=3; } } @@ -177,10 +203,13 @@ int main(int argc, char* argv[]) unsigned char* pi=image+y*textureWidth*3; for(int x=0;x>4; const unsigned char b=180; unsigned char c=b+((s+(t&1))&1)*(255-b); - pi[0]=pi[1]=pi[2]=pi[3]=c;pi+=3; + pi[0]=pi[1]=pi[2]=pi[3]=c; + pi+=3; } } #endif diff --git a/examples/TinyRenderer/model.cpp b/examples/TinyRenderer/model.cpp index bc7983dd5..f52b01126 100644 --- a/examples/TinyRenderer/model.cpp +++ b/examples/TinyRenderer/model.cpp @@ -44,6 +44,34 @@ Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffus load_texture(filename, "_spec.tga", specularmap_); } +Model::Model():verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_() +{ +} + +void Model::loadDiffuseTexture(const char* relativeFileName) +{ + diffusemap_.read_tga_file(relativeFileName); +} + +void Model::addVertex(float x,float y,float z, float normalX, float normalY, float normalZ, float u, float v) +{ + verts_.push_back(Vec3f(x,y,z)); + norms_.push_back(Vec3f(normalX,normalY,normalZ)); + uv_.push_back(Vec2f(u,v)); + +} +void Model::addTriangle(int vertexposIndex0, int normalIndex0, int uvIndex0, + int vertexposIndex1, int normalIndex1, int uvIndex1, + int vertexposIndex2, int normalIndex2, int uvIndex2) +{ + std::vector f; + f.push_back(Vec3i(vertexposIndex0, normalIndex0, uvIndex0)); + f.push_back(Vec3i(vertexposIndex1, normalIndex1, uvIndex1)); + f.push_back(Vec3i(vertexposIndex2, normalIndex2, uvIndex2)); + faces_.push_back(f); +} + + Model::~Model() {} int Model::nverts() { diff --git a/examples/TinyRenderer/model.h b/examples/TinyRenderer/model.h index 035cc119a..72f505f9a 100644 --- a/examples/TinyRenderer/model.h +++ b/examples/TinyRenderer/model.h @@ -17,6 +17,13 @@ private: void load_texture(std::string filename, const char *suffix, TGAImage &img); public: Model(const char *filename); + Model(); + void loadDiffuseTexture(const char* relativeFileName); + void addVertex(float x,float y,float z, float normalX, float normalY, float normalZ, float u, float v); + void addTriangle(int vertexposIndex0, int normalIndex0, int uvIndex0, + int vertexposIndex1, int normalIndex1, int uvIndex1, + int vertexposIndex2, int normalIndex2, int uvIndex2); + ~Model(); int nverts(); int nfaces(); diff --git a/examples/TinyRenderer/our_gl.cpp b/examples/TinyRenderer/our_gl.cpp index 4c99c0685..867c2cdd3 100644 --- a/examples/TinyRenderer/our_gl.cpp +++ b/examples/TinyRenderer/our_gl.cpp @@ -61,23 +61,36 @@ Vec3f barycentric(Vec2f A, Vec2f B, Vec2f C, Vec2f P) { void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix) { mat<3,4,float> pts = (viewPortMatrix*clipc).transpose(); // transposed to ease access to each of the points - mat<3,2,float> pts2; + + + //we don't clip triangles that cross the near plane, just discard them instead of showing artifacts + if (pts[0][3]<0 || pts[1][3] <0 || pts[2][3] <0) + return; + + + mat<3,2,float> pts2; for (int i=0; i<3; i++) pts2[i] = proj<2>(pts[i]/pts[i][3]); Vec2f bboxmin( std::numeric_limits::max(), std::numeric_limits::max()); Vec2f bboxmax(-std::numeric_limits::max(), -std::numeric_limits::max()); Vec2f clamp(image.get_width()-1, image.get_height()-1); + for (int i=0; i<3; i++) { for (int j=0; j<2; j++) { bboxmin[j] = b3Max(0.f, b3Min(bboxmin[j], pts2[i][j])); bboxmax[j] = b3Min(clamp[j], b3Max(bboxmax[j], pts2[i][j])); } } - Vec2i P; + + + + Vec2i P; TGAColor color; for (P.x=bboxmin.x; P.x<=bboxmax.x; P.x++) { for (P.y=bboxmin.y; P.y<=bboxmax.y; P.y++) { Vec3f bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P); + + Vec3f bc_clip = Vec3f(bc_screen.x/pts[0][3], bc_screen.y/pts[1][3], bc_screen.z/pts[2][3]); bc_clip = bc_clip/(bc_clip.x+bc_clip.y+bc_clip.z); float frag_depth = clipc[2]*bc_clip; diff --git a/examples/TinyRenderer/tgaimage.cpp b/examples/TinyRenderer/tgaimage.cpp index 47e6ff833..b68fb32fc 100644 --- a/examples/TinyRenderer/tgaimage.cpp +++ b/examples/TinyRenderer/tgaimage.cpp @@ -141,7 +141,7 @@ bool TGAImage::load_rle_data(std::ifstream &in) { return true; } -bool TGAImage::write_tga_file(const char *filename, bool rle) { +bool TGAImage::write_tga_file(const char *filename, bool rle) const { unsigned char developer_area_ref[4] = {0, 0, 0, 0}; unsigned char extension_area_ref[4] = {0, 0, 0, 0}; unsigned char footer[18] = {'T','R','U','E','V','I','S','I','O','N','-','X','F','I','L','E','.','\0'}; @@ -202,7 +202,7 @@ bool TGAImage::write_tga_file(const char *filename, bool rle) { } // TODO: it is not necessary to break a raw chunk for two equal pixels (for the matter of the resulting size) -bool TGAImage::unload_rle_data(std::ofstream &out) { +bool TGAImage::unload_rle_data(std::ofstream &out) const { const unsigned char max_chunk_length = 128; unsigned long npixels = width*height; unsigned long curpix = 0; @@ -244,9 +244,9 @@ bool TGAImage::unload_rle_data(std::ofstream &out) { return true; } -TGAColor TGAImage::get(int x, int y) { +TGAColor TGAImage::get(int x, int y) const { if (!data || x<0 || y<0 || x>=width || y>=height) { - return TGAColor(); + return TGAColor(128.f,128.f,128.f,255.f); } return TGAColor(data+(x+y*width)*bytespp, bytespp); } diff --git a/examples/TinyRenderer/tgaimage.h b/examples/TinyRenderer/tgaimage.h index 63a944bca..7a4dbfae9 100644 --- a/examples/TinyRenderer/tgaimage.h +++ b/examples/TinyRenderer/tgaimage.h @@ -68,7 +68,7 @@ protected: int bytespp; bool load_rle_data(std::ifstream &in); - bool unload_rle_data(std::ofstream &out); + bool unload_rle_data(std::ofstream &out) const; public: enum Format { GRAYSCALE=1, RGB=3, RGBA=4 @@ -78,11 +78,12 @@ public: TGAImage(int w, int h, int bpp); TGAImage(const TGAImage &img); bool read_tga_file(const char *filename); - bool write_tga_file(const char *filename, bool rle=true); + bool write_tga_file(const char *filename, bool rle=true) const; bool flip_horizontally(); bool flip_vertically(); bool scale(int w, int h); - TGAColor get(int x, int y); + TGAColor get(int x, int y) const; + bool set(int x, int y, TGAColor &c); bool set(int x, int y, const TGAColor &c); ~TGAImage(); From ab4299f5177138d7648ed9853e7320c3f7c8d92e Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Fri, 29 Apr 2016 14:45:15 -0700 Subject: [PATCH 23/50] expose the local inertial frame for each link in the shared memory API struct b3LinkState { double m_worldPosition[3];//this is the inertial frame double m_worldOrientation[4]; double m_localInertialPosition[3];//this is the local frame from inertial to link frame double m_localInertialOrientation[4]; }; const btTransform link_frame_world = inertial_frame_world * m_local_inertial_frame->inverse(); --- examples/SharedMemory/PhysicsClientC_API.cpp | 2 ++ .../PhysicsServerCommandProcessor.cpp | 22 +++++++++++++++++++ examples/SharedMemory/SharedMemoryCommands.h | 2 ++ examples/SharedMemory/SharedMemoryPublic.h | 10 +++++++-- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/examples/SharedMemory/PhysicsClientC_API.cpp b/examples/SharedMemory/PhysicsClientC_API.cpp index 809413c16..33b8593be 100644 --- a/examples/SharedMemory/PhysicsClientC_API.cpp +++ b/examples/SharedMemory/PhysicsClientC_API.cpp @@ -233,10 +233,12 @@ void b3GetLinkState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandle for (int i = 0; i < 3; ++i) { state->m_worldPosition[i] = status->m_sendActualStateArgs.m_linkState[7 * linkIndex + i]; + state->m_localInertialPosition[i] = status->m_sendActualStateArgs.m_linkLocalInertialFrames[7 * linkIndex + i]; } for (int i = 0; i < 4; ++i) { state->m_worldOrientation[i] = status->m_sendActualStateArgs.m_linkState[7 * linkIndex + 3 + i]; + state->m_localInertialOrientation[i] = status->m_sendActualStateArgs.m_linkLocalInertialFrames[7 * linkIndex + 3 + i]; } } } diff --git a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp index f498fccaf..82040713d 100644 --- a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp +++ b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp @@ -82,6 +82,7 @@ struct InteralBodyData int m_testData; btTransform m_rootLocalInertialFrame; + btAlignedObjectArray m_linkLocalInertialFrames; InteralBodyData() :m_multiBody(0), @@ -763,11 +764,18 @@ bool PhysicsServerCommandProcessor::loadUrdf(const char* fileName, const btVecto //disable serialization of the collision objects (they are too big, and the client likely doesn't need them); util->m_memSerializer->m_skipPointers.insert(mb->getBaseCollider(),0); + bodyHandle->m_linkLocalInertialFrames.reserve(mb->getNumLinks()); for (int i=0;igetNumLinks();i++) { //disable serialization of the collision objects util->m_memSerializer->m_skipPointers.insert(mb->getLink(i).m_collider,0); int urdfLinkIndex = creation.m_mb2urdfLink[i]; + btScalar mass; + btVector3 localInertiaDiagonal(0,0,0); + btTransform localInertialFrame; + u2b.getMassAndInertia(urdfLinkIndex, mass,localInertiaDiagonal,localInertialFrame); + bodyHandle->m_linkLocalInertialFrames.push_back(localInertialFrame); + std::string* linkName = new std::string(u2b.getLinkName(urdfLinkIndex).c_str()); m_data->m_strings.push_back(linkName); util->m_memSerializer->registerNameForPointer(linkName->c_str(),linkName->c_str()); @@ -1349,8 +1357,12 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm //} } } + btVector3 linkLocalInertialOrigin = body->m_linkLocalInertialFrames[l].getOrigin(); + btQuaternion linkLocalInertialRotation = body->m_linkLocalInertialFrames[l].getRotation(); + btVector3 linkOrigin = mb->getLink(l).m_cachedWorldTransform.getOrigin(); btQuaternion linkRotation = mb->getLink(l).m_cachedWorldTransform.getRotation(); + serverCmd.m_sendActualStateArgs.m_linkState[l*7+0] = linkOrigin.getX(); serverCmd.m_sendActualStateArgs.m_linkState[l*7+1] = linkOrigin.getY(); serverCmd.m_sendActualStateArgs.m_linkState[l*7+2] = linkOrigin.getZ(); @@ -1358,6 +1370,16 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm serverCmd.m_sendActualStateArgs.m_linkState[l*7+4] = linkRotation.y(); serverCmd.m_sendActualStateArgs.m_linkState[l*7+5] = linkRotation.z(); serverCmd.m_sendActualStateArgs.m_linkState[l*7+6] = linkRotation.w(); + + serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+0] = linkLocalInertialOrigin.getX(); + serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+1] = linkLocalInertialOrigin.getY(); + serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+2] = linkLocalInertialOrigin.getZ(); + + serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+3] = linkLocalInertialRotation.x(); + serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+4] = linkLocalInertialRotation.y(); + serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+5] = linkLocalInertialRotation.z(); + serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+6] = linkLocalInertialRotation.w(); + } diff --git a/examples/SharedMemory/SharedMemoryCommands.h b/examples/SharedMemory/SharedMemoryCommands.h index eafe68fe0..6c7b72ee8 100644 --- a/examples/SharedMemory/SharedMemoryCommands.h +++ b/examples/SharedMemory/SharedMemoryCommands.h @@ -197,7 +197,9 @@ struct SendActualStateArgs double m_jointReactionForces[6*MAX_DEGREE_OF_FREEDOM]; double m_jointMotorForce[MAX_DEGREE_OF_FREEDOM]; + double m_linkState[7*MAX_NUM_LINKS]; + double m_linkLocalInertialFrames[7*MAX_NUM_LINKS]; }; enum EnumSensorTypes diff --git a/examples/SharedMemory/SharedMemoryPublic.h b/examples/SharedMemory/SharedMemoryPublic.h index b5542a01c..9f3da3a77 100644 --- a/examples/SharedMemory/SharedMemoryPublic.h +++ b/examples/SharedMemory/SharedMemoryPublic.h @@ -105,12 +105,18 @@ struct b3DebugLines const float* m_linesColor;//float red,green,blue times 'm_numDebugLines'. }; -///b3LinkState provides extra information such as the Cartesian world coordinates of the link -///relative to the world reference frame. Orientation is a quaternion x,y,z,w +///b3LinkState provides extra information such as the Cartesian world coordinates +///center of mass (COM) of the link, relative to the world reference frame. +///Orientation is a quaternion x,y,z,w +///Note: to compute the URDF link frame (which equals the joint frame at joint position 0) +///use URDF link frame = link COM frame * inertiaFrame.inverse() struct b3LinkState { double m_worldPosition[3]; double m_worldOrientation[4]; + + double m_localInertialPosition[3]; + double m_localInertialOrientation[4]; }; //todo: discuss and decide about control mode and combinations From 1d0f038aad6858a04c7b4dbd3e2d14f3f7ad680d Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sat, 30 Apr 2016 11:18:54 -0700 Subject: [PATCH 24/50] add initial pybullet module, using the shared memory API (for now, start the example browser in 'physics server', then compile using premake --python option, then run python in the bin folder (so it finds pybullet.so) and run the test.py script in examples/pybullet folder. The robotics shared memory C API is very suitable for this. --- build3/premake4.lua | 11 ++++ examples/TinyRenderer/main.cpp | 7 +- examples/pybullet/premake4.lua | 48 ++++++++++++++ examples/pybullet/pybullet.c | 114 +++++++++++++++++++++++++++++++++ examples/pybullet/test.py | 7 ++ 5 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 examples/pybullet/premake4.lua create mode 100644 examples/pybullet/pybullet.c create mode 100644 examples/pybullet/test.py diff --git a/build3/premake4.lua b/build3/premake4.lua index 108f33473..062c08443 100644 --- a/build3/premake4.lua +++ b/build3/premake4.lua @@ -73,6 +73,14 @@ description = "Enable Lua scipting support in Example Browser" } + newoption + { + trigger = "python", + description = "Enable Python scripting (experimental, use Physics Server in Example Browser). " + } + + + newoption { trigger = "targetdir", value = "path such as ../bin", @@ -192,6 +200,9 @@ if _OPTIONS["lua"] then include "../examples/ThirdPartyLibs/lua-5.2.3" end + if _OPTIONS["python"] then + include "../examples/pybullet" + end if not _OPTIONS["no-test"] then include "../test/SharedMemory" diff --git a/examples/TinyRenderer/main.cpp b/examples/TinyRenderer/main.cpp index 6328820b2..4f50e7227 100644 --- a/examples/TinyRenderer/main.cpp +++ b/examples/TinyRenderer/main.cpp @@ -82,8 +82,11 @@ int main(int argc, char* argv[]) int textureWidth = gWidth; int textureHeight = gHeight; - - TinyRenderObjectData renderData(textureWidth, textureHeight);//, "african_head/african_head.obj");//floor.obj"); + TGAImage rgbColorBuffer(gWidth,gHeight,TGAImage::RGB); + b3AlignedObjectArray depthBuffer; + depthBuffer.resize(gWidth*gHeight); + + TinyRenderObjectData renderData(textureWidth, textureHeight,rgbColorBuffer,depthBuffer);//, "african_head/african_head.obj");//floor.obj"); //renderData.loadModel("african_head/african_head.obj"); //renderData.loadModel("floor.obj"); diff --git a/examples/pybullet/premake4.lua b/examples/pybullet/premake4.lua new file mode 100644 index 000000000..da3da721c --- /dev/null +++ b/examples/pybullet/premake4.lua @@ -0,0 +1,48 @@ + + +project ("pybullet") + + language "C++" + kind "SharedLib" + targetsuffix ("") + targetprefix ("") + targetextension (".so") + includedirs {"../../src", "../../examples", + "../../examples/ThirdPartyLibs"} + defines {"PHYSICS_IN_PROCESS_EXAMPLE_BROWSER"} + hasCL = findOpenCL("clew") + + links{"BulletExampleBrowserLib","gwen", "OpenGL_Window","BulletSoftBody", "BulletInverseDynamicsUtils", "BulletInverseDynamics", "BulletDynamics","BulletCollision","LinearMath","Bullet3Common"} + initOpenGL() + initGlew() + + includedirs { + ".", + "../../src", + "../ThirdPartyLibs", + } + + + if os.is("MacOSX") then + links{"Cocoa.framework","Python"} + end + + if (hasCL) then + links { + "Bullet3OpenCL_clew", + "Bullet3Dynamics", + "Bullet3Collision", + "Bullet3Geometry", + "Bullet3Common", + } + end + + files { + "pybullet.c", + "../../examples/ExampleBrowser/ExampleEntries.cpp", + } + if os.is("Linux") then + initX11() + end + + diff --git a/examples/pybullet/pybullet.c b/examples/pybullet/pybullet.c new file mode 100644 index 000000000..24cec5b7d --- /dev/null +++ b/examples/pybullet/pybullet.c @@ -0,0 +1,114 @@ +#include "../SharedMemory/SharedMemoryInProcessPhysicsC_API.h" +#include "../SharedMemory/PhysicsClientC_API.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +static PyObject *SpamError; +static b3PhysicsClientHandle sm; + +static PyObject * +spam_step(PyObject *self, PyObject *args) +{ + + { + b3SharedMemoryStatusHandle statusHandle; + int statusType; + + if (b3CanSubmitCommand(sm)) + { + statusHandle = b3SubmitClientCommandAndWaitStatus(sm, b3InitStepSimulationCommand(sm)); + statusType = b3GetStatusType(statusHandle); + } + } + +return PyLong_FromLong(1); +} + +static PyObject * +spam_loadURDF(PyObject* self, PyObject* args) +{ + int size= PySequence_Size(args); + + int bodyIndex = -1; + const char* urdfFileName=0; + float startPosX =0; + float startPosY =0; + float startPosZ = 1; + float startOrnX = 0; + float startOrnY = 0; + float startOrnZ = 0; + float startOwnW = 1; + printf("size=%d\n", size); + if (size==1) + { + if (!PyArg_ParseTuple(args, "s", &urdfFileName)) + return NULL; + } + if (size == 4) + { + if (!PyArg_ParseTuple(args, "sfff", &urdfFileName, + &startPosX,&startPosY,&startPosZ)) + return NULL; + } + if (size==7) + { + if (!PyArg_ParseTuple(args, "sfffffff", &urdfFileName, + &startPosX,startPosY,&startPosZ, + &startOrnX,&startOrnY,&startOrnZ, &startOwnW)) + return NULL; + } + printf("urdf filename = %s\n", urdfFileName); + b3SharedMemoryStatusHandle statusHandle; + int statusType; + b3SharedMemoryCommandHandle command = b3LoadUrdfCommandInit(sm, urdfFileName); + + //setting the initial position, orientation and other arguments are optional + int ret = b3LoadUrdfCommandSetStartPosition(command, startPosX,startPosY,startPosZ); + statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); + statusType = b3GetStatusType(statusHandle); + if (statusType!=CMD_URDF_LOADING_COMPLETED) + { + PyErr_SetString(SpamError, "Cannot load URDF file."); + return NULL; + } + bodyIndex = b3GetStatusBodyIndex(statusHandle); + return PyLong_FromLong(bodyIndex); +} + +static PyMethodDef SpamMethods[] = { + {"step", spam_step, METH_VARARGS, + "Step the simulation forward."}, +{"loadURDF", spam_loadURDF, METH_VARARGS, + "Create a multibody by loading a URDF file."}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + + +PyMODINIT_FUNC +initpybullet(void) +{ + + b3PhysicsClientHandle h; + + PyObject *m; +sm = b3ConnectSharedMemory(SHARED_MEMORY_KEY); + +//#ifdef __APPLE__ +//sm = b3CreateInProcessPhysicsServerAndConnectMainThread(0,0); +//#else +//sm = b3CreateInProcessPhysicsServerAndConnect(0,0); +//#endif + m = Py_InitModule("pybullet", SpamMethods); + if (m == NULL) + return; + + SpamError = PyErr_NewException("pybullet.error", NULL, NULL); + Py_INCREF(SpamError); + PyModule_AddObject(m, "error", SpamError); +} + + diff --git a/examples/pybullet/test.py b/examples/pybullet/test.py new file mode 100644 index 000000000..e9d111305 --- /dev/null +++ b/examples/pybullet/test.py @@ -0,0 +1,7 @@ +import pybullet +pybullet.loadURDF('r2d2.urdf') +pybullet.loadURDF('kuka_lwr/kuka.urdf',3,0,0) + +for x in range(0, 1000000): + pybullet.step() + From 3c5b4af1c3421139720b17806ab352d7736cc8b5 Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Sun, 1 May 2016 15:45:03 +0200 Subject: [PATCH 25/50] Improve HelloWorld - explain in comments the shape of the ground and better group that code - give enough time for the sphere to hit the ground - don't ask for confirmation to exit, it's annoying --- examples/HelloWorld/HelloWorld.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/HelloWorld/HelloWorld.cpp b/examples/HelloWorld/HelloWorld.cpp index f7a195746..e51e6d541 100644 --- a/examples/HelloWorld/HelloWorld.cpp +++ b/examples/HelloWorld/HelloWorld.cpp @@ -44,20 +44,24 @@ int main(int argc, char** argv) ///-----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 collisionShapes; - collisionShapes.push_back(groundShape); - btTransform groundTransform; - groundTransform.setIdentity(); - groundTransform.setOrigin(btVector3(0,-56,0)); + ///create a few basic rigid bodies + //the ground is a cube of side 100 at position y = -56. + //the sphere will hit it at y = -6, with center at -5 { + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); + + 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 @@ -113,7 +117,7 @@ int main(int argc, char** argv) ///-----stepsimulation_start----- - for (i=0;i<100;i++) + for (i=0;i<150;i++) { dynamicsWorld->stepSimulation(1.f/60.f,10); @@ -178,9 +182,5 @@ int main(int argc, char** argv) //next line is optional: it will be cleared by the destructor when the array goes out of scope collisionShapes.clear(); - - ///-----cleanup_end----- - printf("Press a key to exit\n"); - getchar(); } From 984c880b2c435816e80e1e54920b7b9be2f3aa87 Mon Sep 17 00:00:00 2001 From: erwin coumans Date: Sun, 1 May 2016 14:52:27 -0700 Subject: [PATCH 26/50] move 'main' functions into a separate folder, to make it easier to create standalone demos (console app without gui, or opengl app, and possibly even other versions, like a software renderer, producing pictures in the cloud) Add a line in an example cpp file to allow a standalone version. See examples/BasicExample.cpp: B3_STANDALONE_EXAMPLE(BasicExampleCreateFunc) --- examples/BasicDemo/BasicExample.cpp | 4 + examples/BasicDemo/main.cpp | 244 +--------------- examples/BasicDemo/premake4.lua | 46 ++- .../CommonInterfaces/CommonExampleInterface.h | 11 + .../main_console_single_example.cpp | 46 +++ .../main_opengl_single_example.cpp | 65 +++++ .../main_sw_tinyrenderer_single_example.cpp | 266 ++++++++++++++++++ 7 files changed, 435 insertions(+), 247 deletions(-) create mode 100644 examples/StandaloneMain/main_console_single_example.cpp create mode 100644 examples/StandaloneMain/main_opengl_single_example.cpp create mode 100644 examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp diff --git a/examples/BasicDemo/BasicExample.cpp b/examples/BasicDemo/BasicExample.cpp index 775f6fbb6..f5bd9486c 100644 --- a/examples/BasicDemo/BasicExample.cpp +++ b/examples/BasicDemo/BasicExample.cpp @@ -140,7 +140,11 @@ void BasicExample::renderScene() CommonExampleInterface* BasicExampleCreateFunc(CommonExampleOptions& options) { return new BasicExample(options.m_guiHelper); + } +B3_STANDALONE_EXAMPLE(BasicExampleCreateFunc) + + diff --git a/examples/BasicDemo/main.cpp b/examples/BasicDemo/main.cpp index eb5e6c958..9ee7222d6 100644 --- a/examples/BasicDemo/main.cpp +++ b/examples/BasicDemo/main.cpp @@ -26,248 +26,6 @@ subject to the following restrictions: #include "LinearMath/btTransform.h" #include "LinearMath/btHashMap.h" -#ifdef USE_GUI -#include "../TinyRenderer/TinyRenderer.h" -#include "../OpenGLWindow/SimpleOpenGL3App.h" -#include -#include "../ExampleBrowser/OpenGLGuiHelper.h" - -class SW_And_OpenGLGuiHelper : public OpenGLGuiHelper -{ - - btHashMap m_swRenderObjects; - btHashMap m_swInstances; - - - int m_swWidth; - int m_swHeight; - TGAImage m_rgbColorBuffer; - - b3AlignedObjectArray m_depthBuffer; - int m_textureHandle; - unsigned char* m_image; - GLPrimitiveRenderer* m_primRenderer; - -public: - SW_And_OpenGLGuiHelper (CommonGraphicsApp* glApp, bool useOpenGL2, int swWidth, int swHeight, GLPrimitiveRenderer* primRenderer) - :OpenGLGuiHelper(glApp,useOpenGL2), - m_swWidth(swWidth), - m_swHeight(swHeight), - m_rgbColorBuffer(swWidth,swHeight,TGAImage::RGB), - m_primRenderer(primRenderer) - { - - m_depthBuffer.resize(swWidth*swHeight); - CommonRenderInterface* render = getRenderInterface(); - m_image=new unsigned char[m_swWidth*m_swHeight*4]; - - m_textureHandle = render->registerTexture(m_image,m_swWidth,m_swHeight); - } - - void clearBuffers(TGAColor& clearColor) - { - for(int y=0;ygetUserIndex(); - int shapeIndex = obj->getCollisionShape()->getUserIndex(); - - if (colIndex>=0 && shapeIndex>=0) - { - m_swInstances.insert(colIndex,shapeIndex); - } - - } - - virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices) - { - int shapeIndex = OpenGLGuiHelper::registerGraphicsShape(vertices,numvertices,indices,numIndices); - if (shapeIndex>=0) - { - TinyRenderObjectData* swObj = new TinyRenderObjectData(m_swWidth,m_swHeight,m_rgbColorBuffer,m_depthBuffer); - //swObj->registerMeshShape(vertices,numvertices,indices,numIndices); - swObj->createCube(1,1,1);//MeshShape(vertices,numvertices,indices,numIndices); - - m_swRenderObjects.insert(shapeIndex,swObj); - } - return shapeIndex; - } - - virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) - { - int instanceId = OpenGLGuiHelper::registerGraphicsInstance(shapeIndex,position,quaternion,color,scaling); - return instanceId ; - } - - virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape) - { - OpenGLGuiHelper::createCollisionShapeGraphicsObject(collisionShape); - } - - virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld) - { - OpenGLGuiHelper::syncPhysicsToGraphics(rbWorld); - } - - virtual void render(const btDiscreteDynamicsWorld* rbWorld) - { - OpenGLGuiHelper::render(rbWorld); - - //clear the color buffer - TGAColor clearColor; - clearColor.bgra[0] = 255; - clearColor.bgra[1] = 255; - clearColor.bgra[2] = 255; - clearColor.bgra[3] = 255; - - clearBuffers(clearColor); - - - ATTRIBUTE_ALIGNED16(float modelMat[16]); - ATTRIBUTE_ALIGNED16(float viewMat[16]); - CommonRenderInterface* render = getRenderInterface(); - - render->getActiveCamera()->getCameraViewMatrix(viewMat); - - - for (int i=0;igetNumCollisionObjects();i++) - { - btCollisionObject* colObj = rbWorld->getCollisionObjectArray()[i]; - int colObjIndex = colObj->getUserIndex(); - int shapeIndex = colObj->getCollisionShape()->getUserIndex(); - if (colObjIndex>=0 && shapeIndex>=0) - { - - TinyRenderObjectData* renderObj = 0; - - int* cptr = m_swInstances[colObjIndex]; - if (cptr) - { - int c = *cptr; - TinyRenderObjectData** sptr = m_swRenderObjects[c]; - if (sptr) - { - renderObj = *sptr; - } - } - //sync the object transform - const btTransform& tr = colObj->getWorldTransform(); - tr.getOpenGLMatrix(modelMat); - - for (int i=0;i<4;i++) - { - for (int j=0;j<4;j++) - { - renderObj->m_modelMatrix[i][j] = modelMat[i+4*j]; - renderObj->m_viewMatrix[i][j] = viewMat[i+4*j]; - } - } - TinyRenderer::renderObject(*renderObj); - } - } - - for(int y=0;yactivateTexture(m_textureHandle); - render->updateTexture(m_textureHandle,m_image); - - static int counter=0; - counter++; - if (counter>10) - { - counter=0; - getFrameBuffer().write_tga_file("/Users/erwincoumans/develop/bullet3/framebuf.tga",true); - } - float color[4] = {1,1,1,1}; - m_primRenderer->drawTexturedRect(0,0,m_swWidth, m_swHeight,color,0,0,1,1,true); - - - } - - virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld) - { - OpenGLGuiHelper::autogenerateGraphicsObjects(rbWorld); - } - -}; - -int main(int argc, char* argv[]) -{ - - SimpleOpenGL3App* app = new SimpleOpenGL3App("BasicDemoGui",1024,768,true); - int textureWidth = 640; - int textureHeight = 480; - - - SW_And_OpenGLGuiHelper gui(app,false,textureWidth,textureHeight,app->m_primRenderer); - - CommonExampleOptions options(&gui); - CommonExampleInterface* example = BasicExampleCreateFunc(options); - - example->initPhysics(); - - do - { - app->m_instancingRenderer->init(); - app->m_instancingRenderer->updateCamera(); - - example->stepSimulation(1./60.); - - - example->renderScene(); - - app->drawGrid(); - app->swapBuffer(); - } while (!app->m_window->requestedExit()); - - example->exitPhysics(); - delete example; - delete app; - return 0; -} - - -#else int main(int argc, char* argv[]) { @@ -285,5 +43,5 @@ int main(int argc, char* argv[]) return 0; } -#endif + diff --git a/examples/BasicDemo/premake4.lua b/examples/BasicDemo/premake4.lua index 8e9625e55..2b2a7d45f 100644 --- a/examples/BasicDemo/premake4.lua +++ b/examples/BasicDemo/premake4.lua @@ -28,7 +28,44 @@ if _OPTIONS["ios"] then else kind "ConsoleApp" end -defines {"USE_GUI"} +defines {"B3_USE_STANDALONE_EXAMPLE"} + +includedirs {"../../src"} + +links { + "BulletDynamics","BulletCollision", "LinearMath", "OpenGL_Window","Bullet3Common" +} + + initOpenGL() + initGlew() + + +language "C++" + +files { + "BasicExample.cpp", + "*.h", + "../StandaloneMain/main_opengl_single_example.cpp", + "../ExampleBrowser/OpenGLGuiHelper.cpp", + "../ExampleBrowser/GL_ShapeDrawer.cpp", +} + +if os.is("Linux") then initX11() end + +if os.is("MacOSX") then + links{"Cocoa.framework"} +end + + + +project "App_BasicExampleGuiWithSoftwareRenderer" + +if _OPTIONS["ios"] then + kind "WindowedApp" +else + kind "ConsoleApp" +end +defines {"B3_USE_STANDALONE_EXAMPLE"} includedirs {"../../src"} @@ -43,8 +80,9 @@ links { language "C++" files { - "**.cpp", - "**.h", + "BasicExample.cpp", + "*.h", + "../StandaloneMain/main_sw_tinyrenderer_single_example.cpp", "../ExampleBrowser/OpenGLGuiHelper.cpp", "../ExampleBrowser/GL_ShapeDrawer.cpp", "../TinyRenderer/geometry.cpp", @@ -60,4 +98,4 @@ if os.is("Linux") then initX11() end if os.is("MacOSX") then links{"Cocoa.framework"} end - + \ No newline at end of file diff --git a/examples/CommonInterfaces/CommonExampleInterface.h b/examples/CommonInterfaces/CommonExampleInterface.h index 71ced8fca..28859f99e 100644 --- a/examples/CommonInterfaces/CommonExampleInterface.h +++ b/examples/CommonInterfaces/CommonExampleInterface.h @@ -48,6 +48,17 @@ public: }; +CommonExampleInterface* StandaloneExampleCreateFunc(CommonExampleOptions& options); + +#ifdef B3_USE_STANDALONE_EXAMPLE + #define B3_STANDALONE_EXAMPLE(ExampleFunc) CommonExampleInterface* StandaloneExampleCreateFunc(CommonExampleOptions& options)\ + {\ + return ExampleFunc(options);\ + } +#else//B3_USE_STANDALONE_EXAMPLE + #define B3_STANDALONE_EXAMPLE(ExampleFunc) +#endif //B3_USE_STANDALONE_EXAMPLE + #endif //COMMON_EXAMPLE_INTERFACE_H diff --git a/examples/StandaloneMain/main_console_single_example.cpp b/examples/StandaloneMain/main_console_single_example.cpp new file mode 100644 index 000000000..e1f5b6dd8 --- /dev/null +++ b/examples/StandaloneMain/main_console_single_example.cpp @@ -0,0 +1,46 @@ +/* +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 "../CommonInterfaces/CommonExampleInterface.h" +#include "../CommonInterfaces/CommonGUIHelperInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + + +#include "LinearMath/btTransform.h" +#include "LinearMath/btHashMap.h" + + +int main(int argc, char* argv[]) +{ + + DummyGUIHelper noGfx; + + CommonExampleOptions options(&noGfx); + CommonExampleInterface* example = StandaloneExampleCreateFunc(options); + + example->initPhysics(); + example->stepSimulation(1.f/60.f); + example->exitPhysics(); + + delete example; + + return 0; +} + + diff --git a/examples/StandaloneMain/main_opengl_single_example.cpp b/examples/StandaloneMain/main_opengl_single_example.cpp new file mode 100644 index 000000000..4fd1ff422 --- /dev/null +++ b/examples/StandaloneMain/main_opengl_single_example.cpp @@ -0,0 +1,65 @@ +/* +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 "../CommonInterfaces/CommonExampleInterface.h" +#include "../CommonInterfaces/CommonGUIHelperInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + + +#include "LinearMath/btTransform.h" +#include "LinearMath/btHashMap.h" + + + +#include "../OpenGLWindow/SimpleOpenGL3App.h" +#include +#include "../ExampleBrowser/OpenGLGuiHelper.h" + + +int main(int argc, char* argv[]) +{ + + SimpleOpenGL3App* app = new SimpleOpenGL3App("Bullet Standalone Example",1024,768,true); + + OpenGLGuiHelper gui(app,false); + + CommonExampleOptions options(&gui); + CommonExampleInterface* example = StandaloneExampleCreateFunc(options); + + example->initPhysics(); + + do + { + app->m_instancingRenderer->init(); + app->m_instancingRenderer->updateCamera(); + + example->stepSimulation(1./60.); + + example->renderScene(); + + app->drawGrid(); + app->swapBuffer(); + } while (!app->m_window->requestedExit()); + + example->exitPhysics(); + delete example; + delete app; + return 0; +} + diff --git a/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp b/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp new file mode 100644 index 000000000..230f5e651 --- /dev/null +++ b/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp @@ -0,0 +1,266 @@ +/* +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 "../CommonInterfaces/CommonExampleInterface.h" +#include "../CommonInterfaces/CommonGUIHelperInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + + +#include "LinearMath/btTransform.h" +#include "LinearMath/btHashMap.h" + + +#include "../TinyRenderer/TinyRenderer.h" +#include "../OpenGLWindow/SimpleOpenGL3App.h" +#include +#include "../ExampleBrowser/OpenGLGuiHelper.h" + +class SW_And_OpenGLGuiHelper : public OpenGLGuiHelper +{ + + btHashMap m_swRenderObjects; + btHashMap m_swInstances; + + int m_swWidth; + int m_swHeight; + TGAImage m_rgbColorBuffer; + + b3AlignedObjectArray m_depthBuffer; + int m_textureHandle; + unsigned char* m_image; + GLPrimitiveRenderer* m_primRenderer; + +public: + SW_And_OpenGLGuiHelper (CommonGraphicsApp* glApp, bool useOpenGL2, int swWidth, int swHeight, GLPrimitiveRenderer* primRenderer) + :OpenGLGuiHelper(glApp,useOpenGL2), + m_swWidth(swWidth), + m_swHeight(swHeight), + m_rgbColorBuffer(swWidth,swHeight,TGAImage::RGB), + m_primRenderer(primRenderer) + { + + m_depthBuffer.resize(swWidth*swHeight); + CommonRenderInterface* render = getRenderInterface(); + m_image=new unsigned char[m_swWidth*m_swHeight*4]; + + m_textureHandle = render->registerTexture(m_image,m_swWidth,m_swHeight); + } + + void clearBuffers(TGAColor& clearColor) + { + for(int y=0;ygetUserIndex(); + int shapeIndex = obj->getCollisionShape()->getUserIndex(); + + if (colIndex>=0 && shapeIndex>=0) + { + m_swInstances.insert(colIndex,shapeIndex); + } + + } + + virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices) + { + int shapeIndex = OpenGLGuiHelper::registerGraphicsShape(vertices,numvertices,indices,numIndices); + if (shapeIndex>=0) + { + TinyRenderObjectData* swObj = new TinyRenderObjectData(m_swWidth,m_swHeight,m_rgbColorBuffer,m_depthBuffer); + //swObj->registerMeshShape(vertices,numvertices,indices,numIndices); + swObj->createCube(1,1,1);//MeshShape(vertices,numvertices,indices,numIndices); + m_swRenderObjects.insert(shapeIndex,swObj); + } + return shapeIndex; + } + + virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) + { + int instanceId = OpenGLGuiHelper::registerGraphicsInstance(shapeIndex,position,quaternion,color,scaling); + return instanceId ; + } + + virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape) + { + OpenGLGuiHelper::createCollisionShapeGraphicsObject(collisionShape); + } + + virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld) + { + OpenGLGuiHelper::syncPhysicsToGraphics(rbWorld); + } + + virtual void render(const btDiscreteDynamicsWorld* rbWorld) + { + OpenGLGuiHelper::render(rbWorld); + + //clear the color buffer + TGAColor clearColor; + clearColor.bgra[0] = 255; + clearColor.bgra[1] = 255; + clearColor.bgra[2] = 255; + clearColor.bgra[3] = 255; + + clearBuffers(clearColor); + + + ATTRIBUTE_ALIGNED16(float modelMat[16]); + ATTRIBUTE_ALIGNED16(float viewMat[16]); + CommonRenderInterface* render = getRenderInterface(); + + render->getActiveCamera()->getCameraViewMatrix(viewMat); + + + for (int i=0;igetNumCollisionObjects();i++) + { + btCollisionObject* colObj = rbWorld->getCollisionObjectArray()[i]; + int colObjIndex = colObj->getUserIndex(); + int shapeIndex = colObj->getCollisionShape()->getUserIndex(); + if (colObjIndex>=0 && shapeIndex>=0) + { + + TinyRenderObjectData* renderObj = 0; + + int* cptr = m_swInstances[colObjIndex]; + if (cptr) + { + int c = *cptr; + TinyRenderObjectData** sptr = m_swRenderObjects[c]; + if (sptr) + { + renderObj = *sptr; + } + } + //sync the object transform + const btTransform& tr = colObj->getWorldTransform(); + tr.getOpenGLMatrix(modelMat); + + for (int i=0;i<4;i++) + { + for (int j=0;j<4;j++) + { + renderObj->m_modelMatrix[i][j] = modelMat[i+4*j]; + renderObj->m_viewMatrix[i][j] = viewMat[i+4*j]; + } + } + TinyRenderer::renderObject(*renderObj); + } + } + + for(int y=0;yactivateTexture(m_textureHandle); + render->updateTexture(m_textureHandle,m_image); + + static int counter=0; + counter++; + if (counter>10) + { + counter=0; + getFrameBuffer().write_tga_file("/Users/erwincoumans/develop/bullet3/framebuf.tga",true); + } + float color[4] = {1,1,1,1}; + m_primRenderer->drawTexturedRect(0,0,m_swWidth, m_swHeight,color,0,0,1,1,true); + + + } + + virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld) + { + OpenGLGuiHelper::autogenerateGraphicsObjects(rbWorld); + } + +}; + +int main(int argc, char* argv[]) +{ + + SimpleOpenGL3App* app = new SimpleOpenGL3App("Standalone Example (Software Renderer, TinyRenderer)",1024,768,true); + int textureWidth = 640; + int textureHeight = 480; + + + SW_And_OpenGLGuiHelper gui(app,false,textureWidth,textureHeight,app->m_primRenderer); + + CommonExampleOptions options(&gui); + CommonExampleInterface* example = StandaloneExampleCreateFunc(options); + + example->initPhysics(); + + do + { + app->m_instancingRenderer->init(); + app->m_instancingRenderer->updateCamera(); + + example->stepSimulation(1./60.); + + + example->renderScene(); + + app->drawGrid(); + app->swapBuffer(); + } while (!app->m_window->requestedExit()); + + example->exitPhysics(); + delete example; + delete app; + return 0; +} + + From fb65c290330f0d53dc949773702be611edc0d0cf Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 3 May 2016 12:59:21 -0700 Subject: [PATCH 27/50] use "world" to make door static (instead of using mass = 0) minor improvements to pybullet --- data/door.urdf | 11 ++- examples/pybullet/pybullet.c | 130 ++++++++++++++++++++++++++--------- 2 files changed, 105 insertions(+), 36 deletions(-) diff --git a/data/door.urdf b/data/door.urdf index 7b0cb2eae..012597d07 100644 --- a/data/door.urdf +++ b/data/door.urdf @@ -1,10 +1,17 @@ + + + + + + + - - + + diff --git a/examples/pybullet/pybullet.c b/examples/pybullet/pybullet.c index 24cec5b7d..9bea19d17 100644 --- a/examples/pybullet/pybullet.c +++ b/examples/pybullet/pybullet.c @@ -8,15 +8,21 @@ #endif static PyObject *SpamError; -static b3PhysicsClientHandle sm; +static b3PhysicsClientHandle sm=0; + static PyObject * -spam_step(PyObject *self, PyObject *args) +pybullet_stepSimulation(PyObject *self, PyObject *args) { + if (0==sm) + { + PyErr_SetString(SpamError, "Not connected to physics server."); + return NULL; + } { - b3SharedMemoryStatusHandle statusHandle; - int statusType; + b3SharedMemoryStatusHandle statusHandle; + int statusType; if (b3CanSubmitCommand(sm)) { @@ -29,15 +35,53 @@ return PyLong_FromLong(1); } static PyObject * -spam_loadURDF(PyObject* self, PyObject* args) +pybullet_connectPhysicsServer(PyObject *self, PyObject *args) { + if (0!=sm) + { + PyErr_SetString(SpamError, "Already connected to physics server, disconnect first."); + return NULL; + } + + { + sm = b3ConnectSharedMemory(SHARED_MEMORY_KEY); + } + + return PyLong_FromLong(1); +} + +static PyObject * +pybullet_disconnectPhysicsServer(PyObject *self, PyObject *args) +{ + if (0==sm) + { + PyErr_SetString(SpamError, "Not connected to physics server."); + return NULL; + } + { + b3DisconnectSharedMemory(sm); + sm = 0; + } + + return PyLong_FromLong(1); +} + + +static PyObject * +pybullet_loadURDF(PyObject* self, PyObject* args) +{ + if (0==sm) + { + PyErr_SetString(SpamError, "Not connected to physics server."); + return NULL; + } int size= PySequence_Size(args); int bodyIndex = -1; const char* urdfFileName=0; float startPosX =0; - float startPosY =0; - float startPosZ = 1; + float startPosY =0; + float startPosZ = 1; float startOrnX = 0; float startOrnY = 0; float startOrnZ = 0; @@ -61,29 +105,56 @@ spam_loadURDF(PyObject* self, PyObject* args) &startOrnX,&startOrnY,&startOrnZ, &startOwnW)) return NULL; } - printf("urdf filename = %s\n", urdfFileName); - b3SharedMemoryStatusHandle statusHandle; - int statusType; - b3SharedMemoryCommandHandle command = b3LoadUrdfCommandInit(sm, urdfFileName); + { + printf("urdf filename = %s\n", urdfFileName); + b3SharedMemoryStatusHandle statusHandle; + int statusType; + b3SharedMemoryCommandHandle command = b3LoadUrdfCommandInit(sm, urdfFileName); - //setting the initial position, orientation and other arguments are optional - int ret = b3LoadUrdfCommandSetStartPosition(command, startPosX,startPosY,startPosZ); - statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); - statusType = b3GetStatusType(statusHandle); - if (statusType!=CMD_URDF_LOADING_COMPLETED) - { - PyErr_SetString(SpamError, "Cannot load URDF file."); - return NULL; - } - bodyIndex = b3GetStatusBodyIndex(statusHandle); + //setting the initial position, orientation and other arguments are optional + b3LoadUrdfCommandSetStartPosition(command, startPosX,startPosY,startPosZ); + statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); + statusType = b3GetStatusType(statusHandle); + if (statusType!=CMD_URDF_LOADING_COMPLETED) + { + PyErr_SetString(SpamError, "Cannot load URDF file."); + return NULL; + } + bodyIndex = b3GetStatusBodyIndex(statusHandle); + } return PyLong_FromLong(bodyIndex); } +static PyObject * +pybullet_resetSimulation(PyObject* self, PyObject* args) +{ + if (0==sm) + { + PyErr_SetString(SpamError, "Not connected to physics server."); + return NULL; + } + + { + b3SharedMemoryStatusHandle statusHandle; + statusHandle = b3SubmitClientCommandAndWaitStatus(sm, b3InitResetSimulationCommand(sm)); +// ASSERT_EQ(b3GetStatusType(statusHandle), CMD_RESET_SIMULATION_COMPLETED); + } +} static PyMethodDef SpamMethods[] = { - {"step", spam_step, METH_VARARGS, - "Step the simulation forward."}, -{"loadURDF", spam_loadURDF, METH_VARARGS, - "Create a multibody by loading a URDF file."}, + {"loadURDF", pybullet_loadURDF, METH_VARARGS, + "Create a multibody by loading a URDF file."}, + + {"connect", pybullet_connectPhysicsServer, METH_VARARGS, + "Connect to an existing physics server (using shared memory by default)."}, + {"disconnect", pybullet_disconnectPhysicsServer, METH_VARARGS, + "Disconnect from the physics server."}, + + {"resetSimulation", pybullet_resetSimulation, METH_VARARGS, + "Reset the simulation: remove all objects and start from an empty world."}, + + {"stepSimulation", pybullet_stepSimulation, METH_VARARGS, + "Step the simulation using forward dynamics."}, + {NULL, NULL, 0, NULL} /* Sentinel */ }; @@ -92,16 +163,7 @@ PyMODINIT_FUNC initpybullet(void) { - b3PhysicsClientHandle h; - PyObject *m; -sm = b3ConnectSharedMemory(SHARED_MEMORY_KEY); - -//#ifdef __APPLE__ -//sm = b3CreateInProcessPhysicsServerAndConnectMainThread(0,0); -//#else -//sm = b3CreateInProcessPhysicsServerAndConnect(0,0); -//#endif m = Py_InitModule("pybullet", SpamMethods); if (m == NULL) return; From 709a55d5ab5378a7d3fced8940e262afde73d456 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 3 May 2016 13:02:06 -0700 Subject: [PATCH 28/50] add CMake support for pybullet (still preliminary) requires shared library build: cmake .. -DBUILD_SHARED_LIBS=on then create a symbolic link from libpybullet.so to pybullet.so --- examples/CMakeLists.txt | 2 +- examples/ExampleBrowser/CMakeLists.txt | 100 +++++++++++++++++-------- examples/pybullet/CMakeLists.txt | 24 ++++++ examples/pybullet/premake4.lua | 1 + 4 files changed, 93 insertions(+), 34 deletions(-) create mode 100644 examples/pybullet/CMakeLists.txt diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4d26967f1..18c2f16c8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,5 +1,5 @@ SUBDIRS( HelloWorld BasicDemo ) IF(BUILD_BULLET3) - SUBDIRS( ExampleBrowser ThirdPartyLibs/Gwen OpenGLWindow) + SUBDIRS( ExampleBrowser ThirdPartyLibs/Gwen OpenGLWindow pybullet) ENDIF() diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index 2e8de4868..8942c3ec7 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -1,21 +1,19 @@ - INCLUDE_DIRECTORIES( . ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs ) -FILE(GLOB ExampleBrowser_SRCS "*" "GwenGUISupport/*" ) -FILE(GLOB ExampleBrowser_HDRS "*" "GwenGUISupport/*" ) +FILE(GLOB GwenGUISupport_SRCS "GwenGUISupport/*" ) +FILE(GLOB GwenGUISupport_HDRS "GwenGUISupport/*" ) - -SET(App_ExampleBrowser_SRCS - main.cpp - ExampleEntries.cpp - ExampleEntries.h +SET(BulletExampleBrowser_SRCS + OpenGLExampleBrowser.cpp + OpenGLGuiHelper.cpp InProcessExampleBrowser.cpp + GL_ShapeDrawer.cpp ../SharedMemory/PhysicsServer.cpp ../SharedMemory/PhysicsClientSharedMemory.cpp ../SharedMemory/PhysicsClient.cpp @@ -97,8 +95,10 @@ SET(App_ExampleBrowser_SRCS ../../Extras/Serialize/BulletWorldImporter/btWorldImporter.cpp ../../Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.cpp -../../Extras/Serialize/BulletFileLoader/bChunk.cpp ../../Extras/Serialize/BulletFileLoader/bFile.cpp -../../Extras/Serialize/BulletFileLoader/bDNA.cpp ../../Extras/Serialize/BulletFileLoader/btBulletFile.cpp + ../../Extras/Serialize/BulletFileLoader/bChunk.cpp + ../../Extras/Serialize/BulletFileLoader/bFile.cpp + ../../Extras/Serialize/BulletFileLoader/bDNA.cpp + ../../Extras/Serialize/BulletFileLoader/btBulletFile.cpp ../Importers/ImportBsp/BspLoader.h ../Importers/ImportBsp/ImportBspExample.h @@ -168,44 +168,76 @@ SET(App_ExampleBrowser_SRCS ../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp ../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp - - ../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 ../Utils/b3Clock.cpp ../Utils/b3Clock.h ../Utils/b3ResourcePath.cpp ../Utils/b3ResourcePath.h - ${ExampleBrowser_SRCS} - ${ExampleBrowser_HDRS} + ${GwenGUISupport_SRCS} + ${GwenGUISupport_HDRS} ${BULLET_PHYSICS_SOURCE_DIR}/build3/bullet.rc ) +IF (WIN32) + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/Glew + ) + IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES( + Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils + BulletInverseDynamics LinearMath OpenGLWindow gwen + ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + ENDIF (BUILD_SHARED_LIBS) + ADD_DEFINITIONS(-DGLEW_STATIC) +ELSE(WIN32) + IF(APPLE) + find_library(COCOA NAMES Cocoa) + MESSAGE(${COCOA}) + IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES( + Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils + BulletInverseDynamics LinearMath OpenGLWindow gwen + ${COCOA} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + ELSE(APPLE) + ENDIF (BUILD_SHARED_LIBS) + 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}/examples/ThirdPartyLibs/Glew ) + IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES( + Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils + BulletInverseDynamics LinearMath OpenGLWindow gwen + pthread dl + ) + ENDIF(BUILD_SHARED_LIBS) + ENDIF(APPLE) +ENDIF(WIN32) + + +ADD_LIBRARY(BulletExampleBrowserLib ${BulletExampleBrowser_SRCS} ) +SET_TARGET_PROPERTIES(BulletExampleBrowserLib PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletExampleBrowserLib PROPERTIES SOVERSION ${BULLET_VERSION}) + +INCLUDE_DIRECTORIES( + . + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs +) + + LINK_LIBRARIES( - Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen + BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen ) IF (WIN32) - SET(App_ExampleBrowser_SRCS ${App_ExampleBrowser_SRCS} ) INCLUDE_DIRECTORIES( - ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/Glew + ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/Glew ) LINK_LIBRARIES( ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} @@ -229,7 +261,9 @@ ENDIF(WIN32) ADD_EXECUTABLE(App_ExampleBrowser - ${App_ExampleBrowser_SRCS} + main.cpp + ExampleEntries.cpp + ExampleEntries.h ) diff --git a/examples/pybullet/CMakeLists.txt b/examples/pybullet/CMakeLists.txt new file mode 100644 index 000000000..db057eda9 --- /dev/null +++ b/examples/pybullet/CMakeLists.txt @@ -0,0 +1,24 @@ +IF (BUILD_SHARED_LIBS) + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${BULLET_PHYSICS_SOURCE_DIR}/examples + ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs + /usr/include/python2.7 + ) + +SET(pybullet_SRCS + pybullet.c + ../../examples/ExampleBrowser/ExampleEntries.cpp +) + + +ADD_LIBRARY(pybullet ${pybullet_SRCS}) + +SET_TARGET_PROPERTIES(pybullet PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(pybullet PROPERTIES SOVERSION ${BULLET_VERSION}) + + TARGET_LINK_LIBRARIES(pybullet BulletExampleBrowserLib BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen Bullet3Common) +ENDIF (BUILD_SHARED_LIBS) + + diff --git a/examples/pybullet/premake4.lua b/examples/pybullet/premake4.lua index da3da721c..39092b889 100644 --- a/examples/pybullet/premake4.lua +++ b/examples/pybullet/premake4.lua @@ -20,6 +20,7 @@ project ("pybullet") ".", "../../src", "../ThirdPartyLibs", + "/usr/include/python2.7", } From a9ef14591008a4a4347b78a104ce30d1cb047abd Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 3 May 2016 21:27:30 -0700 Subject: [PATCH 29/50] add standalone opengl version of BasicExample for cmake, called BasicExampleGui --- examples/BasicDemo/CMakeLists.txt | 69 +++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/examples/BasicDemo/CMakeLists.txt b/examples/BasicDemo/CMakeLists.txt index 716c3a064..7286d93f9 100644 --- a/examples/BasicDemo/CMakeLists.txt +++ b/examples/BasicDemo/CMakeLists.txt @@ -29,3 +29,72 @@ IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) SET_TARGET_PROPERTIES(App_BasicExample PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") SET_TARGET_PROPERTIES(App_BasicExample PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + + + + + +################# +# Standalone BasicExampleGui using OpenGL (but not the example browser) + + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${BULLET_PHYSICS_SOURCE_DIR}/btgui + ${BULLET_PHYSICS_SOURCE_DIR}/examples + ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/Glew +) + + +SET(AppBasicExampleGui_SRCS + BasicExample.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/build3/bullet.rc + ../StandaloneMain/main_opengl_single_example.cpp + ../ExampleBrowser/OpenGLGuiHelper.cpp + ../ExampleBrowser/GL_ShapeDrawer.cpp +) + +#this define maps StandaloneExampleCreateFunc to the right 'CreateFunc' +ADD_DEFINITIONS(-DB3_USE_STANDALONE_EXAMPLE) + +LINK_LIBRARIES( + BulletDynamics BulletCollision LinearMath OpenGLWindow Bullet3Common ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +#some code to support OpenGL and Glew cross platform +IF (WIN32) + 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) + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/btgui/OpenGLWindow/GlewWindows + ) + ADD_DEFINITIONS("-DGLEW_INIT_OPENGL11_FUNCTIONS=1") + ADD_DEFINITIONS("-DGLEW_STATIC") + ADD_DEFINITIONS("-DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1") + + LINK_LIBRARIES( X11 pthread dl Xext) + ENDIF(APPLE) +ENDIF(WIN32) + + +ADD_EXECUTABLE(AppBasicExampleGui + ${AppBasicExampleGui_SRCS} +) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppBasicExampleGui PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppBasicExampleGui PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppBasicExampleGui PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + + From a251ff4331eacbbffcf6cb856c63752f2ad83ebc Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 3 May 2016 21:48:28 -0700 Subject: [PATCH 30/50] add 'dl' target libs in cmake --- examples/OpenGLWindow/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/OpenGLWindow/CMakeLists.txt b/examples/OpenGLWindow/CMakeLists.txt index 1e95d87c6..f7f1db5ad 100644 --- a/examples/OpenGLWindow/CMakeLists.txt +++ b/examples/OpenGLWindow/CMakeLists.txt @@ -59,7 +59,7 @@ if (BUILD_SHARED_LIBS) else() set (CMAKE_THREAD_PREFER_PTHREAD TRUE) FIND_PACKAGE(Threads) - target_link_libraries(OpenGLWindow ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(OpenGLWindow dl ${CMAKE_THREAD_LIBS_INIT}) endif() endif() From 7a833a7ac2528b834a7ae14b6d14e2c063e9c072 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 3 May 2016 22:05:30 -0700 Subject: [PATCH 31/50] fix target link libs in cmake --- examples/ExampleBrowser/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index 8942c3ec7..66fd7109f 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -187,7 +187,7 @@ IF (WIN32) ) IF (BUILD_SHARED_LIBS) TARGET_LINK_LIBRARIES( - Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils + BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) @@ -199,7 +199,7 @@ ELSE(WIN32) MESSAGE(${COCOA}) IF (BUILD_SHARED_LIBS) TARGET_LINK_LIBRARIES( - Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils + BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen ${COCOA} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) @@ -211,7 +211,7 @@ ELSE(WIN32) INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/Glew ) IF (BUILD_SHARED_LIBS) TARGET_LINK_LIBRARIES( - Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils + BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen pthread dl ) From 938db633dfaf377a0750bd2ddb6aeae2d30adb88 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 3 May 2016 23:34:48 -0700 Subject: [PATCH 32/50] fixes in build system --- examples/ExampleBrowser/CMakeLists.txt | 57 +++---- examples/ExampleBrowser/ExampleEntries.cpp | 20 +-- examples/ExampleBrowser/ExampleEntries.h | 44 ++++-- .../InProcessExampleBrowser.cpp | 141 +++++++++++++++++- examples/ExampleBrowser/main.cpp | 2 +- examples/pybullet/CMakeLists.txt | 2 +- examples/pybullet/pybullet.c | 2 + 7 files changed, 219 insertions(+), 49 deletions(-) diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index 66fd7109f..b3f06d557 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -185,44 +185,51 @@ IF (WIN32) INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/Glew ) - IF (BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES( - BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils - BulletInverseDynamics LinearMath OpenGLWindow gwen - ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} - ) - ENDIF (BUILD_SHARED_LIBS) - ADD_DEFINITIONS(-DGLEW_STATIC) + ADD_DEFINITIONS(-DGLEW_STATIC) ELSE(WIN32) IF(APPLE) find_library(COCOA NAMES Cocoa) - MESSAGE(${COCOA}) - IF (BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES( - BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils - BulletInverseDynamics LinearMath OpenGLWindow gwen - ${COCOA} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} - ) - ELSE(APPLE) - ENDIF (BUILD_SHARED_LIBS) + 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}/examples/ThirdPartyLibs/Glew ) - IF (BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES( - BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils - BulletInverseDynamics LinearMath OpenGLWindow gwen - pthread dl - ) - ENDIF(BUILD_SHARED_LIBS) - ENDIF(APPLE) + ENDIF(APPLE) ENDIF(WIN32) ADD_LIBRARY(BulletExampleBrowserLib ${BulletExampleBrowser_SRCS} ) SET_TARGET_PROPERTIES(BulletExampleBrowserLib PROPERTIES VERSION ${BULLET_VERSION}) SET_TARGET_PROPERTIES(BulletExampleBrowserLib PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + IF (WIN32) + TARGET_LINK_LIBRARIES( + BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils + BulletInverseDynamics LinearMath OpenGLWindow gwen + ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + ELSE(WIN32) + IF(APPLE) + TARGET_LINK_LIBRARIES( + BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils + BulletInverseDynamics LinearMath OpenGLWindow gwen + ${COCOA} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + ELSE(APPLE) + TARGET_LINK_LIBRARIES( + BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils + BulletInverseDynamics LinearMath OpenGLWindow gwen + pthread dl + ) + ENDIF(APPLE) + ENDIF(WIN32) +ENDIF(BUILD_SHARED_LIBS) + +#################### +# +# Bullet Example Browser main app +# +#################### INCLUDE_DIRECTORIES( . diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index 36611663f..3ec1403d6 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -274,17 +274,17 @@ struct ExampleEntriesInternalData btAlignedObjectArray m_allExamples; }; -ExampleEntries::ExampleEntries() +ExampleEntriesAll::ExampleEntriesAll() { m_data = new ExampleEntriesInternalData; } -ExampleEntries::~ExampleEntries() +ExampleEntriesAll::~ExampleEntriesAll() { delete m_data; } -void ExampleEntries::initOpenCLExampleEntries() +void ExampleEntriesAll::initOpenCLExampleEntries() { #ifdef B3_USE_CLEW #ifndef NO_OPENGL3 @@ -297,7 +297,7 @@ void ExampleEntries::initOpenCLExampleEntries() #endif //B3_USE_CLEW } -void ExampleEntries::initExampleEntries() +void ExampleEntriesAll::initExampleEntries() { m_data->m_allExamples.clear(); @@ -330,33 +330,33 @@ void ExampleEntries::initExampleEntries() } -void ExampleEntries::registerExampleEntry(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option) +void ExampleEntriesAll::registerExampleEntry(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option) { ExampleEntry e( menuLevel,name,description, createFunc, option); gAdditionalRegisteredExamples.push_back(e); } -int ExampleEntries::getNumRegisteredExamples() +int ExampleEntriesAll::getNumRegisteredExamples() { return m_data->m_allExamples.size(); } -CommonExampleInterface::CreateFunc* ExampleEntries::getExampleCreateFunc(int index) +CommonExampleInterface::CreateFunc* ExampleEntriesAll::getExampleCreateFunc(int index) { return m_data->m_allExamples[index].m_createFunc; } -int ExampleEntries::getExampleOption(int index) +int ExampleEntriesAll::getExampleOption(int index) { return m_data->m_allExamples[index].m_option; } -const char* ExampleEntries::getExampleName(int index) +const char* ExampleEntriesAll::getExampleName(int index) { return m_data->m_allExamples[index].m_name; } -const char* ExampleEntries::getExampleDescription(int index) +const char* ExampleEntriesAll::getExampleDescription(int index) { return m_data->m_allExamples[index].m_description; } diff --git a/examples/ExampleBrowser/ExampleEntries.h b/examples/ExampleBrowser/ExampleEntries.h index f6d661adb..286e73f57 100644 --- a/examples/ExampleBrowser/ExampleEntries.h +++ b/examples/ExampleBrowser/ExampleEntries.h @@ -6,32 +6,56 @@ - class ExampleEntries +{ + +public: + + virtual ~ExampleEntries() {} + + + virtual void initExampleEntries()=0; + + virtual void initOpenCLExampleEntries()=0; + + virtual int getNumRegisteredExamples()=0; + + virtual CommonExampleInterface::CreateFunc* getExampleCreateFunc(int index)=0; + + virtual const char* getExampleName(int index)=0; + + virtual const char* getExampleDescription(int index)=0; + + virtual int getExampleOption(int index)=0; + +}; + + +class ExampleEntriesAll : public ExampleEntries { struct ExampleEntriesInternalData* m_data; public: - ExampleEntries(); - virtual ~ExampleEntries(); + ExampleEntriesAll(); + virtual ~ExampleEntriesAll(); static void registerExampleEntry(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option=0); - void initExampleEntries(); + virtual void initExampleEntries(); - void initOpenCLExampleEntries(); + virtual void initOpenCLExampleEntries(); - int getNumRegisteredExamples(); + virtual int getNumRegisteredExamples(); - CommonExampleInterface::CreateFunc* getExampleCreateFunc(int index); + virtual CommonExampleInterface::CreateFunc* getExampleCreateFunc(int index); - const char* getExampleName(int index); + virtual const char* getExampleName(int index); - const char* getExampleDescription(int index); + virtual const char* getExampleDescription(int index); - int getExampleOption(int index); + virtual int getExampleOption(int index); }; diff --git a/examples/ExampleBrowser/InProcessExampleBrowser.cpp b/examples/ExampleBrowser/InProcessExampleBrowser.cpp index d9be45726..97b0761c4 100644 --- a/examples/ExampleBrowser/InProcessExampleBrowser.cpp +++ b/examples/ExampleBrowser/InProcessExampleBrowser.cpp @@ -25,6 +25,143 @@ void* ExampleBrowserMemoryFunc(); #ifndef _WIN32 #include "../MultiThreading/b3PosixThreadSupport.h" +#include "ExampleEntries.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "EmptyExample.h" + +#include "../SharedMemory/PhysicsServerExample.h" +#include "../SharedMemory/PhysicsClientExample.h" + + + + +class ExampleEntriesPhysicsServer : public ExampleEntries +{ + + struct ExampleEntriesInternalData2* m_data; + +public: + + ExampleEntriesPhysicsServer(); + virtual ~ExampleEntriesPhysicsServer(); + + static void registerExampleEntry(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option=0); + + virtual void initExampleEntries(); + + virtual void initOpenCLExampleEntries(); + + virtual int getNumRegisteredExamples(); + + virtual CommonExampleInterface::CreateFunc* getExampleCreateFunc(int index); + + virtual const char* getExampleName(int index); + + virtual const char* getExampleDescription(int index); + + virtual int getExampleOption(int index); + +}; + + +struct ExampleEntryPhysicsServer +{ + int m_menuLevel; + const char* m_name; + const char* m_description; + CommonExampleInterface::CreateFunc* m_createFunc; + int m_option; + + ExampleEntryPhysicsServer(int menuLevel, const char* name) + :m_menuLevel(menuLevel), m_name(name), m_description(0), m_createFunc(0), m_option(0) + { + } + + ExampleEntryPhysicsServer(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option=0) + :m_menuLevel(menuLevel), m_name(name), m_description(description), m_createFunc(createFunc), m_option(option) + { + } +}; + +struct ExampleEntriesInternalData2 +{ + btAlignedObjectArray m_allExamples; +}; + +static ExampleEntryPhysicsServer gDefaultExamplesPhysicsServer[]= +{ + + ExampleEntryPhysicsServer(0,"Robotics Control"), + + ExampleEntryPhysicsServer(1,"Physics Server", "Create a physics server that communicates with a physics client over shared memory", + PhysicsServerCreateFunc), + ExampleEntryPhysicsServer(1,"Physics Server (Logging)", "Create a physics server that communicates with a physics client over shared memory. It will log all commands to a file.", + PhysicsServerCreateFunc,PHYSICS_SERVER_ENABLE_COMMAND_LOGGING), + ExampleEntryPhysicsServer(1,"Physics Server (Replay Log)", "Create a physics server that replay a command log from disk.", + PhysicsServerCreateFunc,PHYSICS_SERVER_REPLAY_FROM_COMMAND_LOG), + + ExampleEntryPhysicsServer(1, "Physics Client", "Create a physics client that can communicate with a physics server over shared memory", PhysicsClientCreateFunc), + +}; + + +ExampleEntriesPhysicsServer::ExampleEntriesPhysicsServer() +{ + m_data = new ExampleEntriesInternalData2; +} + +ExampleEntriesPhysicsServer::~ExampleEntriesPhysicsServer() +{ + delete m_data; +} + +void ExampleEntriesPhysicsServer::initOpenCLExampleEntries() +{ +} + +void ExampleEntriesPhysicsServer::initExampleEntries() +{ + m_data->m_allExamples.clear(); + + + + int numDefaultEntries = sizeof(gDefaultExamplesPhysicsServer)/sizeof(ExampleEntryPhysicsServer); + for (int i=0;im_allExamples.push_back(gDefaultExamplesPhysicsServer[i]); + } + +} + +void ExampleEntriesPhysicsServer::registerExampleEntry(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option) +{ +} + +int ExampleEntriesPhysicsServer::getNumRegisteredExamples() +{ + return m_data->m_allExamples.size(); +} + +CommonExampleInterface::CreateFunc* ExampleEntriesPhysicsServer::getExampleCreateFunc(int index) +{ + return m_data->m_allExamples[index].m_createFunc; +} + +int ExampleEntriesPhysicsServer::getExampleOption(int index) +{ + return m_data->m_allExamples[index].m_option; +} + +const char* ExampleEntriesPhysicsServer::getExampleName(int index) +{ + return m_data->m_allExamples[index].m_name; +} + +const char* ExampleEntriesPhysicsServer::getExampleDescription(int index) +{ + return m_data->m_allExamples[index].m_description; +} + static b3ThreadSupportInterface* createExampleBrowserThreadSupport(int numThreads) { b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("testThreads", @@ -91,7 +228,7 @@ void ExampleBrowserThreadFunc(void* userPtr,void* lsMemory) b3Clock clock; - ExampleEntries examples; + ExampleEntriesPhysicsServer examples; examples.initExampleEntries(); DefaultBrowser* exampleBrowser = new DefaultBrowser(&examples); @@ -231,7 +368,7 @@ void btShutDownExampleBrowser(btInProcessExampleBrowserInternalData* data) struct btInProcessExampleBrowserMainThreadInternalData { - ExampleEntries m_examples; + ExampleEntriesPhysicsServer m_examples; DefaultBrowser* m_exampleBrowser; SharedMemoryInterface* m_sharedMem; b3Clock m_clock; diff --git a/examples/ExampleBrowser/main.cpp b/examples/ExampleBrowser/main.cpp index c3442de73..65b82021b 100644 --- a/examples/ExampleBrowser/main.cpp +++ b/examples/ExampleBrowser/main.cpp @@ -22,7 +22,7 @@ int main(int argc, char* argv[]) b3Clock clock; - ExampleEntries examples; + ExampleEntriesAll examples; examples.initExampleEntries(); ExampleBrowserInterface* exampleBrowser = new DefaultBrowser(&examples); diff --git a/examples/pybullet/CMakeLists.txt b/examples/pybullet/CMakeLists.txt index db057eda9..b5ee53a0e 100644 --- a/examples/pybullet/CMakeLists.txt +++ b/examples/pybullet/CMakeLists.txt @@ -18,7 +18,7 @@ ADD_LIBRARY(pybullet ${pybullet_SRCS}) SET_TARGET_PROPERTIES(pybullet PROPERTIES VERSION ${BULLET_VERSION}) SET_TARGET_PROPERTIES(pybullet PROPERTIES SOVERSION ${BULLET_VERSION}) - TARGET_LINK_LIBRARIES(pybullet BulletExampleBrowserLib BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen Bullet3Common) + TARGET_LINK_LIBRARIES(pybullet BulletExampleBrowserLib BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen Bullet3Common Python) ENDIF (BUILD_SHARED_LIBS) diff --git a/examples/pybullet/pybullet.c b/examples/pybullet/pybullet.c index 9bea19d17..f2b9c5500 100644 --- a/examples/pybullet/pybullet.c +++ b/examples/pybullet/pybullet.c @@ -138,6 +138,8 @@ pybullet_resetSimulation(PyObject* self, PyObject* args) statusHandle = b3SubmitClientCommandAndWaitStatus(sm, b3InitResetSimulationCommand(sm)); // ASSERT_EQ(b3GetStatusType(statusHandle), CMD_RESET_SIMULATION_COMPLETED); } + return PyLong_FromLong(1); + } static PyMethodDef SpamMethods[] = { From f0b9037cd2217394a82026e948dbcc6965f4412c Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 3 May 2016 23:42:19 -0700 Subject: [PATCH 33/50] tweak cmake, add option BUILD_PYBULLET --- CMakeLists.txt | 1 + examples/CMakeLists.txt | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf653084a..7e3321091 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,7 @@ IF (APPLE) ENDIF() OPTION(BUILD_BULLET3 "Set when you want to build Bullet 3" ON) +OPTION(BUILD_PYBULLET "Set when you want to build pybullet (experimental Python bindings for Bullet)" OFF) IF(BUILD_BULLET3) IF(APPLE) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 18c2f16c8..8a974c55b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,5 +1,7 @@ SUBDIRS( HelloWorld BasicDemo ) IF(BUILD_BULLET3) - SUBDIRS( ExampleBrowser ThirdPartyLibs/Gwen OpenGLWindow pybullet) + SUBDIRS( ExampleBrowser ThirdPartyLibs/Gwen OpenGLWindow ) ENDIF() - +IF(BUILD_PYBULLET) + SUBDIRS(pybullet) +ENDIF(BUILD_PYBULLET) From 0d3440b3887bcc78968d2f4c4f84c3fed76231ee Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 3 May 2016 23:46:29 -0700 Subject: [PATCH 34/50] fixes in Mac resizing example browser (if window size exceeds capability) --- .../CommonInterfaces/CommonWindowInterface.h | 4 ++- .../ExampleBrowser/OpenGLExampleBrowser.cpp | 18 ++++++----- examples/OpenGLWindow/MacOpenGLWindow.h | 3 ++ examples/OpenGLWindow/MacOpenGLWindow.mm | 19 ++++++++++-- examples/OpenGLWindow/SimpleOpenGL3App.cpp | 31 +++++++++++++------ 5 files changed, 55 insertions(+), 20 deletions(-) diff --git a/examples/CommonInterfaces/CommonWindowInterface.h b/examples/CommonInterfaces/CommonWindowInterface.h index fb3b574e9..346fdac72 100644 --- a/examples/CommonInterfaces/CommonWindowInterface.h +++ b/examples/CommonInterfaces/CommonWindowInterface.h @@ -119,7 +119,9 @@ class CommonWindowInterface virtual float getRetinaScale() const =0; virtual void setAllowRetina(bool allow) =0; - + + virtual int getWidth() const = 0; + virtual int getHeight() const = 0; virtual int fileOpenDialog(char* fileName, int maxFileNameLength) = 0; diff --git a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp index d8756f67e..c07e63a7c 100644 --- a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp +++ b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp @@ -695,8 +695,8 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[]) } - int width = 1024; - int height=768; + int width = 1920; + int height=1080; #ifndef NO_OPENGL3 SimpleOpenGL3App* simpleApp=0; sUseOpenGL2 =args.CheckCmdLineFlag("opengl2"); @@ -723,6 +723,8 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[]) char title[1024]; sprintf(title,"%s using OpenGL3+. %s", appTitle,optMode); simpleApp = new SimpleOpenGL3App(title,width,height, gAllowRetina); + + s_app = simpleApp; } #endif @@ -734,7 +736,11 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[]) #endif s_instancingRenderer = s_app->m_renderer; - s_window = s_app->m_window; + s_window = s_app->m_window; + + width = s_window->getWidth(); + height = s_window->getHeight(); + prevMouseMoveCallback = s_window->getMouseMoveCallback(); s_window->setMouseMoveCallback(MyMouseMoveCallback); @@ -817,9 +823,7 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[]) ///add some demos to the gAllExamples - - - + int numDemos = gAllExamples->getNumRegisteredExamples(); //char nodeText[1024]; @@ -924,7 +928,7 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[]) gui->registerFileOpenCallback(fileOpenCallback); gui->registerQuitCallback(quitCallback); - + return true; } diff --git a/examples/OpenGLWindow/MacOpenGLWindow.h b/examples/OpenGLWindow/MacOpenGLWindow.h index f17102a8b..d84b031b4 100644 --- a/examples/OpenGLWindow/MacOpenGLWindow.h +++ b/examples/OpenGLWindow/MacOpenGLWindow.h @@ -101,6 +101,9 @@ public: virtual float getTimeInSeconds(); + virtual int getWidth() const; + virtual int getHeight() const; + virtual void setRenderCallback( b3RenderCallback renderCallback); diff --git a/examples/OpenGLWindow/MacOpenGLWindow.mm b/examples/OpenGLWindow/MacOpenGLWindow.mm index 818726971..d247f95b0 100644 --- a/examples/OpenGLWindow/MacOpenGLWindow.mm +++ b/examples/OpenGLWindow/MacOpenGLWindow.mm @@ -423,8 +423,8 @@ void MacOpenGLWindow::createWindow(const b3gWindowConstructionInfo& ci) [m_internalData->m_window makeKeyAndOrderFront: nil]; [m_internalData->m_myview MakeCurrent]; - //m_internalData->m_width = m_internalData->m_myview.GetWindowWidth; - //m_internalData->m_height = m_internalData->m_myview.GetWindowHeight; + m_internalData->m_width = m_internalData->m_myview.GetWindowWidth; + m_internalData->m_height = m_internalData->m_myview.GetWindowHeight; [NSApp activateIgnoringOtherApps:YES]; @@ -1132,6 +1132,21 @@ void MacOpenGLWindow::getMouseCoordinates(int& x, int& y) } +int MacOpenGLWindow::getWidth() const +{ + if (m_internalData && m_internalData->m_myview && m_internalData->m_myview.GetWindowWidth) + return m_internalData->m_myview.GetWindowWidth; + return 0; +} + +int MacOpenGLWindow::getHeight() const +{ + if (m_internalData && m_internalData->m_myview && m_internalData->m_myview.GetWindowHeight) + return m_internalData->m_myview.GetWindowHeight; + return 0; +} + + void MacOpenGLWindow::setResizeCallback(b3ResizeCallback resizeCallback) { [m_internalData->m_myview setResizeCallback:resizeCallback]; diff --git a/examples/OpenGLWindow/SimpleOpenGL3App.cpp b/examples/OpenGLWindow/SimpleOpenGL3App.cpp index 241ff7bba..d77c12bef 100644 --- a/examples/OpenGLWindow/SimpleOpenGL3App.cpp +++ b/examples/OpenGLWindow/SimpleOpenGL3App.cpp @@ -56,8 +56,11 @@ static void SimpleResizeCallback( float widthf, float heightf) { int width = (int)widthf; int height = (int)heightf; - gApp->m_instancingRenderer->resize(width,height); - gApp->m_primRenderer->setScreenSize(width,height); + if (gApp && gApp->m_instancingRenderer) + gApp->m_instancingRenderer->resize(width,height); + + if (gApp && gApp->m_primRenderer) + gApp->m_primRenderer->setScreenSize(width,height); } @@ -115,6 +118,7 @@ extern unsigned char OpenSansData[]; SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, bool allowRetina) { gApp = this; + m_data = new SimpleInternalData; m_data->m_frameDumpPngFileName = 0; m_data->m_renderTexture = 0; @@ -123,6 +127,7 @@ SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, boo m_data->m_upAxis = 1; m_window = new b3gDefaultOpenGLWindow(); + m_window->setAllowRetina(allowRetina); b3gWindowConstructionInfo ci; @@ -141,6 +146,9 @@ SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, boo 1.f); m_window->startRendering(); + width = m_window->getWidth(); + height = m_window->getHeight(); + b3Assert(glGetError() ==GL_NO_ERROR); #ifndef __APPLE__ @@ -160,17 +168,21 @@ SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, boo b3Assert(glGetError() ==GL_NO_ERROR); - m_primRenderer = new GLPrimitiveRenderer(width,height); m_parameterInterface = 0; - + b3Assert(glGetError() ==GL_NO_ERROR); m_instancingRenderer = new GLInstancingRenderer(128*1024,64*1024*1024); - m_renderer = m_instancingRenderer ; - m_instancingRenderer->init(); + m_primRenderer = new GLPrimitiveRenderer(width,height); + + m_renderer = m_instancingRenderer ; + m_window->setResizeCallback(SimpleResizeCallback); + + + m_instancingRenderer->init(); m_instancingRenderer->resize(width,height); - - b3Assert(glGetError() ==GL_NO_ERROR); + m_primRenderer->setScreenSize(width,height); + b3Assert(glGetError() ==GL_NO_ERROR); m_instancingRenderer->InitShaders(); @@ -178,8 +190,7 @@ SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, boo m_window->setMouseButtonCallback(SimpleMouseButtonCallback); m_window->setKeyboardCallback(SimpleKeyboardCallback); m_window->setWheelCallback(SimpleWheelCallback); - m_window->setResizeCallback(SimpleResizeCallback); - + TwGenerateDefaultFonts(); m_data->m_fontTextureId = BindFont(g_DefaultNormalFont); m_data->m_largeFontTextureId = BindFont(g_DefaultLargeFont); From 8360e2e66d6adb9d06077d849ca8ba480e929729 Mon Sep 17 00:00:00 2001 From: erwin coumans Date: Wed, 4 May 2016 00:16:53 -0700 Subject: [PATCH 35/50] windows fixes --- .../InProcessExampleBrowser.cpp | 63 ++++++++++--------- .../ExampleBrowser/OpenGLExampleBrowser.cpp | 4 +- examples/OpenGLWindow/Win32OpenGLWindow.cpp | 15 +++++ examples/OpenGLWindow/Win32OpenGLWindow.h | 3 + 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/examples/ExampleBrowser/InProcessExampleBrowser.cpp b/examples/ExampleBrowser/InProcessExampleBrowser.cpp index 97b0761c4..1f03b7e92 100644 --- a/examples/ExampleBrowser/InProcessExampleBrowser.cpp +++ b/examples/ExampleBrowser/InProcessExampleBrowser.cpp @@ -13,7 +13,7 @@ #include "../Utils/b3Clock.h" #include "ExampleEntries.h" -#include "Bullet3Common/b3Logging.h" +#include "Bullet3Common/b3Scalar.h" #include "../SharedMemory/InProcessMemory.h" void ExampleBrowserThreadFunc(void* userPtr,void* lsMemory); @@ -22,9 +22,7 @@ void* ExampleBrowserMemoryFunc(); #include //#include "BulletMultiThreaded/PlatformDefinitions.h" -#ifndef _WIN32 -#include "../MultiThreading/b3PosixThreadSupport.h" - +#include "Bullet3Common/b3Logging.h" #include "ExampleEntries.h" #include "LinearMath/btAlignedObjectArray.h" #include "EmptyExample.h" @@ -32,6 +30,38 @@ void* ExampleBrowserMemoryFunc(); #include "../SharedMemory/PhysicsServerExample.h" #include "../SharedMemory/PhysicsClientExample.h" +#ifndef _WIN32 +#include "../MultiThreading/b3PosixThreadSupport.h" + + + +static b3ThreadSupportInterface* createExampleBrowserThreadSupport(int numThreads) +{ + b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("testThreads", + ExampleBrowserThreadFunc, + ExampleBrowserMemoryFunc, + numThreads); + b3ThreadSupportInterface* threadSupport = new b3PosixThreadSupport(constructionInfo); + + return threadSupport; + +} + + + +#elif defined( _WIN32) +#include "../MultiThreading/b3Win32ThreadSupport.h" + +b3ThreadSupportInterface* createExampleBrowserThreadSupport(int numThreads) +{ + b3Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("testThreads",ExampleBrowserThreadFunc,ExampleBrowserMemoryFunc,numThreads); + b3Win32ThreadSupport* threadSupport = new b3Win32ThreadSupport(threadConstructionInfo); + return threadSupport; + +} +#endif + + @@ -162,30 +192,6 @@ const char* ExampleEntriesPhysicsServer::getExampleDescription(int index) return m_data->m_allExamples[index].m_description; } -static b3ThreadSupportInterface* createExampleBrowserThreadSupport(int numThreads) -{ - b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("testThreads", - ExampleBrowserThreadFunc, - ExampleBrowserMemoryFunc, - numThreads); - b3ThreadSupportInterface* threadSupport = new b3PosixThreadSupport(constructionInfo); - - return threadSupport; - -} - - -#elif defined( _WIN32) -#include "../MultiThreading/b3Win32ThreadSupport.h" - -b3ThreadSupportInterface* createExampleBrowserThreadSupport(int numThreads) -{ - b3Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("testThreads",ExampleBrowserThreadFunc,ExampleBrowserMemoryFunc,numThreads); - b3Win32ThreadSupport* threadSupport = new b3Win32ThreadSupport(threadConstructionInfo); - return threadSupport; - -} -#endif @@ -284,6 +290,7 @@ struct btInProcessExampleBrowserInternalData }; + btInProcessExampleBrowserInternalData* btCreateInProcessExampleBrowser(int argc,char** argv2) { diff --git a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp index c07e63a7c..5804c2c65 100644 --- a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp +++ b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp @@ -695,8 +695,8 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[]) } - int width = 1920; - int height=1080; + int width = 1024; + int height=768; #ifndef NO_OPENGL3 SimpleOpenGL3App* simpleApp=0; sUseOpenGL2 =args.CheckCmdLineFlag("opengl2"); diff --git a/examples/OpenGLWindow/Win32OpenGLWindow.cpp b/examples/OpenGLWindow/Win32OpenGLWindow.cpp index d7571bf98..0e076b92c 100644 --- a/examples/OpenGLWindow/Win32OpenGLWindow.cpp +++ b/examples/OpenGLWindow/Win32OpenGLWindow.cpp @@ -180,6 +180,21 @@ int Win32OpenGLWindow::fileOpenDialog(char* fileName, int maxFileNameLength) //return 0; } +int Win32OpenGLWindow::getWidth() const +{ + if (m_data) + return m_data->m_openglViewportWidth; + return 0; +} + +int Win32OpenGLWindow::getHeight() const +{ + if (m_data) + return m_data->m_openglViewportHeight; + return 0; +} + + #endif diff --git a/examples/OpenGLWindow/Win32OpenGLWindow.h b/examples/OpenGLWindow/Win32OpenGLWindow.h index bf8a0f5eb..901ce6518 100644 --- a/examples/OpenGLWindow/Win32OpenGLWindow.h +++ b/examples/OpenGLWindow/Win32OpenGLWindow.h @@ -53,6 +53,9 @@ public: virtual float getRetinaScale() const {return 1.f;} virtual void setAllowRetina(bool /*allowRetina*/) {}; + virtual int getWidth() const; + virtual int getHeight() const; + virtual int fileOpenDialog(char* fileName, int maxFileNameLength); }; From 194009f46e4697a1bc89ca3f31124d554472e8b2 Mon Sep 17 00:00:00 2001 From: "Erwin Coumans (Google)" Date: Wed, 4 May 2016 00:17:39 -0700 Subject: [PATCH 36/50] linux fixes --- examples/OpenGLWindow/X11OpenGLWindow.cpp | 14 ++++++++++++++ examples/OpenGLWindow/X11OpenGLWindow.h | 7 ++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/examples/OpenGLWindow/X11OpenGLWindow.cpp b/examples/OpenGLWindow/X11OpenGLWindow.cpp index e6d0f666d..f2a077145 100644 --- a/examples/OpenGLWindow/X11OpenGLWindow.cpp +++ b/examples/OpenGLWindow/X11OpenGLWindow.cpp @@ -1076,6 +1076,20 @@ b3KeyboardCallback X11OpenGLWindow::getKeyboardCallback() return m_data->m_keyboardCallback; } +int X11OpenGLWindow::getWidth() const +{ + if (m_data) + return m_data->m_glWidth; + return 0; +} +int X11OpenGLWindow::getHeight() const +{ + if (m_data) + return m_data->m_glHeight; + return 0; +} + + #include int X11OpenGLWindow::fileOpenDialog(char* filename, int maxNameLength) diff --git a/examples/OpenGLWindow/X11OpenGLWindow.h b/examples/OpenGLWindow/X11OpenGLWindow.h index cc28aae1a..fd88689bc 100644 --- a/examples/OpenGLWindow/X11OpenGLWindow.h +++ b/examples/OpenGLWindow/X11OpenGLWindow.h @@ -54,7 +54,7 @@ public: virtual void setResizeCallback(b3ResizeCallback resizeCallback); virtual void setWheelCallback(b3WheelCallback wheelCallback); virtual void setKeyboardCallback( b3KeyboardCallback keyboardCallback); - + virtual b3MouseMoveCallback getMouseMoveCallback(); virtual b3MouseButtonCallback getMouseButtonCallback(); virtual b3ResizeCallback getResizeCallback(); @@ -65,9 +65,14 @@ public: virtual void setWindowTitle(const char* title); + virtual int getWidth() const; + + virtual int getHeight() const; + int fileOpenDialog(char* filename, int maxNameLength); }; + #endif From 372c4ef9c1cc9b8ae1a6a6e5c69d2fbb5f56a3e2 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 4 May 2016 13:01:06 -0700 Subject: [PATCH 37/50] Add btConvexHullShape::optimizeConvexHull method, it automatically removes vertices that are not on the convex hull. It uses the btConvexHullComputer for this. --- .../CollisionShapes/btConvexHullShape.cpp | 17 +++++++++++++---- .../CollisionShapes/btConvexHullShape.h | 5 ++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp index 0623e351a..c1aa6ca46 100644 --- a/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp +++ b/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp @@ -22,6 +22,8 @@ subject to the following restrictions: #include "LinearMath/btQuaternion.h" #include "LinearMath/btSerializer.h" +#include "btConvexPolyhedron.h" +#include "LinearMath/btConvexHullComputer.h" btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexAabbCachingShape () { @@ -121,10 +123,17 @@ btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const } - - - - +void btConvexHullShape::optimizeConvexHull() +{ + btConvexHullComputer conv; + conv.compute(&m_unscaledPoints[0].getX(), sizeof(btVector3),m_unscaledPoints.size(),0.f,0.f); + int numVerts = conv.vertices.size(); + m_unscaledPoints.resize(0); + for (int i=0;i Date: Wed, 4 May 2016 13:24:06 -0700 Subject: [PATCH 38/50] use cmake FIND_PACKAGE(PythonLibs 2.7 REQUIRED) if pybullet is build --- CMakeLists.txt | 3 +++ examples/ExampleBrowser/ExampleEntries.cpp | 2 ++ examples/pybullet/CMakeLists.txt | 4 ++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e3321091..7809a87ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,6 +192,9 @@ ENDIF() OPTION(BUILD_BULLET3 "Set when you want to build Bullet 3" ON) OPTION(BUILD_PYBULLET "Set when you want to build pybullet (experimental Python bindings for Bullet)" OFF) +IF(BUILD_PYBULLET) + FIND_PACKAGE(PythonLibs 2.7 REQUIRED) +ENDIF(BUILD_PYBULLET) IF(BUILD_BULLET3) IF(APPLE) diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index 3ec1403d6..08f71cf69 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -83,8 +83,10 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(0,"API"), + ExampleEntry(1,"Basic Example","Create some rigid bodies using box collision shapes. This is a good example to familiarize with the basic initialization of Bullet. The Basic Example can also be compiled without graphical user interface, as a console application. Press W for wireframe, A to show AABBs, I to suspend/restart physics simulation. Press D to toggle auto-deactivation of the simulation. ", BasicExampleCreateFunc), + ExampleEntry(1,"Rolling Friction", "Damping is often not good enough to keep rounded objects from rolling down a sloped surface. Instead, you can set the rolling friction of a rigid body. Generally it is best to leave the rolling friction to zero, to avoid artifacts.", RollingFrictionCreateFunc), ExampleEntry(1,"Constraints","Show the use of the various constraints in Bullet. Press the L key to visualize the constraint limits. Press the C key to visualize the constraint frames.", diff --git a/examples/pybullet/CMakeLists.txt b/examples/pybullet/CMakeLists.txt index b5ee53a0e..a583192ab 100644 --- a/examples/pybullet/CMakeLists.txt +++ b/examples/pybullet/CMakeLists.txt @@ -4,7 +4,7 @@ INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/examples ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs - /usr/include/python2.7 + ${PYTHON_INCLUDE_DIRS} ) SET(pybullet_SRCS @@ -18,7 +18,7 @@ ADD_LIBRARY(pybullet ${pybullet_SRCS}) SET_TARGET_PROPERTIES(pybullet PROPERTIES VERSION ${BULLET_VERSION}) SET_TARGET_PROPERTIES(pybullet PROPERTIES SOVERSION ${BULLET_VERSION}) - TARGET_LINK_LIBRARIES(pybullet BulletExampleBrowserLib BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen Bullet3Common Python) + TARGET_LINK_LIBRARIES(pybullet BulletExampleBrowserLib BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen Bullet3Common ${PYTHON_LIBRARIES}) ENDIF (BUILD_SHARED_LIBS) From 85368973a1a8b5d0d230feb512fd19540611f923 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 4 May 2016 13:46:55 -0700 Subject: [PATCH 39/50] When using cmake -DBUILD_PYBULLET=ON, force BUILD_SHARED_LIBS option --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7809a87ef..2f04917ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,6 +194,7 @@ OPTION(BUILD_BULLET3 "Set when you want to build Bullet 3" ON) OPTION(BUILD_PYBULLET "Set when you want to build pybullet (experimental Python bindings for Bullet)" OFF) IF(BUILD_PYBULLET) FIND_PACKAGE(PythonLibs 2.7 REQUIRED) + SET(BUILD_SHARED_LIBS ON CACHE BOOL "Shared Libs" FORCE) ENDIF(BUILD_PYBULLET) IF(BUILD_BULLET3) From 0a3efbe349e17f00771339ea154ecb29581bbb17 Mon Sep 17 00:00:00 2001 From: erwin coumans Date: Fri, 6 May 2016 13:57:48 -0700 Subject: [PATCH 40/50] make standalone versions (console, tinyrender, opengl) of InverseDynamics/InverseDynamicsExample --- build3/premake4.lua | 2 +- examples/ExampleBrowser/OpenGLGuiHelper.cpp | 1 + .../ImportColladaDemo/LoadMeshFromCollada.cpp | 2 +- .../ImportColladaDemo/LoadMeshFromCollada.h | 2 +- .../ImportObjDemo/LoadMeshFromObj.cpp | 4 +- .../Wavefront2GLInstanceGraphicsShape.cpp | 10 +- .../Wavefront2GLInstanceGraphicsShape.h | 2 +- .../Importers/ImportSTLDemo/LoadMeshFromSTL.h | 2 +- .../ImportURDFDemo/BulletUrdfImporter.cpp | 2 +- .../ImportURDFDemo/MyMultiBodyCreator.cpp | 2 +- .../Importers/ImportURDFDemo/UrdfParser.cpp | 2 +- .../InverseDynamicsExample.cpp | 56 +++--- examples/InverseDynamics/premake4.lua | 162 ++++++++++++++++++ .../RenderingExamples/TimeSeriesCanvas.cpp | 15 +- .../main_console_single_example.cpp | 6 +- .../main_opengl_single_example.cpp | 13 +- .../main_sw_tinyrenderer_single_example.cpp | 12 +- examples/TinyRenderer/TinyRenderer.cpp | 4 +- 18 files changed, 246 insertions(+), 53 deletions(-) create mode 100644 examples/InverseDynamics/premake4.lua diff --git a/build3/premake4.lua b/build3/premake4.lua index 062c08443..31ca45afa 100644 --- a/build3/premake4.lua +++ b/build3/premake4.lua @@ -193,7 +193,7 @@ include "../examples/HelloWorld" include "../examples/BasicDemo" - + include "../examples/InverseDynamics" include "../examples/SharedMemory" include "../examples/MultiThreading" diff --git a/examples/ExampleBrowser/OpenGLGuiHelper.cpp b/examples/ExampleBrowser/OpenGLGuiHelper.cpp index ec88c0c78..5dd62fcdd 100644 --- a/examples/ExampleBrowser/OpenGLGuiHelper.cpp +++ b/examples/ExampleBrowser/OpenGLGuiHelper.cpp @@ -501,6 +501,7 @@ CommonParameterInterface* OpenGLGuiHelper::getParameterInterface() void OpenGLGuiHelper::setUpAxis(int axis) { m_data->m_glApp->setUpAxis(axis); + } void OpenGLGuiHelper::resetCamera(float camDist, float pitch, float yaw, float camPosX,float camPosY, float camPosZ) diff --git a/examples/Importers/ImportColladaDemo/LoadMeshFromCollada.cpp b/examples/Importers/ImportColladaDemo/LoadMeshFromCollada.cpp index f5a70a0cf..b9a9479e0 100644 --- a/examples/Importers/ImportColladaDemo/LoadMeshFromCollada.cpp +++ b/examples/Importers/ImportColladaDemo/LoadMeshFromCollada.cpp @@ -20,7 +20,7 @@ subject to the following restrictions: #include //fopen #include "Bullet3Common/b3AlignedObjectArray.h" #include -#include "tinyxml/tinyxml.h" +#include "../../ThirdPartyLibs/tinyxml/tinyxml.h" #include "Bullet3Common/b3FileUtils.h" #include "LinearMath/btHashMap.h" diff --git a/examples/Importers/ImportColladaDemo/LoadMeshFromCollada.h b/examples/Importers/ImportColladaDemo/LoadMeshFromCollada.h index c65666f8b..2e939b575 100644 --- a/examples/Importers/ImportColladaDemo/LoadMeshFromCollada.h +++ b/examples/Importers/ImportColladaDemo/LoadMeshFromCollada.h @@ -21,7 +21,7 @@ subject to the following restrictions: #include "LinearMath/btAlignedObjectArray.h" #include "LinearMath/btTransform.h" -#include "../OpenGLWindow/GLInstanceGraphicsShape.h" +#include "../../OpenGLWindow/GLInstanceGraphicsShape.h" #include "ColladaGraphicsInstance.h" diff --git a/examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp b/examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp index 4988fb877..d90bedfe2 100644 --- a/examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp +++ b/examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp @@ -1,6 +1,6 @@ #include "LoadMeshFromObj.h" -#include"Wavefront/tiny_obj_loader.h" -#include "../OpenGLWindow/GLInstanceGraphicsShape.h" +#include"../../ThirdPartyLibs/Wavefront/tiny_obj_loader.h" +#include "../../OpenGLWindow/GLInstanceGraphicsShape.h" #include //fopen #include "Bullet3Common/b3AlignedObjectArray.h" #include diff --git a/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp b/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp index c1b417ec9..c57dabf8b 100644 --- a/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp +++ b/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp @@ -1,12 +1,12 @@ #include "Wavefront2GLInstanceGraphicsShape.h" -#include "../OpenGLWindow/GLInstancingRenderer.h" -#include "../OpenGLWindow/GLInstanceGraphicsShape.h" +#include "../../OpenGLWindow/GLInstancingRenderer.h" +#include "../../OpenGLWindow/GLInstanceGraphicsShape.h" #include "btBulletDynamicsCommon.h" -#include "../OpenGLWindow/SimpleOpenGL3App.h" +#include "../../OpenGLWindow/SimpleOpenGL3App.h" #include "Wavefront2GLInstanceGraphicsShape.h" -#include "../OpenGLWindow/GLInstancingRenderer.h" -#include "../OpenGLWindow/GLInstanceGraphicsShape.h" +#include "../../OpenGLWindow/GLInstancingRenderer.h" +#include "../../OpenGLWindow/GLInstanceGraphicsShape.h" GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector& shapes) { diff --git a/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h b/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h index c93d1c465..a2b129bea 100644 --- a/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h +++ b/examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h @@ -1,7 +1,7 @@ #ifndef WAVEFRONT2GRAPHICS_H #define WAVEFRONT2GRAPHICS_H -#include"Wavefront/tiny_obj_loader.h" +#include"../../ThirdPartyLibs/Wavefront/tiny_obj_loader.h" #include struct GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector& shapes); diff --git a/examples/Importers/ImportSTLDemo/LoadMeshFromSTL.h b/examples/Importers/ImportSTLDemo/LoadMeshFromSTL.h index a44781221..f670dfeec 100644 --- a/examples/Importers/ImportSTLDemo/LoadMeshFromSTL.h +++ b/examples/Importers/ImportSTLDemo/LoadMeshFromSTL.h @@ -2,7 +2,7 @@ #ifndef LOAD_MESH_FROM_STL_H #define LOAD_MESH_FROM_STL_H -#include "../OpenGLWindow/GLInstanceGraphicsShape.h" +#include "../../OpenGLWindow/GLInstanceGraphicsShape.h" #include //fopen #include "Bullet3Common/b3AlignedObjectArray.h" diff --git a/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp b/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp index 1639e3b36..77d11953b 100644 --- a/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp +++ b/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp @@ -21,7 +21,7 @@ subject to the following restrictions: #include "../ImportSTLDemo/LoadMeshFromSTL.h" #include "../ImportColladaDemo/LoadMeshFromCollada.h" #include "BulletCollision/CollisionShapes/btShapeHull.h"//to create a tesselation of a generic btConvexShape -#include "../CommonInterfaces/CommonGUIHelperInterface.h" +#include "../../CommonInterfaces/CommonGUIHelperInterface.h" #include "Bullet3Common/b3FileUtils.h" #include #include "../../Utils/b3ResourcePath.h" diff --git a/examples/Importers/ImportURDFDemo/MyMultiBodyCreator.cpp b/examples/Importers/ImportURDFDemo/MyMultiBodyCreator.cpp index dd36baa76..28e9023d8 100644 --- a/examples/Importers/ImportURDFDemo/MyMultiBodyCreator.cpp +++ b/examples/Importers/ImportURDFDemo/MyMultiBodyCreator.cpp @@ -1,6 +1,6 @@ #include "MyMultiBodyCreator.h" -#include "../CommonInterfaces/CommonGUIHelperInterface.h" +#include "../../CommonInterfaces/CommonGUIHelperInterface.h" #include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h" #include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h" diff --git a/examples/Importers/ImportURDFDemo/UrdfParser.cpp b/examples/Importers/ImportURDFDemo/UrdfParser.cpp index 81df76996..d0b064bfb 100644 --- a/examples/Importers/ImportURDFDemo/UrdfParser.cpp +++ b/examples/Importers/ImportURDFDemo/UrdfParser.cpp @@ -1,6 +1,6 @@ #include "UrdfParser.h" -#include "tinyxml/tinyxml.h" +#include "../../ThirdPartyLibs/tinyxml/tinyxml.h" #include "urdfStringSplit.h" #include "urdfLexicalCast.h" diff --git a/examples/InverseDynamics/InverseDynamicsExample.cpp b/examples/InverseDynamics/InverseDynamicsExample.cpp index e062e1717..a2ac8f1d6 100644 --- a/examples/InverseDynamics/InverseDynamicsExample.cpp +++ b/examples/InverseDynamics/InverseDynamicsExample.cpp @@ -129,13 +129,15 @@ void InverseDynamicsExample::initPhysics() SliderParams slider("Kp",&kp); slider.m_minVal=0; slider.m_maxVal=2000; - m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + if (m_guiHelper->getParameterInterface()) + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); } { SliderParams slider("Kd",&kd); slider.m_minVal=0; slider.m_maxVal=50; - m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + if (m_guiHelper->getParameterInterface()) + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); } if (m_option == BT_ID_PROGRAMMATICALLY) @@ -148,6 +150,7 @@ void InverseDynamicsExample::initPhysics() switch (m_option) { + case 0: case BT_ID_LOAD_URDF: { BulletURDFImporter u2b(m_guiHelper); @@ -189,9 +192,11 @@ void InverseDynamicsExample::initPhysics() if(m_multiBody) { { - m_timeSeriesCanvas = new TimeSeriesCanvas(m_guiHelper->getAppInterface()->m_2dCanvasInterface,512,230, "Joint Space Trajectory"); - m_timeSeriesCanvas ->setupTimeSeries(3,100, 0); - + if (m_guiHelper->getAppInterface() && m_guiHelper->getParameterInterface()) + { + m_timeSeriesCanvas = new TimeSeriesCanvas(m_guiHelper->getAppInterface()->m_2dCanvasInterface,512,230, "Joint Space Trajectory"); + m_timeSeriesCanvas ->setupTimeSeries(3,100, 0); + } } // construct inverse model @@ -203,23 +208,30 @@ void InverseDynamicsExample::initPhysics() } // add joint target controls qd.resize(m_multiBody->getNumDofs()); + qd[3]=B3_HALF_PI; qd_name.resize(m_multiBody->getNumDofs()); q_name.resize(m_multiBody->getNumDofs()); - for(std::size_t dof=0;dofgetParameterInterface()->registerSliderFloatParameter(slider); - btVector4 color = sJointCurveColors[dof&7]; - m_timeSeriesCanvas->addDataSource(q_name[dof].c_str(), color[0]*255,color[1]*255,color[2]*255); - } - + + if (m_timeSeriesCanvas && m_guiHelper->getParameterInterface()) + { + for(std::size_t dof=0;dofgetParameterInterface()->registerSliderFloatParameter(slider); + btVector4 color = sJointCurveColors[dof&7]; + m_timeSeriesCanvas->addDataSource(q_name[dof].c_str(), color[0]*255,color[1]*255,color[2]*255); + + } + } } @@ -246,7 +258,8 @@ void InverseDynamicsExample::stepSimulation(float deltaTime) const btScalar qd_dot=0; const btScalar qd_ddot=0; - m_timeSeriesCanvas->insertDataAtCurrentTime(q[dof],dof,true); + if (m_timeSeriesCanvas) + m_timeSeriesCanvas->insertDataAtCurrentTime(q[dof],dof,true); // pd_control is either desired joint torque for pd control, // or the feedback contribution to nu @@ -330,3 +343,4 @@ CommonExampleInterface* InverseDynamicsExampleCreateFunc(CommonExampleOptions +B3_STANDALONE_EXAMPLE(InverseDynamicsExampleCreateFunc) \ No newline at end of file diff --git a/examples/InverseDynamics/premake4.lua b/examples/InverseDynamics/premake4.lua new file mode 100644 index 000000000..1114283ef --- /dev/null +++ b/examples/InverseDynamics/premake4.lua @@ -0,0 +1,162 @@ + +project "App_InverseDynamicsExample" + +if _OPTIONS["ios"] then + kind "WindowedApp" +else + kind "ConsoleApp" +end +defines {"B3_USE_STANDALONE_EXAMPLE"} +includedirs {"../../src"} + +links { + "BulletInverseDynamicsUtils", "BulletInverseDynamics","Bullet3Common","BulletDynamics","BulletCollision", "LinearMath" +} + +language "C++" + +files { + "**.cpp", + "**.h", + "../StandaloneMain/main_console_single_example.cpp", + "../Utils/b3ResourcePath.cpp", + "../Utils/b3ResourcePath.h", + "../RenderingExamples/TimeSeriesCanvas.cpp", + "../RenderingExamples/TimeSeriesFontData.cpp", + "../MultiBody/InvertedPendulumPDControl.cpp", + "../ThirdPartyLibs/tinyxml/tinystr.cpp", + "../ThirdPartyLibs/tinyxml/tinyxml.cpp", + "../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp", + "../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp", + "../ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp", + "../ThirdPartyLibs/Wavefront/tiny_obj_loader.h", + "../Importers/ImportColladaDemo/LoadMeshFromCollada.cpp", + "../Importers/ImportObjDemo/LoadMeshFromObj.cpp", + "../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp", + "../Importers/ImportURDFDemo/BulletUrdfImporter.cpp", + "../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp", + "../Importers/ImportURDFDemo/URDF2Bullet.cpp", + "../Importers/ImportURDFDemo/UrdfParser.cpp", + "../Importers/ImportURDFDemo/urdfStringSplit.cpp", + +} + + +project "App_InverseDynamicsExampleGui" + +if _OPTIONS["ios"] then + kind "WindowedApp" +else + kind "ConsoleApp" +end +defines {"B3_USE_STANDALONE_EXAMPLE"} + +includedirs {"../../src"} + +links { + "BulletInverseDynamicsUtils", "BulletInverseDynamics","BulletDynamics","BulletCollision", "LinearMath", "OpenGL_Window","Bullet3Common" +} + + initOpenGL() + initGlew() + + +language "C++" + +files { + "InverseDynamicsExample.cpp", + "*.h", + "../StandaloneMain/main_opengl_single_example.cpp", + "../ExampleBrowser/OpenGLGuiHelper.cpp", + "../ExampleBrowser/GL_ShapeDrawer.cpp", + "../Utils/b3ResourcePath.cpp", + "../Utils/b3ResourcePath.h", + "../RenderingExamples/TimeSeriesCanvas.cpp", + "../RenderingExamples/TimeSeriesFontData.cpp", + "../MultiBody/InvertedPendulumPDControl.cpp", + "../ThirdPartyLibs/tinyxml/tinystr.cpp", + "../ThirdPartyLibs/tinyxml/tinyxml.cpp", + "../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp", + "../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp", + "../ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp", + "../ThirdPartyLibs/Wavefront/tiny_obj_loader.h", + "../Importers/ImportColladaDemo/LoadMeshFromCollada.cpp", + "../Importers/ImportObjDemo/LoadMeshFromObj.cpp", + "../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp", + "../Importers/ImportURDFDemo/BulletUrdfImporter.cpp", + "../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp", + "../Importers/ImportURDFDemo/URDF2Bullet.cpp", + "../Importers/ImportURDFDemo/UrdfParser.cpp", + "../Importers/ImportURDFDemo/urdfStringSplit.cpp", + +} + +if os.is("Linux") then initX11() end + +if os.is("MacOSX") then + links{"Cocoa.framework"} +end + + + +project "App_InverseDynamicsExampleGuiWithSoftwareRenderer" + +if _OPTIONS["ios"] then + kind "WindowedApp" +else + kind "ConsoleApp" +end +defines {"B3_USE_STANDALONE_EXAMPLE"} + +includedirs {"../../src"} + +links { + "BulletInverseDynamicsUtils", "BulletInverseDynamics","BulletDynamics","BulletCollision", "LinearMath", "OpenGL_Window","Bullet3Common" +} + + initOpenGL() + initGlew() + + +language "C++" + +files { + "InverseDynamicsExample.cpp", + "*.h", + "../StandaloneMain/main_sw_tinyrenderer_single_example.cpp", + "../ExampleBrowser/OpenGLGuiHelper.cpp", + "../ExampleBrowser/GL_ShapeDrawer.cpp", + "../TinyRenderer/geometry.cpp", + "../TinyRenderer/model.cpp", + "../TinyRenderer/tgaimage.cpp", + "../TinyRenderer/our_gl.cpp", + "../TinyRenderer/TinyRenderer.cpp", + "../Utils/b3ResourcePath.cpp", + "../Utils/b3ResourcePath.cpp", + "../Utils/b3ResourcePath.h", + "../RenderingExamples/TimeSeriesCanvas.cpp", + "../RenderingExamples/TimeSeriesFontData.cpp", + "../MultiBody/InvertedPendulumPDControl.cpp", + "../ThirdPartyLibs/tinyxml/tinystr.cpp", + "../ThirdPartyLibs/tinyxml/tinyxml.cpp", + "../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp", + "../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp", + "../ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp", + "../ThirdPartyLibs/Wavefront/tiny_obj_loader.h", + "../Importers/ImportColladaDemo/LoadMeshFromCollada.cpp", + "../Importers/ImportObjDemo/LoadMeshFromObj.cpp", + "../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp", + "../Importers/ImportURDFDemo/BulletUrdfImporter.cpp", + "../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp", + "../Importers/ImportURDFDemo/URDF2Bullet.cpp", + "../Importers/ImportURDFDemo/UrdfParser.cpp", + "../Importers/ImportURDFDemo/urdfStringSplit.cpp", + +} + +if os.is("Linux") then initX11() end + +if os.is("MacOSX") then + links{"Cocoa.framework"} +end + \ No newline at end of file diff --git a/examples/RenderingExamples/TimeSeriesCanvas.cpp b/examples/RenderingExamples/TimeSeriesCanvas.cpp index 5bed56a5b..31bc28c23 100644 --- a/examples/RenderingExamples/TimeSeriesCanvas.cpp +++ b/examples/RenderingExamples/TimeSeriesCanvas.cpp @@ -72,13 +72,14 @@ struct TimeSeriesInternalData TimeSeriesCanvas::TimeSeriesCanvas(struct Common2dCanvasInterface* canvasInterface, int width, int height, const char* windowTitle) { - btAssert(canvasInterface); - m_internalData = new TimeSeriesInternalData(width,height); m_internalData->m_canvasInterface = canvasInterface; - - m_internalData->m_canvasIndex = m_internalData->m_canvasInterface->createCanvas(windowTitle,m_internalData->m_width,m_internalData->m_height); + + if (canvasInterface) + { + m_internalData->m_canvasIndex = m_internalData->m_canvasInterface->createCanvas(windowTitle,m_internalData->m_width,m_internalData->m_height); + } } void TimeSeriesCanvas::addDataSource(const char* dataSourceLabel, unsigned char red,unsigned char green,unsigned char blue) @@ -105,6 +106,9 @@ void TimeSeriesCanvas::addDataSource(const char* dataSourceLabel, unsigned char } void TimeSeriesCanvas::setupTimeSeries(float yScale, int ticksPerSecond, int startTime) { + if (0==m_internalData->m_canvasInterface) + return; + m_internalData->m_pixelsPerUnit = -(m_internalData->m_height/3.f)/yScale; m_internalData->m_ticksPerSecond = ticksPerSecond; m_internalData->m_yScale = yScale; @@ -282,6 +286,9 @@ void TimeSeriesCanvas::shift1PixelToLeft() void TimeSeriesCanvas::insertDataAtCurrentTime(float orgV, int dataSourceIndex, bool connectToPrevious) { + if (0==m_internalData->m_canvasInterface) + return; + btAssert(dataSourceIndex < m_internalData->m_dataSources.size()); float zero = m_internalData->m_zero; diff --git a/examples/StandaloneMain/main_console_single_example.cpp b/examples/StandaloneMain/main_console_single_example.cpp index e1f5b6dd8..c29ebcd79 100644 --- a/examples/StandaloneMain/main_console_single_example.cpp +++ b/examples/StandaloneMain/main_console_single_example.cpp @@ -35,7 +35,11 @@ int main(int argc, char* argv[]) CommonExampleInterface* example = StandaloneExampleCreateFunc(options); example->initPhysics(); - example->stepSimulation(1.f/60.f); + for (int i=0;i<1000;i++) + { + printf("Simulating step %d\n",i); + example->stepSimulation(1.f/60.f); + } example->exitPhysics(); delete example; diff --git a/examples/StandaloneMain/main_opengl_single_example.cpp b/examples/StandaloneMain/main_opengl_single_example.cpp index 4fd1ff422..6205020f4 100644 --- a/examples/StandaloneMain/main_opengl_single_example.cpp +++ b/examples/StandaloneMain/main_opengl_single_example.cpp @@ -41,19 +41,22 @@ int main(int argc, char* argv[]) CommonExampleOptions options(&gui); CommonExampleInterface* example = StandaloneExampleCreateFunc(options); - - example->initPhysics(); - + example->initPhysics(); + example->resetCamera(); + do { app->m_instancingRenderer->init(); - app->m_instancingRenderer->updateCamera(); + app->m_instancingRenderer->updateCamera(app->getUpAxis()); example->stepSimulation(1./60.); example->renderScene(); - app->drawGrid(); + DrawGridData dg; + dg.upAxis = app->getUpAxis(); + app->drawGrid(dg); + app->swapBuffer(); } while (!app->m_window->requestedExit()); diff --git a/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp b/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp index 230f5e651..1819c44cf 100644 --- a/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp +++ b/examples/StandaloneMain/main_sw_tinyrenderer_single_example.cpp @@ -111,8 +111,8 @@ public: if (shapeIndex>=0) { TinyRenderObjectData* swObj = new TinyRenderObjectData(m_swWidth,m_swHeight,m_rgbColorBuffer,m_depthBuffer); - //swObj->registerMeshShape(vertices,numvertices,indices,numIndices); - swObj->createCube(1,1,1);//MeshShape(vertices,numvertices,indices,numIndices); + swObj->registerMeshShape(vertices,numvertices,indices,numIndices); + //swObj->createCube(1,1,1);//MeshShape(vertices,numvertices,indices,numIndices); m_swRenderObjects.insert(shapeIndex,swObj); } return shapeIndex; @@ -242,18 +242,20 @@ int main(int argc, char* argv[]) CommonExampleInterface* example = StandaloneExampleCreateFunc(options); example->initPhysics(); - + example->resetCamera(); do { app->m_instancingRenderer->init(); - app->m_instancingRenderer->updateCamera(); + app->m_instancingRenderer->updateCamera(app->getUpAxis()); example->stepSimulation(1./60.); example->renderScene(); - app->drawGrid(); + DrawGridData dg; + dg.upAxis = app->getUpAxis(); + app->drawGrid(dg); app->swapBuffer(); } while (!app->m_window->requestedExit()); diff --git a/examples/TinyRenderer/TinyRenderer.cpp b/examples/TinyRenderer/TinyRenderer.cpp index a78e9d6ac..7130f84db 100644 --- a/examples/TinyRenderer/TinyRenderer.cpp +++ b/examples/TinyRenderer/TinyRenderer.cpp @@ -69,8 +69,8 @@ struct Shader : public IShader { Vec3f n = (B*m_model->normal(uv)).normalize(); - //float diff = b3Min(b3Max(0.f, n*m_light_dir_local+0.3f),1.f); - float diff = b3Max(0.f, n*m_light_dir_local); + float diff = b3Min(b3Max(0.f, n*m_light_dir_local+0.3f),1.f); + //float diff = b3Max(0.f, n*m_light_dir_local); color = m_model->diffuse(uv)*diff; return false; From 5151519b9494e7b33e3868f300ea848bb9b3e16d Mon Sep 17 00:00:00 2001 From: erwincoumans Date: Fri, 6 May 2016 15:07:54 -0700 Subject: [PATCH 41/50] https://github.com/bulletphysics/bullet3/pull/618 by Mobeen Summary of changes: 1) Changed include paths to be relative to the current sources (affected files: LoadMeshFromObj.cpp, Wavefront2GLInstanceGraphicsShape.h/cpp) 2) Added new tutorials in the ExtendedTutorials folder 3) Modified the main_opengl_single_example.cpp file to enable picking support in standalone demos --- examples/ExampleBrowser/CMakeLists.txt | 11 +- examples/ExampleBrowser/ExampleEntries.cpp | 30 +++- examples/ExampleBrowser/premake4.lua | 1 + examples/ExtendedTutorials/Bridge.cpp | 150 ++++++++++++++++ examples/ExtendedTutorials/Bridge.h | 22 +++ examples/ExtendedTutorials/Chain.cpp | 137 +++++++++++++++ examples/ExtendedTutorials/Chain.h | 22 +++ examples/ExtendedTutorials/MultipleBoxes.cpp | 120 +++++++++++++ examples/ExtendedTutorials/MultipleBoxes.h | 22 +++ .../ExtendedTutorials/RigidBodyFromObj.cpp | 159 +++++++++++++++++ examples/ExtendedTutorials/RigidBodyFromObj.h | 28 +++ examples/ExtendedTutorials/SimpleBox.cpp | 118 +++++++++++++ examples/ExtendedTutorials/SimpleBox.h | 22 +++ examples/ExtendedTutorials/SimpleCloth.cpp | 162 ++++++++++++++++++ examples/ExtendedTutorials/SimpleCloth.h | 22 +++ examples/ExtendedTutorials/SimpleJoint.cpp | 133 ++++++++++++++ examples/ExtendedTutorials/SimpleJoint.h | 22 +++ .../main_opengl_single_example.cpp | 33 +++- 18 files changed, 1206 insertions(+), 8 deletions(-) create mode 100644 examples/ExtendedTutorials/Bridge.cpp create mode 100644 examples/ExtendedTutorials/Bridge.h create mode 100644 examples/ExtendedTutorials/Chain.cpp create mode 100644 examples/ExtendedTutorials/Chain.h create mode 100644 examples/ExtendedTutorials/MultipleBoxes.cpp create mode 100644 examples/ExtendedTutorials/MultipleBoxes.h create mode 100644 examples/ExtendedTutorials/RigidBodyFromObj.cpp create mode 100644 examples/ExtendedTutorials/RigidBodyFromObj.h create mode 100644 examples/ExtendedTutorials/SimpleBox.cpp create mode 100644 examples/ExtendedTutorials/SimpleBox.h create mode 100644 examples/ExtendedTutorials/SimpleCloth.cpp create mode 100644 examples/ExtendedTutorials/SimpleCloth.h create mode 100644 examples/ExtendedTutorials/SimpleJoint.cpp create mode 100644 examples/ExtendedTutorials/SimpleJoint.h diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index b3f06d557..68ffa8f0a 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -7,7 +7,15 @@ INCLUDE_DIRECTORIES( FILE(GLOB GwenGUISupport_SRCS "GwenGUISupport/*" ) FILE(GLOB GwenGUISupport_HDRS "GwenGUISupport/*" ) - +SET(ExtendedTutorialsSources + ../ExtendedTutorials/SimpleBox.cpp + ../ExtendedTutorials/MultipleBoxes.cpp + ../ExtendedTutorials/SimpleJoint.cpp + ../ExtendedTutorials/SimpleCloth.cpp + ../ExtendedTutorials/Chain.cpp + ../ExtendedTutorials/Bridge.cpp + ../ExtendedTutorials/RigidBodyFromObj.cpp +) SET(BulletExampleBrowser_SRCS OpenGLExampleBrowser.cpp @@ -178,6 +186,7 @@ SET(BulletExampleBrowser_SRCS ../Utils/b3ResourcePath.h ${GwenGUISupport_SRCS} ${GwenGUISupport_HDRS} + ${ExtendedTutorialsSources} ${BULLET_PHYSICS_SOURCE_DIR}/build3/bullet.rc ) diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index 08f71cf69..20b14ef8a 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -54,7 +54,14 @@ #endif #endif //B3_USE_CLEW - +//Extended Tutorial Includes Added by Mobeen +#include "../ExtendedTutorials/SimpleBox.h" +#include "../ExtendedTutorials/MultipleBoxes.h" +#include "../ExtendedTutorials/SimpleJoint.h" +#include "../ExtendedTutorials/SimpleCloth.h" +#include "../ExtendedTutorials/Chain.h" +#include "../ExtendedTutorials/Bridge.h" +#include "../ExtendedTutorials/RigidBodyFromObj.h" struct ExampleEntry { @@ -78,11 +85,12 @@ struct ExampleEntry static ExampleEntry gDefaultExamples[]= { - - - - + ExampleEntry(0,"API"), + ExampleEntry(1,"Obj2RigidBody (Show Obj)", "Load a triangle mesh from Wavefront .obj and turn it in a convex hull collision shape, connected to a rigid body. We can use the original .obj mesh data to visualize the rigid body. In 'debug' wireframe mode (press 'w' to toggle) we still see the convex hull data.", ET_RigidBodyFromObjCreateFunc,ObjUseConvexHullForRendering), + ExampleEntry(1,"Obj2RigidBody (Show Hull)", "Load a triangle mesh from Wavefront .obj and turn it in a convex hull collision shape, connected to a rigid body", ET_RigidBodyFromObjCreateFunc), + ExampleEntry(1,"Obj2RigidBody Optimize", "Load a triangle mesh from Wavefront .obj, remove the vertices that are not on the convex hull", ET_RigidBodyFromObjCreateFunc,OptimizeConvexObj), + ExampleEntry(1,"Obj2RigidBody Add Features", "Load a triangle mesh from Wavefront .obj and create polyhedral features to perform the separating axis test (instead of GJK/MPR). It is best to combine optimization and polyhedral feature generation.", ET_RigidBodyFromObjCreateFunc,OptimizeConvexObj+ComputePolyhedralFeatures), ExampleEntry(1,"Basic Example","Create some rigid bodies using box collision shapes. This is a good example to familiarize with the basic initialization of Bullet. The Basic Example can also be compiled without graphical user interface, as a console application. Press W for wireframe, A to show AABBs, I to suspend/restart physics simulation. Press D to toggle auto-deactivation of the simulation. ", BasicExampleCreateFunc), @@ -252,8 +260,18 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(0,"Rendering"), ExampleEntry(1,"Instanced Rendering", "Simple example of fast instanced rendering, only active when using OpenGL3+.",RenderInstancingCreateFunc), ExampleEntry(1,"CoordinateSystemDemo","Show the axis and positive rotation direction around the axis.", CoordinateSystemCreateFunc), - ExampleEntry(1,"Time Series", "Render some value(s) in a 2D graph window, shifting to the left", TimeSeriesCreateFunc) + ExampleEntry(1,"Time Series", "Render some value(s) in a 2D graph window, shifting to the left", TimeSeriesCreateFunc), + //Extended Tutorials Added by Mobeen + ExampleEntry(0,"Extended Tutorials"), + ExampleEntry(1,"Simple Box", "Simplest possible demo creating a single box rigid body that falls under gravity", ET_SimpleBoxCreateFunc), + ExampleEntry(1,"Multiple Boxes", "Adding multiple box rigid bodies that fall under gravity", ET_MultipleBoxesCreateFunc), + ExampleEntry(1,"Simple Joint", "Creating a single distance constraint between two box rigid bodies", ET_SimpleJointCreateFunc), + ExampleEntry(1,"Simple Cloth", "Creating a simple piece of cloth", ET_SimpleClothCreateFunc), + ExampleEntry(1,"Simple Chain", "Creating a simple chain using a pair of point2point/distance constraints. You may click and drag any box to see the chain respond.", ET_ChainCreateFunc), + ExampleEntry(1,"Simple Bridge", "Creating a simple bridge using a pair of point2point/distance constraints. You may click and drag any plank to see the bridge respond.", ET_BridgeCreateFunc), + + }; #ifdef B3_USE_CLEW diff --git a/examples/ExampleBrowser/premake4.lua b/examples/ExampleBrowser/premake4.lua index f671d5a0d..5bbbf51f7 100644 --- a/examples/ExampleBrowser/premake4.lua +++ b/examples/ExampleBrowser/premake4.lua @@ -136,6 +136,7 @@ project "BulletExampleBrowserLib" "../InverseDynamics/InverseDynamicsExample.h", "../BasicDemo/BasicExample.*", "../Tutorial/*", + "../ExtendedTutorials/*", "../Collision/*", "../Collision/Internal/*", "../Benchmarks/*", diff --git a/examples/ExtendedTutorials/Bridge.cpp b/examples/ExtendedTutorials/Bridge.cpp new file mode 100644 index 000000000..269b5c4d0 --- /dev/null +++ b/examples/ExtendedTutorials/Bridge.cpp @@ -0,0 +1,150 @@ +/* +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 "Bridge.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" + +const int TOTAL_PLANKS = 10; +struct BridgeExample : public CommonRigidBodyBase +{ + BridgeExample(struct GUIHelperInterface* helper) + :CommonRigidBodyBase(helper) + { + } + virtual ~BridgeExample(){} + virtual void initPhysics(); + virtual void renderScene(); + void resetCamera() + { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3]={0,0.46,0}; + m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); + } +}; + +void BridgeExample::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_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + { + btScalar mass(0.); + createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1)); + } + + //create two fixed boxes to hold the planks + + + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + btScalar plankWidth = 0.4; + btScalar plankHeight = 0.2; + btScalar plankBreadth = 1; + btScalar plankOffset = plankWidth; //distance between two planks + btScalar bridgeWidth = plankWidth*TOTAL_PLANKS + plankOffset*(TOTAL_PLANKS-1); + btScalar bridgeHeight = 5; + btScalar halfBridgeWidth = bridgeWidth*0.5f; + + btBoxShape* colShape = createBoxShape(btVector3(plankWidth,plankHeight,plankBreadth)); + + 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); + + //create a set of boxes to represent bridge + btAlignedObjectArray boxes; + int lastBoxIndex = TOTAL_PLANKS-1; + for(int i=0;iaddConstraint(leftSpring); + + btPoint2PointConstraint* rightSpring = new btPoint2PointConstraint(*b1, *b2, btVector3(-0.5,0,0.5), btVector3(0.5,0,0.5)); + m_dynamicsWorld->addConstraint(rightSpring); + } + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); +} + + +void BridgeExample::renderScene() +{ + CommonRigidBodyBase::renderScene(); +} + + + + + + + +CommonExampleInterface* ET_BridgeCreateFunc(CommonExampleOptions& options) +{ + return new BridgeExample(options.m_guiHelper); +} + + + diff --git a/examples/ExtendedTutorials/Bridge.h b/examples/ExtendedTutorials/Bridge.h new file mode 100644 index 000000000..5f8331183 --- /dev/null +++ b/examples/ExtendedTutorials/Bridge.h @@ -0,0 +1,22 @@ +/* +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. +*/ + +#ifndef ET_BRIDGE_EXAMPLE_H +#define ET_BRIDGE_EXAMPLE_H + +class CommonExampleInterface* ET_BridgeCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_BRIDGE_EXAMPLE_H diff --git a/examples/ExtendedTutorials/Chain.cpp b/examples/ExtendedTutorials/Chain.cpp new file mode 100644 index 000000000..e78952db9 --- /dev/null +++ b/examples/ExtendedTutorials/Chain.cpp @@ -0,0 +1,137 @@ +/* +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 "Chain.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" + +const int TOTAL_BOXES = 10; +struct ChainExample : public CommonRigidBodyBase +{ + ChainExample(struct GUIHelperInterface* helper) + :CommonRigidBodyBase(helper) + { + } + virtual ~ChainExample(){} + virtual void initPhysics(); + virtual void renderScene(); + void resetCamera() + { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3]={0,0.46,0}; + m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); + } +}; + +void ChainExample::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_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + { + btScalar mass(0.); + createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1)); + } + + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + btBoxShape* colShape = createBoxShape(btVector3(1,1,0.25)); + + 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); + + btAlignedObjectArray boxes; + int lastBoxIndex = TOTAL_BOXES-1; + for(int i=0;iaddConstraint(leftSpring); + + btPoint2PointConstraint* rightSpring = new btPoint2PointConstraint(*b1, *b2, btVector3(0.5,1,0), btVector3(0.5,-1,0)); + + m_dynamicsWorld->addConstraint(rightSpring); + } + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); +} + + +void ChainExample::renderScene() +{ + CommonRigidBodyBase::renderScene(); +} + + + + + + + +CommonExampleInterface* ET_ChainCreateFunc(CommonExampleOptions& options) +{ + return new ChainExample(options.m_guiHelper); +} + + + diff --git a/examples/ExtendedTutorials/Chain.h b/examples/ExtendedTutorials/Chain.h new file mode 100644 index 000000000..b9cea1195 --- /dev/null +++ b/examples/ExtendedTutorials/Chain.h @@ -0,0 +1,22 @@ +/* +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. +*/ + +#ifndef ET_CHAIN_EXAMPLE_H +#define ET_CHAIN_EXAMPLE_H + +class CommonExampleInterface* ET_ChainCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_CHAIN_EXAMPLE_H diff --git a/examples/ExtendedTutorials/MultipleBoxes.cpp b/examples/ExtendedTutorials/MultipleBoxes.cpp new file mode 100644 index 000000000..c9555936a --- /dev/null +++ b/examples/ExtendedTutorials/MultipleBoxes.cpp @@ -0,0 +1,120 @@ +/* +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 "MultipleBoxes.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" + +const int TOTAL_BOXES = 10; +struct MultipleBoxesExample : public CommonRigidBodyBase +{ + MultipleBoxesExample(struct GUIHelperInterface* helper) + :CommonRigidBodyBase(helper) + { + } + virtual ~MultipleBoxesExample(){} + virtual void initPhysics(); + virtual void renderScene(); + void resetCamera() + { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3]={0,0.46,0}; + m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); + } +}; + +void MultipleBoxesExample::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_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + { + btScalar mass(0.); + createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1)); + } + + + { + //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_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 i=0;iautogenerateGraphicsObjects(m_dynamicsWorld); +} + + +void MultipleBoxesExample::renderScene() +{ + CommonRigidBodyBase::renderScene(); +} + + + + + + + +CommonExampleInterface* ET_MultipleBoxesCreateFunc(CommonExampleOptions& options) +{ + return new MultipleBoxesExample(options.m_guiHelper); +} + + + diff --git a/examples/ExtendedTutorials/MultipleBoxes.h b/examples/ExtendedTutorials/MultipleBoxes.h new file mode 100644 index 000000000..56e28b61d --- /dev/null +++ b/examples/ExtendedTutorials/MultipleBoxes.h @@ -0,0 +1,22 @@ +/* +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. +*/ + +#ifndef ET_MULTIPLE_BOXES_EXAMPLE_H +#define ET_MULTIPLE_BOXES_EXAMPLE_H + +class CommonExampleInterface* ET_MultipleBoxesCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_MULTIPLE_BOXES_EXAMPLE_H diff --git a/examples/ExtendedTutorials/RigidBodyFromObj.cpp b/examples/ExtendedTutorials/RigidBodyFromObj.cpp new file mode 100644 index 000000000..ffda148ce --- /dev/null +++ b/examples/ExtendedTutorials/RigidBodyFromObj.cpp @@ -0,0 +1,159 @@ +/* +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 "RigidBodyFromObj.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" + +#include "../Utils/b3ResourcePath.h" +#include "Bullet3Common/b3FileUtils.h" +#include "../Importers/ImportObjDemo/LoadMeshFromObj.h" +#include "../OpenGLWindow/GLInstanceGraphicsShape.h" + + +struct RigidBodyFromObjExample : public CommonRigidBodyBase +{ + int m_options; + + RigidBodyFromObjExample(struct GUIHelperInterface* helper, int options) + :CommonRigidBodyBase(helper), + m_options(options) + { + } + virtual ~RigidBodyFromObjExample(){} + virtual void initPhysics(); + virtual void renderScene(); + void resetCamera() + { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3]={0,0.46,0}; + m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); + } +}; + +void RigidBodyFromObjExample::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_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + { + btScalar mass(0.); + createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1)); + } + + //load our obj mesh + const char* fileName = "teddy.obj";//sphere8.obj";//sponza_closed.obj";//sphere8.obj"; + char relativeFileName[1024]; + if (b3ResourcePath::findResourcePath(fileName, relativeFileName, 1024)) + { + char pathPrefix[1024]; + b3FileUtils::extractPath(relativeFileName, pathPrefix, 1024); + } + + GLInstanceGraphicsShape* glmesh = LoadMeshFromObj(relativeFileName, ""); + printf("[INFO] Obj loaded: Extracted %d verticed from obj file [%s]\n", glmesh->m_numvertices, fileName); + + const GLInstanceVertex& v = glmesh->m_vertices->at(0); + btConvexHullShape* shape = new btConvexHullShape((const btScalar*)(&(v.xyzw[0])), glmesh->m_numvertices, sizeof(GLInstanceVertex)); + + shape->setLocalScaling(btVector3(0.1,0.1,0.1)); + + if (m_options & OptimizeConvexObj) + { + shape->optimizeConvexHull(); + } + + if (m_options & ComputePolyhedralFeatures) + { + shape->initializePolyhedralFeatures(); + } + + + + //shape->setMargin(0.001); + m_collisionShapes.push_back(shape); + + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + bool isDynamic = (mass != 0.f); + btVector3 localInertia(0,0,0); + if (isDynamic) + shape->calculateLocalInertia(mass,localInertia); + + btVector3 position(0,20,0); + startTransform.setOrigin(position); + btRigidBody* body = createRigidBody(mass,startTransform,shape); + + btVector3 color(1,1,1); + btVector3 scaling(0.1,0.1,0.1); + bool useObjForRendering = ((m_options & ObjUseConvexHullForRendering)!=0); + + + if (useObjForRendering) + { + int shapeId = m_guiHelper->getRenderInterface()->registerShape(&glmesh->m_vertices->at(0).xyzw[0], + glmesh->m_numvertices, + &glmesh->m_indices->at(0), + glmesh->m_numIndices, + B3_GL_TRIANGLES,-1); + shape->setUserIndex(shapeId); + int renderInstance = m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId,position,startTransform.getRotation(),color,scaling); + body->setUserIndex(renderInstance); + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); +} + + +void RigidBodyFromObjExample::renderScene() +{ + CommonRigidBodyBase::renderScene(); +} + + + + + + + +CommonExampleInterface* ET_RigidBodyFromObjCreateFunc(CommonExampleOptions& options) +{ + return new RigidBodyFromObjExample(options.m_guiHelper,options.m_option); +} + + + diff --git a/examples/ExtendedTutorials/RigidBodyFromObj.h b/examples/ExtendedTutorials/RigidBodyFromObj.h new file mode 100644 index 000000000..829e9e14a --- /dev/null +++ b/examples/ExtendedTutorials/RigidBodyFromObj.h @@ -0,0 +1,28 @@ +/* +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. +*/ + +#ifndef ET_RIGIDBODYFROMOBJ_EXAMPLE_H +#define ET_RIGIDBODYFROMOBJ_EXAMPLE_H + +enum ObjToRigidBodyOptionsEnum +{ + ObjUseConvexHullForRendering=1, + OptimizeConvexObj=2, + ComputePolyhedralFeatures=4, +}; +class CommonExampleInterface* ET_RigidBodyFromObjCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_RIGIDBODYFROMOBJ_EXAMPLE_H diff --git a/examples/ExtendedTutorials/SimpleBox.cpp b/examples/ExtendedTutorials/SimpleBox.cpp new file mode 100644 index 000000000..474a507f0 --- /dev/null +++ b/examples/ExtendedTutorials/SimpleBox.cpp @@ -0,0 +1,118 @@ +/* +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 "SimpleBox.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" + + +struct SimpleBoxExample : public CommonRigidBodyBase +{ + SimpleBoxExample(struct GUIHelperInterface* helper) + :CommonRigidBodyBase(helper) + { + } + virtual ~SimpleBoxExample(){} + virtual void initPhysics(); + virtual void renderScene(); + void resetCamera() + { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3]={0,0.46,0}; + m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); + } +}; + +void SimpleBoxExample::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_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + { + btScalar mass(0.); + createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1)); + } + + + { + //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_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( + btScalar(0), + btScalar(20), + btScalar(0))); + createRigidBody(mass,startTransform,colShape); + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); +} + + +void SimpleBoxExample::renderScene() +{ + CommonRigidBodyBase::renderScene(); +} + + + + + + + +CommonExampleInterface* ET_SimpleBoxCreateFunc(CommonExampleOptions& options) +{ + return new SimpleBoxExample(options.m_guiHelper); +} + + + diff --git a/examples/ExtendedTutorials/SimpleBox.h b/examples/ExtendedTutorials/SimpleBox.h new file mode 100644 index 000000000..494b3fd03 --- /dev/null +++ b/examples/ExtendedTutorials/SimpleBox.h @@ -0,0 +1,22 @@ +/* +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. +*/ + +#ifndef ET_SIMPLE_BOX_EXAMPLE_H +#define ET_SIMPLE_BOX_EXAMPLE_H + +class CommonExampleInterface* ET_SimpleBoxCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_SIMPLE_BOX_EXAMPLE_H diff --git a/examples/ExtendedTutorials/SimpleCloth.cpp b/examples/ExtendedTutorials/SimpleCloth.cpp new file mode 100644 index 000000000..33a3815b1 --- /dev/null +++ b/examples/ExtendedTutorials/SimpleCloth.cpp @@ -0,0 +1,162 @@ +/* +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 "SimpleCloth.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" + +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" +#include "BulletSoftBody/btSoftBodyHelpers.h" +#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h" + +struct SimpleClothExample : public CommonRigidBodyBase +{ + SimpleClothExample(struct GUIHelperInterface* helper) + :CommonRigidBodyBase(helper) + { + } + virtual ~SimpleClothExample(){} + virtual void initPhysics(); + virtual void renderScene(); + void createEmptyDynamicsWorld() + { + m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(); + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + m_broadphase = new btDbvtBroadphase(); + + m_solver = new btSequentialImpulseConstraintSolver; + + m_dynamicsWorld = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration); + m_dynamicsWorld->setGravity(btVector3(0, -10, 0)); + + softBodyWorldInfo.m_broadphase = m_broadphase; + softBodyWorldInfo.m_dispatcher = m_dispatcher; + softBodyWorldInfo.m_gravity = m_dynamicsWorld->getGravity(); + softBodyWorldInfo.m_sparsesdf.Initialize(); + } + virtual btSoftRigidDynamicsWorld* getSoftDynamicsWorld() + { + ///just make it a btSoftRigidDynamicsWorld please + ///or we will add type checking + return (btSoftRigidDynamicsWorld*) m_dynamicsWorld; + } + void resetCamera() + { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3]={0,0.46,0}; + m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); + } + + void createSoftBody(const btScalar size, const int num_x, const int num_z, const int fixed=1+2); + btSoftBodyWorldInfo softBodyWorldInfo; +}; + +void SimpleClothExample::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_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + { + btScalar mass(0.); + createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1)); + } + + + { + const btScalar s=4; //size of cloth patch + const int NUM_X=31; //vertices on X axis + const int NUM_Z=31; //vertices on Z axis + createSoftBody(s,NUM_X, NUM_Z); + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); +} + +void SimpleClothExample::createSoftBody(const btScalar s, + const int numX, + const int numY, + const int fixed) { + + + + btSoftBody* cloth=btSoftBodyHelpers::CreatePatch(softBodyWorldInfo, + btVector3(-s/2,s+1,0), + btVector3(+s/2,s+1,0), + btVector3(-s/2,s+1,+s), + btVector3(+s/2,s+1,+s), + numX,numY, + fixed,true); + + cloth->getCollisionShape()->setMargin(0.001f); + cloth->generateBendingConstraints(2,cloth->appendMaterial()); + cloth->setTotalMass(10); + //cloth->m_cfg.citerations = 10; +// cloth->m_cfg.diterations = 10; + cloth->m_cfg.piterations = 5; + cloth->m_cfg.kDP = 0.005f; + getSoftDynamicsWorld()->addSoftBody(cloth); + +} + +void SimpleClothExample::renderScene() +{ + CommonRigidBodyBase::renderScene(); + btSoftRigidDynamicsWorld* softWorld = getSoftDynamicsWorld(); + + for ( int i=0;igetSoftBodyArray().size();i++) + { + btSoftBody* psb=(btSoftBody*)softWorld->getSoftBodyArray()[i]; + //if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) + { + btSoftBodyHelpers::DrawFrame(psb,softWorld->getDebugDrawer()); + btSoftBodyHelpers::Draw(psb,softWorld->getDebugDrawer(),softWorld->getDrawFlags()); + } + } +} + + + + + + + +CommonExampleInterface* ET_SimpleClothCreateFunc(CommonExampleOptions& options) +{ + return new SimpleClothExample(options.m_guiHelper); +} + + + diff --git a/examples/ExtendedTutorials/SimpleCloth.h b/examples/ExtendedTutorials/SimpleCloth.h new file mode 100644 index 000000000..d956833e9 --- /dev/null +++ b/examples/ExtendedTutorials/SimpleCloth.h @@ -0,0 +1,22 @@ +/* +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. +*/ + +#ifndef ET_SIMPLE_CLOTH_EXAMPLE_H +#define ET_SIMPLE_CLOTH_EXAMPLE_H + +class CommonExampleInterface* ET_SimpleClothCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_SIMPLE_CLOTH_EXAMPLE_H diff --git a/examples/ExtendedTutorials/SimpleJoint.cpp b/examples/ExtendedTutorials/SimpleJoint.cpp new file mode 100644 index 000000000..da30449b4 --- /dev/null +++ b/examples/ExtendedTutorials/SimpleJoint.cpp @@ -0,0 +1,133 @@ +/* +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 "SimpleJoint.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" + + +struct SimpleJointExample : public CommonRigidBodyBase +{ + SimpleJointExample(struct GUIHelperInterface* helper) + :CommonRigidBodyBase(helper) + { + } + virtual ~SimpleJointExample(){} + virtual void initPhysics(); + virtual void renderScene(); + void resetCamera() + { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3]={0,0.46,0}; + m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); + } +}; + +void SimpleJointExample::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_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + { + btScalar mass(0.); + createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1)); + } + + + { + //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_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( + btScalar(0), + btScalar(10), + btScalar(0))); + btRigidBody* dynamicBox = createRigidBody(mass,startTransform,colShape); + + //create a static rigid body + mass = 0; + startTransform.setOrigin(btVector3( + btScalar(0), + btScalar(20), + btScalar(0))); + + btRigidBody* staticBox = createRigidBody(mass,startTransform,colShape); + + //create a simple p2pjoint constraint + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*dynamicBox, *staticBox, btVector3(0,3,0), btVector3(0,0,0)); + p2p->m_setting.m_damping = 0.0625; + p2p->m_setting.m_impulseClamp = 0.95; + m_dynamicsWorld->addConstraint(p2p); + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); +} + + +void SimpleJointExample::renderScene() +{ + CommonRigidBodyBase::renderScene(); +} + + + + + + + +CommonExampleInterface* ET_SimpleJointCreateFunc(CommonExampleOptions& options) +{ + return new SimpleJointExample(options.m_guiHelper); +} + + + diff --git a/examples/ExtendedTutorials/SimpleJoint.h b/examples/ExtendedTutorials/SimpleJoint.h new file mode 100644 index 000000000..a3d245a23 --- /dev/null +++ b/examples/ExtendedTutorials/SimpleJoint.h @@ -0,0 +1,22 @@ +/* +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. +*/ + +#ifndef ET_SIMPLE_JOINT_EXAMPLE_H +#define ET_SIMPLE_JOINT_EXAMPLE_H + +class CommonExampleInterface* ET_SimpleJointCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_SIMPLE_JOINT_EXAMPLE_H diff --git a/examples/StandaloneMain/main_opengl_single_example.cpp b/examples/StandaloneMain/main_opengl_single_example.cpp index 4fd1ff422..e74cda181 100644 --- a/examples/StandaloneMain/main_opengl_single_example.cpp +++ b/examples/StandaloneMain/main_opengl_single_example.cpp @@ -31,16 +31,47 @@ subject to the following restrictions: #include #include "../ExampleBrowser/OpenGLGuiHelper.h" +CommonExampleInterface* example; + +b3MouseMoveCallback prevMouseMoveCallback = 0; +static void OnMouseMove( float x, float y) +{ + bool handled = false; + handled = example->mouseMoveCallback(x,y); + if (!handled) + { + if (prevMouseMoveCallback) + prevMouseMoveCallback (x,y); + } +} + +b3MouseButtonCallback prevMouseButtonCallback = 0; +static void OnMouseDown(int button, int state, float x, float y) { + bool handled = false; + + handled = example->mouseButtonCallback(button, state, x,y); + if (!handled) + { + if (prevMouseButtonCallback ) + prevMouseButtonCallback (button,state,x,y); + } +} int main(int argc, char* argv[]) { SimpleOpenGL3App* app = new SimpleOpenGL3App("Bullet Standalone Example",1024,768,true); + prevMouseButtonCallback = app->m_window->getMouseButtonCallback(); + prevMouseMoveCallback = app->m_window->getMouseMoveCallback(); + + app->m_window->setMouseButtonCallback((b3MouseButtonCallback)OnMouseDown); + app->m_window->setMouseMoveCallback((b3MouseMoveCallback)OnMouseMove); + OpenGLGuiHelper gui(app,false); CommonExampleOptions options(&gui); - CommonExampleInterface* example = StandaloneExampleCreateFunc(options); + example = StandaloneExampleCreateFunc(options); example->initPhysics(); From 8a68e27bb74fe92dde90a8fde14f279fe94ee27e Mon Sep 17 00:00:00 2001 From: erwincoumans Date: Sat, 7 May 2016 16:36:14 -0700 Subject: [PATCH 42/50] move the RigidBodyFromObj to Importers section. --- examples/ExampleBrowser/ExampleEntries.cpp | 20 +++++++++---------- .../ExtendedTutorials/RigidBodyFromObj.cpp | 4 ++-- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index 20b14ef8a..6c66e2716 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -87,10 +87,6 @@ static ExampleEntry gDefaultExamples[]= { ExampleEntry(0,"API"), - ExampleEntry(1,"Obj2RigidBody (Show Obj)", "Load a triangle mesh from Wavefront .obj and turn it in a convex hull collision shape, connected to a rigid body. We can use the original .obj mesh data to visualize the rigid body. In 'debug' wireframe mode (press 'w' to toggle) we still see the convex hull data.", ET_RigidBodyFromObjCreateFunc,ObjUseConvexHullForRendering), - ExampleEntry(1,"Obj2RigidBody (Show Hull)", "Load a triangle mesh from Wavefront .obj and turn it in a convex hull collision shape, connected to a rigid body", ET_RigidBodyFromObjCreateFunc), - ExampleEntry(1,"Obj2RigidBody Optimize", "Load a triangle mesh from Wavefront .obj, remove the vertices that are not on the convex hull", ET_RigidBodyFromObjCreateFunc,OptimizeConvexObj), - ExampleEntry(1,"Obj2RigidBody Add Features", "Load a triangle mesh from Wavefront .obj and create polyhedral features to perform the separating axis test (instead of GJK/MPR). It is best to combine optimization and polyhedral feature generation.", ET_RigidBodyFromObjCreateFunc,OptimizeConvexObj+ComputePolyhedralFeatures), ExampleEntry(1,"Basic Example","Create some rigid bodies using box collision shapes. This is a good example to familiarize with the basic initialization of Bullet. The Basic Example can also be compiled without graphical user interface, as a console application. Press W for wireframe, A to show AABBs, I to suspend/restart physics simulation. Press D to toggle auto-deactivation of the simulation. ", BasicExampleCreateFunc), @@ -203,6 +199,10 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(0,"Importers"), ExampleEntry(1,"Import .bullet", "Load a binary .bullet file. The serialization mechanism can deal with versioning, differences in endianess, 32 and 64bit, double/single precision. It is easy to save a .bullet file, see the examples/Importers/ImportBullet/SerializeDemo.cpp for a code example how to export a .bullet file.", SerializeBulletCreateFunc), ExampleEntry(1,"Wavefront Obj", "Import a Wavefront .obj file", ImportObjCreateFunc, 0), + ExampleEntry(1,"Obj2RigidBody (Show Obj)", "Load a triangle mesh from Wavefront .obj and turn it in a convex hull collision shape, connected to a rigid body. We can use the original .obj mesh data to visualize the rigid body. In 'debug' wireframe mode (press 'w' to toggle) we still see the convex hull data.", ET_RigidBodyFromObjCreateFunc), + ExampleEntry(1,"Obj2RigidBody (Show Hull)", "Load a triangle mesh from Wavefront .obj and turn it in a convex hull collision shape, connected to a rigid body", ET_RigidBodyFromObjCreateFunc,ObjUseConvexHullForRendering), + ExampleEntry(1,"Obj2RigidBody Optimize", "Load a triangle mesh from Wavefront .obj, remove the vertices that are not on the convex hull", ET_RigidBodyFromObjCreateFunc,OptimizeConvexObj), + ExampleEntry(1,"Quake BSP", "Import a Quake .bsp file", ImportBspCreateFunc, 0), ExampleEntry(1,"COLLADA dae", "Import the geometric mesh data from a COLLADA file. This is used as part of the URDF importer. This loader can also be used to import collision geometry in general. ", ImportColladaCreateFunc, 0), @@ -211,6 +211,7 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(1,"URDF (MultiBody)", "Import a URDF file and create a single multibody (btMultiBody) with tree hierarchy of links (mobilizers).", ImportURDFCreateFunc, 1), + ExampleEntry(0,"Vehicles"), ExampleEntry(1,"Hinge2 Vehicle", "A rigid body chassis with 4 rigid body wheels attached by a btHinge2Constraint",Hinge2VehicleCreateFunc), ExampleEntry(1,"ForkLift","Simulate a fork lift vehicle with a working fork lift that can be moved using the cursor keys. The wheels collision is simplified using ray tests." @@ -226,13 +227,6 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(0,"Experiments"), -// ExampleEntry(1,"Robot Control (Velocity)", "Perform some robot control tasks, using physics server and client that communicate over shared memory", -// RobotControlExampleCreateFunc,ROBOT_VELOCITY_CONTROL), -// ExampleEntry(1,"Robot Control (PD)", "Perform some robot control tasks, using physics server and client that communicate over shared memory", -// RobotControlExampleCreateFunc,ROBOT_PD_CONTROL), -// ExampleEntry(1,"Robot Joint Feedback", "Apply some small ping-pong target velocity jitter, and read the joint reaction forces, using physics server and client that communicate over shared memory.", - // RobotControlExampleCreateFunc,ROBOT_PING_PONG_JOINT_FEEDBACK), - ExampleEntry(1,"Physics Server", "Create a physics server that communicates with a physics client over shared memory", PhysicsServerCreateFunc), ExampleEntry(1,"Physics Server (Logging)", "Create a physics server that communicates with a physics client over shared memory. It will log all commands to a file.", @@ -271,6 +265,10 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(1,"Simple Chain", "Creating a simple chain using a pair of point2point/distance constraints. You may click and drag any box to see the chain respond.", ET_ChainCreateFunc), ExampleEntry(1,"Simple Bridge", "Creating a simple bridge using a pair of point2point/distance constraints. You may click and drag any plank to see the bridge respond.", ET_BridgeCreateFunc), + //todo: create a category/tutorial about advanced topics, such as optimizations, using different collision detection algorithm, different constraint solvers etc. + //ExampleEntry(0,"Advanced"), + //ExampleEntry(1,"Obj2RigidBody Add Features", "Load a triangle mesh from Wavefront .obj and create polyhedral features to perform the separating axis test (instead of GJK/MPR). It is best to combine optimization and polyhedral feature generation.", ET_RigidBodyFromObjCreateFunc,OptimizeConvexObj+ComputePolyhedralFeatures), + }; diff --git a/examples/ExtendedTutorials/RigidBodyFromObj.cpp b/examples/ExtendedTutorials/RigidBodyFromObj.cpp index ffda148ce..1a8835dfd 100644 --- a/examples/ExtendedTutorials/RigidBodyFromObj.cpp +++ b/examples/ExtendedTutorials/RigidBodyFromObj.cpp @@ -120,10 +120,10 @@ void RigidBodyFromObjExample::initPhysics() btVector3 color(1,1,1); btVector3 scaling(0.1,0.1,0.1); - bool useObjForRendering = ((m_options & ObjUseConvexHullForRendering)!=0); + bool useConvexHullForRendering = ((m_options & ObjUseConvexHullForRendering)!=0); - if (useObjForRendering) + if (!useConvexHullForRendering) { int shapeId = m_guiHelper->getRenderInterface()->registerShape(&glmesh->m_vertices->at(0).xyzw[0], glmesh->m_numvertices, From 4f169b4d8f04b4dece25a6560d6cd869a8b948ca Mon Sep 17 00:00:00 2001 From: Benjamin Ellenberger Date: Sun, 8 May 2016 20:26:05 +0200 Subject: [PATCH 43/50] Add missing m_callback call in SliderMove(). ------- The MySliderEventHandler is missing the m_callback whereas the SliderParams contains the m_callback field. Therefore, the m_callback is never called if the slider position is changed. This commit adds the missing m_callback field and call in SliderMove(). Fixes #613. --- .../GwenGUISupport/GwenParameterInterface.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/ExampleBrowser/GwenGUISupport/GwenParameterInterface.cpp b/examples/ExampleBrowser/GwenGUISupport/GwenParameterInterface.cpp index 5032a1cdb..fee07bc94 100644 --- a/examples/ExampleBrowser/GwenGUISupport/GwenParameterInterface.cpp +++ b/examples/ExampleBrowser/GwenGUISupport/GwenParameterInterface.cpp @@ -27,17 +27,19 @@ struct MyButtonEventHandler : public Gwen::Event::Handler template struct MySliderEventHandler : public Gwen::Event::Handler { + SliderParamChangedCallback m_callback; 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) + MySliderEventHandler(const char* varName, Gwen::Controls::TextBox* label, Gwen::Controls::Slider* pSlider,T* target,SliderParamChangedCallback callback) :m_label(label), m_pSlider(pSlider), m_targetValue(target), - m_showValue(true) + m_showValue(true), + m_callback(callback) { memcpy(m_variableName,varName,strlen(varName)+1); } @@ -51,6 +53,11 @@ struct MySliderEventHandler : public Gwen::Event::Handler T v = T(bla); SetValue(v); + if (m_callback) + { + (*m_callback)(v); + } + } void SetValue(T v) @@ -219,7 +226,7 @@ void GwenParameterInterface::registerSliderFloatParameter(SliderParams& params) pSlider->SetValue( *params.m_paramValuePointer);//dimensions[i] ); char labelName[1024]; sprintf(labelName,"%s",params.m_name);//axisNames[0]); - MySliderEventHandler* handler = new MySliderEventHandler(labelName,label,pSlider,params.m_paramValuePointer); + MySliderEventHandler* handler = new MySliderEventHandler(labelName,label,pSlider,params.m_paramValuePointer,params.m_callback); handler->m_showValue = params.m_showValues; m_paramInternalData->m_sliderEventHandlers.push_back(handler); From 2fee43b021e8e61bd9ec3f6cc73801cc36a8a3c7 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 9 May 2016 14:03:13 -0700 Subject: [PATCH 44/50] copy the data folder into the cmake build directory, for the ExampleBrowser out-of-source builds of Example Browser don't find their resources... --- examples/ExampleBrowser/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index 68ffa8f0a..fef09597d 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -282,6 +282,14 @@ ADD_EXECUTABLE(App_ExampleBrowser ExampleEntries.h ) +FILE( MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/data" ) + +ADD_CUSTOM_COMMAND( + TARGET App_ExampleBrowser + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory ${BULLET_PHYSICS_SOURCE_DIR}/data ${PROJECT_BINARY_DIR}/data + ) + IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) SET_TARGET_PROPERTIES(App_ExampleBrowser PROPERTIES DEBUG_POSTFIX "_Debug") From e9c6abff47718e68bb1c314b36814ca3a3ef6c7b Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 9 May 2016 17:25:07 -0700 Subject: [PATCH 45/50] add initial SDF importer, work-in-progress (still too incomplete to be useful) --- data/two_cubes.sdf | 239 +++++++++++ examples/ExampleBrowser/CMakeLists.txt | 1 + examples/ExampleBrowser/ExampleEntries.cpp | 4 +- .../ImportSDFDemo/ImportSDFSetup.cpp | 302 ++++++++++++++ .../Importers/ImportSDFDemo/ImportSDFSetup.h | 8 + .../ImportURDFDemo/BulletUrdfImporter.cpp | 58 +++ .../ImportURDFDemo/BulletUrdfImporter.h | 6 + .../ImportURDFDemo/ImportURDFSetup.cpp | 2 +- .../ImportURDFDemo/URDFImporterInterface.h | 2 + .../Importers/ImportURDFDemo/UrdfParser.cpp | 370 ++++++++++++++---- .../Importers/ImportURDFDemo/UrdfParser.h | 78 +++- 11 files changed, 991 insertions(+), 79 deletions(-) create mode 100644 data/two_cubes.sdf create mode 100644 examples/Importers/ImportSDFDemo/ImportSDFSetup.cpp create mode 100644 examples/Importers/ImportSDFDemo/ImportSDFSetup.h diff --git a/data/two_cubes.sdf b/data/two_cubes.sdf new file mode 100644 index 000000000..24c0854bd --- /dev/null +++ b/data/two_cubes.sdf @@ -0,0 +1,239 @@ + + + + 99.2 + 1 + 0 0 10 0 -0 0 + 0.8 0.8 0.8 1 + 0.2 0.2 0.2 1 + + 1000 + 0.9 + 0.01 + 0.001 + + -0.5 0.1 -0.9 + + + 1 + + + + + 1 2 3 + 100 100 + + + + + 65535 + + + + + 100 + 50 + + + + + + + + 10 + + + 0 + + + 4 5 6 + 100 100 + + + + + + + 0 + 0 + 1 + + + 0 0 -9.8 + 6e-06 2.3e-05 -4.2e-05 + + + 0.001 + 1 + 1000 + + + 0.4 0.4 0.4 1 + 0.7 0.7 0.7 1 + 1 + + + + EARTH_WGS84 + 0 + 0 + 0 + 0 + + + 0.512455 -1.58317 0.5 0 -0 0 + + + 1 + + 0.166667 + 0 + 0 + 0.166667 + 0 + 0.166667 + + + + + + 1 1 1 + + + 10 + + + + + + + + + + + + + + + + + 1 1 1 + + + + + + + 0 + 0 + 1 + + + + 0.105158 -4.55002 0.499995 -2.89297 -0.988287 -3.14159 + + + 1 + + 0.166667 + 0 + 0 + 0.166667 + 0 + 0.166667 + + + + + + 1 1 1 + + + 10 + + + + + + + + + + + + + + + + + 1 1 1 + + + + + + + 0 + 0 + 1 + + + + 0 0 + 0 0 + 1462824251 956472000 + 0 + + 0 0 0 0 -0 0 + 1 1 1 + + 0 0 0 0 -0 0 + 0 0 0 0 -0 0 + 0 0 0 0 -0 0 + 0 0 0 0 -0 0 + + + + 0.223196 -1.84719 0.499995 -2.89297 -0.988287 -3.14159 + 1 1 1 + + 0.223196 -1.84719 0.499995 -2.89297 -0.988287 -3.14159 + 0.004896 3e-06 -0.004891 -6e-06 0.009793 -0 + 0.010615 0.006191 -9.78231 -0.012424 0.021225 -1.8e-05 + 0.010615 0.006191 -9.78231 0 -0 0 + + + + 0.105158 -4.55002 0.499995 -2.89297 -0.988287 -3.14159 + 1 1 1 + + 0.105158 -4.55002 0.499995 -2.89297 -0.988287 -3.14159 + 0 0 0 0 -0 0 + 0 0 0 0 -0 0 + 0 0 0 0 -0 0 + + + + 0 0 10 0 -0 0 + + + + + 8.0562 -8.87312 3.07529 0 0.205021 2.5208 + orbit + perspective + + + + diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index fef09597d..0a1c172f0 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -132,6 +132,7 @@ SET(BulletExampleBrowser_SRCS ../Importers/ImportObjDemo/LoadMeshFromObj.cpp ../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp ../Importers/ImportSTLDemo/ImportSTLSetup.cpp + ../Importers/ImportSDFDemo/ImportSDFSetup.cpp ../Importers/ImportURDFDemo/ImportURDFSetup.cpp ../Importers/ImportURDFDemo/URDF2Bullet.cpp ../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index 6c66e2716..6d8b86bea 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -14,6 +14,7 @@ #include "../Importers/ImportColladaDemo/ImportColladaSetup.h" #include "../Importers/ImportSTLDemo/ImportSTLSetup.h" #include "../Importers/ImportURDFDemo/ImportURDFSetup.h" +#include "../Importers/ImportSDFDemo/ImportSDFSetup.h" #include "../Collision/CollisionTutorialBullet2.h" #include "../GyroscopicDemo/GyroscopicSetup.h" #include "../Constraints/Dof6Spring2Setup.h" @@ -126,7 +127,6 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(1,"Inverse Dynamics URDF", "Create a btMultiBody from URDF. Create an inverse MultiBodyTree model from that. Use either decoupled PD control or computed torque control using the inverse model to track joint position targets", InverseDynamicsExampleCreateFunc,BT_ID_LOAD_URDF), ExampleEntry(1,"Inverse Dynamics Prog", "Create a btMultiBody programatically. Create an inverse MultiBodyTree model from that. Use either decoupled PD control or computed torque control using the inverse model to track joint position targets", InverseDynamicsExampleCreateFunc,BT_ID_PROGRAMMATICALLY), - ExampleEntry(0,"Tutorial"), ExampleEntry(1,"Constant Velocity","Free moving rigid body, without external or constraint forces", TutorialCreateFunc,TUT_VELOCITY), ExampleEntry(1,"Gravity Acceleration","Motion of a free falling rigid body under constant gravitational acceleration", TutorialCreateFunc,TUT_ACCELERATION), @@ -210,7 +210,7 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(1,"URDF (RigidBody)", "Import a URDF file, and create rigid bodies (btRigidBody) connected by constraints.", ImportURDFCreateFunc, 0), ExampleEntry(1,"URDF (MultiBody)", "Import a URDF file and create a single multibody (btMultiBody) with tree hierarchy of links (mobilizers).", ImportURDFCreateFunc, 1), - + ExampleEntry(1,"SDF (MultiBody)", "Import an SDF file, create multiple multibodies etc", ImportSDFCreateFunc), ExampleEntry(0,"Vehicles"), ExampleEntry(1,"Hinge2 Vehicle", "A rigid body chassis with 4 rigid body wheels attached by a btHinge2Constraint",Hinge2VehicleCreateFunc), diff --git a/examples/Importers/ImportSDFDemo/ImportSDFSetup.cpp b/examples/Importers/ImportSDFDemo/ImportSDFSetup.cpp new file mode 100644 index 000000000..b95f528a9 --- /dev/null +++ b/examples/Importers/ImportSDFDemo/ImportSDFSetup.cpp @@ -0,0 +1,302 @@ + +#include "ImportSDFSetup.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h" + + +#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h" +#include "Bullet3Common/b3FileUtils.h" + +#include "BulletDynamics/Featherstone/btMultiBodyJointMotor.h" +#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h" +#include "../CommonInterfaces/CommonParameterInterface.h" +#include "../../Utils/b3ResourcePath.h" + +#include "../ImportURDFDemo/BulletUrdfImporter.h" + + +#include "../ImportURDFDemo/URDF2Bullet.h" + + +//#include "urdf_samples.h" + + + + + +#include "../CommonInterfaces/CommonMultiBodyBase.h" + +#include "../ImportURDFDemo/MyMultiBodyCreator.h" + + +class ImportSDFSetup : public CommonMultiBodyBase +{ + char m_fileName[1024]; + + struct ImportSDFInternalData* m_data; + bool m_useMultiBody; + + //todo(erwincoumans) we need a name memory for each model + btAlignedObjectArray m_nameMemory; + +public: + ImportSDFSetup(struct GUIHelperInterface* helper, int option, const char* fileName); + virtual ~ImportSDFSetup(); + + virtual void initPhysics(); + virtual void stepSimulation(float deltaTime); + + void setFileName(const char* urdfFileName); + + virtual void resetCamera() + { + float dist = 3.5; + float pitch = -136; + float yaw = 28; + float targetPos[3]={0.47,0,-0.64}; + m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); + } +}; + + +static btAlignedObjectArray gFileNameArray; + + +#define MAX_NUM_MOTORS 1024 + +struct ImportSDFInternalData +{ + ImportSDFInternalData() + :m_numMotors(0) + { + for (int i=0;i=numFileNames) + { + count=0; + } + sprintf(m_fileName,"%s",gFileNameArray[count++].c_str()); + } +} + +ImportSDFSetup::~ImportSDFSetup() +{ + for (int i=0;isetUpAxis(upAxis); + + this->createEmptyDynamicsWorld(); + //m_dynamicsWorld->getSolverInfo().m_numIterations = 100; + m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); + m_dynamicsWorld->getDebugDrawer()->setDebugMode( + btIDebugDraw::DBG_DrawConstraints + +btIDebugDraw::DBG_DrawContactPoints + +btIDebugDraw::DBG_DrawAabb + );//+btIDebugDraw::DBG_DrawConstraintLimits); + + + btVector3 gravity(0,0,0); + gravity[upAxis]=-9.8; + + m_dynamicsWorld->setGravity(gravity); + + BulletURDFImporter u2b(m_guiHelper); + + bool loadOk = u2b.loadSDF(m_fileName); + + + if (loadOk) + { + //printTree(u2b,u2b.getRootLinkIndex()); + + //u2b.printTree(); + + btTransform identityTrans; + identityTrans.setIdentity(); + + + + for (int m =0; m