How 3D Turtle like in LOGO - but 3D - math problem

Hello all,

I used a sketch from @vrtxt

https://forum.processing.org/two/discussion/20688/plotting-points-on-a-sphere#latest

and made a Turtle program like in LOGO but as 3D.

see article here.

Imagine a turtle that draws with a pen. When you tell it to go forward, it heads forward and paints a line. When you tell it to turn right 90° and then go forward, you got an right angle painted. Repeat that four times a you have rectangle.

A 3D Turtle

Now imagine you got a water turtle and can tell it to turn upwards and downwards with its nose (pitch) as well and thus paint 3D or paint lines that go in an angle upward or downward from the classical 2D canvas of the Turtle (or imagine first it's only paddling on the surface and then suddenly dips down and swims towards the ground).

I tried to draw a cube by first paint a rect (that works) (points abcda), then I am at point "a" again. Then go forward once to point "b". Then turn downward (that's the 3D part) 90° and paint again a rectangle. Now you would have two rectangles in a 90° angle. That four times should give you a cube made of four rectangles (doesn't work).

Anyway, I failed utterly, probably due to a permanent lack of intelligence I encounter regularly.

Maybe the problem lies there that when I calculate the new line to draw (the new turtle position) I assume to start from the 0,0,0 which is true only at the start.

Maybe someone can track down my bug.

Here's what I got so far:

float a1; 


// see https : // en.wikipedia.org/wiki/Aircraft_principal_axes
int angleTurtle=0; // YAW axis
int angleTurtleNoseDown=0; // PITCH axis 

float Phi=0; 
PVector XYZ=new PVector(100, 100, 100);

void setup() {
  size(1200, 1000, P3D);
  background(111);
}

void draw() {
  background(255);

  lights(); 
  translate(width/2, height/2, 0);

  dropSphere( color(255, 0, 0)); 

  for (int i=0; i<4; i++) {
    FW(100);
    RI(90);
  }

  // dropSphere( color(2, 255, 0));

  FW(100);
  noseDown(90); 

  for (int i=0; i<4; i++) {
    FW(100);
    RI(90);
  }

  dropSphere( color(2, 0, 255));
  FW(100);
  noseDown(90); 

  for (int i=0; i<4; i++) {
    FW(100);
    RI(90);
  }

  dropSphere( color(111));

  noLoop();
}

// -------------------------------------------

void RI (float angleAdd) {
  angleTurtle+=angleAdd;
}

void noseDown (float angleAdd) {
  angleTurtleNoseDown+=angleAdd;
}

void FW(  float len  ) {

  // PVector XYZ=new PVector();
  // PVector gear0=new PVector(100, 100, 100); 
  float Theta=0;
  float Phi=0; 

  println (  XYZ.x+","+ XYZ.y+","+ XYZ.z); 

  PVector oldPV = XYZ.copy();

  Theta = radians(angleTurtleNoseDown); 
  Phi = radians(angleTurtle);

  XYZ.x =oldPV.x+ len*cos(Theta)*sin(Phi);
  XYZ.y =oldPV.y+ len*sin(Theta)*sin(Phi); 
  XYZ.z =oldPV.z+ len*cos(Phi);

  stroke(0);
  line (oldPV.x, oldPV.y, oldPV.z, 
    XYZ.x, XYZ.y, XYZ.z) ;
}

void dropSphere( color colDrop) {
  // just for testing 
  pushMatrix();
  translate(XYZ.x, XYZ.y, XYZ.z);
  fill(colDrop);
  noStroke(); 
  sphere(3);
  popMatrix();
}
//

Thanks to you all!

Best, Chrisir ;-)

«13

