Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

314 lines
9.3 KiB

  1. #pragma warning( disable : 4786 4018 4530 )
  2. #include "NvTriStripObjects.h"
  3. #include "NvTriStrip.h"
  4. #include <assert.h>
  5. static inline unsigned short AsUShort( int nValue )
  6. {
  7. assert( nValue >= 0 && nValue <= 65535 );
  8. return (unsigned short)( nValue );
  9. }
  10. static inline unsigned short AsUShort( unsigned int nValue )
  11. {
  12. assert( nValue <= 65535 );
  13. return (unsigned short)( nValue );
  14. }
  15. ////////////////////////////////////////////////////////////////////////////////////////
  16. //private data
  17. static unsigned int cacheSize = CACHESIZE_GEFORCE1_2;
  18. static bool bStitchStrips = true;
  19. static unsigned int minStripSize = 0;
  20. static bool bListsOnly = false;
  21. ////////////////////////////////////////////////////////////////////////////////////////
  22. // SetListsOnly()
  23. //
  24. // If set to true, will return an optimized list, with no strips at all.
  25. //
  26. // Default value: false
  27. //
  28. void SetListsOnly(const bool _bListsOnly)
  29. {
  30. bListsOnly = _bListsOnly;
  31. }
  32. ////////////////////////////////////////////////////////////////////////////////////////
  33. // SetCacheSize()
  34. //
  35. // Sets the cache size which the stripfier uses to optimize the data.
  36. // Controls the length of the generated individual strips.
  37. // This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2
  38. // You may want to play around with this number to tweak performance.
  39. //
  40. // Default value: 16
  41. //
  42. void SetCacheSize(const unsigned int _cacheSize)
  43. {
  44. cacheSize = _cacheSize;
  45. }
  46. ////////////////////////////////////////////////////////////////////////////////////////
  47. // SetStitchStrips()
  48. //
  49. // bool to indicate whether to stitch together strips into one huge strip or not.
  50. // If set to true, you'll get back one huge strip stitched together using degenerate
  51. // triangles.
  52. // If set to false, you'll get back a large number of separate strips.
  53. //
  54. // Default value: true
  55. //
  56. void SetStitchStrips(const bool _bStitchStrips)
  57. {
  58. bStitchStrips = _bStitchStrips;
  59. }
  60. ////////////////////////////////////////////////////////////////////////////////////////
  61. // SetMinStripSize()
  62. //
  63. // Sets the minimum acceptable size for a strip, in triangles.
  64. // All strips generated which are shorter than this will be thrown into one big, separate list.
  65. //
  66. // Default value: 0
  67. //
  68. void SetMinStripSize(const unsigned int _minStripSize)
  69. {
  70. minStripSize = _minStripSize;
  71. }
  72. ////////////////////////////////////////////////////////////////////////////////////////
  73. // GenerateStrips()
  74. //
  75. // in_indices: input index list, the indices you would use to render
  76. // in_numIndices: number of entries in in_indices
  77. // primGroups: array of optimized/stripified PrimitiveGroups
  78. // numGroups: number of groups returned
  79. //
  80. // Be sure to call delete[] on the returned primGroups to avoid leaking mem
  81. //
  82. void GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices,
  83. PrimitiveGroup** primGroups, unsigned short* numGroups)
  84. {
  85. //put data in format that the stripifier likes
  86. WordVec tempIndices;
  87. tempIndices.resize(in_numIndices);
  88. unsigned short maxIndex = 0;
  89. for(int i = 0; i < in_numIndices; i++)
  90. {
  91. tempIndices[i] = in_indices[i];
  92. if(in_indices[i] > maxIndex)
  93. maxIndex = in_indices[i];
  94. }
  95. NvStripInfoVec tempStrips;
  96. NvFaceInfoVec tempFaces;
  97. NvStripifier stripifier;
  98. //do actual stripification
  99. stripifier.Stripify(tempIndices, cacheSize, minStripSize, maxIndex, tempStrips, tempFaces);
  100. //stitch strips together
  101. IntVec stripIndices;
  102. unsigned int numSeparateStrips = 0;
  103. if(bListsOnly)
  104. {
  105. //if we're outputting only lists, we're done
  106. *numGroups = 1;
  107. (*primGroups) = new PrimitiveGroup[*numGroups];
  108. PrimitiveGroup* primGroupArray = *primGroups;
  109. //count the total number of indices
  110. unsigned int numIndices = 0;
  111. for(int i = 0; i < tempStrips.size(); i++)
  112. {
  113. numIndices += (unsigned int)( tempStrips[i]->m_faces.size() * 3 );
  114. }
  115. //add in the list
  116. numIndices += (unsigned int)( tempFaces.size() * 3 );
  117. primGroupArray[0].type = PT_LIST;
  118. primGroupArray[0].numIndices = numIndices;
  119. primGroupArray[0].indices = new unsigned short[numIndices];
  120. //do strips
  121. unsigned int indexCtr = 0;
  122. for(int i = 0; i < tempStrips.size(); i++)
  123. {
  124. for(int j = 0; j < tempStrips[i]->m_faces.size(); j++)
  125. {
  126. //degenerates are of no use with lists
  127. if(!NvStripifier::IsDegenerate(tempStrips[i]->m_faces[j]))
  128. {
  129. primGroupArray[0].indices[indexCtr++] = AsUShort( tempStrips[i]->m_faces[j]->m_v0 );
  130. primGroupArray[0].indices[indexCtr++] = AsUShort( tempStrips[i]->m_faces[j]->m_v1 );
  131. primGroupArray[0].indices[indexCtr++] = AsUShort( tempStrips[i]->m_faces[j]->m_v2 );
  132. }
  133. else
  134. {
  135. //we've removed a tri, reduce the number of indices
  136. primGroupArray[0].numIndices -= 3;
  137. }
  138. }
  139. }
  140. //do lists
  141. for(int i = 0; i < tempFaces.size(); i++)
  142. {
  143. primGroupArray[0].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v0 );
  144. primGroupArray[0].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v1 );
  145. primGroupArray[0].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v2 );
  146. }
  147. }
  148. else
  149. {
  150. stripifier.CreateStrips(tempStrips, stripIndices, bStitchStrips, numSeparateStrips);
  151. //if we're stitching strips together, we better get back only one strip from CreateStrips()
  152. assert( (bStitchStrips && (numSeparateStrips == 1)) || !bStitchStrips);
  153. //convert to output format
  154. *numGroups = AsUShort( numSeparateStrips ); //for the strips
  155. if(tempFaces.size() != 0)
  156. (*numGroups)++; //we've got a list as well, increment
  157. (*primGroups) = new PrimitiveGroup[*numGroups];
  158. PrimitiveGroup* primGroupArray = *primGroups;
  159. //first, the strips
  160. int startingLoc = 0;
  161. for(int stripCtr = 0; stripCtr < numSeparateStrips; stripCtr++)
  162. {
  163. int stripLength = 0;
  164. if(!bStitchStrips)
  165. {
  166. //if we've got multiple strips, we need to figure out the correct length
  167. int i = startingLoc;
  168. for(i; i < stripIndices.size(); i++)
  169. {
  170. if(stripIndices[i] == -1)
  171. break;
  172. }
  173. stripLength = i - startingLoc;
  174. }
  175. else
  176. {
  177. stripLength = (int)( stripIndices.size() );
  178. }
  179. primGroupArray[stripCtr].type = PT_STRIP;
  180. primGroupArray[stripCtr].indices = new unsigned short[stripLength];
  181. primGroupArray[stripCtr].numIndices = stripLength;
  182. int indexCtr = 0;
  183. for(int i = startingLoc; i < stripLength + startingLoc; i++)
  184. primGroupArray[stripCtr].indices[indexCtr++] = AsUShort( stripIndices[i] );
  185. //we add 1 to account for the -1 separating strips
  186. //this doesn't break the stitched case since we'll exit the loop
  187. startingLoc += stripLength + 1;
  188. }
  189. //next, the list
  190. if(tempFaces.size() != 0)
  191. {
  192. int faceGroupLoc = (*numGroups) - 1; //the face group is the last one
  193. primGroupArray[faceGroupLoc].type = PT_LIST;
  194. primGroupArray[faceGroupLoc].indices = new unsigned short[tempFaces.size() * 3];
  195. primGroupArray[faceGroupLoc].numIndices = (unsigned int)( tempFaces.size() * 3 );
  196. int indexCtr = 0;
  197. for(int i = 0; i < tempFaces.size(); i++)
  198. {
  199. primGroupArray[faceGroupLoc].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v0 );
  200. primGroupArray[faceGroupLoc].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v1 );
  201. primGroupArray[faceGroupLoc].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v2 );
  202. }
  203. }
  204. }
  205. //clean up everything
  206. //delete strips
  207. for(int i = 0; i < tempStrips.size(); i++)
  208. {
  209. for(int j = 0; j < tempStrips[i]->m_faces.size(); j++)
  210. {
  211. delete tempStrips[i]->m_faces[j];
  212. tempStrips[i]->m_faces[j] = NULL;
  213. }
  214. delete tempStrips[i];
  215. tempStrips[i] = NULL;
  216. }
  217. //delete faces
  218. for(int i = 0; i < tempFaces.size(); i++)
  219. {
  220. delete tempFaces[i];
  221. tempFaces[i] = NULL;
  222. }
  223. }
  224. ////////////////////////////////////////////////////////////////////////////////////////
  225. // RemapIndices()
  226. //
  227. // Function to remap your indices to improve spatial locality in your vertex buffer.
  228. //
  229. // in_primGroups: array of PrimitiveGroups you want remapped
  230. // numGroups: number of entries in in_primGroups
  231. // numVerts: number of vertices in your vertex buffer, also can be thought of as the range
  232. // of acceptable values for indices in your primitive groups.
  233. // remappedGroups: array of remapped PrimitiveGroups
  234. //
  235. // Note that, according to the remapping handed back to you, you must reorder your
  236. // vertex buffer.
  237. //
  238. void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups,
  239. const unsigned short numVerts, PrimitiveGroup** remappedGroups)
  240. {
  241. (*remappedGroups) = new PrimitiveGroup[numGroups];
  242. //caches oldIndex --> newIndex conversion
  243. int *indexCache;
  244. indexCache = new int[numVerts];
  245. memset(indexCache, -1, sizeof(int)*numVerts);
  246. //loop over primitive groups
  247. unsigned int indexCtr = 0;
  248. for(int i = 0; i < numGroups; i++)
  249. {
  250. unsigned int numIndices = in_primGroups[i].numIndices;
  251. //init remapped group
  252. (*remappedGroups)[i].type = in_primGroups[i].type;
  253. (*remappedGroups)[i].numIndices = numIndices;
  254. (*remappedGroups)[i].indices = new unsigned short[numIndices];
  255. for(int j = 0; j < numIndices; j++)
  256. {
  257. int cachedIndex = indexCache[in_primGroups[i].indices[j]];
  258. if(cachedIndex == -1) //we haven't seen this index before
  259. {
  260. //point to "last" vertex in VB
  261. (*remappedGroups)[i].indices[j] = AsUShort( indexCtr );
  262. //add to index cache, increment
  263. indexCache[in_primGroups[i].indices[j]] = indexCtr++;
  264. }
  265. else
  266. {
  267. //we've seen this index before
  268. (*remappedGroups)[i].indices[j] = AsUShort( cachedIndex );
  269. }
  270. }
  271. }
  272. delete[] indexCache;
  273. }