Imagination PowerVR SDK Blog

Unaligned vertex weights in exported data

pvrgeopod

#1

Hi,

We’re still trying to get a model rendering on the iPhone, but glDrawElements is generating an exception.

Looking a little deeper, I’ve noticed that the base pointer of the vertex weights (specified as GL_FLOAT) is not 4-byte aligned.  This seems to be because the previous vertex property is the matrix indices, which consists of 3 unsigned bytes.

Is this misalignment likely to cause a problem in glDrawElements (I suspect so), and should the exporter not be aligning blocks consisting of GL_FLOATs to the next 4-byte boundary?

Any advice appreciated!

Thanks,
Rich



#2

Just to follow-up… I found some documentation stating that unaligned data will work, but will probably incur a speed penalty.  The crash must be due to something else…

But, the request still stands: would it be possible in a future version of the exporter to align blocks according to their type when generating interleaved vertices, or at least provide an option to enable this if you wish?



#3
Tragnarion wrote:

But, the request still stands: would it be possible in a future version of the exporter to align blocks according to their type when generating interleaved vertices, or at least provide an option to enable this if you wish?


 

Hi,

 

Thanks for the suggestion. It is a little late to add to the next release of the SDK but it is something we will add to a future release.

 

Thanks,

 

Scott

#4

I’d like to add my support for this feature request. Matrix Palette Indices have to be exported as unsigned bytes (ie. 1 byte) and they will mess up the stride to be non-aligned. Makes accessing the data outside of glDrawElements difficult too. Lots of slow memcpy’ing!

Cheers,
Donovan. 


#5

Hi everyone,





I’m also experiencing a similar issue that my exported model works just fine on the iPhone simulator 3.x. However, it stops at “glDrawElements” when I tried to run it on the actual device (OS3.0).





These are my exporting options (from Maya2009)











Maya MB file





Texture file





POD file





Can anyone please help me on this one? thanks!


#6

When exporting from Maya to POD, does the PVRGeoPOD exporter have an error log of what it couldnt successful convert from Maya to POD?


#7

@ykang - iPhone hardware only supports three bone influences per vertex (whilst the simulator will successfully run with 4)… so uncheck the last box in the exporter for “bone index” and “bone weight” and all should work OK.


#8

@PowerVR - any news on whether this request will make it into a future version of the exporter any time soon?

Thanks.


#9

Aligning data will be supported in a new release of the SDK. A tthem moment a log of what the exporter ttries to export is produced and shown, I believe.


#10

OK, many thanks Gordon.

For the moment, I’m working around the problem by reallocating the ‘interleaved’ chunk at runtime, aligning the contents, and then patching up the data offset and strides of all the elements by hand - but obviously this is a pain and it’ll be great to have the elements aligned at export time :slight_smile:

For the benefit of anyone who finds this thread who might be suffering the same problem as I was - it seems that the iPhone implementation of OpenGL ES isn’t happy with interleaved unaligned vertex elements.  While it seems to work superficially, I was experiencing very strange and random problems regarding the lighting - some meshes were consistently rendered unlit while others were ok, and the behaviour could even be changed by rendering them in a different order.  All these problems go away when feeding glDrawElements() with a properly aligned set of interleaved data.


#11

Hi Tragnerion,

I have had the same lighting problem! Any chance you could share your alignment code in advance of Imagination’s next release?

Would be very helpful Smile

Cheers,
Donovan.


#12

Erm, sure, but it's nothing particularly clever or robust!  It makes a few assumptions about the sort of models we export (e.g. no multitexturing, etc), and also assumes that the only vertex property which will be exported misaligned is the bone weight, and that this is the last property in the interleaved data.

All I did was added the following function to PVRTModelPOD.cpp:

static void AlignInterleavedData(SPODMesh& s)
{
    // This is a hacked-in function to get around the problem that the exporter doesn't align
    // its interleaved vertex data correctly.  OpenGL ES should be able to handle unaligned
    // data (albeit at a speed cost), but the iPhone implementation doesn't.
   
    // It is assumed that the only unaligned data will be the bone weight (the only field
    // which occurs after the bone index field, which causes the problem).
   
    assert(s.sVertex.pData < s.sBoneIdx.pData);
    assert(s.sNormals.pData < s.sBoneIdx.pData);
    assert(s.sTangents.pData < s.sBoneIdx.pData);
    assert(s.sBinormals.pData < s.sBoneIdx.pData);
    assert(s.nNumUVW == 1 && s.psUVW[0].pData < s.sBoneIdx.pData);
    assert(s.sVtxColours.pData < s.sBoneIdx.pData);
    assert(s.sBoneWeight.pData > s.sBoneIdx.pData);
   
    unsigned int oldStride = s.sVertex.nStride;
    unsigned int alignedStride = (oldStride + 3) & ~3;
    unsigned int startUnaligned = reinterpret_cast<unsigned int>(s.sBoneWeight.pData);
   
    assert((oldStride & 3) != 0);
   
    SafeRealloc(s.pInterleaved, s.nNumVertex * alignedStride);
   
    for (int i = s.nNumVertex - 1; i >= 0; i--)
    {
        unsigned char* pSrc = s.pInterleaved + i * oldStride;
        unsigned char* pDest = s.pInterleaved + i * alignedStride;
       
        memmove(pDest + ((startUnaligned + 3) & ~3), pSrc + startUnaligned, oldStride - startUnaligned);
        memmove(pDest, pSrc, startUnaligned);
    }
   
    s.sVertex.nStride = alignedStride;
    s.sNormals.nStride = alignedStride;
    s.sTangents.nStride = alignedStride;
    s.sBinormals.nStride = alignedStride;
    s.psUVW[0].nStride = alignedStride;
    s.sVtxColours.nStride = alignedStride;
    s.sBoneIdx.nStride = alignedStride;
    s.sBoneWeight.nStride = alignedStride;
   
    s.sBoneWeight.pData = reinterpret_cast<unsigned char*>((startUnaligned + 3) & ~3);
}

and then added a call to it in ReadMesh() like so:

        case ePODFileMesh | PVRTMODELPOD_TAG_END:
            if(nUVWs != s.nNumUVW) return false;
            AlignInterleavedData(s);
            return true;

I'm not proud of the solution by any means, but at least it works, even if it fragments the model data a bit :)



#13

Same problem here, thank you very much for sharing the code. Btw, will the new version of SDK include a fix for this problem?



#14

According to https://www.imgtec.com/forum/forum_posts.asp?TID=577, they have already fixed this in SDK version 2.6, but I have no idea when this will get an official release!

#15

Our releases are always in late summer and spring - 2.6 should be available in the next month or so.