LWO loading and UVs

Started by
6 comments, last by PixelPhil 18 years, 6 months ago
Hi, I am currently implementing the lwo mesh loading feature in my engine. But unfortunately I can't get the UV to be loaded correctly and the result looks wrong like this: (this is supposed to be a dead imp like the one we can see in Doom3's demon museum) I use the C parser code provided in the Newtek SDK to read the file and to add uv coordinates to my vertexbuffer (verts) I use the following code.

for (lwVMap* vmap = layer->vmap; vmap; vmap = vmap->next)
{
   if (vmap->dim == 2) // texture coords
   {
       for (int i = 0; i < vmap->nverts; i++)
       {
           int index = vmap->vindex;
           float *values = vmap->val;
           verts[index].uv = D3DXVECTOR2(values[0], 1.0 - values[1]);
       }                 
   }
}
Here I only deal with 1 layer and my vmap contains as much values as I get vertices so I assume it is a bijection (no projected texture here). I tried to flip and swizzle u and v but didn't get a convincing result. I render using DirectX. I'd really appreciate some hints. Phil
Advertisement
Has anybody successfully implemented lwo loading with explicit UV mapping?

Phil
Yeah, I've got one working, but it's a plugin rather than an external loader:

(cut-and-paste code here. No attempt at cleaning it up for the forums)
void expMesh::ExportUVMaps( void ){	int i;	uint a, j, p;	int numUVMaps = obj->numVMaps(LWVMAP_TXUV);	void *uvmap = AQ_NULL;    	//Find valid UV maps (this is WAY more complicated than it needs to be >_<)	for (i = 0; i < numUVMaps; i++) 	{		const char *uvname = AQ_NULL;       		uvname = obj->vmapName(LWVMAP_TXUV, i);        if (uvname) 		{                                 			uvmap = meshInfo->pntVLookup( meshInfo, LWVMAP_TXUV, uvname );			for(j = 0; j < polys.Size(); j++)			{						for(p = 0; p < 3; p++)				{					aQVect2 uvtemp( 0.0f, 0.0f );					a = polys[j].index;										//Check "discontinuous" UV maps first, then continuous					//If it's a discontinuous coord, then we'll have to create a new vertex to hold					//the correct UV. If you ask me this is just a plain fucked up design... *sigh*					if( meshInfo->pntVPIDGet( meshInfo, points[a].pid, polys[j].pid, uvtemp.GetPointer(), uvmap ) )					{						expPoint newPoint = points[a];						newPoint.uv = uvtemp;												polys[j].index = points.Push( newPoint );					}					else if( meshInfo->pntVIDGet( meshInfo, points[a].pid, uvtemp.GetPointer(), uvmap ) )					{						points[a].uv = uvtemp;					}				}			}        }    }	if(expFlags & EXP_DEBUG)	{		InfoBox("UV Extraction Complete");	}	return;}


Hope that helps some. I'm at work now, so I don't have much time to explain, but I'll try to post some more in-depth info when I have a free moment.
// The user formerly known as Tojiro67445, formerly known as Toji [smile]
This post cheers me up. Thanks.
Though I'm not quite sure what meshInfo->pntVPIDGet does... Any hints?
I don't recognises newtek's structures here though the are similar enough for me ta make the connection.

What is that constinuous/discontinuous thing?

EDIT: now I see that some polygons have a vmap and some don't and I understand that points are not doubled as they should be at texture seams. but I have a hard time putting it all together... This vmap mechanism is really a pain in the ...

Phil

[Edited by - PixelPhil on September 23, 2005 7:40:16 PM]
Quote:This vmap mechanism is really a pain in the ...


That really says it all right there. You're right in saying that the verticies aren't doubled up correctly in places where the texture breaks. More accurately: ther is only one "vertex" stored per unique position, and that vertex may have multiple texture coordinates associated with it. It's up to you as the exporter to bring the two togheter logically. (Which is really dumb if you ask me)

In this case they're stored as "continuous" and "discontinuous" mappings. A Continuous mapping is, for example, a point on your imp's head. All of the verticies around it have UV's that can interpolate directly from one point to another without breaking (hence the "continuous" bit). You will only ever have one continuous UV map per vertex, so it's "safe" to store that UV in the original vertex structure. This is what you are doing right now.

A Discontinuous map is essentially anywhere that there is a seam in the texture. These are a little more difficult to get at, but not too hard. The biggest difference is that while you only have to pass in a pointID to get a continous mapping, you must pass in both a polygonID AND a pointID to get a discontinous map. (Probably obvious, but the pointID you supply must be one of the points on that polygon.) If you do get a discontinous map coordinate, you'll have to create a duplicate of your current vertex with the new texture coordinates. Then adjust the index for that point within that polygon.

It's all a little strange to wrap your head around, but it eventually falls into place. Try looking through the code I posted again and you'll see how I handle this (polies and points both use a structure very similar to std::vector)

*sigh* I typed twice as much but I don't think I made any more sense... let me know if you have any other questions!
// The user formerly known as Tojiro67445, formerly known as Toji [smile]
Mmmm... things are getting clearer now though as i use the C version of the parser I don't have these two functions. pntVIDGet is quite straightforward (though it's a stupid inneficient linear search). But i don't see how to implement pntVPIDGet with the structures I got.

My structures are:

typedef struct st_lwVMap {   struct st_lwVMap *next, *prev;   char          *name;   unsigned int   type;   int            dim;   int            nverts;   int            perpoly;   int           *vindex;              /* array of point indexes */   int           *pindex;              /* array of polygon indexes */   float        **val;} lwVMap;typedef struct st_lwPolVert {   int            index;               /* index into the point array */   float          norm[ 3 ];   int            nvmaps;   lwVMapPt      *vm;                  /* array of vmap references */} lwPolVert;typedef struct st_lwPolygon {   lwSurface     *surf;   int            part;                /* part index */   int            smoothgrp;           /* smoothing group */   int            flags;   unsigned int   type;   float          norm[ 3 ];   int            nverts;   lwPolVert     *v;                   /* array of vertex records */} lwPolygon;


somehow pindex is NULL on the vmaps of the imp.

Phil

EDIT: Whooohooo! it works! I figured out that discontinuous and continuous UVs where stored in different lwVMap with the same name. Anyway, thanks for your precious help, you made my day. You might see something coming in the image of the day in a near future ;) Thanks. Phil

[Edited by - PixelPhil on September 24, 2005 12:20:31 PM]
Great! Glad you got that straightened out! I'm going to be looking forward to that IOTD ^_^
// The user formerly known as Tojiro67445, formerly known as Toji [smile]
Here it is :D.

Thanks again.

Phil

This topic is closed to new replies.

Advertisement