spencewah
spencewah

Reputation: 2236

Help me evaluate this casting

I found this in the PowerVR mesh drawing code and I don't really know how to read it.

&((unsigned short*)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]]

What is going on here? Is this a reference to void cast as an unsigned short pointer and then offset by (3*mesh(etc...) + batchNum)? It's breaking my brain.

It's found in the context of a glDrawElements call:

glDrawElements(GL_TRIANGLES, i32Tris * 3, GL_UNSIGNED_SHORT, 
               &((unsigned short*)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]]);

Upvotes: 3

Views: 268

Answers (4)

Bahbar
Bahbar

Reputation: 18015

Really, this kind of hack is due to OpenGL expressing offsets inside Buffer Objects through the pointer argument of glDrawElements.

glDrawElements(mode, count, type, void* indices)

indices represents either a client-side memory pointer or a server-side memory offset based on the binding of GL_ELEMENT_ARRAY_BUFFER_ARB

It's interesting to dig a bit deeper... From the VBO specification:

Is it legal C to use pointers as offsets?

We haven't come to any definitive conclusion about this. [...]

Varying opinions have been expressed as to whether this is legal, although no one could provide an example of a real system where any problems would occur.

Upvotes: 1

Brian Campbell
Brian Campbell

Reputation: 332986

Let's go from the inside out.

(unsigned short*)0

This is casting 0 to an unsigned short pointer. This will be used for computing a memory offset, computed in terms of the size of an unsigned short.

3 * mesh.sBoneBatches.pnBatchOffset[batchNum]

This is, presumably, the offset in memory of some batch of triangles. A triangle is composed of 3 shorts, so it looks like they are storing an offset in terms of numbers of triangles, and then multiplying by 3 to get the number of shorts.

((unsigned short*)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]]

This is now using that 0 pointer to find the memory location of the given offset. This would normally return the value of that memory location, but they want a pointer to pass into glDrawElements, so the use the & operator to get a pointer to that memory location:

&((unsigned short*)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]]

Upvotes: 6

Chris Dodd
Chris Dodd

Reputation: 2960

Its an obfuscated way of computing

sizeof(unsigned short) * 3 * mesh.sBoneBatches.pnBatchOffset[batchNum]

but since it doesn't actually save any characters, its not a very good obfuscation

Upvotes: 0

brool
brool

Reputation: 2135

It's computing a byte offset -- 3 * mesh.sBoneBatches.pnBatchOffset[batchNum] is the index. Using 0 as the pointer means that the address will be just the offset value, nothing else.

Upvotes: 2

Related Questions