133 lines
4.0 KiB
JavaScript
133 lines
4.0 KiB
JavaScript
class Model extends THREE.Mesh {
|
|
constructor(path) {
|
|
let geometry = new THREE.Geometry();
|
|
let materials = [
|
|
new THREE.MeshLambertMaterial( { color: 0xffffff, side: THREE.DoubleSide } ),
|
|
new THREE.MeshBasicMaterial( { transparent: true, opacity: 0 } )
|
|
];
|
|
super(geometry, materials);
|
|
this.frustumCulled = false;
|
|
this.path = path;
|
|
this.vertices = [];
|
|
this.currentLine = 1;
|
|
}
|
|
|
|
throwError(message) {
|
|
let e = new Error("In " + this.path + ":L" + this.currentLine + " " + message);
|
|
e.type = "custom";
|
|
throw e;
|
|
}
|
|
|
|
checkVertex(id) {
|
|
if (this.geometry.vertices[id] === undefined) {
|
|
this.throwError("EditVertex requires vertex " + (id + 1) + " but there is no such vertex");
|
|
}
|
|
}
|
|
|
|
checkFaceId(id) {
|
|
if (this.geometry.faces[id] === undefined) {
|
|
this.throwError("EditFace requires face " + (id + 1) + " but there is no such face");
|
|
}
|
|
}
|
|
|
|
checkFace(f) {
|
|
let vertices = this.geometry.vertices;
|
|
|
|
if (vertices[f.a] === undefined) {
|
|
this.throwError("Face requires vertex " + (f.a + 1) + " but there is no such vertex");
|
|
}
|
|
|
|
if (vertices[f.b] === undefined) {
|
|
this.throwError("Face requires vertex " + (f.b + 1) + " but there is no such vertex");
|
|
}
|
|
|
|
if (vertices[f.c] === undefined) {
|
|
this.throwError("Face requires vertex " + (f.c + 1) + " but there is no such vertex");
|
|
}
|
|
|
|
}
|
|
|
|
manageElement(element) {
|
|
|
|
let vertices = this.geometry.vertices;
|
|
let f, normal;
|
|
|
|
switch (element.type) {
|
|
case Element.AddVertex:
|
|
this.geometry.vertices.push(element.value);
|
|
this.geometry.verticesNeedUpdate = true;
|
|
break;
|
|
|
|
case Element.EditVertex:
|
|
this.checkVertex(element.id);
|
|
this.geometry.vertices[element.id].copy(element.value);
|
|
this.geometry.verticesNeedUpdate = true;
|
|
break;
|
|
|
|
case Element.AddFace:
|
|
|
|
f = element.value;
|
|
this.checkFace(f);
|
|
normal =
|
|
vertices[f.b].clone().sub(vertices[f.a])
|
|
.cross(vertices[f.c].clone().sub(vertices[f.a]));
|
|
normal.normalize();
|
|
|
|
f.normal = normal;
|
|
f.materialIndex = 0;
|
|
this.geometry.faces.push(f);
|
|
this.geometry.elementsNeedUpdate = true;
|
|
break;
|
|
|
|
case Element.AddTriangleStrip:
|
|
case Element.AddTriangleFan:
|
|
|
|
for (let f of element.value) {
|
|
|
|
this.checkFace(f);
|
|
let normal =
|
|
vertices[f.b].clone().sub(vertices[f.a])
|
|
.cross(vertices[f.c].clone().sub(vertices[f.a]));
|
|
normal.normalize();
|
|
|
|
f.normal = normal;
|
|
f.materialIndex = 0;
|
|
this.geometry.faces.push(f);
|
|
|
|
}
|
|
|
|
this.geometry.elementsNeedUpdate = true;
|
|
|
|
break;
|
|
|
|
case Element.EditFace:
|
|
|
|
f = element.value;
|
|
this.checkFaceId(element.id);
|
|
this.checkFace(f);
|
|
normal =
|
|
vertices[f.b].clone().sub(vertices[f.a])
|
|
.cross(vertices[f.c].clone().sub(vertices[f.a]));
|
|
normal.normalize();
|
|
|
|
f.normal = normal;
|
|
|
|
|
|
this.geometry.faces[element.id] = f;
|
|
this.geometry.elementsNeedUpdate = true;
|
|
break;
|
|
|
|
case Element.DeleteFace:
|
|
this.geometry.faces[element.id].materialIndex = 1;
|
|
this.geometry.elementsNeedUpdate = true;
|
|
break;
|
|
|
|
|
|
default:
|
|
throw new Error("unknown element type: " + element.type);
|
|
}
|
|
|
|
this.currentLine++;
|
|
}
|
|
}
|