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