|
import { Geometric3 } from 'davinci-eight' |
|
import { Color } from 'davinci-eight' |
|
import { Arrow, Sphere, Track, Turtle } from 'davinci-eight' |
|
import { GeometryMode } from 'davinci-eight' |
|
import { windowResizer } from './windowResizer' |
|
|
|
import Bug from './Bug' |
|
import Forward from './Forward' |
|
import Repeat from './Repeat' |
|
import Left from './Left' |
|
// import Right from './Right' |
|
// import Rotate from './Rotate' |
|
// import Steppable from './Steppable' |
|
import SteppableList from './SteppableList' |
|
import World from './World' |
|
|
|
const e1 = Geometric3.e1() |
|
const e2 = Geometric3.e2() |
|
const e3 = Geometric3.e3() |
|
|
|
/** |
|
* The initial frame sets the orientation, but since the position and |
|
* up direction are the same on a sphere, this also sets the position. |
|
*/ |
|
const INITIAL_FRAME = [e2, -e1, e3] |
|
/** |
|
* The initial direction of the pointer. |
|
* This is represented by the green arrow. |
|
*/ |
|
const INITIAL_POINTER = e2 |
|
|
|
/** |
|
* A brave new World. |
|
*/ |
|
const world = new World() |
|
const engine = world.engine |
|
|
|
const bug = new Bug() |
|
|
|
const turtle = new Turtle(engine, { color: Color.blueviolet }) |
|
|
|
const coords = new Sphere(engine, { mode: GeometryMode.WIRE, radius: 1 }) |
|
|
|
const track = new Track(engine) |
|
track.color = Color.white |
|
|
|
const arrow = new Arrow(engine) |
|
|
|
world.reset() |
|
world.sideView() |
|
|
|
/** |
|
* Use to control the speed of the animation. |
|
* Roughly the number of frames used to execute a motion step. |
|
*/ |
|
const FRAMES_PER_STEP = 50 |
|
const ONE_TURN = 2 * Math.PI |
|
const QUARTER_TURN = ONE_TURN / 4 |
|
/** |
|
* Divisor for the movement and turning angle. |
|
*/ |
|
const N = 1 // must be an integer |
|
/** |
|
* Ratio of forward movement to turn angle. |
|
*/ |
|
const ρ = 1 |
|
/** |
|
* Distance that we move forward. |
|
*/ |
|
const s = ρ * QUARTER_TURN / N |
|
/** |
|
* Angle that we turn through. |
|
*/ |
|
const θ = QUARTER_TURN / N |
|
/** |
|
* The number of repetitions. |
|
*/ |
|
const REPETITIONS = 3 * N |
|
|
|
const list = new SteppableList() |
|
list.add(new Repeat(new Forward(bug, s / FRAMES_PER_STEP), FRAMES_PER_STEP)) |
|
list.add(new Repeat(new Left(bug, -θ / FRAMES_PER_STEP), FRAMES_PER_STEP)) |
|
const program = new Repeat(list, REPETITIONS) |
|
let stepper = program.stepper() |
|
|
|
const animate = function() { |
|
|
|
world.beginFrame() |
|
|
|
if (world.time === 0) { |
|
// Initialize or Reset. |
|
bug.pointer.copy(INITIAL_POINTER) |
|
bug.X.copy(e3) |
|
bug.frame = INITIAL_FRAME |
|
// Erasing and adding the start point means we only have one point upon reset. |
|
track.clear() |
|
track.addPoint(bug.X) |
|
// We also need a new stepper. |
|
stepper = program.stepper() |
|
} |
|
|
|
if (world.running && stepper.hasNext()) { |
|
// We'll count steps. |
|
// All that matters is that time moves on from zero so we can reset. |
|
world.time = world.time + 1 |
|
stepper.next() |
|
track.addPoint(bug.X) |
|
} |
|
|
|
// Render the bug as a triangle. |
|
turtle.X.copyVector(bug.X) |
|
turtle.R.rotorFromFrameToFrame(INITIAL_FRAME, bug.frame) |
|
turtle.render(world.ambients) |
|
|
|
// Render the track of the bug. |
|
track.render(world.ambients) |
|
|
|
// Render the pointer of the bug as a blue arrow. |
|
arrow.vector = bug.pointer.clone().normalize().scale(0.3) |
|
arrow.X.copy(bug.X) |
|
arrow.color = Color.blue |
|
arrow.render(world.ambients) |
|
|
|
// Render the initial pointer as a green arrow at the initial location. |
|
arrow.vector = INITIAL_POINTER.clone().normalize().scale(0.3) |
|
arrow.X.copy(e3) |
|
arrow.color = Color.green |
|
arrow.render(world.ambients) |
|
|
|
// Render the Spherical Polar Coordinate curves. |
|
coords.render(world.ambients) |
|
|
|
// This call keeps the animation going. |
|
requestAnimationFrame(animate) |
|
} |
|
|
|
windowResizer(engine, world.camera).resize() |
|
// This call starts the animation. |
|
requestAnimationFrame(animate) |