Search Tips Advanced Search |
| Delphi Graphics and Game Programming Exposed with DirectX 7.0 by John Ayres Wordware Publishing, Inc. ISBN: 1556226373 Pub Date: 12/01/99
Search this book:
Previous | Table of Contents | Next
#### Lookup Tables Most game applications require the use of complicated or sophisticated mathematical functions. Functions such as Sin and Cos are common, and some games may require even more arcane trigonometry or calculus equations. Unfortunately, even with math coprocessors, these functions are quite slow, and if they are required in a loop, the application can slow to a crawl. However, if the total range of all inputs to a mathematical function or equation is known, you may be able to use a lookup table. Simply put, a lookup table is an array that contains the results of a mathematical function or equation for all known input values, where the input value acts as an index into the table. For example, the Sin and Cos functions both take an argument in the form of a degree (actually they take radians, but the argument can be converted to radians and it’s easier to think of it as a degree). The total range of inputs that return unique outputs is 0 to 359 degrees. Thus, you can create a 360-entry array and put the Sin or Cos value for each input in the range in its appropriate entry. Then, instead of calling the Sin or Cos function, you simply use the argument as an index into this array. Retrieving predetermined values in this manner is incredibly fast, usually much more so than actually running the equation or function. The table is generally initialized when the application starts. This technique can be applied to any area where a limited range of input values is known. The following listing illustrates this technique. Listing 10-5: Using lookup tables
    procedure TForm1.Button1Click(Sender: TObject);

    var

      StartTime, EndTime, iCount: Integer;

      Lookup: array[0..359] of Real;

      SinValue: Real;

    begin

      {turn optimization off}

      {$O-}

      {generate the lookup table}

      for iCount := 0 to 359 do

        Lookup[iCount] := Sin((iCount)*(PI / 180));

      {begin tracking the time}

      StartTime := timeGetTime;

      {perform a slow mathematical calculation}

      for iCount := 0 to 99999 do

        SinValue := Sin(50*(PI / 180));

      {record the ending time...}

      EndTime := timeGetTime-StartTime;

      {...and display the elapsed time}

      Label1.Caption := ‘Sine Calculation: ’+IntToStr(EndTime);

      {start tracking the time}

      StartTime := timeGetTime;

      {perform the calculation by finding the answer in the lookup table}

      for iCount := 0 to 99999 do

        SinValue := Lookup[50];

      {record the ending time...}

      EndTime := timeGetTime-StartTime;

      {...and display the elapsed time}

      Label2.Caption := ‘Sine Lookup: ’+IntToStr(EndTime);

    end;
#### Binary Bit Shifting Every PC processor has built-in hardware to shift the bits in a register left or right. This has the result of effectively multiplying or dividing the number in this register by a power of 2. Applications can take advantage of this hardware through the use of the shl and shr functions. Shl shifts bits to the left, multiplying the number by two; shr shifts them to the right, dividing by two. This can be used for incredibly fast integer multiplication and division, as it bypasses the math coprocessor. The only drawback to this is that the multiplication or division has to be a multiple of two. However, if an equation can be broken down into components that use simple addition or subtraction with multiplication or division by a power of 2, performance can be dramatically improved. For example, the equation Y * 320 + X would require one multiplication and one addition by the math coprocessor. However, the equivalent function ((Y shl 8) + (Y shl 6)) + X requires two shifts and two additions. Although the number of functions performed on this equation has increased, additions take less time than multiplication, and the shifts are almost instantaneous, resulting in faster performance. The following example demonstrates how to use bit shifting for multiplication. Listing 10-6: Bit Shifting
    procedure TForm1.Button1Click(Sender: TObject);

    var

      iCount: Integer;

      Result: Longword;

      StartTime,

      EndTime: LongInt;

    begin

      {we must run this example with optimization turned on to see the

       performance gains}

      {$O+}

      {set up a dummy variable and begin tracking the time}

      Result := 1;

      StartTime := timeGetTime;

      {perform some function or task}

      for iCount := 0 to 10000000 do

        Result :=  Result * 2;

      {record the ending time...}

      EndTime := timeGetTime;

      {..and display the elapsed time}

      Label1.Caption := ‘Elapse Time (multiply): ’+IntToStr(EndTime - StartTime);

      {set up a dummy variable and begin tracking the time}

      Result := 1;

      StartTime := timeGetTime;

      {perform some function or task using a faster method}

      for iCount := 0 to 10000000 do

        Result := Result shl 1;

      {record the ending time...}

      EndTime := timeGetTime;

      {...and display the elapsed time}

      Label2.Caption := ‘Elapse Time (shl): ’+IntToStr(EndTime - StartTime);

    end;
Previous | Table of Contents | Next

Products | Contact Us | About Us | Privacy | Ad Info | Home Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.