meshbuild.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/meshbuild.h $*
  25. * *
  26. * Author:: Greg_h *
  27. * *
  28. * $Modtime:: 1/08/01 10:04a $*
  29. * *
  30. * $Revision:: 1 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #if defined(_MSC_VER)
  36. #pragma once
  37. #endif
  38. #ifndef MESHBUILD_H
  39. #define MESHBUILD_H
  40. #include "always.h"
  41. #include "vector2.h"
  42. #include "vector3.h"
  43. #include "bittype.h"
  44. #include <assert.h>
  45. /*
  46. ** WorldInfoClass
  47. ** Abstract base class that defines an interface for 'world information'.
  48. ** This class provides the mesh builder with information about the world
  49. ** outside of its mesh.
  50. */
  51. class WorldInfoClass
  52. {
  53. public:
  54. WorldInfoClass(void) { }
  55. virtual ~WorldInfoClass(void) { }
  56. // Public methods
  57. virtual Vector3 Get_Shared_Vertex_Normal (Vector3 pos, int smgroup) = 0;
  58. virtual bool Are_Meshes_Smoothed (void) const { return true; }
  59. };
  60. /*
  61. ** MeshBuilderClass
  62. ** This class will process meshes for you, splitting all vertices which do not
  63. ** share all parameters (such as texture coordinates), sort the polygons by
  64. ** material, and put them into strip order.
  65. **
  66. ** To "build" a mesh:
  67. ** 1. Reset the builder with the number of polys you're going to sumbit
  68. ** 2. Enable the vertex channels that you want
  69. ** 3. Submit each face in the form of a FaceClass
  70. ** 4. Call Build_Mesh
  71. **
  72. ** To use the results:
  73. ** 1. Call Get_Vertex_Count and Get_Face_Count to get the counts
  74. ** 2. Loop through the verts, looking at each one using Get_Vertex
  75. ** 3. Loop through the faces, looking at each one using Get_Face
  76. **
  77. ** *NOTE* This class is meant to be relatively self-sufficient. It is used in a
  78. ** variety of different applications which are built on completely different
  79. ** code-bases. Do not introduce dependencies into this module lightly! :-)
  80. */
  81. class MeshBuilderClass
  82. {
  83. public:
  84. enum {
  85. STATE_ACCEPTING_INPUT = 0, // mesh builder is accepting input triangles
  86. STATE_MESH_PROCESSED, // mesh builder has processed the mesh
  87. MAX_PASSES = 4, // maximum number of material passes supported
  88. MAX_STAGES = 2, // maximum number of texture stages supported in a single pass
  89. };
  90. /*
  91. ** Constructor, Destructor
  92. */
  93. MeshBuilderClass(int pass_count=1,int face_count_guess=255,int face_count_growth_rate=64);
  94. ~MeshBuilderClass(void);
  95. /*
  96. ** VertClass. The MeshBuilder deals with vertices in this format.
  97. */
  98. class VertClass
  99. {
  100. public:
  101. VertClass(void) { Reset(); }
  102. void Reset(void);
  103. public:
  104. Vector3 Position; // position of the vertex
  105. Vector3 Normal; // vertex normal (can be calculated by mesh builder)
  106. int SmGroup; // smoothing group of the face this vertex was submitted with
  107. int Id; // id of the vertex, must match for vert to be welded, ok at zero if you don't care
  108. int BoneIndex; // bone influence if the mesh is a skin
  109. int MaxVertColIndex; // Index into the Max mesh.vertCol array of this vertex.
  110. Vector2 TexCoord[MAX_PASSES][MAX_STAGES];
  111. Vector3 DiffuseColor[MAX_PASSES]; // diffuse color
  112. Vector3 SpecularColor[MAX_PASSES]; // specular color
  113. Vector3 DiffuseIllumination[MAX_PASSES]; // pre-calced diffuse illum
  114. float Alpha[MAX_PASSES]; // alpha
  115. int VertexMaterialIndex[MAX_PASSES]; // vertex material index
  116. int Attribute0; // user-set attributes (passed on through...)
  117. int Attribute1; // user-set attributes
  118. // These values are set up by the mesh builder:
  119. int SharedSmGroup; // smooth bits that were on in all faces that contributed to this final vertex
  120. int UniqueIndex; // used internally!
  121. int ShadeIndex; // used internally!
  122. VertClass * NextHash; // used internally!
  123. };
  124. /*
  125. ** FaceClass. The MeshBuilder deals faces in this format. When inputing faces, set the
  126. ** top half of the struct and the builder will fill in the bottom (vertex indices, normal,
  127. ** and distance).
  128. */
  129. class FaceClass
  130. {
  131. public:
  132. FaceClass(void) { Reset(); }
  133. void Reset(void); // reset this face
  134. public:
  135. VertClass Verts[3]; // array of 3 verts
  136. int SmGroup; // smoothing group
  137. int Index; // user-set index of the face
  138. int Attributes; // user-set attributes
  139. int TextureIndex[MAX_PASSES][MAX_STAGES]; // texture to use for each pass
  140. int ShaderIndex[MAX_PASSES]; // shader for each pass
  141. uint32 SurfaceType; // surface type identifier
  142. int AddIndex; // set by builder: index of addition
  143. int VertIdx[3]; // set by builder: "optimized" vertex indices
  144. Vector3 Normal; // set by builder: Face normal
  145. float32 Dist; // set by builder: Plane distance
  146. void Compute_Plane(void);
  147. bool operator != (const FaceClass & that) { return !(*this == that); }
  148. bool operator == (const FaceClass & /*that*/) { return false; }
  149. bool Is_Degenerate(void);
  150. friend class MeshBuilderClass;
  151. };
  152. /*
  153. ** To "build" a mesh:
  154. ** 1. Reset the builder with the approximate number of polys you're going to sumbit, etc.
  155. ** 3. Submit each face in the form of a FaceClass, set only the fields you need (leave others at default)
  156. ** 4. Call Build_Mesh
  157. */
  158. void Reset(int pass_count,int face_count_guess,int face_count_growth_rate);
  159. int Add_Face(const FaceClass & face);
  160. void Build_Mesh(bool compute_normals);
  161. /*
  162. ** Optional controls:
  163. ** If one of your passes has more textures than another, you may wish to do the
  164. ** stripping and sorting based on that channel. By default, everything will
  165. ** be stripped and sorted based on pass 0, stage 0
  166. ** Sort_Vertices can be used to order the vertices arbitrarily. I use it to
  167. ** sort them according to the bone they are attached for skin meshes.
  168. */
  169. void Set_Polygon_Ordering_Channel(int pass,int texstage);
  170. /*
  171. ** To use the results:
  172. ** 1. Call Get_Vertex_Count and Get_Face_Count to get the counts
  173. ** 2. Loop through the verts, looking at each one using Get_Vertex
  174. ** 3. Loop through the faces, looking at each one using Get_Face
  175. */
  176. int Get_Pass_Count(void) const;
  177. int Get_Vertex_Count(void) const;
  178. int Get_Face_Count(void) const;
  179. const VertClass & Get_Vertex(int index) const;
  180. const FaceClass & Get_Face(int index) const;
  181. /*
  182. ** Access to the Vertices and Faces for modifications. This is used by
  183. ** the max plugin when generating a skin mesh for example. Be careful
  184. ** what you do to them. (I haven't thought through all of the
  185. ** possible things you might do to mess up my nice clean mesh...).
  186. */
  187. VertClass & Get_Vertex(int index);
  188. FaceClass & Get_Face(int index);
  189. /*
  190. ** Bounding volume information about the mesh. These functions can compute
  191. ** various types of bounding volumes for the mesh you just processed...
  192. */
  193. void Compute_Bounding_Box(Vector3 * set_min,Vector3 * set_max);
  194. void Compute_Bounding_Sphere(Vector3 * set_center,float * set_radius);
  195. /*
  196. ** World information managment. Used to give the mesh builder information
  197. ** about the world outside of its mesh.
  198. */
  199. WorldInfoClass * Peek_World_Info(void) const { return WorldInfo; }
  200. void Set_World_Info(WorldInfoClass *world_info) { WorldInfo = world_info; }
  201. /*
  202. ** Mesh Stats, mainly lots of flags for whether this mesh has various
  203. ** channels of information.
  204. */
  205. struct MeshStatsStruct
  206. {
  207. void Reset(void);
  208. bool HasTexture[MAX_PASSES][MAX_STAGES]; // has at least one texture in given pass/stage
  209. bool HasShader[MAX_PASSES]; // has at least one shader in given pass
  210. bool HasVertexMaterial[MAX_PASSES]; // has at least one vert material in given pass
  211. bool HasPerPolyTexture[MAX_PASSES][MAX_STAGES]; // has 2+ textures in given pass/stage
  212. bool HasPerPolyShader[MAX_PASSES]; // has 2+ shaders in given pass
  213. bool HasPerVertexMaterial[MAX_PASSES]; // has 2+ vertex materials in given pass
  214. bool HasDiffuseColor[MAX_PASSES]; // has diffuse colors in given pass
  215. bool HasSpecularColor[MAX_PASSES]; // has specular colors in given pass
  216. bool HasDiffuseIllumination[MAX_PASSES]; // has diffuse illum in given pass
  217. bool HasTexCoords[MAX_PASSES][MAX_STAGES]; // has texture coords in given pass
  218. int UVSplitCount; // how many vertices were split due solely to UV discontinuities
  219. int StripCount; // number of strips that were created
  220. int MaxStripLength; // longest strip created
  221. float AvgStripLength; // average strip length
  222. };
  223. const MeshStatsStruct & Get_Mesh_Stats(void) const;
  224. private:
  225. void Free(void);
  226. void Compute_Mesh_Stats(void);
  227. void Optimize_Mesh(bool compute_normals);
  228. void Strip_Optimize_Mesh(void);
  229. void Remove_Degenerate_Faces(void);
  230. void Compute_Face_Normals(void);
  231. bool Verify_Face_Normals(void);
  232. void Compute_Vertex_Normals(void);
  233. void Grow_Face_Array(void);
  234. void Sort_Vertices(void);
  235. /*
  236. ** Winged edge stuff is used by the strip optimize function
  237. */
  238. struct WingedEdgeStruct
  239. {
  240. int MaterialIdx;
  241. WingedEdgeStruct * Next;
  242. int Vertex[2];
  243. int Poly[2];
  244. };
  245. struct WingedEdgePolyStruct
  246. {
  247. WingedEdgeStruct * Edge[3];
  248. };
  249. int State; // is the builder accepting input or already processed the mesh.
  250. int PassCount; // number of render passes for this mesh
  251. int FaceCount; // number of faces
  252. FaceClass * Faces; // array of faces
  253. int InputVertCount; // number of input verts;
  254. int VertCount; // number of verts;
  255. VertClass * Verts; // array of verts;
  256. int CurFace; // current face being added
  257. WorldInfoClass * WorldInfo; // obj containing info about other meshes in the world
  258. MeshStatsStruct Stats; // internally useful junk about the mesh being processed.
  259. int PolyOrderPass; // order the polys using the texture indices in this pass
  260. int PolyOrderStage; // order the polys using the texture indices in this stage
  261. int AllocFaceCount; // number of faces allocated
  262. int AllocFaceGrowth; // growth rate of face array
  263. };
  264. inline void MeshBuilderClass::Set_Polygon_Ordering_Channel(int pass,int texstage)
  265. {
  266. assert(pass >= 0);
  267. assert(pass < MAX_PASSES);
  268. assert(texstage >= 0);
  269. assert(texstage < MAX_STAGES);
  270. PolyOrderPass = pass;
  271. PolyOrderStage = texstage;
  272. }
  273. inline int MeshBuilderClass::Get_Pass_Count(void) const
  274. {
  275. return PassCount;
  276. }
  277. inline int MeshBuilderClass::Get_Vertex_Count(void) const
  278. {
  279. assert(State == STATE_MESH_PROCESSED);
  280. return VertCount;
  281. }
  282. inline int MeshBuilderClass::Get_Face_Count(void) const
  283. {
  284. assert(State == STATE_MESH_PROCESSED);
  285. return FaceCount;
  286. }
  287. inline const MeshBuilderClass::VertClass & MeshBuilderClass::Get_Vertex(int index) const
  288. {
  289. assert(State == STATE_MESH_PROCESSED);
  290. assert(index >= 0);
  291. assert(index < VertCount);
  292. return Verts[index];
  293. }
  294. inline const MeshBuilderClass::FaceClass & MeshBuilderClass::Get_Face(int index) const
  295. {
  296. assert(State == STATE_MESH_PROCESSED);
  297. assert(index >= 0);
  298. assert(index < FaceCount);
  299. return Faces[index];
  300. }
  301. inline MeshBuilderClass::VertClass & MeshBuilderClass::Get_Vertex(int index)
  302. {
  303. assert(State == STATE_MESH_PROCESSED);
  304. assert(index >= 0);
  305. assert(index < VertCount);
  306. return Verts[index];
  307. }
  308. inline MeshBuilderClass::FaceClass & MeshBuilderClass::Get_Face(int index)
  309. {
  310. assert(State == STATE_MESH_PROCESSED);
  311. assert(index >= 0);
  312. assert(index < FaceCount);
  313. return Faces[index];
  314. }
  315. inline const MeshBuilderClass::MeshStatsStruct & MeshBuilderClass::Get_Mesh_Stats(void) const
  316. {
  317. assert(State == STATE_MESH_PROCESSED);
  318. return Stats;
  319. }
  320. #endif