Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 5x 5x 5x 5x 5x 5x 5x 3x 3x 3x 3x 5x 5x 5x 5x 5x 5x 2x 3x 3x 3x 3x 3x 3x 3x 3x 3x 1x 3x 3x 3x 3x 9x 9x 9x 16x 16x 16x 33x 33x 9x 36x 21x 15x 15x 9x | /*!
* Copyright 2020 Cognite AS
*/
import * as THREE from 'three';
import { WantedSectors, SectorMetadata, SectorScene, DetermineSectorsInput } from './types';
import { traverseDepthFirst, traverseUpwards } from '../../utils/traversal';
import { toThreeMatrix4, toThreeVector3 } from '../../views/threejs/utilities';
import { mat4 } from 'gl-matrix';
import { defaultLoadingHints as defaultCadLoadingHints } from './CadLoadingHints';
const degToRadFactor = Math.PI / 180;
const determineSectorsPreallocatedVars = {
invertCameraModelMatrix: mat4.create(),
frustumMatrix: mat4.create(),
frustum: new THREE.Frustum(),
bbox: new THREE.Box3(),
min: new THREE.Vector3(),
max: new THREE.Vector3()
};
export async function defaultDetermineSectors(params: DetermineSectorsInput): Promise<WantedSectors> {
const hints = { ...defaultCadLoadingHints, ...(params.loadingHints || {}) };
const { scene, cameraPosition, cameraModelMatrix, projectionMatrix, cameraFov } = params;
const { invertCameraModelMatrix, frustumMatrix, frustum, bbox, min, max } = determineSectorsPreallocatedVars;
const sectors: SectorMetadata[] = [];
const distanceToCameraVars = {
threeJsVec3: new THREE.Vector3()
};
function distanceToCamera(s: SectorMetadata) {
const { threeJsVec3 } = distanceToCameraVars;
min.set(s.bounds.min[0], s.bounds.min[1], s.bounds.min[2]);
max.set(s.bounds.max[0], s.bounds.max[1], s.bounds.max[2]);
bbox.makeEmpty();
bbox.expandByPoint(min);
bbox.expandByPoint(max);
return bbox.distanceToPoint(toThreeVector3(threeJsVec3, cameraPosition));
}
Iif (!mat4.invert(invertCameraModelMatrix, cameraModelMatrix)) {
throw new Error('Provided camera model matrix is not invertible');
}
mat4.multiply(frustumMatrix, projectionMatrix, invertCameraModelMatrix);
frustum.setFromMatrix(toThreeMatrix4(frustumMatrix));
traverseDepthFirst(scene.root, sector => {
min.set(sector.bounds.min[0], sector.bounds.min[1], sector.bounds.min[2]);
max.set(sector.bounds.max[0], sector.bounds.max[1], sector.bounds.max[2]);
bbox.makeEmpty();
bbox.expandByPoint(min);
bbox.expandByPoint(max);
if (!frustum.intersectsBox(bbox)) {
return false;
}
const screenHeight = 2.0 * distanceToCamera(sector) * Math.tan((cameraFov / 2) * degToRadFactor);
const largestAllowedQuadSize = hints.maxQuadSize * screenHeight; // no larger than x percent of the height
const quadSize = (() => {
Eif (!sector.simple) {
// Making the quad infinite in size means we will always use the detailed version instead
return Infinity;
}
return sector.simple.gridIncrement;
})();
Iif (quadSize < largestAllowedQuadSize) {
return false;
}
sectors.push(sector);
return true;
});
// TODO 2020-01-21 larsmoa: Waste since we add sectors in a set below
sectors.sort((l, r) => {
return distanceToCamera(l) - distanceToCamera(r);
});
const requestedDetailed = new Set<number>(sectors.map(x => x.id));
const result = determineSectorsQuality(scene, requestedDetailed);
return result;
}
export function determineSectorsQuality(scene: SectorScene, requestedDetailed: Set<number>): WantedSectors {
const simple: number[] = [];
const detailed: number[] = [];
for (const sectorId of requestedDetailed) {
const sector = scene.sectors.get(sectorId);
Iif (!sector) {
throw new Error(`Could not find sector with ID ${sectorId}`);
}
traverseUpwards(sector, (other: SectorMetadata) => {
detailed.push(other.id);
return true;
});
}
traverseDepthFirst(scene.root, sector => {
if (detailed.includes(sector.id)) {
return true;
}
simple.push(sector.id);
return false;
});
return {
detailed: new Set<number>(detailed),
simple: new Set<number>(simple)
};
}
|