1
0
mirror of https://github.com/robonen/canvas-3d.git synced 2026-03-20 02:44:40 +00:00

feat(engine): rendering experiments

This commit is contained in:
2022-11-23 22:16:56 +07:00
parent 2d891c76cd
commit 9a5c028ac0
6 changed files with 171 additions and 10 deletions

View File

@@ -16,7 +16,6 @@ services:
- app - app
app: app:
# container_name: app
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
@@ -25,8 +24,6 @@ services:
replicas: 2 replicas: 2
expose: expose:
- '${FORWARD_APP_PORT:-3000}' - '${FORWARD_APP_PORT:-3000}'
# ports:
# - '${FORWARD_APP_PORT:-3000}:3000'
networks: networks:
- c3d_net - c3d_net
depends_on: depends_on:

View File

@@ -0,0 +1 @@
import {Vector} from './types';

View File

@@ -0,0 +1,2 @@
export type Point = [number, number];
export type Vector = [Point, Point, Point];

View File

@@ -8,7 +8,7 @@ const showForm = ref<boolean>(false);
<div class="header" @click="showForm = !showForm"> <div class="header" @click="showForm = !showForm">
<h2>{{ title }}</h2> <h2>{{ title }}</h2>
<button class="button"> <button class="button">
<IconOpen class="icon" :class="{icon_close: showForm}"/> <IconOpen :class="{icon_close: showForm}" class="icon"/>
</button> </button>
</div> </div>
<div class="content" v-show="showForm"> <div class="content" v-show="showForm">

View File

@@ -4,15 +4,167 @@ const canvas = ref<HTMLCanvasElement | null>(null);
onMounted(() => { onMounted(() => {
if (!canvas.value) return; if (!canvas.value) return;
canvas.value.width = window.innerWidth;
canvas.value.height = window.innerHeight;
const ctx = canvas.value.getContext("2d"); const ctx = canvas.value.getContext("2d");
if (!ctx) return; if (!ctx) return;
ctx.fillStyle = "red"; 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();
}); });
</script> </script>
<template> <template>
<canvas ref="canvas" /> <canvas ref="canvas">
Sorry, your browser doesn't support canvas.
</canvas>
</template> </template>

View File

@@ -1,19 +1,18 @@
<script setup lang="ts"> <script setup lang="ts">
const showMenu = ref<boolean>(false);
const showMenu = ref<boolean>(true);
</script> </script>
<template> <template>
<div class="wrapper"> <div class="wrapper">
<div class="content"> <div class="content">
<button v-if="!showMenu" class="button" @click="showMenu = true"> <button v-if="!showMenu" class="button button__show" @click="showMenu = true">
<IconMenu/> <IconMenu/>
</button> </button>
<template v-else> <template v-else>
<div class="controls"> <div class="controls">
<slot/> <slot/>
</div> </div>
<button class="button" @click="showMenu = false"> <button class="button button__hide" @click="showMenu = false">
<IconHide/> <IconHide/>
</button> </button>
</template> </template>
@@ -61,6 +60,16 @@ const showMenu = ref<boolean>(true);
z-index: 3; z-index: 3;
} }
.button__show {
width: 25px;
height: 25px;
}
.button__hide {
width: 22px;
height: 22px;
}
.canvas { .canvas {
position: absolute; position: absolute;
width: 100%; width: 100%;