//---------------------------------------------------------- void ofGLRenderer::draw(ofMesh & vertexData, ofPolyRenderMode renderType, bool useColors, bool useTextures, bool useNormals){ if (bSmoothHinted) startSmoothing(); #ifndef TARGET_OPENGLES glPushAttrib(GL_POLYGON_BIT); glPolygonMode(GL_FRONT_AND_BACK, ofGetGLPolyMode(renderType)); draw(vertexData,useColors,useTextures,useNormals); glPopAttrib(); //TODO: GLES doesnt support polygon mode, add renderType to gl renderer? #else if(vertexData.getNumVertices()){ glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, sizeof(ofVec3f), vertexData.getVerticesPointer()); } if(vertexData.getNumNormals() && useNormals){ glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, 0, vertexData.getNormalsPointer()); } if(vertexData.getNumColors() && useColors){ glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4,GL_FLOAT, sizeof(ofFloatColor), vertexData.getColorsPointer()); } if(vertexData.getNumTexCoords() && useTextures){ glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, vertexData.getTexCoordsPointer()); } GLenum drawMode; switch(renderType){ case OF_MESH_POINTS: drawMode = GL_POINTS; break; case OF_MESH_WIREFRAME: drawMode = GL_LINES; break; case OF_MESH_FILL: drawMode = ofGetGLPrimitiveMode(vertexData.getMode()); break; default: drawMode = ofGetGLPrimitiveMode(vertexData.getMode()); break; } if(vertexData.getNumIndices()){ glDrawElements(drawMode, vertexData.getNumIndices(),GL_UNSIGNED_SHORT,vertexData.getIndexPointer()); }else{ glDrawArrays(drawMode, 0, vertexData.getNumVertices()); } if(vertexData.getNumColors() && useColors){ glDisableClientState(GL_COLOR_ARRAY); } if(vertexData.getNumNormals() && useNormals){ glDisableClientState(GL_NORMAL_ARRAY); } if(vertexData.getNumTexCoords() && useTextures){ glDisableClientState(GL_TEXTURE_COORD_ARRAY); } #endif if (bSmoothHinted) endSmoothing(); }
//---------------------------------------------------------- void ofGLRenderer::draw(const ofMesh & vertexData, bool useColors, bool useTextures, bool useNormals) const{ if(vertexData.getNumVertices()){ glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, sizeof(ofVec3f), &vertexData.getVerticesPointer()->x); } if(vertexData.getNumNormals() && useNormals){ glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, sizeof(ofVec3f), &vertexData.getNormalsPointer()->x); } if(vertexData.getNumColors() && useColors){ glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4,GL_FLOAT, sizeof(ofFloatColor), &vertexData.getColorsPointer()->r); } if(vertexData.getNumTexCoords() && useTextures){ set<int>::iterator textureLocation = textureLocationsEnabled.begin(); for(;textureLocation!=textureLocationsEnabled.end();textureLocation++){ glActiveTexture(GL_TEXTURE0+*textureLocation); glClientActiveTexture(GL_TEXTURE0+*textureLocation); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, sizeof(ofVec2f), &vertexData.getTexCoordsPointer()->x); } glActiveTexture(GL_TEXTURE0); glClientActiveTexture(GL_TEXTURE0); } if(vertexData.getNumIndices()){ #ifdef TARGET_OPENGLES glDrawElements(ofGetGLPrimitiveMode(vertexData.getMode()), vertexData.getNumIndices(),GL_UNSIGNED_SHORT,vertexData.getIndexPointer()); #else glDrawElements(ofGetGLPrimitiveMode(vertexData.getMode()), vertexData.getNumIndices(),GL_UNSIGNED_INT,vertexData.getIndexPointer()); #endif }else{ glDrawArrays(ofGetGLPrimitiveMode(vertexData.getMode()), 0, vertexData.getNumVertices()); } if(vertexData.getNumColors() && useColors){ glDisableClientState(GL_COLOR_ARRAY); } if(vertexData.getNumNormals() && useNormals){ glDisableClientState(GL_NORMAL_ARRAY); } if(vertexData.getNumTexCoords() && useTextures){ glDisableClientState(GL_TEXTURE_COORD_ARRAY); } }
void MeshHelper::fuseNeighbours( ofMesh& outputMesh, const ofMesh& sourceMesh, float fuseDistance ) { //@todo tex coords, normals assert( sourceMesh.getMode() == OF_PRIMITIVE_TRIANGLES ); if ( fuseDistance < 0 ) { // fuse close-enough vertices // first define 'close enough' as 1/10000 of smallest dimension of the bounding box width/height/depth ofVec3f tlb, brf; // top left back, bottom right front calculateAABoundingBox( sourceMesh, tlb, brf ); float minDimension = min(brf.x-tlb.x,min(brf.y-tlb.y, brf.z-tlb.z)); fuseDistance = minDimension * 0.00001f; } // now fuse map<int,int> fused; vector<ofVec3f> vertices; for ( int i=0; i<sourceMesh.getNumVertices(); i++ ) { const ofVec3f& vertex = sourceMesh.getVertex(i); //vertex.rotate(10, 10, 10); bool didFuse = false; for ( int j=0; j<vertices.size(); j++ ) { if ( (vertex-vertices[j]).length()<fuseDistance ) { // fuse i to j fused[i] = j; didFuse = true; break; } } if ( !didFuse ) { vertices.push_back( vertex ); fused[i] = vertices.size()-1; } } // build the output mesh outputMesh.clear(); outputMesh.addVertices(vertices); if ( sourceMesh.getNumIndices() > 0 ) { // walk through indices to build up the new mesh const vector<ofIndexType>& indices = sourceMesh.getIndices(); for ( int i=0; i<indices.size(); i+=3 ) { assert( fused.find( indices[i] ) != fused.end() ); assert( fused.find( indices[i+1] ) != fused.end() ); assert( fused.find( indices[i+2] ) != fused.end() ); outputMesh.addTriangle( fused[indices[i]], fused[indices[i+1]], fused[indices[i+2]] ); } } else { // triangles are just triples of vertices for ( int i=0; i<sourceMesh.getNumVertices(); i+=3 ) { outputMesh.addTriangle( fused[i], fused[i+1], fused[i+2] ); } } ofLogNotice("MeshHelper") << "fuseNeighbours: input " << sourceMesh.getNumVertices() << " vertices/" << sourceMesh.getNumIndices() << " indices, output " << outputMesh.getNumVertices() << " vertices/" << outputMesh.getNumIndices() << " indices"; }
void MeshHelper::fuseNeighbours( ofMesh& mesh, float fuseDistance ) { //@todo tex coords, normals assert( mesh.getMode() == OF_PRIMITIVE_TRIANGLES ); int oldNumVerts = mesh.getNumVertices(); int oldNumIndices = mesh.getNumIndices(); if ( fuseDistance < 0 ) { // fuse close-enough vertices // first define 'close enough' as 1/10000 of smallest dimension of the bounding box width/height/depth ofVec3f tlb, brf; // top left back, bottom right front calculateAABoundingBox( mesh, tlb, brf ); float minDimension = min(brf.x-tlb.x,min(brf.y-tlb.y, brf.z-tlb.z)); fuseDistance = minDimension * 0.00001f; } // now fuse map<ofIndexType,ofIndexType> fused; vector<ofVec3f> newVertices; vector<ofIndexType> remove; for ( ofIndexType i=0; i<mesh.getNumVertices(); i++ ) { const ofVec3f& vertex = mesh.getVertex(i); // look at all the earlier vertices bool didFuse = false; for ( ofIndexType j=0; j<newVertices.size(); j++ ) { if ( (vertex-newVertices[j]).length()<fuseDistance ) { // fuse i to j fused[i] = j; remove.push_back(i); didFuse = true; break; } } if ( !didFuse ) { newVertices.push_back( vertex ); fused[i] = newVertices.size()-1; } } // update indices for ( int i=0; i<mesh.getNumIndices(); i++ ) { ofIndexType originalIndex = mesh.getIndex(i); assert( fused.find( originalIndex ) != fused.end() ); if ( fused.find(originalIndex) != fused.end() ) { mesh.getIndices()[i] = fused[originalIndex]; } } // remove the fused for ( int i=remove.size()-1; i>=0; i-- ) { mesh.removeVertex( remove[i] ); } ofLogNotice("MeshHelper") << "fuseNeighbours inplace: input " << oldNumVerts << " vertices/" << oldNumIndices << " indices, output " << mesh.getNumVertices() << " vertices/" << mesh.getNumIndices() << " indices"; }
//-------------------------------------------------------------- void ofxBulletSoftTriMesh::create( ofxBulletWorldSoft* a_world, ofMesh& aMesh, btTransform &a_bt_tr, float a_mass ) { if(a_world == NULL) { ofLogError("ofxBulletSoftTriMesh") << "create(): a_world param is NULL"; return; } if( aMesh.getMode() != OF_PRIMITIVE_TRIANGLES ) { ofLogError("ofxBulletSoftTriMesh") << " only excepts meshes that are triangles"; return; } _world = a_world; _cachedMesh.clear(); _cachedMesh = aMesh; if( bullet_vertices != NULL ) { delete bullet_vertices; bullet_vertices = NULL; } int vertStride = sizeof(btVector3); int indexStride = 3*sizeof(int); int totalVerts = (int)aMesh.getNumVertices(); int totalIndices = (int)aMesh.getNumIndices(); bullet_vertices = new btScalar[ totalVerts * 3 ]; int* bullet_indices = new int[ totalIndices ]; auto& tverts = aMesh.getVertices(); vector< ofIndexType >& tindices = aMesh.getIndices(); for( int i = 0; i < totalVerts; i++ ) { bullet_vertices[i*3+0] = tverts[i].x; bullet_vertices[i*3+1] = tverts[i].y; bullet_vertices[i*3+2] = tverts[i].z; } for( int i = 0; i < totalIndices; i++ ) { bullet_indices[i] = tindices[i]; } _softBody = btSoftBodyHelpers::CreateFromTriMesh( _world->getInfo(), bullet_vertices, bullet_indices, totalIndices/3 ); _softBody->transform( a_bt_tr ); setMass( a_mass, true ); setCreated(_softBody); createInternalUserData(); delete [] bullet_indices; }
//---------------------------------------------------------- void ofGLRenderer::draw(ofMesh & vertexData){ if(vertexData.getNumVertices()){ glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, sizeof(ofVec3f), vertexData.getVerticesPointer()); } if(vertexData.getNumNormals()){ glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, 0, vertexData.getNormalsPointer()); } if(vertexData.getNumColors()){ glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4,GL_FLOAT, sizeof(ofColor), vertexData.getColorsPointer()); } if(vertexData.getNumTexCoords()){ glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, vertexData.getTexCoordsPointer()); } if(vertexData.getNumIndices()){ #ifdef TARGET_OPENGLES glDrawElements(ofGetGLPrimitiveMode(vertexData.getMode()), vertexData.getNumIndices(),GL_UNSIGNED_SHORT,vertexData.getIndexPointer()); #else glDrawElements(ofGetGLPrimitiveMode(vertexData.getMode()), vertexData.getNumIndices(),GL_UNSIGNED_INT,vertexData.getIndexPointer()); #endif }else{ glDrawArrays(ofGetGLPrimitiveMode(vertexData.getMode()), 0, vertexData.getNumVertices()); } if(vertexData.getNumColors()){ glDisableClientState(GL_COLOR_ARRAY); } if(vertexData.getNumNormals()){ glDisableClientState(GL_NORMAL_ARRAY); } if(vertexData.getNumTexCoords()){ glDisableClientState(GL_TEXTURE_COORD_ARRAY); } }
glmMesh toGlm(const ofMesh &_mesh){ glmMesh mesh; for (auto &it : _mesh.getColors()) { mesh.addColor(toGlm(it)); } for (auto &it : _mesh.getVertices()) { mesh.addVertex(toGlm(it)); } for (auto &it : _mesh.getNormals()) { mesh.addNormal(toGlm(it)); } for (auto &it : _mesh.getTexCoords()) { mesh.addTexCoord(toGlm(it)); } for (auto &it : _mesh.getIndices()) { mesh.addIndex(toGlm(it)); } GLenum drawMode = ofGetGLPrimitiveMode(_mesh.getMode()); if (drawMode == GL_POINTS) { mesh.setDrawMode(POINTS); } else if (drawMode == GL_LINES){ mesh.setDrawMode(LINES); } else if (drawMode == GL_LINE_STRIP){ mesh.setDrawMode(LINE_STRIP); } else if (drawMode == GL_TRIANGLES){ mesh.setDrawMode(TRIANGLES); } else if (drawMode == GL_TRIANGLE_STRIP){ mesh.setDrawMode(TRIANGLE_STRIP); } return mesh; }
void ofCairoRenderer::draw(ofMesh & primitive, bool useColors, bool useTextures, bool useNormals){ if(primitive.getNumVertices() == 0){ return; } if(primitive.getNumIndices() == 0){ ofMesh indexedMesh = primitive; indexedMesh.setupIndicesAuto(); draw(indexedMesh, useColors, useTextures, useNormals); return; } pushMatrix(); cairo_matrix_init_identity(getCairoMatrix()); cairo_new_path(cr); int i = 1; ofVec3f v = transform(primitive.getVertex(primitive.getIndex(0))); ofVec3f v2; cairo_move_to(cr,v.x,v.y); if(primitive.getMode()==OF_PRIMITIVE_TRIANGLE_STRIP){ v = transform(primitive.getVertex(primitive.getIndex(1))); cairo_line_to(cr,v.x,v.y); v = transform(primitive.getVertex(primitive.getIndex(2))); cairo_line_to(cr,v.x,v.y); i=2; } for(; i<primitive.getNumIndices(); i++){ v = transform(primitive.getVertex(primitive.getIndex(i))); switch(primitive.getMode()){ case(OF_PRIMITIVE_TRIANGLES): if((i+1)%3==0){ cairo_line_to(cr,v.x,v.y); v2 = transform(primitive.getVertex(primitive.getIndex(i-2))); cairo_line_to(cr,v2.x,v2.y); cairo_move_to(cr,v.x,v.y); }else if((i+3)%3==0){ cairo_move_to(cr,v.x,v.y); }else{ cairo_line_to(cr,v.x,v.y); } break; case(OF_PRIMITIVE_TRIANGLE_STRIP): v2 = transform(primitive.getVertex(primitive.getIndex(i-2))); cairo_line_to(cr,v.x,v.y); cairo_line_to(cr,v2.x,v2.y); cairo_move_to(cr,v.x,v.y); break; case(OF_PRIMITIVE_TRIANGLE_FAN): /*triangles.addIndex((GLuint)0); triangles.addIndex((GLuint)1); triangles.addIndex((GLuint)2); for(int i = 2; i < primitive.getNumVertices()-1;i++){ triangles.addIndex((GLuint)0); triangles.addIndex((GLuint)i); triangles.addIndex((GLuint)i+1); }*/ break; default:break; } } cairo_move_to(cr,primitive.getVertex(primitive.getIndex(primitive.getNumIndices()-1)).x,primitive.getVertex(primitive.getIndex(primitive.getNumIndices()-1)).y); if(ofGetStyle().lineWidth>0){ cairo_stroke( cr ); } popMatrix(); }
void ofCairoRenderer::draw(const ofMesh & primitive, ofPolyRenderMode mode, bool useColors, bool useTextures, bool useNormals) const{ if(useColors || useTextures || useNormals){ ofLogWarning("ofCairoRenderer") << "draw(): cairo mesh rendering doesn't support colors, textures, or normals. drawing wireframe ..."; } if(primitive.getNumVertices() == 0){ return; } if(primitive.getNumIndices() == 0){ ofMesh indexedMesh = primitive; indexedMesh.setupIndicesAuto(); draw(indexedMesh, mode, useColors, useTextures, useNormals); return; } cairo_new_path(cr); cairo_matrix_t matrix; cairo_matrix_init_identity(&matrix); cairo_new_path(cr); std::size_t i = 1; ofVec3f v = transform(primitive.getVertex(primitive.getIndex(0))); ofVec3f v2; cairo_move_to(cr,v.x,v.y); if(primitive.getMode()==OF_PRIMITIVE_TRIANGLE_STRIP){ v = transform(primitive.getVertex(primitive.getIndex(1))); cairo_line_to(cr,v.x,v.y); v = transform(primitive.getVertex(primitive.getIndex(2))); cairo_line_to(cr,v.x,v.y); i=2; } for(; i<primitive.getNumIndices(); i++){ v = transform(primitive.getVertex(primitive.getIndex(i))); switch(primitive.getMode()){ case(OF_PRIMITIVE_TRIANGLES): if((i+1)%3==0){ cairo_line_to(cr,v.x,v.y); v2 = transform(primitive.getVertex(primitive.getIndex(i-2))); cairo_line_to(cr,v2.x,v2.y); cairo_move_to(cr,v.x,v.y); }else if((i+3)%3==0){ cairo_move_to(cr,v.x,v.y); }else{ cairo_line_to(cr,v.x,v.y); } break; case(OF_PRIMITIVE_TRIANGLE_STRIP): v2 = transform(primitive.getVertex(primitive.getIndex(i-2))); cairo_line_to(cr,v.x,v.y); cairo_line_to(cr,v2.x,v2.y); cairo_move_to(cr,v.x,v.y); break; case(OF_PRIMITIVE_TRIANGLE_FAN): /*triangles.addIndex((GLuint)0); triangles.addIndex((GLuint)1); triangles.addIndex((GLuint)2); for(int i = 2; i < primitive.getNumVertices()-1;i++){ triangles.addIndex((GLuint)0); triangles.addIndex((GLuint)i); triangles.addIndex((GLuint)i+1); }*/ break; default:break; } } cairo_move_to(cr,primitive.getVertex(primitive.getIndex(primitive.getNumIndices()-1)).x,primitive.getVertex(primitive.getIndex(primitive.getNumIndices()-1)).y); if(currentStyle.lineWidth>0){ cairo_stroke( cr ); } }
//-------------------------------------------------------------- bool ofxBulletCustomShape::addMesh( ofMesh a_mesh, ofVec3f a_localScaling, bool a_bUseConvexHull ) { if(a_mesh.getMode() != OF_PRIMITIVE_TRIANGLES) { ofLog( OF_LOG_ERROR, "ofxBulletCustomShape :: addMesh : mesh must be set to OF_PRIMITIVE_TRIANGLES!! aborting"); return false; } if(_bAdded == true) { ofLog( OF_LOG_ERROR, "ofxBulletCustomShape :: addMesh : can not call after calling add()" ); return false; } btVector3 localScaling( a_localScaling.x, a_localScaling.y, a_localScaling.z ); auto indicies = a_mesh.getIndices(); auto verticies = a_mesh.getVertices(); btVector3 centroid = btVector3(0, 0, 0); if(!a_bUseConvexHull) { for(int i = 0; i < verticies.size(); i++) { btVector3 tempVec = btVector3(verticies[i].x, verticies[i].y, verticies[i].z); tempVec *= localScaling; centroid += tempVec; } centroid /= (float)verticies.size(); vector<btVector3> newVerts; for ( int i = 0; i < indicies.size(); i++) { btVector3 vertex( verticies[indicies[i]].x, verticies[indicies[i]].y, verticies[indicies[i]].z); vertex *= localScaling; vertex -= centroid; newVerts.push_back(vertex); } btConvexHullShape* convexShape = new btConvexHullShape(&(newVerts[0].getX()), newVerts.size()); convexShape->setMargin( 0.01f ); shapes.push_back( convexShape ); centroids.push_back( ofVec3f(centroid.getX(), centroid.getY(), centroid.getZ()) ); } else { // HULL Building code from example ConvexDecompositionDemo.cpp // btTriangleMesh* trimesh = new btTriangleMesh(); for ( int i = 0; i < indicies.size()/3; i++) { int index0 = indicies[i*3]; int index1 = indicies[i*3+1]; int index2 = indicies[i*3+2]; btVector3 vertex0( verticies[index0].x, verticies[index0].y, verticies[index0].z ); btVector3 vertex1( verticies[index1].x, verticies[index1].y, verticies[index1].z ); btVector3 vertex2( verticies[index2].x, verticies[index2].y, verticies[index2].z ); vertex0 *= localScaling; vertex1 *= localScaling; vertex2 *= localScaling; trimesh->addTriangle(vertex0, vertex1, vertex2); } //cout << "ofxBulletCustomShape :: addMesh : input triangles = " << trimesh->getNumTriangles() << endl; //cout << "ofxBulletCustomShape :: addMesh : input indicies = " << indicies.size() << endl; //cout << "ofxBulletCustomShape :: addMesh : input verticies = " << verticies.size() << endl; btConvexShape* tmpConvexShape = new btConvexTriangleMeshShape(trimesh); //create a hull approximation btShapeHull* hull = new btShapeHull(tmpConvexShape); btScalar margin = tmpConvexShape->getMargin(); hull->buildHull(margin); tmpConvexShape->setUserPointer(hull); centroid = btVector3(0., 0., 0.); for (int i = 0; i < hull->numVertices(); i++) { centroid += hull->getVertexPointer()[i]; } centroid /= (float)hull->numVertices(); //printf("ofxBulletCustomShape :: addMesh : new hull numTriangles = %d\n", hull->numTriangles()); //printf("ofxBulletCustomShape :: addMesh : new hull numIndices = %d\n", hull->numIndices()); //printf("ofxBulletCustomShape :: addMesh : new hull numVertices = %d\n", hull->numVertices()); btConvexHullShape* convexShape = new btConvexHullShape(); for (int i=0;i<hull->numVertices();i++) { convexShape->addPoint(hull->getVertexPointer()[i] - centroid); } delete tmpConvexShape; delete hull; shapes.push_back( convexShape ); centroids.push_back( ofVec3f(centroid.getX(), centroid.getY(), centroid.getZ()) ); } return true; }
//-------------------------------------------------------------- void ofxBulletTriMeshShape::create( btDiscreteDynamicsWorld* a_world, ofMesh& aMesh, btTransform &a_bt_tr, float a_mass, glm::vec3 aAAbbMin, glm::vec3 aAAbbMax ) { if( aMesh.getMode() != OF_PRIMITIVE_TRIANGLES ) { ofLogWarning() << " ofxBulletTriMeshShape :: create : mesh must be using triangles, not creating!!" << endl; return; } if( aMesh.getNumIndices() < 3 ) { ofLogWarning() << " ofxBulletTriMeshShape :: create : mesh must have indices, not creating!" << endl; return; } if( !_bInited || _shape == NULL ) { int vertStride = sizeof(btVector3); int indexStride = 3*sizeof(int); totalVerts = (int)aMesh.getNumVertices(); totalIndices = (int)aMesh.getNumIndices(); const int totalTriangles = totalIndices / 3; if( bullet_indices != NULL ) { removeShape(); } if( bullet_vertices != NULL ) { removeShape(); } if( bullet_indexVertexArrays != NULL ) { removeShape(); } if( _shape != NULL ) { removeShape(); } bullet_vertices = new btVector3[ totalVerts ]; bullet_indices = new int[ totalIndices ]; auto& tverts = aMesh.getVertices(); auto& tindices = aMesh.getIndices(); for( int i = 0; i < totalVerts; i++ ) { bullet_vertices[i].setValue( tverts[i].x, tverts[i].y, tverts[i].z ); } for( int i = 0; i < totalIndices; i++ ) { bullet_indices[i] = (int)tindices[i]; } bullet_indexVertexArrays = new btTriangleIndexVertexArray(totalTriangles, bullet_indices, indexStride, totalVerts, (btScalar*) &bullet_vertices[0].x(), vertStride); // if you are having trouble with objects falling through, try passing in smaller or larger aabbMin and aabbMax // to something closer to the size of your object // // btVector3 aabbMin(-10000,-10000,-10000),aabbMax(10000,10000,10000); if( aAAbbMin.length() > 0 && aAAbbMax.length() > 0 ) { btVector3 aabbMin( aAAbbMin.x, aAAbbMin.y, aAAbbMin.z ); btVector3 aabbMax( aAAbbMax.x, aAAbbMax.y, aAAbbMax.z ); _shape = new btBvhTriangleMeshShape(bullet_indexVertexArrays, true, aabbMin, aabbMax ); } else { _shape = new btBvhTriangleMeshShape(bullet_indexVertexArrays, true, true ); } } ofxBulletRigidBody::create( a_world, _shape, a_bt_tr, a_mass ); createInternalUserData(); updateMesh( a_world, aMesh ); }
void ofCairoRenderer::draw(ofMesh & primitive){ if(primitive.getNumVertices()==0) return; pushMatrix(); cairo_matrix_init_identity(getCairoMatrix()); cairo_new_path(cr); //if(indices.getNumIndices()){ int i = 1; ofVec3f v = transform(primitive.getVertex(primitive.getIndex(0))); ofVec3f v2; cairo_move_to(cr,v.x,v.y); if(primitive.getMode()==OF_TRIANGLE_STRIP_MODE){ v = transform(primitive.getVertex(primitive.getIndex(1))); cairo_line_to(cr,v.x,v.y); v = transform(primitive.getVertex(primitive.getIndex(2))); cairo_line_to(cr,v.x,v.y); i=2; } for(; i<primitive.getNumIndices(); i++){ v = transform(primitive.getVertex(primitive.getIndex(i))); switch(primitive.getMode()){ case(OF_TRIANGLES_MODE): if((i+1)%3==0){ cairo_line_to(cr,v.x,v.y); v2 = transform(primitive.getVertex(primitive.getIndex(i-2))); cairo_line_to(cr,v2.x,v2.y); cairo_move_to(cr,v.x,v.y); }else if((i+3)%3==0){ cairo_move_to(cr,v.x,v.y); }else{ cairo_line_to(cr,v.x,v.y); } break; case(OF_TRIANGLE_STRIP_MODE): v2 = transform(primitive.getVertex(primitive.getIndex(i-2))); cairo_line_to(cr,v.x,v.y); cairo_line_to(cr,v2.x,v2.y); cairo_move_to(cr,v.x,v.y); break; case(OF_TRIANGLE_FAN_MODE): /*triangles.addIndex((GLuint)0); triangles.addIndex((GLuint)1); triangles.addIndex((GLuint)2); for(int i = 2; i < primitive.getNumVertices()-1;i++){ triangles.addIndex((GLuint)0); triangles.addIndex((GLuint)i); triangles.addIndex((GLuint)i+1); }*/ break; default:break; } } cairo_move_to(cr,primitive.getVertex(primitive.getIndex(primitive.getNumIndices()-1)).x,primitive.getVertex(primitive.getIndex(primitive.getNumIndices()-1)).y); if(ofGetStyle().lineWidth>0){ cairo_stroke( cr ); } popMatrix(); }
vector<pair<btVector3, btConvexHullShape*> > ofxBulletConvexDecomposer::decompose(const ofMesh &meshToDecompose, btVector3 scale ) { assert( meshToDecompose.getMode() == OF_TRIANGLES_MODE ); vector<pair<btVector3, btConvexHullShape*> > convexShapes; int tcount = meshToDecompose.getNumIndices()/3; if ( tcount == 0 ) // nothing to do return convexShapes; // adapted from bullet-2.81-rev2613/Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.cpp /* unsigned int depth = 5; float cpercent = 5; float ppercent = 15; unsigned int maxv = 16; float skinWidth = 0.0; // ConvexDecomposition::WavefrontObj wo; ConvexDecomposition::DecompDesc desc; desc.mVcount = meshToDecompose.getNumVertices(); desc.mVertices = (float*)(meshToDecompose.getVerticesPointer()); desc.mTcount = meshToDecompose.getNumIndices()/3; desc.mIndices = meshToDecompose.getIndexPointer(); desc.mDepth = depth; desc.mCpercent = cpercent; desc.mPpercent = ppercent; desc.mMaxVertices = maxv; desc.mSkinWidth = skinWidth; desc.mCallback = this; */ //----------------------------------------------- // HACD //----------------------------------------------- std::vector< HACD::Vec3<HACD::Real> > points; std::vector< HACD::Vec3<long> > triangles; for(int i=0; i<meshToDecompose.getNumVertices(); i++ ) { ofVec3f meshVert = meshToDecompose.getVertex(i); HACD::Vec3<HACD::Real> vertex( meshVert.x, meshVert.y, meshVert.z ); points.push_back(vertex); } for(int i=0;i<meshToDecompose.getNumIndices(); i+=3 ) { HACD::Vec3<long> triangle(meshToDecompose.getIndex(i), meshToDecompose.getIndex(i+1), meshToDecompose.getIndex(i+2) ); triangles.push_back(triangle); } assert(triangles.size()==tcount); HACD::HACD myHACD; myHACD.SetPoints(&points[0]); myHACD.SetNPoints(points.size()); myHACD.SetTriangles(&triangles[0]); myHACD.SetNTriangles(triangles.size()); myHACD.SetCompacityWeight(0.1); myHACD.SetVolumeWeight(0.0); // HACD parameters // Recommended parameters: 2 100 0 0 0 0 size_t nClusters = 2; double concavity = 100; bool invert = false; bool addExtraDistPoints = false; bool addNeighboursDistPoints = false; bool addFacesPoints = false; myHACD.SetNClusters(nClusters); // minimum number of clusters myHACD.SetNVerticesPerCH(100); // max of 100 vertices per convex-hull myHACD.SetConcavity(concavity); // maximum concavity myHACD.SetAddExtraDistPoints(addExtraDistPoints); myHACD.SetAddNeighboursDistPoints(addNeighboursDistPoints); myHACD.SetAddFacesPoints(addFacesPoints); myHACD.SetCallBack( hacdCallback ); myHACD.Compute(); nClusters = myHACD.GetNClusters(); int totalTriangles = 0; int totalPoints = 0; for (int c=0;c<nClusters;c++) { //generate convex result size_t nPoints = myHACD.GetNPointsCH(c); size_t nTriangles = myHACD.GetNTrianglesCH(c); ofLogVerbose("ofxBulletConvexDecomposer") << "cluster " << c <<"/" << nClusters << " points " << nPoints << " triangles " << nTriangles; float* vertices = new float[nPoints*3]; unsigned int* triangles = new unsigned int[nTriangles*3]; HACD::Vec3<HACD::Real> * pointsCH = new HACD::Vec3<HACD::Real>[nPoints]; HACD::Vec3<long> * trianglesCH = new HACD::Vec3<long>[nTriangles]; myHACD.GetCH(c, pointsCH, trianglesCH); // points for(size_t v = 0; v < nPoints; v++) { vertices[3*v] = pointsCH[v].X(); vertices[3*v+1] = pointsCH[v].Y(); vertices[3*v+2] = pointsCH[v].Z(); } // triangles for(size_t f = 0; f < nTriangles; f++) { triangles[3*f] = trianglesCH[f].X(); triangles[3*f+1] = trianglesCH[f].Y(); triangles[3*f+2] = trianglesCH[f].Z(); } ConvexResult r(nPoints, vertices, nTriangles, triangles); convexShapes.push_back( createConvexHullShapeFromConvexResult(r, scale) ); delete [] pointsCH; delete [] trianglesCH; delete [] vertices; delete [] triangles; totalTriangles += nTriangles; } return convexShapes; }