1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2015 Google Inc. http://bulletphysics.org
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15
16 #include "../CommonInterfaces/CommonExampleInterface.h"
17 #include "../CommonInterfaces/CommonGUIHelperInterface.h"
18 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
19 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
20 #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
21
22 #include "LinearMath/btTransform.h"
23 #include "LinearMath/btHashMap.h"
24
25 #include "../TinyRenderer/TinyRenderer.h"
26 #include "../OpenGLWindow/SimpleOpenGL3App.h"
27 #include <stdio.h>
28 #include "../ExampleBrowser/OpenGLGuiHelper.h"
29
30 class SW_And_OpenGLGuiHelper : public OpenGLGuiHelper
31 {
32 btHashMap<btHashInt, TinyRenderObjectData*> m_swRenderObjects;
33 btHashMap<btHashInt, int> m_swInstances;
34
35 int m_swWidth;
36 int m_swHeight;
37 TGAImage m_rgbColorBuffer;
38
39 b3AlignedObjectArray<float> m_depthBuffer;
40 int m_textureHandle;
41 unsigned char* m_image;
42 GLPrimitiveRenderer* m_primRenderer;
43
44 public:
SW_And_OpenGLGuiHelper(CommonGraphicsApp * glApp,bool useOpenGL2,int swWidth,int swHeight,GLPrimitiveRenderer * primRenderer)45 SW_And_OpenGLGuiHelper(CommonGraphicsApp* glApp, bool useOpenGL2, int swWidth, int swHeight, GLPrimitiveRenderer* primRenderer)
46 : OpenGLGuiHelper(glApp, useOpenGL2),
47 m_swWidth(swWidth),
48 m_swHeight(swHeight),
49 m_rgbColorBuffer(swWidth, swHeight, TGAImage::RGB),
50 m_primRenderer(primRenderer)
51 {
52 m_depthBuffer.resize(swWidth * swHeight);
53 CommonRenderInterface* render = getRenderInterface();
54 m_image = new unsigned char[m_swWidth * m_swHeight * 4];
55
56 m_textureHandle = render->registerTexture(m_image, m_swWidth, m_swHeight);
57 }
58
clearBuffers(TGAColor & clearColor)59 void clearBuffers(TGAColor& clearColor)
60 {
61 for (int y = 0; y < m_swHeight; ++y)
62 {
63 for (int x = 0; x < m_swWidth; ++x)
64 {
65 m_rgbColorBuffer.set(x, y, clearColor);
66 m_depthBuffer[x + y * m_swWidth] = -1e30f;
67 }
68 }
69 }
70
getFrameBuffer() const71 const TGAImage& getFrameBuffer() const
72 {
73 return m_rgbColorBuffer;
74 }
75
~SW_And_OpenGLGuiHelper()76 virtual ~SW_And_OpenGLGuiHelper()
77 {
78 for (int i = 0; i < m_swRenderObjects.size(); i++)
79 {
80 TinyRenderObjectData** d = m_swRenderObjects[i];
81 if (d && *d)
82 {
83 delete *d;
84 }
85 }
86 }
87
createCollisionObjectGraphicsObject(btCollisionObject * obj,const btVector3 & color)88 virtual void createCollisionObjectGraphicsObject(btCollisionObject* obj, const btVector3& color)
89 {
90 OpenGLGuiHelper::createCollisionObjectGraphicsObject(obj, color);
91 int colIndex = obj->getUserIndex();
92 int shapeIndex = obj->getCollisionShape()->getUserIndex();
93
94 if (colIndex >= 0 && shapeIndex >= 0)
95 {
96 m_swInstances.insert(colIndex, shapeIndex);
97 }
98 }
99
registerTexture(const unsigned char * texels,int width,int height)100 virtual int registerTexture(const unsigned char* texels, int width, int height)
101 {
102 return -1;
103 }
104
registerGraphicsShape(const float * vertices,int numvertices,const int * indices,int numIndices,int primitiveType,int textureId)105 virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices, int primitiveType, int textureId)
106 {
107 int shapeIndex = OpenGLGuiHelper::registerGraphicsShape(vertices, numvertices, indices, numIndices, primitiveType, textureId);
108 if (shapeIndex >= 0)
109 {
110 TinyRenderObjectData* swObj = new TinyRenderObjectData(m_rgbColorBuffer, m_depthBuffer);
111 float rgbaColor[4] = {1, 1, 1, 1};
112 swObj->registerMeshShape(vertices, numvertices, indices, numIndices, rgbaColor);
113 //swObj->createCube(1,1,1);//MeshShape(vertices,numvertices,indices,numIndices);
114 m_swRenderObjects.insert(shapeIndex, swObj);
115 }
116 return shapeIndex;
117 }
118
registerGraphicsInstance(int shapeIndex,const float * position,const float * quaternion,const float * color,const float * scaling)119 virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling)
120 {
121 int instanceId = OpenGLGuiHelper::registerGraphicsInstance(shapeIndex, position, quaternion, color, scaling);
122 return instanceId;
123 }
124
createCollisionShapeGraphicsObject(btCollisionShape * collisionShape)125 virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape)
126 {
127 OpenGLGuiHelper::createCollisionShapeGraphicsObject(collisionShape);
128 }
129
syncPhysicsToGraphics(const btDiscreteDynamicsWorld * rbWorld)130 virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld)
131 {
132 OpenGLGuiHelper::syncPhysicsToGraphics(rbWorld);
133 }
134
render(const btDiscreteDynamicsWorld * rbWorld)135 virtual void render(const btDiscreteDynamicsWorld* rbWorld)
136 {
137 OpenGLGuiHelper::render(rbWorld);
138
139 //clear the color buffer
140 TGAColor clearColor;
141 clearColor.bgra[0] = 255;
142 clearColor.bgra[1] = 255;
143 clearColor.bgra[2] = 255;
144 clearColor.bgra[3] = 255;
145
146 clearBuffers(clearColor);
147
148 ATTRIBUTE_ALIGNED16(btScalar modelMat[16]);
149 ATTRIBUTE_ALIGNED16(float viewMat[16]);
150 ATTRIBUTE_ALIGNED16(float projMat[16]);
151
152 CommonRenderInterface* render = getRenderInterface();
153
154 render->getActiveCamera()->getCameraProjectionMatrix(projMat);
155 render->getActiveCamera()->getCameraViewMatrix(viewMat);
156
157 btVector3 lightDirWorld(-5, 200, -40);
158 switch (1) //app->getUpAxis())
159 {
160 case 1:
161 lightDirWorld = btVector3(-50.f, 100, 30);
162 break;
163 case 2:
164 lightDirWorld = btVector3(-50.f, 30, 100);
165 break;
166 default:
167 {
168 }
169 };
170
171 lightDirWorld.normalize();
172
173 for (int i = 0; i < rbWorld->getNumCollisionObjects(); i++)
174 {
175 btCollisionObject* colObj = rbWorld->getCollisionObjectArray()[i];
176 int colObjIndex = colObj->getUserIndex();
177 int shapeIndex = colObj->getCollisionShape()->getUserIndex();
178 if (colObjIndex >= 0 && shapeIndex >= 0)
179 {
180 TinyRenderObjectData* renderObj = 0;
181
182 int* cptr = m_swInstances[colObjIndex];
183 if (cptr)
184 {
185 int c = *cptr;
186 TinyRenderObjectData** sptr = m_swRenderObjects[c];
187 if (sptr)
188 {
189 renderObj = *sptr;
190 //sync the object transform
191 const btTransform& tr = colObj->getWorldTransform();
192 tr.getOpenGLMatrix(modelMat);
193
194 for (int i = 0; i < 4; i++)
195 {
196 for (int j = 0; j < 4; j++)
197 {
198 renderObj->m_projectionMatrix[i][j] = projMat[i + 4 * j];
199 renderObj->m_modelMatrix[i][j] = modelMat[i + 4 * j];
200 renderObj->m_viewMatrix[i][j] = viewMat[i + 4 * j];
201 }
202 }
203 renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
204 renderObj->m_lightDirWorld = lightDirWorld;
205 renderObj->m_lightAmbientCoeff = 0.6;
206 renderObj->m_lightDiffuseCoeff = 0.35;
207 renderObj->m_lightSpecularCoeff = 0.05;
208 TinyRenderer::renderObject(*renderObj);
209 }
210 }
211 }
212 }
213
214 for (int y = 0; y < m_swHeight; ++y)
215 {
216 unsigned char* pi = m_image + (y)*m_swWidth * 3;
217 for (int x = 0; x < m_swWidth; ++x)
218 {
219 const TGAColor& color = getFrameBuffer().get(x, y);
220 pi[0] = color.bgra[2];
221 pi[1] = color.bgra[1];
222 pi[2] = color.bgra[0];
223 pi += 3;
224 }
225 }
226 render->activateTexture(m_textureHandle);
227 render->updateTexture(m_textureHandle, m_image);
228
229 static int counter = 0;
230 counter++;
231 if ((counter & 7) == 0)
232 {
233 char filename[1024];
234 sprintf(filename, "framebuf%d.tga", counter);
235 getFrameBuffer().write_tga_file(filename, true);
236 }
237 float color[4] = {1, 1, 1, 1};
238 m_primRenderer->drawTexturedRect(0, 0, m_swWidth, m_swHeight, color, 0, 0, 1, 1, true);
239 }
240
autogenerateGraphicsObjects(btDiscreteDynamicsWorld * rbWorld)241 virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld)
242 {
243 OpenGLGuiHelper::autogenerateGraphicsObjects(rbWorld);
244 }
245 };
246
main(int argc,char * argv[])247 int main(int argc, char* argv[])
248 {
249 SimpleOpenGL3App* app = new SimpleOpenGL3App("Standalone Example (Software Renderer, TinyRenderer)", 1024, 768, true);
250 int textureWidth = 640;
251 int textureHeight = 480;
252
253 SW_And_OpenGLGuiHelper gui(app, false, textureWidth, textureHeight, app->m_primRenderer);
254
255 CommonExampleOptions options(&gui);
256 CommonExampleInterface* example = StandaloneExampleCreateFunc(options);
257
258 example->initPhysics();
259 example->resetCamera();
260 do
261 {
262 app->m_instancingRenderer->init();
263 app->m_instancingRenderer->updateCamera(app->getUpAxis());
264
265 example->stepSimulation(1. / 60.);
266
267 example->renderScene();
268
269 DrawGridData dg;
270 dg.upAxis = app->getUpAxis();
271 app->drawGrid(dg);
272 app->swapBuffer();
273 } while (!app->m_window->requestedExit());
274
275 example->exitPhysics();
276 delete example;
277 delete app;
278 return 0;
279 }
280