polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
95 lines (94 loc) • 3.23 kB
JavaScript
import {BaseSopOperation} from "./_Base";
import {objectTypeFromConstructor} from "../../geometry/Constant";
import {MapUtils as MapUtils2} from "../../MapUtils";
import {CoreGeometry} from "../../geometry/Geometry";
import {Group as Group3} from "three/src/objects/Group";
import {InputCloneMode as InputCloneMode2} from "../../../engine/poly/InputCloneMode";
export class MergeSopOperation extends BaseSopOperation {
static type() {
return "merge";
}
cook(input_contents, params) {
let all_objects = [];
for (let input_core_group of input_contents) {
if (input_core_group) {
const objects = input_core_group.objects();
if (params.compact) {
for (let object of objects) {
object.traverse((child) => {
all_objects.push(child);
});
}
} else {
for (let object of input_core_group.objects()) {
all_objects.push(object);
}
}
}
}
if (params.compact) {
all_objects = this._make_compact(all_objects);
}
for (let object of all_objects) {
object.traverse((o) => {
o.matrixAutoUpdate = false;
});
}
return this.create_core_group_from_objects(all_objects);
}
_make_compact(all_objects) {
const materials_by_object_type = new Map();
const objects_by_type = new Map();
const ordered_object_types = [];
for (let object of all_objects) {
object.traverse((object3d) => {
if (object3d instanceof Group3) {
return;
}
const object2 = object3d;
if (object2.geometry) {
const object_type = objectTypeFromConstructor(object2.constructor);
if (!ordered_object_types.includes(object_type)) {
ordered_object_types.push(object_type);
}
if (object_type) {
const found_mat = materials_by_object_type.get(object_type);
if (!found_mat) {
materials_by_object_type.set(object_type, object2.material);
}
MapUtils2.push_on_array_at_entry(objects_by_type, object_type, object2);
}
}
});
}
const merged_objects = [];
ordered_object_types.forEach((object_type) => {
const objects = objects_by_type.get(object_type);
if (objects) {
const geometries = [];
for (let object of objects) {
const geometry = object.geometry;
geometry.applyMatrix4(object.matrix);
geometries.push(geometry);
}
try {
const merged_geometry = CoreGeometry.merge_geometries(geometries);
if (merged_geometry) {
const material = materials_by_object_type.get(object_type);
const object = this.create_object(merged_geometry, object_type, material);
merged_objects.push(object);
} else {
this.states?.error.set("merge failed, check that input geometries have the same attributes");
}
} catch (e) {
this.states?.error.set(e);
}
}
});
return merged_objects;
}
}
MergeSopOperation.DEFAULT_PARAMS = {
compact: true
};
MergeSopOperation.INPUT_CLONED_STATE = InputCloneMode2.FROM_NODE;