diff --git a/scene/lobby.pr b/scene/lobby.pr index 14c16c6..4691427 100644 --- a/scene/lobby.pr +++ b/scene/lobby.pr @@ -106,7 +106,7 @@ ; >>>>> + >>> + 1.0] - >>>> + ; 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 + ]>> + > + ]>>>>>> ; ; []); + 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 { 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 { } 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 { } export const TurtlePrimitives: Cat.Environment = 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 = 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 = 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;