screenPositionFunction not projecting correctly

This is my test of the screenPosition function that is not working correctly for me. I have digitized the 6 faces for a basic block and tried drawing them with world coordinates and then screen coordinates. The screen drawn block is not projecting correctly. Can you tell me what is wrong? Magenta is world - White is screen. Click to spin. Thanx.

https://editor.p5js.org/cln123gp/sketches/dNKVZLsOb

1 Like

You are rotating the XYZ coordinates and projecting your “screen XY” to the rotated XY coordinates.

This is just a quick first pass at this working through your code (modified) with one side only to illustrate how to use this:

Click to open! Version 1 Original quick first pass
var faceXYZ = [];
var faceXY = [];
var th = 0;

function setup() 
  {
  createCanvas(800, 600, WEBGL);
  addScreenPositionFunction();
  noFill();
  strokeWeight(2);
  faceXYZ[0] = [10, 0, 0,  50, 0, 0,  50, 0, 25,  10, 0, 25];
  ortho();
  }

function draw() 
  {
  background(204);
push();
  scale(2);
  rotateX(PI/8);
  if (mouseIsPressed) th = th + PI/180;
  rotateY(th);
  stroke(150);
  line(0, 0, 0, 0, 0, -80); // y-axis aka -z gray
  stroke(150);
  line(0, 0, 0, 80, 0, 0); // x-axis aka +x gray
  stroke(0);
  line(0, 0, 0, 0, -80, 0); // vertical axis aka -y white
  polyDrawXYZ(faceXYZ[0]);
pop();

  translate(20, 20, 0);
  for (i = 0; i < 6; i += 1) polyDrawXY();
  }

function polyDrawXYZ(xface) 
  {
  // Draw 1 sides of block using world cooordinates
  stroke('magenta');
  beginShape();
  var j = 0;
  for (var i = 0; i < 12; i += 3) 
    {
    vertex(xface[i], xface[i + 1], xface[i + 2]);
    var p1 = screenPosition(xface[i], xface[i + 1], xface[i + 2]);
    faceXY[j] = p1.x;
    faceXY[j + 1] = p1.y;
    j += 2;
    }
  endShape(CLOSE);
}

function polyDrawXY() 
  {
  // Draw 1 sides of block using screen coordinates
  stroke(255, 255, 0);
  beginShape();
  for (var i = 0; i < 8; i += 2) 
    {
    vertex(faceXY[i], faceXY[i + 1]);
    }
  endShape(CLOSE);
}
Click to open! Version 2 New and improved
var faceXYZ = [];
var faceXY = [];
var th = 0;

function setup() 
  {
  createCanvas(800, 600, WEBGL);
  addScreenPositionFunction();
  noFill();
  strokeWeight(2);
  faceXYZ[0] = [10, 0, 0,  50, 0, 0,  50, 0, 25,  10, 0, 25];
  faceXY[0] = [0, 0, 0,  0, 0, 0,  0, 0, 0,  0, 0, 0,];
  ortho();
  }

function draw() 
  {
  background(204);
push();
  scale(2);
  rotateX(PI/8);
  if (mouseIsPressed) th = th + PI/180;
  rotateY(th);
  stroke(150);
  line(0, 0, 0, 0, 0, -80); // y-axis aka -z gray
  stroke(150);
  line(0, 0, 0, 80, 0, 0); // x-axis aka +x gray
  stroke(0);
  line(0, 0, 0, 0, -80, 0); // vertical axis aka -y white
  polyDrawXYZ(faceXYZ[0]);
pop();

  //translate(20, 20, 0);
  polyDrawXY(faceXY[0]);
  }

function polyDrawXYZ(xface) 
  {
  // Draw 1 sides of block using world cooordinates
  stroke('magenta');
  beginShape();
  for (var i = 0; i < 12; i += 3) 
    {
    vertex(xface[i], xface[i + 1], xface[i + 2]);
    var p1 = screenPosition(xface[i], xface[i + 1], xface[i + 2]);
    faceXY[0] [i]= p1.x;
    faceXY[0][i+1] = p1.y;
    faceXY[0][i+2] = p1.z; //This is 0
    }
  endShape(CLOSE);
  }

//translate(10, 0, 0);
function polyDrawXY(xface) 
  {
  // Draw 1 sides of block using screen coordinates
  stroke(255, 255, 0);
  beginShape();
  for (var i = 0; i < 12; i += 3) 
    {
    vertex(xface[i], xface[i + 1], 0);
    }
  endShape(CLOSE);
  }

Examples above require this library:
https://github.com/bohnacker/p5js-screenPosition

image

I will leave the rest with you.

There is also an updated P5.js to link to in your index.html:

:)

1 Like

I have tried many variations on your code. The push and pop seem to play a big role. I tried adding the other faces. You can do any one face but things get crazy with more than one. I loaded your code verbatim and the two rectangles do not stay in the same location to each other. They cross over.

There is nothing else I can try. At this point if you have a suggestion it would be welcome. Otherwise I’m done. Thanx.

Hello,

