MAXScript vertex philosophy

Started by
10 comments, last by experiment 10 years, 2 months ago

While writing a script for exporting to custom format I noticed that in max, texture vertices are separated from position vertices, and I can't seem to connect the dots. So you have vertices, face index that iterates through vertices, and then texture vertices with their own story? I thought that as a joke and then read this in the maxscript help:

The mesh class contains a list of texture vertices which are completely independent of the regular vertices in the mesh. There is no correlation between the number of vertices in a mesh and the number of texture vertices. In addition to the texture vertices there are also texture faces. There needs to be one texture face for every regular face in the mesh.

whaat..?

Different number of vertices, same number of faces... my gears just broke.

Under editable mesh and trimesh there is a topic "Understanding texture coordinates.." and a section on "finding the corresponding vertices" which goes like this:

In order to find out which texture vertex corresponds to a mesh vertex, you have to do the following:

  1. Take the index of the mesh vertex.

  2. Find out which faces reference the index of the face.

  3. Note the number of the vertex (1st , 2nd or 3rd - .x, .y or .z) inside each face.

  4. For each face referencing the vertex, get the texture face with the same index.

  5. Get the index of the respective texture vertex from the face - 1st , 2nd or 3rd / .x, .y or .z

  6. The vertex you got corresonds to the mesh vertex we started with.

  7. Repeat steps 3 to 6 for all faces found.

... I don't understand a single step in here. It's just throwing words "find index of vertex, reference, face.." You never know if it means position vertex index or texture vertex. You either have to be a mind reader, or the guy that wrote this. And thanks for not a single illustration.

If I just go through the steps:

1. Take the index of the mesh vertex.

- What index? One specific? All of them? What mesh vertex? Position or texture?

2. Find out which faces reference the index of the face.

- What is "the face"? What did I miss between step 1 and 2??

No. I give up. If someone can shed some light on this or suggest a more suitable software for this task (per vertex position, normals and texture coords export and a decent documentation/help) I'd be so happy. I didn't buy max, so I'm not tied to this. I pray there is a better alternative.

I thought that max was THE choice for game dev modeling, but all these weird design choices. Like, who uses Z as up vector.

Advertisement

That's the way MAX works internally. You'll have a bunch of positions, texture coordinates, smoothing groups (and other stuff) and several face structures defining how to put things together for the MAX renderer.

I assume that you want to extract data that can be used with a GPU. This question arises every now and then so you should be able to find message chains explaining the vertex extraction.

- In order to extract the vertices you'll need to a list of vertex positions

- but since there can be multiple attributes per vertex, you'll actually need a list of lists containing different versions of each vertex.

- so according to the attributes you want to extract, you'll need to search the list of vertices for a vertex with the exactly same attributes (same position same UV, same smoothing group).

- at the end you'll need to create indices for each unique vertex and then map the triangle indices to the vertex indices.

It isn't the easiest thing to implement, but not the hardest when you get your head around it.

Cheers!

This is actually the common way of working with vertices in modeling programs like Max and Maya. It works the same way for normals and colors as well: they're all stored in arrays that are independent from the positions. If it makes you feel any better, this also threw me for a loop back when I was first learning graphics programming.

