3D walker in a 3D grid / cube: what are the directions he can go to?

Hello all,

I was doing a 3D walker in a 3D-grid.

What are the directions he can go to?

I plan to have a list of PVectors and depending which one is active, we add it to his position again and again so he moves in that direction.

I just want the list of possible directions to be complete.

He can go towards x, towards y, towards z,
but also towards -x, towards -y, towards -z,

But then also diagonal…

I came up with the list.
Is it complete? Or redundant?

Thank you!

Warm regards,

Chrisir :wink:


  PVector[] pvList = {
    new PVector (0, 0, 1), 
    new PVector (0, 1, 0), 
    new PVector (1, 0, 0), 

    new PVector (1, 0, 1), 
    new PVector (1, 1, 0), 
    new PVector (0, 1, 1), 

    new PVector (1, 1, 1), 

    //---

    new PVector (0, 0, -1), 
    new PVector (0, -1, 0), 
    new PVector (-1, 0, 0), 

    new PVector (-1, 0, -1), 
    new PVector (-1, -1, 0), 
    new PVector (0, -1, -1), 

    new PVector (-1, -1, -1)

    
  };
1 Like

That list is correct.

There’s probably a fancy technique that you could use, but what you have is pretty much perfect.

No, it’s not complete

Hello,

Here is a ternary count which gives 3^3 = 27 counts:

PVector[] pvList1 = 
    {  
    new PVector ( 0,  0,  0),  // This can be removed
    new PVector ( 0,  0,  1),  // forward
    new PVector ( 0,  0,  2),  // reverse
    new PVector ( 0,  1,  0),   
    new PVector ( 0,  1,  1), 
    new PVector ( 0,  1,  2),     
    new PVector ( 0,  2,  0),   
    new PVector ( 0,  2,  1), 
    new PVector ( 0,  2,  2),   

    new PVector ( 1,  0,  0),   
    new PVector ( 1,  0,  1), 
    new PVector ( 1,  0,  2), 
    new PVector ( 1,  1,  0),   
    new PVector ( 1,  1,  1), 
    new PVector ( 1,  1,  2),     
    new PVector ( 1,  2,  0),   
    new PVector ( 1,  2,  1), 
    new PVector ( 1,  2,  2),      
    
    new PVector ( 2,  0,  0),   
    new PVector ( 2,  0,  1), 
    new PVector ( 2,  0,  2), 
    new PVector ( 2,  1,  0),   
    new PVector ( 2,  1,  1), 
    new PVector ( 2,  1,  2),     
    new PVector ( 2,  2,  0),   
    new PVector ( 2,  2,  1), 
    new PVector ( 2,  2,  2),  
    };

Replace all the 2’s with -1’s and you have a complete list that you can iterate down to what you want to use.

https://en.wikipedia.org/wiki/Ternary_numeral_system

:)

1 Like

Impressive.

I personally thought my list was for example

1,1,1

and

-1,-1,-1

but not

-1,1,-1

So not complete.

But I could not figure it out

Thank you!!

Chrisir

1 Like

here is it with -1

 PVector[] pvList = 
    {  
    // new PVector ( 0,  0,  0),   // This can be removed
    new PVector ( 0, 0, 1), // forward
    new PVector ( 0, 0, -1), // reverse
    new PVector ( 0, 1, 0), 
    new PVector ( 0, 1, 1), 
    new PVector ( 0, 1, -1), 
    new PVector ( 0, -1, 0), 
    new PVector ( 0, -1, 1), 
    new PVector ( 0, -1, -1), 

    new PVector ( 1, 0, 0), 
    new PVector ( 1, 0, 1), 
    new PVector ( 1, 0, -1), 
    new PVector ( 1, 1, 0), 
    new PVector ( 1, 1, 1), 
    new PVector ( 1, 1, -1), 
    new PVector ( 1, -1, 0), 
    new PVector ( 1, -1, 1), 
    new PVector ( 1, -1, -1), 

    new PVector ( -1, 0, 0), 
    new PVector ( -1, 0, 1), 
    new PVector ( -1, 0, -1), 
    new PVector ( -1, 1, 0), 
    new PVector ( -1, 1, 1), 
    new PVector ( -1, 1, -1), 
    new PVector ( -1, -1, 0), 
    new PVector ( -1, -1, 1), 
    new PVector ( -1, -1, -1), 
  };

You must have put a lot of work in this

How did you make the list? Not by hand I guess. But with code.

How did you make the 3D graphic as a demonstration?

It’s an awesome post.

Reminds me of the discussion and your post here by the way: Iterate once and only once through all the possible configurations of an array

ah, the code to generate the list could be:



size(300, 300); 

println("PVector[] pvList1 = "); 
println("    {"  );

