Skip to content

Commit ca18aa8

Browse files
committed
Finished basic inspector
1 parent 85b98f5 commit ca18aa8

11 files changed

Lines changed: 666 additions & 253 deletions

File tree

index.html

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,34 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>Document</title>
6+
<title>Down with canvas!</title>
77
<script type="module" src="/src/main.ts"></script>
88
</head>
9-
<body bgcolor="black">
9+
<body bgcolor="black" text="white">
1010
<center>
11-
<table border="1" >
11+
<h1><font face="Arial">Down with canvas</font></h1>
12+
13+
<table border="1" cellpadding="10" cellspacing="0" width="900" bgcolor="#111111">
14+
1215
<tr>
13-
<td colspan="2" bgcolor="black">
16+
<td colspan="3" align="right" bgcolor="#222222">
17+
<font face="monospace">Triangles: <b id="poly-count">0</b> / 100000</font>
18+
</td>
19+
</tr>
20+
21+
<tr valign="top">
22+
23+
<td width="25%" bgcolor="#1a1a1a">
24+
<h3><font face="Arial">Create</font></h3>
25+
<div id="primitive-toolbar"></div>
26+
<hr>
27+
<div id="primitive-options"></div>
28+
<hr>
29+
<h3><font face="Arial">Import .OBJ</font></h3>
30+
<input type="file" id="file-picker"/>
31+
</td>
32+
33+
<td width="50%" align="center" bgcolor="black">
1434
<svg
1535
width="400px"
1636
height="300px"
@@ -19,31 +39,49 @@
1939
stroke-width ="0.01"
2040
id="container"
2141
shape-rendering ="optimizeSpeed"
22-
>
23-
<path id="render-target" fill="none" stroke="black" stroke-width="0.005" stroke-linejoin="round" />
42+
>
43+
<path id="render-target" fill="none" stroke="white" stroke-width="0.005" stroke-linejoin="round" />
2444
</svg>
45+
<br><br>
46+
<table border="0" width="100%">
47+
<tr>
48+
<td align="center">
49+
<font face="Arial">Wireframe mode?</font> <input type="checkbox" id="wireframe-mode">
50+
</td>
51+
</tr>
52+
</table>
2553
</td>
54+
55+
<td width="25%" bgcolor="#1a1a1a">
56+
<h3><font face="Arial">Inspector</font></h3>
57+
<div id="inspector-panel">
58+
<font color="gray">Select an object to inspect.</font>
59+
</div>
60+
</td>
61+
2662
</tr>
63+
</table>
64+
65+
<br><br>
66+
67+
<table border="1" cellpadding="10" cellspacing="0" bgcolor="#111111">
2768
<tr>
28-
<td>Wireframe mode? <input type="checkbox" id="wireframe-mode"></td>
29-
<td><button id="render">Render</button></td>
69+
<td align="center">
70+
<h3><font face="Arial">Model Preview</font></h3>
71+
<svg
72+
width="400px"
73+
height="300px"
74+
viewBox="-1 -1 2 2"
75+
preserveAspectRatio="none"
76+
stroke-width ="0.01"
77+
id="model-preview-container"
78+
shape-rendering ="optimizeSpeed"
79+
bgcolor="black"
80+
></svg>
81+
</td>
3082
</tr>
3183
</table>
32-
</center>
33-
34-
<p>Want to import your own data? Do it through here (obj file type accepted)</p>
35-
<input type="file" id="file-picker"/>
3684

37-
<svg
38-
width="400px"
39-
height="300px"
40-
viewBox="-1 -1 2 2"
41-
preserveAspectRatio="none"
42-
stroke-width ="0.01"
43-
id="model-preview-container"
44-
shape-rendering ="optimizeSpeed"
45-
>
46-
47-
</svg>
85+
</center>
4886
</body>
4987
</html>

src/main.ts

