Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
103 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

The Triangle Settings

Next in the source code is the setTriangle function.  This function sets up the GIFtag and primitive data.

void setTriangle()
{
   PS2_GIFTAG_CLEAR_TAG(&tri.giftag);
   tri.giftag.NLOOP = sizeof(tri)/16 - 1;
   tri.giftag.EOP = 1;
   tri.giftag.PRE = 0;
   tri.giftag.FLG = 0;
   tri.giftag.NREG = 1;
   tri.giftag.REGS0 = PS2_GIFTAG_REGS_AD;

   tri.prim = PS2_GS_SETREG_PRIM(
      PS2_GS_PRIM_PRIM_TRIANGLE,
      PS2_GS_PRIM_IIP_FLAT,
      PS2_GS_PRIM_TME_OFF,
      PS2_GS_PRIM_FGE_OFF,
      PS2_GS_PRIM_ABE_OFF,
      PS2_GS_PRIM_AA1_OFF,
      PS2_GS_PRIM_FST_STQ,
      PS2_GS_PRIM_CTXT_CONTEXT1,
      PS2_GS_PRIM_FIX_NOFIXDDA);

   tri.prim_adrs = PS2_GS_PRIM;
// vertex 0 settings
   tri.rgb0 = PS2_GS_SETREG_RGBAQ(255, 0, 0, 0, 0);
   tri.rgb0_adrs = PS2_GS_RGBAQ;
   
   tri.v0 = PS2_GS_SETREG_XYZ((g_gp->center_x)<<4, 
                              (g_gp->center_y - 200)<<4, 1);
   tri.v0_adrs = PS2_GS_XYZ2;
   
//vertex 1 settings
   tri.rgb1 = PS2_GS_SETREG_RGBAQ(255, 0, 0, 0, 0);
   tri.rgb1_adrs = PS2_GS_RGBAQ;

   tri.v1 = PS2_GS_SETREG_XYZ((g_gp->center_x + 300)<<4,
                              (g_gp->center_y + 200)<<4, 1);
   tri.v1_adrs = PS2_GS_XYZ2;

//vertex 2 settings
   
   tri.rgb2 = PS2_GS_SETREG_RGBAQ(255, 0, 0, 0, 0);
   tri.rgb2_adrs = PS2_GS_RGBAQ;
   
   tri.v2 = PS2_GS_SETREG_XYZ((g_gp->center_x - 300)<<4,
                              (g_gp->center_y + 200)<<4, 1);
   tri.v2_adrs = PS2_GS_XYZ2;
}

The first function simply clears out the GIFtag so we can make our settings.  Next the fields in the GIFtag are set.  The GIFtag is one qword(128 bits) long and contains the following seven fields:

NLOOP occupies bits 0 through 14 and holds the data size of the primitive.

EOP occupies bit 15 and specifies whether the following data is the last primitive in a GS packet (End Of Packet).  A value of 0 means that more GIFtags with more primitives will be sent after the current primitive.  A value of 1 indicates that the following primitive data is the last in the packet.

PRE occupies bit 46 (note the empty space between EOP and PRE) and specifies whether the PRIM field in the GIFtag is enabled.  A value of 0 ignores the prim field, while a value of 1 outputs the PRIM field to the PRIM register.

PRIM occupies bits 47 through 57 and contains data to be set in the PRIM register.

FLG occupies bits 58 through 59 and contains the data format for the primitive. 00 is PACKED, 01 is REGLIST, 10 is IMAGE, and 11 is Disabled.

NREG occupies bits 60 through 63 and holds the number of register descriptors in the next field, REGS.

REGS occupies bits 64 through 127 and holds up to 16 Register descriptors.

