Compare commits
3 Commits
6fd5e65376
...
1737848330
Author | SHA1 | Date |
---|---|---|
Tony Garnock-Jones | 1737848330 | |
Tony Garnock-Jones | 7d1f6fe249 | |
Tony Garnock-Jones | a2124faebc |
|
@ -106,7 +106,7 @@
|
|||
; >>>>>
|
||||
|
||||
<sprite "tt2" []
|
||||
<move <v 0.0 1.6 3.0>
|
||||
<move <v 0.0 1.6 5.2>
|
||||
<color 0.5 0.0 1.0
|
||||
<turtle [
|
||||
1 to slen
|
||||
|
@ -128,29 +128,46 @@
|
|||
]>>>>
|
||||
|
||||
<sprite "tt" []
|
||||
<move <v 1.0 0.01 0.75>
|
||||
<move <v 1.0 1.01 0.75>
|
||||
<rotate <v -0.125 0.0 0.0>
|
||||
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
|
||||
<v 2.0 1.0>
|
||||
<v 0.0 0.0>
|
||||
1.0]
|
||||
<turtle [
|
||||
1.0 to wallHeight
|
||||
0.1 to wallDepth
|
||||
<csg
|
||||
<subtract [
|
||||
<mesh
|
||||
<turtle [
|
||||
1.0 to wallHeight
|
||||
0.1 to wallDepth
|
||||
|
||||
90 U
|
||||
PenDown
|
||||
[wallHeight F 90 L wallDepth F 90 L] 2 times
|
||||
SetPen
|
||||
Home
|
||||
90 U
|
||||
PenDown
|
||||
[wallHeight F 90 L wallDepth F 90 L] 2 times
|
||||
SetPen
|
||||
Home
|
||||
|
||||
[ 1 to k k / [dup F] k times drop ] to ff
|
||||
[ 2 / dup R 0 F R 0 F ] to rr
|
||||
#t SetMiter
|
||||
; #t SetSmooth
|
||||
|
||||
PenDown
|
||||
1 ff 90 rr 1 ff 90 rr 1 ff 90 rr 1 ff 90 rr
|
||||
PenUp
|
||||
]>>>>>
|
||||
; quote F to ff
|
||||
[ 1 to k k / [dup F] k times drop ] to ff
|
||||
|
||||
[ R 0 F ] to rr
|
||||
; [ R 0 F 60 D ] to rr
|
||||
; [ 4 to k k / [dup R 0 F] k times drop ] to rr
|
||||
|
||||
PenDown
|
||||
60 to sides
|
||||
[4 sides / ff 360 sides / rr] sides 2 / 2 - times
|
||||
1 0.5 1 PenScale 0 F
|
||||
[4 sides / ff 360 sides / rr] 4 times
|
||||
1 1 1 PenScale 0 F
|
||||
[4 sides / ff 360 sides / rr] sides 2 / 2 - times
|
||||
PenUp
|
||||
]>>
|
||||
<mesh <box>>
|
||||
]>>>>>>
|
||||
|
||||
; <Exit "y" "lobby">
|
||||
; <sprite "y" []
|
||||
|
|
|
@ -242,6 +242,10 @@ export const Primitives: Environment<any> = {
|
|||
'%'(a, b) { return [(a as number) % (b as number)]; },
|
||||
'neg'(v) { return [-(v as number)]; },
|
||||
|
||||
'cos'(n) { return [Math.cos(n as number)]; },
|
||||
'sin'(n) { return [Math.sin(n as number)]; },
|
||||
'tan'(n) { return [Math.tan(n as number)]; },
|
||||
|
||||
'to'() {
|
||||
const n_or_ns = this.nextToken('to', (v: any): v is (symbol | symbol[]) =>
|
||||
typeof v === 'symbol' || (Array.isArray(v) && v.every(w => typeof w === 'symbol')));
|
||||
|
|
|
@ -462,8 +462,15 @@ export function buildCSG(name: string, scene: Scene, expr: Shapes.CSGExpr): Buil
|
|||
n.freezeWorldMatrix(matrix, true);
|
||||
n.unfreezeWorldMatrix();
|
||||
});
|
||||
const c = CSG.FromMesh(nodes[0]);
|
||||
nodes.slice(1).forEach(n => c.unionInPlace(CSG.FromMesh(n)));
|
||||
const cs = nodes.flatMap(n => {
|
||||
try {
|
||||
return [CSG.FromMesh(n)];
|
||||
} catch (_e) {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
const c = cs[0];
|
||||
cs.slice(1).forEach(d => c.unionInPlace(d));
|
||||
nodes.forEach(n => n.dispose());
|
||||
return c;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ import * as Cat from './cat.js';
|
|||
export class PenState {
|
||||
templatePath: Vector3[] = [new Vector3()];
|
||||
paths: Vector3[][] | null = null;
|
||||
directions: Quaternion[] | null = null;
|
||||
templateScale = new Vector3(1, 1, 1);
|
||||
|
||||
get isDown(): boolean {
|
||||
return this.paths !== null;
|
||||
|
@ -22,27 +24,43 @@ export class PenState {
|
|||
clear() {
|
||||
this.templatePath = [new Vector3()];
|
||||
this.paths = null;
|
||||
this.directions = null;
|
||||
}
|
||||
|
||||
set() {
|
||||
if (!this.paths) throw new Error("Cannot set pen with no paths");
|
||||
this.templatePath = this.paths[0];
|
||||
this.paths = null;
|
||||
this.directions = null;
|
||||
}
|
||||
|
||||
down() {
|
||||
this.paths = this.templatePath.map(_p => []);
|
||||
this.directions = [];
|
||||
}
|
||||
|
||||
push(pos: Vector3, q: Quaternion) {
|
||||
push(pos: Vector3, q: Quaternion, miter: boolean) {
|
||||
const directions = this.directions!;
|
||||
const paths = this.paths!;
|
||||
|
||||
if (miter && directions.length > 0) {
|
||||
const lastQ = directions[directions.length - 1];
|
||||
const lastDir = new Vector3(0, 0, 1).applyRotationQuaternionInPlace(lastQ);
|
||||
const thisDir = new Vector3(0, 0, 1).applyRotationQuaternionInPlace(q);
|
||||
const miterDir = lastDir.add(thisDir).normalize();
|
||||
const miterPlane = Plane.FromPositionAndNormal(pos, miterDir);
|
||||
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)!));
|
||||
}
|
||||
}
|
||||
|
||||
this.templatePath.forEach((p, i) => {
|
||||
const r = new Vector3();
|
||||
// p.multiplyToRef(this.templateScale, r);
|
||||
// r.rotateByQuaternionToRef(q, r);
|
||||
p.rotateByQuaternionToRef(q, r);
|
||||
r.addInPlace(pos);
|
||||
this.paths![i].push(r);
|
||||
paths[i].push(p.multiply(this.templateScale).applyRotationQuaternion(q).addInPlace(pos));
|
||||
});
|
||||
|
||||
directions.push(q);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -58,8 +76,8 @@ export class TurtleVM extends Cat.VM<TurtleVM> {
|
|||
pen = new PenState();
|
||||
pos = new Vector3();
|
||||
q = new Quaternion();
|
||||
prevQ = this.q;
|
||||
smooth = false;
|
||||
miter = false;
|
||||
|
||||
get euler(): Vector3 {
|
||||
return this.q.toEulerAngles();
|
||||
|
@ -75,33 +93,24 @@ export class TurtleVM extends Cat.VM<TurtleVM> {
|
|||
}
|
||||
|
||||
forwardBy(dist: number) {
|
||||
const v = new Vector3(0, 0, dist);
|
||||
v.rotateByQuaternionToRef(this.q, v);
|
||||
const v = new Vector3(0, 0, dist).applyRotationQuaternionInPlace(this.q);
|
||||
this.pos.addInPlace(v);
|
||||
if (this.pen.isDown) this.pen.push(this.pos, this.q);
|
||||
}
|
||||
|
||||
setQ(newQ: Quaternion) {
|
||||
this.q = newQ;
|
||||
}
|
||||
|
||||
resetQ(newQ: Quaternion) {
|
||||
this.q = this.prevQ = newQ;
|
||||
if (this.pen.isDown) this.pen.push(this.pos, this.q, dist === 0.0 && this.miter);
|
||||
}
|
||||
|
||||
rotate(y: number, x: number, z: number) {
|
||||
const e = this.euler;
|
||||
e.addInPlaceFromFloats(x * D2R, y * D2R, z * D2R);
|
||||
this.setQ(e.toQuaternion());
|
||||
this.q = e.toQuaternion();
|
||||
}
|
||||
|
||||
relativeRotate(y: number, x: number, z: number) {
|
||||
this.setQ(this.q.multiply(Quaternion.FromEulerAngles(x * D2R, y * D2R, z * D2R)));
|
||||
this.q = this.q.multiply(Quaternion.FromEulerAngles(x * D2R, y * D2R, z * D2R));
|
||||
}
|
||||
|
||||
penDown() {
|
||||
this.pen.down();
|
||||
this.pen.push(this.pos, this.q);
|
||||
this.pen.push(this.pos, this.q, false);
|
||||
}
|
||||
|
||||
penUp(close: boolean) {
|
||||
|
@ -201,7 +210,7 @@ export class TurtleVM extends Cat.VM<TurtleVM> {
|
|||
}
|
||||
|
||||
export const TurtlePrimitives: Cat.Environment<TurtleVM> = Object.assign({}, Cat.Primitives, {
|
||||
'Home'() { this.pos = new Vector3(); this.resetQ(new Quaternion()); return []; },
|
||||
'Home'() { this.pos = new Vector3(); this.q = new Quaternion(); return []; },
|
||||
|
||||
'GetPos'() { return [this.pos.asArray()]; },
|
||||
'GetX'() { return [this.pos.x]; },
|
||||
|
@ -223,7 +232,7 @@ export const TurtlePrimitives: Cat.Environment<TurtleVM> = Object.assign({}, Cat
|
|||
'SetRY'(v) { this.q.y = v as number * D2R; return []; },
|
||||
'SetRZ'(v) { this.q.z = v as number * D2R; return []; },
|
||||
'SetHeading'(x, y, z) {
|
||||
this.resetQ(Quaternion.FromEulerAngles(x as number * D2R, y as number * D2R, z as number * D2R));
|
||||
this.q = Quaternion.FromEulerAngles(x as number * D2R, y as number * D2R, z as number * D2R);
|
||||
return [];
|
||||
},
|
||||
|
||||
|
@ -244,11 +253,16 @@ export const TurtlePrimitives: Cat.Environment<TurtleVM> = Object.assign({}, Cat
|
|||
'ClearPen'() { this.pen.clear(); return []; },
|
||||
'SetPen'() { this.pen.set(); return []; },
|
||||
|
||||
'PenScale'(sx, sy, sz) {
|
||||
this.pen.templateScale = new Vector3(sx as number, sy as number, sz as number);
|
||||
return [];
|
||||
},
|
||||
'PenDown'() { this.penDown(); return []; },
|
||||
'PenUp'() { this.penUp(false); return []; },
|
||||
'Close'() { this.penUp(true); return []; },
|
||||
|
||||
'SetSmooth'(b) { this.smooth = b as boolean; return []; },
|
||||
'SetMiter'(b) { this.miter = b as boolean; return []; },
|
||||
'SetSideOrientation'(s) {
|
||||
switch (s) {
|
||||
case "default": this.sideOrientation = Mesh.DEFAULTSIDE; break;
|
||||
|
|
Loading…
Reference in New Issue