-
Notifications
You must be signed in to change notification settings - Fork 1
/
PreviewRenderer.js
90 lines (82 loc) · 3.13 KB
/
PreviewRenderer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import TextureAtlas from "./TextureAtlas.js";
let THREE;
let StandaloneModelViewer;
export default class PreviewRenderer {
viewer;
/**
* Create a preview renderer for a completed geometry file.
* @param {HTMLElement} cont
* @param {TextureAtlas} textureAtlas
* @param {Object} geo The Minecraft geometry object
* @param {Object} animations Contents of the `.animation.json` file
* @param {Boolean} [showSkybox] If the skybox should show or not
*/
constructor(cont, textureAtlas, geo, animations, showSkybox = true) {
return (async () => {
let loadingMessage = document.createElement("div");
loadingMessage.classList.add("previewMessage");
let p = document.createElement("p");
let span = document.createElement("span");
span.dataset.translate = "preview.loading";
p.appendChild(span);
let loader = document.createElement("div");
loader.classList.add("loader");
p.appendChild(loader);
loadingMessage.appendChild(p);
cont.appendChild(loadingMessage);
THREE ??= await import("https://esm.run/[email protected]"); // @bridge-editor/model-viewer uses this version :(
StandaloneModelViewer ??= (await import("https://esm.run/@bridge-editor/model-viewer")).StandaloneModelViewer;
let can = document.createElement("canvas");
(new MutationObserver(mutations => {
mutations.forEach(mutation => {
if(mutation.attributeName == "style") {
can.removeAttribute("style"); // @bridge-editor/model-viewer adds the style attribute at the start, and when the viewport is resized :(
}
});
})).observe(can, {
attributes: true
});
let imageBlob = textureAtlas.imageBlobs.at(-1)[1];
let imageUrl = URL.createObjectURL(imageBlob);
this.viewer = new StandaloneModelViewer(can, geo, imageUrl, {
width: window.innerWidth * 0.6,
height: window.innerWidth * 0.6,
antialias: true,
alpha: !showSkybox
});
this.#addLighting();
if(showSkybox) {
await this.#addSkybox();
} else {
this.viewer.scene.background = null;
}
await this.viewer.loadedModel;
URL.revokeObjectURL(imageUrl);
this.viewer.positionCamera(1.7);
this.viewer.requestRendering();
loadingMessage.replaceWith(can);
this.viewer.controls.minDistance = 10;
this.viewer.controls.maxDistance = 1000;
let animator = this.viewer.getModel().animator;
animator.addAnimation("spawn", animations["animations"]["animation.armor_stand.hologram.spawn"]);
animator.play("spawn");
return this;
})();
}
#addLighting() {
this.viewer.scene.children.shift(); // remove the default ambient light
let directionalLight = new THREE.DirectionalLight(0xFFFFFF, 0.5);
directionalLight.position.set(-6, 16, 10);
directionalLight.target.position.set(6, 5, 10);
this.viewer.scene.add(directionalLight);
this.viewer.scene.add(directionalLight.target);
let ambientLight = new THREE.AmbientLight(0xFFFFFF, 0.6);
this.viewer.scene.add(ambientLight);
}
async #addSkybox() {
let loader = new THREE.CubeTextureLoader();
loader.setPath("assets/previewPanorama/");
let cubemap = await loader.loadAsync([1, 3, 4, 5, 0, 2].map(x => `${x}.png`));
this.viewer.scene.background = cubemap;
}
}