Code Sketch


Rotating Cube: Initial Attempt
By: Anay Narendra Kamat
Category: Art
cleari

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(-100,-100,size),
        Vector3D(100,-100,size),
        Vector3D(100,-100,size+200),
        Vector3D(-100,-100,size+200),
        Vector3D(-100,-100,size),
    )
def topFace = Seq(
        Vector3D(-100,100,size),
        Vector3D(100,100,size),
        Vector3D(100,100,size+200),
        Vector3D(-100,100,size+200),
        Vector3D(-100,100,size),
    ) 

def frontFace = Seq(
        Vector3D(-100,-100,size),
        Vector3D(100,-100,size),
        Vector3D(100,100,size),
        Vector3D(-100,100,size),
        Vector3D(-100,-100,size),
    )

def 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),
    )  

def leftFace = Seq(
        Vector3D(-100,-100,size),
        Vector3D(-100,-100,size+200),
        Vector3D(-100,100,size+200),
        Vector3D(-100,100,size),
        Vector3D(-100,-100,size),
    )

def rightFace = Seq(
        Vector3D(100,-100,size),
        Vector3D(100,-100,size+200),
        Vector3D(100,100,size+200),
        Vector3D(100,100,size),
        Vector3D(100,-100,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
    
}