add model groups

This commit is contained in:
Stewart Allen 2021-12-30 22:59:46 -05:00
commit e43f6c6bc2
5 changed files with 103 additions and 33 deletions

11
app.js
View file

@ -47,11 +47,18 @@ function init(mod) {
let depcache = {}; let depcache = {};
function find_deps(path) { function find_deps(path, seen = []) {
let cached = depcache[path]; let cached = depcache[path];
if (cached) { if (cached) {
return cached; return cached;
} }
if (seen.indexOf(path) >= 0) {
if (debug) {
console.log(`circular dependency at ${path}`, seen);
}
return [];
}
seen.push(path);
let deps = [ "main/gapp" ]; let deps = [ "main/gapp" ];
let lines = fs.readFileSync(`${dir}/src/${path}.js`) let lines = fs.readFileSync(`${dir}/src/${path}.js`)
.toString() .toString()
@ -63,7 +70,7 @@ function init(mod) {
if (deps.indexOf(dep) < 0) { if (deps.indexOf(dep) < 0) {
deps.push(dep); deps.push(dep);
} }
let deep = find_deps(dep); let deep = find_deps(dep, seen);
deps = deps.filter(p => deep.indexOf(p) < 0); deps = deps.filter(p => deep.indexOf(p) < 0);
// deeper dependencies go first // deeper dependencies go first
deps = [...deep, ...deps]; deps = [...deep, ...deps];

View file

@ -84,7 +84,7 @@ broker.subscribe('space_init', data => {
// add object loader // add object loader
broker.subscribe('space_load', data => { broker.subscribe('space_load', data => {
mesh.api.models.add(data.flat().map(el => new mesh.model(el))); mesh.api.group.new(data.flat().map(el => new mesh.model(el)));
}); });
// remove version cache bust from url // remove version cache bust from url

View file

@ -18,41 +18,42 @@ let mesh = self.mesh = self.mesh || {};
if (mesh.api) return; if (mesh.api) return;
let space = moto.Space; let space = moto.Space;
let models = []; let groups = [];
let api = mesh.api = { let api = mesh.api = {
models: { group: {
get all() { list() {
return models.slice(); return groups.slice();
}, },
add: (list, group = new THREE.Group()) => { // @param group {MeshModel[]}
if (!Array.isArray(list)) { new: (models) => {
list = [ list ]; api.group.add(new mesh.group(models));
}
for (let model of list) {
models.addOnce(model);
model.group = group;
group.add(model.mesh);
}
space.world.add(group);
space.refresh();
}, },
remove: list => { // @param group {MeshGroup}
if (!Array.isArray(list)) { add: (group) => {
list = [ list ]; groups.addOnce(group);
} space.world.add(group.group);
for (let model of list) { space.update();
if (models.remove(model)) { },
model.group.remove(model.mesh);
if (model.group.children.length === 0) { // @param group {MeshGroup}
space.world.remove(model.group); remove: (group) => {
} groups.remove(group);
space.refresh(); space.world.remove(group.group);
} space.update();
} }
},
model: {
list() {
return groups.map(g => g.models).flat();
},
remove: (model) => {
model.group.remove(model);
} }
} }
}; };

53
src/mesh/group.js Normal file
View file

@ -0,0 +1,53 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
(function() {
gapp.register("mesh.group", [
"add.array", // dep: add.array
"add.three", // dep: add.three
"moto.license", // dep: moto.license
"mesh.model", // dep: mesh.model
]);
let mesh = self.mesh = self.mesh || {};
if (mesh.group) return;
mesh.group = class MeshGroup {
// @param group {THREE.Group}
constructor(models) {
this.group = new THREE.Group();
this.models = [];
for (let model of (models || [])) {
this.add(model);
}
}
bounds() {
return new THREE.Box3().setFromObject(this.group);
}
// @param model {MeshModel}
add(model) {
model.group = this;
this.models.addOnce(model);
this.group.add(model.mesh);
moto.Space.update();
}
// @param model {MeshModel}
remove(model) {
model.group = undefined;
this.models.remove(model);
this.group.remove(model.mesh);
// auto-remove group when empty
if (this.group.children.length === 0) {
mesh.api.group.remove(this);
}
moto.Space.update();
}
};
})();

View file

@ -7,6 +7,7 @@
gapp.register("mesh.model", [ gapp.register("mesh.model", [
"add.three", // dep: add.three "add.three", // dep: add.three
"moto.license", // dep: moto.license "moto.license", // dep: moto.license
"mesh.group", // dep: mesh.group
]); ]);
let mesh = self.mesh = self.mesh || {}; let mesh = self.mesh = self.mesh || {};
@ -37,6 +38,10 @@ mesh.model = class MeshModel {
this.mesh = this.load(mesh); this.mesh = this.load(mesh);
} }
bounds() {
return new THREE.Box3().setFromObject(this.mesh);
}
load(vertices, indices) { load(vertices, indices) {
let geo = new THREE.BufferGeometry(); let geo = new THREE.BufferGeometry();
if (indices) geo.setIndex(new THREE.BufferAttribute(indices, 1)); if (indices) geo.setIndex(new THREE.BufferAttribute(indices, 1));
@ -57,11 +62,15 @@ mesh.model = class MeshModel {
} }
set group(gv) { set group(gv) {
if (this._group && this._group !== gv) { if (gv && this._group && this._group !== gv) {
throw "model cannot change groups"; throw "models can only belong to one group";
} }
this._group = gv; this._group = gv;
} }
remove() {
mesh.api.model.remove(this);
}
}; };
})(); })();