UNPKG

@polygonjs/polygonjs

Version:

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

544 lines (543 loc) 14.5 kB
"use strict"; import { Box3, Vector2, Vector3, Vector4 } from "three"; import { CoreAttribute } from "./Attribute"; import { CoreString } from "../String"; import { AttribType, AttribClass } from "./Constant"; import { isString } from "../Type"; import { arraySum, arrayCompact, arrayPushItems, arrayCopy } from "../ArrayUtils"; import { Poly } from "../../engine/Poly"; import { isObject3D } from "./ObjectContent"; import { coreObjectClassFactory, coreObjectInstanceFactory } from "./CoreObjectFactory"; import { coreObjectAttributeTypesByName, coreObjectsAttribNames, coreObjectsAttribSizesByName } from "./entities/object/BaseCoreObjectUtils"; import { attribValueNonPrimitive, cloneAttribValue } from "./entities/utils/Common"; import { object3DHasGeometry } from "./GeometryUtils"; import { CoreEntity } from "./CoreEntity"; import { pointsCountFromObject, pointAttributeNames, hasPointAttribute, pointAttributeType, pointAttributeSizes, pointAttributeSize, pointsFromObjects } from "./entities/point/CorePointUtils"; import { CoreCadType, isCADObject } from "./modules/cad/CadCoreType"; import { isCSGObject } from "./modules/csg/CsgCoreType"; import { isQuadObject, isQuadOrThreejsObject } from "./modules/quad/QuadCoreType"; import { isTetObject } from "./modules/tet/TetCoreType"; import { TypeAssert } from "../../engine/poly/Assert"; import { ThreejsCoreObject } from "./modules/three/ThreejsCoreObject"; import { uniqRelatedEntities } from "./entities/utils/Common"; const tmpBox3 = new Box3(); const tmpPos = new Vector3(); const _indices = []; const _points = []; const _relatedPoints = []; const _relatedVertices = []; const _relatedPrimitives = []; const _relatedPrimitivesForObject = []; function objectTotalPointsCount(object) { let sum = 0; object.traverse((child) => { sum += pointsCountFromObject(child); }); return sum; } export class CoreGroup extends CoreEntity { constructor() { super(void 0, 0); this._allObjects = []; this._attributes = {}; this.touch(); } dispose() { if (this._allObjects) { for (const object of this._allObjects) { if (object.dispose) { object.dispose(); } } } this._allObjects.length = 0; } geometry() { return null; } builder() { return void 0; } // // // TIMESTAMP // // timestamp() { return this._timestamp; } touch() { const performance = Poly.performance.performanceManager(); this._timestamp = performance.now(); } // reset() { // // this.resetBoundingBox(); // // this._bounding_sphere = undefined; // // this._coreGeometries = undefined; // // this._coreObjects = undefined; // } resetBoundingBox() { } // // // CLONE // // clone() { const coreGroup = new CoreGroup(); if (this._allObjects) { const allCoreObjects = this.allCoreObjects(); const clonedObjects = []; for (const coreObject of allCoreObjects) { const clonedObject = coreObject.clone().object(); if (clonedObject) { clonedObjects.push(clonedObject); } } coreGroup.setAllObjects(clonedObjects); } const attribNames = this.attribNames(); for (const attribName of attribNames) { const value = this.attribValue(attribName); coreGroup.addAttribute(attribName, value); } return coreGroup; } // // // ALL OBJECTS // // setAllObjects(objects) { this._allObjects = objects; this.touch(); } allObjects() { return this._allObjects; } allCoreObjects() { var _a; return (_a = this.allObjects()) == null ? void 0 : _a.map((o, i) => coreObjectInstanceFactory(o, i)); } // // // CAD OBJECTS // // cadObjects() { var _a; const list = ((_a = this._allObjects) == null ? void 0 : _a.filter(isCADObject)) || void 0; return list; } cadObjectsWithShape() { var _a; return (_a = this.cadObjects()) == null ? void 0 : _a.filter((o) => CoreCadType.isShape(o)); } cadCoreObjects() { var _a; return (_a = this.cadObjects()) == null ? void 0 : _a.map((o, i) => coreObjectInstanceFactory(o, i)); } // // // CSG OBJECTS // // csgObjects() { var _a; const list = ((_a = this._allObjects) == null ? void 0 : _a.filter(isCSGObject)) || void 0; return list; } csgCoreObjects() { var _a; return (_a = this.csgObjects()) == null ? void 0 : _a.map((o, i) => coreObjectInstanceFactory(o, i)); } // // // QUAD OBJECTS // // quadObjects() { var _a; const list = ((_a = this._allObjects) == null ? void 0 : _a.filter(isQuadObject)) || void 0; return list; } quadCoreObjects() { var _a; return (_a = this.quadObjects()) == null ? void 0 : _a.map((o, i) => coreObjectInstanceFactory(o, i)); } threejsOrQuadObjects() { return this._allObjects ? this._allObjects.filter(isQuadOrThreejsObject) : []; } threejsOrQuadCoreObjects() { return this.threejsOrQuadObjects().map((o, i) => coreObjectInstanceFactory(o, i)); } // // // SDF OBJECTS // // // SDFObjects() { // const list = this._allObjects?.filter((o) => SDF_OBJECT_TYPES_SET.has(o.type as SDFObjectType)) || undefined; // return list as SDFObject[] | undefined; // } // SDFCoreObjects() { // return this.csgObjects()?.map((o, i) => coreObjectInstanceFactory(o, i)); // } // // // TET OBJECTS // // tetObjects() { var _a; const list = ((_a = this._allObjects) == null ? void 0 : _a.filter(isTetObject)) || void 0; return list; } tetCoreObjects() { var _a; return (_a = this.tetObjects()) == null ? void 0 : _a.map((o, i) => coreObjectInstanceFactory(o, i)); } // // // THREEJS OBJECTS // // threejsObjects() { return this._allObjects ? this._allObjects.filter(isObject3D) : []; } threejsObjectsWithGeo() { return this.threejsObjects().filter(object3DHasGeometry); } threejsCoreObjects() { return this.threejsObjects().map((o, i) => new ThreejsCoreObject(o, i)); } geometries() { return this.threejsObjectsWithGeo().map((o) => o.geometry); } // coreGeometries(): CoreGeometry[] { // return this.geometries().map((g) => new CoreGeometry(g)); // } // // // POINTS // // points(target) { return pointsFromObjects(this.allObjects(), target); } pointsCount() { return arraySum(this.allObjects().map((g) => pointsCountFromObject(g))); } totalPointsCount() { const threejsObjects = this.threejsObjects(); let sum = 0; for (const object of threejsObjects) { sum += objectTotalPointsCount(object); } return sum; } pointsFromGroup(group, target) { if (group) { CoreString.indices(group, _indices); this.points(_points); const compactPoints = []; const pointsInGroup = arrayCompact( _indices.map((i) => _points[i]), compactPoints ); target.length = 0; arrayPushItems(pointsInGroup, target); return target; } else { return this.points(target); } } pointAttribNames() { const firstObject = this.allObjects()[0]; if (firstObject) { return pointAttributeNames(firstObject); } else { return []; } } hasPointAttrib(attribName) { const firstObject = this.allObjects()[0]; if (firstObject) { return hasPointAttribute(firstObject, attribName); } else { return false; } } pointAttribType(attribName) { const firstObject = this.allObjects()[0]; if (firstObject) { return pointAttributeType(firstObject, attribName); } else { return AttribType.NUMERIC; } } pointAttribNamesMatchingMask(masksString) { return CoreAttribute.attribNamesMatchingMask(masksString, this.pointAttribNames()); } pointAttribSizes() { const firstObject = this.allObjects()[0]; if (firstObject) { return pointAttributeSizes(firstObject); } else { return {}; } } pointAttribSize(attribName) { const firstObject = this.allObjects()[0]; if (firstObject) { return pointAttributeSize(firstObject, attribName); } else { return 0; } } // // // OBJECTS // // static _fromObjects(objects) { const coreGroup = new CoreGroup(); coreGroup.setAllObjects(objects); return coreGroup; } objectAttribTypesByName() { return coreObjectAttributeTypesByName(this.allCoreObjects()); } objectAttribNames() { return coreObjectsAttribNames(this.allCoreObjects()); } objectAttribNamesMatchingMask(masksString) { return CoreAttribute.attribNamesMatchingMask(masksString, this.objectAttribNames()); } objectAttribSizesByName() { return coreObjectsAttribSizesByName(this.allCoreObjects()); } // // // // // renameAttribute(oldName, newName) { const attribValue = this.attribValue(oldName); if (attribValue == null) { return; } this.addAttribute(newName, attribValue); this.deleteAttribute(oldName); } attribNamesMatchingMask(masksString) { return CoreAttribute.attribNamesMatchingMask(masksString, this.attribNames()); } hasAttribute(attribName) { return this.attribValue(attribName) != null; } addAttribute(attribName, attribValue) { this.attributes()[attribName] = attribValue; } addNumericAttribute(attribName, size = 1, defaultValue = 0) { const attributes = this.attributes(); if (defaultValue != null) { if (attribValueNonPrimitive(defaultValue)) { const clonedDefaultValue = cloneAttribValue(defaultValue); if (clonedDefaultValue != null) { attributes[attribName] = clonedDefaultValue; } } else { attributes[attribName] = defaultValue; } } else { switch (size) { case 1: { return this.attributes()[attribName] = 0; } case 2: { return this.attributes()[attribName] = new Vector2(0, 0); } case 3: { return this.attributes()[attribName] = new Vector3(0, 0, 0); } case 4: { return this.attributes()[attribName] = new Vector4(0, 0, 0, 0); } } } } deleteAttribute(name) { delete this.attributes()[name]; } attribValue(attribName) { return this._attributes && this._attributes[attribName]; } attribNames() { return this._attributes ? Object.keys(this._attributes) : []; } attribType(name) { const val = this.attribValue(name); if (isString(val)) { return AttribType.STRING; } else { return AttribType.NUMERIC; } } attribSizes() { const h = {}; for (const attrib_name of this.attribNames()) { const size = this.attribSize(attrib_name); if (size != null) { h[attrib_name] = size; } } return h; } attribSize(name) { const val = this.attribValue(name); if (val == null) { return null; } return CoreAttribute.attribSizeFromValue(val); } attributes() { return this._attributes || this._createAttributesDictionaryIfNone(); } _createAttributesDictionaryIfNone() { if (!this._attributes) { this._attributes = {}; } return this._attributes; } // override setAttribValue(attribName, attribValue) { this.addAttribute(attribName, attribValue); } stringAttribValue(attribName) { return this.attribValue(attribName); } position(target) { const objectsCount = this._allObjects.length; target.set(0, 0, 0); for (const object of this._allObjects) { coreObjectClassFactory(object).position(object, tmpPos); target.add(tmpPos); } target.divideScalar(objectsCount); return target; } attributeNames() { const attributes = this.attributes(); if (!attributes) { return []; } return Object.keys(attributes); } attributeNamesMatchingMask(masksString) { return CoreAttribute.attribNamesMatchingMask(masksString, this.attributeNames()); } // // // RELATED ENTITIES // // relatedObjects(target, traversedRelatedEntityData) { arrayCopy(this.allCoreObjects(), target); } relatedPrimitives(target, traversedRelatedEntityData) { target.length = 0; const objects = this.allObjects(); let i = 0; for (const object of objects) { coreObjectClassFactory(object).relatedPrimitives(object, i, _relatedPrimitivesForObject); for (const _relatedPrimitiveForObject of _relatedPrimitivesForObject) { target.push(_relatedPrimitiveForObject); } i++; } } relatedVertices(target, traversedRelatedEntityData) { this.relatedPrimitives(_relatedPrimitives); uniqRelatedEntities( _relatedPrimitives, (primitive) => { primitive.relatedVertices(_relatedVertices); return _relatedVertices; }, target ); } relatedPoints(target, traversedRelatedEntityData) { this.relatedVertices(_relatedVertices); return uniqRelatedEntities( _relatedVertices, (vertex) => { vertex.relatedPoints(_relatedPoints); return _relatedPoints; }, target ); } relatedEntities(attribClass, coreGroup, target, traversedRelatedEntityData) { switch (attribClass) { case AttribClass.POINT: { this.relatedPoints(target, traversedRelatedEntityData); return; } case AttribClass.VERTEX: { this.relatedVertices(target, traversedRelatedEntityData); return; } case AttribClass.PRIMITIVE: { this.relatedPrimitives(target, traversedRelatedEntityData); return; } case AttribClass.OBJECT: { this.relatedObjects(target, traversedRelatedEntityData); return; } case AttribClass.CORE_GROUP: { target.length = 1; target[0] = coreGroup; return; } } TypeAssert.unreachable(attribClass); } // // // UTILS // // objectsData() { var _a; return ((_a = this._allObjects) == null ? void 0 : _a.map((o) => coreObjectClassFactory(o).objectData(o))) || []; } boundingBox(target) { target.makeEmpty(); const coreObjects = this.allCoreObjects(); for (const coreObject of coreObjects) { coreObject.boundingBox(tmpBox3); target.union(tmpBox3); } } static geometryFromObject(object) { if (object.isMesh || object.isLine || object.isPoints) { return object.geometry; } return null; } }