class Fungus{ Vector boundary; float baseRotation, baseFlaring, baseX, baseY, baseWidth; float topRotation, topFlaring, topX, topY, topWidth; float hatDisplacement, hatWidth, hatHeight; PImage skin,hat; float[][][] trunk; //-------------- Fungus(){ skin = loadImage("fungus_skin.png"); hat = loadImage("fungus_hat.png"); baseWidth = 96; baseFlaring = 0.9; topX = 12; topY = -125; topWidth = 64; topRotation = 0.35; topFlaring = 0.4; calcBezierPatch(); } //-------------- void calcBezierPatch(){ float trunkLength = mag(topX-baseX,topY-baseY); trunk = new float[4][4][2]; // build base layer in bezier patch trunk[0][0][0] = baseX-cos(baseRotation)*baseWidth/2; trunk[0][0][1] = baseY-sin(baseRotation)*baseWidth/2; trunk[3][0][0] = baseX+cos(baseRotation)*baseWidth/2; trunk[3][0][1] = baseY+sin(baseRotation)*baseWidth/2; // build 2:nd layer in bezier patch trunk[0][1][0] = trunk[0][0][0]-sin(baseRotation+baseFlaring)*trunkLength/3; trunk[0][1][1] = trunk[0][0][1]-cos(baseRotation-baseFlaring)*trunkLength/3; trunk[3][1][0] = trunk[3][0][0]-sin(baseRotation-baseFlaring)*trunkLength/3; trunk[3][1][1] = trunk[3][0][1]-cos(baseRotation+baseFlaring)*trunkLength/3; // build top layer in bezier patch trunk[0][3][0] = topX-cos(topRotation)*topWidth/2; trunk[0][3][1] = topY-sin(topRotation)*topWidth/2; trunk[3][3][0] = topX+cos(topRotation)*topWidth/2; trunk[3][3][1] = topY+sin(topRotation)*topWidth/2; // build 3:nd layer in bezier patch trunk[0][2][0] = trunk[0][3][0]+sin(-topRotation-topFlaring)*trunkLength/3; trunk[0][2][1] = trunk[0][3][1]+cos(-topRotation+topFlaring)*trunkLength/3; trunk[3][2][0] = trunk[3][3][0]+sin(-topRotation+topFlaring)*trunkLength/3; trunk[3][2][1] = trunk[3][3][1]+cos(-topRotation-topFlaring)*trunkLength/3; bezierPatchLevelInterpolate(trunk, 0, 0.1); bezierPatchLevelInterpolate(trunk, 1, 0.1); bezierPatchLevelInterpolate(trunk, 2, 0.1); bezierPatchLevelInterpolate(trunk, 3, 0.1); } //-------------- void bezierPatchLevelInterpolate(float[][][] patch, int level, float roundness){ patch[1][level][0] = roundness*patch[3][level][0] + (1-roundness)*patch[0][level][0]; patch[1][level][1] = roundness*patch[3][level][1] + (1-roundness)*patch[0][level][1]; patch[2][level][0] = (1-roundness)*patch[3][level][0] + roundness*patch[0][level][0]; patch[2][level][1] = (1-roundness)*patch[3][level][1] + roundness*patch[0][level][1]; } //-------------- float bezierToX(float[][][] patch, float u, float v){ return bezierToCoord( patch, u, v, 0); } //-------------- float bezierToY(float[][][] patch, float u, float v){ return bezierToCoord( patch, u, v, 1); } //-------------- // return the i:coordinate on a bezierpatch where the patch-coords are (u,v) float bezierToCoord(float[][][] patch, float u, float v, int i){ float u3 = u*u*u; float u3p = (1-u)*(1-u)*(1-u); float u2 = u*u; float u2p = (1-u)*(1-u); float v3 = v*v*v; float v2 = v*v; float v3p = (1-v)*(1-v)*(1-v); float v2p = (1-v)*(1-v); float a = u3*patch[0][0][i] + 3*u2*(1-u)*patch[1][0][i] + 3*u*u2p*patch[2][0][i] + u3p*patch[3][0][i]; float b = u3*patch[0][1][i] + 3*u2*(1-u)*patch[1][1][i] + 3*u*u2p*patch[2][1][i] + u3p*patch[3][1][i]; float c = u3*patch[0][2][i] + 3*u2*(1-u)*patch[1][2][i] + 3*u*u2p*patch[2][2][i] + u3p*patch[3][2][i]; float d = u3*patch[0][3][i] + 3*u2*(1-u)*patch[1][3][i] + 3*u*u2p*patch[2][3][i] + u3p*patch[3][3][i]; return v3*a + 3*v2*(1-v)*b + 3*v*v2p*c + v3p*d; } //-------------- void visualize(){ fill(255); noStroke(); textureMode(NORMALIZED); float uStep = 0.1, vStep = 0.1; for(float u=0;u<1;u+=uStep) for(float v=0;v<1;v+=vStep){ beginShape(); texture(skin); vertex( bezierToX(trunk,u,v), bezierToY(trunk,u,v), u,v); vertex( bezierToX(trunk,u+uStep,v), bezierToY(trunk,u+uStep,v), u+uStep,v); vertex( bezierToX(trunk,u+uStep,v+vStep), bezierToY(trunk,u+uStep,v+vStep), u+uStep,v+vStep); vertex( bezierToX(trunk,u,v+vStep), bezierToY(trunk,u,v+vStep), u,v+vStep); endShape(CLOSE); } pushMatrix(); translate(topX,topY); rotate(topRotation); scale(topWidth/90); image(hat,-hat.width/2,-hat.height+1); popMatrix(); stroke(0); //bezier(trunk[0][0][0],trunk[0][0][1],trunk[0][1][0],trunk[0][1][1],trunk[0][2][0],trunk[0][2][1],trunk[0][3][0],trunk[0][3][1]); //bezier(trunk[3][0][0],trunk[3][0][1],trunk[3][1][0],trunk[3][1][1],trunk[3][2][0],trunk[3][2][1],trunk[3][3][0],trunk[3][3][1]); } //-------------- }