Skip to content

Commit f6feb20

Browse files
committed
- added CRenderModel for drawing MODEL structure
1 parent 91bbba9 commit f6feb20

5 files changed

Lines changed: 361 additions & 2 deletions

File tree

DriverLevelTool/driver_routines/d2_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,11 @@ struct MODEL
259259
}
260260

261261
SVECTOR* pNormal(int i) const
262+
{
263+
return (SVECTOR*)(((ubyte*)this) + normals) + i;
264+
}
265+
266+
SVECTOR* pPointNormal(int i) const
262267
{
263268
return (SVECTOR *)(((ubyte *)this) + point_normals) + i;
264269
}

DriverLevelTool/exporter/export_models.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void WriteMODELToObjStream(IVirtualStream* pStream, MODEL* model, int modelSize,
7171
// store GT3/GT4 vertex normals
7272
for (int i = 0; i < vertex_ref->num_point_normals; i++)
7373
{
74-
SVECTOR* norm = vertex_ref->pNormal(i);
74+
SVECTOR* norm = vertex_ref->pPointNormal(i);
7575
Vector3D sfNorm = Vector3D(norm->x * -EXPORT_SCALING, norm->y * -EXPORT_SCALING, norm->z * EXPORT_SCALING);
7676

7777
pStream->Print("vn %g %g %g\r\n",
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
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+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifndef DRAWMODEL_H
2+
#define DRAWMODEL_H
3+
4+
#include "util/DkList.h"
5+
6+
struct RegionModels_t;
7+
struct ModelRef_t;
8+
struct GrVAO;
9+
10+
struct modelBatch_t
11+
{
12+
int tpage;
13+
int startIndex;
14+
int numIndices;
15+
};
16+
17+
class CRenderModel
18+
{
19+
public:
20+
CRenderModel();
21+
virtual ~CRenderModel();
22+
23+
bool Initialize(ModelRef_t* model);
24+
void Destroy();
25+
26+
void Draw();
27+
28+
protected:
29+
void GenerateBuffers();
30+
31+
RegionModels_t* m_regModelData{ nullptr };
32+
ModelRef_t* m_sourceModel { nullptr };
33+
GrVAO* m_vao { nullptr };
34+
DkList<modelBatch_t*> m_batches;
35+
int m_numVerts;
36+
};
37+
38+
#endif

0 commit comments

Comments
 (0)