void form::setIndex(msa::physics::Particle3D *_p, ofPolyline &_master, ofPolyline &_slave, int _ind) { unsigned int mind = 0; unsigned int sind = 0; ofPoint mcpt = _master.getClosestPoint(_p->getPosition(), &mind); ofPoint scpt = _slave.getClosestPoint(_p->getPosition(), &sind); float mdist = mcpt.distance(_p->getPosition()); float sdist = scpt.distance(_p->getPosition()); //if (mdist < sdist) { if (mdist < mTol) { mMasterEdgeParticles.push_back(new part_and_index(_p,mind, _ind)); } //} else { if (sdist < mTol) { mSlaveEdgeParticles.push_back(new part_and_index(_p,sind, _ind)); } //} }
//============================================================ void HandMeshBuilder::buildMesh (ofPolyline &handContour, ofVec3f &handCentroid, Handmark *hmarks){ // Check to make sure the contour contains data int nContourPoints = handContour.size(); if (nContourPoints > 0){ // Check to make sure all indices are legal bool bAllHandmarkIndicesValid = true; for (int i=0; i<N_HANDMARKS; i++){ Handmarks[i] = hmarks[i]; if ((Handmarks[i].index < 0) || (Handmarks[i].index >= nContourPoints)){ bAllHandmarkIndicesValid = false; printf ("problem with handmark %d: %d\n", i, Handmarks[i].index); } } if (bAllHandmarkIndicesValid){ handMesh.clear(); handMesh.setupIndicesAuto(); handMesh.setMode( OF_PRIMITIVE_TRIANGLES ); // Add triangles for each finger to handMesh: for (int f=0; f<5; f++){ int f0 = (fingerTipIndices[f] - 1 + N_HANDMARKS) % N_HANDMARKS; int f1 = (fingerTipIndices[f] + N_HANDMARKS) % N_HANDMARKS; int f2 = (fingerTipIndices[f] + 1 + N_HANDMARKS) % N_HANDMARKS; int contourIndex0 = Handmarks[f0].index; int contourIndex1 = Handmarks[f1].index; int contourIndex2 = Handmarks[f2].index; // Collect the first side of the finger, from contourIndex0 up to contourIndex1 ofPolyline poly01; poly01.clear(); int contourIndex1a = contourIndex1; if (contourIndex1a < contourIndex0) { contourIndex1a += nContourPoints; } for (int i=contourIndex0; i<=contourIndex1a; i++){ int indexSafe = (i+nContourPoints)%nContourPoints; ofVec3f pointi = handContour[indexSafe]; poly01.addVertex(pointi.x, pointi.y, pointi.z); } // Collect the reverse side of the finger, from contourIndex2 down to contourIndex1 ofPolyline poly21; poly21.clear(); int contourIndex1b = contourIndex1; if (contourIndex1b > contourIndex2) { contourIndex2 += nContourPoints; } for (int i=contourIndex2; i>=contourIndex1b; i--){ int indexSafe = (i+nContourPoints)%nContourPoints; ofVec3f pointi = handContour[indexSafe]; poly21.addVertex(pointi.x, pointi.y, pointi.z); } //----------------------- // Resample the finger's two sides. // Note: ofxPolyline.getResampledByCount() does not return a consistent number of points. Do it my damn self. ofPolyline poly01RS; poly01RS.clear(); int poly01size = poly01.size(); for (int i=0; i<=N_FINGER_LENGTH_SAMPLES; i++){ // int poly01index = (int)ofMap((float)i,0,N_FINGER_LENGTH_SAMPLES, 0,poly01size-1); float indexf = ofMap((float)i,0,N_FINGER_LENGTH_SAMPLES, 0,poly01size-1); int poly01index = (int)((i==N_FINGER_LENGTH_SAMPLES) ? floorf(indexf) : roundf(indexf)); ofVec3f pointi = poly01[poly01index]; poly01RS.addVertex(pointi.x, pointi.y, pointi.z); } ofPolyline poly21RS; poly21RS.clear(); int poly21size = poly21.size(); for (int i=0; i<=N_FINGER_LENGTH_SAMPLES; i++){ float indexf = ofMap((float)i,0,N_FINGER_LENGTH_SAMPLES, 0,poly21size-1); int poly21index = (int)((i==N_FINGER_LENGTH_SAMPLES) ? floorf(indexf) : roundf(indexf)); ofVec3f pointi = poly21[poly21index]; poly21RS.addVertex(pointi.x, pointi.y, pointi.z); } //----------------------- // Render the two finger sides. bool bRenderFingerEdgePolylines = true; if (bRenderFingerEdgePolylines){ ofNoFill(); ofSetColor(0,200,100); poly01RS.draw(); ofSetColor(200,100,0); poly21RS.draw(); } bool bDrawContourTexPoints = false; if (bDrawContourTexPoints){ ofSetColor(0,200,250); vector<ofPoint> poly01RSpts = poly01RS.getVertices(); int nPoly01RSpts = poly01RSpts.size(); for (int i=0; i<nPoly01RSpts; i++){ float ex = poly01RSpts[i].x; float ey = poly01RSpts[i].y; ofEllipse (ex, ey, 6, 6); } ofSetColor(250,200,0); vector<ofPoint> poly21RSpts = poly21RS.getVertices(); int nPoly21RSpts = poly21RSpts.size(); for (int i=0; i<nPoly21RSpts; i++){ float ex = poly21RSpts[i].x; float ey = poly21RSpts[i].y; ofEllipse (ex, ey, 9, 9); } } //--------------- // ADD VERTICES TO THE MESH. vector<ofPoint> poly01RSpts = poly01RS.getVertices(); vector<ofPoint> poly21RSpts = poly21RS.getVertices(); int nPoly01RSpts = poly01RSpts.size(); int nPoly21RSpts = poly21RSpts.size(); if ((nPoly01RSpts == nPoly21RSpts) && (nPoly01RSpts == (N_FINGER_LENGTH_SAMPLES+1))){ for (int i=0; i<=N_FINGER_LENGTH_SAMPLES; i++){ float px01 = poly01RSpts[i].x; float py01 = poly01RSpts[i].y; float px21 = poly21RSpts[i].x; float py21 = poly21RSpts[i].y; if (i == N_FINGER_LENGTH_SAMPLES){ // Special case for the tip. // N.B., px01 and px21 are the same point float qx01 = (poly01RSpts[N_FINGER_LENGTH_SAMPLES-1].x + px01)/2.0; float qy01 = (poly01RSpts[N_FINGER_LENGTH_SAMPLES-1].y + py01)/2.0; ofPoint q01 = ofPoint(qx01, qy01); float qx21 = (poly21RSpts[N_FINGER_LENGTH_SAMPLES-1].x + px21)/2.0; float qy21 = (poly21RSpts[N_FINGER_LENGTH_SAMPLES-1].y + py21)/2.0; ofPoint q21 = ofPoint(qx21, qy21); ofPoint QA = handContour.getClosestPoint(q01); ofPoint QB = handContour.getClosestPoint(q21); ofEllipse(QA.x, QA.y, 2, 2); ofEllipse(px01, py01, 2, 2); ofEllipse(QB.x, QB.y, 2, 2); handMesh.addVertex(ofPoint(QA.x, QA.y,0)); handMesh.addVertex(ofPoint(px01, py01,0)); handMesh.addVertex(ofPoint(QB.x, QB.y,0)); } else { // The usual case, up the sides of the finger. if (f < 2){ for (int j=0; j<N_FINGER_WIDTH_SAMPLES; j++){ float ex = ofMap(j, 0,N_FINGER_WIDTH_SAMPLES-1, px01,px21); float ey = ofMap(j, 0,N_FINGER_WIDTH_SAMPLES-1, py01,py21); ofEllipse(ex,ey, 2, 2); handMesh.addVertex(ofPoint(ex,ey,0)); } } else { // skip the 0th point for fingers 2,3,4, // because these are shared vertices with points we've already laid. for (int j=0; j<N_FINGER_WIDTH_SAMPLES; j++){ float ex = ofMap(j, 0,N_FINGER_WIDTH_SAMPLES-1, px01,px21); float ey = ofMap(j, 0,N_FINGER_WIDTH_SAMPLES-1, py01,py21); ofEllipse(ex,ey, 2, 2); if ((j==0) && (i==0)){ ; } else { handMesh.addVertex(ofPoint(ex,ey,0)); } } } } } //--------------- // ADD TRIANGLES TO THE MESH. // add the triangles on the interior of the finger. int vertexIndex = f * (N_FINGER_WIDTH_SAMPLES * N_FINGER_LENGTH_SAMPLES + 3); int NW = N_FINGER_WIDTH_SAMPLES; if (f >= 2){ // Because we skip the 0th point for fingers 2,3,4 // (Because the start point for a finger is coincident with the end point // for the previous finger)... vertexIndex -= (f-1); for (int i=0; i<(N_FINGER_LENGTH_SAMPLES-1); i++){ int row = vertexIndex + i*N_FINGER_WIDTH_SAMPLES; for (int j=0; j<(N_FINGER_WIDTH_SAMPLES-1); j++){ if ((i==0) && (j==0)){ int screwCase = row - (11*5 + 3 - 5); handMesh.addTriangle(screwCase, row+j+1, row+j+NW); handMesh.addTriangle(row+j+1, row+j+1+NW, row+j+NW); } else { handMesh.addTriangle(row+j , row+j+1, row+j+NW); handMesh.addTriangle(row+j+1, row+j+1+NW, row+j+NW); } } } // add triangles at fingertip. int row = vertexIndex + (N_FINGER_LENGTH_SAMPLES-1)*N_FINGER_WIDTH_SAMPLES; handMesh.addTriangle(row+0, row+1, row+NW); handMesh.addTriangle(row+1, row+2, row+NW); handMesh.addTriangle(row+2, row+6, row+NW); handMesh.addTriangle(row+2, row+7, row+1+NW); handMesh.addTriangle(row+2, row+3, row+2+NW); handMesh.addTriangle(row+3, row+4, row+2+NW); } else { // The simple cases, thumb and pinky. for (int i=0; i<(N_FINGER_LENGTH_SAMPLES-1); i++){ int row = vertexIndex + i*N_FINGER_WIDTH_SAMPLES; for (int j=0; j<(N_FINGER_WIDTH_SAMPLES-1); j++){ handMesh.addTriangle(row+j , row+j+1, row+j+NW); handMesh.addTriangle(row+j+1, row+j+1+NW, row+j+NW); } } // add triangles at fingertip. int row = vertexIndex + (N_FINGER_LENGTH_SAMPLES-1)*N_FINGER_WIDTH_SAMPLES; handMesh.addTriangle(row+0, row+1, row+NW); handMesh.addTriangle(row+1, row+2, row+NW); handMesh.addTriangle(row+2, row+6, row+NW); handMesh.addTriangle(row+2, row+7, row+1+NW); handMesh.addTriangle(row+2, row+3, row+2+NW); handMesh.addTriangle(row+3, row+4, row+2+NW); } } } //---------------------------------------------------- // Add vertices for the knuckles. // TRIAGE: START USING SPECIFIC INDICES (rather than computed indices) to build the rest of the mesh. // 60 = N_FINGER_LENGTH_SAMPLES*N_FINGER_WIDTH_SAMPLES + 3, then +2 more into the finger, etc. // int fingerBaseMiddleIndices[] = {60, 117, 174, 231}; for (int i=0; i<4; i++){ int fingerBaseMiddle0 = fingerBaseMiddleIndices[i]; int fingerBaseMiddle1 = fingerBaseMiddle0 + N_FINGER_WIDTH_SAMPLES; ofVec3f P0 = handMesh.getVertex(fingerBaseMiddle0); ofVec3f P1 = handMesh.getVertex(fingerBaseMiddle1); ofVec3f Pk = P0 - 1.25*(P1 - P0); // move it slightly toward the hand centroid ofVec3f Pc = ofVec3f(handCentroid.x, handCentroid.y, 0); float amountToMoveKnucklesTowardCentroid = 0.25; Pk = Pk - amountToMoveKnucklesTowardCentroid*(Pk - Pc); ofEllipse(Pk.x,Pk.y, 2, 2); handMesh.addVertex(Pk); int nv = handMesh.getNumVertices(); for (int j=0; j<4; j++){ if (i==0){ int fi0 = fingerBaseMiddle0 + j - 2; int fi1 = fingerBaseMiddle0 + j - 1; handMesh.addTriangle(nv-1, fi1, fi0); } else { int fi0 = fingerBaseMiddle0 + j - 2; if (j == 0) { fi0 = fingerBaseMiddleIndices[i-1] + 2; } int fi1 = fingerBaseMiddle0 + j - 1; handMesh.addTriangle(nv-1, fi1, fi0); } } } //---------------------------------------------------- // Add vertices for the wrist. int wristIndex0 = Handmarks[HANDMARK_THUMB_BASE ].index; int wristIndex1 = Handmarks[HANDMARK_THUMBSIDE_WRIST ].index; int wristIndex2 = Handmarks[HANDMARK_PINKYSIDE_WRIST ].index; int wristIndex3 = Handmarks[HANDMARK_PALM_BASE ].index; ofVec2f wristP0 = handContour[wristIndex0]; ofVec2f wristP1 = handContour[wristIndex1]; ofVec2f wristP2 = handContour[wristIndex2]; ofVec2f wristP3 = handContour[wristIndex3]; vector<ofPoint> wSide01; vector<ofPoint> wSide32; vector<ofPoint> wSide12; for (int i=0; i<=4; i++){ ofVec2f whcn = ((4.0 - (float)i)*wristP0 + ((float)i)*wristP1)/4.0; ofPoint wristP_hcn = handContour.getClosestPoint(whcn); wSide01.push_back (wristP_hcn); } for (int i=0; i<=4; i++){ ofVec2f whcn = ((4.0 - (float)i)*wristP3 + ((float)i)*wristP2)/4.0; ofPoint wristP_hcn = handContour.getClosestPoint(whcn); wSide32.push_back (wristP_hcn); } for (int i=0; i<=4; i++){ ofVec2f whcn = ((4.0 - (float)i)*wristP1 + ((float)i)*wristP2)/4.0; ofPoint wristP_hcn = handContour.getClosestPoint(whcn); wSide12.push_back (wristP_hcn); } int nvBeforeWrist = handMesh.getNumVertices(); for (int wy=0; wy<=4; wy++){ ofVec2f pL = wSide01[wy]; ofVec2f pR = wSide32[wy]; if (wy < 4){ for (int wx=4; wx>=0; wx--){ ofVec2f wp = ((4.0 - (float)wx)*pL + ((float)wx)*pR)/4.0; ofEllipse(wp.x,wp.y, 2, 2); handMesh.addVertex(ofPoint(wp.x,wp.y,0)); } } else { for (int wx=4; wx>=0; wx--){ ofVec2f wp = wSide12[wx]; ofEllipse(wp.x,wp.y, 2, 2); handMesh.addVertex(ofPoint(wp.x,wp.y,0)); } } } int nvb = nvBeforeWrist; for (int wy=0; wy<4; wy++){ for (int wx=0; wx<4; wx++){ handMesh.addTriangle(nvb+wx, nvb+wx+5, nvb+wx+1); handMesh.addTriangle(nvb+wx+1, nvb+wx+5, nvb+wx+6); } nvb += 5; } //---------------------------------------------------- // Add vertices for the thumb base. // 0,1,2,3,4, 295 // Get interpolated values on the outside contour: int thumbBaseIndex0 = Handmarks[HANDMARK_THUMB_KNUCKLE ].index; int thumbBaseIndex1 = Handmarks[HANDMARK_THUMB_BASE ].index; ofVec2f thumbBaseHcn0 = handContour[thumbBaseIndex0]; ofVec2f thumbBaseHcn1 = handContour[thumbBaseIndex1]; // create a polyline copy of the handContourNice sub-section between the 2 indices ofPolyline thumbCurve; if (thumbBaseIndex0 < thumbBaseIndex1){ for (int i=thumbBaseIndex0; i<=thumbBaseIndex1; i++){ ofPoint tpoint = handContour[i]; thumbCurve.addVertex(tpoint); } } else { // don't want to deal with an unlikely situation thumbCurve = handContour; } vector<ofPoint> thumbBaseSide; for (int i=0; i<=4; i++){ ofVec2f hcn = ((4.0 - (float)i)*thumbBaseHcn0 + ((float)i)*thumbBaseHcn1)/4.0; ofPoint Phcn = thumbCurve.getClosestPoint(hcn); thumbBaseSide.push_back (Phcn); //ofEllipse(Phcn.x,Phcn.y, 10, 10); // n.b., we will not use points i=0 & i=4 because they are already stored as handMesh vertices 4 & 295 } vector<ofPoint> thumbBaseHypotenuse; ofVec2f thumbBaseP0 = ofVec2f(handMesh.getVertex(0).x, handMesh.getVertex(0).y); for (int i=0; i<=4; i++){ ofVec2f hcn = ((4.0 - (float)i)*thumbBaseP0 + ((float)i)*thumbBaseHcn1)/4.0; thumbBaseHypotenuse.push_back (hcn); //ofEllipse(hcn.x,hcn.y, 10, 10); // n.b., we will not use points i=0 & i=4 because they are already stored as handMesh vertices 0 & 295 } int nvBeforeThumbBase = handMesh.getNumVertices(); for (int y=1; y<4; y++){ // skipping y=0 and y=4 because those vertices already exist in handMesh. int topx = 4-y; for (int x=0; x<=topx; x++){ ofPoint T0 = thumbBaseHypotenuse[y]; ofPoint T1 = thumbBaseSide[y]; ofPoint Tinterp = ((topx-x)*T0 + (x)*T1) / (float)topx; handMesh.addVertex(ofPoint(Tinterp.x,Tinterp.y,0)); ofEllipse(Tinterp.x,Tinterp.y, 2, 2); } } // clockwise triangles int ti = nvBeforeThumbBase; for (int y=0; y<1; y++){ // y == 0 case int topx = 4-y; for (int x=0; x<topx; x++){ if (x == 0){ handMesh.addTriangle(x, ti+x, x+1); } else { handMesh.addTriangle(x, ti+(x-1), ti+x); handMesh.addTriangle(x, ti+x, x+1); } } } int thumbBaseVertexIndex = 295; for (int y=1; y<4; y++){ int topx = 4-y; for (int x=0; x<topx; x++){ if (x == 0){ int tj = ti+x+topx+1; if (y == 3){ tj = thumbBaseVertexIndex; } handMesh.addTriangle(ti+x, tj, ti+x+1); } else { handMesh.addTriangle(ti+x, ti+x+topx+1, ti+x+1); handMesh.addTriangle(ti+x, ti+x+topx , ti+x+topx+1 ); } } ti += topx+1; } //---------------------------------------------------- // Add vertices for the thumb webbing. // Get interpolated values on the outside contour: int thumbWebIndex0 = Handmarks[HANDMARK_POINTER_SIDE ].index; int thumbWebIndex1 = Handmarks[HANDMARK_IT_CROTCH ].index; ofVec2f thumbWebHcn0 = handContour[thumbWebIndex0]; ofVec2f thumbWebHcn1 = handContour[thumbWebIndex1]; // create a polyline copy of the handContourNice sub-section between the 2 indices ofPolyline thumbWebCurve; if (thumbWebIndex0 < thumbWebIndex1){ for (int i=thumbWebIndex0; i<=thumbWebIndex1; i++){ ofPoint tpoint = handContour[i]; thumbWebCurve.addVertex(tpoint); } } else { // don't want to deal with an unlikely situation thumbWebCurve = handContour; } // vector of interpolated points along top edge vector<ofPoint> thumbWebSide1; for (int i=0; i<=4; i++){ ofVec2f hcn = ((4.0 - (float)i)*thumbWebHcn0 + ((float)i)*thumbWebHcn1)/4.0; ofPoint Phcn = thumbWebCurve.getClosestPoint(hcn); thumbWebSide1.push_back (Phcn); // ofEllipse(Phcn.x,Phcn.y, 10, 10); // n.b., we will not use points i=0 & i=4, becasue they are handMesh vertices 0 and 233 } vector<ofPoint> thumbWebHypotenuse; ofVec2f thumbWebP0 = ofVec2f(handMesh.getVertex(233).x, handMesh.getVertex(233).y); ofVec2f thumbWebP1 = ofVec2f(handMesh.getVertex(thumbBaseVertexIndex).x, handMesh.getVertex(thumbBaseVertexIndex).y); int nWebHypSamps = 8; for (int i=0; i<=nWebHypSamps; i++){ ofVec2f hcn = ((nWebHypSamps - (float)i)*thumbWebP0 + ((float)i)*thumbWebP1)/(float)nWebHypSamps; thumbWebHypotenuse.push_back (hcn); // ofEllipse(hcn.x,hcn.y, 10, 10); // n.b., we will not use points i=0 & i=4 because they are already stored as handMesh vertices 233 & 295 } int nvBeforeThumbWeb = handMesh.getNumVertices(); for (int y=1; y<4; y++){ // skipping y=0 and y=4 because those vertices already exist in handMesh. int topx = 4-y; for (int x=0; x<=topx; x++){ ofPoint T0 = thumbWebHypotenuse[8-(y*2)]; ofPoint T1 = thumbWebSide1[4-y]; ofPoint Tinterp = ((topx-x)*T0 + (x)*T1) / (float)topx; handMesh.addVertex(ofPoint(Tinterp.x,Tinterp.y,0)); ofEllipse(Tinterp.x,Tinterp.y, 2, 2); } } for (int i=7; i>=1; i-=2){ handMesh.addVertex( thumbWebHypotenuse[i] ); ofEllipse(thumbWebHypotenuse[i].x,thumbWebHypotenuse[i].y, 2, 2); } int thumbWebSideIndices[] = {0, 316, 320, 323, 295}; int wi = nvBeforeThumbWeb; // handMesh.addTriangle(thumbWebSideIndices[4-0], thumbWebSideIndices[4-1], wi+0); // replace with 2 triangles handMesh.addTriangle(thumbWebSideIndices[4-0], thumbWebSideIndices[4-1], wi+9); handMesh.addTriangle(thumbWebSideIndices[4-1], wi+0, wi+9); handMesh.addTriangle(thumbWebSideIndices[4-1], thumbWebSideIndices[4-2], wi+0); handMesh.addTriangle(thumbWebSideIndices[4-2], wi+1, wi+0); handMesh.addTriangle(thumbWebSideIndices[4-2], thumbWebSideIndices[4-3], wi+1); handMesh.addTriangle(thumbWebSideIndices[4-3], wi+2, wi+1); handMesh.addTriangle(thumbWebSideIndices[4-3], thumbWebSideIndices[4-4], wi+2); handMesh.addTriangle(thumbWebSideIndices[4-4], wi+3, wi+2); // handMesh.addTriangle(wi+0, wi+1, wi+4); // replace with 2 triangles, as follows: handMesh.addTriangle(wi+0, wi+1, wi+10); handMesh.addTriangle(wi+1, wi+4, wi+10); handMesh.addTriangle(wi+1, wi+2, wi+4); handMesh.addTriangle(wi+2, wi+5, wi+4); handMesh.addTriangle(wi+2, wi+3, wi+5); handMesh.addTriangle(wi+3, wi+6, wi+5); // handMesh.addTriangle(wi+4, wi+5, wi+7); // replace with 2 triangles, as follows: handMesh.addTriangle(wi+4, wi+5, wi+11); handMesh.addTriangle(wi+5, wi+7, wi+11); handMesh.addTriangle(wi+5, wi+6, wi+7); handMesh.addTriangle(wi+6, wi+8, wi+7); // handMesh.addTriangle(wi+7, wi+8, 233 ); // replace with 2 triangles, as follows: handMesh.addTriangle(wi+7, wi+8, wi+12 ); handMesh.addTriangle(wi+8, 233, wi+12 ); //---------------------------------------------------- // Mesh the palm. // Get interpolated values on the outside contour: int palmContourIndex0 = Handmarks[HANDMARK_PALM_BASE ].index; int palmContourIndex1 = Handmarks[HANDMARK_PINKY_SIDE ].index; ofPolyline palmSideContour; ofPolyline palmSideContourResampled; bool bGotPalmSideContour = true; if (palmContourIndex0 < palmContourIndex1){ for (int i=palmContourIndex0; i<=palmContourIndex1; i++){ ofPoint cpt = handContour[i]; palmSideContour.addVertex( cpt ); } int nDesiredResampledPoints = 9; palmSideContourResampled.clear(); int palmSideContourSize = palmSideContour.size(); int nDesiredSamples = nDesiredResampledPoints-1; for (int i=0; i<nDesiredSamples; i++){ float indexf = ofMap((float)i,0,nDesiredSamples-1, 0,palmSideContourSize-1); int outindex = (int)((i==(nDesiredSamples-1)) ? floorf(indexf) : roundf(indexf)); ofVec3f pointi = palmSideContour[outindex]; palmSideContourResampled.addVertex(pointi.x, pointi.y, pointi.z); } ofPoint cpt = handContour[palmContourIndex1]; palmSideContourResampled.addVertex( cpt.x, cpt.y ); } else { // hopefully this is really unlikely. // but, it happens for all left hands facing down, or right hands facing up :) bGotPalmSideContour = false; printf("Problem meshing palm side.\n"); } if (bGotPalmSideContour){ int nPalmSideResampledContourPoints = palmSideContourResampled.size(); for (int i=1; i<(nPalmSideResampledContourPoints-1); i++){ ofPoint cpt = palmSideContourResampled[i]; handMesh.addVertex (cpt); ofEllipse(cpt.x, cpt.y, 2,2); } handMesh.addTriangle (344, 287, 58); handMesh.addTriangle (287, 288, 62); handMesh.addTriangle (288, 289, 119); handMesh.addTriangle (289, 290, 176); handMesh.addTriangle (290, 337, 233); int wristPointMeshIndex = 293; int wristPointMeshIndices[] = {292, 293,293,293,293, 294}; int knuckleMeshIndices[] = {344, 287,288,289,290, 337, 337}; int thumbSidePalmMeshIndices[] = {295, 334, 325, 335, 329, 336, 332, 337, 233}; for (int k=0; k<6; k++){ float wx = handMesh.getVertex(wristPointMeshIndices[k]).x; float wy = handMesh.getVertex(wristPointMeshIndices[k]).y; float kx = handMesh.getVertex(knuckleMeshIndices[k]).x; float ky = handMesh.getVertex(knuckleMeshIndices[k]).y; for (int i=1; i<7; i++){ float frac = (float)i/7.0; float px = (1-frac)*wx + frac*kx; float py = (1-frac)*wy + frac*ky; handMesh.addVertex( ofVec3f (px,py, 0)); ofEllipse(px, py, 2,2); } } int starti = 338; for (int j=0; j<=6; j++){ int dn = 6; if (j==0){ dn = 7; } if (j == 6){ for (int i=0; i<=5; i++){ int a = starti + i; int b = thumbSidePalmMeshIndices[i+1]; int c = starti + i + 1; int d = thumbSidePalmMeshIndices[i+2]; if (i==5){ c = 337; handMesh.addTriangle (a, b, c); } else { handMesh.addTriangle (a, b, c); handMesh.addTriangle (c, b, d); } } } else { if ((j>=1) && (j < 5)){ int a = starti; int b = wristPointMeshIndex; int c = starti + dn; handMesh.addTriangle (a, b, c); } for (int i=0; i<=5; i++){ int a = starti + i; int b = starti + i + dn; int c = starti + i + 1; int d = starti + i + dn+1; if (i==5){ if (j > 0){ c = knuckleMeshIndices[j-1]; d = knuckleMeshIndices[j ]; handMesh.addTriangle (a, b, c); handMesh.addTriangle (c, b, d); } } else { handMesh.addTriangle (a, b, c); handMesh.addTriangle (c, b, d); } } } starti += dn; } handMesh.addTriangle (344, 343, 350); handMesh.addTriangle (291, 292, 338); handMesh.addTriangle (292, 345, 338); handMesh.addTriangle (292, 293, 345); handMesh.addTriangle (293, 294, 369); handMesh.addTriangle (294, 375, 369); handMesh.addTriangle (294, 295, 375); handMesh.addTriangle (295, 334, 375); } //---------------------------------------------------- // ofEnableAlphaBlending(); ofSetColor(255,100,100, 70); handMesh.draw(); ofSetColor(255,255,255,140); //255,120,120, 50); handMesh.drawWireframe(); //ofDisableAlphaBlending(); } } }
//-------------------------------------------------------------- void ofApp::draw(){ if(poly.size() < 2) return; ofPushMatrix(); ofTranslate(ofGetWidth()/2, ofGetHeight()/2); ofRotateY(rotAngle); ofSetColor(255, 255, 255); poly.draw(); ofSetColor(0, 255, 0); ofSetRectMode(OF_RECTMODE_CENTER); glPointSize(5); glBegin(GL_POINTS); for(int i=0; i<poly.size(); i++) { ofPoint p = poly[i]; glVertex3f(p.x, p.y, p.z); } glEnd(); for(int i=0; i<poly.size(); i++) { ofPoint p = poly[i]; ofSetColor(255, 0, 0); ofLine(p, p + poly.getTangentAtIndex(i) * 20); ofSetColor(0, 255, 0); ofLine(p, p + poly.getNormalAtIndex(i) * 20); ofSetColor(0, 128, 255); ofLine(p, p + poly.getRotationAtIndex(i) * 20); } float totalLength = poly.getPerimeter(); float totalArea = poly.getArea(); ofPoint nearestPoint = poly.getClosestPoint(ofPoint(mouseX-ofGetWidth()/2, mouseY-ofGetHeight()/2), &nearestIndex); ofPoint nearestDataPoint = poly[nearestIndex]; float lengthAtIndex = poly.getLengthAtIndex(nearestIndex); ofPoint pointAtIndex = poly.getPointAtIndexInterpolated(nearestIndex); ofPoint pointAtLength = poly.getPointAtLength(lengthAtIndex); ofPoint pointAtPercent = poly.getPointAtPercent(lengthAtIndex / totalLength); float indexAtLength = poly.getIndexAtLength(lengthAtIndex); float sinTime = ofMap(sin(ofGetElapsedTimef() * 0.5), -1, 1, 0, 1); float sinIndex = sinTime * (poly.isClosed() ? poly.size() : (poly.size()-1)); // sinTime mapped to indices direct float sinIndexLength = poly.getIndexAtPercent(sinTime); // sinTime mapped to indices based on length float lengthAtIndexSin = poly.getLengthAtIndexInterpolated(sinIndex); ofPoint pointAtIndexSin = poly.getPointAtIndexInterpolated(sinIndex); ofPoint pointAtPercentSin = poly.getPointAtPercent(sinTime); float angleAtIndex = poly.getAngleAtIndex(nearestIndex); float angleAtIndexSin = poly.getAngleAtIndexInterpolated(sinIndex); ofVec3f rotAtIndex = poly.getRotationAtIndex(nearestIndex); ofVec3f rotAtIndexSin = poly.getRotationAtIndexInterpolated(sinIndex); float rotMagAtIndex = rotAtIndex.length(); float rotMagAtIndexSin = rotAtIndexSin.length(); ofVec3f normalAtIndex = poly.getNormalAtIndex(nearestIndex); ofVec3f tangentAtIndexSin = poly.getTangentAtIndexInterpolated(sinIndex); ofVec3f normalAtIndexSin = poly.getNormalAtIndexInterpolated(sinIndex); ofVec3f rotationAtIndexSin = poly.getRotationAtIndexInterpolated(sinIndex); ofNoFill(); ofSetLineWidth(2); ofSetColor(255, 0, 0); ofCircle(nearestPoint, 5); ofSetColor(255, 255, 0); ofCircle(nearestDataPoint, 7); // interpolating on indices { ofPoint p = poly.getPointAtIndexInterpolated(sinIndex); ofSetColor(0, 255, 255); ofCircle(p, 10); ofSetColor(255, 0, 0); ofLine(p, p + poly.getTangentAtIndexInterpolated(sinIndex) * 60); ofSetColor(0, 255, 0); ofLine(p, p + poly.getNormalAtIndexInterpolated(sinIndex) * 60); ofSetColor(0, 128, 255); ofLine(p, p + poly.getRotationAtIndexInterpolated(sinIndex) * 60); } // interpolating on length percentages { ofPoint p = poly.getPointAtIndexInterpolated(sinIndexLength); ofSetColor(255, 0, 255); ofCircle(p, 10); ofSetColor(255, 0, 0); ofLine(p, p + poly.getTangentAtIndexInterpolated(sinIndexLength) * 60); ofSetColor(0, 255, 0); ofLine(p, p + poly.getNormalAtIndexInterpolated(sinIndexLength) * 60); ofSetColor(0, 128, 255); ofLine(p, p + poly.getRotationAtIndexInterpolated(sinIndexLength) * 60); } ofSetColor(255, 255, 255); ofCircle(poly.getCentroid2D(), 20); ofPopMatrix(); stringstream s; s << "Number of points: " << poly.size() << endl; s << "totalLength: " << totalLength << endl; s << endl; s << "nearestIndex: " << nearestIndex << endl; s << "nearestPoint: " << nearestPoint << endl; s << "nearestDataPoint: " << nearestDataPoint << endl; s << endl; s << "lengthAtIndex: " << lengthAtIndex << endl; s << "pointAtIndex: " << pointAtIndex << endl; s << endl; s << "pointAtLength: " << pointAtLength << endl; s << "pointAtPercent: " << pointAtPercent << endl; s << endl; s << "indexAtLength: " << indexAtLength << endl; s << endl; s << "sinTime: " << sinTime << endl; s << "sinIndex: " << sinIndex << endl; s << "sinIndexLength: " << sinIndexLength << endl; s << endl; s << "lengthAtIndexSin: " << lengthAtIndexSin << endl; s << "pointAtIndexSin: " << pointAtIndexSin << endl; s << "pointAtPercentSin: " << pointAtPercentSin << endl; s << endl; s << "angleAtIndex: " << angleAtIndex << endl; s << "angleAtIndexSin: " << angleAtIndexSin << endl; s << endl; s << "rotAtIndex: " << rotAtIndex << endl; s << "rotAtIndexSin: " << rotAtIndexSin << endl; s << endl; s << "rotMagAtIndex: " << rotMagAtIndex << endl; s << "rotMagAtIndexSin: " << rotMagAtIndexSin << endl; s << endl; s << "normalAtIndex: " << normalAtIndex << endl; s << "normalAtIndexSin: " << normalAtIndexSin << endl; ofSetColor(255); ofDrawBitmapString(s.str(), 10, 30); }