chadbook/notebook.ipynb

193 lines
5.2 KiB
Text

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# perspective projection\n",
"\n",
"```\n",
"x' = x / z\n",
"y' = y / z\n",
"```\n",
"\n",
"divide by distance. that's it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# a cube: 8 vertices, 12 edges\n",
"\n",
"vertices = [\n",
" (-1, -1, -1),\n",
" ( 1, -1, -1),\n",
" ( 1, 1, -1),\n",
" (-1, 1, -1),\n",
" (-1, -1, 1),\n",
" ( 1, -1, 1),\n",
" ( 1, 1, 1),\n",
" (-1, 1, 1),\n",
"]\n",
"\n",
"edges = [\n",
" (0, 1), (1, 2), (2, 3), (3, 0), # front\n",
" (4, 5), (5, 6), (6, 7), (7, 4), # back\n",
" (0, 4), (1, 5), (2, 6), (3, 7), # connecting\n",
"]\n",
"\n",
"print(f\"{len(vertices)} vertices, {len(edges)} edges\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# the formula\n",
"\n",
"def project(x, y, z):\n",
" return (x / z, y / z)\n",
"\n",
"# example: a point at (2, 1, 4)\n",
"x, y, z = 2, 1, 4\n",
"x_proj, y_proj = project(x, y, z)\n",
"\n",
"print(f\"3d point: ({x}, {y}, {z})\")\n",
"print(f\"2d projection: ({x_proj}, {y_proj})\")\n",
"print(f\"\\nfarther away = smaller on screen\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# static cube\n",
"\n",
"from IPython.display import HTML\n",
"\n",
"HTML(\"\"\"\n",
"<canvas id=\"static\" width=\"300\" height=\"300\" style=\"background:#111\"></canvas>\n",
"<script>\n",
"(function() {\n",
" const canvas = document.getElementById('static');\n",
" const ctx = canvas.getContext('2d');\n",
" const w = canvas.width, h = canvas.height;\n",
" \n",
" const vertices = [\n",
" [-1,-1,-1], [1,-1,-1], [1,1,-1], [-1,1,-1],\n",
" [-1,-1, 1], [1,-1, 1], [1,1, 1], [-1,1, 1]\n",
" ];\n",
" const edges = [\n",
" [0,1],[1,2],[2,3],[3,0],\n",
" [4,5],[5,6],[6,7],[7,4],\n",
" [0,4],[1,5],[2,6],[3,7]\n",
" ];\n",
" \n",
" function project(x, y, z) {\n",
" z += 4; // push back so z > 0\n",
" return [x/z * 100 + w/2, y/z * 100 + h/2];\n",
" }\n",
" \n",
" ctx.strokeStyle = '#0f0';\n",
" ctx.lineWidth = 2;\n",
" \n",
" for (const [i, j] of edges) {\n",
" const [x1, y1] = project(...vertices[i]);\n",
" const [x2, y2] = project(...vertices[j]);\n",
" ctx.beginPath();\n",
" ctx.moveTo(x1, y1);\n",
" ctx.lineTo(x2, y2);\n",
" ctx.stroke();\n",
" }\n",
"})();\n",
"</script>\n",
"\"\"\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# spinning cube\n",
"\n",
"from IPython.display import HTML\n",
"\n",
"HTML(\"\"\"\n",
"<canvas id=\"spin\" width=\"300\" height=\"300\" style=\"background:#111\"></canvas>\n",
"<script>\n",
"(function() {\n",
" const canvas = document.getElementById('spin');\n",
" const ctx = canvas.getContext('2d');\n",
" const w = canvas.width, h = canvas.height;\n",
" \n",
" const vertices = [\n",
" [-1,-1,-1], [1,-1,-1], [1,1,-1], [-1,1,-1],\n",
" [-1,-1, 1], [1,-1, 1], [1,1, 1], [-1,1, 1]\n",
" ];\n",
" const edges = [\n",
" [0,1],[1,2],[2,3],[3,0],\n",
" [4,5],[5,6],[6,7],[7,4],\n",
" [0,4],[1,5],[2,6],[3,7]\n",
" ];\n",
" \n",
" function rotateY(x, y, z, a) {\n",
" const c = Math.cos(a), s = Math.sin(a);\n",
" return [x*c - z*s, y, x*s + z*c];\n",
" }\n",
" \n",
" function project(x, y, z) {\n",
" z += 4;\n",
" return [x/z * 100 + w/2, y/z * 100 + h/2];\n",
" }\n",
" \n",
" let angle = 0;\n",
" function draw() {\n",
" ctx.fillStyle = '#111';\n",
" ctx.fillRect(0, 0, w, h);\n",
" ctx.strokeStyle = '#0f0';\n",
" ctx.lineWidth = 2;\n",
" \n",
" for (const [i, j] of edges) {\n",
" const a = rotateY(...vertices[i], angle);\n",
" const b = rotateY(...vertices[j], angle);\n",
" const [x1, y1] = project(...a);\n",
" const [x2, y2] = project(...b);\n",
" ctx.beginPath();\n",
" ctx.moveTo(x1, y1);\n",
" ctx.lineTo(x2, y2);\n",
" ctx.stroke();\n",
" }\n",
" \n",
" angle += 0.02;\n",
" requestAnimationFrame(draw);\n",
" }\n",
" draw();\n",
"})();\n",
"</script>\n",
"\"\"\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.11.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}