/* * Daniel King * gtg351x * 901856535 * * CS 4496 Project 4 * Professor Jarek Rossignac */ /* Morph segment. */ class Grid { /* Image texture for this grid. */ PImage image; /* Current number of vertices. */ int numVertices = size * size; /* Array of vertices. */ pt[] vertices = new pt[numVertices]; /* Array of feature vertices. */ pt[] features = new pt[numVertices]; /* Array of interpolated vertices. */ pt[] interpolated = new pt[numVertices]; boolean[] interPinned = new boolean[numVertices]; /* Texture coordinates. */ pt[] textureCoords = new pt[numVertices]; /* Laplace vectors for vertices. */ vec[] laplaces = new vec[numVertices]; /* Bi-laplace vectors for vertices. */ vec[] bilaplaces = new vec[numVertices]; /* Mask for pinned vertices. */ boolean[] pinned = new boolean[numVertices]; /* Vertex valence. */ int[] valence = new int[numVertices]; /* Current number of triangles. */ int numTriangles = 2 * (size - 1) * (size - 1); /* Triangle markers. */ boolean markers[] = new boolean[numTriangles]; /* Current number of corners. */ int numCorners = numTriangles * 3; /* V table - triangle: vertex indices. */ int[] V = new int[3 * numTriangles]; /* O table - opposite corner indices. */ int[] O = new int[3 * numTriangles]; /* Width. */ float w; /* Height. */ float h; /* X-position. */ float x; /* Y-position. */ float y; /* Z-position. */ float z; /* ID of this segment. */ int id; /* Creates a new morph segment. */ Grid(String filename, float w, float h, float x, float y, float z, int id) { image = loadImage(filename); this.w = w; this.h = h; this.x = x; this.y = y; this.z = z; initVertices(); setupGrid(); setTextureCoords(); this.id = id; } /* Initializes the vertices and laplace vectors. */ void initVertices() { for (int i = 0; i < numVertices; i++) { vertices[i] = new pt(0, 0, 0); features[i] = new pt(0, 0, 0); textureCoords[i] = new pt(0, 0, 0); laplaces[i] = new vec(0, 0, 0); bilaplaces[i] = new vec(0, 0, 0); } } /* Sets up the mesh grid. */ void setupGrid() { for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { vertices[size * i + j].setTo(x + w * j / (size - 1), y + h * i / (size - 1), z); features[size * i + j].setTo(x + w * j / (size - 1), y + h * i / (size - 1), z); } } defineTriangles(); pinBorder(); } /* Sets the texture coordinates. */ void setTextureCoords() { for (int i = 0; i < numVertices; i++) { textureCoords[i].setTo(x + vertices[i].x / w, y + vertices[i].y / h, 0); } } /* Defines the triangles in the V and O tables. */ void defineTriangles() { for (int i = 0; i < size - 1; i++) { for (int j = 0; j < size - 1; j++) { V[(i * (size - 1) + j) * 6] = i * size + j; V[(i * (size - 1) + j) * 6 + 2] = (i + 1) * size + j; V[(i * (size - 1) + j) * 6 + 1] = (i + 1) * size + j + 1; V[(i * (size - 1) + j) * 6 + 3] = i * size + j; V[(i * (size - 1) + j) * 6 + 5] = (i + 1) * size + j + 1; V[(i * (size - 1) + j) * 6 + 4] = i * size + j + 1; } } computeOTable(); } /* Initializes the O table to having no opposite (border corners). */ void initOTable() { for (int i = 0; i < 3 * numTriangles; i++) { O[i] = -1; } } /* Computes the O table from the V table. */ void computeOTable() { initOTable(); // Compare the opposites for each pair of corners. for (int i = 0; i < 3 * numTriangles; i++) { for (int j = i + 1; j < 3 * numTriangles; j++) { // If the opposites match, set the O table. if ((v(n(i)) == v(p(j))) && (v(p(i)) == v(n(j)))) { O[i] = j; O[j] = i; } } } } /* Initialize all vertices to un-pinned. */ void initPinned() { for (int i = 0; i < numVertices; i++) { pinned[i] = false; } } /* Pins two rows of border vertices. */ void pinBorder() { initPinned(); for (int i = 0; i < numCorners; i++) { if (border(i)) { pinned[v(n(i))] = true; } } for(int i = 0; i < numCorners; i++) { if (pinned[v(i)]) { markers[t(i)] = true; } } for (int i = 0; i < numCorners; i++) { if (markers[t(i)]) { pinned[v(i)] = true; } } } /* Draws the edges of a triangle. */ void drawEdge(int triangle) { vertices[V[3 * triangle]].vert(); vertices[V[3 * triangle + 1]].vert(); vertices[V[3 * triangle + 2]].vert(); } /* Draws a textured triangle. */ void drawTriangle(int triangle) { int corner = 3 * triangle; vertex(g(corner).x, g(corner).y, textureCoords[v(corner)].x, textureCoords[v(corner)].y); corner = n(corner); vertex(g(corner).x, g(corner).y, textureCoords[v(corner)].x, textureCoords[v(corner)].y); corner = n(corner); vertex(g(corner).x, g(corner).y, textureCoords[v(corner)].x, textureCoords[v(corner)].y); } /* Draws the textured mesh grid. */ void drawGrid(int alpha) { noStroke(); fill(255, 255, 255, alpha); textureMode(NORMALIZED); beginShape(TRIANGLES); texture(image); for (int i = 0; i < numTriangles; i++) { drawTriangle(i); } endShape(); } /* Draws the edges in the mesh grid. */ void drawEdges(color col) { stroke(col); noFill(); beginShape(TRIANGLES); for (int i = 0; i < numTriangles; i++) { drawEdge(i); } endShape(); noStroke(); } /* Draws the pinned vertices in the mesh grid. */ void drawVertices(color col) { noStroke(); for (int i = 0; i < numVertices; i++) { if (pinned[i] && (!selected || v(selectedCorner) != i)) { fill(col); vertices[i].show(4); if (showPNumbers) { textFont(font, 12); vertices[i].label(str(i + 1), new vec(-8, 13, 0)); } } if (selected && v(selectedCorner) == i) { fill(green); vertices[i].show(4); if (showPNumbers) { textFont(font, 12); vertices[i].label(str(i + 1), new vec(-8, 13, 0)); } } } } //////////////////////////////////////// // Helpful Corner Table Functions // //////////////////////////////////////// int t (int c) { int r=int(c/3); return(r); }; int n (int c) { int r=3*int(c/3)+(c+1)%3; return(r); }; int p (int c) { int r=3*int(c/3)+(c+2)%3; return(r); }; int v (int c) { return(V[c]); }; int o (int c) { return(O[c]); }; int l (int c) { return(o(n(c))); }; int r (int c) { return(o(p(c))); }; /* Returns true if a corner has no opposite (is a border vertex). */ boolean border (int corner) { return(O[corner] == -1); } /* Returns the point of a corner. */ pt g (int corner) { return vertices[v(corner)]; } /* Computes the valence of each vertex. */ void computeValence() { for (int i=0; i