pt2D pickedPoint = P2D(); int vc=64, kc=1; // vertex and keyframe counts int k=0; // current key frame Polyloop [] CP= new Polyloop [kc]; // control polyloops //Polyloop C= new Polyloop(); // used to cut and paste Polyloop P= new Polyloop(); // reference for editing Polyloop D= new Polyloop(); // used to capture the curve drawn by the user pt2D[] Tc; // list of triangle centers float[] TcR; // raidus for triangle center disk boolean showKeys=false; // toggle show all keys boolean showMouseProjection=false; // toggle show mouse projection boolean sketching=false; // toggle indicating that the user is sketching the selected curve boolean showVertices=true; // show control vertices boolean showEkey=true; // show edited curve boolean mat = false; // show the medial axis transform boolean matDisks = false; // show the MAT disks boolean meshMode = false; // if true show mesh, else show polyloop boolean spinAnimation = false; // if true do spin animation, else dont do anything float spinAnimCounter=0; // current time for animation float leftmostVertValue=0; //when rotating around y-axis float rightmostVertValue=0; //when rotating around y-axis float distanceFromVertVals=0; //when rotating around y-axis float t=0; // current time for animation int sprayNum = 50; boolean coolSpray = false; int[] O2D = new int[vc]; // 2D opposite table (related to mirror) ArrayList MAT = new ArrayList(); boolean mirrored = false; boolean matMin = true; boolean matMax = false; boolean matAverage = false; void myInit() {for(int i=0; i=kc*vc) t=0; stroke(red); fill(yellow); CP[int(t/vc)].drawSmooth(0,5); // Default style: jumps from frame to frame (stroboscopic) };*/ M.show2D(); if (matDisks) { noStroke(); // Show disks for (int i = 0; i < Tc.length; i++) { fill(orange, 75); ellipse(Tc[i].x, Tc[i].y, TcR[i]*2, TcR[i]*2); } // Show triangle centers for (int i = 0; i < Tc.length; i++) { fill(blue); Tc[i].show(); } } if(mat) { stroke(blue); for (int i = 0; i < MAT.size(); i++) line((Float)((ArrayList)MAT.get(i)).get(0), (Float)((ArrayList)MAT.get(i)).get(1), (Float)((ArrayList)MAT.get(i)).get(2), (Float)((ArrayList)MAT.get(i)).get(3)); } } if (meshMode) { perspective(PI/2.0,width/height,1.0,6.0*Rbox); lights(); directionalLight(0,0,128,0,1,0); directionalLight(0,0,128,0,0,1); //translate(float(height)/2, float(height)/2, 0.0); // center view wrt window if ((!keyPressed)&&(mousePressed)) {C.pan(); C.pullE(); }; if ((keyPressed)&&(mousePressed)) {updateView();}; C1.track(C); C2.track(C1); C2.apply(); M.show(); /*pushMatrix(); fill(red); translate(M.g(M.o(M.c)).x, M.g(M.o(M.c)).y, M.g(M.o(M.c)).z); sphere(5); popMatrix();*/ } // debug if (printIt) { } } void triangleSplitIntoFour(pt2D v0, pt2D v1, pt2D v2){ pt2D Midpoint1 = new pt2D(A2D(v0,v1)); pt2D Midpoint2 = new pt2D(A2D(v0,v2)); pt2D Midpoint3 = new pt2D(A2D(v1,v2)); pt2D CenterOrigTri = centerOfTriangle(v0,v1,v2); pt2D CenterNewTri1 = new pt2D(centerOfTriangle(v0,Midpoint1,Midpoint2)); pt2D CenterNewTri2 = new pt2D(centerOfTriangle(Midpoint1,v1,Midpoint3)); pt2D CenterNewTri3 = new pt2D(centerOfTriangle(Midpoint2,Midpoint3,v2)); //println("happy"); M.addVertex(new pt(CenterOrigTri.x, CenterOrigTri.y, 0)); M.addVertex(new pt(CenterNewTri1.x, CenterNewTri1.y, 0)); M.addVertex(new pt(CenterNewTri2.x, CenterNewTri2.y, 0)); M.addVertex(new pt(CenterNewTri3.x, CenterNewTri3.y, 0)); //line(CenterNewTri1.x, CenterNewTri1.y,CenterNewTri2.x, CenterNewTri2.y); //line(CenterNewTri1.x, CenterNewTri1.y,CenterNewTri3.x, CenterNewTri3.y); //line(CenterNewTri2.x, CenterNewTri2.y,CenterNewTri3.x, CenterNewTri3.y); } pt2D centerOfTriangle(pt2D v0, pt2D v1, pt2D v2){ //float A=v0.triArea(v1,v2); float a=v1.disTo(v2); float b=v2.disTo(v0); float c=v0.disTo(v1); float s=a+b+c; pt2D bary = weightedSum((s-a)/2/s,v0,(s-b)/2/s,v1,(s-c)/2/s,v2); return bary; // Compute and store distance from point to vertices (radius of disk) /*USED THIS ONE*///TcR[i] = min(bary.disTo(v0), bary.disTo(v1), bary.disTo(v2)); } /* * Take the current polyloop, put it in a mesh, and triangulate */ //****************************// void loopToMesh() { mySample(); M.importPolyloop(P); M.triangulate(); M.update(); // Computer center of each triangle /*Tc = new pt2D[M.nt]; TcR = new float[M.nt]; for (int i = 0; i < M.nt; i++) { pt2D v0 = new pt2D(M.g(3*i).x, M.g(3*i).y); pt2D v1 = new pt2D(M.g(3*i+1).x, M.g(3*i+1).y); pt2D v2 = new pt2D(M.g(3*i+2).x, M.g(3*i+2).y); Tc[i] = centerOfTriangle(v0,v1,v2); TcR[i] = min(Tc[i].disTo(v0), Tc[i].disTo(v1), Tc[i].disTo(v2)); }*/ // Get rid of triangles whose center is outside the polyloop clipTriangles(); /*for (int i = 0; i < M.nt; i++) { boolean crossVert; pt2D A; pt2D B = Tc[i]; vec2D AB; // Pick a line segment AB that is formed from the triangle center to a point outside the screen that does not cross a vertex do { // Pick random point outside the screen A = new pt2D(int(random(-myWidth, -1)), int(random(-myHeight, -1))); // See if the line AB intersects with a vertex C crossVert = false; AB = V2D(A, B); for (int j = 0; j < M.nv; j++) { vec2D AC = V2D(A, P.P[j]); if (dot2D(R2D(AB),AC) == 0 && 0 < dot2D(AB,AC) && dot2D(AB,AC) < dot2D(AB,AB)) crossVert = true; } } while(crossVert); // Count the number of times the chosen line crosses an edge of the polyloop int numCrosses = 0; for (int j = 0; j < P.vn; j++) { if (edgesCross(A, B, P.P[j], P.P[P.n(j)])) numCrosses++; } // If the edge count is even, get rid of triangle if (numCrosses % 2 == 0) { // Set triangle as not visible in mesh M.visible[i] = false; // Set place-holder point (for deletion) in center list Tc[i] = new pt2D(-1, -1); } }*/ // Get rid of invisible triangles /*M.clean(); // Clean up center list int j = 0; pt2D[] temp1 = new pt2D[M.nt]; float[] temp2 = new float[M.nt]; for (int i = 0; i < Tc.length; i++) if (Tc[i].x != -1 && Tc[i].y != -1) { temp1[j] = Tc[i]; temp2[j++] = TcR[i]; } Tc = temp1; TcR = temp2;*/ // Computer center of each triangle Tc = new pt2D[M.nt]; TcR = new float[M.nt]; for (int i = 0; i < M.nt; i++) { pt2D v0 = new pt2D(M.g(3*i).x, M.g(3*i).y); pt2D v1 = new pt2D(M.g(3*i+1).x, M.g(3*i+1).y); pt2D v2 = new pt2D(M.g(3*i+2).x, M.g(3*i+2).y); Tc[i] = centerOfTriangle(v0,v1,v2); if (matMin) TcR[i] = min(Tc[i].disTo(v0), Tc[i].disTo(v1), Tc[i].disTo(v2)); else if (matAverage) TcR[i] = (Tc[i].disTo(v0) + Tc[i].disTo(v1) + Tc[i].disTo(v2))/3; else if (matMax) TcR[i] = max(Tc[i].disTo(v0), Tc[i].disTo(v1), Tc[i].disTo(v2)); } saveMAT(); if (coolSpray) for (int i = 0; i < M.nt; i++) { stroke(white); pt2D v0 = new pt2D(M.g(3*i).x, M.g(3*i).y); pt2D v1 = new pt2D(M.g(3*i+1).x, M.g(3*i+1).y); pt2D v2 = new pt2D(M.g(3*i+2).x, M.g(3*i+2).y); triangleSplitIntoFour(v0,v1,v2); } else randomSpray(); M.triangulate(); M.update(); clipTriangles(); }//end loopToMesh /* * Generic method to remove triangles outside the polyloop. */ void clipTriangles() { // Get rid of triangles whose center is outside the polyloop for (int i = 0; i < M.nt; i++) { boolean crossVert; pt2D A; pt2D v0 = new pt2D(M.g(3*i).x, M.g(3*i).y); pt2D v1 = new pt2D(M.g(3*i+1).x, M.g(3*i+1).y); pt2D v2 = new pt2D(M.g(3*i+2).x, M.g(3*i+2).y); pt2D B = centerOfTriangle(v0, v1, v2); vec2D AB; /* // Pick a line segment AB that is formed from the triangle center to a point outside the screen that does not cross a vertex do { // Pick random point outside the screen A = new pt2D(int(random(-myWidth, -1)), int(random(-myHeight, -1))); // See if the line AB intersects with a vertex C crossVert = false; AB = V2D(A, B); for (int j = 0; j < P.vn; j++) { vec2D AC = V2D(A, P.P[j]); if (dot2D(R2D(AB),AC) == 0 && 0 < dot2D(AB,AC) && dot2D(AB,AC) < dot2D(AB,AB)) crossVert = true; } } while(crossVert); // Count the number of times the chosen line crosses an edge of the polyloop int numCrosses = 0; for (int j = 0; j < P.vn; j++) { if (edgesCross(A, B, P.P[j], P.P[P.n(j)])) numCrosses++; } // If the edge count is even, get rid of triangle if (numCrosses % 2 == 0) { // Set triangle as not visible in mesh M.visible[i] = false; }*/ if (!insidePolyloop(B)) M.visible[i] = false; } // Get rid of invisible triangles M.clean(); } void bulge() { mirrored = false; // Go through each vertex of the mesh for (int v = 0; v < M.nv; v++) { pt2D p = new pt2D(M.G[v].x, M.G[v].y); // In order for watertight-ness, we make sure any polyloop vertices (the originals on outside) have z = 0 if (vertexInPolyloop(p.x, p.y)) { M.G[v].z = 0; continue; } // Go through each point on the MAT and save max height float h = 0; for (int m = 0; m < Tc.length; m++) { // Get the distance to MAT point float d = p.disTo(Tc[m]); // If d >= r, not inside circle or height is 0 anyway if (d >= TcR[m]) continue; // Compute height float tempH = sqrt(sq(TcR[m]) - sq(d)); // If height > h, then use it if (tempH > h) h = tempH; } // Set z-coordinate according to h M.G[v].z = h; } // Prepare for watertight mirror zip(); // Initialize the view initView(M); } // Make all border points have a z of 0, so it zips together well for mirror void zip() { // Go through and if a vertex is a border one, make it's z = 0 for (int c = 0; c < M.nc; c++) if (M.b(M.p(c)) || M.b(M.n(c))) // Yay, we have a border point M.g(c).z = 0; } void mirror() { mirrored = true; // Duplicate vertices with -z // Take a snapshot of nv int tempNV = M.nv; // Number skipped (going to use for skipped array) int numSkipped = 0; int[] skippedArray = new int[tempNV]; for (int v = 0; v < tempNV; v++) { // Do not add vertex if the z is 0 (we will share it) if (M.G[v].z != 0) M.addVertex(M.G[v].x, M.G[v].y, -M.G[v].z); else numSkipped++; skippedArray[v] = numSkipped; } // Initialize opposite table O2D = new int[M.nc*2]; // Make mirror triangles // Take a snapshot of nt int tempNT = M.nt; for (int t = 0; t < tempNT; t++) { int v0 = M.v(3*t); int v1 = M.v(3*t+1); int v2 = M.v(3*t+2); // If a vertex is not an edge vertex (used for zipping), then calculate the duplicate index int temp; if (M.G[v0].z != 0) { v0 += tempNV-skippedArray[v0]; } if (M.G[v1].z != 0) { v1 += tempNV-skippedArray[v1]; } if (M.G[v2].z != 0) { v2 += tempNV-skippedArray[v2]; } // Add in opposite order to get proper orientation M.addTriangle(v0, v2, v1); O2D[M.nc-3] = 3*t; O2D[M.nc-2] = 3*t+2; O2D[M.nc-1] = 3*t+1; } // Update mesh M.update(); } boolean vertexInPolyloop(float x, float y) { for (int i = 0; i < P.vn; i++) if (x == P.P[i].x && y == P.P[i].y) return true; // Not found return false; } void randomSpray() { // Find min and max x and y to limit scope float maxX = 0; float minX = width; float maxY = 0; float minY = height; for (int i = 0; i < P.vn; i++) { if (P.P[i].x > maxX) maxX = P.P[i].x; if (P.P[i].x < minX) minX = P.P[i].x; if (P.P[i].y > maxY) maxY = P.P[i].y; if (P.P[i].y < minY) minY = P.P[i].y; } // Spray points pt2D p; for (int i = 0; i < sprayNum; i++) { // Get random point inside polyloop do { p = new pt2D (random(minX, maxX), random(minY, maxY)); } while (!insidePolyloop(p)); // Add it M.addVertex(p.x, p.y, 0); } } boolean insidePolyloop(pt2D B) { pt2D A; boolean crossVert; vec2D AB; // Pick a line segment AB that is formed from the triangle center to a point outside the screen that does not cross a vertex do { // Pick random point outside the screen A = new pt2D(int(random(-myWidth, -1)), int(random(-myHeight, -1))); // See if the line AB intersects with a vertex C crossVert = false; AB = V2D(A, B); for (int j = 0; j < P.vn; j++) { vec2D AC = V2D(A, P.P[j]); if (dot2D(R2D(AB),AC) == 0 && 0 < dot2D(AB,AC) && dot2D(AB,AC) < dot2D(AB,AB)) crossVert = true; } } while(crossVert); // Count the number of times the chosen line crosses an edge of the polyloop int numCrosses = 0; for (int j = 0; j < P.vn; j++) { if (edgesCross(A, B, P.P[j], P.P[P.n(j)])) numCrosses++; } // If the edge count is even, outside (not even, inside) return (numCrosses % 2 != 0); } void saveMAT() { MAT.clear(); int self; int opp; // Iterate through triangles for (int i = 0; i < Tc.length; i++) { // Draw line from triangle center to centers of any adjacent triangle centers if ((self = 3*i) != (opp = M.o(self))) { ArrayList temp = new ArrayList(); temp.add((Float)Tc[M.t(self)].x); temp.add((Float)Tc[M.t(self)].y); temp.add((Float)Tc[M.t(opp)].x); temp.add((Float)Tc[M.t(opp)].y); MAT.add(temp); //line(Tc[M.t(self)].x, Tc[M.t(self)].y, Tc[M.t(opp)].x, Tc[M.t(opp)].y); } if ((self = 3*i+1) != (opp = M.o(self))) { ArrayList temp = new ArrayList(); temp.add((Float)Tc[M.t(self)].x); temp.add((Float)Tc[M.t(self)].y); temp.add((Float)Tc[M.t(opp)].x); temp.add((Float)Tc[M.t(opp)].y); MAT.add(temp); //line(Tc[M.t(self)].x, Tc[M.t(self)].y, Tc[M.t(opp)].x, Tc[M.t(opp)].y); } if ((self = 3*i+2) != (opp = M.o(self))) { ArrayList temp = new ArrayList(); temp.add((Float)Tc[M.t(self)].x); temp.add((Float)Tc[M.t(self)].y); temp.add((Float)Tc[M.t(opp)].x); temp.add((Float)Tc[M.t(opp)].y); MAT.add(temp); //line(Tc[M.t(self)].x, Tc[M.t(self)].y, Tc[M.t(opp)].x, Tc[M.t(opp)].y); } } }