Lines changed: 12 additions & 217 deletions
Original file line numberDiff line numberDiff line change
@@ -1,217 +1,12 @@
1-
import { mat4, vec3 } from "./math/types";
2-
import { perspective, identity, look_at, rotate, translate } from "./math/transformations";
3-
import { create_3d_ngon, create_antiprism, create_sphere, create_torus } from "./rendering/utils/primitives";
4-
import { build_mesh, render_scene } from "./rendering/render";
5-
import { StringBuffer } from "./utils/string_buffer";
6-
import { Mesh } from "./rendering/types/mesh";
7-
import { Scene } from "./rendering/types/scene";
8-
import { mul_mat4 } from "./math/matrix_operators";
9-
import { build_scene } from "./to_html";
10-
import { process_world_coordinates } from "./rendering/process_lighting";
11-
import { Light } from "./rendering/types/light";
12-
import { parse_obj } from "./utils/parser";
13-
import type { Geometry } from "./rendering/types/geometry";
14-
15-
16-
function generate_random_lights(LIGHT_COUNT:number, scene:Scene){
17-
const lights = [];
18-
for (let i = 0; i < LIGHT_COUNT; i++) {
19-
const color = vec3(Math.random(), Math.random(), Math.random());
20-
const l = new Light(vec3(0,0,0), color, 4.0, 12.0);
21-
scene.add_light(l);
22-
23-
const mesh = create_sphere(0.15, 8, 8);
24-
const mesh_idx = scene.meshes.length;
25-
scene.add_mesh(mesh);
26-
lights.push({
27-
light: l,
28-
mesh_idx: mesh_idx,
29-
orbit: {
30-
speed: 0.4 + Math.random() * 0.8,
31-
radius: 2.5 + Math.random() * 2.0,
32-
phase: Math.random() * Math.PI * 2,
33-
y_offset: (Math.random() - 0.5) * 4
34-
}
35-
});
36-
}
37-
return lights;
38-
}
39-
40-
let animation_id:number|null = null;
41-
42-
const frame_max = 1000;
43-
let frame_count = 0;
44-
45-
export function main_3d() {
46-
if(animation_id !== null){
47-
cancelAnimationFrame(animation_id);
48-
}
49-
const target = document.getElementById('container');
50-
if (!target) return;
51-
const wireframe_el = document.getElementById('wireframe-mode') as HTMLInputElement;
52-
53-
const RESOLUTION = 32;
54-
55-
const sun_geo = create_antiprism(RESOLUTION,1,1)
56-
const planet_geo = create_sphere(0.5, RESOLUTION/2, RESOLUTION/2);
57-
const bulb_geo = create_sphere(0.15, 8, 8);
58-
59-
const scene: Scene = new Scene(sun_geo.indices.length + planet_geo.indices.length + bulb_geo.indices.length*32);
60-
scene.add_mesh(sun_geo,vec3(0.4,0.3,0.6),0.7);
61-
scene.add_mesh(planet_geo,vec3(0.7,0.6,0.8));
62-
63-
const camera_pos:vec3 = vec3(0,2,6.5);
64-
65-
const y = vec3(0, 1, 0);
66-
const view: mat4 = look_at(camera_pos, vec3(0, 0, 0), y);
67-
const projection = perspective(60 * Math.PI / 180, 400 / 300, 0.1, 100);
68-
const vp = mul_mat4(projection, view);
69-
let time = 0;
70-
const string_buffer = new StringBuffer(scene.scene_buffer.length * 50);
71-
72-
const sun_light = new Light(vec3(10, 10, 10), vec3(1.0, 0.95, 0.9), 3.0, 200.0);
73-
74-
const point_light = new Light(
75-
vec3(0, 0, 0),
76-
vec3(1.0, 1.0, 0.5),
77-
5.0,
78-
15.0
79-
);
80-
81-
const lights = generate_random_lights(0,scene);
82-
83-
scene.add_light(sun_light);
84-
scene.add_light(point_light);
85-
const do_wireframe: boolean = wireframe_el?.checked;
86-
87-
88-
let start = performance.now();
89-
90-
91-
const loop = () => {
92-
time += 0.01;
93-
frame_count++;
94-
if(frame_count > frame_max){
95-
const end = performance.now();
96-
console.log(end-start);
97-
frame_count = 0;
98-
}
99-
100-
const lx = Math.cos(time * 2) * 2.5;
101-
const ly = Math.sin(time * 2) * 2.5;
102-
const lz = Math.sin(time) * 1.5;
103-
104-
let rotate_matrix = rotate(identity(),time,y);
105-
rotate_matrix = rotate(identity(),time*2,vec3(1,0,0));
106-
107-
let sun_model = rotate(identity(), time * 0.5, y);
108-
109-
let planet_model = rotate(identity(), time, y);
110-
planet_model = translate(planet_model, vec3(3.5, 0, 0));
111-
planet_model = rotate(planet_model, time * 3, vec3(1, 0, 1));
112-
113-
let bulb_model = translate(identity(), vec3(lx, ly, lz));
114-
115-
const models = [sun_model, planet_model,bulb_model];
116-
117-
point_light.position[0] = lx;
118-
point_light.position[1] = ly;
119-
point_light.position[2] = lz;
120-
121-
lights.forEach(entity => {
122-
const { light, orbit } = entity;
123-
124-
const x = Math.cos(time * orbit.speed + orbit.phase) * orbit.radius;
125-
const z = Math.sin(time * orbit.speed + orbit.phase) * orbit.radius;
126-
const y_pos = orbit.y_offset;
127-
128-
light.position[0] = x;
129-
light.position[1] = y_pos;
130-
light.position[2] = z;
131-
const bulb_model = mul_mat4(translate(identity(), vec3(x, y_pos, z)),rotate_matrix);
132-
models.push(bulb_model);
133-
});
134-
const mvps = models.map(m => mul_mat4(vp, m));
135-
136-
for (let i = 0; i < scene.meshes.length; ++i) {
137-
scene.meshes[i].update_normals(models[i]);
138-
}
139-
140-
process_world_coordinates(scene, models, camera_pos);
141-
render_scene(scene, mvps, true);
142-
143-
const frame_html = build_scene(scene, do_wireframe, string_buffer);
144-
target!.innerHTML = frame_html;
145-
animation_id = requestAnimationFrame(loop);
146-
}
147-
animation_id = requestAnimationFrame(loop);
148-
}
149-
150-
export function load_file(){
151-
152-
}
153-
154-
document.getElementById('render')?.addEventListener('click', main_3d);
155-
156-
const file_content = document.getElementById('file-picker');
157-
158-
export async function handle_file(event:Event){
159-
const target = event.target as HTMLInputElement;
160-
if(!target.files) return;
161-
const file = target.files[0];
162-
const geometry = parse_obj(await file.text());
163-
render_preview(geometry);
164-
}
165-
166-
let preview_animation_id:number|null = null;
167-
let zoom_distance = 1.0;
168-
169-
function render_preview(geo: Geometry) {
170-
if (preview_animation_id !== null) {
171-
cancelAnimationFrame(preview_animation_id);
172-
}
173-
console.log(geo.vertices);
174-
const target = document.getElementById('model-preview-container');
175-
if (!target) return;
176-
177-
target.onwheel = (e: WheelEvent) => {
178-
e.preventDefault();
179-
const zoomSpeed = 1.0;
180-
zoom_distance += e.deltaY > 0 ? zoomSpeed : -zoomSpeed;
181-
zoom_distance = Math.max(1.0, Math.min(zoom_distance, 200.0));
182-
};
183-
184-
const scene = new Scene(geo.indices.length);
185-
const mesh_ref = scene.add_mesh(geo, vec3(0.5, 0.8, 0.5), 0.8);
186-
187-
const preview_light = new Light(vec3(100, 100, 100), vec3(1, 1, 1), 120.0, 5000.0);
188-
scene.add_light(preview_light);
189-
190-
const string_buffer = new StringBuffer(scene.scene_buffer.length * 60);
191-
let rotation_time = 0;
192-
193-
const preview_loop = () => {
194-
rotation_time += 0.02;
195-
196-
const camera_pos = vec3(0, 0, zoom_distance);
197-
const view = look_at(camera_pos, vec3(0, 0, 0), vec3(0, 1, 0));
198-
const projection = perspective(45 * Math.PI / 180, 1, 0.1, 100);
199-
const vp = mul_mat4(projection, view);
200-
201-
const rotation_matrix = rotate(identity(), rotation_time, vec3(0, 1, 0));
202-
203-
let model_matrix = rotation_matrix;
204-
205-
mesh_ref.update_normals(model_matrix);
206-
process_world_coordinates(scene, [model_matrix],camera_pos);
207-
208-
render_scene(scene, [mul_mat4(vp, model_matrix)], true);
209-
210-
target.innerHTML = build_scene(scene, false, string_buffer);
211-
preview_animation_id = requestAnimationFrame(preview_loop);
212-
};
213-
214-
preview_loop();
215-
}
216-
217-
file_content?.addEventListener('change',handle_file);
1+
import { SceneManager } from "./ui/scene_manager";
2+
3+
const manager = new SceneManager(
4+
"container",
5+
"primitive-toolbar",
6+
"primitive-options",
7+
"inspector-panel",
8+
"wireframe-mode",
9+
"poly-count"
10+
);
11+
12+
manager.start();

