SUper Easy to Use 3D Engine (Su3De) – Binary File Format Part 2 – Outline

In part 1, I outlined some of the design goals for the Su3De model binary format.  Here, I am going to jump right in and start describing the format based on the work of the past week. The primary idea of the binary format is to be able to pass the object directly on to the Su3De engine so it can be used without any significant conversions or modifications.  This means that the IDEA is for Su3De to pass the model data onto the 3D driver level as intact as possible.  The benefits of this are obvious, speed – with a minor in simplicity. So, what do we need in the file format?  Here is the list I have started with:

  • Vertices
  • Normals
  • Color / Material Data
  • Texture Coords
  • Texture Image
  • Shaders?

Let’s go over these one by one (although vertices will be the focus of THIS post).

Vertices

Vertices are the only truly required objects in the binary format.  The vertices represent the polygonal mesh that makes up the structure of the model.  If all you have is vertices you can draw the 3D object, however, it won’t be very exciting.  It will be end up being flat shaded and will be drawn using a single color.

Ford Flex 3D model flat shaded

The point of all this is that it will be mandatory to have a list of vertices representing the polygonal mesh of the model. The chosen polygon format will be triangles. For now, there won’t be any attempt to “optimize” the mesh – like creating sequences of “triangle strips” or “triangle fans” to reduce the vertex count.  The binary format will be a STRAIGHT UP, three vertices for every triangle kind of thing to start with – meaning there will likely be future versions that will have some optimizations added.

The Ford Flex model shown above, is made up of  1560 triangles (also referred to as “faces”).  This means that there will be x, y, z coordinate entries for each vertex of each triangle. Each x, y, z coordinate entry will be a single precision floating point number requiring 4 bytes.  So each vertex requires 12 bytes and each triangle requires 36 bytes.  So the mesh size will be:

  • 1560 triangles X (12 bytes per vertex X 3 vertices) = 56,160 bytes

The representation of this model in ‘C’ code would look something like this:

[sourcecode language="javascript"]
static int g_numFlexVerts = 4680;

static SU3_VTX3F FlexVerts[12] = {
{-7.093400f, 6.617300f, -4.289700f}, //triangle 1 x
{-6.553800f, 7.036900f, -4.751400f}, //triangle 1 y
{-7.695800f, 2.596000f, -10.338000f}, //triangle 1 z
{-7.695800f, 2.596000f, -10.338000f}, //triangle 2 x
{-8.105300f, 2.607700f, -9.238200f}, //triangle 2 y
{-7.093400f, 6.617300f, -4.289700f}, //triangle 2 z
{0.000000f, -3.951100f, 23.106400f}, //triangle 3 x
{-3.790500f, -3.950100f, 22.999701f}, //triangle 3 y
{-3.790500f, -4.636200f, 22.999201f}, //triangle 3 z
{-3.790500f, -4.636200f, 22.999201f}, //triangle 4 x
{0.000000f, -4.634400f, 23.106400f}, //triangle 4 y
{0.000000f, -3.951100f, 23.106400f}, //triangle 4 z
//…and so on for the remaining triangles.
};
[/sourcecode]

Now, this is a binary format and one of the decisions we need to make is whether or not the .OBJ file converter will spit out a .H file for the model as an option. I don’t really see the disadvantage in having that as a feature of the Su3De object converter, so we are going to proceed with that as “very likely”. Being a binary format, however, we have to represent this data AS binary information. In this case, the data will look like this in memory:

[sourcecode language="javascript"]
0×22,0xfd,0xe2,0xc0,0xec,0xc0,0xd3,0×40,0×39,0×45,0×89,0xc0,0xbb,0xb8,0xd1,
0xc0,0×49,0x2e,0xe1,0×40,0×78,0x0b,0×98,0xc0,0xfe,0×43,0xf6,0xc0,0xdd,0×24,
0×26,0×40,0×73,0×68,0×25,0xc1,0xfe,0×43,0xf6,0xc0,0xdd,0×24,0×26,0×40,0×73,
0×68,0×25,0xc1,0x4f,0xaf,0×01,0xc1,0x8f,0xe4,0×26,0×40,0xab,0xcf,0×13,0xc1,
0×22,0xfd,0xe2,0xc0,0xec,0xc0,0xd3,0×40,0×39,0×45,0×89,0xc0,0×00,0×00,0×00,
0×00,0xd3,0xde,0x7c,0xc0,0xe8,0xd9,0xb8,0×41,0x8d,0×97,0×72,0xc0,0×70,0xce,
0x7c,0xc0,0×63,0xff,0xb7,0×41,0x8d,0×97,0×72,0xc0,0xc0,0x5b,0×94,0xc0,0x5d,
0xfe,0xb7,0×41,0x8d,0×97,0×72,0xc0,0xc0,0x5b,0×94,0xc0,0x5d,0xfe,0xb7,0×41,
0×00,0×00,0×00,0×00,0×01,0x4d,0×94,0xc0,0xe8,0xd9,0xb8,0×41,0×00,0×00,0×00,
0×00,0xd3,0xde,0x7c,0xc0,0xe8,0xd9,0xb8,0×41
[/sourcecode]

