From 9a5c028ac0a15b49bc16707c01fa4a010bfafbbf Mon Sep 17 00:00:00 2001 From: robonen Date: Wed, 23 Nov 2022 22:16:56 +0700 Subject: [PATCH] feat(engine): rendering experiments --- docker-compose.yml | 3 - packages/rendering/index.ts | 1 + packages/rendering/types.ts | 2 + src/components/accordion.vue | 2 +- src/components/board.vue | 156 ++++++++++++++++++++++++++++++++++- src/layouts/default.vue | 17 +++- 6 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 packages/rendering/index.ts create mode 100644 packages/rendering/types.ts diff --git a/docker-compose.yml b/docker-compose.yml index 958f347..03451a8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,6 @@ services: - app app: - # container_name: app build: context: . dockerfile: Dockerfile @@ -25,8 +24,6 @@ services: replicas: 2 expose: - '${FORWARD_APP_PORT:-3000}' - # ports: - # - '${FORWARD_APP_PORT:-3000}:3000' networks: - c3d_net depends_on: diff --git a/packages/rendering/index.ts b/packages/rendering/index.ts new file mode 100644 index 0000000..5701aa9 --- /dev/null +++ b/packages/rendering/index.ts @@ -0,0 +1 @@ +import {Vector} from './types'; diff --git a/packages/rendering/types.ts b/packages/rendering/types.ts new file mode 100644 index 0000000..f02de17 --- /dev/null +++ b/packages/rendering/types.ts @@ -0,0 +1,2 @@ +export type Point = [number, number]; +export type Vector = [Point, Point, Point]; diff --git a/src/components/accordion.vue b/src/components/accordion.vue index 5e67388..7287efb 100644 --- a/src/components/accordion.vue +++ b/src/components/accordion.vue @@ -8,7 +8,7 @@ const showForm = ref(false);

{{ title }}

diff --git a/src/components/board.vue b/src/components/board.vue index ba877d0..24a15e5 100644 --- a/src/components/board.vue +++ b/src/components/board.vue @@ -4,15 +4,167 @@ const canvas = ref(null); onMounted(() => { if (!canvas.value) return; + canvas.value.width = window.innerWidth; + canvas.value.height = window.innerHeight; + const ctx = canvas.value.getContext("2d"); if (!ctx) return; ctx.fillStyle = "red"; - ctx.fillRect(0, 0, Math.random() * 100, Math.random() * 100); + + type Point = [number, number, number, number]; + + const points: Point[] = [ + [500, 500, 500, 1], + [500, 500, 700, 1], + [500, 700, 500, 1], + [500, 700, 700, 1], + [700, 500, 500, 1], + [700, 500, 700, 1], + [700, 700, 500, 1], + [700, 700, 700, 1], + ]; + + const faces: [number, number, number, number][] = [ + [0, 1, 3, 2], + [0, 1, 5, 4], + [0, 2, 6, 4], + [1, 3, 7, 5], + [2, 3, 7, 6], + [4, 5, 7, 6], + ]; + + // Rotate around X axis + const rotateX = (angle: number): Point[] => { + const rad = (angle * Math.PI) / 180; + const cos = Math.cos(rad); + const sin = Math.sin(rad); + + return [ + [1, 0, 0, 0], + [0, cos, -sin, 0], + [0, sin, cos, 0], + [0, 0, 0, 1], + ]; + }; + + // Rotate around Y axis + const rotateY = (angle: number): Point[] => { + const rad = (angle * Math.PI) / 180; + const cos = Math.cos(rad); + const sin = Math.sin(rad); + + return [ + [cos, 0, sin, 0], + [0, 1, 0, 0], + [-sin, 0, cos, 0], + [0, 0, 0, 1], + ]; + }; + + // Rotate around Z axis + const rotateZ = (angle: number): Point[] => { + const rad = (angle * Math.PI) / 180; + const cos = Math.cos(rad); + const sin = Math.sin(rad); + + return [ + [cos, -sin, 0, 0], + [sin, cos, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + ]; + }; + + // Translate + const translate = (x: number, y: number, z: number): Point[] => { + return [ + [1, 0, 0, x], + [0, 1, 0, y], + [0, 0, 1, z], + [0, 0, 0, 1], + ]; + }; + + // Identity matrix + const identity = (): Point[] => { + return [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + ]; + }; + + // Multiply array of points by matrix + const multiply = (points: Point[], matrix: Point[]): Point[] => { + const result: Point[] = []; + + for (const point of points) { + const [x, y, z, w] = point; + + const [x1, y1, z1, w1] = matrix[0]; + const [x2, y2, z2, w2] = matrix[1]; + const [x3, y3, z3, w3] = matrix[2]; + const [x4, y4, z4, w4] = matrix[3]; + + result.push([ + x * x1 + y * x2 + z * x3 + w * x4, + x * y1 + y * y2 + z * y3 + w * y4, + x * z1 + y * z2 + z * z3 + w * z4, + x * w1 + y * w2 + z * w3 + w * w4, + ]); + } + + return result; + }; + + // Draw figure + const drawFigure = (points: Point[], faces: [number, number, number, number][]) => { + ctx.clearRect(0, 0, canvas.value.width, canvas.value.height); + + faces.forEach((face) => { + ctx.beginPath(); + ctx.moveTo(points[face[0]][0], points[face[0]][1]); + ctx.lineTo(points[face[1]][0], points[face[1]][1]); + ctx.lineTo(points[face[2]][0], points[face[2]][1]); + ctx.lineTo(points[face[3]][0], points[face[3]][1]); + ctx.closePath(); + ctx.stroke(); + }); + }; + + // Rotation animation all axis on the center of the canvas + let angle = 0; + + const animate = () => { + const matrix = multiply( + multiply( + multiply( + translate(canvas.value.width / 2, canvas.value.height / 2, 0), + rotateX(angle) + ), + rotateY(angle) + ), + rotateZ(angle) + ); + + const rotatedPoints = multiply(points, matrix); + + drawFigure(rotatedPoints, faces); + + angle += angle < 360 ? 1 : -360; + + requestAnimationFrame(animate); + }; + + animate(); }); diff --git a/src/layouts/default.vue b/src/layouts/default.vue index d59594b..c480fee 100644 --- a/src/layouts/default.vue +++ b/src/layouts/default.vue @@ -1,19 +1,18 @@