Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / OpenCLClothDemo / cl_cloth_demo.cpp
1 /*\r
2 Bullet Continuous Collision Detection and Physics Library\r
3 Copyright (c) 2008 Advanced Micro Devices\r
4 \r
5 This software is provided 'as-is', without any express or implied warranty.\r
6 In no event will the authors be held liable for any damages arising from the use of this software.\r
7 Permission is granted to anyone to use this software for any purpose, \r
8 including commercial applications, and to alter it and redistribute it freely, \r
9 subject to the following restrictions:\r
10 \r
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.\r
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\r
13 3. This notice may not be removed or altered from any source distribution.\r
14 */\r
15 \r
16 #ifdef _WIN32\r
17 #include <GL/glew.h>\r
18 #endif\r
19 \r
20 \r
21 \r
22 #ifndef USE_MINICL\r
23 #define USE_SIMDAWARE_SOLVER\r
24 #endif\r
25 \r
26 #if !defined (__APPLE__)\r
27 #define USE_GPU_SOLVER\r
28 #if defined (_WIN32)  &&  !defined(USE_MINICL)\r
29         #define USE_GPU_COPY //only tested on Windows\r
30 #endif //_WIN32 && !USE_MINICL\r
31 #endif //!__APPLE__ \r
32 \r
33 \r
34 \r
35 \r
36 \r
37 #include "clstuff.h"\r
38 #include "gl_win.h"\r
39 #include "cloth.h"\r
40 \r
41 #include "../OpenGL/GLDebugDrawer.h"\r
42 \r
43 GLDebugDrawer debugDraw;\r
44 \r
45 const int numFlags = 5;\r
46 const int clothWidth = 40;\r
47 const int clothHeight = 60;//60;\r
48 float _windAngle = 1.0;//0.4;\r
49 float _windStrength = 0.;\r
50 \r
51 \r
52 \r
53 #include "btBulletDynamicsCommon.h"\r
54 #include "LinearMath/btHashMap.h"\r
55 #include "BulletSoftBody/btSoftRigidDynamicsWorld.h"\r
56 #include "vectormath/vmInclude.h"\r
57 #include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h"\r
58 #include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h"\r
59 #include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h"\r
60 #include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h"\r
61 \r
62 \r
63 btRigidBody *capCollider;\r
64 \r
65 \r
66 using Vectormath::Aos::Vector3;\r
67 \r
68 class piece_of_cloth;\r
69 class btBroadphaseInterface;\r
70 class btCollisionShape;\r
71 class btOverlappingPairCache;\r
72 class btCollisionDispatcher;\r
73 class btConstraintSolver;\r
74 struct btCollisionAlgorithmCreateFunc;\r
75 class btDefaultCollisionConfiguration;\r
76 \r
77 #include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"\r
78 \r
79 namespace Vectormath\r
80 {\r
81         namespace Aos\r
82         {\r
83                 class Transform3;\r
84         }\r
85 }\r
86 \r
87 \r
88 btAlignedObjectArray<btCollisionShape*> m_collisionShapes;\r
89 btBroadphaseInterface*  m_broadphase;\r
90 btCollisionDispatcher*  m_dispatcher;\r
91 btConstraintSolver*     m_solver;\r
92 btDefaultCollisionConfiguration* m_collisionConfiguration;\r
93 \r
94 btOpenCLSoftBodySolver *g_openCLSolver = NULL;\r
95 btOpenCLSoftBodySolverSIMDAware *g_openCLSIMDSolver = NULL;\r
96 \r
97 btSoftBodySolver *g_solver = NULL;\r
98 \r
99 btSoftBodySolverOutput *g_softBodyOutput = NULL;\r
100 \r
101 btAlignedObjectArray<btSoftBody *> m_flags;\r
102 btSoftRigidDynamicsWorld* m_dynamicsWorld;\r
103 btAlignedObjectArray<piece_of_cloth> cloths;\r
104 \r
105 extern cl_context                       g_cxMainContext;\r
106 extern cl_device_id                     g_cdDevice;\r
107 extern cl_command_queue         g_cqCommandQue;\r
108 \r
109 \r
110 const float flagSpacing = 30.f;\r
111 \r
112 \r
113 // Helper to test and add links correctly.\r
114 // Records links that have already been generated\r
115 static bool testAndAddLink( btAlignedObjectArray<int> &trianglesForLinks, btSoftBody *softBody, int triangle, int *triangleVertexIndexArray, int numVertices, int vertex0, int vertex1, int nonLinkVertex, btSoftBody::Material *structuralMaterial, bool createBendLinks, btSoftBody::Material *bendMaterial )\r
116 {               \r
117         if( trianglesForLinks[ numVertices * vertex0 + vertex1 ] >= 0 && createBendLinks)\r
118         {\r
119                 // Already have link so find other triangle and generate cross link\r
120 \r
121                 int otherTriangle = trianglesForLinks[numVertices * vertex0 + vertex1];\r
122                 int otherIndices[3] = {triangleVertexIndexArray[otherTriangle * 3], triangleVertexIndexArray[otherTriangle * 3 + 1], triangleVertexIndexArray[otherTriangle * 3 + 2]};\r
123 \r
124                 int nodeA;\r
125                 // Test all links of the other triangle against this link. The one that's not part of it is what we want.\r
126                 if( otherIndices[0] != vertex0 && otherIndices[0] != vertex1 )\r
127                         nodeA = otherIndices[0];\r
128                 if( otherIndices[1] != vertex0 && otherIndices[1] != vertex1 )\r
129                         nodeA = otherIndices[1];\r
130                 if( otherIndices[2] != vertex0 && otherIndices[2] != vertex1 )\r
131                         nodeA = otherIndices[2];\r
132 \r
133                 softBody->appendLink( nodeA, nonLinkVertex, bendMaterial );\r
134         } else {\r
135                 // Don't yet have link so create it\r
136                 softBody->appendLink( vertex0, vertex1, structuralMaterial );\r
137 \r
138                 // If we added a new link, set the triangle array\r
139                 trianglesForLinks[numVertices * vertex0 + vertex1] = triangle;\r
140                 trianglesForLinks[numVertices * vertex1 + vertex0] = triangle;\r
141 \r
142         }\r
143 \r
144         return true;\r
145 }\r
146 \r
147 btSoftBody *createFromIndexedMesh( btVector3 *vertexArray, int numVertices, int *triangleVertexIndexArray, int numTriangles, bool createBendLinks )\r
148 {\r
149         btSoftBody* softBody = new btSoftBody(&(m_dynamicsWorld->getWorldInfo()), numVertices, vertexArray, 0);\r
150         btSoftBody::Material * structuralMaterial = softBody->appendMaterial();\r
151         btSoftBody::Material * bendMaterial;\r
152         if( createBendLinks )\r
153         {\r
154                 bendMaterial = softBody->appendMaterial();\r
155                 bendMaterial->m_kLST = 0.7;\r
156         } else {\r
157                 bendMaterial = NULL;\r
158         }\r
159         structuralMaterial->m_kLST = 1.0;\r
160         \r
161 \r
162         // List of values for each link saying which triangle is associated with that link\r
163         // -1 to start. Once a value is entered we know the "other" triangle\r
164         // and can add a link across the link\r
165         btAlignedObjectArray<int> triangleForLinks;\r
166         triangleForLinks.resize( numVertices * numVertices, -1 );\r
167 //      int numLinks = 0;\r
168         for( int triangle = 0; triangle < numTriangles; ++triangle )\r
169         {\r
170                 int index[3] = {triangleVertexIndexArray[triangle * 3], triangleVertexIndexArray[triangle * 3 + 1], triangleVertexIndexArray[triangle * 3 + 2]};\r
171                 softBody->appendFace( index[0], index[1], index[2] );\r
172                 \r
173                 // Generate the structural links directly from the triangles\r
174                 testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[0], index[1], index[2], structuralMaterial, createBendLinks, bendMaterial );\r
175                 testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[1], index[2], index[0], structuralMaterial, createBendLinks, bendMaterial );\r
176                 testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[2], index[0], index[1], structuralMaterial, createBendLinks, bendMaterial);\r
177         }\r
178 \r
179         return softBody;\r
180 }\r
181 \r
182 /**\r
183  * Create a sequence of flag objects and add them to the world.\r
184  */\r
185 void createFlag( btSoftBodySolver &solver, int width, int height, btAlignedObjectArray<btSoftBody *> &flags )\r
186 {\r
187         // First create a triangle mesh to represent a flag\r
188 \r
189         using Vectormath::Aos::Matrix3;\r
190         using Vectormath::Aos::Vector3;\r
191 \r
192         // Allocate a simple mesh consisting of a vertex array and a triangle index array\r
193         btIndexedMesh mesh;\r
194         mesh.m_numVertices = width*height;\r
195         mesh.m_numTriangles = 2*(width-1)*(height-1);\r
196 \r
197         btVector3 *vertexArray = new btVector3[mesh.m_numVertices];\r
198 \r
199         mesh.m_vertexBase = reinterpret_cast<const unsigned char*>(vertexArray);\r
200         int *triangleVertexIndexArray = new int[3*mesh.m_numTriangles]; \r
201         mesh.m_triangleIndexBase = reinterpret_cast<const unsigned char*>(triangleVertexIndexArray);\r
202         mesh.m_triangleIndexStride = sizeof(int)*3;\r
203         mesh.m_vertexStride = sizeof(Vector3);\r
204 \r
205         // Generate normalised object space vertex coordinates for a rectangular flag\r
206         float zCoordinate = 0.0f;\r
207         \r
208         Matrix3 defaultScale(Vector3(5.f, 0.f, 0.f), Vector3(0.f, 20.f, 0.f), Vector3(0.f, 0.f, 1.f));\r
209         for( int y = 0; y < height; ++y )\r
210         {\r
211                 float yCoordinate = y*2.0f/float(height) - 1.0f;\r
212                 for( int x = 0; x < width; ++x )\r
213                 {                       \r
214                         float xCoordinate = x*2.0f/float(width) - 1.0f;\r
215 \r
216                         Vector3 vertex(xCoordinate, yCoordinate, zCoordinate);\r
217                         Vector3 transformedVertex = defaultScale*vertex;\r
218 \r
219                         vertexArray[y*width + x] = btVector3(transformedVertex.getX(), transformedVertex.getY(), transformedVertex.getZ() );\r
220 \r
221                 }\r
222         }\r
223 \r
224         // Generate vertex indices for triangles\r
225         for( int y = 0; y < (height-1); ++y )\r
226         {\r
227                 for( int x = 0; x < (width-1); ++x )\r
228                 {       \r
229                         // Triangle 0\r
230                         // Top left of square on mesh\r
231                         {\r
232                                 int vertex0 = y*width + x;\r
233                                 int vertex1 = vertex0 + 1;\r
234                                 int vertex2 = vertex0 + width;\r
235                                 int triangleIndex = 2*y*(width-1) + 2*x;\r
236                                 triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)] = vertex0;\r
237                                 triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex+1)/sizeof(int)+1] = vertex1;\r
238                                 triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex+2)/sizeof(int)+2] = vertex2;\r
239                         }\r
240 \r
241                         // Triangle 1\r
242                         // Bottom right of square on mesh\r
243                         {\r
244                                 int vertex0 = y*width + x + 1;\r
245                                 int vertex1 = vertex0 + width;\r
246                                 int vertex2 = vertex1 - 1;\r
247                                 int triangleIndex = 2*y*(width-1) + 2*x + 1;\r
248                                 triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)] = vertex0;\r
249                                 triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)+1] = vertex1;\r
250                                 triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)+2] = vertex2;\r
251                         }\r
252                 }\r
253         }\r
254 \r
255         \r
256         float rotateAngleRoundZ = 0.0;\r
257         float rotateAngleRoundX = 0.5;\r
258         btMatrix3x3 defaultRotate;\r
259         defaultRotate[0] = btVector3(cos(rotateAngleRoundZ), sin(rotateAngleRoundZ), 0.f); \r
260         defaultRotate[1] = btVector3(-sin(rotateAngleRoundZ), cos(rotateAngleRoundZ), 0.f);\r
261         defaultRotate[2] = btVector3(0.f, 0.f, 1.f);\r
262         btMatrix3x3 defaultRotateX;\r
263         defaultRotateX[0] = btVector3(1.f, 0.f, 0.f);\r
264         defaultRotateX[1] = btVector3( 0.f, cos(rotateAngleRoundX), sin(rotateAngleRoundX));\r
265         defaultRotateX[2] = btVector3(0.f, -sin(rotateAngleRoundX), cos(rotateAngleRoundX));\r
266 \r
267         btMatrix3x3 defaultRotateAndScale( (defaultRotateX*defaultRotate) );\r
268 \r
269 \r
270         // Construct the sequence flags applying a slightly different translation to each one to arrange them\r
271         // appropriately in the scene.\r
272         for( int i = 0; i < numFlags; ++i )\r
273         {\r
274                 float zTranslate = flagSpacing * (i-numFlags/2);\r
275 \r
276                 btVector3 defaultTranslate(0.f, 20.f, zTranslate);\r
277 \r
278                 btTransform transform( defaultRotateAndScale, defaultTranslate );\r
279                 transform.setOrigin(defaultTranslate);\r
280 \r
281 \r
282                 btSoftBody *softBody = createFromIndexedMesh( vertexArray, mesh.m_numVertices, triangleVertexIndexArray, mesh.m_numTriangles, true );\r
283 \r
284 \r
285                 for( int i = 0; i < mesh.m_numVertices; ++i )\r
286                 {\r
287                         softBody->setMass(i, 10.f/mesh.m_numVertices);\r
288                 }\r
289                 softBody->setMass((height-1)*(width), 0.f);\r
290                 softBody->setMass((height-1)*(width) + width - 1, 0.f);\r
291                 softBody->setMass((height-1)*width + width/2, 0.f);\r
292                 softBody->m_cfg.collisions = btSoftBody::fCollision::CL_SS+btSoftBody::fCollision::CL_RS;       \r
293                 \r
294                 softBody->m_cfg.kLF = 0.0005f;\r
295                 softBody->m_cfg.kVCF = 0.001f;\r
296                 softBody->m_cfg.kDP = 0.f;\r
297                 softBody->m_cfg.kDG = 0.f;\r
298 \r
299                 \r
300                 flags.push_back( softBody );\r
301 \r
302                 softBody->transform( transform );\r
303                 \r
304                 m_dynamicsWorld->addSoftBody( softBody );\r
305         }\r
306 \r
307         delete [] vertexArray;\r
308         delete [] triangleVertexIndexArray;\r
309 }\r
310 \r
311 \r
312 void updatePhysicsWorld()\r
313 {\r
314         static int counter = 1;\r
315 \r
316         // Change wind velocity a bit based on a frame counter\r
317         if( (counter % 400) == 0 )\r
318         {\r
319                 _windAngle = (_windAngle + 0.05f);\r
320                 if( _windAngle > (2*3.141) )\r
321                         _windAngle = 0;\r
322 \r
323                 for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex )\r
324                 {               \r
325                         btSoftBody *cloth = 0;\r
326 \r
327                         cloth = m_flags[flagIndex];\r
328 \r
329                         float localWind = _windAngle + 0.5*(((float(rand())/RAND_MAX))-0.1);\r
330                         float xCoordinate = cos(localWind)*_windStrength;\r
331                         float zCoordinate = sin(localWind)*_windStrength;\r
332 \r
333                         cloth->setWindVelocity( btVector3(xCoordinate, 0, zCoordinate) );\r
334                 }\r
335         }\r
336 \r
337         //btVector3 origin( capCollider->getWorldTransform().getOrigin() );\r
338         //origin.setX( origin.getX() + 0.05 );\r
339         //capCollider->getWorldTransform().setOrigin( origin );\r
340         \r
341         counter++;\r
342 }\r
343 \r
344 void initBullet(void)\r
345 {\r
346 \r
347 #ifdef USE_GPU_SOLVER\r
348 #ifdef USE_SIMDAWARE_SOLVER\r
349         g_openCLSIMDSolver = new btOpenCLSoftBodySolverSIMDAware( g_cqCommandQue, g_cxMainContext);\r
350         g_solver = g_openCLSIMDSolver;\r
351 #ifdef USE_GPU_COPY\r
352         g_softBodyOutput = new btSoftBodySolverOutputCLtoGL(g_cqCommandQue, g_cxMainContext);\r
353 #else // #ifdef USE_GPU_COPY\r
354         g_softBodyOutput = new btSoftBodySolverOutputCLtoCPU;\r
355 #endif // #ifdef USE_GPU_COPY\r
356 #else\r
357         g_openCLSolver = new btOpenCLSoftBodySolver( g_cqCommandQue, g_cxMainContext );\r
358         g_solver = g_openCLSolver;\r
359 #ifdef USE_GPU_COPY\r
360         g_softBodyOutput = new btSoftBodySolverOutputCLtoGL(g_cqCommandQue, g_cxMainContext);\r
361 #else // #ifdef USE_GPU_COPY\r
362         g_softBodyOutput = new btSoftBodySolverOutputCLtoCPU;\r
363 #endif // #ifdef USE_GPU_COPY\r
364 #endif\r
365 #else\r
366         g_openCLSolver = new btOpenCLSoftBodySolver( g_cqCommandQue, g_cxMainContext );\r
367         g_solver = g_openCLSolver;\r
368 #endif\r
369 \r
370         //m_collisionConfiguration = new btDefaultCollisionConfiguration();\r
371         m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();\r
372         \r
373 \r
374         m_dispatcher = new      btCollisionDispatcher(m_collisionConfiguration);\r
375         m_broadphase = new btDbvtBroadphase();\r
376         btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;\r
377         m_solver = sol;\r
378 \r
379         m_dynamicsWorld = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration, g_solver);       \r
380 \r
381         m_dynamicsWorld->setGravity(btVector3(0,-10,0));        \r
382         btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));   \r
383         m_collisionShapes.push_back(groundShape);\r
384         btTransform groundTransform;\r
385         groundTransform.setIdentity();\r
386         groundTransform.setOrigin(btVector3(0,-50,0));\r
387 \r
388         \r
389 \r
390 \r
391 \r
392 \r
393         m_dynamicsWorld->getWorldInfo().air_density                     =       (btScalar)1.2;\r
394         m_dynamicsWorld->getWorldInfo().water_density           =       0;\r
395         m_dynamicsWorld->getWorldInfo().water_offset            =       0;\r
396         m_dynamicsWorld->getWorldInfo().water_normal            =       btVector3(0,0,0);\r
397         m_dynamicsWorld->getWorldInfo().m_gravity.setValue(0,-10,0);\r
398 \r
399 \r
400 \r
401 #if 0\r
402         {\r
403                 btScalar mass(0.);\r
404 \r
405                 //rigidbody is dynamic if and only if mass is non zero, otherwise static\r
406                 bool isDynamic = (mass != 0.f);\r
407 \r
408                 btVector3 localInertia(0,0,0);\r
409                 if (isDynamic)\r
410                         groundShape->calculateLocalInertia(mass,localInertia);\r
411 \r
412                 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects\r
413                 btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);\r
414                 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);\r
415                 btRigidBody* body = new btRigidBody(rbInfo);\r
416 \r
417                 //add the body to the dynamics world\r
418                 m_dynamicsWorld->addRigidBody(body);\r
419         }\r
420  \r
421 #endif\r
422 \r
423         #if 1\r
424         {               \r
425                 btScalar mass(0.);\r
426 \r
427                 //btScalar mass(1.);\r
428 \r
429                 //rigidbody is dynamic if and only if mass is non zero, otherwise static\r
430                 bool isDynamic = (mass != 0.f);\r
431                 \r
432                 btCollisionShape *capsuleShape = new btCapsuleShape(5, 10);\r
433                 capsuleShape->setMargin( 0.5 );\r
434                 \r
435                 \r
436 \r
437 \r
438                 btVector3 localInertia(0,0,0);\r
439                 if (isDynamic)\r
440                         capsuleShape->calculateLocalInertia(mass,localInertia);\r
441 \r
442                 m_collisionShapes.push_back(capsuleShape);\r
443                 btTransform capsuleTransform;\r
444                 capsuleTransform.setIdentity();\r
445 #ifdef TABLETEST\r
446                 capsuleTransform.setOrigin(btVector3(0, 10, -11));\r
447                 const btScalar pi = 3.141592654;\r
448                 capsuleTransform.setRotation(btQuaternion(0, 0, pi/2));\r
449 #else\r
450                 capsuleTransform.setOrigin(btVector3(0, 0, 0));\r
451                 \r
452         //      const btScalar pi = 3.141592654;\r
453                 //capsuleTransform.setRotation(btQuaternion(0, 0, pi/2));\r
454                 capsuleTransform.setRotation(btQuaternion(0, 0, 0));\r
455 #endif\r
456                 btDefaultMotionState* myMotionState = new btDefaultMotionState(capsuleTransform);\r
457                 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,capsuleShape,localInertia);\r
458                 btRigidBody* body = new btRigidBody(rbInfo);\r
459                 body->setFriction( 0.8f );\r
460 \r
461                 m_dynamicsWorld->addRigidBody(body);\r
462                 //cap_1.collisionShape = body;\r
463                 capCollider = body;\r
464         }\r
465 #endif\r
466 \r
467 \r
468 //#ifdef USE_GPU_SOLVER\r
469         createFlag( *g_openCLSolver, clothWidth, clothHeight, m_flags );\r
470 //#else\r
471         \r
472 //#endif\r
473 \r
474         // Create output buffer descriptions for ecah flag\r
475         // These describe where the simulation should send output data to\r
476         for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex )\r
477         {               \r
478 //              m_flags[flagIndex]->setWindVelocity( Vectormath::Aos::Vector3( 0.f, 0.f, 15.f ) );\r
479                 \r
480                 // In this case we have a DX11 output buffer with a vertex at index 0, 8, 16 and so on as well as a normal at 3, 11, 19 etc.\r
481                 // Copies will be performed GPU-side directly into the output buffer\r
482 \r
483 #ifdef USE_GPU_COPY\r
484                 GLuint targetVBO = cloths[flagIndex].getVBO();\r
485                 btOpenGLInteropVertexBufferDescriptor *vertexBufferDescriptor = new btOpenGLInteropVertexBufferDescriptor(g_cqCommandQue, g_cxMainContext, targetVBO, 0, 8, 3, 8);\r
486 #else\r
487                 btCPUVertexBufferDescriptor *vertexBufferDescriptor = new btCPUVertexBufferDescriptor(reinterpret_cast< float* >(cloths[flagIndex].cpu_buffer), 0, 8, 3, 8);\r
488 #endif\r
489                 cloths[flagIndex].m_vertexBufferDescriptor = vertexBufferDescriptor;\r
490         }\r
491 \r
492 \r
493         g_solver->optimize( m_dynamicsWorld->getSoftBodyArray() );\r
494         \r
495         if (!g_solver->checkInitialized())\r
496         {\r
497                 printf("OpenCL kernel initialization ?failed\n");\r
498                 btAssert(0);\r
499                 exit(0);\r
500         }\r
501 \r
502 }\r
503 \r
504 \r
505 \r
506 \r
507 btClock m_clock;\r
508 \r
509 void doFlags()\r
510 {\r
511         //float ms = getDeltaTimeMicroseconds();\r
512         btScalar dt = (btScalar)m_clock.getTimeMicroseconds();\r
513         m_clock.reset();\r
514 \r
515         ///step the simulation\r
516         if( m_dynamicsWorld )\r
517         {\r
518                 m_dynamicsWorld->stepSimulation(dt/1000000.);\r
519 \r
520                 static int frameCount = 0;\r
521                 frameCount++;\r
522                 if (frameCount==100)\r
523                 {\r
524                         m_dynamicsWorld->stepSimulation(1./60.,0);\r
525                         \r
526                 // Option to save a .bullet file\r
527                 //      btDefaultSerializer*    serializer = new btDefaultSerializer();\r
528                 //      m_dynamicsWorld->serialize(serializer);\r
529                 //      FILE* file = fopen("testFile.bullet","wb");\r
530                 //      fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1, file);\r
531                 //      fclose(file);\r
532 \r
533                         CProfileManager::dumpAll();\r
534                 }\r
535                 updatePhysicsWorld();\r
536 \r
537                 //m_dynamicsWorld->setDebugDrawer(&debugDraw);\r
538                 //debugDraw.setDebugMode(btIDebugDraw::DBG_DrawWireframe);\r
539                 //g_solver->copyBackToSoftBodies();\r
540 \r
541                 m_dynamicsWorld->debugDrawWorld();\r
542                 \r
543         }\r
544         \r
545 \r
546         for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex )\r
547         {\r
548         if (g_softBodyOutput)\r
549             g_softBodyOutput->copySoftBodyToVertexBuffer( m_flags[flagIndex], cloths[flagIndex].m_vertexBufferDescriptor );\r
550                 cloths[flagIndex].draw();\r
551         }\r
552 }\r
553 \r
554 \r
555 int main(int argc, char *argv[])\r
556 {\r
557 \r
558         \r
559         preInitGL(argc, argv);\r
560 #ifdef _WIN32\r
561         glewInit();\r
562 #endif\r
563 \r
564 #ifdef USE_GPU_COPY\r
565 #ifdef _WIN32\r
566     HGLRC glCtx = wglGetCurrentContext();\r
567 #else //!_WIN32\r
568     GLXContext glCtx = glXGetCurrentContext();\r
569 #endif //!_WIN32\r
570         HDC glDC = wglGetCurrentDC();\r
571         \r
572         initCL(glCtx, glDC);\r
573 #else\r
574 \r
575         initCL();\r
576 \r
577 #endif\r
578 \r
579         cloths.resize(numFlags);\r
580 \r
581         for( int flagIndex =  0; flagIndex < numFlags; ++flagIndex )\r
582         {\r
583                 cloths[flagIndex].create_buffers(clothWidth, clothHeight);\r
584         }\r
585 \r
586         initBullet();\r
587         m_dynamicsWorld->stepSimulation(1./60.,0);\r
588 \r
589         std::string flagTexs[] = {\r
590                 "bullet_logo.png",\r
591                 "bullet_logo.png",\r
592         };\r
593         int numFlagTexs = 2;\r
594 \r
595         for( int flagIndex =  0; flagIndex < numFlags; ++flagIndex )\r
596         {\r
597                 cloths[flagIndex].create_texture(flagTexs[flagIndex % numFlagTexs]);\r
598                 cloths[flagIndex].x_offset = 0; \r
599                 cloths[flagIndex].y_offset = 0; \r
600                 cloths[flagIndex].z_offset = 0;\r
601         }\r
602 \r
603         goGL();\r
604 \r
605         if( g_openCLSolver  )\r
606                 delete g_openCLSolver;\r
607         if( g_openCLSIMDSolver  )\r
608                 delete g_openCLSIMDSolver;\r
609         if( g_softBodyOutput )\r
610                 delete g_softBodyOutput;\r
611 \r
612         return 0;\r
613 }\r
614 \r