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