Code Sketch
cubiod animation
Category: Art
clear
case class Vector3D(x:Double, y:Double, z:Double)
def viewAngleHalf = Math.toRadians(90.0/2.0)
def size = canvasBounds.width*0.5
def bottomFace = Seq(
Vector3D(-50,-50,size),
Vector3D(50,-50,size),
Vector3D(50,-50,size+200),
Vector3D(-50,-50,size+200),
Vector3D(-50,-50,size),
)
def topFace = Seq(
Vector3D(-50,50,size),
Vector3D(50,50,size),
Vector3D(50,50,size+200),
Vector3D(-50,50,size+200),
Vector3D(-50,50,size),
)
def frontFace = Seq(
Vector3D(-50,-50,size),
Vector3D(50,-50,size),
Vector3D(50,50,size),
Vector3D(-50,50,size),
Vector3D(-50,-50,size),
)
def backFace = Seq(
Vector3D(-50,-50,size+200),
Vector3D(50,-50,size+200),
Vector3D(50,50,size+200),
Vector3D(-50,50,size+200),
Vector3D(-50,-50,size+200),
)
def leftFace = Seq(
Vector3D(-50,-50,size),
Vector3D(-50,-50,size+200),
Vector3D(-50,50,size+200),
Vector3D(-50,50,size),
Vector3D(-50,-50,size),
)
def rightFace = Seq(
Vector3D(50,-50,size),
Vector3D(50,-50,size+200),
Vector3D(50,50,size+200),
Vector3D(50,50,size),
Vector3D(50,-50,size),
)
def cube = Seq(bottomFace, topFace, frontFace, backFace, leftFace, rightFace)
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()
cube.foreach { face =>
renderFace(-angle, face)
}
angle+1
}