First the NLOOP field is set to the size of our data structure tri.  What we are trying to find is the number of units of data. Because the tri structure follows the A+D format, we know that each unit of data consists of 128 bits (64 for the data, 8 for the address, with the remainder of the 128 bits empty), we need to find the size of the structure and then divide 128 bits.  That will give us the number of data units in A+D format in the tri structure.  We first use sizeof(tri) to find the size of our structure, which returns the size in bytes.  We then must divide by 16 (16 bytes = 128 bits).  PRIM register settings are not included in with the size of the data so 1 is subtracted from the final answer (this removes one qword from the size, eliminating prim and prim_adrs.

Since there is no primitive data or GIFtags following our triangle, EOP is set to zero to signal that the following data is the end of the GS packet.

Since all of our primitive data is stored inside the Triangle structure, the PRIM field of the GIFtag will not be used.  Therefore, PRE is set to 0;

The data format mode PACKED uses the register descriptors in the REGS field to show the format of the data in every following qword.  Since the data in each qword of our triangle is in A+D format, we must use PACKED mode so that we can set the A+D format in the REGS field.  Packed mode is set by making FLG equal zero.

Only one register descriptor is in the REGS field so NREG is set to 0.  The REGS0 field is set to PS2_GIFTAG_REGS_AD.  This tells the GS that the data in each following qword is in A+D format.  REGS0 is the first of 16 registers that may be set in the REGS field.

Primitive settings are initialized using the PS2_GS_SETREG_PRIM function.  First the type of primitive is set followed by its drawing options.

The first field can be PS2_GS_PRIM_PRIM_POINT, PS2_GS_PRIM_PRIM_LINE, PS2_GS_PRIM_PRIM_LINESTRIP, PS2_GS_PRIM_PRIM_SPRITE, PS2_GS_PRIM_PRIM_TRIANGLE, PS2_GS_PRIM_PRIM_TRISTRIP, PS2_GS_PRIM_PRIM_TRIFAN. These should be self explanatory, with the possible exception of the sprite primitive.  The sprite primitive takes only 2 vertices and draws a rectangle with a corner at each vertex.  With the sprite and point primitives shading can be flat only and antialiasing is always off.

The next mode is for shading and can be PS2_GS_PRIM_IIP_FLAT or PS2_GS_PRIM_IIP_GOURAUD.

The following four settings are only set to on or off. PS2_GS_PRIM_TME_ON/OFF is for enabling texture mapping, PS2_GS_PRIM_FGE_ON/OFF is for enabling fog, PS2_GS_PRIM_ABE_ON/OFF is for enabling alpha blending, and PS2_GS_PRIM_AA1_ON/OFF is for enabling antialiasing.

The next field specifies what type of texture coordinates will be used and can be PS2_GS_PRIM_FST_STQ or PS2_GS_PRIM_FST_UV. At this point this field is irrelevant as we aren't doing any texture mapping.

Each register in the GS has to contexts.  At this point we are only worried about setting the registers and we are using context 1 with PS2_GS_PRIM_CTXT_CONTEXT1.

Now that the primitive data has been set in the prim variable, we must follow the A+D format and set prim_adrs to the correct register address.  The data in the prim variable is going to the PRIM register so prim_adrs is set equal to PS2_GS_PRIM.

We now get to setup the vertices of the triangle using the A+D format.  First rgb0 is set using the PS2_GS_SETREG_RGBAQ function. This function takes three values for the vertex color, one for alpha blending, and one for normalized texture coordinates.  The vertex is set to a solid red by making the first field in the function 255, and the other two zero.  The last two fields are left at zero since no alpha blending or texture mapping is used.  The register address is then set to PS2_GS_RGBAQ.

With the color set up it is time to set the vertex coordinates. This is done using the PS2_GS_SETREG_XYZ function. To find the center of the screen g_gp->center_x and g_gp->center_y are used.  This structure contains the parameters of the GS, including the center of the screen.  The triangle is then built around these values by adding and subtracting from them.  After finding each XY coordinate for the triangle, the answer must then be shifted four bits to the left.  The XYZF2 register stores coordinate data as 12 bits for integer values and 4 bits for decimal values.  Since our triangle uses integer values only, the final value for each XY coordinate must be shifted out of the decimal place and into the integer place.

Finally the address for the vertex coordinates is set using PS2_GS_SETREG_XYZ2. The XYZ2 register holds each vertex value of a primitive.  Once all the primitives coordinates are specified, the primitive is drawn to the screen.  The number of coordinates that must be specified varies depending on what type of primitive is being drawn (a triangle requires 3, a sprite requires 2).  The other vertex coordinate register, XYZ3, won't draw a primitive even after all of its coordinates are specified.  Since we are only drawing one shape and we want it to be drawn right away, XYZ2 is used.

Since all three coordinates are all set as described, we will now move onto the final function of the program.





Drawing the Scene

Contents
  Introduction
  Triangle Settings
  Drawing the Scene

  Printable version
  Discuss this article

The Series
  Part 1: Initialization
  Part 2: Drawing Primitives