If you don't want to deal with directly exporting data from Max, you can consider exporting to FBX or Collada and using Assimp to load the mesh data. Assimp is really easy to use, and has flags that let you process the mesh data into something that's nearly ready for the GPU to consume (it will give you the positions/normals/texcoords as separate arrays, but they're already duplicated/split so you just need to combine them into a single structure if you want the data to be interleaved). Just be aware that you need to build from the latest development branch if you want FBX support, and it only supports ASCII FBX files at the moment.

Yeah. You know I'm just mad cause I can't wrap my head around it. It's too bad they didn't cover this section a little better with more help or even some predefined functions. Hey, newcomers are a good source of income too.

I have noticed it is the same with some other attributes.

I can understand the design behind "per face normal" and I got around it by: - going through each position vertex, and for each vertex go through every face and see if it holds any index that is equal to the current position vertex index and storing that face normal in an array, so just after writing that vertex position, it adds all the normals in the array and divides by number of normals (finding the average among them) and normalizes that vector before writing it down.

in some pseudo it would be:


for each postion vertex i
{
   pvec = getVert(i);

   array A;
   for each face j
   {
       face = getFace(j)
       if face[0] or face[1] or face[2] == i
       append faceNormal(j) to A;
   }
   nvec = sum of all elements in A / A.size();
   nvec.normalize();

   write(pvec); // postition
   write(nvec); // normal
}

It's easy to get per vertex normals because they correspond to the index held by faces describing position verts.

Textures have their own faces.. which are the same size as postion vertex faces.. but have a different index inside - I'm guessing, since the number of position and texture verts is not the same it would make sense. Hmmm..

I exported a simple box / cube model


box

// position verts
-0.5 -0.5 -0.5
0.5 -0.5 -0.5
-0.5 -0.5 0.5
0.5 -0.5 0.5
-0.5 0.5 -0.5
0.5 0.5 -0.5
-0.5 0.5 0.5
0.5 0.5 0.5

// position faces
1 3 4
4 2 1
5 6 8
8 7 5
1 2 6
6 5 1
2 4 8
8 6 2
4 3 7
7 8 4
3 1 5
5 7 3

// texture verts
0.0 0.0
1.0 0.0
0.0 1.0
1.0 1.0
0.0 0.0
1.0 0.0
0.0 1.0
1.0 1.0
0.0 0.0
1.0 0.0
0.0 1.0
1.0 1.0

// texture faces
10 12 11
11 9 10
9 10 12
12 11 9
5 6 8
8 7 5
1 2 4
4 3 1
5 6 8
8 7 5
1 2 4
4 3 1

Or what if I somehow adapted the position verts to texture verts instead of vice versa in order to preserve texture coordinates.. I wonder how that would affect GPU performance / memory on large scale. Hmm..

Now I did the same for a simple plane model, and noticed that some of the texture vertices don't even get used.


plane

// pos v
-0.5 0.0 -0.5
0.5 0.0 -0.5
-0.5 0.0 0.5
0.5 0.0 0.5

// pos faces
3 1 4
2 4 1

// tex v
0.0 0.0
1.0 0.0
0.0 0.0
1.0 0.0
0.0 0.0
1.0 0.0
0.0 1.0
1.0 1.0

// tex faces
7 5 8
6 8 5

you are inspecting geometry definition wrongly. In max script you have to inspect faces. A face is a triple (face=triangle) of indicies that will point to data- verticies. A vertex without specification does not exist in max, there is a -position (vertex), normal (vertex), facenormal (vertex)..... and much much more. max just guarentiies that by the index of a face.x/y/z you will peek corespondant data of that corner in any of the many type verticies arrays (normal,color) . It is up to you how many verticies you duplicate, meaning, max in object properties displays amount of position+unweld verticies, if you export the mesh. you may have much more or less verticies, but the information of triangle count fits, f.e. in editable poly max displays not amount of triangles but polygons.

so the code would be:

mesh=snapshotAsMesh object

numtriangles= getTriangleCount mesh

for i=1 to numtriangles do

(

face= getMeshFace mesh i

position=getVert face.x

normal=getNormal face.x

)

you are inspecting geometry definition wrongly. In max script you have to inspect faces. A face is a triple (face=triangle) of indicies that will point to data- verticies. A vertex without specification does not exist in max, there is a -position (vertex), normal (vertex), facenormal (vertex)..... and much much more. max just guarentiies that by the index of a face.x/y/z you will peek corespondant data of that corner in any of the many type verticies arrays (normal,color) . It is up to you how many verticies you duplicate, meaning, max in object properties displays amount of position+unweld verticies, if you export the mesh. you may have much more or less verticies, but the information of triangle count fits, f.e. in editable poly max displays not amount of triangles but polygons.

so the code would be:

mesh=snapshotAsMesh object

numtriangles= getTriangleCount mesh

for i=1 to numtriangles do

(

face= getMeshFace mesh i

position=getVert face.x

normal=getNormal face.x

)

This is a more correct inspection method compared to what? My pseudo code? The reason I don't post script code is that I can't expect people to take time to fix my code. Instead just give some guide. But if someone wants to do that, be my guest.

edit: *code removed for political reasons if you still want to look at it, see post history*

This is supposed to be a billiard 11ball...

0b5d.jpg

why do you cry over my shoulder you posted pseudo code? I did not offend you for doing so. And I am not gonna be your guest to correct your very code for I believe I explained abstractly enough information for you to be aware of - diplayed in my pseudo code, about how verticies are treated in max. That there is simply a face index, wheather there are mapfaces or faces, and their indicies point to correct value. In your script you only write to a file unindexed texture coordinates of every face, I do not see anything about normals and positions you sepparated from texture coordinates-which- you append to an array upon vertex count not by the face way, as you do for texture coordinates. Your code absolutely violates indexing and vertex layout.

This topic is closed to new replies.

Advertisement