for (int i0 = 0; i0 < 3; i0++) { 
  for (int i1 = 0; i1 < 3; i1++) { 
    for (int i2 = 0; i2 < 3; i2++) { 
      //String a = str(i0)
      //  +str(i1)
      //  +str(i2);
      println(
        "        new PVector ( "  
        + str(i0)+", "
        +str(i1)+", "
        +str(i2)
        +" ),");
    }//for
  }
}

println("};");

and the code to demonstrate the list as a graphic


float angle1; 

// auto-generated list of 3D PVectors for all possible directions in 3D (right, left, up, diagonal right downwards....)
PVector[] pvList1 = 
  {
  //  new PVector ( 0, 0, 0 ), 
  new PVector ( 0, 0, 1 ), 
  new PVector ( 0, 0, -1 ), 
  new PVector ( 0, 1, 0 ), 
  new PVector ( 0, 1, 1 ), 
  new PVector ( 0, 1, -1 ), 
  new PVector ( 0, -1, 0 ), 
  new PVector ( 0, -1, 1 ), 
  new PVector ( 0, -1, -1 ), 
  new PVector ( 1, 0, 0 ), 
  new PVector ( 1, 0, 1 ), 
  new PVector ( 1, 0, -1 ), 
  new PVector ( 1, 1, 0 ), 
  new PVector ( 1, 1, 1 ), 
  new PVector ( 1, 1, -1 ), 
  new PVector ( 1, -1, 0 ), 
  new PVector ( 1, -1, 1 ), 
  new PVector ( 1, -1, -1 ), 
  new PVector ( -1, 0, 0 ), 
  new PVector ( -1, 0, 1 ), 
  new PVector ( -1, 0, -1 ), 
  new PVector ( -1, 1, 0 ), 
  new PVector ( -1, 1, 1 ), 
  new PVector ( -1, 1, -1 ), 
  new PVector ( -1, -1, 0 ), 
  new PVector ( -1, -1, 1 ), 
  new PVector ( -1, -1, -1 ) 
};

void setup() {
  // init
  size(800, 600, P3D);
} // func 

void draw() {
  // runs on and on 
  background(0);
  lights();

  stroke(255, 0, 0);
  strokeWeight(8);

  pushMatrix();
  translate(width/2, height/2, 0);
  rotateX(-0.2992);
  rotateY(angle1); 

  int i=0; 
  for (PVector pv : pvList1) {
    float amt = map(i, 
      0, pvList1.length, 
      0, 1);
    stroke(lerpColor(color(255), color(255, 0, 0), amt));
    line(
      //0, 0, 0, 
      pv.x*8, pv.y*8, pv.z*8, 
      pv.x*88, pv.y*88, pv.z*88);
    i++;
  }//for
  popMatrix();
  //

  stroke(100); 
  //  noFill();
  fill(255, 0, 0);

  pushMatrix();
  translate(100, 100, 0);
  rotateZ(angle1);
  if (!keyPressed)
    angle1+=.04; 
  box(60);
  popMatrix();

  pushMatrix();
  translate(400, 100, 0); 
  rotateX(angle1);
  fill(0, 0, 255);
  box(60);
  popMatrix();

  pushMatrix();
  translate(700, 100, 0);
  rotateY(angle1);
  box(60);
  popMatrix();

  pushMatrix();
  translate(700, 300, -330);
  noStroke(); 
  sphere(50);
  popMatrix();
} // func 
//

Thank you!

Very inspiring!

1 Like

I did some house cleaning (refactoring) and post a new version

Chrisir


// Demo for a **graphical representation** of a list of PVectors that represent the directions you can go in a 3D grid (like L/R and up/down and diagonal etc.):
// in the upper etage 9 directions, in the lower etage 9 directions and in the same plane (middle etage) 8 directions. This gives you 9+9+8 = 26 directions (without vector 0,0,0 itself of course).
// cf. https://discourse.processing.org/t/3d-walker-in-a-3d-grid-cube-what-are-the-directions-he-can-go-to/24419

// (I used this in a 3D Tic-Tac-Toe Game to find all possible lines (of 3 cells) in the 3D-board (grid) you can **win** in (these indices / lines are NOT what is shown here).)

// auto-generated list of 3D PVectors for all possible directions in 3D (right, left, up, diagonal right downwards....)
PVector[] pvList = {
  //  new PVector ( 0, 0, 0 ),
  new PVector ( 0, 0, 1 ),
  new PVector ( 0, 0, -1 ),
  new PVector ( 0, 1, 0 ),
  new PVector ( 0, 1, 1 ),
  new PVector ( 0, 1, -1 ),
  new PVector ( 0, -1, 0 ),
  new PVector ( 0, -1, 1 ),
  new PVector ( 0, -1, -1 ),
  new PVector ( 1, 0, 0 ),
  new PVector ( 1, 0, 1 ),
  new PVector ( 1, 0, -1 ),
  new PVector ( 1, 1, 0 ),
  new PVector ( 1, 1, 1 ),
  new PVector ( 1, 1, -1 ),
  new PVector ( 1, -1, 0 ),
  new PVector ( 1, -1, 1 ),
  new PVector ( 1, -1, -1 ),
  new PVector ( -1, 0, 0 ),
  new PVector ( -1, 0, 1 ),
  new PVector ( -1, 0, -1 ),
  new PVector ( -1, 1, 0 ),
  new PVector ( -1, 1, 1 ),
  new PVector ( -1, 1, -1 ),
  new PVector ( -1, -1, 0 ),
  new PVector ( -1, -1, 1 ),
  new PVector ( -1, -1, -1 )
};

