void ofxScale(ofMesh &mesh, float x, float y, float z) { for (int i=0; i<mesh.getNumVertices(); i++) { mesh.getVertices()[i].x *= x; mesh.getVertices()[i].y *= y; mesh.getVertices()[i].z *= z; } }
//-------------------------------------------------------------- void ofApp::colorFaces(ofMesh & mesh){ for(int i = 0; i < mesh.getVertices().size(); i++){ const ofVec3f & v = mesh.getVertices()[i]; ofColor col; col.setHsb(ofMap(v.x + v.y, -1000, 1000, 0, 255), 255, 255); mesh.addColor(col); } }
void buildNormalsFaces(ofMesh& mesh) { mesh.clearNormals(); for(int i = 0; i < mesh.getNumVertices(); i += 3) { int i0 = i + 0, i1 = i + 1, i2 = i + 2; ofVec3f normal = getNormal(mesh.getVertices()[i0], mesh.getVertices()[i1], mesh.getVertices()[i2]); for(int j = 0; j < 3; j++) { mesh.addNormal(normal); } } }
ofMesh meshPointAdder::returnMeshWarpedToThisMesh(ofMesh & meshToMatch){ // this could / should be optimized; ofMesh newMesh; vector < ofPoint > newPoints; vector < ofPoint > newTexPoints; for (int i = 0; i < ptsList.size(); i++){ int who = ptsListBarycentric[i].whichTriangle; float a = ptsListBarycentric[i].a; float b = ptsListBarycentric[i].b; float c = ptsListBarycentric[i].c; ofPoint newPos = ApplyBarycentric( meshToMatch.getVertices()[who*3+0], meshToMatch.getVertices()[who*3+1], meshToMatch.getVertices()[who*3+2],a,b,c); ofVec2f newTex = ApplyBarycentric( meshToMatch.getTexCoord(who*3+0), meshToMatch.getTexCoord(who*3+0), meshToMatch.getTexCoord(who*3+0),a,b,c); newPoints.push_back(newPos); newTexPoints.push_back(newTex); } ofMesh objectMesh; for(int i = 0; i < triangles.size(); i++){ ofVec3f p1 = newPoints[triangles[i].a]; ofVec3f p2 = newPoints[triangles[i].b]; ofVec3f p3 = newPoints[triangles[i].c]; objectMesh.addVertex(p1); objectMesh.addVertex(p2); objectMesh.addVertex(p3); ofVec3f t1 = newTexPoints[triangles[i].a]; ofVec3f t2 = newTexPoints[triangles[i].b]; ofVec3f t3 = newTexPoints[triangles[i].c]; objectMesh.addTexCoord(t1); objectMesh.addTexCoord(t2); objectMesh.addTexCoord(t3); } return objectMesh; }
//-------------------------------------------------------------- bool load(const string& path, ofMesh& mesh) { ofFile file(path, ofFile::ReadOnly, true); if (!file.exists()) { ofLogError("ofxBinaryMesh::load") << "Cannot open file at " << path; return false; } mesh.clear(); int numVerts = 0; file.read((char *)(&numVerts), sizeof(int)); if (numVerts > 0) { mesh.getVertices().resize(numVerts); file.read((char *)(&(mesh.getVertices())[0]), sizeof(ofPoint) * numVerts); } int numNormals = 0; file.read((char *)(&numNormals), sizeof(int)); if (numNormals > 0) { mesh.getNormals().resize(numNormals); file.read((char *)(&(mesh.getNormals())[0]), sizeof(ofPoint) * numNormals); } int numTexCoords = 0; file.read((char *)(&numTexCoords), sizeof(int)); if (numTexCoords > 0) { mesh.getTexCoords().resize(numTexCoords); file.read((char *)(&(mesh.getTexCoords())[0]), sizeof(ofVec2f) * numTexCoords); } int numColors = 0; file.read((char *)(&numColors), sizeof(int)); if (numColors > 0) { mesh.getColors().resize(numColors); file.read((char *)(&(mesh.getColors())[0]), sizeof(ofFloatColor) * numColors); } int numIndices = 0; file.read((char *)(&numIndices), sizeof(int)); if (numIndices > 0) { mesh.getIndices().resize(numIndices); file.read((char *)(&(mesh.getIndices())[0]), sizeof(ofIndexType) * numIndices); } file.close(); return true; }
void buildNormalsAverage(ofMesh& mesh) { vector<ofIndexType>& indices = mesh.getIndices(); vector<ofVec3f> normals(mesh.getNumVertices()); for(int i = 0; i < indices.size(); i += 3) { int i0 = indices[i + 0], i1 = indices[i + 1], i2 = indices[i + 2]; ofVec3f normal = getNormal(mesh.getVertices()[i0], mesh.getVertices()[i1], mesh.getVertices()[i2]); normals[i0] += normal; normals[i1] += normal; normals[i2] += normal; } for(int i = 0; i < normals.size(); i++) { normals[i].normalize(); } mesh.addNormals(normals); }
//-------------------------------------------------------------- void ofxBulletTriMeshShape::updateMesh( btDiscreteDynamicsWorld* a_world, ofMesh& aMesh ) { if( aMesh.getNumVertices() != totalVerts || aMesh.getNumIndices() != totalIndices ) { ofLogWarning() << "updateMesh :: the verts or the indices are not the correct size, not updating"; return; } auto& tverts = aMesh.getVertices(); btVector3 aabbMin(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); btVector3 aabbMax(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); for( int i = 0; i < totalVerts; i++ ) { auto& v = tverts[i]; bullet_vertices[i].setValue( v.x, v.y, v.z ); aabbMin.setMin( bullet_vertices[i] ); aabbMax.setMax( bullet_vertices[i] ); } btBvhTriangleMeshShape* triShape = (btBvhTriangleMeshShape*)_shape; // triShape->partialRefitTree( aabbMin, aabbMax ); triShape->refitTree( aabbMin, aabbMax ); //clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation. a_world->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs( getRigidBody()->getBroadphaseHandle(), a_world->getDispatcher()); }
ofMesh & ofBitmapStringGetMesh(const string & text, int x, int y){ int len = (int)text.length(); //float yOffset = 0; float fontSize = 8.0f; bool bOrigin = false; float sx = x; float sy = y-fontSize; ofDrawBitmapCharacterStart(text.size()); for(int c = 0; c < len; c++){ if(text[c] == '\n'){ sy += bOrigin ? -1 : 1 * (fontSize*1.7); sx = x; //glRasterPos2f(x,y + (int)yOffset); } else if (text[c] >= 32){ // < 32 = control characters - don't draw // solves a bug with control characters // getting drawn when they ought to not be ofDrawBitmapCharacter(text[c], (int)sx, (int)sy); sx += fontSize; } } //We do this because its way faster charMesh.getVertices().resize(vC); charMesh.getTexCoords().resize(vC); return charMesh; }
//--------------------------------------------------------------------- void ofDrawBitmapCharacterEnd(){ if( vC > 0 ){ charMesh.getVertices().resize(vC); charMesh.getTexCoords().resize(vC); bitmappedFontTexture.bind(); ofPtr<ofGLProgrammableRenderer> programmableRenderer = ofGetGLProgrammableRenderer(); if (!programmableRenderer){ #ifndef TARGET_OPENGLES // this temporarily enables alpha testing, // which discards pixels unless their alpha is 1.0f glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0); #endif }else{ // glPush/PopAttrib is deprecated + we are doing the alpha test through a shader programmableRenderer->setAlphaBitmapText(true); } charMesh.draw(); if (!programmableRenderer){ #ifndef TARGET_OPENGLES glPopAttrib(); #endif }else{ programmableRenderer->setAlphaBitmapText(false); } bitmappedFontTexture.unbind(); } }
void updateMesh(ofMesh& mesh) { float t = ofGetElapsedTimef(); ofVec3f axis; axis.x = ofSignedNoise(1, 0, 0, t); axis.y = ofSignedNoise(0, 1, 0, t); axis.z = ofSignedNoise(0, 0, 1, t); axis.normalize(); vector<ofVec3f>& verts = mesh.getVertices(); vector<ofVec3f>& norms = mesh.getNormals(); for (int i = 0; i < verts.size(); i++) { ofVec3f& v = verts[i]; ofVec3f& n = norms[i]; ofVec3f vv = v; float r = vv.y * fmodf(t, 10) * 0.1; vv.rotate(r, axis); n.rotate(r, axis); v = vv; } }
//-------------------------------------------------------------- void ofxBulletSoftTriMesh::updateMesh( ofMesh& aMesh ) { int totalNodes = getNumNodes(); auto& tverts = aMesh.getVertices(); if( _cachedMesh.getMode() == OF_PRIMITIVE_TRIANGLES ) { if( tverts.size() != totalNodes ) { tverts.resize( totalNodes ); } auto& tnormals = aMesh.getNormals(); if( aMesh.getNumNormals() != totalNodes ) { tnormals.resize( totalNodes ); } for( int i = 0; i < totalNodes; i++ ) { tverts[i].x = _softBody->m_nodes[i].m_x.x(); tverts[i].y = _softBody->m_nodes[i].m_x.y(); tverts[i].z = _softBody->m_nodes[i].m_x.z(); tnormals[i].x = _softBody->m_nodes[i].m_n.x(); tnormals[i].y = _softBody->m_nodes[i].m_n.y(); tnormals[i].z = _softBody->m_nodes[i].m_n.z(); } } _lastMeshUpdateFrame = ofGetFrameNum(); }
//-------------------------------------------------------------- void ofVbo::setMesh(const ofMesh & mesh, int usage, bool useColors, bool useTextures, bool useNormals){ if(mesh.getVertices().empty()){ ofLogWarning("ofVbo") << "setMesh(): ignoring mesh with no vertices"; return; } setVertexData(mesh.getVerticesPointer(),mesh.getNumVertices(),usage); if(mesh.hasColors() && useColors){ setColorData(mesh.getColorsPointer(),mesh.getNumColors(),usage); enableColors(); }else{ disableColors(); } if(mesh.hasNormals() && useNormals){ setNormalData(mesh.getNormalsPointer(),mesh.getNumNormals(),usage); enableNormals(); }else{ disableNormals(); } if(mesh.hasTexCoords() && useTextures){ setTexCoordData(mesh.getTexCoordsPointer(),mesh.getNumTexCoords(),usage); enableTexCoords(); }else{ disableTexCoords(); } if(mesh.hasIndices()){ setIndexData(mesh.getIndexPointer(), mesh.getNumIndices(), usage); enableIndices(); }else{ disableIndices(); } }
// this is important for avoiding slightl discrepencies when the mesh is // projected, or processed by GL transforms vs OF transforms void testApp::normalizeMesh(ofMesh& mesh) { vector<ofVec3f>& vertices = mesh.getVertices(); for(int i = 0; i < vertices.size(); i++) { vertices[i] *= normalizedMeshScale / normalizedWidth; vertices[i] += ofVec2f(normalizedWidth, normalizedHeight) / 2.; vertices[i].z = 0; } }
void ofxObjLoader::save(string path, ofMesh& mesh){ path = ofToDataPath(path); GLuint writeMode = GLM_NONE; GLMmodel* m = new GLMmodel(); if(mesh.getNumVertices() > 0){ m->numvertices = mesh.getNumVertices(); m->vertices = new GLfloat[m->numvertices*3+1]; memcpy(&m->vertices[3], &mesh.getVertices()[0].x, sizeof(ofVec3f) * mesh.getNumVertices()); } else { ofLogError("ofxObjLoader::save -- No vertices to save!"); return; } if(mesh.getNumNormals() > 0){ m->numnormals = mesh.getNumNormals(); m->normals = new GLfloat[m->numnormals*3+1]; memcpy(&m->normals[3], &mesh.getNormals()[0].x, sizeof(ofVec3f)*mesh.getNumNormals()); writeMode |= GLM_SMOOTH; } if(mesh.getNumTexCoords() > 0){ m->numtexcoords = mesh.getNumTexCoords(); m->texcoords = new GLfloat[m->numtexcoords*2+1]; memcpy(&m->texcoords[2], &mesh.getTexCoords()[0].x, sizeof(ofVec2f)*mesh.getNumTexCoords()); writeMode |= GLM_TEXTURE; } if(mesh.getNumIndices() > 0){ //create triangles m->numtriangles = mesh.getNumIndices()/3; m->triangles = new GLMtriangle[m->numtriangles]; //add them all to one group m->groups = new GLMgroup(); m->groups->next = NULL; m->groups->material = NULL; string name = "ofMesh"; m->groups->name = (char*)malloc(sizeof(char) * name.length()+1); strcpy(m->groups->name, name.c_str()); m->groups->numtriangles = mesh.getNumIndices()/3; m->groups->triangles = new GLuint[m->groups->numtriangles]; m->numgroups = 1; for(int i = 0; i < mesh.getNumIndices()/3; i++){ memcpy(m->triangles[i].vindices, &mesh.getIndices()[i*3], sizeof(GLuint)*3); memcpy(m->triangles[i].nindices, &mesh.getIndices()[i*3], sizeof(GLuint)*3); memcpy(m->triangles[i].tindices, &mesh.getIndices()[i*3], sizeof(GLuint)*3); m->groups->triangles[i] = i; } } glmWriteOBJ(m, (char*)path.c_str(), writeMode); glmDelete(m); }
//-------------------------------------------------------------- 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 ofDrawBitmapCharacterStart(int stringLength){ charMesh.getVertices().resize(6 * stringLength); charMesh.getTexCoords().resize(6 * stringLength); if(!bBitmapTexturePrepared){ prepareBitmapTexture(); } vC = 0; }
void ofApp::drawNormals(const ofMesh& mesh){ for(int i = 0; i < mesh.getVertices().size(); i++){ ofVec3f n = mesh.getNormal(i); ofVec3f v = mesh.getVertex(i); ofPushStyle(); ofSetColor(0, 255, 0); ofLine(v.x, v.y, v.z, v.x + (n.x*4), v.y + (n.y*4), v.z + (n.z*4) ); ofPopStyle(); } }
//--------------------------------------------------------------------- static void addBitmapCharacter(ofMesh & charMesh, int & vertexCount, int character, int x , int y, bool vFlipped){ if (character < 128) { float posTexW = (float)(character % 16)/16.0f; float posTexH = ((int)(character / 16.0f))/16.0f; float texY1 = posTexH; float texY2 = posTexH+heightTex; //TODO: look into a better fix. //old ofDrawBitmapString was 3 pixels higher, so this version renders text in a different position. //3 pixel adjustment corrects that when y is flpped 5 when it's not. int yOffset = 14; if(!vFlipped){ y += 5; y += yOffset; yOffset *= -1; }else{ y -= 3; } size_t vC = vertexCount; charMesh.getTexCoords()[vC] = {posTexW,texY1}; charMesh.getTexCoords()[vC+1] = {posTexW + widthTex,texY1}; charMesh.getTexCoords()[vC+2] = {posTexW+widthTex,texY2}; charMesh.getTexCoords()[vC+3] = {posTexW + widthTex,texY2}; charMesh.getTexCoords()[vC+4] = {posTexW,texY2}; charMesh.getTexCoords()[vC+5] = {posTexW,texY1}; charMesh.getVertices()[vC] = glm::vec3(x,y,0.f); charMesh.getVertices()[vC+1] = glm::vec3(x+8,y,0.f); charMesh.getVertices()[vC+2] = glm::vec3(x+8,y+yOffset,0.f); charMesh.getVertices()[vC+3] = glm::vec3(x+8,y+yOffset,0.f); charMesh.getVertices()[vC+4] = glm::vec3(x,y+yOffset,0.f); charMesh.getVertices()[vC+5] = glm::vec3(x,y,0.f); vertexCount += 6; } }
void ofxPoly2Tri::triangulate(ofMesh bounds) { vector<p2t::Point*> bound; vector<ofPoint>edgepoints = bounds.getVertices(); for (int i=0;i<edgepoints.size();++i) { bound.push_back(new p2t::Point(edgepoints[i].x,edgepoints[i].y)); } doTriangulation(bound); //clear the vector again for (vector<p2t::Point*>::iterator it = bound.begin(); it != bound.end(); ++it) { delete *it; } }
void exportPlyCloud(string filename, ofMesh& cloud) { ofFile ply; if (ply.open(filename, ofFile::WriteOnly)) { // write the header ply << "ply" << endl; ply << "format binary_little_endian 1.0" << endl; ply << "element vertex " << cloud.getVertices().size() << endl; ply << "property float x" << endl; ply << "property float y" << endl; ply << "property float z" << endl; ply << "end_header" << endl; // write all the vertices vector<ofVec3f>& surface = cloud.getVertices(); for(int i = 0; i < surface.size(); i++) { if (surface[i].z != 0) { // write the raw data as if it were a stream of bytes ply.write((char*) &surface[i], sizeof(ofVec3f)); } } } }
void MeshHelper::appendMesh( ofMesh& targetMesh, const ofMesh& toAppend, bool fuse ) { ofIndexType indexOffset = targetMesh.getNumVertices(); targetMesh.addVertices( toAppend.getVertices() ); // append indices const vector<ofIndexType>& indices = toAppend.getIndices(); for ( int i=0; i<indices.size(); i++ ) { targetMesh.addIndex( indices[i]+indexOffset ); } if ( fuse ) fuseNeighbours(targetMesh); }
void addForheadToFaceMesh(ofMesh & input){ if (input.getVertices().size() != 66) return; static int forehead[10] = {0,17,18,19,20,/*21,22,*/23,24,25,26,16}; // skipping 21 and 22 because there is a triangle that overlaps somehow ofPoint extras[10]; ofVec2f texture[10]; for (int i = 0; i < 10; i++){ extras[i] = input.getVertices()[forehead[i]] + (input.getVertices()[27] - input.getVertices()[33]); texture[i] = input.getTexCoords()[forehead[i]] + (input.getTexCoords()[27] - input.getTexCoords()[33]); input.addVertex(extras[i]); input.addTexCoord(texture[i]); } for (int i = 0; i < (10-1); i++){ // a b c // b c d; int a = forehead[i]; int b = 66 + i; int c = forehead[i+1]; input.addIndex(a); input.addIndex(b); input.addIndex(c); int d = 66 + i + 1; input.addIndex(b); input.addIndex(c); input.addIndex(d); } }
void getBoundingBox(const ofMesh& mesh, ofVec3f& min, ofVec3f& max) { int n = mesh.getNumVertices(); if(n > 0) { min = mesh.getVertex(0); max = mesh.getVertex(0); for(int i = 1; i < n; i++) { const ofVec3f& cur = mesh.getVertices()[i]; min.x = MIN(min.x, cur.x); min.y = MIN(min.y, cur.y); min.z = MIN(min.z, cur.z); max.x = MAX(max.x, cur.x); max.y = MAX(max.y, cur.y); max.z = MAX(max.z, cur.z); } } }
void getBounds(ofMesh& mesh, ofVec3f& lower, ofVec3f& upper) { for(int i = 0; i < mesh.getNumVertices(); i++) { ofVec3f& cur = mesh.getVertices()[i]; if(i == 0) { lower = cur; upper = cur; } else { lower.x = MIN(lower.x, cur.x); lower.y = MIN(lower.y, cur.y); lower.z = MIN(lower.z, cur.z); upper.x = MAX(upper.x, cur.x); upper.y = MAX(upper.y, cur.y); upper.z = MAX(upper.z, cur.z); } } }
void ofxMesh::fromMesh(const ofMesh & mesh){ if (mesh.hasVertices()) { getVertices()=mesh.getVertices(); } if (mesh.hasColors()) { getColors()=mesh.getColors(); } if (mesh.hasNormals()) { getNormals()=mesh.getNormals(); } if (mesh.hasTexCoords()) { getTexCoords()=mesh.getTexCoords(); } if (mesh.hasIndices()) { getIndices()=mesh.getIndices(); } }
//-------------------------------------------------------------- void ofxBulletSoftBody::updateMesh( ofMesh& aMesh ) { int totalNodes = getNumNodes(); int totalFaces = getNumFaces(); auto& tverts = aMesh.getVertices(); if( _cachedMesh.getMode() == OF_PRIMITIVE_TRIANGLES ) { if( tverts.size() != totalFaces * 3 ) { tverts.resize( totalFaces * 3 ); } auto& tnormals = aMesh.getNormals(); if( aMesh.getNumNormals() != totalFaces * 3 ) { tnormals.resize( totalFaces * 3 ); } for (int i = 0; i < totalFaces; i += 1 ) { for (int j = 0; j < 3; ++j) { tverts[ i * 3 + j ].x = _softBody->m_faces.at(i).m_n[j]->m_x.x(); tverts[ i * 3 + j ].y = _softBody->m_faces.at(i).m_n[j]->m_x.y(); tverts[ i * 3 + j ].z = _softBody->m_faces.at(i).m_n[j]->m_x.z(); tnormals[ i * 3 + j ].x = _softBody->m_faces.at(i).m_n[j]->m_n.x(); tnormals[ i * 3 + j ].y = _softBody->m_faces.at(i).m_n[j]->m_n.y(); tnormals[ i * 3 + j ].z = _softBody->m_faces.at(i).m_n[j]->m_n.z(); } } } else if( _cachedMesh.getMode() == OF_PRIMITIVE_LINE_STRIP ) { if( tverts.size() != totalNodes ) { tverts.resize( totalNodes ); } for( int i = 0; i < totalNodes; i++ ) { tverts[i].x = _softBody->m_nodes[i].m_x.x(); tverts[i].y = _softBody->m_nodes[i].m_x.y(); tverts[i].z = _softBody->m_nodes[i].m_x.z(); } } _lastMeshUpdateFrame = ofGetFrameNum(); }
void ofxMesh::toMesh(ofMesh & mesh){ mesh.clear(); if (hasVertices()) { mesh.getVertices()=getVertices(); } if (hasColors()) { mesh.getColors()=getColors(); } if (hasNormals()) { mesh.getNormals()=getNormals(); } if (hasTexCoords()) { mesh.getTexCoords()=getTexCoords(); } if (hasIndices()) { mesh.getIndices()=getIndices(); } }
void ofxAlembic::transform(ofMesh &mesh, const ofMatrix4x4 &m) { vector<ofVec3f>& vertices = mesh.getVertices(); for (int i = 0; i < vertices.size(); i++) { vertices[i] = vertices[i] * m; } if (mesh.hasNormals()) { vector<ofVec3f>& normals = mesh.getNormals(); for (int i = 0; i < normals.size(); i++) { const ofVec3f& v = normals[i]; normals[i] = ofVec4f(v.x, v.y, v.z, 0) * m; } } }
void CloudsVisualSystem3DModelLoader::facetMesh( ofMesh& smoothedMesh, ofMesh& targetMesh ) { //get our vertex, uv and face info vector<ofVec3f>& v = smoothedMesh.getVertices(); vector<ofVec2f>& uv = smoothedMesh.getTexCoords(); vector<ofIndexType>& indices = smoothedMesh.getIndices(); bool hasTC = smoothedMesh.getNumTexCoords(); //use these to store our new mesh info vector<ofVec3f> facetedVertices( indices.size() ); vector<ofVec3f> facetedNormals( indices.size() ); vector<ofVec2f> facetedTexCoords; if(hasTC){ facetedTexCoords.resize( indices.size() ); } vector<ofIndexType> facetedIndices( indices.size() ); //store vertex and uv data for (int i=0; i < indices.size(); i++) { facetedIndices[i] = i; facetedVertices[i] = v[indices[i]]; if(hasTC) facetedTexCoords[i] = uv[indices[i]]; } //calculate our face normals ofVec3f n; for (int i=0; i < facetedIndices.size(); i+=3) { n = normalFrom3Points( facetedVertices[i], facetedVertices[i+1], facetedVertices[i+2]); facetedNormals[i] = n; facetedNormals[i+1] = n; facetedNormals[i+2] = n; } //setup our faceted mesh. this should still work if our targetMesh is our smoothMesh targetMesh.clear(); targetMesh.addVertices( facetedVertices ); targetMesh.addNormals( facetedNormals ); if(hasTC) targetMesh.addTexCoords( facetedTexCoords ); targetMesh.addIndices( facetedIndices ); }
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; }