Wireframe, and fixes to mitering
This commit is contained in:
parent
5606b3c2a4
commit
dc45666ed7
|
@ -35,7 +35,28 @@
|
|||
<scale <v 2.0 2.0 0.1>
|
||||
<box>>>>>>
|
||||
|
||||
<sprite "house" []
|
||||
<sprite "t" []
|
||||
<move <v -2.0 0.001 0.0>
|
||||
<rotate <v 0.0 0.0 0.0>
|
||||
<turtle [
|
||||
90 U
|
||||
90 L 0.05 B 90 R
|
||||
PenDown 1 F 90 L 0.1 F 90 L 1 F 90 L 0.1 F DefinePen
|
||||
Home
|
||||
"double" SetSideOrientation
|
||||
#t SetMiter
|
||||
#f SetWireframe
|
||||
90 L
|
||||
PenDown
|
||||
90 R 0 F
|
||||
1 F 90 R 0 F
|
||||
1 F 90 R 0 F
|
||||
1 F 90 R 0 F
|
||||
PenUp
|
||||
]>
|
||||
>>>
|
||||
|
||||
@<sprite "house" []
|
||||
<move <v 0.0 0.0 10.0>
|
||||
<rotate <v 0.0 0.0 0.0>
|
||||
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"]
|
||||
|
@ -82,13 +103,16 @@
|
|||
|
||||
[ to [angle length] [ angle L [length F] draw ] saved ] to wall
|
||||
|
||||
#f SetWireframe
|
||||
#t SetMiter
|
||||
[ 0 F ] to miter
|
||||
[ 90 L miter ] to --
|
||||
[ 90 R miter ] to ++
|
||||
|
||||
exteriorWall
|
||||
--
|
||||
[
|
||||
++
|
||||
2.1 F --
|
||||
0.3 F [1 F] eDoor 0.9 F ++
|
||||
7.7 F ++
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
Mesh,
|
||||
MeshBuilder,
|
||||
Plane,
|
||||
Quaternion,
|
||||
Ray,
|
||||
|
@ -9,6 +10,7 @@ import {
|
|||
} from '@babylonjs/core/Legacy/legacy';
|
||||
|
||||
import * as Cat from './cat.js';
|
||||
import { earcut } from './earcut';
|
||||
|
||||
export class PenError extends Cat.RuntimeError {}
|
||||
|
||||
|
@ -40,6 +42,11 @@ export class PenState {
|
|||
this.directions = [];
|
||||
}
|
||||
|
||||
up() {
|
||||
this.paths = null;
|
||||
this.directions = null;
|
||||
}
|
||||
|
||||
push(pos: Vector3, q: Quaternion, miter: boolean) {
|
||||
const directions = this.directions!;
|
||||
const paths = this.paths!;
|
||||
|
@ -53,23 +60,40 @@ export class PenState {
|
|||
for (let pathIndex = 0; pathIndex < paths.length; pathIndex++) {
|
||||
const steps = paths[pathIndex];
|
||||
const p = steps[steps.length - 1];
|
||||
steps[steps.length - 1] = p.add(lastDir.scale(new Ray(p, lastDir).intersectsPlane(miterPlane)!));
|
||||
const d = pointDistance(p, lastDir, miterPlane);
|
||||
if (d !== null) steps[steps.length - 1] = p.add(lastDir.scale(d));
|
||||
}
|
||||
this.templatePath.forEach((p, i) => {
|
||||
const r = p.multiply(this.templateScale).applyRotationQuaternion(q).addInPlace(pos);
|
||||
const d = pointDistance(r, thisDir, miterPlane);
|
||||
if (d !== null) r.addInPlace(thisDir.scale(d));
|
||||
paths[i].push(r);
|
||||
});
|
||||
} else {
|
||||
this.templatePath.forEach((p, i) => {
|
||||
const r = p.multiply(this.templateScale).applyRotationQuaternion(q).addInPlace(pos);
|
||||
paths[i].push(r);
|
||||
});
|
||||
}
|
||||
|
||||
this.templatePath.forEach((p, i) => {
|
||||
paths[i].push(p.multiply(this.templateScale).applyRotationQuaternion(q).addInPlace(pos));
|
||||
});
|
||||
|
||||
directions.push(q);
|
||||
}
|
||||
};
|
||||
|
||||
// Adapted from Ray.intersectsPlane
|
||||
function pointDistance(origin: Vector3, direction: Vector3, plane: Plane): number | null {
|
||||
const result1 = Vector3.Dot(plane.normal, direction);
|
||||
if (Math.abs(result1) < 1e-6) return null; // direction parallel to plane
|
||||
const result2 = Vector3.Dot(plane.normal, origin);
|
||||
return (-plane.d - result2) / result1;
|
||||
}
|
||||
|
||||
const D2R = Math.PI / 180;
|
||||
|
||||
export class TurtleVM extends Cat.VM<TurtleVM> {
|
||||
container: Mesh;
|
||||
meshes: Mesh[] = [];
|
||||
wireframe = false;
|
||||
|
||||
counter = 0;
|
||||
sideOrientation = Mesh.DEFAULTSIDE;
|
||||
|
@ -121,10 +145,37 @@ export class TurtleVM extends Cat.VM<TurtleVM> {
|
|||
throw new Error('todo');
|
||||
}
|
||||
|
||||
const m = new Mesh(this.container.name + this.counter++);
|
||||
// TODO: this.sideOrientation
|
||||
if (this.wireframe) {
|
||||
this.emitWireframe();
|
||||
} else {
|
||||
this.emitSolid();
|
||||
}
|
||||
|
||||
const vertexData = new VertexData();
|
||||
this.pen.up();
|
||||
}
|
||||
|
||||
emitWireframe() {
|
||||
const lines: Vector3[][] = [];
|
||||
const paths = this.pen.paths!;
|
||||
const pathCount = paths.length;
|
||||
const stepCount = paths[0].length;
|
||||
|
||||
for (let pathIndex = 1; pathIndex < pathCount; pathIndex++) {
|
||||
for (let stepIndex = 1; stepIndex < stepCount; stepIndex++) {
|
||||
lines.push([paths[pathIndex - 1][stepIndex - 1],
|
||||
paths[pathIndex - 1][stepIndex],
|
||||
paths[pathIndex][stepIndex],
|
||||
paths[pathIndex][stepIndex - 1]]);
|
||||
}
|
||||
}
|
||||
|
||||
const meshName = this.container.name + this.counter++;
|
||||
const ls = MeshBuilder.CreateLineSystem(meshName, { lines }, null);
|
||||
ls.parent = this.container;
|
||||
this.meshes.push(ls);
|
||||
}
|
||||
|
||||
emitSolid() {
|
||||
const positions: number[] = [];
|
||||
const indices: number[] = [];
|
||||
const normals: number[] = [];
|
||||
|
@ -139,6 +190,10 @@ export class TurtleVM extends Cat.VM<TurtleVM> {
|
|||
const uTotal: number[] = [];
|
||||
const vTotal: number[] = [];
|
||||
|
||||
const capVerts = paths.flatMap(p => p[0].asArray());
|
||||
console.log(capVerts);
|
||||
console.log(earcut(capVerts, void 0, 3).map(i => paths[0][i].asArray()));
|
||||
|
||||
for (let pathIndex = 0; pathIndex < pathCount; pathIndex++) {
|
||||
uTotal.push(0);
|
||||
us.push([]);
|
||||
|
@ -167,7 +222,8 @@ export class TurtleVM extends Cat.VM<TurtleVM> {
|
|||
const pointIndex = positions.length / 3;
|
||||
const p = paths[pathIndex][stepIndex];
|
||||
positions.push(... p.asArray());
|
||||
uvs.push((p.x - p.z) / 1.2, (p.y) / 0.9);
|
||||
uvs.push((p.x - p.z), (p.y));
|
||||
// uvs.push((p.x - p.z) / 1.2, (p.y) / 0.9);
|
||||
// uvs.push(us[pathIndex][stepIndex] / uTotal[pathIndex],
|
||||
// vs[stepIndex][pathIndex] / vTotal[stepIndex]);
|
||||
return pointIndex;
|
||||
|
@ -195,18 +251,15 @@ export class TurtleVM extends Cat.VM<TurtleVM> {
|
|||
|
||||
VertexData.ComputeNormals(positions, indices, normals);
|
||||
VertexData._ComputeSides(this.sideOrientation, positions, indices, normals, uvs);
|
||||
|
||||
const vertexData = new VertexData();
|
||||
vertexData.positions = new Float32Array(positions);
|
||||
vertexData.indices = new Int32Array(indices);
|
||||
vertexData.normals = new Float32Array(normals);
|
||||
vertexData.uvs = new Float32Array(uvs);
|
||||
|
||||
const m = new Mesh(this.container.name + this.counter++);
|
||||
vertexData.applyToMesh(m);
|
||||
|
||||
// const m = MeshBuilder.CreateRibbon(this.container.name + this.counter++, {
|
||||
// pathArray: this.pen.paths!,
|
||||
// sideOrientation: this.sideOrientation,
|
||||
// });
|
||||
|
||||
m.parent = this.container;
|
||||
this.meshes.push(m);
|
||||
}
|
||||
|
@ -275,6 +328,7 @@ export const TurtlePrimitives: Cat.Environment<TurtleVM> = Object.assign({}, Cat
|
|||
'PenUp'() { this.penUp(false); return []; },
|
||||
'Close'() { this.penUp(true); return []; },
|
||||
|
||||
'SetWireframe'(b) { this.wireframe = b as boolean; return []; },
|
||||
'SetSmooth'(b) { this.smooth = b as boolean; return []; },
|
||||
'SetMiter'(b) { this.miter = b as boolean; return []; },
|
||||
'SetSideOrientation'(s) {
|
||||
|
|
Loading…
Reference in New Issue