UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

238 lines (237 loc) 7.97 kB
"use strict"; import { Color, Sphere, Vector3 } from "three"; import { cloneBufferGeometry } from "../../Geometry"; import { AttribClass, dataFromObject } from "../../Constant"; import { objectData } from "../../entities/object/BaseCoreObjectUtils"; import { applyCustomMaterials } from "../../Material"; import { objectCloneDeep } from "../../../ObjectUtils"; import { ThreeMeshBVHHelper } from "../../bvh/ThreeMeshBVHHelper"; import { CoreGeometryBuilderMerge } from "./builders/Merge"; import { objectContentCopyProperties } from "../../ObjectContent"; import { BaseCoreObject } from "../../entities/object/BaseCoreObject"; import { TransformTargetType } from "../../../Transform"; import { TypeAssert } from "../../../../engine/poly/Assert"; import { applyTransformWithSpaceToObject } from "../../../TransformSpace"; import { BaseSopOperation } from "../../../../engine/operations/sop/_Base"; import { primitiveClassFactoryNonAbstract } from "./ThreeModule"; import { ThreejsVertex } from "./ThreejsVertex"; import { ThreejsPoint } from "./ThreejsPoint"; import { arrayCopy } from "../../../ArrayUtils"; const COMPUTE_PRECISE_BOUNDS = true; const SPHERE_EMPTY = new Sphere(new Vector3(0, 0, 0), 0); export class ThreejsCoreObject extends BaseCoreObject { constructor(_object, index) { super(_object, index); this._object = _object; } humanType() { return dataFromObject(this._object).humanName; } object() { return this._object; } geometry() { return this._object.geometry; } // object():Object3D{ // return this._object // } // coreGeometry(): CoreGeometry | null { // const geo = this.geometry(); // if (geo) { // return new CoreGeometry(geo); // } else { // return null; // } // // const geo = this.geometry() // // if (geo) { // // return new CoreGeometry(geo) // // } else { // // return null // // } // } static objectData(object) { const data = objectData(object); data.verticesCount = ThreejsVertex.entitiesCount(object); data.pointsCount = ThreejsPoint.entitiesCount(object); const primitiveClass = primitiveClassFactoryNonAbstract(object); data.primitivesCount = (primitiveClass == null ? void 0 : primitiveClass.entitiesCount(object)) || 0; data.primitiveName = (primitiveClass == null ? void 0 : primitiveClass.primitiveName()) || ""; return data; } static position(object, target) { target.copy(object.position); } static boundingBox(object, target) { target.setFromObject(object, COMPUTE_PRECISE_BOUNDS); } static geometryBoundingBox(object, target) { const geometry = object.geometry; if (geometry) { if (!geometry.boundingBox) { geometry.computeBoundingBox(); } if (geometry.boundingBox) { target.copy(geometry.boundingBox); } } else { target.makeEmpty(); } } static boundingSphere(object, target) { const geometry = object.geometry; if (!geometry) { target.copy(SPHERE_EMPTY); return; } geometry.computeBoundingSphere(); const computedSphere = geometry.boundingSphere; if (!computedSphere) { target.copy(SPHERE_EMPTY); return; } target.copy(computedSphere); } static geometryBoundingSphere(object, target) { this.boundingSphere(object, target); } // computeVertexNormals() { // this.coreGeometry()?.computeVertexNormals(); // } static clone(srcObject) { const clonedObject = srcObject.clone(); var sourceLookup = /* @__PURE__ */ new Map(); var cloneLookup = /* @__PURE__ */ new Map(); ThreejsCoreObject.parallelTraverse( srcObject, clonedObject, function(sourceNode, clonedNode) { sourceLookup.set(clonedNode, sourceNode); cloneLookup.set(sourceNode, clonedNode); } ); clonedObject.traverse(function(node) { const srcNode = sourceLookup.get(node); const meshNode = node; if (meshNode.geometry && srcNode && srcNode.geometry) { const srcNodeGeometry = srcNode.geometry; meshNode.geometry = cloneBufferGeometry(srcNodeGeometry); ThreeMeshBVHHelper.copyBVH(meshNode, srcNode); } if (meshNode.material) { applyCustomMaterials(node, meshNode.material); const material_with_color = meshNode.material; if (material_with_color.color == null) { material_with_color.color = new Color(1, 1, 1); } } if (srcNode) { if (srcNode.userData) { node.userData = objectCloneDeep(srcNode.userData); } const src_node_with_animations = srcNode; if (src_node_with_animations.animations) { node.animations = src_node_with_animations.animations.map( (animation) => animation.clone() ); } const skinned_node = node; if (skinned_node.isSkinnedMesh) { var clonedMesh = skinned_node; var sourceMesh = srcNode; var sourceBones = sourceMesh.skeleton.bones; clonedMesh.skeleton = sourceMesh.skeleton.clone(); clonedMesh.bindMatrix.copy(sourceMesh.bindMatrix); const new_bones = sourceBones.map(function(bone) { return cloneLookup.get(bone); }); clonedMesh.skeleton.bones = new_bones; clonedMesh.bind(clonedMesh.skeleton, clonedMesh.bindMatrix); } } }); return clonedObject; } static parallelTraverse(a, b, callback) { callback(a, b); for (var i = 0; i < a.children.length; i++) { const childA = a.children[i]; const childB = b.children[i]; if (childA && childB) { this.parallelTraverse(childA, childB, callback); } } } static applyMatrix(object, matrix, transformTargetType, transformSpace, transformMode) { switch (transformTargetType) { case TransformTargetType.OBJECT: { applyTransformWithSpaceToObject(object, matrix, transformSpace, transformMode); return; } case TransformTargetType.GEOMETRY: { const geometry = object.geometry; if (geometry) { geometry.applyMatrix4(matrix); } return; } } TypeAssert.unreachable(transformTargetType); } static mergeCompact(options) { const { objects, material, objectType, mergedObjects, onError } = options; const firstObject = objects[0]; if (!firstObject) { return; } const geometries = []; for (const object of objects) { const geometry = object.geometry; if (geometry) { geometry.applyMatrix4(object.matrix); geometries.push(geometry); } } try { const mergedGeometry = CoreGeometryBuilderMerge.merge(geometries); if (mergedGeometry) { const newObject = BaseSopOperation.createObject(mergedGeometry, objectType, material); if (newObject) { objectContentCopyProperties(firstObject, newObject); mergedObjects.push(newObject); } } else { onError("merge failed, check that input geometries have the same attributes"); } } catch (e) { onError(e.message || "unknown error"); } } // // // RELATED ENTITIES // // static relatedPrimitiveIds(object, index, target, traversedRelatedEntityData) { const _primitiveClassFactory = primitiveClassFactoryNonAbstract(object); if (!_primitiveClassFactory) { target.length = 0; return; } const count = _primitiveClassFactory == null ? void 0 : _primitiveClassFactory.entitiesCount(object); target.length = count; for (let i = 0; i < count; i++) { target[i] = i; } if (traversedRelatedEntityData && traversedRelatedEntityData[AttribClass.PRIMITIVE].ids != target) { arrayCopy(target, traversedRelatedEntityData[AttribClass.PRIMITIVE].ids); } } static relatedPrimitiveClass(object) { return primitiveClassFactoryNonAbstract(object); } }