src/rendering/types/mesh.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ export class Mesh{
5555
this.normals[i+2] = world_n[2];
5656
}
5757
}
58+
rebind_buffers(
59+
raster_color: ArrayType,
60+
raster_buffer: ArrayType,
61+
projected_buffer: ArrayType,
62+
color_buffer: ArrayType
63+
) {
64+
this.raster_color = raster_color;
65+
this.raster_buffer = raster_buffer;
66+
this.projected_buffer = projected_buffer;
67+
this.color_buffer = color_buffer;
68+
}
5869
}
5970

6071

src/rendering/types/node.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
1-
import type { mat4 } from "../../math/types";
1+
import { mat4, vec3 } from "../../math/types";
2+
import { identity, translate, rotate, scale } from "../../math/transformations";
23
import type { Mesh } from "./mesh";
34

4-
class Node{
5-
mesh:Mesh;
6-
model:mat4;
7-
mvp:mat4;
5+
export class Node {
6+
mesh: Mesh;
7+
position: vec3 = vec3(0,0,0);
8+
rotation: vec3 = vec3(0, 0, 0);
9+
scale_vec: vec3 = vec3(1, 1, 1);
10+
11+
model: mat4 = identity();
812

9-
constructor(mesh:Mesh, model:mat4, mvp:mat4){
13+
constructor(mesh: Mesh) {
1014
this.mesh = mesh;
11-
this.model = model;
12-
this.mvp = mvp;
15+
this.update_matrix();
16+
}
17+
18+
update_matrix() {
19+
let m = identity();
20+
21+
m = translate(m, this.position);
22+
23+
if (this.rotation[2] !== 0) m = rotate(m, this.rotation[2], vec3(0, 0, 1));
24+
if (this.rotation[1] !== 0) m = rotate(m, this.rotation[1], vec3(0, 1, 0));
25+
if (this.rotation[0] !== 0) m = rotate(m, this.rotation[0], vec3(1, 0, 0));
26+
27+
m = scale(m, this.scale_vec);
28+
29+
this.model = m;
1330
}
1431
}

0 commit comments

Comments
 (0)