terrain.cpp

00001 /*
00002 * "PS2" Application Framework
00003 *
00004 * University of Abertay Dundee
00005 * May be used for educational purposed only
00006 *
00007 * Author - Dr Henry S Fortuna
00008 *
00009 * $Revision: 1.2 $
00010 * $Date: 2007/08/19 12:45:12 $
00011 *
00012 */
00013 
00014 #include <sps2lib.h>
00015 #include <sps2tags.h>
00016 #include <sps2util.h>
00017 #include <sps2regstructs.h>
00018 #include "PS2Defines.h"
00019 #include "ps2matrix4x4.h"
00020 #include "sps2wrap.h"
00021 #include "dma.h"
00022 #include "terrain.h"
00023 
00024 
00025 CTerrain::CTerrain()
00026 {
00027         // Initialise some default vaules
00028         m_iStaticAddr = 0;
00029         m_World = Matrix4x4::IDENTITY;
00030         m_WVP = Matrix4x4::IDENTITY;
00031         m_bWorldLoaded = false;
00032         LoadTerrainData();
00033 }
00034 
00035 CTerrain::~CTerrain()
00036 {
00037         // Nothing to destruct
00038 }
00039 
00040 void CTerrain::SetWorldMatrix(const Matrix4x4 & matWorld)
00041 {
00042         m_World = matWorld;
00043         m_WVP = m_World * Pipeline.GetViewProjection();
00044         m_bWorldLoaded = true;
00045 }
00046         
00047 void CTerrain::SetWVPMatrix(const Matrix4x4 & matWVP)
00048 {
00049         m_WVP = matWVP;
00050 }
00051 
00052 
00053 
00054 void CTerrain::LoadTerrainData(void)
00055 {
00056         // Get the address that we can call to later.
00057         m_iStaticAddr = VIFStaticDMA.GetPointer();
00058 
00059         VIFStaticDMA.Add32(FLUSH);                      // Make sure VU1 isn't busy
00060         VIFStaticDMA.Add32(STCYCL(1,1));        // Unpack linearly, i.e. don't skip any spaces
00061         VIFStaticDMA.Add32(BASE(32));           // The double buffers start at VU1 address 16 (giving us 16 QW to store data that won't change)
00062         VIFStaticDMA.Add32(OFFSET(496));        // The size of each buffer.
00063 
00064         VIFStaticDMA.AddUnpack(V4_32, 0, 1);    // Unpack 8QW of data that won't change
00065         VIFStaticDMA.AddVector(Vector4(2048, 2048, (0xFFFFFF / 32.0f), 1));     // 0: The scales
00066 
00067         // Set the PRIM field here. This may look like it's for convenience, but actually it's the only
00068         // way we can do it. If we set this in the GIFTag it would reset the strip every buffer.
00069         // As we want one huge strip, we can't use the prim setting capabilites of the GIFTag.
00070         VIFStaticDMA.StartDirect();
00071         VIFStaticDMA.StartAD();
00072         VIFStaticDMA.AddAD(PRIM_SET(GS_TRISTRIP, 1, 1, 0, 0, 0, 0, 0, 0), PRIM);
00073         VIFStaticDMA.EndAD();
00074         VIFStaticDMA.EndDirect();
00075         
00076 
00077         // The verts are 3QW each, and the 504QW is split in half. Therefore we have 252QW for each buffer.
00078         // Each buffer also has 2QW of info (GIFTag + Numverts), so we can process 83 vertices (249QW)
00079         // in each buffer.
00080         int iNumVertsPerChunk = 82;
00081 
00082         // The number of triangles in each dimension.
00083         int iSizeX = 256;
00084         int iSizeY = 256;
00085 
00086         int iNumVerts = (iSizeX * 2) * (iSizeY - 1);
00087 
00088         int iX = 0, iY = 0;
00089         int bBottomRow = 0;
00090         bool bFirst = true;
00091 
00092         while(iNumVerts > 0)
00093         {
00094                 int iVertsThisChunk;
00095 
00096                 if(iNumVerts > iNumVertsPerChunk)
00097                 {
00098                         iVertsThisChunk = iNumVertsPerChunk;
00099                         iNumVerts -= iVertsThisChunk;
00100                 }
00101                 else
00102                 {
00103                         iVertsThisChunk = iNumVerts;
00104                         iNumVerts -= iVertsThisChunk;
00105                 }
00106 
00107                 VIFStaticDMA.AddUnpack(V4_32, 0, iVertsThisChunk * 3 + 2, 1);
00108                 VIFStaticDMA.Add128(iVertsThisChunk * 3);
00109                 VIFStaticDMA.Add128(
00110                         GS_GIFTAG_BATCH(iVertsThisChunk,
00111                                         1, 0, 0, GIF_FLG_PACKED,
00112                                         GS_BATCH_3(GIF_REG_ST, GIF_REG_RGBAQ, GIF_REG_XYZ2)));
00113 
00114                 // Zigzag from left to right across the patch making a huge triangle strip.
00115                 //
00116                 //      0               2               4               6
00117                 //  |     / |     / |     / |
00118                 //  |   /   |   /   |   /   |
00119                 //      1 /             3 /             5 /             7 etc.
00120                 //
00121                 for(int iVert = 0; iVert < iVertsThisChunk; iVert++)
00122                 {
00123                         float fX = (float)iX;
00124                         float fY = (float)(iY + bBottomRow);
00125 
00126                         // Disable the drawing kick when we move to the next row, so that we don't get a huge
00127                         // polygon going across the patch.
00128                         int iDontDraw = (iX == 0) ? 1 : 0;
00129 
00130                         // Alternate between the current row and the one below.
00131                         iX += bBottomRow;
00132                         bBottomRow ^= 1;
00133 
00134                         // If we have reached the end, start again on the next row.
00135                         if(iX == iSizeX)
00136                         {
00137                                 iX = 0;
00138                                 bBottomRow = 0;
00139                                 iY += 1;
00140                         }
00141 
00142                         // Add a huge number of vertices 
00143                         VIFStaticDMA.AddVector(Vector4(fX / iSizeX, fY / iSizeY, 1, *((float *)&iDontDraw)));   // Tex coords + in W, a flag to set ADC or not.
00144                         VIFStaticDMA.AddVector(Vector4(0, 1, 0, 0));                                                                                    // Normal
00145                         VIFStaticDMA.AddVector(Vector4((fX - (iSizeX / 2)), 0, (fY - (iSizeY / 2)), 1));                // Position
00146                 }
00147 
00148                 if(bFirst)
00149                 {
00150                         bFirst = false;
00151                         // If this is the first buffer then run the VU code from address 0 so that the initialisation
00152                         // VU code is ran.
00153                         VIFStaticDMA.Add32(MSCALL(0));
00154                 }
00155                 else
00156                 {
00157                         // For multiple times MSCNT means to continue where the VU code finished last time at the --cont.
00158                         VIFStaticDMA.Add32(MSCNT);
00159                 }
00160 
00161                 // Notice that due to the quad buffer setup we don't need to flush here because we can upload, process, and render
00162                 // all in parallel now. (the XGKick in the vector code will flush to make sure that we don't get ahead of ourselves)
00163         }
00164 
00165         VIFStaticDMA.Add32(FLUSH);
00166         VIFStaticDMA.DMARet();
00167         
00168         
00169         
00170         
00171 }
00172 
00173 
00174 void CTerrain::Render(void) const
00175 {
00176         assert(m_bWorldLoaded && m_iStaticAddr);
00177         
00178         // Wait for all to be idle in VU1 land
00179         // Before uploading the data
00180         VIFDynamicDMA.Add32(FLUSH);
00181         
00182         // Upload the matrices in the dynamic buffer
00183         // because they can change every frame.
00184         VIFDynamicDMA.AddUnpack(V4_32, 1, 16);
00185         VIFDynamicDMA.AddMatrix(Pipeline.GetLightDirs());
00186         VIFDynamicDMA.AddMatrix(Pipeline.GetLightCols());
00187         VIFDynamicDMA.AddMatrix(m_WVP);
00188         VIFDynamicDMA.AddMatrix(m_World);
00189         
00190         // Call the packet with the static data that doesn't change per frame.
00191         VIFDynamicDMA.DMACall(m_iStaticAddr);
00192 }

Generated on Sun May 18 21:45:09 2008 for PS2X by  doxygen 1.5.4