CSG
This commit is contained in:
parent
b82fdea3c4
commit
a03269603a
|
@ -42,10 +42,13 @@ Touchable = <touchable @shape Shape> .
|
|||
CSG = <csg @expr CSGExpr> .
|
||||
|
||||
CSGExpr =
|
||||
/ <mesh @shape Shape>
|
||||
/ <subtract @base CSGExpr @more [CSGExpr ...]>
|
||||
/ <union @shapes [CSGExpr ...]>
|
||||
/ <intersect @shapes [CSGExpr ...]>
|
||||
/ <mesh @shape Mesh>
|
||||
/ <scale @v Vector3 @shape CSGExpr>
|
||||
/ <move @v Vector3 @shape CSGExpr>
|
||||
/ <rotate @v Vector3 @shape CSGExpr>
|
||||
/ <subtract [@base CSGExpr @more CSGExpr ...]>
|
||||
/ <union [@base CSGExpr @more CSGExpr ...]>
|
||||
/ <intersect [@base CSGExpr @more CSGExpr ...]>
|
||||
/ <invert @shape CSGExpr>
|
||||
.
|
||||
|
||||
|
|
|
@ -66,7 +66,28 @@
|
|||
<color 0.5 0.5 0.0
|
||||
<box>>>>>>>
|
||||
|
||||
<sprite "house"
|
||||
<scale <v 10.0 4.0 15.0>
|
||||
<floor
|
||||
<move <v 1.5 0.5 -0.5> <box>>>>>
|
||||
<sprite "x"
|
||||
<move <v 10.0 1.6 -5.0>
|
||||
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
|
||||
<v 1.0 3.0 1.0>
|
||||
<v 0.0 0.0 0.0>]
|
||||
<csg
|
||||
<subtract [
|
||||
<move <v 0.0 0.0 0.5> <scale <v 1.1 3.1 1.1> <mesh <box>>>>
|
||||
<move <v 0.0 0.0 0.5> <scale <v 1.0 3.0 1.0> <mesh <box>>>>
|
||||
]>
|
||||
>
|
||||
>>>
|
||||
|
||||
<sprite "y"
|
||||
<move <v 12.0 0.75 -5.0>
|
||||
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
|
||||
<v 1.0 1.0 1.0>
|
||||
<v 0.0 0.0 0.0>]
|
||||
<csg
|
||||
<intersect [
|
||||
<scale <v 0.5 1.0 0.5> <mesh <box>>>
|
||||
<mesh <sphere>>
|
||||
]>
|
||||
>
|
||||
>>>
|
||||
|
|
|
@ -17,3 +17,16 @@
|
|||
<touchable <move <v 0.0 0.5 0.0> <plane>>>>>
|
||||
<scale <v 1.0 2.11 0.1> <move <v 0.0 0.5 0.6> <box>>>
|
||||
]>>>
|
||||
|
||||
<sprite "x"
|
||||
<move <v 0.0 0.0 10.0>
|
||||
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
|
||||
<v 1.0 3.0 1.0>
|
||||
<v 0.0 0.0 0.0>]
|
||||
<csg
|
||||
<subtract [
|
||||
<move <v 0.0 0.0 0.5> <scale <v 1.1 3.1 1.1> <mesh <box>>>>
|
||||
<move <v 0.0 0.0 0.5> <scale <v 1.0 3.0 1.0> <mesh <box>>>>
|
||||
]>
|
||||
>
|
||||
>>>
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
CSG,
|
||||
HemisphericLight,
|
||||
Material,
|
||||
Matrix,
|
||||
Mesh,
|
||||
MeshBuilder,
|
||||
Node,
|
||||
|
@ -177,32 +178,22 @@ function releaseTexture(entry: CachedTexture) {
|
|||
}
|
||||
}
|
||||
|
||||
export function buildMesh(name: string, scene: Scene | null, meshSpec: Shapes.Mesh): Mesh {
|
||||
switch (meshSpec._variant) {
|
||||
case "Sphere": return MeshBuilder.CreateSphere(name, {}, scene);
|
||||
case "Box": return MeshBuilder.CreateBox(name, {}, scene);
|
||||
case "Ground": {
|
||||
const v = v2(meshSpec.value.size);
|
||||
return MeshBuilder.CreateGround(name, { width: v.x, height: v.y }, scene ?? void 0);
|
||||
}
|
||||
case "Plane": return MeshBuilder.CreatePlane(name, {}, scene);
|
||||
}
|
||||
}
|
||||
|
||||
export function build(name: string, scene: Scene, shape: Shapes.Shape, customize: MeshCustomizer): ShapeTree {
|
||||
switch (shape._variant) {
|
||||
case "Mesh": {
|
||||
const mesh = shape.value;
|
||||
let t: ShapeTree<Mesh>;
|
||||
switch (mesh._variant) {
|
||||
case "Sphere":
|
||||
t = new ShapeTree<Mesh>(scene, shape, MeshBuilder.CreateSphere(name, {}, scene));
|
||||
break;
|
||||
case "Box":
|
||||
t = new ShapeTree<Mesh>(scene, shape, MeshBuilder.CreateBox(name, {}, scene));
|
||||
break;
|
||||
|
||||
case "Ground": {
|
||||
const v = v2(mesh.value.size);
|
||||
t = new ShapeTree(
|
||||
scene,
|
||||
shape,
|
||||
MeshBuilder.CreateGround(name, { width: v.x, height: v.y }, scene));
|
||||
break;
|
||||
}
|
||||
|
||||
case "Plane":
|
||||
t = new ShapeTree<Mesh>(scene, shape, MeshBuilder.CreatePlane(name, {}, scene));
|
||||
break;
|
||||
}
|
||||
const t = new ShapeTree<Mesh>(scene, shape, buildMesh(name, scene, shape.value));
|
||||
applyCustomizer(t, customize);
|
||||
return t;
|
||||
}
|
||||
|
@ -307,7 +298,10 @@ export function build(name: string, scene: Scene, shape: Shapes.Shape, customize
|
|||
});
|
||||
|
||||
case "CSG": {
|
||||
throw new Error("unimplemented");
|
||||
const t = new ShapeTree<Mesh>(
|
||||
scene, shape, buildCSG(shape.value.expr).toMesh(name, null, scene));
|
||||
applyCustomizer(t, customize);
|
||||
return t;
|
||||
}
|
||||
|
||||
case "Skybox": {
|
||||
|
@ -331,6 +325,63 @@ export function build(name: string, scene: Scene, shape: Shapes.Shape, customize
|
|||
}
|
||||
}
|
||||
|
||||
function emptyCSG(): CSG {
|
||||
const c = new CSG();
|
||||
c.matrix = Matrix.Identity();
|
||||
c.position = Vector3.Zero();
|
||||
c.rotation = Vector3.Zero();
|
||||
c.scaling = Vector3.Zero();
|
||||
c.rotationQuaternion = null;
|
||||
return c;
|
||||
}
|
||||
|
||||
export function buildCSG(expr: Shapes.CSGExpr): CSG {
|
||||
function walk(expr: Shapes.CSGExpr, matrix: Matrix): CSG {
|
||||
switch (expr._variant) {
|
||||
case "mesh": {
|
||||
const mesh = buildMesh("", null, expr.shape);
|
||||
mesh.freezeWorldMatrix(matrix, true);
|
||||
mesh.unfreezeWorldMatrix();
|
||||
const c = CSG.FromMesh(mesh);
|
||||
mesh.dispose();
|
||||
return c;
|
||||
}
|
||||
case "scale":
|
||||
return walk(expr.shape, matrix.multiply(
|
||||
Matrix.Scaling(expr.v.x, expr.v.y, expr.v.z)));
|
||||
case "move":
|
||||
return walk(expr.shape, matrix.multiply(
|
||||
Matrix.Translation(expr.v.x, expr.v.y, expr.v.z)));
|
||||
case "rotate":
|
||||
return walk(expr.shape, matrix.multiply(
|
||||
Matrix.RotationYawPitchRoll(expr.v.y * 2 * Math.PI,
|
||||
expr.v.x * 2 * Math.PI,
|
||||
expr.v.z * 2 * Math.PI)));
|
||||
case "subtract": {
|
||||
let c = walk(expr.base, matrix);
|
||||
expr.more.forEach(d => c.subtractInPlace(walk(d, matrix)));
|
||||
return c;
|
||||
}
|
||||
case "union": {
|
||||
let c = walk(expr.base, matrix);
|
||||
expr.more.forEach(d => c.unionInPlace(walk(d, matrix)));
|
||||
return c;
|
||||
}
|
||||
case "intersect": {
|
||||
let c = walk(expr.base, matrix);
|
||||
expr.more.forEach(d => c.intersectInPlace(walk(d, matrix)));
|
||||
return c;
|
||||
}
|
||||
case "invert": {
|
||||
let c = walk(expr.shape, matrix);
|
||||
c.inverseInPlace();
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return walk(expr, Matrix.Identity());
|
||||
}
|
||||
|
||||
export const builder: { [key: string]: (... args: any[]) => Shapes.Shape } = {
|
||||
sphere: () => Shapes.Shape.Mesh(Shapes.Mesh.Sphere(Shapes.Sphere())),
|
||||
box: () => Shapes.Shape.Mesh(Shapes.Mesh.Box(Shapes.Box())),
|
||||
|
|
Loading…
Reference in New Issue