It is now time to digress and talk about endianness…

Endianness

After some thought, I have decided to simply go with a little endian format for the binary data. For those of you who might not know, endian ordering – which came from Gulliver’s Travels and the people of Lilliput.  Some people would crack their boiled eggs on the big end, while a previous Emperor decreed that you must crack your boiled eggs on the little end.  Therefore, there exists “little endians” and “big endians” in the world of Lilliput.
Endianessmap
Some clever person, decided that they would apply this terminology to the ordering of multi-byte sequences in computer systems.  Say, you have a 32 bit number (which is comprised of four 8 bit bytes…obviously).  How do you order the bytes?  If the number is 0×12345678 (305419896 in decimal) how does it “show up” in memory?  Does it show up as 0×12, 0×34, 0×56, 0×78 (big endian) -or- does it show up as 0×78, 0×56, 0×34, 0×12? It makes a HUGE difference.  There is a whole SLEW of processor systems out there that use big-endian and a whole SLEW of processor systems that use little-endian.  So, we had to make a choice and the choice is little endian for Su3De. For more information from Wikipedia on endianness, click here.

Here is a list of little endian systems – which is quite impressive – (list based on the previously mentioned Wikipedia article on endianness):

  • DragonFlyBSD on x86, and x86-64
  • FreeBSD on x86, x86-64, and Itanium
  • Linux on x86, x86-64, MIPSEL, Alpha, Itanium, S+core, MN103, CRIS, Blackfin, MicroblazeEL, ARM, M32REL, TILE, SH, XtensaEL and UniCore32
  • Mac OS X on x86, x86-64
  • iOS on ARM
  • NetBSD on x86, x86-64, Itanium, etc.
  • OpenBSD on x86, x86-64, Alpha, VAX, Loongson (MIPSEL)
  • OpenVMS on VAX, Alpha and Itanium
  • Solaris on x86, x86-64, PowerPC
  • Tru64 UNIX on Alpha
  • ESX on x86, x86-64
  • Windows on x86, x86-64, Alpha, PowerPC, MIPS and Itanium (and now ARM)

OK…so back to our regularly scheduled programming…

Vertices..again

We have determined that we will need three floats per vertex and three vertices per triangle, so that means that we should be able to just “open” a .SU3 file and start reading out vertices…right?  Well…of course it isn’t THAT simple.  We need a bit more information.  Like how many triangles are in the model.  So organizationally, we are going to need to know that. From a code standpoint then the first thing we read out of the file will be the triangle count (not actually a true statement…but let’s pretend for the moment). This brings us to this:

[sourcecode language="C"]
#pragma pack(1)

typedef struct{
float x;
float y;
float z;
}SU3_VTX3F;

typedef struct{
unsigned int triangleCount;
SU3_VTX3F vertices[1];
}SU3_VERTICES;

#pragma pack()
[/sourcecode]

Wait!!! Is this CODE I am starting to see. Methinks it is!!!

The #pragma pack(1) insures that the compiler will view the structure as being “byte aligned” and won’t add any clever “padding” that might interfere with our interpretation of the data as we read it. If the compiler pads the data, we won’t have any way of knowing this happened and we can easily get misaligned and the model will be read incorrectly.

Ford Flex with vertices showing…

OK…so NOW we have the beginnings, albeit ever so humble, of the Su3De binary file format. At this point, we can create a binary model that has everything we need to draw a 3D model like the Ford Flex example. In the next post, we will discuss the plan to incorporate some other things…starting with texture coordinates and textures.  This will be interesting for sure, so stay tuned.  See you in Su3De again soon.

2 thoughts on “SUper Easy to Use 3D Engine (Su3De) – Binary File Format Part 2 – Outline

  1. Ryan Spoelhof

    Have you considered indexed vertices? It’s obviously a deviation from the “straight up” approach, but may reduce the total data required in the vertex buffer at render-time.

    Reply
    1. ricktewell Post author

      Indexed vertices are great -kind of like how the .OBJ format stores its data. The issue is that some of the environments that Su3De is targeting can’t take indexed vertices…so they would have to be converted into a straight vertex list anyway. Part of the goal would be to store a SU3 file in flash memory and hand it off to the 3D API without any changes…so you don’t have to allocate DRAM and then build the model. Now…with VBOs, the vertices could be handed off to 3D engine’s graphic controller and we could then just free the DRAM…so this could work out. The question is, how should the format hold the vertices? Perhaps an OPTION to store as indexed vertices, however, if you add an option then Su3De has to support it. It wouldn’t be polite for Su3De to return an error if you handed off a defined format… The trick is balancing speed against the size of the 3D model.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>