diff --git a/src/gltf_utils.js b/src/gltf_utils.js index 4a819f68..80a89b74 100644 --- a/src/gltf_utils.js +++ b/src/gltf_utils.js @@ -67,24 +67,13 @@ function getExtendsFromAccessor(accessor, worldTransform, outMin, outMax) const radius = vec3.length(centerToSurface); - for (const i of [1, 2, 3]) + for (const i of [0, 1, 2]) { outMin[i] = center[i] - radius; outMax[i] = center[i] + radius; } } -function getScaleFactor(gltf, sceneIndex) -{ - const min = vec3.create(); - const max = vec3.create(); - getSceneExtends(gltf, sceneIndex, min, max); - const minValue = Math.min(min[0], Math.min(min[1], min[2])); - const maxValue = Math.max(max[0], Math.max(max[1], max[2])); - const deltaValue = maxValue - minValue; - return 1.0 / deltaValue; -} - function computePrimitiveCentroids(gltf) { const meshes = gltf.nodes.filter(node => node.mesh !== undefined).map(node => gltf.meshes[node.mesh]); @@ -145,4 +134,4 @@ function computePrimitiveCentroids(gltf) } } -export { getSceneExtends, getScaleFactor, computePrimitiveCentroids }; +export { getSceneExtends, computePrimitiveCentroids }; diff --git a/src/renderer.js b/src/renderer.js index 7dc193f8..dd9bc581 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -103,13 +103,13 @@ class gltfRenderer let currentCamera = undefined; - if(!this.parameters.userCameraActive()) + if(this.parameters.userCameraActive()) { - currentCamera = gltf.cameras[this.parameters.cameraIndex].clone(); + currentCamera = this.defaultCamera; } else { - currentCamera = this.defaultCamera; + currentCamera = gltf.cameras[this.parameters.cameraIndex].clone(); } currentCamera.aspectRatio = this.currentWidth / this.currentHeight; diff --git a/src/shaders/punctual.glsl b/src/shaders/punctual.glsl index 046cc0f0..d6589682 100644 --- a/src/shaders/punctual.glsl +++ b/src/shaders/punctual.glsl @@ -27,7 +27,7 @@ float getRangeAttenuation(float range, float distance) if (range <= 0.0) { // negative range means unlimited - return 1.0; + return 1.0 / pow(distance, 2.0); } return max(min(1.0 - pow(distance / range, 4.0), 1.0), 0.0) / pow(distance, 2.0); } diff --git a/src/user_camera.js b/src/user_camera.js index d2f46f4f..c88df9a5 100644 --- a/src/user_camera.js +++ b/src/user_camera.js @@ -4,6 +4,8 @@ import { jsToGl, clamp } from './utils.js'; import { getSceneExtends } from './gltf_utils.js'; const VecZero = vec3.create(); +const PanSpeedDenominator = 1200; +const MaxNearFarRatio = 10000; class UserCamera extends gltfCamera { @@ -25,7 +27,7 @@ class UserCamera extends gltfCamera this.zoom = zoom; this.zoomFactor = 1.04; this.rotateSpeed = 1 / 180; - this.scaleFactor = 1; + this.panSpeed = 1; } updatePosition() @@ -46,7 +48,7 @@ class UserCamera extends gltfCamera { this.xRot = 0; this.yRot = 0; - this.fitViewToScene(gltf, sceneIndex); + this.fitViewToScene(gltf, sceneIndex, true); } zoomIn(value) @@ -71,27 +73,41 @@ class UserCamera extends gltfCamera pan(x, y) { - const moveSpeed = 1 / (this.scaleFactor * 200); - const left = vec3.fromValues(-1, 0, 0); this.toLocalRotation(left); - vec3.scale(left, left, x * moveSpeed); + vec3.scale(left, left, x * this.panSpeed); const up = vec3.fromValues(0, 1, 0); this.toLocalRotation(up); - vec3.scale(up, up, y * moveSpeed); + vec3.scale(up, up, y * this.panSpeed); vec3.add(this.target, this.target, up); vec3.add(this.target, this.target, left); } + fitPanSpeedToScene(min, max) + { + const longestDistance = vec3.distance(min, max); + this.panSpeed = longestDistance / PanSpeedDenominator; + } + fitViewToScene(gltf, sceneIndex) { const min = vec3.create(); const max = vec3.create(); getSceneExtends(gltf, sceneIndex, min, max); - this.fitCameraTargetToExtends(min, max); - this.fitZoomToExtends(min, max); + this.fitCameraTargetToExtents(min, max); + this.fitZoomToExtents(min, max); + this.fitPanSpeedToScene(min, max); + this.fitCameraPlanesToExtents(min, max); + } + + fitCameraPlanesToScene(gltf, sceneIndex) + { + const min = vec3.create(); + const max = vec3.create(); + getSceneExtends(gltf, sceneIndex, min, max); + this.fitCameraPlanesToExtents(min, max); } toLocalRotation(vector) @@ -110,13 +126,13 @@ class UserCamera extends gltfCamera return this.position; } - fitZoomToExtends(min, max) + fitZoomToExtents(min, max) { const maxAxisLength = Math.max(max[0] - min[0], max[1] - min[1]); this.zoom = this.getFittingZoom(maxAxisLength); } - fitCameraTargetToExtends(min, max) + fitCameraTargetToExtents(min, max) { for (const i of [0, 1, 2]) { @@ -124,6 +140,19 @@ class UserCamera extends gltfCamera } } + fitCameraPlanesToExtents(min, max) + { + const longestDistance = vec3.distance(min, max); + let zNear = this.zoom - (longestDistance * 0.6); + let zFar = this.zoom + (longestDistance * 0.6); + + // minimum near plane value needs to depend on far plane value to avoid z fighting or too large near planes + zNear = Math.max(zNear, zFar / MaxNearFarRatio); + + this.znear = zNear; + this.zfar = zFar; + } + getFittingZoom(axisLength) { const yfov = this.yfov; diff --git a/src/viewer.js b/src/viewer.js index dffb4f90..a2d6d483 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -10,7 +10,7 @@ import { UserCamera } from './user_camera.js'; import { jsToGl, getIsGlb, Timer, getContainingFolder } from './utils.js'; import { GlbParser } from './glb_parser.js'; import { gltfEnvironmentLoader } from './environment.js'; -import { getScaleFactor, computePrimitiveCentroids } from './gltf_utils.js'; +import { computePrimitiveCentroids } from './gltf_utils.js'; class gltfViewer { @@ -44,10 +44,6 @@ class gltfViewer this.gltf = undefined; this.lastDropped = undefined; - this.scaledSceneIndex = 0; - this.scaledGltfChanged = true; - this.sceneScaleFactor = 1; - this.renderingParameters = new gltfRenderingParameters(environmentMap); this.userCamera = new UserCamera(); this.currentlyRendering = false; @@ -282,7 +278,6 @@ class gltfViewer this.gltf = gltf; this.currentlyRendering = true; - this.scaledGltfChanged = true; this.prepareSceneForRendering(gltf); this.userCamera.fitViewToScene(gltf, this.renderingParameters.sceneIndex); @@ -303,6 +298,7 @@ class gltfViewer if (self.currentlyRendering) { self.prepareSceneForRendering(self.gltf); + self.userCamera.fitCameraPlanesToScene(self.gltf, self.renderingParameters.sceneIndex); self.renderer.resize(self.canvas.clientWidth, self.canvas.clientHeight); self.renderer.newFrame(); @@ -375,33 +371,6 @@ class gltfViewer this.animateNode(gltf); scene.applyTransformHierarchy(gltf); - - const transform = mat4.create(); - - let scaled = false; - if (this.renderingParameters.userCameraActive() && (this.scaledGltfChanged || this.scaledSceneIndex !== this.renderingParameters.sceneIndex || this.prevCameraIndex !== this.renderingParameters.cameraIndex)) - { - this.sceneScaleFactor = getScaleFactor(gltf, this.renderingParameters.sceneIndex); - - scaled = true; - this.scaledGltfChanged = false; - this.scaledSceneIndex = this.renderingParameters.sceneIndex; - console.log("Rescaled scene " + this.scaledSceneIndex + " by " + this.sceneScaleFactor); - } - else if(!this.renderingParameters.userCameraActive() && this.prevCameraIndex !== this.renderingParameters.cameraIndex) - { - this.sceneScaleFactor = 1; - } - - this.prevCameraIndex = this.renderingParameters.cameraIndex; - - mat4.scale(transform, transform, vec3.fromValues(this.sceneScaleFactor, this.sceneScaleFactor, this.sceneScaleFactor)); - scene.applyTransformHierarchy(gltf, transform); - - if(scaled) - { - this.userCamera.fitViewToScene(gltf, this.renderingParameters.sceneIndex); - } } animateNode(gltf)