Graphics 101

All of you who start a processing tool to convert art resources or game resources into a game database and then leave to have lunch , get a soda, have a snack , go to the bathroom, pick up your kids from school, or go home, all yell, "ME!"

WOW! That was loud! It could be heard reverberating across the planet.

Those of you who have worked on games in the past, did you meet your timelines ? Did you find yourself working lots of extra ( crunch ) time to meet a milestone? (We will ignore E 3 and the final milestones!) How often do you have to wait for a tool to complete a data conversion? Add up all that "waiting" time. What did your tally come to?

You don't really know? Here is a thought: Add a wee bit of code to your program and write the results to an accumulative log file. Then check it from time to time to see where some of that time is going.

Some people believe in optimizing the game only if there is time somewhere in the schedule. Management quite often counts the time beans and decides that getting the milestone met is much more important than early ongoing debugging or optimization. But just think of that time savings if your tools are written with optimization. Just do not tell management about it or they will think they can ship the product early.

3D rendering tools are expensive and so programmers typically do not have ready access to a live tool. They sometimes write plug-ins, but quite often they will merely write an ASCII scene exporter (ASE) file parser to import the 3D data into their tools that generate the game databases. With this method, programmers do not have to have a licensed copy of a very expensive tool sitting on their desks.

Hint 

Prevent artist versus programmer wars by working out who gets the burden of the day-to-day conversion of art resources for the game application before the project coding begins. Use and document it in the game design, technical design, and especially the art bible documents, and treat these as living entities and not written in stone!

This little item brings up a trivial item of artist versus programmer wars. It all comes down to who will have the task of running the tools to export and convert data into a form loaded and used by a game application. Neither typically wants the task and both consider it mundane, but it is nevertheless required. Artists need to run the tools occasionally so as to check results of their changes to art resources. Programmers occasionally need to run the tools to test changes to database designs, etc. But nobody wants to do it all the time. So my suggestion is to automate the tools and incorporate the who and what into the game design, technical design, and art bibles for the project. In that way there will be no misperception.

Let's talk about something else but related to assembly. In this particular case, an ASE file is an ASCII export from 3D Studio MAX. How many of you have actually written a parser and have wondered where all your processing time had gone? Did you use streaming file reads to load a line at a time, or a block read to read the entire file into memory?

I personally write ASE parsers by loading the entire file into memory even when they are 20MB or larger in size . The core ASE parser code included with this book can actually parse an entire 20MB file and convert about 1.15 million floating-point values from ASCII to doubles in a few seconds. But here is where it really gets interesting!

ASCII String to Double-Precision Float

Calling the standard C language function atof() to convert an ASCII floating-point value to single or double-precision will add significant time onto your processing time for those large ASE files.

Hint 

Do not use the runtime C library atof()! Use the following functionality instead. By using this single function, this book will pay for itself quickly in time savings and that is what it is all about!

But I have good news for you. The following function will carve those hours back to something a lot more reasonable. What it does is take advantage of a little-known functionality within the floating-point unit of the 80x86 processor.

As discussed in Chapter 8, the FPU loads and handles the following data types:

  • (4-byte) single-precision floating-point

  • (8-byte) double-precision floating-point

  • (10-byte) double extended-precision floating-point

  • (10-byte) binary-coded decimal (BCD)

ASCII to Double

Note that the following code sample expects a normal floating-point number and no exponential. The ASE files do not contain exponential, just really long ASCII floating-point numbers ; thus, the reason this code traps for more than 18 digits.

Listing 15-2: \chap15\ase2vmp\util.cpp
image from book
 double exptbl[] =   // -e {   1.0,                  0.1,   0.01,                 0.001,   0.0001,               0.00001,   0.000001,             0.0000001,   0.00000001,           0.000000001,   0.0000000001,         0.00000000001,   0.000000000001,       0.0000000000001,   0.00000000000001,     0.000000000000001,   0.0000000000000001,   0.00000000000000001,   0.000000000000000001 };                            // Limit 18 places     double ASCIItoDouble(const char *pStr) { #ifdef CC_VMP_WIN32   unsigned int dig[80], *pd;   unsigned char bcd[10+2], *pb;   double f;   int n, e;   const char *p;       ASSERT_PTR(pStr);       *(((uint32*)bcd)+0) = 0;        // Clear (12 bytes)   *(((uint32*)bcd)+1) = 0;   *(((uint32*)bcd)+2) = 0;        // 2 + 2  spare bytes         // Collect negative/positive  and delimiters are pre-stripped.       p = pStr;   if ('-' == *p)   {     *(bcd+9) = 0x80;       // Set the negative bit into the BCD     p++;   }           // Collect digits and remember position of decimal point       *dig = 0;                // Prepend a leading zero   e = n = 0;   pd = dig+1;       while (('0' <= *p) && (*p <= '9'))   {     *pd++ = (*p++ - '0');       // Collect a digit     n++;         // The decimal place is checked after the first digit as no     // floating-point value should start with a decimal point.     // Even values between 0 and 1 should have a leading zero!   0.1     if ('.' == *p)      // Decimal place?     {      // Remember its position       e = n;       p++;   } }     // Check for a really BIG (and thus ridiculous) number     if (n > 18)      // More than 18 digits? {   return atof(pStr); }     if (e)            // 0=1.0   1=0.1   2=0.01   3=0.001, etc. {   e = n - e;      // Get  correct exponent }        // repack into BCD (preset lead zeros)    // last to first digit     n = (n+1)>>1;     // Start in middle of BCD buffer pb = bcd;         // Calc. 1st BCD character position     while(n--)        // loop for digit pairs {   pd-=2;          // Roll back to last 2 digits   *pb++ = ((*(pd+0)<<4)  *(pd+1));   // blend two digits }  __asm {   fbld   tbyte ptr bcd     ; Load (10-byte) BCD   fstp   f      ; Write 64-bit double-precision  }         return f * exptbl[e];                    // FASTER //  return f * pow(10.0, (double) -e);     // FAST #else   return atof(p);                            // Really SLOW #endif } 
image from book
 

If you do not believe me about the speed, then replace all the atof() functions in your current tool with a macro to assign 0.0 and measure the difference in speed. Or better yet, embed the atof() function within this function and then do a float comparison with the precision slop factor since by now you should be very aware that you never ever compare two floating-point numbers to each other to test for equivalence unless a precision slop factor (accuracy) is utilized.

Tip 

One should always test optimized code (vector based or not) in conjunction with slow scalar code written in C to ensure that the code is functioning as required.

One more thing: If you insist on using atof() or sscanf (), copy the ASCII number to a scratch buffer before processing it with either of these two functions because processing them within a 20MB file dramatically increases the processing time by hours. Apparently these conversion functions scan the string until they reach the terminator, which in the case of an ASE file can be a few megabytes away instead of a few bytes.



32.64-Bit 80X86 Assembly Language Architecture
32/64-Bit 80x86 Assembly Language Architecture
ISBN: 1598220020
EAN: 2147483647
Year: 2003
Pages: 191

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net