polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
323 lines (322 loc) • 8.83 kB
JavaScript
import {Vector3 as Vector32} from "three/src/math/Vector3";
import {Group as Group2} from "three/src/objects/Group";
import {Box3 as Box32} from "three/src/math/Box3";
import {CoreObject} from "./Object";
import {CoreGeometry} from "./Geometry";
import {CoreAttribute} from "./Attribute";
import {CoreString} from "../String";
import {CoreConstant, objectTypeFromConstructor} from "./Constant";
import {CoreType} from "../Type";
import {ArrayUtils as ArrayUtils2} from "../ArrayUtils";
export class CoreGroup {
constructor() {
this._objects = [];
this._objects_with_geo = [];
this.touch();
}
timestamp() {
return this._timestamp;
}
touch() {
this._timestamp = performance.now();
this.reset();
}
reset() {
this._bounding_box = void 0;
this._core_geometries = void 0;
this._core_objects = void 0;
}
clone() {
const core_group = new CoreGroup();
if (this._objects) {
const objects = [];
for (let object of this._objects) {
objects.push(CoreObject.clone(object));
}
core_group.setObjects(objects);
}
return core_group;
}
setObjects(objects) {
this._objects = objects;
this._objects_with_geo = objects.filter((obj) => obj.geometry != null);
this.touch();
}
objects() {
return this._objects;
}
objectsWithGeo() {
return this._objects_with_geo;
}
coreObjects() {
return this._core_objects = this._core_objects || this._create_core_objects();
}
_create_core_objects() {
if (this._objects) {
return this._objects.map((object, i) => new CoreObject(object, i));
}
return [];
}
objectsData() {
if (this._objects) {
return this._objects.map((object) => this._objectData(object));
}
return [];
}
_objectData(object) {
let points_count = 0;
if (object.geometry) {
points_count = CoreGeometry.pointsCount(object.geometry);
}
return {
type: objectTypeFromConstructor(object.constructor),
name: object.name,
children_count: object.children.length,
points_count
};
}
geometries() {
const list = [];
for (let core_object of this.coreObjects()) {
const geometry = core_object.object().geometry;
if (geometry) {
list.push(geometry);
}
}
return list;
}
coreGeometries() {
return this._core_geometries = this._core_geometries || this._createCoreGeometries();
}
_createCoreGeometries() {
const list = [];
for (let geometry of this.geometries()) {
list.push(new CoreGeometry(geometry));
}
return list;
}
static geometryFromObject(object) {
if (object.isMesh || object.isLine || object.isPoints) {
return object.geometry;
}
return null;
}
faces() {
return this.coreGeometries().map((g) => g.faces()).flat();
}
points() {
return this.coreGeometries().map((g) => g.points()).flat();
}
pointsCount() {
return ArrayUtils2.sum(this.coreGeometries().map((g) => g.pointsCount()));
}
totalPointsCount() {
if (this._objects) {
let sum = 0;
for (let object of this._objects) {
object.traverse((object2) => {
const geometry = object2.geometry;
if (geometry) {
sum += CoreGeometry.pointsCount(geometry);
}
});
}
return sum;
} else {
return 0;
}
}
pointsFromGroup(group) {
if (group) {
const indices = CoreString.indices(group);
const points = this.points();
return ArrayUtils2.compact(indices.map((i) => points[i]));
} else {
return this.points();
}
}
static _fromObjects(objects) {
const core_group = new CoreGroup();
core_group.setObjects(objects);
return core_group;
}
objectsFromGroup(group_name) {
return this.coreObjectsFromGroup(group_name).map((co) => co.object());
}
coreObjectsFromGroup(group_name) {
group_name = group_name.trim();
if (group_name !== "") {
const index = parseInt(group_name);
if (!CoreType.isNaN(index)) {
return ArrayUtils2.compact([this.coreObjects()[index]]);
} else {
return this.coreObjects().filter((core_object) => {
return CoreString.matchMask(group_name, core_object.name());
});
}
} else {
return this.coreObjects();
}
}
boundingBox() {
return this._bounding_box = this._bounding_box || this._compute_bounding_box();
}
center() {
const center = new Vector32();
this.boundingBox().getCenter(center);
return center;
}
size() {
const size = new Vector32();
this.boundingBox().getSize(size);
return size;
}
_compute_bounding_box() {
let bbox;
if (this._objects) {
for (let object of this._objects) {
const geometry = object.geometry;
if (geometry) {
geometry.computeBoundingBox();
if (bbox) {
bbox.expandByObject(object);
} else {
if (geometry.boundingBox) {
bbox = geometry.boundingBox.clone();
}
}
}
}
}
bbox = bbox || new Box32(new Vector32(-1, -1, -1), new Vector32(1, 1, 1));
return bbox;
}
computeVertexNormals() {
for (let object of this.coreObjects()) {
object.computeVertexNormals();
}
}
hasAttrib(name) {
let first_geometry;
if ((first_geometry = this.coreGeometries()[0]) != null) {
return first_geometry.hasAttrib(name);
} else {
return false;
}
}
attribType(name) {
const first_core_geometry = this.coreGeometries()[0];
if (first_core_geometry != null) {
return first_core_geometry.attribType(name);
} else {
return null;
}
}
objectAttribType(name) {
const first_core_object = this.coreObjects()[0];
if (first_core_object != null) {
return first_core_object.attribType(name);
} else {
return null;
}
}
renameAttrib(old_name, new_name, attrib_class) {
switch (attrib_class) {
case CoreConstant.ATTRIB_CLASS.VERTEX:
if (this.hasAttrib(old_name)) {
if (this._objects) {
for (let object of this._objects) {
object.traverse((child) => {
const geometry = CoreGroup.geometryFromObject(child);
if (geometry) {
const core_geometry = new CoreGeometry(geometry);
core_geometry.renameAttrib(old_name, new_name);
}
});
}
}
}
break;
case CoreConstant.ATTRIB_CLASS.OBJECT:
if (this.hasAttrib(old_name)) {
if (this._objects) {
for (let object of this._objects) {
object.traverse((child) => {
const core_object = new CoreObject(child, 0);
core_object.renameAttrib(old_name, new_name);
});
}
}
}
break;
}
}
attribNames() {
let first_geometry;
if ((first_geometry = this.coreGeometries()[0]) != null) {
return first_geometry.attribNames();
} else {
return [];
}
}
objectAttribNames() {
let first_object;
if ((first_object = this.coreObjects()[0]) != null) {
return first_object.attribNames();
} else {
return [];
}
}
attribNamesMatchingMask(masks_string) {
const masks = CoreString.attribNames(masks_string);
const matching_attrib_names = [];
for (let attrib_name of this.attribNames()) {
for (let mask of masks) {
if (CoreString.matchMask(attrib_name, mask)) {
matching_attrib_names.push(attrib_name);
}
}
}
return ArrayUtils2.uniq(matching_attrib_names);
}
attribSizes() {
let first_geometry;
if ((first_geometry = this.coreGeometries()[0]) != null) {
return first_geometry.attribSizes();
} else {
return {};
}
}
objectAttribSizes() {
let first_object;
if ((first_object = this.coreObjects()[0]) != null) {
return first_object.attribSizes();
} else {
return {};
}
}
attribSize(attrib_name) {
let first_geometry;
if ((first_geometry = this.coreGeometries()[0]) != null) {
return first_geometry.attribSize(attrib_name);
} else {
return 0;
}
}
addNumericVertexAttrib(name, size, default_value) {
if (default_value == null) {
default_value = CoreAttribute.default_value(size);
}
for (let core_geometry of this.coreGeometries()) {
core_geometry.addNumericAttrib(name, size, default_value);
}
}
static clone(src_group) {
const new_group = new Group2();
src_group.children.forEach((src_object) => {
const new_object = CoreObject.clone(src_object);
new_group.add(new_object);
});
return new_group;
}
}