vim-webgl-component
Version:
A demonstration app built on top of the vim-webgl-viewer
324 lines (323 loc) • 12.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.G3dSubsetOG = exports.G3dSubset2 = void 0;
const g3d_1 = require("./g3d");
const g3dMeshIndex_1 = require("./g3dMeshIndex");
const g3dMeshOffsets_1 = require("./g3dMeshOffsets");
class G3dSubset2 {
constructor(source,
//source-based indices of included instanced
instances) {
this._source = source;
// TODO: Remove this
if (!instances) {
instances = new Array();
for (let i = 0; i < source.instanceMeshes.length; i++) {
if (source.instanceMeshes[i] >= 0) {
instances.push(i);
}
}
}
this._instances = instances;
this._meshes = new Array();
const map = new Map();
instances.forEach(instance => {
const mesh = source.instanceMeshes[instance];
const index = source instanceof g3dMeshIndex_1.G3dMeshIndex ? source.instanceIndices[instance] : instance;
if (!map.has(mesh)) {
this._meshes.push(mesh);
map.set(mesh, [index]);
}
else {
map.get(mesh).push(index);
}
});
this._meshInstances = new Array(this._meshes.length);
this._meshes.forEach((m, i) => this._meshInstances[i] = map.get(m));
}
getMesh(index) {
return this._meshes?.[index] ?? index;
}
getMeshCount() {
return this._meshes?.length ?? this._source.getMeshCount();
}
/**
* Returns index count for given mesh and section.
*/
getMeshIndexCount(mesh, section) {
const instances = this.getMeshInstanceCount(mesh);
const indices = this._source.getMeshIndexCount(this.getMesh(mesh), section);
return indices * instances;
}
/**
* Returns vertext count for given mesh and section.
*/
getMeshVertexCount(mesh, section) {
const instances = this.getMeshInstanceCount(mesh);
const vertices = this._source.getMeshVertexCount(this.getMesh(mesh), section);
return vertices * instances;
}
/**
* Returns instance count for given mesh.
* @param mesh The index of the mesh from the g3dIndex.
*/
getMeshInstanceCount(mesh) {
return this._meshInstances
? this._meshInstances[mesh].length
: this._source.getMeshInstanceCount(this.getMesh(mesh));
}
/**
* Returns the list of mesh-based instance indices for given mesh or undefined if all instances are included.
* @param mesh The index of the mesh from the g3dIndex.
*/
getMeshInstances(mesh) {
return this._meshInstances?.[mesh];
}
/**
* Returns index-th mesh-based instance index for given mesh.
* @param mesh The index of the mesh from the g3dIndex.
*/
getMeshInstance(mesh, index) {
const instance = this._meshInstances
? this._meshInstances[mesh][index]
: index;
return instance;
}
/**
* Returns a new subset that only contains unique meshes.
*/
filterUniqueMeshes() {
return this.filterByCount(count => count === 1);
}
/**
* Returns a new subset that only contains non-unique meshes.
*/
filterNonUniqueMeshes() {
return this.filterByCount(count => count > 1);
}
filterByCount(predicate) {
const set = new Set();
this._meshInstances.forEach((instances, i) => {
if (predicate(instances.length)) {
set.add(this._meshes[i]);
}
});
const instances = this._instances.filter(instance => set.has(this._source.instanceMeshes[instance]));
return new G3dSubset2(this._source, instances);
}
/**
* Returns offsets needed to build geometry.
*/
getOffsets(section) {
return g3dMeshOffsets_1.G3dMeshOffsets.fromSubset(this, section);
}
getAttributeCounts(section = 'all') {
const result = new g3dMeshOffsets_1.G3dMeshCounts();
const count = this.getMeshCount();
for (let i = 0; i < count; i++) {
result.instances += this.getMeshInstanceCount(i);
result.indices += this.getMeshIndexCount(i, section);
result.vertices += this.getMeshVertexCount(i, section);
}
result.meshes = count;
return result;
}
getBoudingBox() {
if (this._instances.length === 0)
return;
if (this._source instanceof g3dMeshIndex_1.G3dMeshIndex) {
// To avoid including (0,0,0)
let box = new Float32Array(6);
const min = this._source.getInstanceMin(this._instances[0]);
const max = this._source.getInstanceMax(this._instances[0]);
box[0] = min[0];
box[1] = min[1];
box[2] = min[2];
box[3] = max[0];
box[4] = max[1];
box[5] = max[2];
for (let i = 1; i < this._instances.length; i++) {
const instance = this._instances[i];
const min = this._source.getInstanceMin(instance);
const max = this._source.getInstanceMax(instance);
minBox(box, min);
maxBox(box, max);
}
return box;
}
}
filter(mode, filter) {
if (filter === undefined || mode === undefined) {
return new G3dSubset2(this._source, undefined);
}
if (mode === 'instance') {
const instances = this.filterOnArray(filter, this._source.instanceNodes);
return new G3dSubset2(this._source, instances);
}
if (mode === 'mesh') {
const instances = this.filterOnArray(filter, this._source.instanceMeshes);
return new G3dSubset2(this._source, instances);
}
if (mode === 'tag' || mode === 'group') {
throw new Error("Filter Mode Not implemented");
}
}
filterOnArray(filter, array) {
const set = new Set(filter);
const result = new Array();
array.forEach((mesh, i) => {
if (set.has(mesh) && this._source.instanceMeshes[i] >= 0) {
result.push(i);
}
});
return result;
}
}
exports.G3dSubset2 = G3dSubset2;
/**
* Represents a filter applied to a G3dMeshIndex.
*/
class G3dSubsetOG {
/**
* @param index G3d source geometry.
* @param meshes indices of meshes to include or undefined if all meshes.
* @param meshToInstances indices of instances to include for each mesh or undefined if all meshes.
*/
constructor(index, instances, meshes, meshToInstances) {
this._source = index;
this._instances = instances;
this._meshes = meshes;
this._meshInstances = meshToInstances;
}
getBoudingBox() {
if (this._instances.length === 0)
return;
if (this._source instanceof g3dMeshIndex_1.G3dMeshIndex) {
// To avoid including (0,0,0)
let box = new Float32Array(6);
const min = this._source.getInstanceMin(this._instances[0]);
const max = this._source.getInstanceMax(this._instances[0]);
box[0] = min[0];
box[1] = min[1];
box[2] = min[2];
box[3] = max[0];
box[4] = max[1];
box[5] = max[2];
for (let i = 1; i < this._instances.length; i++) {
const instance = this._instances[i];
const min = this._source.getInstanceMin(instance);
const max = this._source.getInstanceMax(instance);
minBox(box, min);
maxBox(box, max);
}
return box;
}
}
getMesh(index) {
return this._meshes?.[index] ?? index;
}
getMeshCount() {
return this._meshes?.length ?? this._source.getMeshCount();
}
/**
* Returns index count for given mesh and section.
*/
getMeshIndexCount(mesh, section) {
const instances = this.getMeshInstanceCount(mesh);
const indices = this._source.getMeshIndexCount(this.getMesh(mesh), section);
return indices * instances;
}
/**
* Returns vertext count for given mesh and section.
*/
getMeshVertexCount(mesh, section) {
const instances = this.getMeshInstanceCount(mesh);
const vertices = this._source.getMeshVertexCount(this.getMesh(mesh), section);
return vertices * instances;
}
/**
* Returns instance count for given mesh.
* @param mesh The index of the mesh from the g3dIndex.
*/
getMeshInstanceCount(mesh) {
return this._meshInstances
? this._meshInstances[mesh].length
: this._source.getMeshInstanceCount(this.getMesh(mesh));
}
/**
* Returns index-th mesh-based instance index for given mesh. Returns -1 otherwise.
* @param mesh The index of the mesh from the g3dIndex.
*/
getMeshInstance(mesh, index) {
const instance = this._meshInstances
? this._meshInstances[mesh][index]
: index;
if (this._source instanceof g3d_1.G3d) {
// Dereference one more time. Meshes can sometime be unreferenced
const m = this.getMesh(mesh);
return this._source.meshInstances[m]?.[instance] ?? -1;
}
return instance;
}
/**
* Returns the list of mesh-based instance indices for given mesh or undefined if all instances are included.
* @param mesh The index of the mesh from the g3dIndex.
*/
getMeshInstances(mesh) {
return this._meshInstances?.[mesh];
}
/**
* Returns a new subset that only contains unique meshes.
*/
filterUniqueMeshes() {
return this.filterByCount(count => count === 1);
}
/**
* Returns a new subset that only contains non-unique meshes.
*/
filterNonUniqueMeshes() {
return this.filterByCount(count => count > 1);
}
filterByCount(predicate) {
const filteredMeshes = new Array();
const filteredInstances = this._meshInstances ? new Array() : undefined;
const count = this.getMeshCount();
for (let m = 0; m < count; m++) {
if (predicate(this.getMeshInstanceCount(m))) {
filteredMeshes.push(this.getMesh(m));
filteredInstances?.push(this.getMeshInstances(m));
}
}
const meshes = new Set(filteredMeshes);
const instances = this._instances?.filter(i => meshes.has(this._source.instanceMeshes[i]));
return new G3dSubsetOG(this._source, instances, filteredMeshes, filteredInstances);
}
/**
* Returns offsets needed to build geometry.
*/
getOffsets(section) {
return g3dMeshOffsets_1.G3dMeshOffsets.fromSubset(this, section);
}
getAttributeCounts(section = 'all') {
const result = new g3dMeshOffsets_1.G3dMeshCounts();
const count = this.getMeshCount();
for (let i = 0; i < count; i++) {
result.instances += this.getMeshInstanceCount(i);
result.indices += this.getMeshIndexCount(i, section);
result.vertices += this.getMeshVertexCount(i, section);
}
result.meshes = count;
return result;
}
}
exports.G3dSubsetOG = G3dSubsetOG;
function minBox(box, other) {
box[0] = Math.min(box[0], other[0]);
box[1] = Math.min(box[1], other[1]);
box[2] = Math.min(box[2], other[2]);
}
function maxBox(box, other) {
box[3] = Math.max(box[3], other[0]);
box[4] = Math.max(box[4], other[1]);
box[5] = Math.max(box[5], other[2]);
}