|
@ -36,14 +36,17 @@ proc rewrite(terms: Terms, maxIterations: int) : Terms = |
|
|
currentTerms = @[LineTerm] & currentTerms |
|
|
currentTerms = @[LineTerm] & currentTerms |
|
|
return currentTerms |
|
|
return currentTerms |
|
|
|
|
|
|
|
|
|
|
|
type PolarCoord = object |
|
|
|
|
|
angle: float64 |
|
|
|
|
|
magnitude: float64 |
|
|
|
|
|
|
|
|
type StackControl = enum Push, Pop |
|
|
type StackControl = enum Push, Pop |
|
|
|
|
|
|
|
|
# An intruction along with a change in angle and magnitude (i.e. a vector) |
|
|
# An intruction along with a change in angle and magnitude (i.e. a vector) |
|
|
type DrawInstruction = object |
|
|
type DrawInstruction = object |
|
|
angle_change: float64 |
|
|
|
|
|
width: float64 |
|
|
width: float64 |
|
|
magnitude: float64 |
|
|
|
|
|
color: Color |
|
|
color: Color |
|
|
|
|
|
coord: PolarCoord |
|
|
|
|
|
|
|
|
type |
|
|
type |
|
|
InstructionKind = enum pkDraw, pkStack |
|
|
InstructionKind = enum pkDraw, pkStack |
|
@ -54,7 +57,7 @@ type |
|
|
|
|
|
|
|
|
proc `$` (i: Instruction): string = |
|
|
proc `$` (i: Instruction): string = |
|
|
case i.kind: |
|
|
case i.kind: |
|
|
of pkDraw: return "angle_change = " & $i.drawInstruction.angle_change & ", magnitude = " & $i.drawInstruction.magnitude |
|
|
of pkDraw: return "angle_change = " & $i.drawInstruction.coord.angle & ", magnitude = " & $i.drawInstruction.coord.magnitude |
|
|
of pkStack: return "direction = " & $i.stackInstruction |
|
|
of pkStack: return "direction = " & $i.stackInstruction |
|
|
|
|
|
|
|
|
iterator axiomToInstructions(maxIterations: int, magnitude: float64, angle: float64, leafColor: Color = DARKGREEN) : Instruction = |
|
|
iterator axiomToInstructions(maxIterations: int, magnitude: float64, angle: float64, leafColor: Color = DARKGREEN) : Instruction = |
|
@ -67,7 +70,7 @@ iterator axiomToInstructions(maxIterations: int, magnitude: float64, angle: floa |
|
|
var current_magnitude = magnitude |
|
|
var current_magnitude = magnitude |
|
|
var current_width: float64 = widths[0] |
|
|
var current_width: float64 = widths[0] |
|
|
# axiom |
|
|
# axiom |
|
|
yield Instruction(kind: pkDraw, drawInstruction: DrawInstruction(angle_change: 180, magnitude: magnitude)) |
|
|
yield Instruction(kind: pkDraw, drawInstruction: DrawInstruction(coord: PolarCoord(angle: 180, magnitude: magnitude))) |
|
|
|
|
|
|
|
|
for term in termsToConvert: |
|
|
for term in termsToConvert: |
|
|
# TODO make this definable by the grammar and/or tweakable |
|
|
# TODO make this definable by the grammar and/or tweakable |
|
@ -81,12 +84,31 @@ iterator axiomToInstructions(maxIterations: int, magnitude: float64, angle: floa |
|
|
# TODO make this definable by the grammar and/or tweakable |
|
|
# TODO make this definable by the grammar and/or tweakable |
|
|
currentLeafColor.r += (sample(@[5, 2, 10, -1, -2, 3]).uint8) |
|
|
currentLeafColor.r += (sample(@[5, 2, 10, -1, -2, 3]).uint8) |
|
|
|
|
|
|
|
|
yield Instruction(kind: pkDraw, drawInstruction: DrawInstruction(color: currentLeafColor, width: leaf_width, angle_change: angle_delta, magnitude: magnitudes[0])) |
|
|
yield Instruction(kind: pkDraw, |
|
|
yield Instruction(kind: pkDraw, drawInstruction: DrawInstruction(color: currentLeafColor, width: leaf_width, angle_change: 0, magnitude: -magnitudes[0])) # hack |
|
|
drawInstruction: |
|
|
yield Instruction(kind: pkDraw, drawInstruction: DrawInstruction(color: currentLeafColor, width: leaf_width, angle_change: -(angle_delta*2), magnitude: magnitudes[0])) |
|
|
DrawInstruction(color: currentLeafColor, |
|
|
|
|
|
width: leaf_width, |
|
|
|
|
|
coord: PolarCoord(angle: angle_delta, magnitude: magnitudes[0]))) |
|
|
|
|
|
|
|
|
|
|
|
yield Instruction(kind: pkDraw, |
|
|
|
|
|
drawInstruction: |
|
|
|
|
|
DrawInstruction(color: currentLeafColor, |
|
|
|
|
|
width: leaf_width, |
|
|
|
|
|
coord: PolarCoord(angle: 0, magnitude: -magnitudes[0]))) # hack |
|
|
|
|
|
|
|
|
|
|
|
yield Instruction(kind: pkDraw, |
|
|
|
|
|
drawInstruction: |
|
|
|
|
|
DrawInstruction(color: currentLeafColor, |
|
|
|
|
|
width: leaf_width, |
|
|
|
|
|
coord: PolarCoord(angle: -(angle_delta*2), |
|
|
|
|
|
magnitude: magnitudes[0]))) |
|
|
of LineTerm: |
|
|
of LineTerm: |
|
|
# Draw without changing direction |
|
|
# Draw without changing direction |
|
|
yield Instruction(kind: pkDraw, drawInstruction: DrawInstruction(color: DARKBROWN, width: current_width, angle_change: 0, magnitude: magnitudes[0])) |
|
|
yield Instruction(kind: pkDraw, |
|
|
|
|
|
drawInstruction: |
|
|
|
|
|
DrawInstruction(color: DARKBROWN, |
|
|
|
|
|
width: current_width, |
|
|
|
|
|
coord: PolarCoord(angle: 0, magnitude: magnitudes[0]))) |
|
|
|
|
|
|
|
|
# L-systems don't go "backwards" |
|
|
# L-systems don't go "backwards" |
|
|
# So you can go left or right on the x-axis at a given angle delta |
|
|
# So you can go left or right on the x-axis at a given angle delta |
|
@ -94,12 +116,23 @@ iterator axiomToInstructions(maxIterations: int, magnitude: float64, angle: floa |
|
|
# TODO make this definable by the grammar and/or tweakable |
|
|
# TODO make this definable by the grammar and/or tweakable |
|
|
current_magnitude = current_magnitude - (current_magnitude * sample(@[0.05, 0.10])) |
|
|
current_magnitude = current_magnitude - (current_magnitude * sample(@[0.05, 0.10])) |
|
|
current_width = current_width - (current_width * sample(@[0.15, 0.10])) |
|
|
current_width = current_width - (current_width * sample(@[0.15, 0.10])) |
|
|
yield Instruction(kind: pkDraw, drawInstruction: DrawInstruction(color: DARKBROWN, width: current_width, angle_change: angle_delta, magnitude: current_magnitude)) |
|
|
|
|
|
|
|
|
yield Instruction(kind: pkDraw, |
|
|
|
|
|
drawInstruction: |
|
|
|
|
|
DrawInstruction(color: DARKBROWN, |
|
|
|
|
|
width: current_width, |
|
|
|
|
|
coord: PolarCoord(angle: angle_delta, magnitude: current_magnitude))) |
|
|
|
|
|
|
|
|
of GoRight: |
|
|
of GoRight: |
|
|
# TODO make this definable by the grammar and/or tweakable |
|
|
# TODO make this definable by the grammar and/or tweakable |
|
|
current_magnitude = current_magnitude - (current_magnitude * sample(@[0.05, 0.01])) |
|
|
current_magnitude = current_magnitude - (current_magnitude * sample(@[0.05, 0.01])) |
|
|
current_width = current_width - (current_width * sample(@[0.15, 0.10])) |
|
|
current_width = current_width - (current_width * sample(@[0.15, 0.10])) |
|
|
yield Instruction(kind: pkDraw, drawInstruction: DrawInstruction(color: DARKBROWN, width: current_width, angle_change: -angle_delta, magnitude: current_magnitude)) |
|
|
|
|
|
|
|
|
yield Instruction(kind: pkDraw, |
|
|
|
|
|
drawInstruction: |
|
|
|
|
|
DrawInstruction(color: DARKBROWN, |
|
|
|
|
|
width: current_width, |
|
|
|
|
|
coord: PolarCoord(angle: -angle_delta, magnitude: current_magnitude))) |
|
|
|
|
|
|
|
|
# Control the stack of saved positions |
|
|
# Control the stack of saved positions |
|
|
of PushTerm: |
|
|
of PushTerm: |
|
@ -145,21 +178,32 @@ type DrawLine = object |
|
|
proc `$` (d: DrawLine): string = |
|
|
proc `$` (d: DrawLine): string = |
|
|
return "start_pos = " & $d.start_pos & ", " & "end_pos = " & $d.end_pos |
|
|
return "start_pos = " & $d.start_pos & ", " & "end_pos = " & $d.end_pos |
|
|
|
|
|
|
|
|
proc calculateNextLine(inst: DrawInstruction, pos: StartingPosition) : DrawLine = |
|
|
proc polarToCartesian(coord: PolarCoord): Vector2 = |
|
|
# Change the angle |
|
|
# Convert from polar coordinates to cartesian |
|
|
let new_angle = inst.angle_change + pos.angle |
|
|
# angle is in degrees |
|
|
|
|
|
let new_x = -(coord.magnitude * cos(degToRad(coord.angle))) |
|
|
|
|
|
let new_y = coord.magnitude * sin(degToRad(coord.angle)) |
|
|
|
|
|
|
|
|
# Use the same magnitude as before |
|
|
return Vector2(x: new_x, y: new_y) |
|
|
let magnitude = inst.magnitude |
|
|
|
|
|
|
|
|
|
|
|
# Convert from polar coordinates to cartesian |
|
|
proc cartesianToPolar(start_pos: Vector2, end_pos: Vector2): PolarCoord = |
|
|
let new_x = -(magnitude * cos(degToRad(new_angle))) |
|
|
# Convert from cartesian coordinates to polar |
|
|
let new_y = magnitude * sin(degToRad(new_angle)) |
|
|
# angle is in degrees |
|
|
|
|
|
|
|
|
|
|
|
let magnitude = sqrt((end_pos.y - start_pos.y)^2 + (end_pos.x - start_pos.x)^2) |
|
|
|
|
|
let angle = radToDeg(arcsin(end_pos.y / magnitude)) |
|
|
|
|
|
|
|
|
|
|
|
return PolarCoord(magnitude: magnitude, angle: angle) |
|
|
|
|
|
|
|
|
|
|
|
proc calculateNextLine(inst: DrawInstruction, pos: StartingPosition) : DrawLine = |
|
|
|
|
|
# Change the angle |
|
|
|
|
|
let new_angle = inst.coord.angle + pos.angle |
|
|
|
|
|
let endPosition = polarToCartesian(PolarCoord(magnitude: inst.coord.magnitude, angle: new_angle)) |
|
|
|
|
|
|
|
|
result.start_pos = Vector2(x: pos.x, y: pos.y) |
|
|
result.start_pos = Vector2(x: pos.x, y: pos.y) |
|
|
|
|
|
|
|
|
# Ending position is relative to the starting position, so add the coordinates |
|
|
# Ending position is relative to the starting position, so add the coordinates |
|
|
result.end_pos = Vector2(x: result.start_pos.x+new_x, y: result.start_pos.y+new_y) |
|
|
result.end_pos = Vector2(x: result.start_pos.x+endPosition.x, y: result.start_pos.y+endPosition.y) |
|
|
result.mid_pos = Vector2(x: result.start_pos.x, y: result.end_pos.y) |
|
|
result.mid_pos = Vector2(x: result.start_pos.x, y: result.end_pos.y) |
|
|
|
|
|
|
|
|
result.width = inst.width |
|
|
result.width = inst.width |
|
@ -244,6 +288,8 @@ proc guiLoop*() = |
|
|
|
|
|
|
|
|
var camera: Camera2D |
|
|
var camera: Camera2D |
|
|
|
|
|
|
|
|
|
|
|
#var testTexture = LoadTextureFromImage(LoadImage("./test_texture.png")) |
|
|
|
|
|
|
|
|
camera.offset = Vector2(x: camera_x_offset, y: camera_y_offset) |
|
|
camera.offset = Vector2(x: camera_x_offset, y: camera_y_offset) |
|
|
camera.target = Vector2(x: screenWidth/2, y: screenHeight/2) |
|
|
camera.target = Vector2(x: screenWidth/2, y: screenHeight/2) |
|
|
|
|
|
|
|
|