mirror of
				https://github.com/isledecomp/isle.git
				synced 2025-10-28 19:04:06 +00:00 
			
		
		
		
	 5fd5a4cec0
			
		
	
	5fd5a4cec0
	
	
	
		
			
			* Clear unknowns in LegoROI and related classes * Update names * Consistently naming: `GetTextureInfo` --------- Co-authored-by: Christian Semmler <mail@csemmler.com>
		
			
				
	
	
		
			409 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			409 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
 | |
| #include "legolod.h"
 | |
| 
 | |
| #include "legoroi.h"
 | |
| #include "misc/legocontainer.h"
 | |
| #include "misc/legostorage.h"
 | |
| #include "shape/legomesh.h"
 | |
| #include "tgl/d3drm/impl.h"
 | |
| 
 | |
| DECOMP_SIZE_ASSERT(LODObject, 0x04)
 | |
| DECOMP_SIZE_ASSERT(ViewLOD, 0x0c)
 | |
| DECOMP_SIZE_ASSERT(LegoLOD, 0x20)
 | |
| DECOMP_SIZE_ASSERT(LegoLOD::Mesh, 0x08)
 | |
| 
 | |
| // GLOBAL: LEGO1 0x101013d4
 | |
| LPDIRECT3DRMMATERIAL g_unk0x101013d4 = NULL;
 | |
| 
 | |
| // GLOBAL: LEGO1 0x101013dc
 | |
| const char* g_unk0x101013dc = "inh";
 | |
| 
 | |
| inline IDirect3DRM2* GetD3DRM(Tgl::Renderer* pRenderer);
 | |
| inline BOOL GetMeshData(IDirect3DRMMesh*& mesh, D3DRMGROUPINDEX& index, Tgl::Mesh* pMesh);
 | |
| 
 | |
| // FUNCTION: LEGO1 0x100aa380
 | |
| LegoLOD::LegoLOD(Tgl::Renderer* p_renderer) : ViewLOD(p_renderer)
 | |
| {
 | |
| 	if (g_unk0x101013d4 == NULL) {
 | |
| 		GetD3DRM(p_renderer)->CreateMaterial(10.0, &g_unk0x101013d4);
 | |
| 	}
 | |
| 
 | |
| 	m_melems = NULL;
 | |
| 	m_numMeshes = 0;
 | |
| 	m_numVertices = 0;
 | |
| 	m_numPolys = 0;
 | |
| 	m_meshOffset = 0;
 | |
| }
 | |
| 
 | |
| // FUNCTION: LEGO1 0x100aa450
 | |
| LegoLOD::~LegoLOD()
 | |
