1+ #include " driver_routines/models.h"
2+ #include " rendermodel.h"
3+
4+ #include " driver_level.h"
5+ #include " gl_renderer.h"
6+ #include " core/cmdlib.h"
7+ #include " util/DkList.h"
8+ #include < assert.h>
9+
10+ CRenderModel::CRenderModel ()
11+ {
12+ }
13+
14+ CRenderModel::~CRenderModel ()
15+ {
16+ Destroy ();
17+ }
18+
19+ bool CRenderModel::Initialize (ModelRef_t* model)
20+ {
21+ if (!model)
22+ return false ;
23+
24+ if (!model->model )
25+ return false ;
26+
27+ m_sourceModel = model;
28+ GenerateBuffers ();
29+
30+ return true ;
31+ }
32+
33+ void CRenderModel::Destroy ()
34+ {
35+ GR_DestroyVAO (m_vao);
36+ m_vao = nullptr ;
37+ m_sourceModel = nullptr ;
38+ m_batches.clear ();
39+ }
40+
41+ struct vertexTuple_t
42+ {
43+ int flags; // store few face flags here
44+
45+ short grVertexIndex;
46+
47+ short vertexIndex;
48+ short normalIndex; // point normal index
49+ ushort uvs;
50+ };
51+
52+ int FindGrVertexIndex (const DkList<vertexTuple_t>& whereFind, int flags, int vertexIndex, int normalIndex, ushort uvs)
53+ {
54+ for (int i = 0 ; i < whereFind.numElem (); i++)
55+ {
56+ if (whereFind[i].flags != flags)
57+ continue ;
58+
59+ if (flags & FACE_VERT_NORMAL)
60+ {
61+ if (whereFind[i].normalIndex != normalIndex)
62+ continue ;
63+ }
64+
65+ if (flags & FACE_TEXTURED)
66+ {
67+ if (whereFind[i].uvs != uvs)
68+ continue ;
69+ }
70+
71+ if (whereFind[i].vertexIndex == vertexIndex)
72+ return whereFind[i].grVertexIndex ;
73+ }
74+
75+ return -1 ;
76+ }
77+
78+ modelBatch_t* FindBatch (DkList<modelBatch_t*>& batches, int tpageId)
79+ {
80+ for (int i = 0 ; i < batches.numElem (); i++)
81+ {
82+ if (batches[i]->tpage == tpageId)
83+ return batches[i];
84+ }
85+ return nullptr ;
86+ }
87+
88+ void CRenderModel::GenerateBuffers ()
89+ {
90+ DkList<vertexTuple_t> verticesMap;
91+
92+ DkList<GrVertex> vertices;
93+ DkList<int > indices;
94+
95+ MODEL* model = m_sourceModel->model ;
96+ MODEL* vertex_ref = model;
97+
98+ if (model->instance_number > 0 ) // car models have vertex_ref=0
99+ {
100+ ModelRef_t* ref = FindModelByIndex (model->instance_number , m_regModelData);
101+
102+ if (!ref)
103+ {
104+ Msg (" vertex ref not found %d\n " , model->instance_number );
105+ return ;
106+ }
107+
108+ vertex_ref = ref->model ;
109+ }
110+
111+ modelBatch_t* batch = nullptr ;
112+
113+ int modelSize = m_sourceModel->size ;
114+ int face_ofs = 0 ;
115+ dpoly_t dec_face;
116+
117+ // go throught all polygons
118+ for (int i = 0 ; i < model->num_polys ; i++)
119+ {
120+ char * facedata = model->pPolyAt (face_ofs);
121+
122+ // check offset
123+ if ((ubyte*)facedata >= (ubyte*)model + modelSize)
124+ {
125+ MsgError (" poly id=%d type=%d ofs=%d bad offset!\n " , i, *facedata & 31 , model->poly_block + face_ofs);
126+ break ;
127+ }
128+
129+ int poly_size = decode_poly (facedata, &dec_face);
130+
131+ // check poly size
132+ if (poly_size == 0 )
133+ {
134+ MsgError (" poly id=%d type=%d ofs=%d zero size!\n " , i, *facedata & 31 , model->poly_block + face_ofs);
135+ break ;
136+ }
137+
138+ int numPolyVerts = (dec_face.flags & FACE_IS_QUAD) ? 4 : 3 ;
139+ bool bad_face = false ;
140+
141+ // perform vertex checks
142+ for (int v = 0 ; v < numPolyVerts; v++)
143+ {
144+ if (dec_face.vindices [v] >= vertex_ref->num_vertices )
145+ {
146+ bad_face = true ;
147+ break ;
148+ }
149+
150+ // also check normals
151+ if (dec_face.flags & FACE_VERT_NORMAL)
152+ {
153+ if (dec_face.nindices [v] >= vertex_ref->num_point_normals )
154+ {
155+ bad_face = true ;
156+ break ;
157+ }
158+ }
159+ }
160+
161+ if (bad_face)
162+ {
163+ MsgError (" poly id=%d type=%d ofs=%d has invalid indices (or format is unknown)\n " , i, *facedata & 31 , model->poly_block + face_ofs);
164+ face_ofs += poly_size;
165+ continue ;
166+ }
167+
168+ // find or create new batch
169+ int tpageId = (dec_face.flags & FACE_TEXTURED) ? dec_face.page : -1 ;
170+
171+ batch = FindBatch (m_batches, tpageId);
172+ if (!batch)
173+ {
174+ batch = new modelBatch_t;
175+ batch->startIndex = indices.numElem ();
176+ batch->numIndices = 0 ;
177+ batch->tpage = tpageId;
178+
179+ m_batches.append (batch);
180+ }
181+
182+ // Gouraud-shaded poly smoothing
183+ bool smooth = (dec_face.flags & FACE_VERT_NORMAL);
184+
185+ int faceIndices[4 ];
186+
187+ // add vertices and generate faces
188+ for (int v = 0 ; v < numPolyVerts; v++)
189+ {
190+ // NOTE: Vertex indexes is reversed here
191+ #define VERT_IDX numPolyVerts - 1 - v
192+
193+ int vflags = dec_face.flags & ~(FACE_IS_QUAD | FACE_RGB);
194+
195+ // try searching for vertex
196+ int index = FindGrVertexIndex (verticesMap,
197+ vflags,
198+ dec_face.vindices [VERT_IDX],
199+ dec_face.nindices [VERT_IDX],
200+ *(ushort*)dec_face.uv [VERT_IDX]);
201+
202+ // add new vertex
203+ if (index == -1 )
204+ {
205+ GrVertex newVert;
206+ vertexTuple_t vertMap;
207+
208+ vertMap.flags = vflags;
209+ vertMap.normalIndex = -1 ;
210+
211+ // get the vertex
212+ SVECTOR* vert = vertex_ref->pVertex (dec_face.vindices [VERT_IDX]);
213+
214+ (*(Vector3D*)&newVert.vx ) = Vector3D (vert->x * -EXPORT_SCALING, vert->y * -EXPORT_SCALING, vert->z * EXPORT_SCALING);
215+
216+ if (smooth)
217+ {
218+ vertMap.normalIndex = dec_face.nindices [VERT_IDX];
219+
220+ SVECTOR* norm = vertex_ref->pPointNormal (vertMap.normalIndex );
221+ *(Vector3D*)&newVert.nx = Vector3D (norm->x * -EXPORT_SCALING, norm->y * -EXPORT_SCALING, norm->z * EXPORT_SCALING);
222+ }
223+
224+ if (dec_face.flags & FACE_TEXTURED)
225+ {
226+ UV_INFO uv = *(UV_INFO*)dec_face.uv [VERT_IDX];
227+
228+ // map to 0..1
229+ newVert.tc_u = float (uv.u / 2 ) / 128 .0f ; // do /2 and *2 as textures were already 4 bit
230+ newVert.tc_v = float (uv.v ) / 256 .0f ;
231+ }
232+
233+ vertMap.grVertexIndex = vertices.append (newVert);
234+ vertMap.vertexIndex = dec_face.vindices [VERT_IDX];
235+
236+ // add vertex and a map
237+ index = verticesMap.append (vertMap);
238+
239+ // vertices and verticesMap should be equal
240+ _ASSERT (verticesMap.numElem () == vertices.numElem ());
241+ }
242+
243+ // add index
244+ faceIndices[v] = index;
245+ }
246+
247+ // if not gouraud shaded we just compute face normal
248+ // FIXME: make it like game does?
249+ if (!smooth)
250+ {
251+ // it takes only triangle
252+ Vector3D v0 = *(Vector3D*)&vertices[faceIndices[0 ]].vx ;
253+ Vector3D v1 = *(Vector3D*)&vertices[faceIndices[1 ]].vx ;
254+ Vector3D v2 = *(Vector3D*)&vertices[faceIndices[2 ]].vx ;
255+
256+ Vector3D normal = normalize (cross (v2 - v1, v0 - v1));
257+
258+ // set to each vertex
259+ for (int v = 0 ; v < numPolyVerts; v++)
260+ *(Vector3D*)&vertices[faceIndices[0 ]].nx = normal;
261+ }
262+
263+ // triangulate quads
264+ if (numPolyVerts == 4 )
265+ {
266+ indices.append (faceIndices[0 ]);
267+ indices.append (faceIndices[1 ]);
268+ indices.append (faceIndices[2 ]);
269+
270+ indices.append (faceIndices[0 ]);
271+ indices.append (faceIndices[2 ]);
272+ indices.append (faceIndices[3 ]);
273+ batch->numIndices += 6 ;
274+ }
275+ else
276+ {
277+ indices.append (faceIndices[0 ]);
278+ indices.append (faceIndices[1 ]);
279+ indices.append (faceIndices[2 ]);
280+ batch->numIndices += 6 ;
281+ }
282+
283+ face_ofs += poly_size;
284+ }
285+
286+ m_vao = GR_CreateVAO (vertices.numElem (), indices.numElem (), vertices.ptr (), indices.ptr (), 0 );
287+
288+ if (!m_vao)
289+ {
290+ MsgError (" Cannot create Model VAO!\n " );
291+ }
292+ }
293+
294+ void CRenderModel::Draw ()
295+ {
296+ extern TextureID g_hwTexturePages[128 ][32 ];
297+ extern ShaderID g_modelShader;
298+
299+ GR_SetVAO (m_vao);
300+
301+ for (int i = 0 ; i < m_batches.numElem (); i++)
302+ {
303+ modelBatch_t* batch = m_batches[i];
304+ GR_SetShader (g_modelShader);
305+ GR_SetTexture (g_hwTexturePages[batch->tpage ][0 ]);
306+ GR_DrawIndexed (PRIM_TRIANGLES, batch->startIndex , batch->numIndices );
307+ }
308+ }
0 commit comments