Archives August 2021

Example: Plane Trapped in a Torus

This example demonstrates the use of various camera-related functions, shape inversion, the premodel primitive and others to create this cool animation of a plane trapped in a torus!

The procedure first sets the turtle model to the built-in plane model, before creating a tag that sets the color of the torus. Then it creates an inverted torus (one whose inside is rendered instead of its outslde) because we’re going to fly inside it!

We then position the turtle to prepare it for its orbital flight path, position the camera behind it and set up its light. Then we begin orbiting, and while we do so we use setpremodel to move the turtle relative to the camera, creating the drifting motions of the plane as it flies.

Every so often, we change the color of the torus by replacing the contents of the color tag. Cool stuff!

Read through the source code below and take note of the comments, which explain what various parts of the trapped procedure do.

TO trapped
  setmodel "plane
  ;sets Myrtle's model to the built-in plane model
  begintag "col
  setfillcolor 1 + random 15
  ;the contents of tags can be used to create models, or
  ;they can be disabled or replaced. We're going to replace
  ;the contents of this tag later in our procedure, to change
  ;the color of the torus 'on the fly' (ba-dum)
  torus 30 -50 20 20
  ;creates an inverted torus by inverting the radius parameter.
  ;Closed shapes such as the torus don't ordinarily have an 'inside'
  ;unless we create them inverted.
  ;Why do we want to invert it?
  ;We're going to switch the camera turtle to Myrtle, and so
  ;we want to see inside the torus, not the outside. To do this,
  ;we invert it, as demonstrated above.
  ;don't forget, the turtle draws a line by default
  pullout 50
  left 90
  ;We're going to use the orbit primitive to move Myrtle
  ;inside of the torus. So we 'dropanchor' at Myrtle's position,
  ;to set the 'anchorpoint' that the orbit primitives rotate around,
  ;'tether' to keep the anchor point static (because otherwise
  ;when Myrtle turns the anchor point moves to stay in front of
  ;her) 'pullout' 50 turtle units from the anchor point, and then
  ;turn left 90 degrees (which we can do because we called tether)
  ;To demonstrate the need for tether, try:
  ;reset repeat 36 [repeat 90 [orbitleft 4] right 10]
  ;As you can see, the point Myrtle orbit arounds moves when she
  ;turns right. Put a 'tether' primitive before the first repeat
  ;and notice the difference!
  setpremodel [rt 10]
  ;'setpremodel' allows us to put commands between the 'turtle track'
  ;that contains everything the turtle draws and the turtle model
  ;When we attach the camera to a turtle, its position is
  ;set before premodel (and the turtle model) and so we can use
  ;setpremodel to change the position and orientation of the turtle
  ;as seen from the camera. And so we will see the model pointing
  ;slightly to the right
  setview "myrtle
  ;set the camera to show Myrtle's point of view
  snappy:setlight 0
  ;turn Snappy (the normal camera turtle)'s light off.
  ;Snappy has a light on by defalt.
  setlight 2
  ;turn Myrtle's light on. The value 2 is a point light,
  ;which casts light around Myrtle
  setdiffuse [40 40 40 100]
  setambient [0 0 0 0]
  ;these set paramets related to the light.
  ;see their help entries for more information
  setviewpoint [5 10 -50]
  ;sets the position of the camera relative to the turtle
  ;as a list of [x y z]. So in this case, to the right, above
  ;and behind the turtle
  forever [
    setpremodel {
    "right 20 - 30 * (sin 0.5 * loopcount)
    "slideright -5 + 10 * (sin 0.5 * loopcount)
    "up 10 * (sin loopcount)
    "raise 2.5 - 10 * (0.5 * sin loopcount)
    ;curly braces indicate a 'softlist', a list that is
    ;evaluated at the time of execution (the point at
    ;which the interpreter interprets the list).
    ;They allow us to use functions and containers to
    ;assemble a list dynamically.
    ;In this case, we're using the sin function and loopcount
    ;to move the turtle model relative to its position and
    ;simulate the motion of an aircraft in flight.
    ;loopcount is similar to repcount, but is used in non-repeat
    ;loops such as forever, while, until, dowhile, dountil and
    ;it counts the number of times the loop has been executed
    orbitleft 0.5
    ;orbit to the left half a degree. In this case, 'to the left'
    ;causes the turtle to appear to move forward. But remember,
    ;we turned the turtle to the left earlier in the procedure!
    if divp 300 loopcount [
      replacetag "col {
      "setfillcolor 1 + random 15
      "setfs -15 + random 30
    ;divp (or divisorp) returns true if the numerator (the first
    ;number) divides equally into the denominator (the second
    ;number, in this case the loopcount.)
    ;if divp returns true, we replace the "col tag we created
    ;earlier in the procedure with new contents setting a random
    ;color and shade. We need to use curly braces so that the
    ;random numbers are generated at the time we call replacetag.
    ;note that the primitives need to have a " in front of them
    ;so they are not themselves executed when the softlist is
    ;evaluated! By putting a quotation mark in front of them,
    ;they are evaluated as words and passed verbatim to
    ;the replacetag primitive.
    ;there are other ways to do this that you can do in other
    ;Logo environments but they are more cumbersome.
    sleep 5
    ;sleep for 5 milliseconds
  ;do this forever, or until we press escape or the stop button




A Guide to 3D Printing Using turtleSpaces

This guide is in development

Turtle Pen:

In the 3D turtleSpaces environment, pen sizes greater than 1 create cylinders.

setpensize 20

There is also a square pen style more suitable for 3D printing flat objects called mark. To activate it, type:

setpenstyle “mark

mark is two-dimensional by default. But you can increase its depth by setting pendepth using:

setpendepth 20

Valid shapes:

Shapes must be closed, that is they must have no exposed ‘inside’ faces. Closed shapes include:

voxel, voxeloid, sphere, spheroid, icosphere, icospheroid, cappeddome, cappeddomoid, cylinder, torus, etc.

Note: the cylinders used for large pen sizes (rope) are valid shapes and appear to slice correctly.

Warning: open shapes will be rejected by your 3D printer’s ‘slicing’ software!

Making hollow forms:

To create a ‘hollow’ form, an inverted shape must be created within the outer shape. For example:

ico 50 ico -40


voxel 100 fd 90 lo 90 sr 90 voxel -80

cone 50 100 10 rr 180 ra 10 cone 40 -80 10

Rocket Orbit

This simple commented project allows for the introduction of 3D movements and shapes (the rocket procedure) including a basic introduction to repeat, the creation of turtle models and the use of premodel, an introduction to the orbit primitives and the use of a new worker (thread) for orbiting the camera!

TO rocket
  forward 70
  down 90
  ;these two commands orient the rocket better for use as
  ;a turtle model
  setfillcolor yellow
  ;yellow is a function that returns the value 13
  ;it is a shortcut used for convenience in learning
  ;as is red, green, blue etc.
  cylinder 20 120 10
  ;cylinder takes   
  rollright 180
  ;flip the turtle over to create the nose cone
  cone 20 50 10
  lower 50
  ;lower the turtle to create the 'nose'
  setfillcolor red
  icosphere 3
  setfillcolor orange
  ra 50 + 120
  ;ra is short for raise
  rr 180
  ;rr is shorthand for rollright
  cutcone 20 30 30 10
  ;move the turtle to the bottom of the rocket and
  ;create the tail
  up 90 bk 30.1
  ;bk is short for back
  setfillcolor white
  repeat 2 [cylinderslice 40 5 20 10 rr 90]
  ;create the fins
  setfillcolor red
  dn 90 sl 10 bk 10 cylinder 10 10 10
  ;sl is short for slideleft
  fd 20 cylinder 10 10 10 sr 20
  ;fd is short for forward
  ;sr is short for slideright
  cylinder 10 10 10 bk 20 cylinder 10 10 10
  ;create the jets

TO createmodel
  ;cs is short for clearscreen
  begintag "rocketmodel
  ;tags are used to create turtle models
  ;among other uses. You can also use them to
  ;show or hide parts of the 'turtle track'
  ;run the rocket procedure
  ;close the tag
  newmodel "rocket "rocketmodel
  ;create a new model called 'rocket' based on the
  ;rocketmodel tag
  setmodel "rocket
  ;set the turtle's model to the rocket model
  ;clear away the tagged model, leaving only the

TO starfield :number
  ;suspend rendering of the scene until we're done drawing the stars
  repeat :number [
    randomvectors randomfillcolor
    ;randomvectors orients the turtle randomly
    ;while randomfillcolor sets a random fill color
    forward 1000 + random 1000
    ;move forward a random distance
    up 90
    ;orient the turtle up in preparation of creating a spot
    ;because the spot is created around and below the turtle
    spot 10 + random 10
    ;create a randomly-sized spot
  ;resume rendering

TO main
  ;resets turtleSpaces to a default state
  ;execute the createmodel procedure
  starfield 200
  ;execute the starfield procedure, passing the parameter value 200
  setmodelscale 0.5
  ;decrease the size of the turtle model to half normal
  setpremodel [lt 90]
  ;inserts 'left 90' into the turtle track between the scene
  ;and the turtle model ('pre' the model)
  setfillcolor 14
  ;sets the fillcolor to 14. Type 'showcolors' or 'sc' in the console
  ;to see a list of default colors. You can also definecolor your own!
  ico 50
  ;create an icosphere (the planet)
  ;set the 'anchor point', or the point the turtle 'orbits' around
  ;using the orbit commands, to the current turtle position
  pullout 80
  ;pull away 80 turtle units from the anchor point
  snappy:newworker [forever [orbitleft 0.1]]
  ;tell snappy the camera turtle to create a new routine or thread
  ;that forever orbits around the scene to its left one tenth of
  ;a degree at a time
  make "rotation 0
  ;define a container (variable) called 'rotation'
  ;and set it to 0. We're going to use it to keep track of the
  ;rotation of the rocket
  forever [
    inc "rotation
    ;same as make "rotation :rotation + 1
    ;there is also dec (decrement)
    setpremodel {"lt 90 "rollright :rotation % 360}
    ;curly braces indicate a 'softlist', a list that is evaluated
    ;at runtime. In this case, so that we can have a dynamic
    ;rotation value we pass to setpremodel
    ;% is shorthand for modulus
    orbitleft 1
    ;orbit the rocket one degree to the left
    wait 1
    ;wait one sixtieth of a second