// old wrong version for comparison
PVector[] pvList_OLD = {
  new PVector (0, 0, 1),
  new PVector (0, 1, 0),
  new PVector (1, 0, 0),

  new PVector (1, 0, 1),
  new PVector (1, 1, 0),
  new PVector (0, 1, 1),

  new PVector (1, 1, 1),

  //---

  new PVector (0, 0, -1),
  new PVector (0, -1, 0),
  new PVector (-1, 0, 0),

  new PVector (-1, 0, -1),
  new PVector (-1, -1, 0),
  new PVector (0, -1, -1),

  new PVector (-1, -1, -1)
};

// rotate the object
float angleRotate;

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

void setup() {
  size(1800, 900, P3D);
  textSize(19);
  textMode(SHAPE);
  println("Number of directions: "+pvList.length);
} // func

void draw() {
  background(0);
  lights();

  showListOfPVectors(pvList);

  if (! keyPressed)  // stop rotation with any key 
    angleRotate += 0.004;

  decoration();
} // func

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

void showListOfPVectors(PVector[] pvList_) {
  // prepare scene
  pushMatrix();
  translate(width/2, height/2, 0);
  rotateX(-0.2992);
  rotateY(angleRotate); // rotate animation 

  // loop over the list
  int i=0;
  for (PVector pv : pvList_) {
    showThisVector(pv, i); // show one PVector 
    i++;
  }//for

  // reset
  popMatrix();
}

void showThisVector(PVector pv_, int intNumber_) {
  float lengthLine = 188;

  // calc color for this vector 
  float amt = map(intNumber_,
    0, pvList.length,
    0, 1);
  color colLine3d = lerpColor(color(255), color(255, 0, 0), amt);

  // draw pv_ as a 3D line
  line3D(
    pv_.copy().mult(8),
    pv_.copy().mult(lengthLine),
    16,
    colLine3d,
    intNumber_);
}

void line3D(PVector pv1_,
  PVector pv2_,
  float weight_,
  color color_,
  int intNumber_) {
  // draws a 3D-Line from pv1_ TO pv2_ with thickness weight_ and color color_
  // and shows a number intNumber_ at its end.

  // Was called drawLine; programmed by James Carruthers, modified,
  // see http://processing.org/discourse/yabb2/YaBB.pl?num=1262458611/0#9
  PVector v1 = new PVector(pv2_.x-pv1_.x, pv2_.y-pv1_.y, pv2_.z-pv1_.z);
  float rho = sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z);
  float phi = acos(v1.z/rho);
  float the = atan2(v1.y, v1.x);
  v1.mult(0.5);

  // The line
  pushMatrix();
  translate(pv1_.x, pv1_.y, pv1_.z);
  translate(v1.x, v1.y, v1.z);
  rotateZ(the);
  rotateY(phi);
  // noStroke();
  stroke(0);
  fill(color_);
  // box(weight,weight,p1.dist(p2)*1.2);
  box(weight_, weight_, pv1_.dist(pv2_)*1.0);
  popMatrix();

  // The text (optional)
  pushMatrix();
  float yAdd = -21;// for the 2 upper etages we push intNumber_ up by 21
  if (pv2_.y > height/2.0-300) {
    yAdd = 23; // for the lower etage we push intNumber_ down by 23
  }
  translate( pv2_.x+21, pv2_.y + yAdd, pv2_.z-21);
  rotateY(-angleRotate);// rotate towards camera
  fill(255);
  text(intNumber_, 0, 0);
  popMatrix();
}

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

void decoration() {
  stroke(100);
  fill(255, 0, 0);

  pushMatrix();
  translate(100, 100, 0);
  rotateZ(angleRotate);
  box(60);
  popMatrix();

  pushMatrix();
  translate(400, 100, 0);
  rotateX(angleRotate);
  fill(0, 0, 255);
  box(60);
  popMatrix();

  pushMatrix();
  translate(700, 100, 0);
  rotateY(angleRotate);
  box(60);
  popMatrix();

  pushMatrix();
  translate(1000, 100, -30);
  noStroke();
  sphere(50);
  popMatrix();
}
//

1 Like