| {
 | |
| 	if (m_numMeshes && m_melems != NULL) {
 | |
| 		for (LegoU32 i = 0; i < m_numMeshes; i++) {
 | |
| 			if (m_melems[i].m_tglMesh != NULL) {
 | |
| 				delete m_melems[i].m_tglMesh;
 | |
| 				m_melems[i].m_tglMesh = NULL;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (m_melems) {
 | |
| 		delete[] m_melems;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // FUNCTION: LEGO1 0x100aa510
 | |
| LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_textureContainer, LegoStorage* p_storage)
 | |
| {
 | |
| 	float(*normals)[3] = NULL;
 | |
| 	float(*vertices)[3] = NULL;
 | |
| 	float(*textureVertices)[2] = NULL;
 | |
| 	LegoS32 numVerts = 0;
 | |
| 	LegoS32 numNormals = 0;
 | |
| 	LegoS32 numTextureVertices = 0;
 | |
| 	LegoMesh* mesh = NULL;
 | |
| 	LegoU32(*polyIndices)[3] = NULL;
 | |
| 	LegoU32(*textureIndices)[3] = NULL;
 | |
| 	LegoTextureInfo* textureInfo = NULL;
 | |
| 
 | |
| 	LegoU32 i, meshUnd1, meshUnd2, tempNumVertsAndNormals;
 | |
| 	unsigned char paletteEntries[256];
 | |
| 
 | |
| 	if (p_storage->Read(&m_unk0x08, sizeof(m_unk0x08)) != SUCCESS) {
 | |
| 		goto done;
 | |
| 	}
 | |
| 
 | |
| 	if (GetUnknown0x08Test4()) {
 | |
| 		return SUCCESS;
 | |
| 	}
 | |
| 
 | |
| 	m_meshBuilder = p_renderer->CreateMeshBuilder();
 | |
| 
 | |
| 	if (p_storage->Read(&m_numMeshes, sizeof(m_numMeshes)) != SUCCESS) {
 | |
| 		goto done;
 | |
| 	}
 | |
| 
 | |
| 	if (m_numMeshes == 0) {
 | |
| 		ClearFlag(c_bit4);
 | |
| 		return SUCCESS;
 | |
| 	}
 | |
| 
 | |
| 	SetFlag(c_bit4);
 | |
| 
 | |
| 	m_melems = new Mesh[m_numMeshes];
 | |
| 	memset(m_melems, 0, sizeof(*m_melems) * m_numMeshes);
 | |
| 
 | |
| 	meshUnd1 = m_numMeshes - 1;
 | |
| 	meshUnd2 = 0;
 | |
| 
 | |
| 	if (p_storage->Read(&tempNumVertsAndNormals, sizeof(tempNumVertsAndNormals)) != SUCCESS) {
 | |
| 		goto done;
 | |
| 	}
 | |
| 
 | |
| 	numVerts = *((LegoU16*) &tempNumVertsAndNormals) & MAXSHORT;
 | |
| 	numNormals = (*((LegoU16*) &tempNumVertsAndNormals + 1) >> 1) & MAXSHORT;
 | |
| 
 | |
| 	if (p_storage->Read(&numTextureVertices, sizeof(numTextureVertices)) != SUCCESS) {
 | |
| 		goto done;
 | |
| 	}
 | |
| 
 | |
| 	if (numVerts > 0) {
 | |
| 		vertices = new float[numVerts][sizeOfArray(*vertices)];
 | |
| 		if (p_storage->Read(vertices, numVerts * sizeof(*vertices)) != SUCCESS) {
 | |
| 			goto done;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (numNormals > 0) {
 | |
| 		normals = new float[numNormals][sizeOfArray(*normals)];
 | |
| 		if (p_storage->Read(normals, numNormals * sizeof(*normals)) != SUCCESS) {
 | |
| 			goto done;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (numTextureVertices > 0) {
 | |
| 		textureVertices = new float[numTextureVertices][sizeOfArray(*textureVertices)];
 | |
| 		if (p_storage->Read(textureVertices, numTextureVertices * sizeof(*textureVertices)) != SUCCESS) {
 | |
| 			goto done;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	for (i = 0; i < m_numMeshes; i++) {
 | |
| 		LegoU32 numPolys, numVertices, numTextureIndices, meshIndex;
 | |
| 		const LegoChar *textureName, *materialName;
 | |
| 		Tgl::ShadingModel shadingModel;
 | |
| 
 | |
| 		if (p_storage->Read(&numPolys, 2) != SUCCESS) {
 | |
| 			goto done;
 | |
| 		}
 | |
| 
 | |
| 		m_numPolys += numPolys & USHRT_MAX;
 | |
| 
 | |
| 		if (p_storage->Read(&numVertices, 2) != SUCCESS) {
 | |
| 			goto done;
 | |
| 		}
 | |
| 
 | |
| 		polyIndices = new LegoU32[numPolys & USHRT_MAX][sizeOfArray(*polyIndices)];
 | |
| 		if (p_storage->Read(polyIndices, (numPolys & USHRT_MAX) * sizeof(*polyIndices)) != SUCCESS) {
 | |
| 			goto done;
 | |
| 		}
 | |
| 
 | |
| 		if (p_storage->Read(&numTextureIndices, sizeof(numTextureIndices)) != SUCCESS) {
 | |
| 			goto done;
 | |
| 		}
 | |
| 
 | |
| 		if (numTextureIndices > 0) {
 | |
| 			textureIndices = new LegoU32[numPolys & USHRT_MAX][sizeOfArray(*textureIndices)];
 | |
| 			if (p_storage->Read(textureIndices, (numPolys & USHRT_MAX) * sizeof(*textureIndices)) != SUCCESS) {
 | |
| 				goto done;
 | |
| 			}
 | |
| 		}
 | |
| 		else {
 | |
| 			textureIndices = NULL;
 | |
| 		}
 | |
| 
 | |
| 		mesh = new LegoMesh();
 | |
| 
 | |
| 		if (mesh->Read(p_storage) != SUCCESS) {
 | |
| 			goto done;
 | |
| 		}
 | |
| 
 | |
| 		switch (mesh->GetShading()) {
 | |
| 		case LegoMesh::e_flat:
 | |
| 			shadingModel = Tgl::Flat;
 | |
| 			break;
 | |
| 		case LegoMesh::e_wireframe:
 | |
| 			shadingModel = Tgl::Wireframe;
 | |
| 			break;
 | |
| 		default:
 | |
| 			shadingModel = Tgl::Gouraud;
 | |
| 		}
 | |
| 
 | |
| 		m_numVertices += numVertices & USHRT_MAX;
 | |
| 
 | |
| 		textureName = mesh->GetTextureName();
 | |
| 		materialName = mesh->GetMaterialName();
 | |
| 
 | |
| 		if (FUN_100aae20(textureName) || FUN_100aae20(materialName)) {
 | |
| 			meshIndex = meshUnd1;
 | |
| 			meshUnd1--;
 | |
| 		}
 | |
| 		else {
 | |
| 			meshIndex = meshUnd2;
 | |
| 			meshUnd2++;
 | |
| 		}
 | |
| 
 | |
| 		m_melems[meshIndex].m_tglMesh = m_meshBuilder->CreateMesh(
 | |
| 			numPolys & USHRT_MAX,
 | |
| 			numVertices & USHRT_MAX,
 | |
| 			vertices,
 | |
| 			normals,
 | |
| 			textureVertices,
 | |
| 			polyIndices,
 | |
| 			textureIndices,
 | |
| 			shadingModel
 | |
| 		);
 | |
| 
 | |
| 		if (m_melems[meshIndex].m_tglMesh == NULL) {
 | |
| 			goto done;
 | |
| 		}
 | |
| 
 | |
| 		m_melems[meshIndex].m_tglMesh->SetShadingModel(shadingModel);
 | |
| 
 | |
| 		if (textureName != NULL) {
 | |
| 			if (mesh->GetUnknown0x21()) {
 | |
| 				LegoROI::GetPaletteEntries(textureName, paletteEntries, sizeOfArray(paletteEntries));
 | |
| 			}
 | |
| 
 | |
| 			textureInfo = p_textureContainer->Get(mesh->GetTextureName());
 | |
| 
 | |
| 			if (textureInfo == NULL) {
 | |
| 				goto done;
 | |
| 			}
 | |
| 
 | |
| 			m_melems[meshIndex].m_tglMesh->SetColor(1.0F, 1.0F, 1.0F, 0.0F);
 | |
| 			LegoTextureInfo::SetGroupTexture(m_melems[meshIndex].m_tglMesh, textureInfo);
 | |
| 			m_melems[meshIndex].m_unk0x04 = TRUE;
 | |
| 		}
 | |
| 		else {
 | |
| 			LegoFloat red = 1.0F;
 | |
| 			LegoFloat green = 0.0F;
 | |
| 			LegoFloat blue = 1.0F;
 | |
| 			LegoFloat alpha = 0.0F;
 | |
| 
 | |
| 			if (mesh->GetUnknown0x21()) {
 | |
| 				LegoROI::GetRGBAColor(materialName, red, green, blue, alpha);
 | |
| 			}
 | |
| 			else {
 | |
| 				red = mesh->GetColor().GetRed() / 255.0;
 | |
| 				green = mesh->GetColor().GetGreen() / 255.0;
 | |
| 				blue = mesh->GetColor().GetBlue() / 255.0;
 | |
| 				alpha = mesh->GetAlpha();
 | |
| 			}
 | |
| 
 | |
| 			m_melems[meshIndex].m_tglMesh->SetColor(red, green, blue, alpha);
 | |
| 		}
 | |
| 
 | |
| 		if (mesh->GetUnknown0x0d() > 0) {
 | |
| 			IDirect3DRMMesh* mesh;
 | |
| 			D3DRMGROUPINDEX index;
 | |
| 			GetMeshData(mesh, index, m_melems[meshIndex].m_tglMesh);
 | |
| 			mesh->SetGroupMaterial(index, g_unk0x101013d4);
 | |
| 		}
 | |
| 
 | |
| 		if (mesh != NULL) {
 | |
| 			delete mesh;
 | |
| 			mesh = NULL;
 | |
| 		}
 | |
| 		if (polyIndices != NULL) {
 | |
| 			delete[] polyIndices;
 | |
| 			polyIndices = NULL;
 | |
| 		}
 | |
| 		if (textureIndices != NULL) {
 | |
| 			delete[] textureIndices;
 | |
| 			textureIndices = NULL;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	m_meshOffset = meshUnd2;
 | |
| 
 | |
| 	if (textureVertices != NULL) {
 | |
| 		delete[] textureVertices;
 | |
| 	}
 | |
| 	if (normals != NULL) {
 | |
| 		delete[] normals;
 | |
| 	}
 | |
| 	if (vertices != NULL) {
 | |
| 		delete[] vertices;
 | |
| 	}
 | |
| 
 | |
| 	return SUCCESS;
 | |
| 
 | |
| done:
 | |
| 	if (normals != NULL) {
 | |
| 		delete[] normals;
 | |
| 	}
 | |
| 	if (vertices != NULL) {
 | |
| 		delete[] vertices;
 | |
| 	}
 | |
| 	if (textureVertices != NULL) {
 | |
| 		delete[] textureVertices;
 | |
| 	}
 | |
| 	if (mesh != NULL) {
 | |
| 		delete mesh;
 | |
| 	}
 | |
| 	if (polyIndices != NULL) {
 | |
| 		delete[] polyIndices;
 | |
| 	}
 | |
| 	if (textureIndices != NULL) {
 | |
| 		delete[] textureIndices;
 | |
| 	}
 | |
| 
 | |
| 	return FAILURE;
 | |
| }
 | |
| 
 | |
| // FUNCTION: LEGO1 0x100aabb0
 | |
| LegoLOD* LegoLOD::Clone(Tgl::Renderer* p_renderer)
 | |
| {
 | |
| 	LegoLOD* dupLod = new LegoLOD(p_renderer);
 | |
| 
 | |
| 	dupLod->m_meshBuilder = m_meshBuilder->Clone();
 | |
| 	dupLod->m_melems = new Mesh[m_numMeshes];
 | |
| 
 | |
| 	for (LegoU32 i = 0; i < m_numMeshes; i++) {
 | |
| 		dupLod->m_melems[i].m_tglMesh = m_melems[i].m_tglMesh->ShallowClone(dupLod->m_meshBuilder);
 | |
| 		dupLod->m_melems[i].m_unk0x04 = m_melems[i].m_unk0x04;
 | |
| 	}
 | |
| 
 | |
| 	dupLod->m_unk0x08 = m_unk0x08;
 | |
| 	dupLod->m_numMeshes = m_numMeshes;
 | |
| 	dupLod->m_numVertices = m_numVertices;
 | |
| 	dupLod->m_numPolys = m_numPolys;
 | |
| 	dupLod->m_meshOffset = m_meshOffset;
 | |
| 
 | |
| 	return dupLod;
 | |
| }
 | |
| 
 | |
| // FUNCTION: LEGO1 0x100aacb0
 | |
| LegoResult LegoLOD::SetColor(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha)
 | |
| {
 | |
| 	for (LegoU32 i = m_meshOffset; i < m_numMeshes; i++) {
 | |
| 		if (!m_melems[i].m_unk0x04) {
 | |
| 			m_melems[i].m_tglMesh->SetColor(p_red, p_green, p_blue, p_alpha);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return SUCCESS;
 | |
| }
 | |
| 
 | |
| // FUNCTION: LEGO1 0x100aad00
 | |
| LegoResult LegoLOD::SetTextureInfo(LegoTextureInfo* p_textureInfo)
 | |
| {
 | |
| 	for (LegoU32 i = m_meshOffset; i < m_numMeshes; i++) {
 | |
| 		if (m_melems[i].m_unk0x04) {
 | |
| 			LegoTextureInfo::SetGroupTexture(m_melems[i].m_tglMesh, p_textureInfo);
 | |
| 			m_melems[i].m_tglMesh->SetColor(1.0F, 1.0F, 1.0F, 0.0F);
 | |
| 			m_melems[i].m_unk0x04 = TRUE;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return SUCCESS;
 | |
| }
 | |
| 
 | |
| // FUNCTION: LEGO1 0x100aad70
 | |
| LegoResult LegoLOD::FUN_100aad70(LegoTextureInfo* p_textureInfo)
 | |
| {
 | |
| 	for (LegoU32 i = m_meshOffset; i < m_numMeshes; i++) {
 | |
| 		if (m_melems[i].m_unk0x04) {
 | |
| 			LegoTextureInfo::SetGroupTexture(m_melems[i].m_tglMesh, p_textureInfo);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return SUCCESS;
 | |
| }
 | |
| 
 | |
| // FUNCTION: LEGO1 0x100aadc0
 | |
| LegoResult LegoLOD::GetTextureInfo(LegoTextureInfo*& p_textureInfo)
 | |
| {
 | |
| 	for (LegoU32 i = m_meshOffset; i < m_numMeshes; i++) {
 | |
| 		if (m_melems[i].m_unk0x04) {
 | |
| 			if (LegoTextureInfo::GetGroupTexture(m_melems[i].m_tglMesh, p_textureInfo) == TRUE) {
 | |
| 				return SUCCESS;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return FAILURE;
 | |
| }
 | |
| 
 | |
| // FUNCTION: LEGO1 0x100aae20
 | |
| LegoBool LegoLOD::FUN_100aae20(const LegoChar* p_name)
 | |
| {
 | |
| 	if (p_name != NULL) {
 | |
| 		if (!strnicmp(p_name, g_unk0x101013dc, strlen(g_unk0x101013dc))) {
 | |
| 			return TRUE;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return FALSE;
 | |
| }
 | |
| 
 | |
| // FUNCTION: LEGO1 0x100aae60
 | |
| // FUNCTION: BETA10 0x1018e50f
 | |
| void LegoLOD::ClearMeshOffset()
 | |
| {
 | |
| 	m_meshOffset = 0;
 | |
| }
 | |
| 
 | |
| inline BOOL GetMeshData(IDirect3DRMMesh*& mesh, D3DRMGROUPINDEX& index, Tgl::Mesh* pMesh)
 | |
| {
 | |
| 	mesh = ((TglImpl::MeshImpl*) pMesh)->ImplementationData()->groupMesh;
 | |
| 	index = ((TglImpl::MeshImpl*) pMesh)->ImplementationData()->groupIndex;
 | |
| 	return FALSE;
 | |
| }
 | |
| 
 | |
| inline IDirect3DRM2* GetD3DRM(Tgl::Renderer* pRenderer)
 | |
| {
 | |
| 	return ((TglImpl::RendererImpl*) pRenderer)->ImplementationData();
 | |
| }
 |