问题
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