#include "GpuConvexScene.h" #include "GpuRigidBodyDemo.h" #include "../OpenGLWindow/ShapeData.h" #include "../OpenGLWindow/GLInstancingRenderer.h" #include "Bullet3Common/b3Quaternion.h" #include "../CommonInterfaces/CommonWindowInterface.h" #include "Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h" #include "../CommonOpenCL/GpuDemoInternalData.h" #include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h" #include "../OpenGLWindow/OpenGLInclude.h" #include "../OpenGLWindow/GLInstanceRendererInternalData.h" #include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h" #include "Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h" #include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h" #include "Bullet3Collision/NarrowPhaseCollision/b3Config.h" #include "GpuRigidBodyDemoInternalData.h" #include "Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h" #include "../OpenGLWindow/GLPrimitiveRenderer.h" #include "Bullet3OpenCL/Raycast/b3GpuRaycast.h" #include "Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h" #include "Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h" #include "../OpenGLWindow/GLRenderToTexture.h" static bool gUseInstancedCollisionShapes = true; extern int gGpuArraySizeX; extern int gGpuArraySizeY; extern int gGpuArraySizeZ; #include "GpuRigidBodyDemo.h" #include "Bullet3Common/b3AlignedObjectArray.h" #include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h" class GpuConvexScene : public GpuRigidBodyDemo { protected: class b3GpuRaycast* m_raycaster; public: GpuConvexScene(GUIHelperInterface* helper) : GpuRigidBodyDemo(helper), m_raycaster(0) { } virtual ~GpuConvexScene() {} virtual const char* getName() { return "Tetrahedra"; } virtual void setupScene(); virtual void destroyScene(); virtual int createDynamicsObjects(); virtual int createDynamicsObjects2(const float* vertices, int numVertices, const int* indices, int numIndices); virtual void createStaticEnvironment(); }; class GpuConvexPlaneScene : public GpuConvexScene { public: GpuConvexPlaneScene(GUIHelperInterface* helper) : GpuConvexScene(helper) {} virtual ~GpuConvexPlaneScene() {} virtual const char* getName() { return "ConvexOnPlane"; } virtual void createStaticEnvironment(); }; class GpuBoxPlaneScene : public GpuConvexPlaneScene { public: GpuBoxPlaneScene(GUIHelperInterface* helper) : GpuConvexPlaneScene(helper) {} virtual ~GpuBoxPlaneScene() {} virtual const char* getName() { return "BoxBox"; } virtual int createDynamicsObjects(); }; class GpuTetraScene : public GpuConvexScene { protected: void createFromTetGenData(const char* ele, const char* node); public: virtual const char* getName() { return "TetraBreakable"; } virtual int createDynamicsObjects(); }; b3Vector4 colors[4] = { b3MakeVector4(1, 0, 0, 1), b3MakeVector4(0, 1, 0, 1), b3MakeVector4(0, 1, 1, 1), b3MakeVector4(1, 1, 0, 1), }; void GpuConvexScene::setupScene() { m_raycaster = new b3GpuRaycast(m_clData->m_clContext, m_clData->m_clDevice, m_clData->m_clQueue); int index = 0; createStaticEnvironment(); index += createDynamicsObjects(); m_data->m_rigidBodyPipeline->writeAllInstancesToGpu(); float camPos[4] = {0, 0, 0, 0}; //ci.arraySizeX,ci.arraySizeY/2,ci.arraySizeZ,0}; //float camPos[4]={1,12.5,1.5,0}; m_guiHelper->getRenderInterface()->getActiveCamera()->setCameraTargetPosition(camPos[0], camPos[1], camPos[2]); m_guiHelper->getRenderInterface()->getActiveCamera()->setCameraDistance(150); //m_instancingRenderer->setCameraYaw(85); m_guiHelper->getRenderInterface()->getActiveCamera()->setCameraYaw(225); m_guiHelper->getRenderInterface()->getActiveCamera()->setCameraPitch(-30); m_guiHelper->getRenderInterface()->updateCamera(1); //>updateCamera(); char msg[1024]; int numInstances = index; sprintf(msg, "Num objects = %d", numInstances); b3Printf(msg); //if (ci.m_gui) // ci.m_gui->setStatusBarMessage(msg,true); } void GpuConvexScene::destroyScene() { delete m_raycaster; m_raycaster = 0; } int GpuConvexScene::createDynamicsObjects() { int strideInBytes = 9 * sizeof(float); /*int numVertices = sizeof(barrel_vertices)/strideInBytes; int numIndices = sizeof(barrel_indices)/sizeof(int); return createDynamicsObjects2(ci,barrel_vertices,numVertices,barrel_indices,numIndices); */ int numVertices = sizeof(tetra_vertices) / strideInBytes; int numIndices = sizeof(tetra_indices) / sizeof(int); return createDynamicsObjects2(tetra_vertices, numVertices, tetra_indices, numIndices); } int GpuBoxPlaneScene::createDynamicsObjects() { int strideInBytes = 9 * sizeof(float); int numVertices = sizeof(cube_vertices) / strideInBytes; int numIndices = sizeof(cube_indices) / sizeof(int); return createDynamicsObjects2(cube_vertices_textured, numVertices, cube_indices, numIndices); } int GpuConvexScene::createDynamicsObjects2(const float* vertices, int numVertices, const int* indices, int numIndices) { int strideInBytes = 9 * sizeof(float); int textureIndex = -1; if (0) { int width, height, n; const char* filename = "data/cube.png"; const unsigned char* image = 0; const char* prefix[] = {"./", "../", "../../", "../../../", "../../../../"}; int numprefix = sizeof(prefix) / sizeof(const char*); for (int i = 0; !image && i < numprefix; i++) { char relativeFileName[1024]; sprintf(relativeFileName, "%s%s", prefix[i], filename); image = loadImage(relativeFileName, width, height, n); } b3Assert(image); if (image) { textureIndex = m_instancingRenderer->registerTexture(image, width, height); } } int shapeId = m_guiHelper->getRenderInterface()->registerShape(&vertices[0], numVertices, indices, numIndices, B3_GL_TRIANGLES, textureIndex); //int group=1; //int mask=1; int index = 0; { int curColor = 0; float scaling[4] = {1, 1, 1, 1}; int prevBody = -1; //int insta = 0; b3ConvexUtility* utilPtr = new b3ConvexUtility(); { b3AlignedObjectArray verts; unsigned char* vts = (unsigned char*)vertices; for (int i = 0; i < numVertices; i++) { float* vertex = (float*)&vts[i * strideInBytes]; verts.push_back(b3MakeVector3(vertex[0] * scaling[0], vertex[1] * scaling[1], vertex[2] * scaling[2])); } bool merge = true; if (numVertices) { utilPtr->initializePolyhedralFeatures(&verts[0], verts.size(), merge); } } int colIndex = -1; if (gUseInstancedCollisionShapes) colIndex = m_data->m_np->registerConvexHullShape(utilPtr); //int colIndex = m_data->m_np->registerSphereShape(1); for (int i = 0; i < gGpuArraySizeX; i++) { //printf("%d of %d\n", i, ci.arraySizeX); for (int j = 0; j < gGpuArraySizeY; j++) { for (int k = 0; k < gGpuArraySizeZ; k++) { //int colIndex = m_data->m_np->registerConvexHullShape(&vertices[0],strideInBytes,numVertices, scaling); if (!gUseInstancedCollisionShapes) colIndex = m_data->m_np->registerConvexHullShape(utilPtr); float mass = 1.f; if (j == 0) //ci.arraySizeY-1) { //mass=0.f; } b3Vector3 position = b3MakeVector3(((j + 1) & 1) + i * 2.2, 1 + j * 2., ((j + 1) & 1) + k * 2.2); //b3Vector3 position = b3MakeVector3(i*2,1+j*2,k*2); //b3Vector3 position=b3MakeVector3(1,0.9,1); b3Quaternion orn(0, 0, 0, 1); b3Vector4 color = colors[curColor]; curColor++; curColor &= 3; // b3Vector4 scaling=b3MakeVector4(1,1,1,1); int id; id = m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId, position, orn, color, scaling); int pid; pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass, position, orn, colIndex, index, false); if (prevBody >= 0) { //b3Point2PointConstraint* p2p = new b3Point2PointConstraint(pid,prevBody,b3Vector3(0,-1.1,0),b3Vector3(0,1.1,0)); // m_data->m_rigidBodyPipeline->addConstraint(p2p);//,false); } prevBody = pid; index++; } } } delete utilPtr; } return index; } void GpuConvexScene::createStaticEnvironment() { int strideInBytes = 9 * sizeof(float); int numVertices = sizeof(cube_vertices) / strideInBytes; int numIndices = sizeof(cube_indices) / sizeof(int); //int shapeId = ci.m_instancingRenderer->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices); int shapeId = m_instancingRenderer->registerShape(&cube_vertices[0], numVertices, cube_indices, numIndices); //int group=1; //int mask=1; int index = 0; { b3Vector4 scaling = b3MakeVector4(400, 400, 400, 1); int colIndex = m_data->m_np->registerConvexHullShape(&cube_vertices[0], strideInBytes, numVertices, scaling); b3Vector3 position = b3MakeVector3(0, -400, 0); b3Quaternion orn(0, 0, 0, 1); b3Vector4 color = b3MakeVector4(0, 0, 1, 1); int id; id = m_instancingRenderer->registerGraphicsInstance(shapeId, position, orn, color, scaling); int pid; pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f, position, orn, colIndex, index, false); } } void GpuConvexPlaneScene::createStaticEnvironment() { int strideInBytes = 9 * sizeof(float); int numVertices = sizeof(cube_vertices) / strideInBytes; int numIndices = sizeof(cube_indices) / sizeof(int); //int shapeId = ci.m_instancingRenderer->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices); int shapeId = m_guiHelper->getRenderInterface()->registerShape(&cube_vertices[0], numVertices, cube_indices, numIndices); // int group=1; // int mask=1; int index = 0; { b3Vector4 scaling = b3MakeVector4(400, 400, 400, 1); int colIndex = m_data->m_np->registerConvexHullShape(&cube_vertices[0], strideInBytes, numVertices, scaling); b3Vector3 position = b3MakeVector3(0, -400, 0); b3Quaternion orn(0, 0, 0, 1); b3Vector4 color = b3MakeVector4(0, 0, 1, 1); int id; id = m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId, position, orn, color, scaling); int pid; pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f, position, orn, colIndex, index, false); } } /* void GpuConvexPlaneScene::createStaticEnvironment(const ConstructionInfo& ci) { int strideInBytes = 9*sizeof(float); int numVertices = sizeof(cube_vertices)/strideInBytes; int numIndices = sizeof(cube_indices)/sizeof(int); //int shapeId = ci.m_instancingRenderer->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices); int shapeId = ci.m_instancingRenderer->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices); int group=1; int mask=1; int index=0; { b3Vector4 scaling=b3MakeVector4(100,0.001,100,1); //int colIndex = m_data->m_np->registerConvexHullShape(&cube_vertices[0],strideInBytes,numVertices, scaling); b3Vector3 normal=b3MakeVector3(0,1,0); float constant=0.f; int colIndex = m_data->m_np->registerPlaneShape(normal,constant);//>registerConvexHullShape(&cube_vertices[0],strideInBytes,numVertices, scaling); b3Vector3 position=b3MakeVector3(0,0,0); b3Quaternion orn(0,0,0,1); b3Vector4 color=b3MakeVector4(0,0,1,1); int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling); int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index,false); } } */ struct TetraBunny { #include "bunny.inl" }; struct TetraCube { #include "cube.inl" }; static int nextLine(const char* buffer) { int numBytesRead = 0; while (*buffer != '\n') { buffer++; numBytesRead++; } if (buffer[0] == 0x0a) { buffer++; numBytesRead++; } return numBytesRead; } static float mytetra_vertices[] = { -1.f, 0, -1.f, 0.5f, 0, 1, 0, 0, 0, -1.f, 0, 1.f, 0.5f, 0, 1, 0, 1, 0, 1.f, 0, 1.f, 0.5f, 0, 1, 0, 1, 1, 1.f, 0, -1.f, 0.5f, 0, 1, 0, 0, 1}; static int mytetra_indices[] = { 0, 1, 2, 3, 1, 2, 3, 2, 0, 3, 0, 1}; /* Create from TetGen .ele, .face, .node data */ void GpuTetraScene::createFromTetGenData(const char* ele, const char* node) { b3Scalar scaling(10); b3AlignedObjectArray pos; int nnode = 0; int ndims = 0; int nattrb = 0; int hasbounds = 0; int result = sscanf(node, "%d %d %d %d", &nnode, &ndims, &nattrb, &hasbounds); result = sscanf(node, "%d %d %d %d", &nnode, &ndims, &nattrb, &hasbounds); node += nextLine(node); //b3AlignedObjectArray rigidBodyPositions; //b3AlignedObjectArray rigidBodyIds; pos.resize(nnode); for (int i = 0; i < pos.size(); ++i) { int index = 0; //int bound=0; float x, y, z; sscanf(node, "%d %f %f %f", &index, &x, &y, &z); // sn>>index; // sn>>x;sn>>y;sn>>z; node += nextLine(node); //for(int j=0;j>a; //if(hasbounds) // sn>>bound; pos[index].setX(b3Scalar(x) * scaling); pos[index].setY(b3Scalar(y) * scaling); pos[index].setZ(b3Scalar(z) * scaling); } if (ele && ele[0]) { int ntetra = 0; int ncorner = 0; int neattrb = 0; sscanf(ele, "%d %d %d", &ntetra, &ncorner, &neattrb); ele += nextLine(ele); //se>>ntetra;se>>ncorner;se>>neattrb; for (int i = 0; i < ntetra; ++i) { int index = 0; int ni[4]; //se>>index; //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3]; sscanf(ele, "%d %d %d %d %d", &index, &ni[0], &ni[1], &ni[2], &ni[3]); ele += nextLine(ele); b3Vector3 average = b3MakeVector3(0, 0, 0); for (int v = 0; v < 4; v++) { average += pos[ni[v]]; } average /= 4; for (int v = 0; v < 4; v++) { b3Vector3 shiftedPos = pos[ni[v]] - average; mytetra_vertices[0 + v * 9] = shiftedPos.getX(); mytetra_vertices[1 + v * 9] = shiftedPos.getY(); mytetra_vertices[2 + v * 9] = shiftedPos.getZ(); } //todo: subtract average int strideInBytes = 9 * sizeof(float); int numVertices = sizeof(mytetra_vertices) / strideInBytes; int numIndices = sizeof(mytetra_indices) / sizeof(int); int shapeId = m_instancingRenderer->registerShape(&mytetra_vertices[0], numVertices, mytetra_indices, numIndices); // int group=1; // int mask=1; { b3Vector4 scaling = b3MakeVector4(1, 1, 1, 1); int colIndex = m_data->m_np->registerConvexHullShape(&mytetra_vertices[0], strideInBytes, numVertices, scaling); b3Vector3 position = b3MakeVector3(0, 150, 0); // position+=average;//*1.2;//*2; position += average * 1.2; //*2; //rigidBodyPositions.push_back(position); b3Quaternion orn(0, 0, 0, 1); static int curColor = 0; b3Vector4 color = colors[curColor++]; curColor &= 3; int id; id = m_instancingRenderer->registerGraphicsInstance(shapeId, position, orn, color, scaling); int pid; pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(1.f, position, orn, colIndex, 0, false); //rigidBodyIds.push_back(pid); } //for(int j=0;j>a; //psb->appendTetra(ni[0],ni[1],ni[2],ni[3]); } // printf("Nodes: %u\r\n",psb->m_nodes.size()); // printf("Links: %u\r\n",psb->m_links.size()); // printf("Faces: %u\r\n",psb->m_faces.size()); // printf("Tetras: %u\r\n",psb->m_tetras.size()); } m_data->m_rigidBodyPipeline->writeAllInstancesToGpu(); m_data->m_np->writeAllBodiesToGpu(); m_data->m_bp->writeAabbsToGpu(); m_data->m_rigidBodyPipeline->setupGpuAabbsFull(); m_data->m_bp->calculateOverlappingPairs(m_data->m_config.m_maxBroadphasePairs); int numPairs = m_data->m_bp->getNumOverlap(); cl_mem pairs = m_data->m_bp->getOverlappingPairBuffer(); b3OpenCLArray clPairs(m_clData->m_clContext, m_clData->m_clQueue); clPairs.setFromOpenCLBuffer(pairs, numPairs); b3AlignedObjectArray allPairs; clPairs.copyToHost(allPairs); for (int p = 0; p < allPairs.size(); p++) { b3Vector3 posA, posB; b3Quaternion ornA, ornB; int bodyIndexA = allPairs[p].x; int bodyIndexB = allPairs[p].y; m_data->m_np->getObjectTransformFromCpu(posA, ornA, bodyIndexA); m_data->m_np->getObjectTransformFromCpu(posB, ornB, bodyIndexB); b3Vector3 pivotWorld = (posA + posB) * 0.5f; b3Transform transA, transB; transA.setIdentity(); transA.setOrigin(posA); transA.setRotation(ornA); transB.setIdentity(); transB.setOrigin(posB); transB.setRotation(ornB); b3Vector3 pivotInA = transA.inverse() * pivotWorld; b3Vector3 pivotInB = transB.inverse() * pivotWorld; b3Transform frameInA, frameInB; frameInA.setIdentity(); frameInB.setIdentity(); frameInA.setOrigin(pivotInA); frameInB.setOrigin(pivotInB); b3Quaternion relTargetAB = frameInA.getRotation() * frameInB.getRotation().inverse(); //c = new b3FixedConstraint(pid,prevBody,frameInA,frameInB); float breakingThreshold = 45; //37.f; //c->setBreakingImpulseThreshold(37.1); bool useGPU = true; if (useGPU) { int cid; cid = m_data->m_rigidBodyPipeline->createFixedConstraint(bodyIndexA, bodyIndexB, pivotInA, pivotInB, relTargetAB, breakingThreshold); } else { b3FixedConstraint* c = new b3FixedConstraint(bodyIndexA, bodyIndexB, frameInA, frameInB); c->setBreakingImpulseThreshold(breakingThreshold); m_data->m_rigidBodyPipeline->addConstraint(c); } } printf("numPairs = %d\n", numPairs); } int GpuTetraScene::createDynamicsObjects() { //createFromTetGenData(TetraCube::getElements(),TetraCube::getNodes()); createFromTetGenData(TetraBunny::getElements(), TetraBunny::getNodes()); return 0; } class CommonExampleInterface* OpenCLBoxBoxCreateFunc(struct CommonExampleOptions& options) { return new GpuBoxPlaneScene(options.m_guiHelper); }