3D Vertex to Screen coordinates

HI.

I am trying to get screen coordinates from vertices of an imported .obj file however it seems tricky.

I have used screenX(x,y,z) and screenY(x,y,z) but the problem is that these are affected by translations and rotations and so don’t actually give you the screen coordinates.
(I presume what is happening in the background is something to do with the modelview matrix in OPENGL but that’s a little beyond me).

So, to explain in a little more detail.
If I used the code below -

PShape object;
boolean doOnce = true;
float rx =0;

void setup() {
  size(640, 360, P3D); 


  object = loadShape("rocket_lo2.obj");
  object.disableStyle(); 

  /*
  pushMatrix();
   translate(width/4, height/8, -100);
   for(int i=0; i<object.length; i++) {
   shape(object[i]);
   println("Convert Vertices");
   convertVertices(object[i]);
   }
   strokeWeight(2);
   stroke(255, 0, 0);
   noFill();
   line (0, 0, 0, 20, 0, 0);
   line (0, 0, 0, 0, 20, 0);
   line (0, 0, 0, 0, 0, 20);
   popMatrix();
   */
}

void draw() {
  background(0, 0);
  strokeWeight(2);
  noFill();
  stroke(255);
  pushMatrix();
  translate(width/4, height/8, -200);
  //rotateZ(10);
  
  origin();
  shape(object);
  
    if (doOnce) {
    printChildVertices(object); 
    doOnce=false;
  }
  popMatrix();

  
  text(mouseX+","+mouseY, mouseX, mouseY);
  stroke(0, 255, 0);
  origin();

  
}

void keyPressed() {


  doOnce = true;
}

void origin() {
  line (0, 0, 0, 20, 0, 0);
  line (0, 0, 0, 0, 20, 0);
  line (0, 0, 0, 0, 0, 20);
}

void printChildVertices(PShape shape) {
  println("start of printChildVertices");
  println("Object child count: "+shape.getChildCount());
  for (int i=0; i<shape.getChildCount(); i++) {   
    PShape child = shape.getChild(i);
    println("child#: "+i);
    for (int j=0; j<child.getVertexCount(); j++) {
      PVector vert = child.getVertex(j);
      PVector modelVert = new PVector(modelX(vert.x, vert.y, vert.z), modelY(vert.x, vert.y, vert.z), modelZ(vert.x, vert.y, vert.z));
      println("vertex"+j+": "+vert);
      println("modelvertex"+j+ modelVert);
      println("screenvertex"+j+": "+screenX(modelVert.x, modelVert.y, modelVert.z)+","+screenY(modelVert.x, modelVert.y, modelVert.z));
    }
  }
  if (shape.getChildCount() ==0) {
    for (int j=0; j<shape.getVertexCount(); j++) {
      println("Object vertex count: "+shape.getVertexCount());
      PVector vert = shape.getVertex(j);
      println(vert);
    }
  }
  println("---------------------------------");
}

I get the following screen output

and (for example) the console output for the last two faces as:

child#: 18
vertex0: [ 0.088187, 317.6546, 0.016646 ]
modelvertex0[ 160.08818, 362.6546, -199.98337 ]
screenvertex0: 320.03864,279.7196
vertex1: [ 0.368775, 167.19542, 53.173702 ]
modelvertex1[ 160.36877, 212.19542, -146.8263 ]
screenvertex1: 320.17456,216.54315
vertex2: [ 38.06308, 163.50952, 39.772385 ]
modelvertex2[ 198.06308, 208.50952, -160.2276 ]
screenvertex2: 337.65915,214.10432
child#: 19
vertex0: [ 0.088187, 317.6546, 0.016646 ]
modelvertex0[ 160.08818, 362.6546, -199.98337 ]
screenvertex0: 320.03864,279.7196
vertex1: [ 38.06308, 163.50952, 39.772385 ]
modelvertex1[ 198.06308, 208.50952, -160.2276 ]
screenvertex1: 337.65915,214.10432
vertex2: [ 53.24524, 167.19543, -0.263939 ]
modelvertex2[ 213.24524, 212.19543, -200.26392 ]
screenvertex2: 343.31384,213.80061

So as can be seen from the image there is no point on the model that has a screen vertex of v.x = 343 and so these values don’t make sense.

I tried to work around this by using the following idea

apply translation in setup() then update the shape coordinates to the model coordinates and then call shape without translations in draw(). (as below).

pushMatrix();
   translate(width/4, height/8, -100);
   convertVertices(object);
   popMatrix();

void convertVertices(PShape shape) {
  for (int i=0; i<shape.getChildCount(); i++) {   
    PShape child = shape.getChild(i);
    for (int j = 0; j < child.getVertexCount(); j++) {
      PVector vert = child.getVertex(j);
      println("vert: "+vert);
      PVector modelVert = new PVector(modelX(vert.x, vert.y, vert.z), modelY(vert.x, vert.y, vert.z), modelZ(vert.x, vert.y, vert.z));
      println("modelVert: "+modelVert);
      child.setVertex(j, modelVert);
    }
  }
}
   

The problem with this is that it doesn’t allow me to rotate/move the model in the draw function (which I want to do). Or at least it makes it very tricky as the object has been moved from the origin.

If there was a way to actually get the screen coordinates as displayed that would be great. I presume OPENGL has to compute them somewhere to draw them - but maybe processing can’t easily get at that.
(I see here that processing does some tricky OPENGL stuff and so maybe this is why the screenX and ScreenY aren’t working as I would have hoped - or maybe I’m just doing something wrong).

The ultimate aim is to have an object or series of objects which are moving/rotating but from which I can determine the vertices in screen position.
It doesn’t necessarily have to be able to do so per frame (at 30fps) although this would be nice.
Any help much appreciated.
Thanks

Use screenX inside pushmatrix and popmatrix

Use it with (0,0,0);

Hi. Thanks

In my example ScreenX and ScreenY are called within the pushmatrix popmatrix as they are called in the function below.
But I was calling them on the model vertices (which was an artefact from an earlier attempt) and so that’s why they were wrong - I guess if you do ScreenX on top of Model X you get the transformation twice or something).
I have changed the function below to apply screenX to child vertices themselves.
Seems to do the job
Thanks for the help!

void printChildVertices(PShape shape) {
  println("start of printChildVertices");
  println("Object child count: "+shape.getChildCount());
  for (int i=0; i<shape.getChildCount(); i++) {   
    PShape child = shape.getChild(i);
    println("child#: "+i);
    for (int j=0; j<child.getVertexCount(); j++) {
      PVector vert = child.getVertex(j);
      //PVector modelVert = new PVector(modelX(vert.x, vert.y, vert.z), modelY(vert.x, vert.y, vert.z), modelZ(vert.x, vert.y, vert.z));
      println("vertex"+j+": "+vert);
     //println("modelvertex"+j+ modelVert);
      //println("screenvertex"+j+": "+screenX(modelVert.x, modelVert.y, modelVert.z)+","+screenY(modelVert.x, modelVert.y, modelVert.z));
      println("screenvertex"+j+": "+screenX(vert.x, vert.y, vert.z)+","+screenY(vert.x, vert.y, vert.z));
    }
  }
  if (shape.getChildCount() ==0) {
    for (int j=0; j<shape.getVertexCount(); j++) {
      println("Object vertex count: "+shape.getVertexCount());
      PVector vert = shape.getVertex(j);
      println(vert);
    }
  }
  println("---------------------------------");
}

Nicely done.

Chrisir

Not without a little help!
thanks