Clone of Akilla's ac2d @ https://github.com/deregtd/AC2D

cModel.cpp 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. #include "stdafx.h"
  2. #include "cModel.h"
  3. #include "BSPTypes.h"
  4. cModel::cModel()
  5. {
  6. m_pTranslation = cPoint3D(0,0,0);
  7. for (int i=0;i<4;i++)
  8. m_fRotation[i] = 0;
  9. }
  10. cModel::~cModel()
  11. {
  12. for (std::vector<stTriSet *>::iterator i = m_vTriSets.begin(); i != m_vTriSets.end(); i++)
  13. {
  14. glDeleteTextures(1, (GLuint *) &((*i)->dwGLTex));
  15. delete *i;
  16. }
  17. }
  18. int cModel::Draw()
  19. {
  20. int tricount = 0;
  21. glPushMatrix();
  22. glTranslatef(m_pTranslation.x, m_pTranslation.y, m_pTranslation.z);
  23. float s = m_fRotation[1]*m_fRotation[1] + m_fRotation[2]*m_fRotation[2] + m_fRotation[3]*m_fRotation[3];
  24. if (s > 0)
  25. glRotatef(2*acos(m_fRotation[0])*180.0f/(float)M_PI, m_fRotation[1]/s, m_fRotation[2]/s, m_fRotation[3]/s);
  26. glPushName(m_dwID);
  27. int i = 0;
  28. for (std::vector<stTriSet *>::iterator rgi = m_vTriSets.begin(); rgi != m_vTriSets.end(); rgi++)
  29. {
  30. tricount += (*rgi)->iTriCount;
  31. glBindTexture(GL_TEXTURE_2D, (*rgi)->dwGLTex);
  32. glColor4f(0,0,0,0.5f);
  33. glVertexPointer(3, GL_FLOAT, 0, (*rgi)->pVertarray);
  34. glColorPointer(4, GL_UNSIGNED_BYTE, 0, (*rgi)->pColorarray);
  35. glTexCoordPointer(2, GL_FLOAT, 0, (*rgi)->pTexarray);
  36. glDrawElements(GL_TRIANGLES, (*rgi)->iTriCount*3, GL_UNSIGNED_INT, (*rgi)->pTriarray);
  37. }
  38. glPopName();
  39. glPopMatrix();
  40. return tricount;
  41. }
  42. bool cModel::ReadDungeonPart(DWORD dwDungeon, WORD wDungeonPart, std::vector<WORD> * v_Textures)
  43. {
  44. cPortalFile *pf = m_Portal->OpenEntry(dwDungeon);
  45. if (!pf)
  46. {
  47. return false;
  48. }
  49. // char lele[500];
  50. // sprintf(lele, "c:\\portalfiles\\%08X.pf", dwDungeon);
  51. // pf->Dump(lele);
  52. cByteStream pBS(pf->data, pf->length);
  53. pBS.ReadBegin();
  54. m_dwID = pBS.ReadDWORD();
  55. DWORD dwNumParts = pBS.ReadDWORD();
  56. for (int i=0; i<(int) dwNumParts; i++)
  57. {
  58. //Read Part Header
  59. DWORD dwPartID = pBS.ReadDWORD();
  60. cACPreModel NewModel;
  61. NewModel.iNumTriFans = (int) pBS.ReadDWORD();
  62. DWORD dwNumClipping = pBS.ReadDWORD();
  63. DWORD dwNumConnectable = pBS.ReadDWORD();
  64. pBS.ReadDWORD(); //unk2
  65. NewModel.iNumVerts = (int) pBS.ReadDWORD();
  66. for (std::vector<WORD>::iterator i = v_Textures->begin(); i != v_Textures->end(); i++)
  67. NewModel.m_Textures.push_back(0x08000000 | *i);
  68. NewModel.m_Vertices = new cACVertex[NewModel.iNumVerts];
  69. for (int h=0; h<NewModel.iNumVerts; h++)
  70. {
  71. WORD wVertNum = pBS.ReadWORD();
  72. if (h != wVertNum)
  73. {
  74. return false;
  75. }
  76. NewModel.m_Vertices[h].Unpack(&pBS);
  77. }
  78. NewModel.m_TriFans = new cACTriFan[NewModel.iNumTriFans];
  79. for (int h=0; h<NewModel.iNumTriFans; h++)
  80. {
  81. WORD wPolyNum = pBS.ReadWORD();
  82. if (h != wPolyNum)
  83. {
  84. return false;
  85. }
  86. NewModel.m_TriFans[h].Unpack(&pBS);
  87. }
  88. for (int h=0; h<(int)dwNumConnectable; h++)
  89. {
  90. WORD wConnectsTo = pBS.ReadWORD();
  91. int a = 4;
  92. }
  93. //dword align now?
  94. pBS.ReadAlign();
  95. cBSPNode *BSP = cBSPNode::ParseNode(&pBS, 2); //dwTreeType = not 1
  96. delete BSP;
  97. for (int h=0; h<(int)dwNumClipping; h++)
  98. {
  99. WORD wPolyNum = pBS.ReadWORD();
  100. if (h != wPolyNum)
  101. {
  102. return false;
  103. }
  104. cACTriFan tpFan;
  105. tpFan.Unpack(&pBS);
  106. }
  107. BSP = cBSPNode::ParseNode(&pBS, 1); //dwTreeType = not 1
  108. delete BSP;
  109. DWORD test = pBS.ReadDWORD();
  110. if (test)
  111. {
  112. BSP = cBSPNode::ParseNode(&pBS, 0); //dwTreeType = not 1
  113. delete BSP;
  114. }
  115. pBS.ReadAlign();
  116. if (dwPartID == wDungeonPart)
  117. {
  118. ParsePreModel(&NewModel);
  119. return true;
  120. }
  121. }
  122. return false;
  123. }
  124. bool cModel::ReadModel(DWORD dwModel, int iModelNum, std::vector<stPaletteSwap> *vPaletteSwaps, std::vector<stTextureSwap> *vTextureSwaps)
  125. {
  126. // return true;
  127. //out with the old
  128. for (std::vector<stTriSet *>::iterator i = m_vTriSets.begin(); i != m_vTriSets.end(); i++)
  129. delete *i;
  130. m_vTriSets.clear();
  131. //in with the new
  132. cPortalFile *pf = m_Portal->OpenEntry(dwModel);
  133. if (!pf)
  134. {
  135. return false;
  136. }
  137. //stage one - loading from turbine's ass format
  138. //note: need to clean this out a bit at some point...
  139. //switch this to auto_ptr
  140. cByteStream pBS(pf->data, pf->length);
  141. pBS.ReadBegin();
  142. //data
  143. m_dwID = pBS.ReadDWORD();
  144. DWORD dwType = pBS.ReadDWORD();
  145. cACPreModel NewModel;
  146. NewModel.vTextureSwaps = vTextureSwaps;
  147. NewModel.vPaletteSwaps = vPaletteSwaps;
  148. NewModel.iSwapModelNum = iModelNum;
  149. NewModel.m_bSwaps = (vTextureSwaps) || (vPaletteSwaps);
  150. BYTE bTextureCount = pBS.ReadByte();
  151. for (int i=0; i<bTextureCount; i++)
  152. NewModel.m_Textures.push_back(pBS.ReadDWORD());
  153. DWORD VertexType = pBS.ReadDWORD();
  154. NewModel.iNumVerts = (int) pBS.ReadDWORD();
  155. NewModel.m_Vertices = new cACVertex[NewModel.iNumVerts];
  156. for (int i=0; i<NewModel.iNumVerts; i++)
  157. {
  158. WORD vertNum = pBS.ReadWORD();
  159. if (i != vertNum)
  160. {
  161. return false;
  162. }
  163. NewModel.m_Vertices[i].Unpack(&pBS);
  164. }
  165. if (dwType & 1)
  166. {
  167. //Collision Data
  168. WORD wColTriCount = pBS.ReadPackedWORD();
  169. cACTriFan *tfCollision = new cACTriFan[wColTriCount];
  170. for (int i=0; i<wColTriCount; i++)
  171. {
  172. WORD polyNum = pBS.ReadWORD();
  173. if (i != polyNum)
  174. {
  175. return false;
  176. }
  177. tfCollision[i].Unpack(&pBS);
  178. }
  179. //we don't use this so nuke it for now
  180. delete []tfCollision;
  181. //BSP Data
  182. cBSPNode *BSP = cBSPNode::ParseNode(&pBS, 1); //dwTreeType = 1
  183. delete BSP;
  184. }
  185. float qx = pBS.ReadFloat();
  186. float qy = pBS.ReadFloat();
  187. float qz = pBS.ReadFloat();
  188. if (dwType & 2)
  189. {
  190. //Actual Model Triangle Data
  191. NewModel.iNumTriFans = (int) pBS.ReadPackedWORD();
  192. NewModel.m_TriFans = new cACTriFan[NewModel.iNumTriFans];
  193. for (int i=0; i<NewModel.iNumTriFans; i++)
  194. {
  195. WORD polyNum = pBS.ReadWORD();
  196. if (i != polyNum)
  197. {
  198. return false;
  199. }
  200. NewModel.m_TriFans[i].Unpack(&pBS);
  201. }
  202. }
  203. return ParsePreModel(&NewModel);
  204. }
  205. bool cModel::ParsePreModel(cACPreModel * pModel)
  206. {
  207. // return true;
  208. //loading stage 2 - Convert trifan lists into triangle lists by texture unit
  209. //Loop through each trifan, and make an index of all the different textures that this model uses
  210. std::unordered_set<DWORD> mTex;
  211. std::vector<stTexInfo> vTex;
  212. for (int i=0; i<pModel->iNumTriFans; i++)
  213. {
  214. if (pModel->m_TriFans[i].wTexNum >= pModel->m_Textures.size())
  215. {
  216. return false;
  217. }
  218. DWORD dwTexture = pModel->m_Textures[pModel->m_TriFans[i].wTexNum];
  219. cPortalFile *pfTexInfo = m_Portal->OpenEntry(dwTexture);
  220. if (!pfTexInfo)
  221. {
  222. return false;
  223. }
  224. cByteStream pBSTex(pfTexInfo->data, pfTexInfo->length);
  225. pBSTex.ReadBegin();
  226. stTexInfo tiTex;
  227. DWORD flags = pBSTex.ReadDWORD();
  228. if (flags & 1)
  229. {
  230. //rgb
  231. tiTex.dwColor = pBSTex.ReadDWORD();
  232. tiTex.dwTexID = 0;
  233. //Enable transparency... this seems wrong somehow...
  234. float fTransTex = pBSTex.ReadFloat();
  235. float fTransUnknown = pBSTex.ReadFloat();
  236. float fTransPix = pBSTex.ReadFloat();
  237. //1-Transtex doesn't seem to work, 1-transpix seems to work
  238. DWORD tpf = ((DWORD) (0xFF * (1.0f-fTransPix))) << 24;
  239. tiTex.dwColor &= 0x00FFFFFF;
  240. tiTex.dwColor |= tpf;
  241. }
  242. if ((flags & 2) || (flags & 4))
  243. {
  244. DWORD dwTexture = pBSTex.ReadDWORD();
  245. //This used to be palette, but no longer makes any sense since palettes are embedded in the file...
  246. DWORD dwPalette = pBSTex.ReadDWORD();
  247. if (dwPalette > 0)
  248. int a = 4;
  249. float fTransTex = pBSTex.ReadFloat();
  250. float fTransUnknown = pBSTex.ReadFloat();
  251. float fTransPix = pBSTex.ReadFloat();
  252. tiTex.dwColor = 0x7F7F7F7F;
  253. //textureswap
  254. if (pModel->m_bSwaps)
  255. {
  256. for (std::vector<stTextureSwap>::iterator i = pModel->vTextureSwaps->begin(); i != pModel->vTextureSwaps->end(); i++)
  257. {
  258. if (i->modelIndex == pModel->iSwapModelNum)
  259. {
  260. if (i->oldTexture == (dwTexture & 0xFFFF))
  261. {
  262. dwTexture = (*i).newTexture | 0x05000000;
  263. break;
  264. }
  265. }
  266. }
  267. }
  268. //retrieve texture/palette combo from portal
  269. tiTex.dwTexID = m_Portal->FindTexturePalette(dwTexture, pModel->vPaletteSwaps, fTransTex, fTransPix);
  270. }
  271. vTex.push_back(tiTex);
  272. mTex.insert(tiTex.dwTexID);
  273. }
  274. //Now, loop through each unique texture index and figure out which triangles use this texture
  275. int icnt = 0;
  276. for (std::unordered_set<DWORD>::iterator texid = mTex.begin(); texid != mTex.end(); texid++, icnt++)
  277. {
  278. stTriSet *rgT = new stTriSet();
  279. rgT->dwGLTex = *texid;
  280. //Should probably turn these into pointers - vectors suck at making new large structs
  281. std::vector<renderTriangle> vTris;
  282. std::vector<cPoint3D> vVerts;
  283. std::vector<stACUV> vTexels;
  284. std::vector<DWORD> vColors;
  285. //Loop through the trifans and see if any of them use this texture
  286. int vertcount = 0;
  287. for (int i=0; i<pModel->iNumTriFans; i++)
  288. {
  289. if (vTex[i].dwTexID == rgT->dwGLTex)
  290. {
  291. for (int j=0; j<pModel->m_TriFans[i].bNumVerts;j++)
  292. {
  293. int iVertNum = pModel->m_TriFans[i].wVerts[j];
  294. vVerts.push_back(pModel->m_Vertices[iVertNum].GetP3D());
  295. if (pModel->m_TriFans[i].bUVs)
  296. vTexels.push_back(pModel->m_Vertices[iVertNum].UVs[pModel->m_TriFans[i].bUVs[j]]);
  297. else
  298. vTexels.push_back(stACUV(0,0));
  299. vColors.push_back(vTex[i].dwColor);
  300. }
  301. for (int j=0;j<pModel->m_TriFans[i].bNumVerts-2;j++)
  302. {
  303. renderTriangle rtTemp;
  304. rtTemp.pt[0] = vertcount; rtTemp.pt[1] = vertcount+j+1; rtTemp.pt[2] = vertcount+j+2;
  305. vTris.push_back(rtTemp);
  306. }
  307. vertcount = (int) vVerts.size();
  308. }
  309. }
  310. rgT->iTriCount = (int) vTris.size();
  311. rgT->pColorarray = new GLuint[vertcount];
  312. rgT->pTriarray = new GLuint[3*rgT->iTriCount];
  313. rgT->pTexarray = new GLfloat[2*vertcount];
  314. rgT->pVertarray = new GLfloat[3*vertcount];
  315. int jcnt = 0;
  316. for (std::vector<renderTriangle>::iterator j = vTris.begin(); j != vTris.end(); j++, jcnt++)
  317. {
  318. rgT->pTriarray[3*jcnt] = (*j).pt[0];
  319. rgT->pTriarray[3*jcnt+1] = (*j).pt[1];
  320. rgT->pTriarray[3*jcnt+2] = (*j).pt[2];
  321. }
  322. for (int j=0;j<vertcount;j++)
  323. {
  324. rgT->pColorarray[j] = vColors[j];
  325. rgT->pTexarray[2*j] = vTexels[j].u;
  326. rgT->pTexarray[2*j+1] = vTexels[j].v;
  327. rgT->pVertarray[3*j] = vVerts[j].x;
  328. rgT->pVertarray[3*j+1] = vVerts[j].y;
  329. rgT->pVertarray[3*j+2] = vVerts[j].z;
  330. }
  331. m_vTriSets.push_back(rgT);
  332. }
  333. return true;
  334. }
  335. void cModel::SetTranslation(cPoint3D Translation)
  336. {
  337. m_pTranslation = Translation;
  338. }
  339. void cModel::SetRotation(float Rot1, float Rot2, float Rot3, float Rot4)
  340. {
  341. m_fRotation[0] = Rot1;
  342. m_fRotation[1] = Rot2;
  343. m_fRotation[2] = Rot3;
  344. m_fRotation[3] = Rot4;
  345. }