It is very common in graphics programming to work with vertex formats. This is described, for example, here.
However, I am looking for a way to accomplish that which does not invoke undefined behavior (I'm mainly looking for C++ info, but C would be fine, too).
The common way to do it is like this: First, declare your vertex format as a struct.
struct Vertex {
float x;
float y;
uint16_t someData;
float etc;
};
Then, you create an array of these, fill them in, and send them to your graphics API (eg: OpenGL).
Vertex myVerts[100];
myVerts[0].x = 42.0;
// etc.
// when done, send the data along:
graphicsApi_CreateVertexBuffer(&myVerts[0], ...);
(Aside: I skipped the part where you tell the API what the format is; we'll just assume it knows).
However, the graphics API has no knowledge about your struct. It just wants a sequence of values in memory, something like:
|<--- first vertex -->||<--- second vertex -->| ...
[float][float][u16][float][float][float][u16][float] ...
And thanks to issues of packing and alignment, there is no guarantee that myVerts
will be laid out that way in memory.
Of course, tons of code is written this way, and it works, despite not being portable.
But is there any portable way to do this that is not either
1. Inefficient
2. Awkward to write
?
This is basically a serialization problem. See also: Correct, portable way to interpret buffer as a struct
The main standards-compliant way I know of is to allocate your memory as char[]
.
Then, you just fill in all the bytes exactly how you want them laid out.
But to transform from the struct Vertex
representation above to that char[]
representation would require an extra copy (and a slow byte-by-byte one, at that). So that's inefficient.
Alternatively, you could write data into the char[]
representation directly, but that's extremely awkward. It's much nicer to say verts[5].x = 3.0f
than addressing into a byte array, writing a float as 4 bytes, etc.
Is there a good, portable way to do this?