No, the morphs aren’t being welded. Their indices are correlated to the unaltered geometry. Morphs can be defined in the imported file that defines the figure. But they can also be ‘injected’ at any later time - thus the reason to keep the vertex array order and count unaltered.
Anyway, yes I have seen this problem and I think we understand the issue pretty well. What I’m ultimately telling you is the OBJs are a very base format and you shouldn’t be using OBJs if you can at all help it. You should be exporting the geometry to a format that has proper support for groups and material assignments so you don’t have to deal with segmented meshes at all. That would be the best solution. I mean these meshes aren’t segmented in Poser are they? If not, why export to a fomrat that’s going to muck up the mesh by segmenting it and omitting important information?
If you are going to continue to use these OBJs your method of comparing vertex to vertex is going to be very slow. You have to use a better method to find matches. If you are still seeing seams after a mesh is welded it’s because you aren’t properly handling your normals. I don’t think OBJ supports normals so C4D must be creating face varying normals. When you weld you need to create a new normal for each point you weld to smooth out the seam.
Nothing that I can do about the use of these OBJ files - they are what is used by the format being imported. Poser welds them (these are the weld commands about which I mentioned earlier). I’m working with the same base objects that Poser loads and must weld them as well.
The seams are currently being correctly welded, just very slowly in cases of many vertices/polygons. OBJ does indeed support normals (v = vertices, vt = UV, vn = normals). The seams are only an artifact caused by the discontinuity between the polygons because of the different albethey coincident vertices. I don’t think normals are a factor - these are ignored anyway and not included in many figure geometries at all.
One thing that is still confusing me is that you mentioned sorting the array into ascending order. But upon what criteria? They are already sorted by index (0-n) - obviously :). The Cinema 4D vertex array for polygon objects contains everything (indices and actual point coordinates, not two separate lists or whatnot):
point[0] = vertex(x,y,z)
point[1] = vertex’(x,y,z)
…
point[n] = vertex’’’(x,y,z)
So that the array is an array of Vector structs with Float x,y,z values and operators and friend methods (a public class, that is). It’s easy enough to duplicate the array and sort it in situ, but should it be sorted on matches (equivalent vertices by epsilon) or x,y,z values?
Also, Cinema 4D’s polygon structure is a bit of a pita, especially concerning the separate groups. If you don’t mind, I can explain this is more detail so that you see what I’m working with. The polygons are stored in an array as well. So there is a Vector array for vertices and a Polygon struct array for polygons. The polygon struct is:
struct Polygon
{
public:
Polygon(LONG t_a, LONG t_b, LONG t_c);
Polygon(LONG t_a, LONG t_b, LONG t_c, LONG t_d);
LONG a;
LONG b;
LONG c;
LONG d;
};
where a,b,c,d are indices into the Vector array storing the vertices. If the polygon is a triangle, d = c. This is all pretty standard construction for polygonal meshes.
Now the fun part. Since the Polygon mesh is a single object, the groups are stored and determined using ‘tags’. Tags are attached to objects and store attributes. For our purposes, there are Point Selection and Polygon Selection tags that are of interest. Cinema 4D stores an array in each of these that just stores a selection state (selected or not) over the entire vertex or polygon set (i.e.: if there are 32000 polygons, there are 32000 selection states in each Polygon Selection tag). So, a group of the OBJ can be stored in a Polygon Selection tag by selecting the polygons in the selection array that match those referenced by the OBJ group.
Getting at the selection set is odd. Each Selection tag stores a BaseSelect class which contains the selection set (this class is used for various other selections in the interface as well). The ‘quick’ and recommended method to traverse through the selected items in the BaseSelect is:
BaseSelect* pbs = tag->GetBaseSelect();
for (pseg = 0; pbs->GetRange(pseg,&c,&d); ++pseg)
{
for (j = c; j <= d; ++j)
{
....
}
}
As you can see, this is very loop intensive. Doing two of these nested of course means doing a four-level nested for loop to compare polygons of each selection set (group).
I’m trying to divorce myself from these constructs so as to apply the welding optimally - and thus the reason for researching, searching, and asking for help. And, thank you very much for the ideas so far! It may take a little bit to get me to understand how to arrange this data in a fashion that makes the two processes optimal: vertex matching and polygon reindexing.
Robert