ms3dmodel.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:10 $
00011 *
00012 */
00013 
00014 
00015 #include "ms3dmodel.h"
00016 #include "dma.h"
00017 #include <memory.h>
00018 
00019 // Uncomment next line to check loading of model data
00020 //#define MSVERBOSE
00021 
00022 
00023 CMs3dModel::CMs3dModel(void)
00024 :m_pMeshes(NULL)
00025 {       
00026         // Initialise some default vaules
00027         m_pMeshes = NULL;
00028         m_iStaticAddr = 0;
00029         m_World = Matrix4x4::IDENTITY;
00030         m_WVP = Matrix4x4::IDENTITY;
00031         m_bWorldLoaded = false;
00032         
00033 }
00034 
00035 CMs3dModel::~CMs3dModel(void)
00036 {
00037         for(int nMesh = 0; nMesh < m_nMeshes; nMesh++)
00038         {
00039                 if(m_pMeshes[nMesh].pVertices != NULL)
00040                 {
00041                         #ifdef MSVERBOSE
00042                         printf("Delete m_pMeshes[%d].pVertices\n", nMesh);
00043                         #endif
00044                         delete [] m_pMeshes[nMesh].pVertices;
00045                         m_pMeshes[nMesh].pVertices = NULL;
00046                 }
00047                 
00048                 if(m_pMeshes[nMesh].pNormals != NULL)
00049                 {
00050                         #ifdef MSVERBOSE
00051                         printf("Delete m_pMeshes[%d].pNormals\n", nMesh);
00052                         #endif
00053                         delete [] m_pMeshes[nMesh].pNormals;
00054                         m_pMeshes[nMesh].pNormals = NULL;
00055                 }
00056                 
00057                 if(m_pMeshes[nMesh].pTriangles != NULL)
00058                 {
00059                         #ifdef MSVERBOSE
00060                         printf("Delete m_pMeshes[%d].pTriangles\n", nMesh);
00061                         #endif
00062                         delete [] m_pMeshes[nMesh].pTriangles;
00063                         m_pMeshes[nMesh].pTriangles = NULL;
00064                 }
00065         }
00066 
00067         if(m_pMeshes != NULL)
00068         {
00069                 #ifdef MSVERBOSE
00070                 printf("Delete m_pMeshes\n");
00071                 #endif
00072                 delete [] m_pMeshes;
00073                 m_pMeshes = NULL;
00074         }       
00075 }
00076 
00077 void CMs3dModel::SetWorldMatrix(const Matrix4x4 & matWorld)
00078 {
00079         m_World = matWorld;
00080         m_WVP = m_World * Pipeline.GetViewProjection();
00081         m_bWorldLoaded = true;
00082 }
00083         
00084 void CMs3dModel::SetWVPMatrix(const Matrix4x4 & matWVP)
00085 {
00086         m_WVP = matWVP;
00087 }
00088 
00089 // This function reads a whole line (maximum of 1024 characters) from the file
00090 void CMs3dModel::GetNextLOC(char *pStr1024)
00091 {
00092         bool foundcode = false;
00093 
00094         while(foundcode != true)
00095         {
00096                 fgets(pStr1024, 1024, m_fp);
00097 
00098                 if((pStr1024[0] != '/' &&
00099                    pStr1024[1] != '/') &&
00100                    pStr1024[0] != '\r')
00101                    foundcode = true;
00102         }
00103 }
00104 
00105 bool CMs3dModel::LoadModelData(const char *strFilename, bool bTransparent)
00106 {
00107         m_fp = fopen(strFilename, "ra");
00108 
00109         if(m_fp == NULL)
00110         {
00111                 printf("Failed to load model %s.\n", strFilename);
00112                 exit(-1);
00113         }
00114 
00115         // The array that will be used to read the file one line at a time
00116         char strLine[1024];
00117 
00118         // Frames
00119         GetNextLOC(strLine);
00120         sscanf(strLine, "Frames: %d", &m_nFrames);
00121         
00122 #ifdef MSVERBOSE
00123         printf("Model: %s\nFrames: %d\n", strFilename, m_nFrames);
00124 #endif
00125 
00126         // Current frame
00127         GetNextLOC(strLine);
00128         sscanf(strLine, "Frame: %d", &m_nCurrentFrame);
00129         
00130 #ifdef MSVERBOSE
00131         printf("Current Frame: %d\n", m_nCurrentFrame);
00132 #endif
00133 
00134         // No. meshes
00135         GetNextLOC(strLine);
00136         sscanf(strLine, "Meshes: %d", &m_nMeshes);
00137         
00138 #ifdef MSVERBOSE
00139         printf("Meshes: %d\n", m_nMeshes);
00140 #endif
00141 
00142         m_pMeshes = new MSMesh[m_nMeshes];
00143         memset(m_pMeshes, 0, m_nMeshes * sizeof(MSMesh));
00144 
00145         for(int nMesh = 0; nMesh < m_nMeshes; nMesh++)
00146         {
00147                 GetNextLOC(strLine);
00148                 // mesh: name, flags, material index
00149                 sscanf(strLine, "\"%[^\"]\" %d %d", m_pMeshes[nMesh].strName,
00150                                                 &m_pMeshes[nMesh].flags,
00151                                                 &m_pMeshes[nMesh].matindex);
00152 
00153 #ifdef MSVERBOSE
00154                 printf("%s %d %d\n",    m_pMeshes[nMesh].strName,
00155                                                                 m_pMeshes[nMesh].flags,
00156                                                                 m_pMeshes[nMesh].matindex);
00157 #endif
00158 
00159 
00160                 // No. vertices
00161                 GetNextLOC(strLine);
00162                 sscanf(strLine, "%d", &m_pMeshes[nMesh].nVerts);
00163 
00164 #ifdef MSVERBOSE
00165                 printf("Vertices: %d\n", m_pMeshes[nMesh].nVerts);
00166 #endif
00167 
00168                 m_pMeshes[nMesh].pVertices = new MSVertex[m_pMeshes[nMesh].nVerts];
00169 
00170                 // The vertices
00171                 for(int nVert = 0; nVert < m_pMeshes[nMesh].nVerts; nVert++)
00172                 {
00173                         GetNextLOC(strLine);
00174                         // flags, x, y, z, u, v, bone index
00175                         sscanf(strLine, "%d %f %f %f %f %f %d", 
00176                                 &m_pMeshes[nMesh].pVertices[nVert].flags,
00177                                 &m_pMeshes[nMesh].pVertices[nVert].x,
00178                                 &m_pMeshes[nMesh].pVertices[nVert].y,
00179                                 &m_pMeshes[nMesh].pVertices[nVert].z,
00180                                 &m_pMeshes[nMesh].pVertices[nVert].u,
00181                                 &m_pMeshes[nMesh].pVertices[nVert].v,
00182                                 &m_pMeshes[nMesh].pVertices[nVert].bone);
00183 
00184 #ifdef MSVERBOSE
00185                         printf("%d %f %f %f %f %f %d\n", 
00186                                 m_pMeshes[nMesh].pVertices[nVert].flags,
00187                                 m_pMeshes[nMesh].pVertices[nVert].x,
00188                                 m_pMeshes[nMesh].pVertices[nVert].y,
00189                                 m_pMeshes[nMesh].pVertices[nVert].z,
00190                                 m_pMeshes[nMesh].pVertices[nVert].u,
00191                                 m_pMeshes[nMesh].pVertices[nVert].v,
00192                                 m_pMeshes[nMesh].pVertices[nVert].bone);
00193 #endif
00194                                 
00195                                 
00196                 }
00197 
00198                 // No. normals
00199                 GetNextLOC(strLine);
00200                 sscanf(strLine, "%d", &m_pMeshes[nMesh].nNormals);
00201 
00202 #ifdef MSVERBOSE
00203                 printf("Normals: %d\n", m_pMeshes[nMesh].nNormals);
00204 #endif
00205 
00206 
00207                 m_pMeshes[nMesh].pNormals = new Vector3[m_pMeshes[nMesh].nNormals];
00208 
00209                 // The normals
00210                 for(int nNormal = 0; nNormal < m_pMeshes[nMesh].nNormals; nNormal++)
00211                 {
00212                         GetNextLOC(strLine);
00213 
00214                         // x, y, z
00215                         sscanf(strLine, "%f %f %f",
00216                                 &m_pMeshes[nMesh].pNormals[nNormal].x,
00217                                 &m_pMeshes[nMesh].pNormals[nNormal].y,
00218                                 &m_pMeshes[nMesh].pNormals[nNormal].z);
00219                                 
00220 #ifdef MSVERBOSE
00221                         printf("%f %f %f\n",
00222                                 m_pMeshes[nMesh].pNormals[nNormal].x,
00223                                 m_pMeshes[nMesh].pNormals[nNormal].y,
00224                                 m_pMeshes[nMesh].pNormals[nNormal].z);
00225 #endif                          
00226                                 
00227 
00228                 }
00229 
00230                 // No. triangles
00231                 GetNextLOC(strLine);
00232                 sscanf(strLine, "%d", &m_pMeshes[nMesh].nTriangles);
00233                 
00234 #ifdef MSVERBOSE
00235                 printf("Triangles: %d\n", m_pMeshes[nMesh].nTriangles);
00236 #endif
00237 
00238                 m_pMeshes[nMesh].pTriangles = new MSTriangle[m_pMeshes[nMesh].nTriangles];
00239 
00240                 // The triangles
00241                 for(int nTriangle = 0; nTriangle < m_pMeshes[nMesh].nTriangles; nTriangle++)
00242                 {
00243                         GetNextLOC(strLine);
00244 
00245                         // triangle: flags, vertex index1, vertex index2, vertex index3, 
00246                         // normal index1, normal index 2, normal index 3, smoothing group
00247                         sscanf(strLine, "%d %d %d %d %d %d %d %d",
00248                                 &m_pMeshes[nMesh].pTriangles[nTriangle].flags,
00249                                 &m_pMeshes[nMesh].pTriangles[nTriangle].vert1,
00250                                 &m_pMeshes[nMesh].pTriangles[nTriangle].vert2,
00251                                 &m_pMeshes[nMesh].pTriangles[nTriangle].vert3,
00252                                 &m_pMeshes[nMesh].pTriangles[nTriangle].norm1,
00253                                 &m_pMeshes[nMesh].pTriangles[nTriangle].norm2,
00254                                 &m_pMeshes[nMesh].pTriangles[nTriangle].norm3,
00255                                 &m_pMeshes[nMesh].pTriangles[nTriangle].smoothinggroup);
00256 
00257 #ifdef MSVERBOSE
00258                         printf("%d %d %d %d %d %d %d %d\n",
00259                                 m_pMeshes[nMesh].pTriangles[nTriangle].flags,
00260                                 m_pMeshes[nMesh].pTriangles[nTriangle].vert1,
00261                                 m_pMeshes[nMesh].pTriangles[nTriangle].vert2,
00262                                 m_pMeshes[nMesh].pTriangles[nTriangle].vert3,
00263                                 m_pMeshes[nMesh].pTriangles[nTriangle].norm1,
00264                                 m_pMeshes[nMesh].pTriangles[nTriangle].norm2,
00265                                 m_pMeshes[nMesh].pTriangles[nTriangle].norm3,
00266                                 m_pMeshes[nMesh].pTriangles[nTriangle].smoothinggroup);
00267 #endif                          
00268 
00269                 }
00270         }
00271 
00272         // Get the number of materials (we don't care, we'll just use the first one)
00273         GetNextLOC(strLine);
00274 
00275         // The material name (enclosed in double quotes)
00276         GetNextLOC(strLine);
00277         sscanf(strLine, "\"%[^\"]\"", m_strTexname);
00278 
00279 #ifdef MSVERBOSE
00280         printf("%s\n", m_strTexname);
00281 #endif
00282 
00283 
00284         fclose(m_fp);
00285 
00286         InitialiseDMA(bTransparent);
00287 
00288         return true;
00289 }
00290 
00291 void CMs3dModel::InitialiseDMA(bool bTransparent)
00292 {
00293         m_iStaticAddr = VIFStaticDMA.GetPointer();
00294 
00295         VIFStaticDMA.Add32(FLUSH);                      // Make sure VU1 isn't busy
00296         VIFStaticDMA.Add32(STCYCL(1,1));        // Unpack linearly, i.e. don't skip any spaces
00297         VIFStaticDMA.Add32(BASE(32));           // The double buffers start at VU1 address 16 (giving us 16 QW to store data that won't change)
00298         VIFStaticDMA.Add32(OFFSET(496));        // The size of each buffer.
00299 
00300         VIFStaticDMA.AddUnpack(V4_32, 0, 1);    // Unpack 8QW of data that won't change
00301         VIFStaticDMA.AddVector(Pipeline.GetScaleVector());      // 0: The scales
00302 
00303 
00304         int iNumTrisPerChunk = 27;
00305         bool bFirst = true;
00306         
00307         //printf("m_nMeshes = %d\n", m_nMeshes);
00308         
00309         for(int nMesh = 0; nMesh < m_nMeshes; nMesh++)
00310         //for(int nMesh = 0; nMesh < 1; nMesh++)
00311         {
00312         
00313                 MSMesh & pMesh = m_pMeshes[nMesh];
00314                 int iNumTris = pMesh.nTriangles;
00315                 int iAbsoluteTri = 0;
00316         
00317                 
00318         
00319                 while(iNumTris > 0)
00320                 {
00321                         int iTrisThisChunk;
00322         
00323                         if(iNumTris > iNumTrisPerChunk)
00324                         {
00325                                 iTrisThisChunk = iNumTrisPerChunk;
00326                                 iNumTris -= iTrisThisChunk;
00327                         }
00328                         else
00329                         {
00330                                 iTrisThisChunk = iNumTris;
00331                                 iNumTris -= iTrisThisChunk;
00332                         }
00333         
00334                         VIFStaticDMA.AddUnpack(V4_32, 0, iTrisThisChunk * 9 + 2, 1);
00335         
00336                         VIFStaticDMA.Add128(iTrisThisChunk * 9);
00337         
00338                         VIFStaticDMA.Add128(
00339                                 GS_GIFTAG_BATCH(iTrisThisChunk * 3, // NLOOP
00340                                                 1,      // EOP
00341                                                 1,      // PRE
00342                                                 // GS_PRIM(    PRIM, IIP, TME, FGE,  ABE         , AA1, FST, CTXT, FIX)
00343                                                 GS_PRIM(GS_TRIANGLE,  1,   1,   0 , bTransparent ,   0,   0,    0,   0),        // PRIM
00344                                                 GIF_FLG_PACKED,
00345                                                 GS_BATCH_3(GIF_REG_ST, GIF_REG_RGBAQ, GIF_REG_XYZ2)));
00346         
00347                         for(int iTriangle = 0; iTriangle < iTrisThisChunk; iTriangle++)
00348                         {
00349                                 MSTriangle & pTriangle = pMesh.pTriangles[iAbsoluteTri++];
00350         
00351                                 MSVertex & pVert1 = pMesh.pVertices[pTriangle.vert1];
00352                                 MSVertex & pVert2 = pMesh.pVertices[pTriangle.vert2];
00353                                 MSVertex & pVert3 = pMesh.pVertices[pTriangle.vert3];
00354         
00355                                 Vector3 & pNorm1 = pMesh.pNormals[pTriangle.norm1];
00356                                 Vector3 & pNorm2 = pMesh.pNormals[pTriangle.norm2];
00357                                 Vector3 & pNorm3 = pMesh.pNormals[pTriangle.norm3];
00358         
00359                                 VIFStaticDMA.AddVector(Vector4(pVert1.u, pVert1.v, 1, 0));
00360                                 VIFStaticDMA.AddVector(Vector4(pNorm1.x, pNorm1.y, pNorm1.z, 0));
00361                                 VIFStaticDMA.AddVector(Vector4(pVert1.x, pVert1.y, pVert1.z, 1));
00362                         
00363                                 VIFStaticDMA.AddVector(Vector4(pVert2.u, pVert2.v, 1, 0));
00364                                 VIFStaticDMA.AddVector(Vector4(pNorm2.x, pNorm2.y, pNorm2.z, 0));
00365                                 VIFStaticDMA.AddVector(Vector4(pVert2.x, pVert2.y, pVert2.z, 1));
00366         
00367                                 VIFStaticDMA.AddVector(Vector4(pVert3.u, pVert3.v, 1, 0));
00368                                 VIFStaticDMA.AddVector(Vector4(pNorm3.x, pNorm3.y, pNorm3.z, 0));
00369                                 VIFStaticDMA.AddVector(Vector4(pVert3.x, pVert3.y, pVert3.z, 1));
00370                         }
00371                         
00372                         if(bFirst)
00373                         {
00374                                 VIFStaticDMA.Add32(MSCALL(0));
00375                                 bFirst = false;
00376                         }
00377                         else
00378                                 VIFStaticDMA.Add32(MSCNT);
00379                 }
00380         }
00381 
00382         VIFStaticDMA.Add32(FLUSH);
00383 
00384         VIFStaticDMA.DMARet();
00385 }
00386 
00387 void CMs3dModel::Render(void)
00388 {       
00389         assert(m_bWorldLoaded && m_iStaticAddr);
00390         
00391         // Wait for all to be idle in VU1 land
00392         // Before uploading the data
00393         VIFDynamicDMA.Add32(FLUSH);
00394         
00395         // Upload the matrices in the dynamic buffer
00396         // because they can change every frame.
00397         VIFDynamicDMA.AddUnpack(V4_32, 1, 16);
00398         VIFDynamicDMA.AddMatrix(Pipeline.GetLightDirs());
00399         VIFDynamicDMA.AddMatrix(Pipeline.GetLightCols());
00400         VIFDynamicDMA.AddMatrix(m_WVP);
00401         VIFDynamicDMA.AddMatrix(m_World);
00402         
00403         // Call the packet with the static data that doesn't change per frame.
00404         VIFDynamicDMA.DMACall(m_iStaticAddr);
00405 }

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