@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
238 lines (237 loc) • 7.97 kB
JavaScript
;
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);
}
}