Code Sketch
yadnesh shahre
Category: Art
cleari()
// 3D Vector Representation
case class Vector3D(x: Double, y: Double, z: Double)
// Viewport and Geometry Configurations
val viewAngleHalf = Math.toRadians(90.0 / 2.0)
val size = canvasBounds.width * 0.5
// Cube / Body Faces Definition
val bottomFace = Seq(
Vector3D(-100, -100, size),
Vector3D(100, -100, size),
Vector3D(100, -100, size + 200),
Vector3D(-100, -100, size + 200),
Vector3D(-100, -100, size)
)
val topFace = Seq(
Vector3D(-100, 100, size),
Vector3D(100, 100, size),
Vector3D(100, 100, size + 200),
Vector3D(-100, 100, size + 200),
Vector3D(-100, 100, size)
)
val frontFace = Seq(
Vector3D(-100, -100, size),
Vector3D(100, -100, size),
Vector3D(100, 100, size),
Vector3D(-100, 100, size),
Vector3D(-100, -100, size)
)
val backFace = Seq(
Vector3D(-100, -100, size + 200),
Vector3D(100, -100, size + 200),
Vector3D(100, 100, size + 200),
Vector3D(-100, 100, size + 200),
Vector3D(-100, -100, size + 200)
)
val leftFace = Seq(
Vector3D(-100, -100, size),
Vector3D(-100, -100, size + 200),
Vector3D(-100, 100, size + 200),
Vector3D(-100, 100, size),
Vector3D(-100, -100, size)
)
val rightFace = Seq(
Vector3D(100, -100, size),
Vector3D(100, -100, size + 200),
Vector3D(100, 100, size + 200),
Vector3D(100, 100, size),
Vector3D(100, -100, size)
)
val cube = Seq(bottomFace, topFace, frontFace, backFace, leftFace, rightFace)
// Robot Parts Definition
def head = Seq(
Seq(
Vector3D(-40, 120, size),
Vector3D(40, 120, size),
Vector3D(40, 200, size),
Vector3D(-40, 200, size),
Vector3D(-40, 120, size)
)
)
def body = cube
def leftArm = Seq(
Seq(
Vector3D(-170, -60, size),
Vector3D(-100, -60, size),
Vector3D(-100, 80, size),
Vector3D(-170, 80, size),
Vector3D(-170, -60, size)
)
)
def rightArm = Seq(
Seq(
Vector3D(100, -60, size),
Vector3D(170, -60, size),
Vector3D(170, 80, size),
Vector3D(100, 80, size),
Vector3D(100, -60, size)
)
)
def leftLeg = Seq(
Seq(
Vector3D(-70, -250, size),
Vector3D(-20, -250, size),
Vector3D(-20, -100, size),
Vector3D(-70, -100, size),
Vector3D(-70, -250, size)
)
)
def rightLeg = Seq(
Seq(
Vector3D(20, -250, size),
Vector3D(70, -250, size),
Vector3D(70, -100, size),
Vector3D(20, -100, size),
Vector3D(20, -250, size)
)
)
val robot = body ++ head ++ leftArm ++ rightArm ++ leftLeg ++ rightLeg
// Transformation Helpers
def translateToOrigin(referencePoint: Vector3D, point: Vector3D): Vector3D =
Vector3D(
point.x - referencePoint.x,
point.y - referencePoint.y,
point.z - referencePoint.z
)
def translateBy(referencePoint: Vector3D, point: Vector3D): Vector3D =
Vector3D(
point.x + referencePoint.x,
point.y + referencePoint.y,
point.z + referencePoint.z
)
def rotateAroundY(angle: Double, point: Vector3D) =
Vector3D(
point.x * Math.cos(angle) + point.z * Math.sin(angle),
point.y,
point.z * Math.cos(angle) - point.x * Math.sin(angle)
)
def rotateAroundX(angle: Double, point: Vector3D) =
Vector3D(
point.x,
point.y * Math.cos(angle) - point.z * Math.sin(angle),
point.y * Math.sin(angle) + point.z * Math.cos(angle)
)
def rotateAroundZ(angle: Double, point: Vector3D) =
Vector3D(
point.x * Math.cos(angle) - point.y * Math.sin(angle),
point.x * Math.sin(angle) + point.y * Math.cos(angle),
point.z
)
def normalisePoint(point: Vector3D): Vector3D = {
return Vector3D(
point.x / (canvasBounds.width * 0.5),
point.y / (canvasBounds.width * 0.5),
point.z / (canvasBounds.width * 0.5)
)
}
def toWorld(point: Vector3D): Vector3D = {
return Vector3D(
point.x * (canvasBounds.width * 0.5),
point.y * (canvasBounds.width * 0.5),
point.z * canvasBounds.width * 0.5
)
}
def toPerspective(point: Vector3D): Vector3D = {
return Vector3D(
point.x / (point.z * Math.tan(viewAngleHalf)),
point.y / (point.z * Math.tan(viewAngleHalf)),
point.z
)
}
def drawFace(face: Seq[Vector3D]): Picture = Picture.fromVertexShape { x =>
x.beginShape()
face.foreach { v =>
x.vertex(v.x, v.y)
}
x.endShape()
}
def renderFace(angle: Double, face: Seq[Vector3D]): Unit = {
val transformedFace = face
.map(translateToOrigin(Vector3D(0, 0, size + 100), _))
.map(rotateAroundY(Math.toRadians(angle), _))
.map(rotateAroundX(Math.toRadians(angle / 2), _))
.map(translateBy(Vector3D(0, 0, size + 100), _))
.map(normalisePoint)
.map(toPerspective)
.map(toWorld)
draw(drawFace(transformedFace))
}
animateWithState(0) { angle =>
erasePictures()
robot.foreach { face =>
renderFace(-angle, face)
}
angle + 1
}