You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
3.8 KiB
JavaScript

import * as THREE from 'three';
import {Color, Group} from 'three';
import {ShapeCollection} from "./ShapeCollection";
export class HeadRenderer {
constructor() {
this.shapes = {};
this.renderQueue = [];
this.isRendering = false;
this.scene = null;
this.renderer = null;
this.camera = null;
this.canvas = null;
}
init(width = window.innerWidth, height = window.innerHeight) {
if (window.OffscreenCanvas !== undefined) {
this.canvas = new OffscreenCanvas(width, height);
} else {
let canvasElement = document.createElement("canvas");
canvasElement.width = width;
canvasElement.height = height;
this.canvas = canvasElement;
}
this.renderer = new THREE.WebGLRenderer({
canvas: this.canvas,
alpha: true
});
this.renderer.setSize(width, height);
this.camera = new THREE.PerspectiveCamera(70, width / height, 1, 200);
this.camera.position.z = 40;
this.scene = new THREE.Scene();
let light = new THREE.PointLight(0xffffff, 1);
light.position.set(1, 1, 2);
// Make sure light follow the camera
this.camera.add(light);
// Add camera to scene so light gets rendered
this.scene.add(this.camera);
let ambientLight = new THREE.AmbientLight(0x404040, 1);
this.scene.add(ambientLight);
}
async draw() {
this.renderer.render(this.scene, this.camera);
return new Promise(async (res, rej) => {
window.requestAnimationFrame(async () => {
if (this.canvas.convertToBlob) {
await this.canvas.convertToBlob({
type: 'image/png'
}).then(res, rej);
} else {
this.canvas.toBlob((blob) => {
if (blob) return res(blob);
return rej();
}, 'image/png')
}
})
})
}
render(objects) {
return new Promise(async (res) => {
this.renderQueue.push([objects, res]);
if (!this.isRendering) {
await this.startRender();
}
})
}
async startRender() {
if (this.isRendering) return;
this.isRendering = true;
this.clear();
while (this.renderQueue.length > 0) {
let [objects, res] = this.renderQueue.shift();
console.log(objects, res);
let shapePromises = objects.map(async x => {
let req = await fetch(`blob/shape/${x}.json`);
let json = await req.json();
let shapeColl = await ShapeCollection.forceLoad(json, 'blob/texture/');
this.add(shapeColl);
});
await Promise.all(shapePromises);
this.rotate(-5 * (Math.PI / 180), -30 * (Math.PI / 180), 0);
res(await this.draw());
this.clear();
}
this.isRendering = false;
}
add(shapeCollection) {
this.shapes[shapeCollection.id] = shapeCollection;
this.scene.add(shapeCollection.getGroup());
}
remove(shapeCollection) {
delete this.shapes[shapeCollection.id];
this.scene.remove(shapeCollection.getGroup());
}
clear() {
for (let shape of Object.values(this.shapes)) {
this.remove(shape)
}
}
expose() {
window.scene = this.scene;
window.camera = this.camera;
window.renderer = this.renderer;
}
rotate(x, y, z) {
for (let shape of Object.values(this.shapes)) {
let group = shape.getGroup();
group.rotateX(x);
group.rotateY(y);
group.rotateZ(z);
}
}
}