MLRSortByOrder.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. //===========================================================================//
  2. // Copyright (C) Microsoft Corporation. All rights reserved. //
  3. //===========================================================================//
  4. #include "MLRHeaders.hpp"
  5. extern DWORD gEnableTextureSort, gEnableAlphaSort, gEnableLightMaps;
  6. MLRSortByOrder::ClassData*
  7. MLRSortByOrder::DefaultData = NULL;
  8. //#############################################################################
  9. //############################ MLRSortByOrder ################################
  10. //#############################################################################
  11. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  12. //
  13. void
  14. MLRSortByOrder::InitializeClass()
  15. {
  16. Verify(!DefaultData);
  17. Verify(gos_GetCurrentHeap() == StaticHeap);
  18. DefaultData =
  19. new ClassData(
  20. MLRSortByOrderClassID,
  21. "MidLevelRenderer::MLRSortByOrder",
  22. MLRSorter::DefaultData
  23. );
  24. Register_Object(DefaultData);
  25. }
  26. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  27. //
  28. void
  29. MLRSortByOrder::TerminateClass()
  30. {
  31. Unregister_Object(DefaultData);
  32. delete DefaultData;
  33. DefaultData = NULL;
  34. }
  35. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  36. //
  37. MLRSortByOrder::MLRSortByOrder(MLRTexturePool *tp) :
  38. MLRSorter(DefaultData, tp)
  39. {
  40. Verify(gos_GetCurrentHeap() == Heap);
  41. int i;
  42. gos_PushCurrentHeap(StaticHeap);
  43. for(i=0;i<MLRState::PriorityCount;i++)
  44. {
  45. lastUsedInBucket[i] = 0;
  46. priorityBuckets[i].SetLength(Limits::Max_Number_Primitives_Per_Frame + Limits::Max_Number_ScreenQuads_Per_Frame);
  47. }
  48. alphaSort.SetLength(2*Limits::Max_Number_Vertices_Per_Frame);
  49. for(i=0;i<alphaSort.GetLength();i++)
  50. {
  51. alphaSort[i] = new SortAlpha;
  52. }
  53. gos_PopCurrentHeap();
  54. }
  55. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  56. //
  57. MLRSortByOrder::~MLRSortByOrder()
  58. {
  59. int i;
  60. gos_PushCurrentHeap(StaticHeap);
  61. for(i=0;i<alphaSort.GetLength();i++)
  62. {
  63. delete alphaSort[i];
  64. }
  65. alphaSort.SetLength(0);
  66. gos_PopCurrentHeap();
  67. }
  68. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  69. //
  70. void
  71. MLRSortByOrder::Reset ()
  72. {
  73. Check_Object(this);
  74. int i;
  75. for(i=0;i<MLRState::PriorityCount;i++)
  76. {
  77. lastUsedInBucket[i] = 0;
  78. }
  79. MLRSorter::Reset();
  80. }
  81. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  82. //
  83. void
  84. MLRSortByOrder::AddPrimitive(MLRPrimitiveBase *pt, int pass)
  85. {
  86. Check_Object(this);
  87. Check_Object(pt);
  88. SortData *sd = NULL;
  89. switch(pt->GetSortDataMode())
  90. {
  91. case SortData::TriList:
  92. case SortData::TriIndexedList:
  93. sd = SetRawData(pt, pass);
  94. break;
  95. }
  96. unsigned priority = pt->GetCurrentState(pass).GetPriority();
  97. if(sd != NULL)
  98. {
  99. priorityBuckets[priority][lastUsedInBucket[priority]++] = sd;
  100. }
  101. }
  102. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  103. //
  104. void
  105. MLRSortByOrder::AddEffect(MLREffect *ef, const MLRState& state)
  106. {
  107. Check_Object(this);
  108. Check_Object(ef);
  109. SortData *sd = NULL;
  110. switch(ef->GetSortDataMode())
  111. {
  112. case SortData::PointCloud:
  113. sd = SetRawData(
  114. ef->GetGOSVertices(),
  115. ef->GetNumGOSVertices(),
  116. state,
  117. SortData::PointCloud
  118. );
  119. sd->numIndices = ef->GetType(0);
  120. break;
  121. case SortData::LineCloud:
  122. sd = SetRawData(
  123. ef->GetGOSVertices(),
  124. ef->GetNumGOSVertices(),
  125. state,
  126. SortData::LineCloud
  127. );
  128. sd->numIndices = ef->GetType(0);
  129. break;
  130. case SortData::TriList:
  131. sd = SetRawData(
  132. ef->GetGOSVertices(),
  133. ef->GetNumGOSVertices(),
  134. state,
  135. SortData::TriList
  136. );
  137. break;
  138. case SortData::TriIndexedList:
  139. {
  140. MLRIndexedTriangleCloud *itc = Cast_Object(MLRIndexedTriangleCloud*, ef);
  141. sd = SetRawIndexedData(
  142. itc->GetGOSVertices(),
  143. itc->GetNumGOSVertices(),
  144. itc->GetGOSIndices(),
  145. itc->GetNumGOSIndices(),
  146. state,
  147. SortData::TriIndexedList
  148. );
  149. }
  150. break;
  151. }
  152. unsigned priority = state.GetPriority();
  153. if(sd != NULL)
  154. {
  155. priorityBuckets[priority][lastUsedInBucket[priority]++] = sd;
  156. }
  157. }
  158. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  159. //
  160. void
  161. MLRSortByOrder::AddScreenQuads
  162. (
  163. GOSVertex *vertices,
  164. const DrawScreenQuadsInformation *dInfo
  165. )
  166. {
  167. Verify(dInfo->currentNrOfQuads != 0 && (dInfo->currentNrOfQuads&3) == 0);
  168. SortData *sd = SetRawData
  169. (
  170. vertices,
  171. dInfo->currentNrOfQuads,
  172. dInfo->state,
  173. SortData::Quads
  174. );
  175. unsigned priority = dInfo->state.GetPriority();
  176. if(sd != NULL)
  177. {
  178. priorityBuckets[priority][lastUsedInBucket[priority]++] = sd;
  179. }
  180. }
  181. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  182. //
  183. void
  184. MLRSortByOrder::AddSortRawData(SortData *sd)
  185. {
  186. Check_Object(this);
  187. if(sd==NULL)
  188. {
  189. return;
  190. }
  191. unsigned priority = sd->state.GetPriority();
  192. priorityBuckets[priority][lastUsedInBucket[priority]++] = sd;
  193. }
  194. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  195. //
  196. void
  197. MLRSortByOrder::RenderNow ()
  198. {
  199. Check_Object(this);
  200. //
  201. // So GameOS knows how long the transform and clip and lighting took of update renderers
  202. //
  203. Stuff::DynamicArrayOf<SortData*>
  204. *priorityBucket;
  205. Stuff::DynamicArrayOf<ToBeDrawnPrimitive*>
  206. *priorityBucketNotDrawn;
  207. GOSVertex::farClipReciprocal = farClipReciprocal;
  208. int i, j, k;
  209. // Limits::Max_Number_Primitives_Per_Frame + Max_Number_ScreenQuads_Per_Frame
  210. MLRPrimitiveBase *primitive;
  211. for(i=0;i<MLRState::PriorityCount;i++)
  212. {
  213. #ifdef CalDraw
  214. ToBeDrawnPrimitive *tbdp;
  215. int alphaToSort = 0;
  216. if(lastUsedInBucketNotDrawn[i])
  217. {
  218. Verify(lastUsedInBucketNotDrawn[i]<=Limits::Max_Number_Primitives_Per_Frame + Limits::Max_Number_ScreenQuads_Per_Frame);
  219. if( gEnableTextureSort && i != MLRState::AlphaPriority)
  220. {
  221. Start_Timer(Texture_Sorting_Time);
  222. // do a shell sort
  223. int ii, jj, hh;
  224. ToBeDrawnPrimitive *tempSortData;
  225. priorityBucketNotDrawn = &priorityBucketsNotDrawn[i];
  226. for(hh=1;hh<lastUsedInBucketNotDrawn[i]/9;hh=3*hh+1);
  227. for(;hh>0;hh/=3)
  228. {
  229. for(ii=hh;ii<lastUsedInBucketNotDrawn[i];ii++)
  230. {
  231. tempSortData = (*priorityBucketNotDrawn)[ii];
  232. jj = ii;
  233. while(jj>=hh && (*priorityBucketNotDrawn)[jj-hh]->state.GetTextureHandle() > tempSortData->state.GetTextureHandle())
  234. {
  235. (*priorityBucketNotDrawn)[jj] = (*priorityBucketNotDrawn)[jj-hh];
  236. jj -= hh;
  237. }
  238. (*priorityBucketNotDrawn)[jj] = tempSortData;
  239. }
  240. }
  241. Stop_Timer(Texture_Sorting_Time);
  242. }
  243. if(i != MLRState::AlphaPriority)
  244. {
  245. for(j=0;j<lastUsedInBucketNotDrawn[i];j++)
  246. {
  247. tbdp = priorityBucketsNotDrawn[i][j];
  248. Check_Pointer(tbdp);
  249. primitive = tbdp->primitive;
  250. Check_Object(primitive);
  251. int nrOfLightMaps = 0;
  252. for(k=0;k<tbdp->nrOfActiveLights;k++)
  253. {
  254. Check_Object(tbdp->activeLights[k]);
  255. nrOfLightMaps += (tbdp->activeLights[k]->GetLightMap() != NULL) ? 1 : 0;
  256. tbdp->activeLights[k]->SetLightToShapeMatrix(tbdp->worldToShape);
  257. }
  258. if(!gEnableLightMaps)
  259. {
  260. nrOfLightMaps = 0;
  261. }
  262. if(nrOfLightMaps)
  263. {
  264. MLRLightMap::SetDrawData
  265. (
  266. ToBeDrawnPrimitive::allVerticesToDraw,
  267. &tbdp->shapeToClipMatrix,
  268. tbdp->clippingFlags,
  269. tbdp->state
  270. );
  271. }
  272. if(primitive->FindBackFace(tbdp->cameraPosition))
  273. {
  274. primitive->Lighting(tbdp->activeLights, tbdp->nrOfActiveLights);
  275. if(tbdp->clippingFlags.GetClippingState() != 0)
  276. {
  277. if(primitive->TransformAndClip(
  278. &tbdp->shapeToClipMatrix,
  279. tbdp->clippingFlags,
  280. ToBeDrawnPrimitive::allVerticesToDraw,
  281. true)
  282. )
  283. {
  284. if(primitive->GetVisible())
  285. {
  286. for(k=0;k<primitive->GetNumPasses();k++)
  287. {
  288. DrawPrimitive(primitive, k);
  289. }
  290. }
  291. }
  292. }
  293. else
  294. {
  295. primitive->TransformNoClip(
  296. &tbdp->shapeToClipMatrix,
  297. ToBeDrawnPrimitive::allVerticesToDraw,
  298. true);
  299. for(k=0;k<primitive->GetNumPasses();k++)
  300. {
  301. DrawPrimitive(primitive, k);
  302. }
  303. }
  304. #ifdef LAB_ONLY
  305. Set_Statistic(Number_Of_Primitives, Number_Of_Primitives+1);
  306. if(primitive->IsDerivedFrom(MLRIndexedPrimitiveBase::DefaultData))
  307. {
  308. Point3D *coords;
  309. unsigned short *indices;
  310. int nr;
  311. (Cast_Pointer(MLRIndexedPrimitiveBase*, primitive))->GetIndexData(&indices, &nr);
  312. Set_Statistic(NumAllIndices, NumAllIndices+nr);
  313. primitive->GetCoordData(&coords, &nr);
  314. Set_Statistic(NumAllVertices, NumAllVertices + nr);
  315. Set_Statistic(Index_Over_Vertex_Ratio, (Scalar)NumAllIndices/(Scalar)NumAllVertices);
  316. }
  317. #endif
  318. }
  319. if(nrOfLightMaps)
  320. {
  321. MLRLightMap::DrawLightMaps(this);
  322. }
  323. }
  324. }
  325. else
  326. {
  327. SortData *sd = NULL;
  328. for(j=0;j<lastUsedInBucketNotDrawn[i];j++)
  329. {
  330. tbdp = priorityBucketsNotDrawn[i][j];
  331. primitive = tbdp->primitive;
  332. if(primitive->FindBackFace(tbdp->cameraPosition))
  333. {
  334. primitive->Lighting(tbdp->activeLights, tbdp->nrOfActiveLights);
  335. if(tbdp->clippingFlags.GetClippingState() != 0)
  336. {
  337. if(primitive->TransformAndClip(
  338. &tbdp->shapeToClipMatrix,
  339. tbdp->clippingFlags,
  340. ToBeDrawnPrimitive::allVerticesToDraw,
  341. true)
  342. )
  343. {
  344. if(!primitive->GetVisible())
  345. {
  346. continue;
  347. }
  348. }
  349. }
  350. else
  351. {
  352. primitive->TransformNoClip(
  353. &tbdp->shapeToClipMatrix,
  354. ToBeDrawnPrimitive::allVerticesToDraw,
  355. true);
  356. }
  357. #ifdef LAB_ONLY
  358. Set_Statistic(Number_Of_Primitives, Number_Of_Primitives+1);
  359. if(primitive->IsDerivedFrom(MLRIndexedPrimitiveBase::DefaultData))
  360. {
  361. Point3D *coords;
  362. unsigned short *indices;
  363. int nr;
  364. (Cast_Pointer(MLRIndexedPrimitiveBase*, primitive))->GetIndexData(&indices, &nr);
  365. Set_Statistic(NumAllIndices, NumAllIndices+nr);
  366. primitive->GetCoordData(&coords, &nr);
  367. Set_Statistic(NumAllVertices, NumAllVertices+nr);
  368. Set_Statistic(Index_Over_Vertex_Ratio, (Scalar)NumAllIndices/(Scalar)NumAllVertices);
  369. }
  370. #endif
  371. }
  372. else
  373. {
  374. continue;
  375. }
  376. if(primitive->GetNumGOSVertices() > 0)
  377. for(k=0;k<primitive->GetNumPasses();k++)
  378. {
  379. sd = SetRawData(primitive, k);
  380. Check_Pointer(sd);
  381. if( gEnableAlphaSort && (sd->type == SortData::TriList || sd->type == SortData::TriIndexedList) )
  382. {
  383. SortData::LoadSortAlphaFunc alphaFunc = sd->LoadSortAlpha[sd->type];
  384. Verify(alphaToSort+sd->numVertices/3 < 2*Limits::Max_Number_Vertices_Per_Frame);
  385. alphaToSort += (sd->*alphaFunc)(alphaSort.GetData() + alphaToSort);
  386. }
  387. else
  388. {
  389. if(theCurrentState != sd->state)
  390. {
  391. SetDifferences(theCurrentState, sd->state);
  392. theCurrentState = sd->state;
  393. }
  394. SortData::DrawFunc drawFunc = sd->Draw[sd->type];
  395. (sd->*drawFunc)();
  396. }
  397. }
  398. }
  399. }
  400. }
  401. #endif
  402. if(lastUsedInBucket[i])
  403. {
  404. Verify(lastUsedInBucket[i]<=Limits::Max_Number_Primitives_Per_Frame + Limits::Max_Number_ScreenQuads_Per_Frame);
  405. if( gEnableTextureSort && i != MLRState::AlphaPriority)
  406. {
  407. Start_Timer(Texture_Sorting_Time);
  408. // do a shell sort
  409. int ii, jj, hh;
  410. SortData *tempSortData;
  411. priorityBucket = &priorityBuckets[i];
  412. for(hh=1;hh<lastUsedInBucket[i]/9;hh=3*hh+1);
  413. for(;hh>0;hh/=3)
  414. {
  415. for(ii=hh;ii<lastUsedInBucket[i];ii++)
  416. {
  417. tempSortData = (*priorityBucket)[ii];
  418. jj = ii;
  419. while(jj>=hh && (*priorityBucket)[jj-hh]->state.GetTextureHandle() > tempSortData->state.GetTextureHandle())
  420. {
  421. (*priorityBucket)[jj] = (*priorityBucket)[jj-hh];
  422. jj -= hh;
  423. }
  424. (*priorityBucket)[jj] = tempSortData;
  425. }
  426. }
  427. Stop_Timer(Texture_Sorting_Time);
  428. }
  429. if(i != MLRState::AlphaPriority)
  430. {
  431. for(j=0;j<lastUsedInBucket[i];j++)
  432. {
  433. SortData *sd = priorityBuckets[i][j];
  434. Check_Pointer(sd);
  435. if(theCurrentState != sd->state)
  436. {
  437. SetDifferences(theCurrentState, sd->state);
  438. theCurrentState = sd->state;
  439. }
  440. SortData::DrawFunc drawFunc = sd->Draw[sd->type];
  441. // _clear87();
  442. (sd->*drawFunc)();
  443. // _clear87();
  444. }
  445. }
  446. else
  447. {
  448. for(j=0;j<lastUsedInBucket[i];j++)
  449. {
  450. SortData *sd = priorityBuckets[i][j];
  451. Check_Pointer(sd);
  452. if( gEnableAlphaSort && (sd->type == SortData::TriList || sd->type == SortData::TriIndexedList) )
  453. {
  454. SortData::LoadSortAlphaFunc alphaFunc = sd->LoadSortAlpha[sd->type];
  455. Verify(alphaToSort+sd->numVertices/3 < 2*Limits::Max_Number_Vertices_Per_Frame);
  456. alphaToSort += (sd->*alphaFunc)(alphaSort.GetData() + alphaToSort);
  457. }
  458. else
  459. {
  460. if(theCurrentState != sd->state)
  461. {
  462. SetDifferences(theCurrentState, sd->state);
  463. theCurrentState = sd->state;
  464. }
  465. SortData::DrawFunc drawFunc = sd->Draw[sd->type];
  466. (sd->*drawFunc)();
  467. }
  468. }
  469. }
  470. }
  471. if(alphaToSort > 0)
  472. {
  473. Start_Timer(Alpha_Sorting_Time);
  474. // do a shell sort
  475. int ii, jj, hh;
  476. SortAlpha *tempSortAlpha;
  477. Stuff::DynamicArrayOf<SortAlpha*>
  478. *alphaArray;
  479. alphaArray = &alphaSort;
  480. for(hh=1;hh<alphaToSort/9;hh=3*hh+1);
  481. for(;hh>0;hh/=3)
  482. {
  483. for(ii=hh;ii<alphaToSort;ii++)
  484. {
  485. tempSortAlpha = (*alphaArray)[ii];
  486. jj = ii;
  487. while(jj>=hh && (*alphaArray)[jj-hh]->distance < tempSortAlpha->distance)
  488. {
  489. (*alphaArray)[jj] = (*alphaArray)[jj-hh];
  490. jj -= hh;
  491. }
  492. (*alphaArray)[jj] = tempSortAlpha;
  493. }
  494. }
  495. Stop_Timer(Alpha_Sorting_Time);
  496. for(ii=0;ii<alphaToSort;ii++)
  497. {
  498. if(theCurrentState != *alphaSort[ii]->state)
  499. {
  500. SetDifferences(theCurrentState, *alphaSort[ii]->state);
  501. theCurrentState = *alphaSort[ii]->state;
  502. }
  503. Start_Timer(GOS_Draw_Time);
  504. if ((alphaSort[ii]->triangle[0].z >= 0.0f) &&
  505. (alphaSort[ii]->triangle[0].z < 1.0f) &&
  506. (alphaSort[ii]->triangle[1].z >= 0.0f) &&
  507. (alphaSort[ii]->triangle[1].z < 1.0f) &&
  508. (alphaSort[ii]->triangle[2].z >= 0.0f) &&
  509. (alphaSort[ii]->triangle[2].z < 1.0f))
  510. {
  511. gos_DrawTriangles( &(alphaSort[ii]->triangle[0]), 3);
  512. }
  513. Stop_Timer(GOS_Draw_Time);
  514. }
  515. Set_Statistic(NumberOfAlphaSortedTriangles, NumberOfAlphaSortedTriangles+alphaToSort);
  516. }
  517. }
  518. }
  519. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  520. //
  521. void
  522. MLRSortByOrder::TestInstance() const
  523. {
  524. Verify(IsDerivedFrom(DefaultData));
  525. }