mirror of
https://github.com/TomHodson/tomhodson.github.com.git
synced 2025-06-26 10:01:18 +02:00
update model viewer code
This commit is contained in:
parent
c248dcb77b
commit
f384514243
@ -118,6 +118,7 @@ class CustomOutlinePass extends Pass {
|
||||
uniform vec4 screenSize;
|
||||
uniform vec3 outlineColor;
|
||||
uniform vec2 multiplierParameters;
|
||||
uniform int debugVisualize;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
@ -196,6 +197,22 @@ class CustomOutlinePass extends Pass {
|
||||
// Combine outline with scene color.
|
||||
vec4 outlineColor = vec4(outlineColor, 1.0);
|
||||
gl_FragColor = vec4(mix(sceneColor, outlineColor, outline));
|
||||
|
||||
//// For debug visualization of the different inputs to this shader.
|
||||
if (debugVisualize == 2) {
|
||||
gl_FragColor = sceneColor;
|
||||
}
|
||||
if (debugVisualize == 3) {
|
||||
gl_FragColor = vec4(vec3(depth), 1.0);
|
||||
}
|
||||
if (debugVisualize == 4) {
|
||||
// 4 visualizes the surfaceID buffer
|
||||
gl_FragColor = vec4(surfaceValue, 1.0);
|
||||
}
|
||||
if (debugVisualize == 5) {
|
||||
// Outlines only
|
||||
gl_FragColor = mix(vec4(0,0,0,0), outlineColor, outline);
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
@ -203,6 +220,7 @@ class CustomOutlinePass extends Pass {
|
||||
createOutlinePostProcessMaterial() {
|
||||
return new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
debugVisualize: { value: 0 },
|
||||
sceneColorBuffer: {},
|
||||
depthBuffer: {},
|
||||
surfaceBuffer: {},
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as THREE from "three";
|
||||
|
||||
import * as dat from 'dat.gui';
|
||||
|
||||
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
||||
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
||||
@ -12,6 +13,123 @@ import { CustomOutlinePass } from "./CustomOutlinePass.js";
|
||||
import FindSurfaces from "./FindSurfaces.js";
|
||||
|
||||
|
||||
// Todo:
|
||||
// Swap in the version of this code that has a debug GUI behind a flag
|
||||
// Consider support for transparent objects by rendering them as a wireframe in the color and excluding them from the edge pass.
|
||||
// Fix the cetnering and scaling
|
||||
// Switch to an angled isometric camera to match the style from the main page.
|
||||
|
||||
const fitCameraToCenteredObject = function (camera, object, offset, orbitControls ) {
|
||||
const boundingBox = new THREE.Box3();
|
||||
boundingBox.setFromObject( object );
|
||||
|
||||
var middle = new THREE.Vector3();
|
||||
var size = new THREE.Vector3();
|
||||
boundingBox.getSize(size);
|
||||
|
||||
// figure out how to fit the box in the view:
|
||||
// 1. figure out horizontal FOV (on non-1.0 aspects)
|
||||
// 2. figure out distance from the object in X and Y planes
|
||||
// 3. select the max distance (to fit both sides in)
|
||||
//
|
||||
// The reason is as follows:
|
||||
//
|
||||
// Imagine a bounding box (BB) is centered at (0,0,0).
|
||||
// Camera has vertical FOV (camera.fov) and horizontal FOV
|
||||
// (camera.fov scaled by aspect, see fovh below)
|
||||
//
|
||||
// Therefore if you want to put the entire object into the field of view,
|
||||
// you have to compute the distance as: z/2 (half of Z size of the BB
|
||||
// protruding towards us) plus for both X and Y size of BB you have to
|
||||
// figure out the distance created by the appropriate FOV.
|
||||
//
|
||||
// The FOV is always a triangle:
|
||||
//
|
||||
// (size/2)
|
||||
// +--------+
|
||||
// | /
|
||||
// | /
|
||||
// | /
|
||||
// | F° /
|
||||
// | /
|
||||
// | /
|
||||
// | /
|
||||
// |/
|
||||
//
|
||||
// F° is half of respective FOV, so to compute the distance (the length
|
||||
// of the straight line) one has to: `size/2 / Math.tan(F)`.
|
||||
//
|
||||
// FTR, from https://threejs.org/docs/#api/en/cameras/PerspectiveCamera
|
||||
// the camera.fov is the vertical FOV.
|
||||
|
||||
const fov = camera.fov * ( Math.PI / 180 );
|
||||
const fovh = 2*Math.atan(Math.tan(fov/2) * camera.aspect);
|
||||
let dx = size.z / 2 + Math.abs( size.x / 2 / Math.tan( fovh / 2 ) );
|
||||
let dy = size.z / 2 + Math.abs( size.y / 2 / Math.tan( fov / 2 ) );
|
||||
let cameraZ = Math.max(dx, dy);
|
||||
|
||||
// offset the camera, if desired (to avoid filling the whole canvas)
|
||||
if( offset !== undefined && offset !== 0 ) cameraZ *= offset;
|
||||
|
||||
camera.position.set( 0, 0, cameraZ );
|
||||
|
||||
// set the far plane of the camera so that it easily encompasses the whole object
|
||||
const minZ = boundingBox.min.z;
|
||||
const cameraToFarEdge = ( minZ < 0 ) ? -minZ + cameraZ : cameraZ - minZ;
|
||||
|
||||
camera.far = cameraToFarEdge * 3;
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
if ( orbitControls !== undefined ) {
|
||||
// set camera to rotate around the center
|
||||
orbitControls.target = new THREE.Vector3(0, 0, 0);
|
||||
|
||||
// prevent camera from zooming out far enough to create far plane cutoff
|
||||
orbitControls.maxDistance = cameraToFarEdge * 2;
|
||||
}
|
||||
};
|
||||
|
||||
const setupDebug = () => {
|
||||
// Set up GUI controls
|
||||
const GUI = dat.GUI;
|
||||
const gui = new GUI({ width: 300, autoPlace: true});
|
||||
// container.append(gui.domElement);
|
||||
|
||||
const uniforms = customOutline.fsQuad.material.uniforms;
|
||||
const params = {
|
||||
mode: { Mode: 0 },
|
||||
depthBias: uniforms.multiplierParameters.value.x,
|
||||
depthMult: uniforms.multiplierParameters.value.y,
|
||||
normalBias: uniforms.multiplierParameters.value.z,
|
||||
normalMult: uniforms.multiplierParameters.value.w,
|
||||
};
|
||||
|
||||
gui
|
||||
.add(params.mode, "Mode", {
|
||||
"Outlines": 0,
|
||||
"Original scene": 2,
|
||||
"Depth buffer": 3,
|
||||
"SurfaceID debug buffer": 4,
|
||||
"Outlines only": 5,
|
||||
})
|
||||
.onChange(function (value) {
|
||||
uniforms.debugVisualize.value = value;
|
||||
});
|
||||
|
||||
gui.add(params, "depthBias", 0.0, 5).onChange(function (value) {
|
||||
uniforms.multiplierParameters.value.x = value;
|
||||
});
|
||||
gui.add(params, "depthMult", 0.0, 20).onChange(function (value) {
|
||||
uniforms.multiplierParameters.value.y = value;
|
||||
});
|
||||
gui.add(params, "normalBias", 0.0, 20).onChange(function (value) {
|
||||
uniforms.multiplierParameters.value.z = value;
|
||||
});
|
||||
gui.add(params, "normalMult", 0.0, 10).onChange(function (value) {
|
||||
uniforms.multiplierParameters.value.w = value;
|
||||
});
|
||||
}
|
||||
|
||||
class OutlineModelViewer extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
@ -20,16 +138,19 @@ class OutlineModelViewer extends HTMLElement {
|
||||
this.render();
|
||||
|
||||
const model_path = this.getAttribute("model") || "/assets/projects/bike_lights/models/bigger.glb";
|
||||
const container = this.shadow.querySelector("div#container");
|
||||
console.log(container);
|
||||
const canvas = this.shadow.querySelector("canvas");
|
||||
|
||||
let canvas_rect = canvas.getBoundingClientRect();
|
||||
console.log(canvas.clientWidth, canvas.clientHeight, canvas_rect, window.devicePixelRatio);
|
||||
|
||||
const body = document.getElementsByTagName("body")[0];
|
||||
const style = window.getComputedStyle(body);
|
||||
const background_color = style.getPropertyValue("background-color");
|
||||
|
||||
const outline_color = 0x000000;
|
||||
const model_color = 0xffffff;
|
||||
const isDark = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
const outline_color = isDark ? 0xffffff : 0x000000;
|
||||
const model_color = background_color;
|
||||
|
||||
// Init scene
|
||||
const camera = new THREE.PerspectiveCamera(
|
||||
@ -121,12 +242,20 @@ class OutlineModelViewer extends HTMLElement {
|
||||
// Set up orbital camera controls.
|
||||
let controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.autoRotate = true;
|
||||
|
||||
let bbox = new THREE.Box3().setFromObject(scene);
|
||||
let middle = new THREE.Vector3();
|
||||
bbox.getCenter(middle);
|
||||
|
||||
// // Center it
|
||||
scene.applyMatrix4(new THREE.Matrix4().makeTranslation( -middle.x, -middle.y, -middle.z ) );
|
||||
// fitCameraToCenteredObject(camera, scene, 1, controls );
|
||||
controls.update();
|
||||
|
||||
// Render loop
|
||||
function update() {
|
||||
requestAnimationFrame(update);
|
||||
controls.update();
|
||||
// controls.update();
|
||||
composer.render();
|
||||
}
|
||||
update();
|
||||
@ -147,18 +276,24 @@ class OutlineModelViewer extends HTMLElement {
|
||||
}
|
||||
|
||||
window.addEventListener("resize", onWindowResize, false);
|
||||
if(this.getAttribute("debug")) setupDebug();
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
this.shadow.innerHTML = `
|
||||
<canvas class="canvas" id="bob"></canvas>
|
||||
|
||||
<div id="container">
|
||||
<canvas class = "object-viewer"></canvas>
|
||||
<summary>
|
||||
Debug
|
||||
<details>Details</details>
|
||||
</summary>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.canvas {
|
||||
.object-viewer {
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
height: 100%;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
</style>
|
||||
|
Loading…
x
Reference in New Issue
Block a user