Point topLeft; PerspectivePrism prism; color c; float x, y; float w, h, depth; int hue, saturation, brightness; //for tiles int Xa, Ya, Xb, Yb, Xd, Yd; float dist, tileSize, tilesHigh, tilesWide; void setup() { size(800, 800); smooth(); w = 150; h = 150; depth = 150; x = random(width - w); y = random(height - w); hue = (int)random(360); saturation = 50; brightness = 80; topLeft = new Point((int)x, (int)y); prism = new PerspectivePrism(topLeft, w, h, depth); //for tiles Xa = width + 5000; Ya = height; Xb = -5000; Yb = height; Xd = 3 * width / 2; Yd = height /2; dist = Xd - (width / 2); tileSize = 400; tilesHigh = 20; tilesWide = 50; colorMode(HSB, 360, 100, 100, 100); c = color(hue, saturation, brightness); } void keyPressed() { if (key == CODED) { if (keyCode == UP) { prism.frontFaceHeight -= 10; prism.setVertices(); } else if (keyCode == DOWN) { prism.frontFaceHeight +=10; prism.setVertices(); } else if (keyCode == LEFT) { prism.frontFaceWidth -= 10; prism.setVertices(); } else if (keyCode == RIGHT) { prism.frontFaceWidth += 10; prism.setVertices(); } else if (keyCode == SHIFT) { prism.prismDepth += 20; prism.setVertices(); } } if (key == ENTER) { prism.prismDepth -= 20; prism.setVertices(); } } void mouseDragged() { x = mouseX; y = mouseY; prism.topFrontLeft = new Point((int)x, (int)y); prism.setVertices(); } void draw() { //noStroke(); background(202, 22, 96); //sky blue fill(127, 88, 53); //GREEN rect(0, 3 * height/4, width, height/2); //grass //for tiles stroke(127, 88, 48); for (int k = 0; k < tilesHigh; k++) { float t = dist/((k * tileSize) + dist); float x1 = Xd + (t * (Xa - (k * tileSize) - Xd)); float ym = Yd + (t * (Ya - Yd)); float xq = (Xa - x1) + Xb; //point on other side of the floor float tileLength = (x1 - xq) / tilesWide; //width of a tile from row k float t2 = dist/(((k + 1) * tileSize) + dist); float x2 = Xd + (t2 * (Xa - ((k + 1) * tileSize) - Xd)); float y2 = Yd + (t2 * (Ya - Yd)); float xq2 = (Xa- x2) + Xb; float tileLength2 = (x2 - xq2) / tilesWide; //width of a tile from row k + 1 for (int i = 0; i < tilesWide; i++) { float xv = x1 - i * (tileLength); float xv2 = x2 - i * (tileLength2); quad(xv, ym, xv2, y2, xv2 - tileLength2, y2, xv - tileLength, ym); } } noStroke(); drawPrism(); } void drawPrism() { drawSide(); drawTopOrBottom(); drawFront(); } void drawSide() { fill(hue, saturation, brightness - (100 - brightness)/4); if (prism.topFrontLeft.x >= prism.center.x) drawLeftFace(); else if (prism.topFrontLeft.x <= prism.center.x - prism.frontFaceWidth) drawRightFace(); } void drawLeftFace() { quad(prism.topFrontLeft.x, prism.topFrontLeft.y, prism.topBackLeft.x, prism.topBackLeft.y, prism.bottomBackLeft.x, prism.bottomBackLeft.y, prism.bottomFrontLeft.x, prism.bottomFrontLeft.y); } void drawRightFace() { quad(prism.topFrontRight.x, prism.topFrontRight.y, prism.topBackRight.x, prism.topBackRight.y, prism.bottomBackRight.x, prism.bottomBackRight.y, prism.bottomFrontRight.x, prism.bottomFrontRight.y); } void drawTopOrBottom() { if (prism.topFrontLeft.y >= prism.center.y) drawTop(); else if (prism.topFrontLeft.y <= prism.center.y - prism.frontFaceHeight) drawBottom(); } void drawTop() { fill(hue, saturation, brightness + (100 - brightness)/4); quad(prism.topFrontLeft.x, prism.topFrontLeft.y, prism.topBackLeft.x, prism.topBackLeft.y, prism.topBackRight.x, prism.topBackRight.y, prism.topFrontRight.x, prism.topFrontRight.y); } void drawBottom() { fill(hue, saturation, brightness - (100 - brightness)/2); quad(prism.bottomFrontLeft.x, prism.bottomFrontLeft.y, prism.bottomBackLeft.x, prism.bottomBackLeft.y, prism.bottomBackRight.x, prism.bottomBackRight.y, prism.bottomFrontRight.x, prism.bottomFrontRight.y); } void drawFront() { fill(hue, saturation, brightness); rect(prism.topFrontLeft.x, prism.topFrontLeft.y, prism.frontFaceWidth, prism.frontFaceHeight); } //Point public class Point { float x; // x-coordinate float y; // y-coordinate // random point public Point() { x = 0; y = 0; } // point initialized from parameters public Point(float x, float y) { this.x = x; this.y = y; } // Euclidean distance between this point and that point public double distanceTo(Point that) { double dx = this.x - that.x; double dy = this.y - that.y; return Math.sqrt(dx*dx + dy*dy); } // return a string representation of this point public String toString() { return "(" + x + ", " + y + ")"; } } //PerspectivePrism class PerspectivePrism { Point center, d; Point topFrontLeft, topFrontRight, bottomFrontRight, bottomFrontLeft; Point topBackLeft, topBackRight, bottomBackRight, bottomBackLeft; float frontFaceWidth, backFaceWidth, frontFaceHeight, backFaceHeight, prismDepth; float horizon, distanceCenterToD; boolean isSelected; PerspectivePrism(Point tLeft, float frontWidth) { this(tLeft, frontWidth, frontWidth, frontWidth); } PerspectivePrism(Point tLeft, float frontWidth, float frontHeight, float depth) { horizon = height/2; center = new Point(width/2, height/2); d = new Point(center.x + (width), center.y); distanceCenterToD = d.x - center.x; frontFaceWidth = frontWidth; frontFaceHeight = frontHeight; prismDepth = depth; topFrontLeft = tLeft; setVertices(); backFaceWidth = calculateBackFaceWidth(); backFaceHeight = calculateBackFaceHeight(); } void setVertices() { setFrontFaceVertices(); setBackFaceVertices(); } void setFrontFaceVertices() { topFrontRight = new Point(round(topFrontLeft.x + frontFaceWidth), topFrontLeft.y); bottomFrontRight = new Point(topFrontRight.x, round(topFrontLeft.y + frontFaceHeight)); bottomFrontLeft = new Point(topFrontLeft.x, bottomFrontRight.y); } void setBackFaceVertices() { topBackLeft = findPointToCenter(topFrontLeft, prismDepth); bottomBackLeft = findPointToCenter(bottomFrontLeft, prismDepth); bottomBackRight = findPointToCenter(bottomFrontRight, prismDepth); topBackRight = findPointToCenter(topFrontRight, prismDepth); } float calculateBackFaceWidth() { Point lowerCorner = findPointToCenter(bottomFrontLeft, prismDepth); Point upperCorner = findPointToCenter(topFrontLeft, prismDepth); float backWidth = abs(upperCorner.x - lowerCorner.x); return backWidth; } float calculateBackFaceHeight() { Point lowerCorner = findPointToD(bottomFrontLeft, prismDepth); Point upperCorner = findPointToCenter(topFrontLeft, prismDepth); float backHeight = abs(upperCorner.y - lowerCorner.y); return backHeight; } Point findPointToD(Point point, float cubeHeight) { float t = distanceCenterToD / (cubeHeight+distanceCenterToD); int x = (int) (d.x + t * (point.x - d.x)); int y = (int) (d.y + t * (point.y - d.y)); return new Point(x, y); } private float calculateT(float givenDistance) { return distanceCenterToD / (givenDistance + distanceCenterToD); } Point findPointToCenter(Point point, float cubeHeight) { float t = calculateT(cubeHeight); int x = (int) (center.x + t * (point.x - center.x)); int y = (int) (center.y + t * (point.y - center.y)); return new Point((int)x, (int)y); } }