Processing OBJ extract vertex

半腔热情 提交于 2019-12-08 10:36:03

问题


How can i get, and print vertex of an OBJ on processing?

PShape x;

void setup(){ size(600,600,P3D); x = loadShape("x.obj");

} void draw(){

   for (int i = 0; i < x.getVertexCount(); i++) {   PVector v =
x.getVertex(i);

translate(width/2,height/2); shape(x,0,0); }

}

回答1:


I recommend first having a look at the OBJ format and at your mesh.(More details on Paul Bourke's site)

You should be able to easily inspect the topology using a free 3D editor (such as Blender, Wings3D, etc.). (e.g. mesh -> triangles or quads -> vervices)

The idea is to have a clear understanding how your file is structured (does it use triangle, quad faces or a combination, are there any nested structures, etc.)

Once you know how your model is structured it will be much easier to access each face and it's vertices. As Kevin mentioned, just use Processing's PShape functions to traverse the mesh. For example:

  • getChildCount() to count the number of PShape child instances (handy for traversing deeply nested tree structures)
  • getChild() to retrieve a PShape child instance at a given instance
  • getVertexCount() to count vertices in a PShape instance
  • getVertex() to get a PShape instance vertex at a given (valid index)

Be sure to always check how many PShape children are available before traversing and how many vertices are available to avoid NullPointerReference errors.

Here's a modified version of the sample from Examples > Basics > Shape > LoadDisplayOBJ

/**
 * Load and Display an OBJ Shape. 
 * 
 * The loadShape() command is used to read simple SVG (Scalable Vector Graphics)
 * files and OBJ (Object) files into a Processing sketch. This example loads an
 * OBJ file of a rocket and displays it to the screen. 
 */


PShape rocket;

float ry;

int startFaceIndex = 0;
int stopFaceIndex;

int maxFaceIndex;

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

  rocket = loadShape("rocket.obj");

  maxFaceIndex = rocket.getChildCount();
  stopFaceIndex = maxFaceIndex;

  println("total faces:",rocket.getChildCount());
  println("faces[0] vertices count:",rocket.getChild(0).getVertexCount());
  println("faces[0] vertices[0]",rocket.getChild(0).getVertex(0));
  println("faces[0] vertices[1]",rocket.getChild(0).getVertex(1));
  println("faces[0] vertices[2]",rocket.getChild(0).getVertex(2));
}

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

  translate(width/2, height/2 + 100, -200);
  rotateZ(PI);
  rotateY(ry);
  //shape(rocket);
  drawFaceSelection();

  ry += 0.02;
}

void drawFaceSelection(){
  beginShape(TRIANGLES);
  for(int i = startFaceIndex; i < stopFaceIndex; i++){
    PShape face = rocket.getChild(i);
    int numVertices = face.getVertexCount();
    for(int j = 0; j < numVertices; j++){
      vertex(face.getVertexX(j),face.getVertexY(j),face.getVertexZ(j));
    }
  }
  endShape();
}

void mouseDragged(){
  if(keyPressed){
    startFaceIndex = (int)map(mouseX,0,width,0,maxFaceIndex-1);
    startFaceIndex = constrain(startFaceIndex,0,maxFaceIndex-1);
  }else{
    stopFaceIndex = (int)map(mouseX,0,width,1,maxFaceIndex-1);
    stopFaceIndex = constrain(stopFaceIndex,0,maxFaceIndex-1);
  }
}

Running the demo you can drag the mouse on X axis to control how many faces of the .obj mesh are drawn:

If you don't care about the faces/structure and just want to access the vertices (to render them as quads or any shape you like), you could write a recursive function to traverse the PShape and it's children and append all vertices to a flat list:

/**
 * Load and Display an OBJ Shape. 
 * 
 * The loadShape() command is used to read simple SVG (Scalable Vector Graphics)
 * files and OBJ (Object) files into a Processing sketch. This example loads an
 * OBJ file of a rocket and displays it to the screen. 
 */


PShape rocket;

float ry;

ArrayList<PVector> vertices = new ArrayList<PVector>();
int startVertexIndex = 0;

public void setup() {
  size(640, 360, P3D);
  strokeWeight(9);

  rocket = loadShape("rocket.obj");

  getVertices(rocket,vertices);
  println(vertices);
}

/*
* recursively retrieves vertices from a PShape
* @arg PShape shape - the PShape instance to traverse (must be not null)
* @arg ArrayList<PVector> vertices - the list of vertices to add values to
*/
void getVertices(PShape shape,ArrayList<PVector> vertices){
  //for each face in current mesh
  for(int i = 0 ; i < shape.getChildCount(); i++){
    //get each child element
    PShape child = shape.getChild(i);
    int numChildren = child.getChildCount();
    //if has nested elements, recurse
    if(numChildren > 0){
      for(int j = 0 ; j < numChildren; j++){
        getVertices(child.getChild(j),vertices);
      } 
    }
    //otherwise append child's vertices
    else{
      //get each vertex and append it
      for(int j = 0 ; j < child.getVertexCount(); j++){
        vertices.add(child.getVertex(j));
      }
    }
  }
}

public void draw() {
  background(255);
  lights();

  translate(width/2, height/2 + 100, -200);
  rotateZ(PI);
  rotateY(ry);
  //shape(rocket);
  drawVerticesSelection();

  ry += 0.02;
}

void drawVerticesSelection(){
  beginShape(POINTS);
  for(int i = startVertexIndex; i < vertices.size(); i++){
    PVector v = vertices.get(i);
    vertex(v.x,v.y,v.z);
  }
  endShape();
}

void mouseDragged(){
  startVertexIndex = (int)map(mouseX,0,width,0,vertices.size()-1);
  startVertexIndex = constrain(startVertexIndex,0,vertices.size()-1);
}

Here's a preview showing/hiding vertices in a mesh:

Bare in mind this ignores vertexCodes().

Additionally, if you don't want to change the .obj file itself and just how it's rendered, you should look into GLSL and read the Processing PShader tutorial. It's lower level, but will be a lot more efficient and you'll have a lot more flexibility over the rendering process.




回答2:


From the Processing forum:

According to the documentation, the getVertexCount() and getVertex() functions only work with vertexes you've added by calling the vertex() function, not from shapes you've loaded from a file.

But there is a way to (at least sometimes) get to the vertexes inside a shape file: you first have to loop through the children of the shape file, then get the vertexes from those children.

PShape shape = loadShape("x.obj");
PShape child = shape.getChild(0);
PVector vertex = child.getVertex(0);

Consult the reference for functions that would allow you to loop over each child PShape, then loop over the vertexes of each child.



来源:https://stackoverflow.com/questions/40937648/processing-obj-extract-vertex

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!