//-------------------------------------------------------------- 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 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 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 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 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; } } }
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 save(const string& path, const ofMesh& mesh) { ofFile file(path, ofFile::WriteOnly, true); int numVerts = mesh.getNumVertices(); file.write((char *)(&numVerts), sizeof(int)); if (numVerts > 0) { file.write((char *)(&(mesh.getVertices())[0]), sizeof(ofPoint) * numVerts); } int numNormals = mesh.getNumNormals(); file.write((char *)(&numNormals), sizeof(int)); if (numNormals > 0) { file.write((char *)(&(mesh.getNormals())[0]), sizeof(ofPoint) * numNormals); } int numTexCoords = mesh.getNumTexCoords(); file.write((char *)(&numTexCoords), sizeof(int)); if (numTexCoords > 0) { file.write((char *)(&(mesh.getTexCoords())[0]), sizeof(ofVec2f) * numTexCoords); } int numColors = mesh.getNumColors(); file.write((char *)(&numColors), sizeof(int)); if (numColors > 0) { file.write((char *)(&(mesh.getColors())[0]), sizeof(ofFloatColor) * numColors); } int numIndices = mesh.getNumIndices(); file.write((char *)(&numIndices), sizeof(int)); if (numIndices > 0) { file.write((char *)(&(mesh.getIndices())[0]), sizeof(ofIndexType) * numIndices); } file.close(); }
//-------------------------------------------------------------- void ofxBulletPatch::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( (getResolutionX()-1) * (getResolutionY()-1) * 6 ); } auto& tnormals = aMesh.getNormals(); if( tnormals.size() != tverts.size() ) { tnormals.resize( tverts.size() ); } ofVec3f p1, p2, p3, p4; ofVec3f n1, n2, n3, n4; int ti = 0; for( int iy = 0; iy < getResolutionY()-1; iy++ ) { for( int ix = 0; ix < getResolutionX()-1; ix++ ) { int ni = iy * getResolutionX() + ix; p1.set( _softBody->m_nodes[ni].m_x.x(), _softBody->m_nodes[ni].m_x.y(), _softBody->m_nodes[ni].m_x.z() ); n1.set( _softBody->m_nodes[ni].m_n.x(), _softBody->m_nodes[ni].m_n.y(), _softBody->m_nodes[ni].m_n.z() ); ni = (iy+1) * getResolutionX() + ix; p2.set( _softBody->m_nodes[ni].m_x.x(), _softBody->m_nodes[ni].m_x.y(), _softBody->m_nodes[ni].m_x.z() ); n2.set( _softBody->m_nodes[ni].m_n.x(), _softBody->m_nodes[ni].m_n.y(), _softBody->m_nodes[ni].m_n.z() ); ni = (iy+1) * getResolutionX() + ix+1; p3.set( _softBody->m_nodes[ni].m_x.x(), _softBody->m_nodes[ni].m_x.y(), _softBody->m_nodes[ni].m_x.z() ); n3.set( _softBody->m_nodes[ni].m_n.x(), _softBody->m_nodes[ni].m_n.y(), _softBody->m_nodes[ni].m_n.z() ); ni = (iy) * getResolutionX() + ix+1; p4.set( _softBody->m_nodes[ni].m_x.x(), _softBody->m_nodes[ni].m_x.y(), _softBody->m_nodes[ni].m_x.z() ); n4.set( _softBody->m_nodes[ni].m_n.x(), _softBody->m_nodes[ni].m_n.y(), _softBody->m_nodes[ni].m_n.z() ); tverts[ti] = p1; tnormals[ti] = n1; ti += 1; // ni = (iy+1) * getResolutionX() + ix; tverts[ti] = p2; tnormals[ti] = n2; ti += 1; // ni = (iy+1) * getResolutionX() + ix+1; tverts[ti] = p3; tnormals[ti] = n3; ti += 1; // // ni = (iy+1) * getResolutionX() + ix+1; tverts[ti] = p3; tnormals[ti] = n3; ti += 1; // ni = (iy) * getResolutionX() + ix+1; tverts[ti] = p4; tnormals[ti] = n4; ti += 1; // ni = (iy) * getResolutionX() + ix; tverts[ti] = p1; tnormals[ti] = n1; ti += 1; } } } _lastMeshUpdateFrame = ofGetFrameNum(); }
vector<float> Model::generateTangents(ofMesh& mesh) { // Tangent generation adapted from algorithm at http://www.terathon.com/code/tangent.html auto vertices = mesh.getVertices(); auto normals = mesh.getNormals(); auto texcoords = mesh.getTexCoords(); auto triangles = mesh.getIndices(); vector<float> tangents(vertices.size()*4); vector<ofVec3f> tan1(vertices.size(), ofVec3f(0,0,0)); vector<ofVec3f> tan2(vertices.size(), ofVec3f(0,0,0)); for (unsigned int i = 0; i < triangles.size(); i += 3) { long i1 = triangles[i]; long i2 = triangles[i+1]; long i3 = triangles[i+2]; const ofVec3f& v1 = vertices[i1]; const ofVec3f& v2 = vertices[i2]; const ofVec3f& v3 = vertices[i3]; const ofVec2f& w1 = texcoords[i1]; const ofVec2f& w2 = texcoords[i2]; const ofVec2f& w3 = texcoords[i3]; float x1 = v2.x - v1.x; float x2 = v3.x - v1.x; float y1 = v2.y - v1.y; float y2 = v3.y - v1.y; float z1 = v2.z - v1.z; float z2 = v3.z - v1.z; float s1 = w2.x - w1.x; float s2 = w3.x - w1.x; float t1 = w2.y - w1.y; float t2 = w3.y - w1.y; float r = 1.0F / (s1 * t2 - s2 * t1); ofVec3f sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); ofVec3f tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); tan1[i1] += sdir; tan1[i2] += sdir; tan1[i3] += sdir; tan2[i1] += tdir; tan2[i2] += tdir; tan2[i3] += tdir; } for (unsigned int i = 0; i < vertices.size(); ++i) { ofVec3f& n = normals[i]; ofVec3f& t = tan1[i]; // Gram-Schmidt orthogonalize auto tangent = (t - n * n.dot(t)).normalize(); // Calculate handedness float w = (n.cross(t).dot(tan2[i]) < 0.0) ? -1.0 : 1.0; tangents[i*4] = tangent.x; tangents[i*4+1] = tangent.y; tangents[i*4+2] = tangent.z; tangents[i*4+3] = w; } return tangents; }