void ofxNDCircularGradient(float radius, const ofColor & start, const ofColor & end) { int n = 32; // circular gradient resolution static ofMesh _nd_cg_mesh; _nd_cg_mesh.clear(); _nd_cg_mesh.setMode(OF_PRIMITIVE_TRIANGLE_FAN); ofVec2f center(0,0); _nd_cg_mesh.addVertex(center); float angleBisector = TWO_PI / (n * 2); float smallRadius = radius; float bigRadius = smallRadius / cos(angleBisector); for(int i = 0; i <= n; i++) { float theta = i * TWO_PI / n; _nd_cg_mesh.addVertex(center + ofVec2f(sin(theta), cos(theta)) * bigRadius); } _nd_cg_mesh.clearColors(); _nd_cg_mesh.addColor(start); for(int i = 0; i <= n; i++) { _nd_cg_mesh.addColor(end); } _nd_cg_mesh.draw(); }
void ofxPolyline::createMesh(ofMesh &mesh, int begin, int end) { if (end - begin == 1) { // If only two points, just make a line. mesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); pair<ofVec2f, ofVec2f> joint = jointBegin((*this)[begin], (*this)[end], width); mesh.addVertex(joint.first); mesh.addVertex(joint.second); joint = jointEnd((*this)[begin], (*this)[end], width); mesh.addVertex(joint.first); mesh.addVertex(joint.second); return; } else if (end - begin == 0) { // Return no mesh return; } // More than two points if (strokeLinejoin == OFXSVG_STROKE_LINEJOIN_MITER) { createMeshMiterJoint(mesh, begin, end); } else if (strokeLinejoin == OFXSVG_STROKE_LINEJOIN_BEVEL) { createMeshBevelJoint(mesh, begin, end); } else if (strokeLinejoin == OFXSVG_STROKE_LINEJOIN_ROUND) { createMeshRoundJoint(mesh, begin, end); } }
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); }
//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 update() { ofVec2f cur(mouseX, mouseY); historyMesh.addVertex(cur); vector<ofVec2f*> neighbors = data.getNeighborsRatio(cur, .1); neighborsMesh.clear(); for(int i = 0; i < neighbors.size(); i++) { neighborsMesh.addVertex(*neighbors[i]); } float minimumDistance = getMinimumDistance(cur, neighbors); if(neighbors.size() == 0 || minimumDistance > 16) { data.add(cur, cur); dataMesh.addVertex(cur); } }
void CloudsVisualSystemLSystem::addBranch(ofMesh &_mesh, int _index, float _relativeTime, float _speed){ int totalPoints = lsysLines[_index].size(); int drawPoints = 0; for (int k = 0 ; k < totalPoints-1; k++){ float thisTime = _speed*(float)k; float nextTime = _speed*((float)k+1.0f); if ( k == totalPoints-1){ nextTime = thisTime; } if (_relativeTime > thisTime && _relativeTime < nextTime ){ float part = _relativeTime - thisTime; float whole = nextTime - thisTime; float pct = part / whole; ofPoint A = lsysLines[ _index ][k]; ofPoint B = lsysLines[ _index ][k+1]; // figure out where we are between a and b // ofPoint pos = (1.0-pct)*A + (pct)*B; dots.push_back(pos); _mesh.addVertex(lsysLines[ _index ][k]); _mesh.addVertex(pos); } else if ( _relativeTime > thisTime ){ ofPoint pos = lsysLines[ _index ][k]; _mesh.addVertex(pos); _mesh.addVertex(lsysLines[_index][k+1]); // check if pass over a node // int index = isNode(pos); if (index != -1){ if ( lsysNodes[index].startTime == -1.0 ){ lsysNodes[index].startTime = time +lsysGrowingBorn*_speed; } } } else { break; } } }
void update() { mesh.clear(); float t = ofGetElapsedTimef() * 0.3; float noise_scale = 0.05; float size = 300; float shape_size = 200; int num = 100; for (int i = 0; i < num; i++) { ofVec3f base(ofSignedNoise(10, 0, 0, i * noise_scale + t), ofSignedNoise(0, 10, 0, i * noise_scale + t), ofSignedNoise(0, 0, 10, i * noise_scale + t)); ofVec3f v0(ofSignedNoise(1, 0, 0, i * noise_scale + t), ofSignedNoise(0, 1, 0, i * noise_scale + t), ofSignedNoise(0, 0, 1, i * noise_scale + t)); ofVec3f v1(ofSignedNoise(2, 0, 0, i * noise_scale + t), ofSignedNoise(0, 2, 0, i * noise_scale + t), ofSignedNoise(0, 0, 2, i * noise_scale + t)); ofVec3f v2(ofSignedNoise(3, 0, 0, i * noise_scale + t), ofSignedNoise(0, 3, 0, i * noise_scale + t), ofSignedNoise(0, 0, 3, i * noise_scale + t)); float hue = ofMap(i, 0, num, 0, 1); ofFloatColor c = ofFloatColor::fromHsb(hue, 1, 1); float s = fabs(sin(i * 0.1 + t)) + 0.1; mesh.addColor(c); mesh.addColor(c); mesh.addColor(c); mesh.addVertex(base * size + v0 * shape_size * s); mesh.addVertex(base * size + v1 * shape_size * s); mesh.addVertex(base * size + v2 * shape_size * s); } IndexColor::convertColorToTexCoord(mesh); // export to abc abc_out.addPolyMesh("/mesh", mesh); }
//http://www.packtpub.com/sites/default/files/9781849518048_Chapter_07.pdf //knotExample void ofApp::addCircle( ofVec3f nextPoint, ofMesh &mesh ){ float time = ofGetElapsedTimef(); //Time //Parameters – twisting and rotating angles and color ofFloatColor color( ofNoise( time * 0.05 ), ofNoise( time * 0.1 ), ofNoise( time * 0.15 )); color.setSaturation( 1.0 ); //Make the color maximally //Add vertices for (int i=0; i<circleN; i++) { float angle = float(i) / circleN * TWO_PI+(PI*0.25); float x = Rad * cos( angle ); float y = Rad * sin( angle ); ofPoint p = nextPoint+ofVec3f(x ,y , 0); mesh.addVertex( p ); mesh.addColor( color ); } //Add the triangles int base = mesh.getNumVertices() - 2 * circleN; if ( base >= 0 ) { //Check if it is not the first step //and we really need to add the triangles for (int i=0; i<circleN; i++) { int a = base + i; int b = base + (i + 1) % circleN; int c = circleN + a; int d = circleN + b; mesh.addTriangle(a,b,d); mesh.addTriangle(a, d, c); } //Update the normals setNormals( mesh ); } }
void CloudsVisualSystemNbody::meshFromFbo(ofFbo& fbo, ofMesh& mesh){ mesh.addTexCoord(ofVec2f(0,0)); mesh.addVertex(ofVec3f(0,0,0)); mesh.addTexCoord(ofVec2f(fbo.getWidth(),0)); mesh.addVertex(ofVec3f(fbo.getWidth(),0,0)); mesh.addTexCoord(ofVec2f(0,fbo.getHeight())); mesh.addVertex(ofVec3f(0,fbo.getHeight(),0)); mesh.addTexCoord(ofVec2f(fbo.getWidth(),fbo.getHeight())); mesh.addVertex(ofVec3f(fbo.getWidth(),fbo.getHeight(),0)); mesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); }
void texturedRect(float width, float height) { if(texturedRectMesh.getNumVertices() == 0) { texturedRectMesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); texturedRectMesh.addTexCoord(ofVec2f(0, 0)); texturedRectMesh.addVertex(ofVec2f(0, 0)); texturedRectMesh.addTexCoord(ofVec2f(0, 1)); texturedRectMesh.addVertex(ofVec2f(0, 1)); texturedRectMesh.addTexCoord(ofVec2f(1, 0)); texturedRectMesh.addVertex(ofVec2f(1, 0)); texturedRectMesh.addTexCoord(ofVec2f(1, 1)); texturedRectMesh.addVertex(ofVec2f(1, 1)); } ofPushMatrix(); ofScale(width, height); texturedRectMesh.drawFaces(); ofPopMatrix(); }
//-------------------------------------------------------------- void testApp::draw(){ fbo.begin(); ofSetTextureWrap(GL_REPEAT,GL_REPEAT); fbfbo.draw(0,2); //cam.draw(0,0); fbfbo.getTextureReference().bind(); trik2.draw(); fbfbo.getTextureReference().unbind(); ofSetColor(255,255,255); if(tritimer>tritimerlimit){ float xpt, ypt,xtoff,ytoff; //draw gradient splashes ofMesh trik; for(int b = 0;b<5;b++){ xtoff = ofRandomf()*0.5; ytoff = ofRandomf()*0.5; for(int i=0;i<3;i++){ xpt = ofRandomuf()*2+xtoff; ypt = ofRandomuf()*2+ytoff; trik.addVertex(ofVec3f(xpt*w,ypt*h,0)); trik.addColor(ofFloatColor(float(ofRandomuf()>0.5)*0.6+0.4,float(ofRandomuf()>0.5)*0.5+0.5,float(ofRandomuf()>0.5)*0.7+0.3)); } } trik.draw(); tritimer = 0; tritimerlimit= ofRandom(20,200); } if(tritimer2>45){ //re-generate the feedback triangles float xpt, ypt,xoff,yoff,xtoff,ytoff; trik2.clear(); //ofEnableNormalizedTexCoords(); for(int b = 0;b<5;b++){ xoff = ofRandomf()*0.1; yoff = ofRandomf()*0.1; xtoff = ofRandomf()*0.5; ytoff = ofRandomf()*0.5; for(int i=0;i<3;i++){ xpt = ofRandomuf()+xtoff; ypt = ofRandomuf()+ytoff; trik2.addVertex(ofVec3f((xpt+xoff)*w,(ypt+yoff)*h,0)); trik2.addTexCoord(ofVec2f(xpt*w,ypt*h)); trik2.addColor(ofFloatColor(1,1,1)); } } tritimer2=0; tritimer2limit= ofRandom(20,200); //ofDisableNormalizedTexCoords(); } fbo.end(); fbfbo.begin(); fbo.draw(0,0); fbfbo.end(); fbo.draw(0,0); }
void Particle::addToMesh(ofMesh & mesh, unsigned long long systemTime) { float pct; switch(state) { case INACTIVE: break; case BORN: mesh.addColor(ofColor(baseColor)); mesh.addVertex(location); break; case FALLING: pct = 1 - ofMap(systemTime - bornTime, BORN_TIMEOUT_MS, FALL_TIMEOUT_MS, 0,1,true); curColor = baseColor * pct; mesh.addColor(curColor); mesh.addVertex(location); break; default: break; } }
void update() { int n = mesh.getNumVertices(); int start = ofMap(mouseX, 0, ofGetWidth(), 0, n, true); controlPoints.clear(); controlPoints.setMode(OF_PRIMITIVE_POINTS); for(int i = start; i < n; i++) { unsigned int index = rankedCorners[i]; controlPoints.addVertex(mesh.getVertex(index)); } }
//-------------------------------------------------------------- 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); }
//-------------------------------------------------------------- ofMesh testApp::pixelManipulate(ofImage imageA, ofMesh meshA, float intensityThreshold, float sketchDepth){ imageA.resize(200, 200); //create mesh with points as the primitive //meshA.setMode(OF_PRIMITIVE_POINTS); //create a mesh with lines meshA.setMode(OF_PRIMITIVE_LINE_LOOP); //meshA.setMode(OF_PRIMITIVE_LINE_STRIP); int w = imageA.getWidth(); int h = imageA.getHeight(); //loop through each pixel in the image using image width & height for (int x=0; x<w; x++){ for(int y=0; y<h; y++){ //create the color object at that pixel //ofColor c = imageA.getColor(x, y); ofColor c = imageA.getColor(x, y); //check the intensity of the pixel's color float intensity = c.getLightness(); //if the intensity exceeds the threshold, create a vertex at the location of the pixel //& color it with the pixel's color if (intensity >= intensityThreshold){ //pushes brighter colors in the positive z direction //pushes whiter colors in the negative z direction float saturation = c.getSaturation(); float z = ofMap(saturation, 0, 255, -sketchDepth, sketchDepth); //the image is now 1/4 the size of the OF window, so multiply //the pixel location by 4 so that the mesh covers the OF window ofVec3f pos(5*x, 4*y, z); meshA.addVertex(pos); meshA.addColor(c); } } } return meshA; }
void CloudsVisualSystemTunnelDrawing::drawRibbonTrail(const RibbonTrail& trail, ofMesh& geo){ for(int i = 1; i < trail.points.size(); i++){ //find this point and the next point ofVec3f thisPoint = trail.points[i-1]; ofVec3f nextPoint = trail.points[i]; //get the direction from one to the next. //the ribbon should fan out from this direction ofVec3f direction = (nextPoint - thisPoint); //direction.z = 0; //get the distance from one point to the next float distance = direction.length(); //get the normalized direction. normalized vectors always have a length of one //and are really useful for representing directions as opposed to something with length ofVec3f unitDirection = direction.normalized(); //find both directions to the left and to the right ofVec3f toTheLeft = unitDirection.getRotated(-90, ofVec3f(0,0,1)); ofVec3f toTheRight = unitDirection.getRotated(90, ofVec3f(0,0,1)); //use the map function to determine the distance. //the longer the distance, the narrower the line. //this makes it look a bit like brush strokes float thickness = ofMap(distance, distanceRange.min, distanceRange.max, thicknessRange.max, thicknessRange.min, true); //calculate the points to the left and to the right //by extending the current point in the direction of left/right by the length ofVec3f leftPoint = thisPoint + toTheLeft * thickness; ofVec3f rightPoint = thisPoint + toTheRight * thickness; if(i == 1){ geo.addColor(ofFloatColor(0,0,0,0)); geo.addVertex(ofVec3f(leftPoint.x, leftPoint.y, leftPoint.z)); geo.addColor(ofFloatColor(0,0,0,0)); geo.addVertex(ofVec3f(rightPoint.x, rightPoint.y, rightPoint.z)); } //add these points to the triangle strip geo.addColor(ofFloatColor::white); geo.addVertex(ofVec3f(leftPoint.x, leftPoint.y, leftPoint.z)); geo.addColor(ofFloatColor::white); geo.addVertex(ofVec3f(rightPoint.x, rightPoint.y, rightPoint.z)); if( i == trail.points.size()-1 ){ geo.addColor(ofFloatColor(0,0,0,0)); geo.addVertex(ofVec3f(leftPoint.x, leftPoint.y, leftPoint.z)); geo.addColor(ofFloatColor(0,0,0,0)); geo.addVertex(ofVec3f(rightPoint.x, rightPoint.y, rightPoint.z)); } } }
//-------------------------------------------------------------- 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 TextWriter::addGlyphToMesh(Letter &letter, ofRectangle box, ofMesh& mesh) { //float randomness = 0.05; for( int i = 0; i < letter.points.size(); i++ ) { ofVec3f v; v.x = box.x + ofMap(letter.points[i].x + ofRandom(-lineRandomness, lineRandomness), 0, glyphWidth, 0, box.width); v.y = box.y + ofMap(letter.points[i].y + ofRandom(-lineRandomness, lineRandomness), 0, glyphHeight, 0, box.height); mesh.addVertex(v); ofColor vcolor(colour); vcolor.setBrightness(vcolor.getBrightness() * ofRandom(colourFlickerMin, 1)); mesh.addColor(vcolor); } }
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 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 Helix::generateVertices(std::deque<ofVec3f>& spine, ofMesh& vertices) { vertices.clear(); std::vector<ofVec3f> points; for(int i = 1; i < spine.size(); ++i) { ofVec3f& a0 = spine[i-1]; ofVec3f& a2 = spine[i]; ofVec3f t = a2 - a0; ofVec3f c(0.0f, a0.y, 0.0f); // <-- we could use one spine in the center and swirl around that ofVec3f perp = a0 - c; perp.normalize(); perp *= ribbon_thickness; ofVec3f diry = perp.getCrossed(t); //cross(perp, t); diry.normalize(); diry *= ribbon_height; points.push_back((a0 - perp) - diry); points.push_back((a0 + perp) - diry); points.push_back((a2 + perp) + diry); points.push_back((a2 - perp) + diry); } int num_slices = points.size() / 4; for(int i = 0; i < num_slices - 1; ++i) { int dx = i * 4; ofVec3f& a0 = points[dx + 0]; ofVec3f& a3 = points[dx + 3]; ofVec3f& a4 = points[dx + 4]; vertices.addVertex(a0); vertices.addVertex(a3); } }
//--------------------------------------------------------- void ofxPolyline::createMeshMiterJoint(ofMesh &mesh, int begin, int end) { mesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); // Starting point pair<ofVec2f, ofVec2f> joint = jointBegin((*this)[begin], (*this)[begin+1], width); mesh.addVertex(joint.first); mesh.addVertex(joint.second); // Between both ends for (int i=begin+1; i<end-1; i++) { joint = miterJoint((*this)[i-1], (*this)[i], (*this)[i+1], width); mesh.addVertex(joint.first); mesh.addVertex(joint.second); } // End point joint = jointEnd((*this)[end-1], (*this)[end], width); mesh.addVertex(joint.first); mesh.addVertex(joint.second); }
void addFace(ofMesh& mesh, ofVec3f a, ofVec3f b, ofVec3f c) { mesh.addVertex(a); mesh.addVertex(b); mesh.addVertex(c); }
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::createSegmentedMeshTriangles(const ofVec3f& center, ofMesh &mesh, double radius, double limitH, int textWidth, int textHeight) //using triangles only { int h, drawH, drawW, w; int divNumber = 32; double theta, phi, phi_1, limitW; ofVec3f 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; } mesh.setMode(OF_PRIMITIVE_TRIANGLES); //limitH = 3.14 / (double) hDivNumber; limitW = limitH * (textWidth/(double)textHeight); drawH = textHeight / divNumber; drawW = textWidth / divNumber; for(h = 0; h < drawH; h++) //create the mesh { phi = (((h * divNumber) * limitH)/(double) textHeight) + (1.57079632679 - (limitH/ (double )2)); //phi_1 = (((h+1) * limitH)/(double) textHeight) + (1.57079632679 - (limitH/ (double )2)); for(w = 1; w <= drawW; w++) //count forward { theta = (limitW * (w * divNumber)) / (double) textWidth + (1.57079632679 - (limitW/ (double )2)); p.x = radius*cos(theta)*sin(phi); p.y = radius* sin(theta)*sin(phi); p.z = radius*cos(phi); /*p.x = w; p.y = 2; p.z = h;*/ mesh.addTexCoord(ofVec2f((w*divNumber), (h*divNumber))); mesh.addVertex(p); } } /*for (int y = 0; y<drawH; y = y+1){ for (int x=0; x<drawW; x = x + 1){ const ofIndexType texIndex = static_cast<ofIndexType>(x + y*drawW); mesh.setTexCoord(texIndex, ofVec2f((w*divNumber), (h*divNumber))); } }*/ //mesh.clearIndices(); for (int y = 0; y<drawH-1; y = y+1){ for (int x=0; x<drawW-1; x++){ mesh.addIndex(x+y*drawW); // 0 mesh.addIndex(x+(y+1)*drawW); // 10 mesh.addIndex((x+1)+(y+1)*drawW); // 11 // mesh.addIndex(x); // 0 //mesh.addIndex(x+drawW); // 10 //mesh.addIndex((x+1)+drawW); // 11 mesh.addIndex((x+1)+y*drawW); // 1 mesh.addIndex(x+y*drawW); // 0 mesh.addIndex((x+1)+(y+1)*drawW); // 11 } } }
/* Old, beta function, use the triangle funtion now */ void ofApp::createSegmentedMeshMine(const ofVec3f& center, ofMesh &mesh, double radius, int textWidth, int textHeight) { //uses triangle strips int h, hTemp, w; double theta, phi, phi_1, limitH, limitW; ofVec3f 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; } //mesh.setupIndicesAuto(); textWidth = textWidth / 4; textHeight = textHeight / 4; mesh.setMode( OF_PRIMITIVE_TRIANGLE_STRIP); limitH = 3.14 / (double) 3; limitW = limitH * (textWidth/(double)textHeight); for(hTemp = 0; hTemp < textHeight-1; hTemp = hTemp+2) { h = hTemp; //phi = (h * 3.141)/(double) textHeight; //phi_1 = ((h+1) * 3.141)/(double) textHeight; phi = ((h * limitH)/(double) textHeight) + (1.57079632679 - (limitH/ (double )2)); phi_1 = (((h+1) * limitH)/(double) textHeight) + (1.57079632679 - (limitH/ (double )2)); for(w = 0; w <= textWidth; w++) //count forward { theta = (limitW * w) / (double) textWidth + (1.57079632679 - (limitW/ (double )2)); // p.x = radius * cos(theta); //p.y = h; //p.z = radius * sin(theta); p.x = radius*cos(theta)*sin(phi); p.y = radius* sin(theta)*sin(phi); p.z = radius*cos(phi); mesh.addTexCoord(ofVec2f(4*w, 4*h)); mesh.addVertex(p); //p.x = radius *cos(theta); //p.y = h+1; //p.z = radius * sin(theta); p.x = radius*cos(theta)*sin(phi_1); p.y = radius* sin(theta)*sin(phi_1); p.z = radius*cos(phi_1); mesh.addTexCoord(ofVec2f(4*w, (4*h)+1)); mesh.addVertex(p); } h = hTemp+1; phi = ((h * limitH)/(double) textHeight) + (1.57079632679 - (limitH/ (double )2)); phi_1 = (((h+1) * limitH)/(double) textHeight) + (1.57079632679 - (limitH/ (double )2)); for(w = textWidth; w>=0; w--) //count backwards { theta = (limitW * w) / (double) textWidth + (1.57079632679 - (limitW/ (double )2)); p.x = radius*cos(theta)*sin(phi); p.y = radius* sin(theta)*sin(phi); p.z = radius*cos(phi); mesh.addTexCoord(ofVec2f(w, h)); mesh.addVertex(p); p.x = radius*cos(theta)*sin(phi_1); p.y = radius* sin(theta)*sin(phi_1); p.z = radius*cos(phi_1); mesh.addTexCoord(ofVec2f(w, h+1)); mesh.addVertex(p); } } }
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); } } }