//Some helper functions //-------------------------------------------------------------- void Page::addFace(ofMesh& mesh, ofPoint a, ofPoint b, ofPoint c) { ofVec3f normal = ((b - a).cross(c - a)).normalize(); mesh.addNormal(normal); mesh.addVertex(a); mesh.addNormal(normal); mesh.addVertex(b); mesh.addNormal(normal); mesh.addVertex(c); }
void addFace(ofMesh& mesh, ofVec3f a, ofVec3f b, ofVec3f c) { ofVec3f normal = ((b - a).cross(c - a)).normalize(); mesh.addNormal(normal); mesh.addVertex(a); mesh.addNormal(normal); mesh.addVertex(b); mesh.addNormal(normal); mesh.addVertex(c); }
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); } } }
//-------------------------------------------------------------- void addFace(ofMesh& mesh, ofVec3f a, ofFloatColor aC, ofVec3f b, ofFloatColor bC, ofVec3f c, ofFloatColor cC) { ofVec3f normal = ((b - a).cross(c - a)).normalize() * -1.0; mesh.addNormal(normal); mesh.addColor(aC); mesh.addVertex(a); mesh.addNormal(normal); mesh.addColor(bC); mesh.addVertex(b); mesh.addNormal(normal); mesh.addColor(cC); mesh.addVertex(c); }
OFX_OBJLOADER_BEGIN_NAMESPACE void load(string path, ofMesh& mesh, bool generateNormals, bool flipFace) { path = ofToDataPath(path); mesh.clear(); GLMmodel* m; m = glmReadOBJ((char*)path.c_str()); if (generateNormals) { glmFacetNormals(m); glmVertexNormals(m, 90); } if (flipFace) { glmReverseWinding(m); } for (int j = 0; j < m->numtriangles; j++) { const GLMtriangle &tri = m->triangles[j]; for (int k = 0; k < 3; k++) { GLfloat *v = m->vertices + (tri.vindices[k] * 3); mesh.addVertex(ofVec3f(v[0], v[1], v[2])); if (m->colors) { GLfloat *c = m->colors + (tri.vindices[k] * 3); mesh.addColor(ofFloatColor(c[0], c[1], c[2])); } if (m->normals && ofInRange(tri.nindices[k], 0, m->numnormals)) { GLfloat *n = m->normals + (tri.nindices[k] * 3); mesh.addNormal(ofVec3f(n[0], n[1], n[2])); } if (m->texcoords && ofInRange(tri.tindices[k], 0, m->numtexcoords)) { GLfloat *c = m->texcoords + (tri.tindices[k] * 2); mesh.addTexCoord(ofVec2f(c[0], c[1])); } } } glmDelete(m); }
//---------------------------------------- void ofGenerateSphereMesh( ofMesh& _mesh, float _radius, int _numRings, int _numSegments ){ cout << "*** ofGenerateSphereMesh ***" << endl; _mesh.clear(); float uTile = 1.0f; // Texcoord tiling, do we want to support that? float vTile = 1.0f; float fDeltaRingAngle = (PI / _numRings); float fDeltaSegAngle = (TWO_PI / _numSegments); int offset = 0; // Generate the group of rings for the sphere for(unsigned int ring = 0; ring <= _numRings; ring++ ) { float r0 = _radius * sinf (ring * fDeltaRingAngle); float y0 = _radius * cosf (ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(unsigned int seg = 0; seg <= _numSegments; seg++) { float x0 = r0 * sinf(seg * fDeltaSegAngle); float z0 = r0 * cosf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere ofVec3f pos(x0, y0, z0); _mesh.addVertex( pos ); _mesh.addNormal( pos.getNormalized() ); if( ofGetPrimitiveGenerateTexCoords() ){ //for (unsigned int tc=0;tc<numTexCoordSet;tc++) _mesh.addTexCoord( ofVec2f( (float) seg / (float)_numSegments * uTile, (float) ring / (float)_numRings * vTile ) ); } if (ring != _numRings) { // each vertex (except the last) has six indices pointing to it _mesh.addIndex(offset + _numSegments); _mesh.addIndex(offset); _mesh.addIndex(offset + _numSegments + 1); _mesh.addIndex(offset); _mesh.addIndex(offset + 1); _mesh.addIndex(offset + _numSegments + 1); offset ++; } }; // end for seg } // end for ring }
/** * Add a quad to the mesh with clockwise front face vertex order */ void addQuad(ofVec3f const & bottomLeft, ofVec3f const & topLeft, ofVec3f const & topRight, ofVec3f const & bottomRight) { mesh.enableNormals(); vbo.enableNormals(); ofVec3f v1 = topLeft; ofVec3f v2 = topRight; ofVec3f v3 = bottomRight; ofVec3f v4 = bottomLeft; ofVec3f v1N, v2N, v3N, v4N; v1N = crossProd(v1,v2,v3); v3N = crossProd(v3,v4,v1); v2N = crossProd(v2,v1,v4); v4N = crossProd(v4,v3,v2); mesh.addVertex(v4); mesh.addNormal(v4N); mesh.addVertex(v1); mesh.addNormal(v1N); mesh.addVertex(v2); mesh.addNormal(v2N); mesh.addVertex(v3); mesh.addNormal(v3N); }
//-------------------------------------------------------------- static void aiMeshToOfMesh(const aiMesh* aim, ofMesh& ofm, ofxAssimpMeshHelper * helper = NULL){ // default to triangle mode ofm.setMode(OF_PRIMITIVE_TRIANGLES); // copy vertices for (int i=0; i < (int)aim->mNumVertices;i++){ ofm.addVertex(ofVec3f(aim->mVertices[i].x,aim->mVertices[i].y,aim->mVertices[i].z)); } if(aim->HasNormals()){ for (int i=0; i < (int)aim->mNumVertices;i++){ ofm.addNormal(ofVec3f(aim->mNormals[i].x,aim->mNormals[i].y,aim->mNormals[i].z)); } } // aiVector3D * mTextureCoords [AI_MAX_NUMBER_OF_TEXTURECOORDS] // just one for now if(aim->GetNumUVChannels()>0){ for (int i=0; i < (int)aim->mNumVertices;i++){ if( helper != NULL && helper->texture.getWidth() > 0.0 ){ ofVec2f texCoord = helper->texture.getCoordFromPercent(aim->mTextureCoords[0][i].x ,aim->mTextureCoords[0][i].y); ofm.addTexCoord(texCoord); }else{ ofm.addTexCoord(ofVec2f(aim->mTextureCoords[0][i].x ,aim->mTextureCoords[0][i].y)); } } } //aiColor4D * mColors [AI_MAX_NUMBER_OF_COLOR_SETS] // just one for now if(aim->GetNumColorChannels()>0){ for (int i=0; i < (int)aim->mNumVertices;i++){ ofm.addColor(aiColorToOfColor(aim->mColors[0][i])); } } for (int i=0; i <(int) aim->mNumFaces;i++){ if(aim->mFaces[i].mNumIndices>3){ ofLog(OF_LOG_WARNING,"non-triangular face found: model face # " + ofToString(i)); } for (int j=0; j<(int)aim->mFaces[i].mNumIndices; j++){ ofm.addIndex(aim->mFaces[i].mIndices[j]); } } ofm.setName(string(aim->mName.data)); // ofm.materialId = aim->mMaterialIndex; }
void ofxObjLoader::load(string path, ofMesh& mesh, bool generateNormals) { path = ofToDataPath(path); mesh.clear(); GLMmodel* m; m = glmReadOBJ((char*)path.c_str()); if(generateNormals){ glmFacetNormals(m); glmVertexNormals(m, 90); } GLfloat *v, *n, *c; for(int i = 1; i <= m->numvertices; i++){ v = &m->vertices[3 * i]; mesh.addVertex(ofVec3f(v[0], v[1], v[2])); } for(int i = 1; i <= m->numnormals; i++){ n = &m->normals[3 * i]; mesh.addNormal(ofVec3f(n[0], n[1], n[2])); } for(int i = 1; i <= m->numtexcoords; i++){ c = &m->texcoords[2 * i]; mesh.addTexCoord(ofVec2f(c[0], c[1])); } for (int i = 0; i < m->numtriangles; i++) { GLMtriangle &t = m->triangles[i]; //NOTE: ofMesh does not have support for different indices for tex coords and mormals mesh.addIndex(t.vindices[0]); mesh.addIndex(t.vindices[1]); mesh.addIndex(t.vindices[2]); } glmDelete(m); return mesh; }
void ofxLSTriangle::generate(ofMesh& mesh, const ofxLSBranch branch, const float length){ //if you set offsetBetweenBranches to 0, all the triangles composing // the branch will start exactly where the previous one finish, // to make them look a bit more intricates, I've overlapped them a bit const int offsetBetweenBranches = 10; const int radius = branch.capSizes.first; const int scaledRadius = branch.capSizes.second; const float stepLenght = length; ofMatrix4x4 beginMatrix = branch.begin.getGlobalTransformMatrix(); ofMatrix4x4 endMatrix = branch.end.getGlobalTransformMatrix(); vector<ofVec3f> topValues; vector<ofVec3f> bottomValues; // create top and bottom points for (int i = 0; i < resolution; i++){ float theta = 2.0f * 3.1415926f * float(i) / float(resolution); float x = radius * cosf(theta); float z = radius * sinf(theta); float y = 0; ofVec3f circleBottom = ofVec3f(x, y-offsetBetweenBranches, z); bottomValues.push_back(circleBottom); float topX = scaledRadius * cosf(theta); float topZ = scaledRadius * sinf(theta); float topY = 0; ofVec3f circleTop = ofVec3f(topX, topY+offsetBetweenBranches, topZ); topValues.push_back(circleTop); } //random shuffle them random_shuffle(topValues.begin(), topValues.end()); random_shuffle(bottomValues.begin(), bottomValues.end()); int n_triangles = resolution; int firstIndex = mesh.getNumVertices(); float middleLength = stepLenght /2; for (unsigned int i = 0; i< (n_triangles*3); i += 3) { ofVec3f firstV = topValues.at(i/3); ofVec3f thirdV = bottomValues.at(i/3); ofVec3f secondV = bottomValues.at(i/3); //secondV.z = ofRandom(-scaledRadius, radius); secondV.y = ofRandom(middleLength -radius*2, middleLength + radius*2); mesh.addIndex(firstIndex +i); mesh.addIndex(firstIndex +i+1); mesh.addIndex(firstIndex +i+2); //find position AND direction of 2 vertices of the triangle; ofVec3f e1 = firstV - secondV; ofVec3f e2 = thirdV - secondV; //Use these 2 vertices to find the normal ofVec3f no = e2.cross( e1 ).normalize(); mesh.addVertex(firstV * endMatrix); mesh.addNormal(no); mesh.addVertex(secondV * (beginMatrix)); mesh.addNormal(no); mesh.addVertex(thirdV * beginMatrix); mesh.addNormal(no); } }
void ofApp::createSegmentedMesh(const ofVec3f& center, ofMesh &mesh, double radius, int precision, int textWidth, int textHeight, double theta1, double theta2, double phi1, double phi2) { /* original funtion used as inspiration Create a sphere centered at c, with radius r, and precision n Draw a point for zero radius spheres Use CCW facet ordering Partial spheres can be created using theta1->theta2, phi1->phi2 in radians 0 < theta < 2pi, -pi/2 < phi < pi/2 */ int i,j; double t1,t2,t3; ofVec3f e,p; mesh.clear(); /* Handle special cases */ if (radius < 0) radius = -radius; if (precision < 0) precision = -precision; if (precision < 4 || radius <= 0) { mesh.addVertex(center); return; } for (j=0;j<precision/2;j++) { t1 = phi1 + j * (phi2 - phi1) / (precision/2); t2 = phi1 + (j + 1) * (phi2 - phi1) / (precision/2); mesh.setMode(OF_PRIMITIVE_POINTS ); //mesh.setMode( OF_PRIMITIVE_LINE_STRIP); for (i=0;i<=precision;i++) { t3 = theta1 + i * (theta2 - theta1) / precision; e.x = cos(t1) * cos(t3); e.y = sin(t1); e.z = cos(t1) * sin(t3); p.x = center.x + radius * e.x; p.y = center.y + radius * e.y; p.z = center.z + radius * e.z; mesh.addNormal(e); mesh.addTexCoord(ofVec2f( (i/(double)precision) * textWidth, textHeight - (2*j/(double)precision) * textHeight)); mesh.addVertex(p); e.x = cos(t2) * cos(t3); e.y = sin(t2); e.z = cos(t2) * sin(t3); p.x = center.x + radius * e.x; p.y = center.y + radius * e.y; p.z = center.z + radius * e.z; mesh.addNormal(e); mesh.addTexCoord(ofVec2f( (i/(double)precision) * textWidth, textHeight - (2*(j+1)/(double)precision) * textHeight)); mesh.addVertex(p); } } }
void ofxPolyvox::polyvoxToOfMesh(const PolyVox::SurfaceMesh<PositionMaterialNormal>& surfaceMesh, ofMesh& polyvxToOfMesh, bool setColor){ //Convienient access to the vertices and indices const vector<uint32_t>& vecIndices = surfaceMesh.getIndices(); const vector<PositionMaterialNormal>& vecVertices = surfaceMesh.getVertices();//surfaceMesh.getRawVertexData(); ofIndexType ofVecIndices; const void* pIndices = static_cast<const void*>(&(vecIndices[0])); int* indices = (int*)pIndices; vector<int> indx; for (int i = 0; i < surfaceMesh.getNoOfIndices(); i++ ){ indx.push_back(indices[i]); //cout << "indices:" << indices[i] << endl; polyvxToOfMesh.addIndex(indx[i]); } ofLog(OF_LOG_NOTICE, "ofMesh: number of indices is %d", polyvxToOfMesh.getNumIndices()); ofVec3f ofVecVertices; for (int i = 0; i < surfaceMesh.getNoOfVertices(); i++ ){ PositionMaterialNormal vert0 = vecVertices[i]; ofVecVertices = ofVec3f(vert0.getPosition().getX(),vert0.getPosition().getY(),vert0.getPosition().getZ()); polyvxToOfMesh.addVertex(ofVecVertices); } ofLog(OF_LOG_NOTICE, "ofMesh: number of vertices is %d", polyvxToOfMesh.getNumVertices()); ofVec3f ofVecNormals; for (int i = 0; i < surfaceMesh.getNoOfVertices(); i++ ){ PositionMaterialNormal vert0 = vecVertices[i]; ofVecNormals = ofVec3f(vert0.getNormal().getX(),vert0.getNormal().getY(),vert0.getNormal().getZ()); polyvxToOfMesh.addNormal(ofVecNormals); } ofLog(OF_LOG_NOTICE, "ofMesh: number of normals is %d", polyvxToOfMesh.getNumNormals()); if(setColor){ for (int i = 0; i < surfaceMesh.getNoOfVertices(); i++ ){ PositionMaterialNormal vert0 = vecVertices[i]; uint8_t material = static_cast<uint8_t>(vert0.getMaterial() + 0.5); //cout << "material:" << int(material) << endl; ofFloatColor colour = convertMaterialIDToColour(material); //cout << colour << endl; polyvxToOfMesh.addColor(colour); bool col = polyvxToOfMesh.hasColors(); //cout << "hasColors:" << col << endl; } } }
//from ofSetSphereResolution void testApp::buildSphereMesh(int radius, int res, ofMesh & sphereMesh) { int n = res * 2; float ndiv2=(float)n/2; /* Original code by Paul Bourke A more efficient contribution by Federico Dosil (below) Draw a point for zero radius spheres Use CCW facet ordering http://paulbourke.net/texture_colour/texturemap/ */ float theta2 = TWO_PI; float phi1 = -HALF_PI; float phi2 = HALF_PI; // float r = 1.f; // normalize the verts float r = radius; sphereMesh.clear(); //sphereMesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); int i, j; float theta1 = 0.f; float jdivn,j1divn,idivn,dosdivn,unodivn=1/(float)n,t1,t2,t3,cost1,cost2,cte1,cte3; cte3 = (theta2-theta1)/n; cte1 = (phi2-phi1)/ndiv2; dosdivn = 2*unodivn; ofVec3f e,p,e2,p2; if (n < 0){ n = -n; ndiv2 = -ndiv2; } if (n < 4) {n = 4; ndiv2=(float)n/2;} if(r <= 0) r = -r; t2=phi1; cost2=cos(phi1); j1divn=0; ofVec3f vert, normal; ofVec2f tcoord; for (j=0;j<ndiv2;j++) { t1 = t2; t2 += cte1; t3 = theta1 - cte3; cost1 = cost2; cost2 = cos(t2); e.y = sin(t1); e2.y = sin(t2); p.y = r * e.y; p2.y = r * e2.y; idivn=0; jdivn=j1divn; j1divn+=dosdivn; for (i=0;i<=n;i++) { t3 += cte3; e.x = cost1 * cos(t3); e.z = cost1 * sin(t3); p.x = r * e.x; p.z = r * e.z; normal.set( e.x, e.y, e.z ); tcoord.set( idivn, jdivn); vert.set( p.x, p.y, p.z ); sphereMesh.addNormal(normal); sphereMesh.addTexCoord(tcoord); sphereMesh.addVertex(vert); e2.x = cost2 * cos(t3); e2.z = cost2 * sin(t3); p2.x = r * e2.x; p2.z = r * e2.z; normal.set(e2.x, e2.y, e2.z); tcoord.set(idivn, j1divn); vert.set(p2.x, p2.y, p2.z); sphereMesh.addNormal(normal); sphereMesh.addTexCoord(tcoord); sphereMesh.addVertex(vert); idivn += unodivn; } } }
void BGGraphics::pushVertex(ofMesh & mesh, float x, float y, float z, float nx, float ny, float nz, float offsetX, float offsetY) { mesh.addVertex(ofVec3f(x, y, z)); mesh.addNormal(ofVec3f(nx, ny, nz)); mesh.addTexCoord(ofVec2f(offsetX, offsetY)); mesh.addColor(ofFloatColor(255, 255, 255)); }