Isle
Loading...
Searching...
No Matches
legolod.cpp
Go to the documentation of this file.
1
2#include "legolod.h"
3
4#include "legoroi.h"
6#include "misc/legostorage.h"
7#include "shape/legomesh.h"
8#include "tgl/d3drm/impl.h"
9
13DECOMP_SIZE_ASSERT(LegoLOD::Mesh, 0x08)
14
15// GLOBAL: LEGO1 0x101013d4
16LPDIRECT3DRMMATERIAL g_unk0x101013d4 = NULL;
17
18// GLOBAL: LEGO1 0x101013dc
19const char* g_unk0x101013dc = "inh";
20
21inline IDirect3DRM2* GetD3DRM(Tgl::Renderer* pRenderer);
22inline BOOL GetMeshData(IDirect3DRMMesh*& mesh, D3DRMGROUPINDEX& index, Tgl::Mesh* pMesh);
23
24// FUNCTION: LEGO1 0x100aa380
25LegoLOD::LegoLOD(Tgl::Renderer* p_renderer) : ViewLOD(p_renderer)
26{
27 if (g_unk0x101013d4 == NULL) {
28 GetD3DRM(p_renderer)->CreateMaterial(10.0, &g_unk0x101013d4);
29 }
30
31 m_melems = NULL;
32 m_numMeshes = 0;
33 m_numVertices = 0;
34 m_numPolys = 0;
35 m_meshOffset = 0;
36}
37
38// FUNCTION: LEGO1 0x100aa450
40{
41 if (m_numMeshes && m_melems != NULL) {
42 for (LegoU32 i = 0; i < m_numMeshes; i++) {
43 if (m_melems[i].m_tglMesh != NULL) {
44 delete m_melems[i].m_tglMesh;
46 }
47 }
48 }
49
50 if (m_melems) {
51 delete[] m_melems;
52 }
53}
54
55// FUNCTION: LEGO1 0x100aa510
56LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_textureContainer, LegoStorage* p_storage)
57{
58 float(*normals)[3] = NULL;
59 float(*vertices)[3] = NULL;
60 float(*textureVertices)[2] = NULL;
61 LegoS32 numVerts = 0;
62 LegoS32 numNormals = 0;
63 LegoS32 numTextureVertices = 0;
64 LegoMesh* mesh = NULL;
65 LegoU32(*polyIndices)[3] = NULL;
66 LegoU32(*textureIndices)[3] = NULL;
67 LegoTextureInfo* textureInfo = NULL;
68
69 LegoU32 i, meshUnd1, meshUnd2, tempNumVertsAndNormals;
70 unsigned char paletteEntries[256];
71
72 if (p_storage->Read(&m_unk0x08, sizeof(m_unk0x08)) != SUCCESS) {
73 goto done;
74 }
75
76 if (GetUnknown0x08Test4()) {
77 return SUCCESS;
78 }
79
80 m_meshBuilder = p_renderer->CreateMeshBuilder();
81
82 if (p_storage->Read(&m_numMeshes, sizeof(m_numMeshes)) != SUCCESS) {
83 goto done;
84 }
85
86 if (m_numMeshes == 0) {
88 return SUCCESS;
89 }
90
92
94 memset(m_melems, 0, sizeof(*m_melems) * m_numMeshes);
95
96 meshUnd1 = m_numMeshes - 1;
97 meshUnd2 = 0;
98
99 if (p_storage->Read(&tempNumVertsAndNormals, sizeof(tempNumVertsAndNormals)) != SUCCESS) {
100 goto done;
101 }
102
103 numVerts = *((LegoU16*) &tempNumVertsAndNormals) & MAXSHORT;
104 numNormals = (*((LegoU16*) &tempNumVertsAndNormals + 1) >> 1) & MAXSHORT;
105
106 if (p_storage->Read(&numTextureVertices, sizeof(numTextureVertices)) != SUCCESS) {
107 goto done;
108 }
109
110 if (numVerts > 0) {
111 vertices = new float[numVerts][sizeOfArray(*vertices)];
112 if (p_storage->Read(vertices, numVerts * sizeof(*vertices)) != SUCCESS) {
113 goto done;
114 }
115 }
116
117 if (numNormals > 0) {
118 normals = new float[numNormals][sizeOfArray(*normals)];
119 if (p_storage->Read(normals, numNormals * sizeof(*normals)) != SUCCESS) {
120 goto done;
121 }
122 }
123
124 if (numTextureVertices > 0) {
125 textureVertices = new float[numTextureVertices][sizeOfArray(*textureVertices)];
126 if (p_storage->Read(textureVertices, numTextureVertices * sizeof(*textureVertices)) != SUCCESS) {
127 goto done;
128 }
129 }
130
131 for (i = 0; i < m_numMeshes; i++) {
132 LegoU32 numPolys, numVertices, numTextureIndices, meshIndex;
133 const LegoChar *textureName, *materialName;
134 Tgl::ShadingModel shadingModel;
135
136 if (p_storage->Read(&numPolys, 2) != SUCCESS) {
137 goto done;
138 }
139
140 m_numPolys += numPolys & USHRT_MAX;
141
142 if (p_storage->Read(&numVertices, 2) != SUCCESS) {
143 goto done;
144 }
145
146 polyIndices = new LegoU32[numPolys & USHRT_MAX][sizeOfArray(*polyIndices)];
147 if (p_storage->Read(polyIndices, (numPolys & USHRT_MAX) * sizeof(*polyIndices)) != SUCCESS) {
148 goto done;
149 }
150
151 if (p_storage->Read(&numTextureIndices, sizeof(numTextureIndices)) != SUCCESS) {
152 goto done;
153 }
154
155 if (numTextureIndices > 0) {
156 textureIndices = new LegoU32[numPolys & USHRT_MAX][sizeOfArray(*textureIndices)];
157 if (p_storage->Read(textureIndices, (numPolys & USHRT_MAX) * sizeof(*textureIndices)) != SUCCESS) {
158 goto done;
159 }
160 }
161 else {
162 textureIndices = NULL;
163 }
164
165 mesh = new LegoMesh();
166
167 if (mesh->Read(p_storage) != SUCCESS) {
168 goto done;
169 }
170
171 switch (mesh->GetShading()) {
172 case LegoMesh::e_flat:
173 shadingModel = Tgl::Flat;
174 break;
176 shadingModel = Tgl::Wireframe;
177 break;
178 default:
179 shadingModel = Tgl::Gouraud;
180 }
181
182 m_numVertices += numVertices & USHRT_MAX;
183
184 textureName = mesh->GetTextureName();
185 materialName = mesh->GetMaterialName();
186
187 if (FUN_100aae20(textureName) || FUN_100aae20(materialName)) {
188 meshIndex = meshUnd1;
189 meshUnd1--;
190 }
191 else {
192 meshIndex = meshUnd2;
193 meshUnd2++;
194 }
195
197 numPolys & USHRT_MAX,
198 numVertices & USHRT_MAX,
199 vertices,
200 normals,
201 textureVertices,
202 polyIndices,
203 textureIndices,
204 shadingModel
205 );
206
207 if (m_melems[meshIndex].m_tglMesh == NULL) {
208 goto done;
209 }
210
211 m_melems[meshIndex].m_tglMesh->SetShadingModel(shadingModel);
212
213 if (textureName != NULL) {
214 if (mesh->GetUnknown0x21()) {
215 LegoROI::GetPaletteEntries(textureName, paletteEntries, sizeOfArray(paletteEntries));
216 }
217
218 textureInfo = p_textureContainer->Get(mesh->GetTextureName());
219
220 if (textureInfo == NULL) {
221 goto done;
222 }
223
224 m_melems[meshIndex].m_tglMesh->SetColor(1.0F, 1.0F, 1.0F, 0.0F);
225 LegoTextureInfo::SetGroupTexture(m_melems[meshIndex].m_tglMesh, textureInfo);
226 m_melems[meshIndex].m_unk0x04 = TRUE;
227 }
228 else {
229 LegoFloat red = 1.0F;
230 LegoFloat green = 0.0F;
231 LegoFloat blue = 1.0F;
232 LegoFloat alpha = 0.0F;
233
234 if (mesh->GetUnknown0x21()) {
235 LegoROI::GetRGBAColor(materialName, red, green, blue, alpha);
236 }
237 else {
238 red = mesh->GetColor().GetRed() / 255.0;
239 green = mesh->GetColor().GetGreen() / 255.0;
240 blue = mesh->GetColor().GetBlue() / 255.0;
241 alpha = mesh->GetAlpha();
242 }
243
244 m_melems[meshIndex].m_tglMesh->SetColor(red, green, blue, alpha);
245 }
246
247 if (mesh->GetUnknown0x0d() > 0) {
248 IDirect3DRMMesh* mesh;
249 D3DRMGROUPINDEX index;
250 GetMeshData(mesh, index, m_melems[meshIndex].m_tglMesh);
251 mesh->SetGroupMaterial(index, g_unk0x101013d4);
252 }
253
254 if (mesh != NULL) {
255 delete mesh;
256 mesh = NULL;
257 }
258 if (polyIndices != NULL) {
259 delete[] polyIndices;
260 polyIndices = NULL;
261 }
262 if (textureIndices != NULL) {
263 delete[] textureIndices;
264 textureIndices = NULL;
265 }
266 }
267
268 m_meshOffset = meshUnd2;
269
270 if (textureVertices != NULL) {
271 delete[] textureVertices;
272 }
273 if (normals != NULL) {
274 delete[] normals;
275 }
276 if (vertices != NULL) {
277 delete[] vertices;
278 }
279
280 return SUCCESS;
281
282done:
283 if (normals != NULL) {
284 delete[] normals;
285 }
286 if (vertices != NULL) {
287 delete[] vertices;
288 }
289 if (textureVertices != NULL) {
290 delete[] textureVertices;
291 }
292 if (mesh != NULL) {
293 delete mesh;
294 }
295 if (polyIndices != NULL) {
296 delete[] polyIndices;
297 }
298 if (textureIndices != NULL) {
299 delete[] textureIndices;
300 }
301
302 return FAILURE;
303}
304
305// FUNCTION: LEGO1 0x100aabb0
307{
308 LegoLOD* dupLod = new LegoLOD(p_renderer);
309
310 dupLod->m_meshBuilder = m_meshBuilder->Clone();
311 dupLod->m_melems = new Mesh[m_numMeshes];
312
313 for (LegoU32 i = 0; i < m_numMeshes; i++) {
315 dupLod->m_melems[i].m_unk0x04 = m_melems[i].m_unk0x04;
316 }
317
318 dupLod->m_unk0x08 = m_unk0x08;
319 dupLod->m_numMeshes = m_numMeshes;
321 dupLod->m_numPolys = m_numPolys;
322 dupLod->m_meshOffset = m_meshOffset;
323
324 return dupLod;
325}
326
327// FUNCTION: LEGO1 0x100aacb0
329{
330 for (LegoU32 i = m_meshOffset; i < m_numMeshes; i++) {
331 if (!m_melems[i].m_unk0x04) {
332 m_melems[i].m_tglMesh->SetColor(p_red, p_green, p_blue, p_alpha);
333 }
334 }
335
336 return SUCCESS;
337}
338
339// FUNCTION: LEGO1 0x100aad00
341{
342 for (LegoU32 i = m_meshOffset; i < m_numMeshes; i++) {
343 if (m_melems[i].m_unk0x04) {
344 LegoTextureInfo::SetGroupTexture(m_melems[i].m_tglMesh, p_textureInfo);
345 m_melems[i].m_tglMesh->SetColor(1.0F, 1.0F, 1.0F, 0.0F);
347 }
348 }
349
350 return SUCCESS;
351}
352
353// FUNCTION: LEGO1 0x100aad70
355{
356 for (LegoU32 i = m_meshOffset; i < m_numMeshes; i++) {
357 if (m_melems[i].m_unk0x04) {
358 LegoTextureInfo::SetGroupTexture(m_melems[i].m_tglMesh, p_textureInfo);
359 }
360 }
361
362 return SUCCESS;
363}
364
365// FUNCTION: LEGO1 0x100aadc0
367{
368 for (LegoU32 i = m_meshOffset; i < m_numMeshes; i++) {
369 if (m_melems[i].m_unk0x04) {
370 if (LegoTextureInfo::GetGroupTexture(m_melems[i].m_tglMesh, p_textureInfo) == TRUE) {
371 return SUCCESS;
372 }
373 }
374 }
375
376 return FAILURE;
377}
378
379// FUNCTION: LEGO1 0x100aae20
381{
382 if (p_name != NULL) {
383 if (!strnicmp(p_name, g_unk0x101013dc, strlen(g_unk0x101013dc))) {
384 return TRUE;
385 }
386 }
387
388 return FALSE;
389}
390
391// FUNCTION: LEGO1 0x100aae60
392// FUNCTION: BETA10 0x1018e50f
394{
395 m_meshOffset = 0;
396}
397
398inline BOOL GetMeshData(IDirect3DRMMesh*& mesh, D3DRMGROUPINDEX& index, Tgl::Mesh* pMesh)
399{
400 mesh = ((TglImpl::MeshImpl*) pMesh)->ImplementationData()->groupMesh;
401 index = ((TglImpl::MeshImpl*) pMesh)->ImplementationData()->groupIndex;
402 return FALSE;
403}
404
405inline IDirect3DRM2* GetD3DRM(Tgl::Renderer* pRenderer)
406{
407 return ((TglImpl::RendererImpl*) pRenderer)->ImplementationData();
408}
[AI] Abstract base class for a Level-of-Detail (LOD) variant of a geometric object.
Definition: roi.h:97
LegoU8 GetRed()
Get the red channel value.
Definition: legocolor.h:18
LegoU8 GetGreen()
Get the green channel value.
Definition: legocolor.h:26
LegoU8 GetBlue()
Get the blue channel value.
Definition: legocolor.h:34
T * Get(const char *p_name)
Retrieve the element mapped to the given name, or nullptr if missing.
Definition: legocontainer.h:92
[AI] Level-Of-Detail (LOD) object used for rendering and managing polygonal mesh data with LOD switch...
Definition: legolod.h:27
LegoResult FUN_100aad70(LegoTextureInfo *p_textureInfo)
[AI] Assigns the group texture to all textured meshes, but does NOT override mesh color.
Definition: legolod.cpp:354
void ClearMeshOffset()
[AI] Reset mesh offset index to start at 0, affecting which meshes are updated by future color/textur...
Definition: legolod.cpp:393
LegoU32 m_numPolys
Total number of polygons (faces) across all meshes (NumPolys implementation). [AI].
Definition: legolod.h:150
LegoU32 m_meshOffset
Internal mesh starting index for iteration; used for color/texture selective assignment....
Definition: legolod.h:151
~LegoLOD() override
[AI] Destructor.
Definition: legolod.cpp:39
LegoLOD * Clone(Tgl::Renderer *p_renderer)
[AI] Create an exact copy of this LOD, including cloned meshes, for another (or the same) renderer.
Definition: legolod.cpp:306
LegoResult SetTextureInfo(LegoTextureInfo *p_textureInfo)
[AI] Assigns the same texture group to all textured meshes in this LOD.
Definition: legolod.cpp:340
LegoResult SetColor(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha)
[AI] Overrides the color of all non-textured mesh parts for this LOD.
Definition: legolod.cpp:328
LegoResult GetTextureInfo(LegoTextureInfo *&p_textureInfo)
[AI] Retrieves the texture info/group of the first mesh with group texture in this LOD.
Definition: legolod.cpp:366
LegoU32 m_numVertices
Total number of vertices across all mesh parts. Used for stats and validation. [AI].
Definition: legolod.h:149
LegoResult Read(Tgl::Renderer *p_renderer, LegoTextureContainer *p_textureContainer, LegoStorage *p_storage)
[AI] Load LOD geometry and material info from storage, building Tgl::Mesh group(s).
Definition: legolod.cpp:56
static LegoBool FUN_100aae20(const LegoChar *p_name)
[AI] Helper to check if a mesh/material name matches the "inh" group, which separates non-inheritable...
Definition: legolod.cpp:380
LegoU32 m_numMeshes
Number of sub-meshes held in m_melems. [AI].
Definition: legolod.h:148
Mesh * m_melems
Array of mesh struct objects representing all mesh parts that make up this LOD. [AI].
Definition: legolod.h:147
[AI] Represents the rendering attributes and state of a LEGO mesh, including color,...
Definition: legomesh.h:51
LegoFloat GetAlpha()
[AI] Gets the mesh's transparency alpha value.
Definition: legomesh.h:81
@ e_flat
[AI] Use flat shading (per-polygon color).
Definition: legomesh.h:58
@ e_wireframe
[AI] Use wireframe rendering.
Definition: legomesh.h:60
LegoResult Read(LegoStorage *p_storage)
[AI] Reads mesh properties (color, alpha, shading, flags, names) from the given storage stream.
Definition: legomesh.cpp:39
LegoU8 GetUnknown0x0d()
[AI] Returns the value of an unknown flag or property at offset 0x0d.
Definition: legomesh.h:99
LegoColor GetColor()
[AI] Returns the mesh's primary color.
Definition: legomesh.h:69
LegoU8 GetShading()
[AI] Gets the shading mode of the mesh.
Definition: legomesh.h:87
LegoBool GetUnknown0x21()
[AI] Returns the value of an unknown boolean at offset 0x21.
Definition: legomesh.h:117
const LegoChar * GetTextureName()
[AI] Returns the texture resource name associated with the mesh.
Definition: legomesh.h:105
const LegoChar * GetMaterialName()
[AI] Returns the material resource name for the mesh.
Definition: legomesh.h:111
static LegoBool GetPaletteEntries(const LegoChar *p_name, unsigned char *paletteEntries, LegoU32 p_numEntries)
[AI] [Static] Fetches palette entries for a named texture using current texture handler.
Definition: legoroi.cpp:792
static LegoBool GetRGBAColor(const LegoChar *p_name, float &p_red, float &p_green, float &p_blue, float &p_alpha)
[AI] [Static] Resolves a logical color alias into RGBA floats.
Definition: legoroi.cpp:758
Abstract base class providing an interface for file-like storage with binary and text read/write oper...
Definition: legostorage.h:16
virtual LegoResult Read(void *p_buffer, LegoU32 p_size)=0
Read bytes from storage into buffer.
Specialized LegoContainer handling LegoTextureInfo objects and their DirectDraw/Direct3D caching.
[AI] Contains DirectDraw and Direct3DRM handles and metadata for a texture used in the LEGO Island re...
static BOOL GetGroupTexture(Tgl::Mesh *pMesh, LegoTextureInfo *&p_textureInfo)
[AI] Retrieves the LegoTextureInfo currently attached to the supplied mesh group.
static BOOL SetGroupTexture(Tgl::Mesh *pMesh, LegoTextureInfo *p_textureInfo)
[AI] Assigns a Direct3DRM texture group from a LegoTextureInfo to a mesh group via the Tgl/Microsoft ...
[AI] Implementation of Tgl::Mesh, manages a mesh object and geometry data with group index [AI]
Definition: impl.h:816
[AI] Implements Tgl::MeshBuilder; facilitates mesh construction [AI]
Definition: impl.h:55
virtual MeshBuilder * Clone()=0
[AI] Makes a copy of the mesh builder instance (deep copy).
virtual Mesh * CreateMesh(unsigned long faceCount, unsigned long vertexCount, float(*pPositions)[3], float(*pNormals)[3], float(*pTextureCoordinates)[2], unsigned long(*pFaceIndices)[3], unsigned long(*pTextureIndices)[3], ShadingModel shadingModel)=0
[AI] Creates a mesh from supplied geometry data.
[AI] Represents a renderable 3D mesh.
Definition: tgl.h:596
virtual Result SetShadingModel(ShadingModel)=0
[AI] Sets the mesh's shading model (e.g., Gouraud, Phong).
virtual Mesh * ShallowClone(MeshBuilder *)=0
[AI] Performs a shallow clone—new wrapper, same mesh data.
virtual Result SetColor(float r, float g, float b, float a)=0
[AI] Sets the color and transparency for the mesh.
[AI] Main interface/factory for rendering resources and scene graphs.
Definition: tgl.h:188
virtual MeshBuilder * CreateMeshBuilder()=0
[AI] Creates a new mesh builder.
[AI] Represents a Level of Detail (LOD) object for rendering, implemented with a mesh builder and sup...
Definition: viewlod.h:20
Tgl::MeshBuilder * m_meshBuilder
[AI] Points to a mesh builder instance for constructing or managing polygonal mesh data for this LOD.
Definition: viewlod.h:102
@ c_bit4
[AI] Flag value for bit 4 mask operation.
Definition: viewlod.h:23
void ClearFlag(unsigned char p_flag)
[AI] Clears a given flag in the internal flags (m_unk0x08) using bitwise AND with negated p_flag.
Definition: viewlod.h:93
undefined4 m_unk0x08
[AI] Internal bitfield for flag/status storage controlling LOD state and behavior.
Definition: viewlod.h:107
void SetFlag(unsigned char p_flag)
[AI] Sets a given flag in the internal flags (m_unk0x08) using bitwise OR.
Definition: viewlod.h:87
unsigned char GetUnknown0x08Test4()
[AI] Performs a bitwise AND (mask) with value 0xffffff04 on the internal flag, returning result as an...
Definition: viewlod.h:74
#define TRUE
Definition: d3drmdef.h:28
#define FALSE
Definition: d3drmdef.h:27
LONG D3DRMGROUPINDEX
Definition: d3drmdef.h:334
#define DECOMP_SIZE_ASSERT(T, S)
Definition: decomp.h:19
#define sizeOfArray(arr)
Definition: decomp.h:23
typedef BOOL(FAR PASCAL *LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA
BOOL GetMeshData(IDirect3DRMMesh *&mesh, D3DRMGROUPINDEX &index, Tgl::Mesh *pMesh)
Definition: legolod.cpp:398
const char * g_unk0x101013dc
Definition: legolod.cpp:19
LPDIRECT3DRMMATERIAL g_unk0x101013d4
Definition: legolod.cpp:16
IDirect3DRM2 * GetD3DRM(Tgl::Renderer *pRenderer)
Definition: legolod.cpp:405
#define NULL
[AI] Null pointer value (C/C++ semantics).
Definition: legotypes.h:26
unsigned long LegoU32
[AI] Unsigned 32-bit integer type for cross-platform compatibility.
Definition: legotypes.h:71
char LegoChar
[AI] Alias for char, for use in character/byte data and string handling.
Definition: legotypes.h:83
#define FAILURE
[AI] Used to indicate a failed operation in result codes.
Definition: legotypes.h:34
LegoS32 LegoResult
[AI] Function result type (return code): typically SUCCESS (0) or FAILURE (-1).
Definition: legotypes.h:101
long LegoS32
[AI] Signed 32-bit integer type for cross-platform compatibility.
Definition: legotypes.h:65
#define SUCCESS
[AI] Used to indicate a successful operation in result codes.
Definition: legotypes.h:30
unsigned short LegoU16
[AI] Unsigned 16-bit integer type for cross-platform compatibility.
Definition: legotypes.h:59
float LegoFloat
[AI] Floating point type used throughout LEGO Island.
Definition: legotypes.h:77
LegoU8 LegoBool
[AI] Boolean value used throughout the codebase.
Definition: legotypes.h:89
[AI] Namespace containing all classes related to the 3D graphics abstraction/rendering engine.
ShadingModel
[AI] Represents shading models available for rendering geometry.
Definition: tgl.h:29
@ Flat
[AI] Flat shaded, possibly single color per polygon with lighting. [AI]
Definition: tgl.h:32
@ Gouraud
[AI] Gouraud (vertex-interpolated) shading. [AI]
Definition: tgl.h:33
@ Wireframe
[AI] No shading; renders only mesh edges. [AI]
Definition: tgl.h:30
[AI] Structure representing a sub-mesh and its texturization flag.
Definition: legolod.h:36
BOOL m_unk0x04
Indicates if this mesh has a texture group assigned (TRUE = textured). [AI].
Definition: legolod.h:38
Tgl::Mesh * m_tglMesh
Pointer to the mesh object for rendering. [AI].
Definition: legolod.h:37