diff --git a/source/gltf/accessor.js b/source/gltf/accessor.js index eda42085..d5884a3e 100644 --- a/source/gltf/accessor.js +++ b/source/gltf/accessor.js @@ -305,6 +305,7 @@ class gltfAccessor extends GltfObject } // dequantize can be used to perform the normalization from WebGL2 vertexAttribPointer explicitly + // https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_mesh_quantization/README.md#encoding-quantized-data static dequantize(typedArray, componentType) { switch (componentType) diff --git a/source/gltf/gltf_utils.js b/source/gltf/gltf_utils.js index 990a95a6..8cc913c7 100644 --- a/source/gltf/gltf_utils.js +++ b/source/gltf/gltf_utils.js @@ -1,5 +1,6 @@ import { vec3 } from 'gl-matrix'; import { jsToGl } from './utils.js'; +import { gltfAccessor } from './accessor.js'; function getSceneExtents(gltf, sceneIndex, outMin, outMax) { @@ -52,19 +53,42 @@ function getSceneExtents(gltf, sceneIndex, outMin, outMax) function getExtentsFromAccessor(accessor, worldTransform, outMin, outMax) { - const boxMin = vec3.create(); let min = jsToGl(accessor.min); - if (accessor.normalized){ - vec3.normalize(min, min); + let max = jsToGl(accessor.max); + + if (accessor.normalized) { + min = gltfAccessor.dequantize(min, accessor.componentType) + max = gltfAccessor.dequantize(max, accessor.componentType) } - vec3.transformMat4(boxMin, min, worldTransform); - const boxMax = vec3.create(); - let max = jsToGl(accessor.max); - if (accessor.normalized){ - vec3.normalize(max, max); + // Construct all eight corners from min and max values + let boxVertices = [ + vec3.fromValues(min[0], min[1], min[2]), + vec3.fromValues(min[0], min[1], max[2]), + vec3.fromValues(min[0], max[1], min[2]), + vec3.fromValues(min[0], max[1], max[2]), + + vec3.fromValues(max[0], min[1], min[2]), + vec3.fromValues(max[0], min[1], max[2]), + vec3.fromValues(max[0], max[1], min[2]), + vec3.fromValues(max[0], max[1], max[2])] + + + // Transform all bounding box vertices + for(let i in boxVertices) { + vec3.transformMat4(boxVertices[i], boxVertices[i], worldTransform); + } + + // Create new (axis-aligned) bounding box out of transformed bounding box + const boxMin = vec3.clone(boxVertices[0]); // initialize + const boxMax = vec3.clone(boxVertices[0]); + + for(let i in boxVertices) { + for (const component of [0, 1, 2]) { + boxMin[component] = Math.min(boxMin[component], boxVertices[i][component]); + boxMax[component] = Math.max(boxMax[component], boxVertices[i][component]); + } } - vec3.transformMat4(boxMax, max, worldTransform); const center = vec3.create(); vec3.add(center, boxMax, boxMin);