Answers

  • edited February 2017 Answer ✓

    @Chrisir -- this is a thought -- I haven't tested, however.

    If you want to keep a relative position no matter what the turtle does, perhaps you should use appluyMatrix() to save the relative state before you pop at the end of draw(), and getMatrix() at the beginning of draw. Likewise, to modify the state outside draw (e.g. with input key functions) you would wrap the key function code in the same way:

    1. push
    2. get
    3. translate
    4. apply
    5. pop.

    In this way you can continue to pile on transformations with each turtle rotate and move-forward, and you won't ever run out of matrix stack since you are popping the stack at the end of each operation and reloading only its last state.

    Then it really is a turtle -- it will always start at 0,0,0 and always move forward to (0,0,n) (or whatever you want your default axis to be).

  • Good idea.
    I had implemented something similar a year or so back, will try and dig it out. It used a Turtle class however, unlike your code. And if I remember right, it had FD, BK, RT, LT, UP and DN for directions/moving. But it wasn't much wisely built, so it wouldn't seem very realistic.

  • That sounds very interesting!!

  • I realised that it's probably on my older laptop, so it will take a fair bit of time to search it (in fact, I'm sure I can write the code again in that much time, but I won't, just for the sake of it).

    Note that the directions are very non-intuitive, so you may struggle to get it to draw anything useful - one of the reasons why I never bothered to make the program into a library.

  • Gotoloop, did you try your link? Doesn't work for me....?

    Also, it is turtle and not 3D Turtle?

  • edited February 2017 Answer ✓

    @Chrisir -- re:

    four times should give you a cube made of four rectangles

    Your concept as described (3D Turtle) is a good one, and it can work just fine. translate() and rotate() are already relative and cumulative, so you can use them directly (accepting that there may be a small floating point error -- see https://forum.processing.org/two/discussion/comment/76577/#Comment_76577).

    That simplifies things a lot: drawing a line is always moving forward (x,0,0). Moving is always moving forward (x,0,0). Turning is just calling rotateX(), rotateY(), or rotateZ(). A line is a line, a rect is four lines, a box is four rects. Make sure that the rotation calls for the rects and the box are on different axes (the tricky part!) and you are done:

    /**
     * Turtle3D RectBox
     * 2017-02-07 Jeremy Douglass - Processing 3.2.3
     * https:// forum.processing.org/two/discussion/20706/how-3d-turtle-like-in-logo-but-3d-math-problem
     */
    import peasy.*;
    PeasyCam camera;
    
    void setup(){
      size(300,300, P3D);
      // focus the cam on the center of the box
      camera = new PeasyCam(this, 25, 25, -25, 100);
    }
    
    void draw(){
      background(192);
      pushMatrix();
        tRectBox(50);
      popMatrix();
    }
    
    void tRectBox(int x){
      for(int i=0; i<4; i++){
       tRect(x);
       tStep(x);
       rotateY(HALF_PI);
      }
    }
    
    void tRect(int x){
      for(int i=0; i<4; i++){
       tLine(x);
       rotateZ(HALF_PI);
      }
    }
    
    void tStep(int x){
      translate(x,0,0);
    }
    
    void tLine(int x){
      line(0,0,0,x,0,0);
      translate(x,0,0);
    }
    

    Turtle3DRectBox--screenshot

  • edited February 2017 Answer ✓

    Did you try your link?

    Sometimes I don't, b/c those links are copied directly from browser's address bar.
    That 1 is a tag link, which lists all forum threads using that tag.

  • Thanks!

    link is working now

  • edited February 2017

    link is working now

    Well, I haven't edited that link post at all.
    Some glitch on your side back when you tried it 1st. :-??

  • edited March 2017

    i tried it on my phone first and then on computer, yes. I wasn't working on my phone. So a glitch on my side, yes. Thank you.

  • @Chrisir -- so... did my turtle sketch solve your problem...? You said you wanted a solution, but you seem more interested in other things ;)

  • i don't have time to look into it right now, but thanks!!

  • edited February 2017 Answer ✓

    @jeremydouglass Sure, your program does draw a box, but I think that @Chrisir is more interested in something that will allow you to draw anything you want in 3D.

  • edited February 2017 Answer ✓

    But that is the whole point. The only things you need to turtle-draw anything in 3D are tStep, tLine, and the built-ins rotateX()/rotateY()/rotateZ().

    If you also want turtle state to persist between frames for continuous progressive drawing you additionally need getMatrix/applyMatrix, since the turtle is always at 0,0 and its location is saved by the matrix stack (which gets wiped each draw).

    But that's it -- move, line, three degrees of rotation and stack location gets you a full 3D turtle.

  • edited March 2017

    @jeremydouglass: thanks, mate! Today I had time to look into your 3D Turtle sketch and it is impressive. Here is my version.

    Thank you!

    Best, Chrisir ;-)

    https://github.com/Kango/3D-Turtle/tree/master/simpleDemoOld

  • You beat me, @Chrisir. Much better than mine.

  • edited March 2017

    I made a tree house with the turtle.

    It's much fun and more hands on than working with abstract numbers.

    The turtle can also YAW, roll and pitch now like a plane (what it is in a way).

    https://github.com/Kango/3D-Turtle

    Thanks again.

    Best, Chrisir ;-)

  • edited March 2017

    this shows a function to draw a shape with N corners

    https://github.com/Kango/3D-Turtle

  • edited March 2017

    I made small tutorial for the 3D Turtle

    https://github.com/Kango/3D-Turtle

  • edited March 2017

    .

  • Perhaps you should use GitHub. It will make it a lot simpler. I could help you package everything into a library if you want.

  • Thank you so much, I never used github or made a library

  • So you'll learn then? Good. First just create a GitHub account and upload all this code in a new repository. It's fairly easy to do, just took me a day to learn the basics. Then you can just post the link here and get rid of all this long code. It's a lot cleaner. Converting to a library is a bit more difficult, but if you don't want all the fancy documentation, it's not much work.

  • edited March 2017

    Can I upload a sketch to github which has multiple tabs in processing ?

    Can you show me a link?

  • Answer ✓

    I think you will load multiple pde files under the same github folder. After all, the Processing IDE creates a file for each tab. Or you could merge all the files into a single pde. I will keep the multiple pde files if they are modular. For example, if each tab represented a class.

    One question about your code, do you draw your lines through a script or would you do that live when the user is interacting with your software. When I run your code (I haven't run your tutorial version yet), what is the command to put down your pencil?

    Kf

  • edited March 2017

    There is no script.

    The user writes his turtle code into the code itself. Which is bad.

    pen Down is the default. Drawing.

    When pen is up, the pen is not touching the surface anymore, so the turtle is only moving without drawing.

    Commands are penDown() and penUp() without parameters.

  • Answer ✓

    Great and thxs for your clarification @Chrisir. I will give it a try... soonish I hope.

    Kf

  • edited March 2017

    Tutorial shows this (penDown() and penUp()); unfortunately I had to post the tutorial in two posts here

  • The user writes his turtle code into the code itself. Which is bad.

    But the fix is fairly easy. Just create a function to take in a String and execute accordingly.

    Now on how to upload to GitHub-

    • Create a repository of appropriate name.
    • On you computer, create a folder containing all the .pde files that make up the project (is it correct to call it that?).
    • Click the upload files button in GitHub and upload the entire folder (created previously).
    • Commit to changes.
    • Done!
  • @Lord_of_the_Galaxy You need to explain if you want to make changes, would you fork or push changes? Or commit every time? What do you do? :-B 8-} :(|)

    Kf

  • That really depends on your wish. You could commit directly to the master branch, or fork and then submit a pull request before merging the two branches. The second method is recommended in later stages where you may want approval from multiple people. In initial stages of a project, you just commit directly to the master branch. And there ends my knowledge of GitHub. I'm still not clear how that "releases" thing works.

  • edited March 2017

    @Lord_of_the_Galaxy

    you wrote:

    But the fix is fairly easy. Just create a function to take in a String and execute accordingly.

    Well, yes...

    not sure I understand this.

    do you mean with eval()?

    but it's pretty hard to implement it manually so to speak, because to program your own for loop or your own functions with parameters, that's pretty hard, I guess...

    Or what do you mean?

    I agree though a simple Forward 100 Left 90 ... would be doable...

    Thanks!

    Chrisir

  • edited March 2017

    [SOLVED]

    github....

    …or create a new repository on the command line
    
    echo "# Turtle-3D-Logo" >> README.md
    git init
    git add README.md
    git commit -m "first commit"
    git remote add origin https://github.com/Kango/Turtle-3D-Logo.git
    git push -u origin master
    

    what am I gonna do???????????????????

    which command line?????????????????????????

    in web command line I get:

    git init
    git add README.md
    git commit -m "first commit"
    git remote add origin https://github.com/Kango/Turtle-3D-Logo.git
    git push -u origin master
    
    SyntaxError: missing ; before statement [Weitere Informationen]
    git remote add origin https://github.com/Kango/Turtle-3D-Logo.git
    git push -u origin master
    SyntaxError: missing ; before statement [Weitere Informationen]
    

    [SOLVED]

  • edited March 2017

    Oh, I think I got it. Just edit the readme and you are there.

    https://github.com/Kango/3D-Turtle

  • Watch the movie:

  • Answer ✓

    Your movie is great and very helpful. I downloaded the source from your github. I notice that after opening the container folder, the foldername does not match any of the pde file name. Could you name the main pde file and the folder name the same?

    Also, is it possible to draw a reference axis in case I get lost in space? Or having a grid on the XY plane would also be helpful as to depict a ground surface,

    Kf

  • edited March 2017

    Nice tutorial. That little turtle is cute.

    But I think that the organisation is a bit flawed. You should be having something like this -

    README.md
    LICENSE 
    Turtle-3D-Logo
      \src
        \[all .pde files, excluding any main .pde file as its not required]
      \examples
        \[example 1 name]
          \[example 1 .pde files, including a main .pde file with same name as the folder]
        \[example 2 name]
          \[example 2 .pde files, including a main .pde file with same name as the folder]
    

    That way, you just need a single repository. Like mine - https://github.com/Lord-of-the-Galaxy/Timing-Utilities (ignore the config_.yml file)

  • Well, something like eval. For example, if the function is called as such - Turtle.execute("FD 100") the turtle should move forward by 100.

  • edited March 2017

    you wrote:

    Well, something like eval. For example, if the function is called as such - Turtle.execute("FD 100") the turtle should move forward by 100.

    True. But as soon as you have nested for-loops or functions in your script you need to parse it, don't you?

  • edited March 2017

    @kfrajer

    I uploaded a new version of a small turtle sketch; the turtle has a function that allows to draw a shape with n corners.

    I hope this time the folder name is correct as you described

    It also comes with a neat new grid as you asked

    https://github.com/Kango/3D-Turtle

  • umh...... actually github always appends a _master on my folder name.

    It seems you have to rename the folder (delete _master at the end of the folder name)

    Sorry!

  • @Chrisir Really, you need to put all that into a single repository. Like I said earlier.

    As for parsing, perhaps another function "parse" that takes in an array of String as parameter and executes them in order, perhaps even having functionality for REPEAT.

  • edited March 2017

    not sure I understand the single repository.

    Should I do this although I don't have a library yet?

    (I need to read this:

    Make a GitHub repo place for them all:

    https://Help.GitHub.com/articles/create-a-repo/

    https://guides.github.com/activities/hello-world/

    )

  • Do it, if only for practice. It is better to have all related items in a single repository. First, you create a folder on your own computer with the same structure as you need in the repository (I have given the guidelines in my previous comments). Then upload the whole folder to a GitHub repository as is. You can always use the website if the command line thingy confuses you (it did confuse me at first).

  • @Lord_of_the_Galaxy

    like this?

    https://github.com/Kango/3D-Turtle

    I couldn't select multiple folders....

  • how can I delete an entire repository?

    or a folder inside a repository?

  • Exactly, @Chrisir. As for how to delete an entire repository, just search online and you'll find it. But AFAIK it is fairly difficult to just delete an entire folder in a GitHub repository.

    And perhaps you should rename the __github folder to something better. Just google to find out how.

  • Answer ✓

    How can I delete an entire repository?

    • Just below the repo's name, there are 7 clickable tabs.
    • Click at Settings tab; the last 1 btW.
    • Once there, scroll all the way down and click at "Delete this repository".
  • edited March 2017 Answer ✓

    I couldn't select multiple folders...

    • At the left side of this green button: "Clone or download", there are more 3 buttons.
    • Choose "Upload files". You can drag onto it your whole project's folder and you're done!
Sign In or Register to comment.