Code Sketch
yadnesh shahare using gemini
Category: Programming
// --- Kojo 3x3 Dynamic Color Cube (Rubik's Cube) ---
cleari()
setBackground(Color(15, 15, 25)) // ????? ??????????
// 3D ????????
case class Vector3D(x: Double, y: Double, z: Double)
val size = canvasBounds.width * 0.4
val viewAngleHalf = Math.toRadians(60.0 / 2.0)
// 3D ???????? (X, Y, Z ???????? ????????????)
def rotateX(p: Vector3D, angle: Double): Vector3D = {
val rad = Math.toRadians(angle)
Vector3D(p.x, p.y * Math.cos(rad) - p.z * Math.sin(rad), p.y * Math.sin(rad) + p.z * Math.cos(rad))
}
def rotateY(p: Vector3D, angle: Double): Vector3D = {
val rad = Math.toRadians(angle)
Vector3D(p.x * Math.cos(rad) + p.z * Math.sin(rad), p.y, -p.x * Math.sin(rad) + p.z * Math.cos(rad))
}
def rotateZ(p: Vector3D, angle: Double): Vector3D = {
val rad = Math.toRadians(angle)
Vector3D(p.x * Math.cos(rad) - p.y * Math.sin(rad), p.x * Math.sin(rad) + p.y * Math.cos(rad), p.z)
}
// 3D ?? 2D ????????? ??????????
def project(p: Vector3D): (Double, Double, Double) = {
val distance = size + 350
val pz = p.z + distance
val factor = size / (pz * Math.tan(viewAngleHalf))
(p.x * factor, p.y * factor, pz)
}
// ?? (Cube) ???? 6 ??????? ??? (Rubik's Standard Colors)
val faceColors = Map(
"FRONT" -> Color(255, 50, 50), // ??? (Red)
"BACK" -> Color(255, 140, 0), // ?????? (Orange)
"TOP" -> Color(255, 255, 255), // ?????? (White)
"BOTTOM" -> Color(255, 215, 0), // ????? (Yellow)
"RIGHT" -> Color(50, 205, 50), // ????? (Green)
"LEFT" -> Color(30, 144, 255) // ???? (Blue)
)
// ?? ???? Cube ?? ????
case class MiniCube(cx: Double, cy: Double, cz: Double, s: Double) {
val h = s / 2.0
// ?? ?? 8 ????? (Vertices)
val vertices = Seq(
Vector3D(cx - h, cy - h, cz - h), // 0
Vector3D(cx + h, cy - h, cz - h), // 1
Vector3D(cx + h, cy + h, cz - h), // 2
Vector3D(cx - h, cy + h, cz - h), // 3
Vector3D(cx - h, cy - h, cz + h), // 4
Vector3D(cx + h, cy - h, cz + h), // 5
Vector3D(cx + h, cy + h, cz + h), // 6
Vector3D(cx - h, cy + h, cz + h) // 7
)
// ? ???????? (Faces)
val faces = Seq(
("FRONT", Seq(4, 5, 6, 7), Vector3D(0, 0, 1)),
("BACK", Seq(1, 0, 3, 2), Vector3D(0, 0, -1)),
("TOP", Seq(3, 2, 6, 7), Vector3D(0, 1, 0)),
("BOTTOM", Seq(4, 5, 1, 0), Vector3D(0, -1, 0)),
("RIGHT", Seq(5, 1, 2, 6), Vector3D(1, 0, 0)),
("LEFT", Seq(0, 4, 7, 3), Vector3D(-1, 0, 0))
)
}
// 3x3x3 ?? ?? ???? Cube ???? ????
val cubeSpacing = 34.0
val miniCubeScale = 30.0
val rubiksCube = for {
x <- -1 to 1
y <- -1 to 1
z <- -1 to 1
} yield MiniCube(x * cubeSpacing, y * cubeSpacing, z * cubeSpacing, miniCubeScale)
// ??????? ??? (Animation Loop)
animateWithState(0.0) { angle =>
erasePictures()
// 3D ????? ?????? ?????
val rotX = angle * 0.7
val rotY = angle * 1.0
val rotZ = angle * 0.3
// ???? ???????? (Faces) ???? ???? Z-Depth ????? ????? ???? (Painter's Algorithm)
var allRenderFaces = Seq.empty[(Seq[(Double, Double)], Color, Double)]
rubiksCube.foreach { mini =>
mini.faces.foreach { case (faceName, idxs, normal) =>
// ???? ????? ?????? 3D ????????? ????
val rotatedVerts = idxs.map { i =>
val v = mini.vertices(i)
val r = rotateZ(rotateY(rotateX(v, rotX), rotY), rotZ)
project(r)
}
// Normal Vector ?? ???? ???? ???-??? ????? ????
val rNormal = rotateZ(rotateY(rotateX(normal, rotX), rotY), rotZ)
if (rNormal.z < 0) { // ???? ??????? ???????? ???? ???
val points2D = rotatedVerts.map { case (px, py, _) => (px, py) }
val avgZ = rotatedVerts.map(_._3).sum / 4.0
val baseColor = faceColors(faceName)
allRenderFaces = allRenderFaces :+ (points2D, baseColor, avgZ)
}
}
}
// ????? ???????? ??? ??? ????? ???? ????? (Depth Sorting)
val sortedFaces = allRenderFaces.sortBy(_._3).reverse
// ????????? ???? ????
sortedFaces.foreach { case (pts, color, _) =>
val facePic = Picture.fromVertexShape { p =>
p.beginShape()
pts.foreach { case (x, y) => p.vertex(x, y) }
p.endShape()
}
facePic.setFillColor(color)
facePic.setPenColor(Color(20, 20, 20)) // ???? ?????? (Plastic Frame Effect)
facePic.setPenThickness(2)
draw(facePic)
}
angle + 1.5
}