Caps. They don't work right yet (earcut problems?)
This commit is contained in:
parent
dc45666ed7
commit
096946d0ad
|
@ -38,23 +38,54 @@
|
|||
<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
|
||||
]>
|
||||
>>>
|
||||
<texture ["textures/pixar128/wall/Rattan_pxr128.jpg"]
|
||||
<turtle [
|
||||
90 U
|
||||
90 L 0.05 B 90 R
|
||||
ClearPen
|
||||
PenDown
|
||||
[
|
||||
30 to lean
|
||||
1 lean cos / to len
|
||||
lean R
|
||||
[len F 90 lean + L 0.1 F 90 lean - L] 2 times
|
||||
] apply
|
||||
DefinePen GetPen to vPen
|
||||
|
||||
"DOUBLE" SetSideOrientation
|
||||
"BOTH" SetCap
|
||||
#t SetMiter
|
||||
#f SetWireframe
|
||||
|
||||
[ to [f] PenDown f PenUp ] to draw
|
||||
|
||||
4 to nSides
|
||||
360 nSides / to angle
|
||||
20 nSides / to dist
|
||||
|
||||
[
|
||||
angle R 0 F
|
||||
[dist F angle R 0 F] nSides times
|
||||
angle L
|
||||
] to plotArea
|
||||
|
||||
Home
|
||||
ClearPen
|
||||
PenDown
|
||||
90 D
|
||||
plotArea
|
||||
DefinePen GetPen to floorPen
|
||||
Home
|
||||
|
||||
Home
|
||||
[
|
||||
floorPen SetPen
|
||||
90 U [0.1 F] draw 90 D
|
||||
vPen SetPen
|
||||
quote plotArea draw 90 U 1 F 90 D
|
||||
] 3 times
|
||||
]>
|
||||
>>>>
|
||||
|
||||
@<sprite "house" []
|
||||
<move <v 0.0 0.0 10.0>
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
slen F
|
||||
DefinePen
|
||||
Home
|
||||
"double" SetSideOrientation
|
||||
"DOUBLE" SetSideOrientation
|
||||
#t SetSmooth
|
||||
PenDown
|
||||
[6 CW dlen F] 240 times
|
||||
|
|
|
@ -234,6 +234,8 @@ export class VM<Self extends VM<Self>> {
|
|||
}
|
||||
}
|
||||
|
||||
export const D2R = Math.PI / 180;
|
||||
|
||||
export const Primitives: Environment<any> = {
|
||||
'+'(a, b) { return [(a as number) + (b as number)]; },
|
||||
'-'(a, b) { return [(a as number) - (b as number)]; },
|
||||
|
@ -242,9 +244,9 @@ 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)]; },
|
||||
'cos'(n) { return [Math.cos(n as number * D2R)]; },
|
||||
'sin'(n) { return [Math.sin(n as number * D2R)]; },
|
||||
'tan'(n) { return [Math.tan(n as number * D2R)]; },
|
||||
|
||||
'to'() {
|
||||
const n_or_ns = this.nextToken('to', (v: any): v is (symbol | symbol[]) =>
|
||||
|
|
|
@ -26,15 +26,13 @@ export class PenState {
|
|||
|
||||
clear() {
|
||||
this.templatePath = [new Vector3()];
|
||||
this.paths = null;
|
||||
this.directions = null;
|
||||
this.up();
|
||||
}
|
||||
|
||||
set() {
|
||||
if (!this.paths) throw new PenError("Cannot set pen with no paths");
|
||||
this.templatePath = this.paths[0];
|
||||
this.paths = null;
|
||||
this.directions = null;
|
||||
this.up();
|
||||
}
|
||||
|
||||
down() {
|
||||
|
@ -88,12 +86,18 @@ function pointDistance(origin: Vector3, direction: Vector3, plane: Plane): numbe
|
|||
return (-plane.d - result2) / result1;
|
||||
}
|
||||
|
||||
const D2R = Math.PI / 180;
|
||||
export enum CapType {
|
||||
NONE,
|
||||
START,
|
||||
END,
|
||||
BOTH,
|
||||
};
|
||||
|
||||
export class TurtleVM extends Cat.VM<TurtleVM> {
|
||||
container: Mesh;
|
||||
meshes: Mesh[] = [];
|
||||
wireframe = false;
|
||||
cap: CapType = CapType.BOTH;
|
||||
|
||||
counter = 0;
|
||||
sideOrientation = Mesh.DEFAULTSIDE;
|
||||
|
@ -125,12 +129,12 @@ export class TurtleVM extends Cat.VM<TurtleVM> {
|
|||
|
||||
rotate(y: number, x: number, z: number) {
|
||||
const e = this.euler;
|
||||
e.addInPlaceFromFloats(x * D2R, y * D2R, z * D2R);
|
||||
e.addInPlaceFromFloats(x * Cat.D2R, y * Cat.D2R, z * Cat.D2R);
|
||||
this.q = e.toQuaternion();
|
||||
}
|
||||
|
||||
relativeRotate(y: number, x: number, z: number) {
|
||||
this.q = this.q.multiply(Quaternion.FromEulerAngles(x * D2R, y * D2R, z * D2R));
|
||||
this.q = this.q.multiply(Quaternion.FromEulerAngles(x * Cat.D2R, y * Cat.D2R, z * Cat.D2R));
|
||||
}
|
||||
|
||||
penDown() {
|
||||
|
@ -190,10 +194,6 @@ 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([]);
|
||||
|
@ -237,6 +237,21 @@ export class TurtleVM extends Cat.VM<TurtleVM> {
|
|||
}
|
||||
|
||||
const computePointIndex = this.smooth ? cachedPoint : pushPoint;
|
||||
|
||||
function cap(stepIndex: number) {
|
||||
const capVerts = paths.flatMap(p => p[stepIndex].asArray());
|
||||
const capIndices = earcut(capVerts, void 0, 3);
|
||||
for (let i = 0; i < capIndices.length; i += 3) {
|
||||
indices.push(computePointIndex(capIndices[i+0], stepIndex),
|
||||
computePointIndex(capIndices[i+1], stepIndex),
|
||||
computePointIndex(capIndices[i+2], stepIndex));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.cap === CapType.START || this.cap === CapType.BOTH) {
|
||||
cap(0);
|
||||
}
|
||||
|
||||
for (let pathIndex = 1; pathIndex < pathCount; pathIndex++) {
|
||||
for (let stepIndex = 1; stepIndex < stepCount; stepIndex++) {
|
||||
indices.push(computePointIndex(pathIndex - 1, stepIndex - 1),
|
||||
|
@ -249,6 +264,10 @@ export class TurtleVM extends Cat.VM<TurtleVM> {
|
|||
}
|
||||
}
|
||||
|
||||
if (this.cap === CapType.END || this.cap === CapType.BOTH) {
|
||||
cap(stepCount - 1);
|
||||
}
|
||||
|
||||
VertexData.ComputeNormals(positions, indices, normals);
|
||||
VertexData._ComputeSides(this.sideOrientation, positions, indices, normals, uvs);
|
||||
|
||||
|
@ -281,16 +300,16 @@ export const TurtlePrimitives: Cat.Environment<TurtleVM> = Object.assign({}, Cat
|
|||
return [];
|
||||
},
|
||||
|
||||
'GetHeading'() { return [this.euler.asArray().map(v => v / D2R)]; },
|
||||
'GetRX'() { return [this.euler.x / D2R]; },
|
||||
'GetRY'() { return [this.euler.y / D2R]; },
|
||||
'GetRZ'() { return [this.euler.z / D2R]; },
|
||||
'SetRX'(v) { this.q.x = v as number * D2R; return []; },
|
||||
'SetRY'(v) { this.q.y = v as number * D2R; return []; },
|
||||
'SetRZ'(v) { this.q.z = v as number * D2R; return []; },
|
||||
'GetHeading'() { return [this.euler.asArray().map(v => v / Cat.D2R)]; },
|
||||
'GetRX'() { return [this.euler.x / Cat.D2R]; },
|
||||
'GetRY'() { return [this.euler.y / Cat.D2R]; },
|
||||
'GetRZ'() { return [this.euler.z / Cat.D2R]; },
|
||||
'SetRX'(v) { this.q.x = v as number * Cat.D2R; return []; },
|
||||
'SetRY'(v) { this.q.y = v as number * Cat.D2R; return []; },
|
||||
'SetRZ'(v) { this.q.z = v as number * Cat.D2R; return []; },
|
||||
'SetHeading'(v) {
|
||||
const [x, y, z] = v as number[];
|
||||
this.q = Quaternion.FromEulerAngles(x as number * D2R, y as number * D2R, z as number * D2R);
|
||||
this.q = Quaternion.FromEulerAngles(x as number * Cat.D2R, y as number * Cat.D2R, z as number * Cat.D2R);
|
||||
return [];
|
||||
},
|
||||
|
||||
|
@ -328,15 +347,24 @@ export const TurtlePrimitives: Cat.Environment<TurtleVM> = Object.assign({}, Cat
|
|||
'PenUp'() { this.penUp(false); return []; },
|
||||
'Close'() { this.penUp(true); return []; },
|
||||
|
||||
'SetCap'(t) {
|
||||
const n = t as keyof typeof CapType;
|
||||
if (typeof t === 'string' && n in CapType) {
|
||||
this.cap = CapType[n];
|
||||
} else {
|
||||
throw new Cat.TypeError("Bad cap type: " + t);
|
||||
}
|
||||
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) {
|
||||
switch (s) {
|
||||
case "default": this.sideOrientation = Mesh.DEFAULTSIDE; break;
|
||||
case "front": this.sideOrientation = Mesh.FRONTSIDE; break;
|
||||
case "back": this.sideOrientation = Mesh.BACKSIDE; break;
|
||||
case "double": this.sideOrientation = Mesh.DOUBLESIDE; break;
|
||||
case "DEFAULT": this.sideOrientation = Mesh.DEFAULTSIDE; break;
|
||||
case "FRONT": this.sideOrientation = Mesh.FRONTSIDE; break;
|
||||
case "BACK": this.sideOrientation = Mesh.BACKSIDE; break;
|
||||
case "DOUBLE": this.sideOrientation = Mesh.DOUBLESIDE; break;
|
||||
default: throw new TypeError("Invalid SideOrientation: " + s);
|
||||
}
|
||||
return [];
|
||||
|
|
Loading…
Reference in New Issue