That is because I added this so you could see the two shapes without them overlapping:

translate(20, 20, 0);

Feel free to comment it out!

I just threw this together for proof of concept.
Focus on the concept and not the code.

Update:

  • I added another face.
  • I cut and paste sections of my code.
  • It works.
  • And then I was able to refactor it to slim down the code.
  • The rest of faces can be done same way.

Output without translate and another face:
image

You may have one big huge mess but then you have to look at it and think about reducing comment elements down to simple ones.

:)

References:


https://p5js.org/reference/#/p5/push
1 Like

Please send me the revised code. My rectangles aren’t just linear translations. They cross each other in random order. Thank you for your help.

I am only providing you with code that will lead you towards a solution to your project.

I added a Version 2 to previous post above; my Version 1 was a quick first pass version as an example and really needed a rework.
Version 2 is an improved simple example with one face that can be expanded to more with a bit of effort; you will have to pass some additional parameters to function or rework it to suit you. The one function only works with faceXY[0] but that is easily remedied and I have done this in my code.

That is great! The examples take XYZ (world) and project it to XY plane (this can be screen).

image

:)

It is really frustrating to not know my way around this forum well enough to find the revised code or sketch you issued here. It is doing exactly what I expected. Please tell me how to get the new example. Thanx.

Hello,

Yes indeed!

I am working through your code as an exercise for me; I do enjoy the daily challenges.

Here is what I can share:

Click for Code

//Requires this library:
//https://github.com/bohnacker/p5js-screenPosition

var faceXYZ = [];
var faceXY = [];
var th = 0;

function setup() 
  {
  createCanvas(500, 500, WEBGL);
  addScreenPositionFunction();
  noFill();
  strokeWeight(2);
  faceXYZ[0] = [10,0,0,    50,0,0,     50,0,25,     10,0,25];
  faceXYZ[1] = [10,0,25,      50,0,25,  50,-25,25,  10,-25,25];
  faceXYZ[2] = [50,0,25,       50,0,0,   50,-25,0,  50,-25,25];
  faceXYZ[3] = [10,-25,25,  50,-25,25,   50,-25,0,   10,-25,0];
  faceXYZ[4] = [10,-25,25,   10,-25,0,     10,0,0,    10,0,25];
  faceXYZ[5] = [10,-25,0,    50,-25,0,     50,0,0,     10,0,0];
  
  for (var i = 0; i < 6; i++ )
    {
    faceXY[i] = [0, 0, 50,  0, 0, 50,  0, 50, 0,  50, 0, 0];
    }
  ortho();
  }

function draw() 
  {
  background(204);
  
  translate(0, 0, 100);

  //XYZ World
 push();
  scale(2);
  rotateX(PI/8);
  if (mouseIsPressed) th = th + PI/180;
  rotateY(th);
  stroke(150);
  
  line(0, 0, 0, 0, 0, -80); // y-axis aka -z gray
  stroke(150);
  line(0, 0, 0, 80, 0, 0); // x-axis aka +x gray
  stroke(0);
  line(0, 0, 0, 0, -80, 0); // vertical axis aka -y white
  
  for (var i = 0; i < 6; i++ )
    {
    polyDrawXYZ(i);
    }
 pop();
 
// XY Screen  
  for (var k = 0; k < 6; k++ )
    {
    polyDrawXY(k);
    }
  }
  
//******************************************************************************************** 

function polyDrawXYZ(j) 
  {
  // Draw 1 side of block using XYZ world cooordinates
  stroke('magenta');
  beginShape();
  for (var i = 0; i < 12; i += 3) 
    {
    vertex(faceXYZ[j][i], faceXYZ[j][i+1], faceXYZ[j][i+2]);
    var p1 = screenPosition(faceXYZ[j][i], faceXYZ[j][i+1], faceXYZ[j][i+2]);
         
    //faceXY[j][i] ...
    }    
  endShape(CLOSE);
  }

function polyDrawXY(k) 
  {
  // Draw 1 side of block using XY screen coordinates
  
  // faceXY[k][i]
  }
  

I found it easier to pass around the array element (face) when working through this.
You have to fill in the missing pieces if you want to try this.

:)

Hello: This is not my project. I sent in my first entry because your function was not working correctly for me. I am 67 years old and have been writing 3d javascript/canvas code as a hobby for many years. There is something wrong here. You need to help me and yourself find out what that is. It could be Macintosh related. I do not need you to leave me with code to finish for educational purposes. I need your complete revised sketch with the three polygons. If I have to I will rewrite this for Processing and test the screen XY functions there. Thank you.

I was hoping you would submit the final version of the faces test with 3 polygons. I have tried everything I can to make the double array method work with no success. You keep leaving your examples for me to take it from there. I am not able to do that on my own yet. Could you please publish the final version so that I can figure out what is wrong? Thank you.

1 Like

I will not be assisting further with this.

You never gave me enough information to find out what is wrong and now you refuse my one last request to answer that question. Please reconsider. Are you absolutely sure that your function works on a Macintosh?

1 Like