Implement LegoCharacterManager::CreateROI (#709)

* WIP

* Create globals

* Add Read

* Name Init

* Add LegoCharacter init data

* Add define for NULL

* Use MxS8

* Add LegoCharacterLOD

* WIP CreateROI

* Fix

* WIP

* Match

* Match

* Match, implement Find

* Fix MeshBuilder

* Fix

* space
This commit is contained in:
Christian Semmler 2024-03-22 13:40:19 -04:00 committed by GitHub
parent 8cffa7cf8c
commit 68bb20f04f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 1617 additions and 109 deletions

View file

@ -317,6 +317,7 @@ add_library(lego1 SHARED
LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp
LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp
LEGO1/lego/legoomni/src/common/legocharactermanager.cpp LEGO1/lego/legoomni/src/common/legocharactermanager.cpp
LEGO1/lego/legoomni/src/common/legocharacters.cpp
LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp
LEGO1/lego/legoomni/src/common/legogamestate.cpp LEGO1/lego/legoomni/src/common/legogamestate.cpp
LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp

View file

@ -31,50 +31,27 @@ struct LegoCharacter {
MxU32 m_refCount; // 0x04 MxU32 m_refCount; // 0x04
}; };
typedef map<const char*, LegoCharacter*, LegoCharacterComparator> LegoCharacterMap; struct LegoCharacterData;
struct LegoSaveDataEntry3 { typedef map<const char*, LegoCharacter*, LegoCharacterComparator> LegoCharacterMap;
char* m_name;
void* m_unk0x04;
LegoActor* m_actor;
MxS32 m_savePart1;
MxS32 m_savePart2;
MxU8 m_savePart3;
undefined4 m_unk0x18[6];
MxU8 m_frameOffsetInDwords; // 0x30
MxS32* m_pFrameData;
MxU8 m_currentFrame;
undefined4 m_unk0x3c[2];
MxU8 m_savePart5; // 0x44
undefined4 m_unk0x48[5];
MxU8 m_savePart6; // 0x5c
undefined4 m_unk0x60[11];
MxU8 m_savePart7; // 0x8c
undefined4 m_unk0x90[5];
MxU8 m_savePart8; // 0xa4
undefined4 m_unk0xa8[17];
MxU8 m_savePart9; // 0xec
undefined4 m_unk0xf0[5];
MxU8 m_savePart10; // 0x104
};
// SIZE 0x08 // SIZE 0x08
class LegoCharacterManager { class LegoCharacterManager {
public: public:
LegoCharacterManager(); LegoCharacterManager();
MxResult WriteSaveData3(LegoStorage* p_storage); MxResult Write(LegoStorage* p_storage);
MxResult ReadSaveData3(LegoStorage* p_storage); MxResult Read(LegoStorage* p_storage);
LegoROI* GetROI(const char* p_key, MxBool p_createEntity); LegoROI* GetROI(const char* p_key, MxBool p_createEntity);
void InitSaveData(); void Init();
static void SetCustomizeAnimFile(const char* p_value); static void SetCustomizeAnimFile(const char* p_value);
static MxBool FUN_10084c00(const LegoChar*); static MxBool FUN_10084c00(const LegoChar*);
void FUN_100832a0(); void FUN_100832a0();
void FUN_10083db0(LegoROI* p_roi); void FUN_10083db0(LegoROI* p_roi);
void FUN_10083f10(LegoROI* p_roi); void FUN_10083f10(LegoROI* p_roi);
LegoSaveDataEntry3* FUN_10084c60(const char* p_key); LegoCharacterData* Find(const char* p_key);
MxBool FUN_10084ec0(LegoROI* p_roi); MxBool FUN_10084ec0(LegoROI* p_roi);
MxU32 FUN_10085140(LegoROI*, MxBool); MxU32 FUN_10085140(LegoROI*, MxBool);
LegoROI* FUN_10085210(const LegoChar*, LegoChar*, undefined); LegoROI* FUN_10085210(const LegoChar*, LegoChar*, undefined);
@ -92,6 +69,12 @@ class LegoCharacterManager {
}; };
// clang-format off // clang-format off
// TEMPLATE: LEGO1 0x1001a690
// list<ROI *,allocator<ROI *> >::_Buynode
// TEMPLATE: LEGO1 0x10035790
// _Construct
// TEMPLATE: LEGO1 0x10082b90 // TEMPLATE: LEGO1 0x10082b90
// _Tree<char const *,pair<char const * const,LegoCharacter *>,map<char const *,LegoCharacter *,LegoCharacterComparator,allocator<LegoCharacter *> >::_Kfn,LegoCharacterComparator,allocator<LegoCharacter *> >::~_Tree<char const *,pair<char const * const,LegoCharacter *>,map<char const *,LegoCharacter *,LegoCharacterComparator,allocator<LegoCharacter *> >::_Kfn,LegoCharacterComparator,allocator<LegoCharacter *> > // _Tree<char const *,pair<char const * const,LegoCharacter *>,map<char const *,LegoCharacter *,LegoCharacterComparator,allocator<LegoCharacter *> >::_Kfn,LegoCharacterComparator,allocator<LegoCharacter *> >::~_Tree<char const *,pair<char const * const,LegoCharacter *>,map<char const *,LegoCharacter *,LegoCharacterComparator,allocator<LegoCharacter *> >::_Kfn,LegoCharacterComparator,allocator<LegoCharacter *> >

View file

@ -0,0 +1,51 @@
#ifndef LEGOCHARACTERS_H
#define LEGOCHARACTERS_H
#include "decomp.h"
#include "mxtypes.h"
class LegoActor;
class LegoROI;
// SIZE 0x108
struct LegoCharacterData {
// SIZE 0x18
struct Part {
MxU8* m_unk0x00; // 0x00
const char** m_unk0x04; // 0x04
MxU8 m_unk0x08; // 0x08
MxU8* m_unk0x0c; // 0x0c
const char** m_unk0x10; // 0x10
MxU8 m_unk0x14; // 0x14
};
char* m_name; // 0x00
LegoROI* m_roi; // 0x04
LegoActor* m_actor; // 0x08
MxS32 m_unk0x0c; // 0x0c
MxS32 m_unk0x10; // 0x10
MxU8 m_unk0x14; // 0x14
Part m_parts[10]; // 0x18
};
// SIZE 0x58
struct LegoCharacterLOD {
enum {
c_flag1 = 0x01,
c_flag2 = 0x02
};
const char* m_name; // 0x00
const char* m_parentName; // 0x04
MxU32 m_flags; // 0x08
float m_boundingSphere[4]; // 0x0c
float m_boundingBox[6]; // 0x1c
float m_position[3]; // 0x34
float m_direction[3]; // 0x40
float m_up[3]; // 0x4c
};
extern LegoCharacterData g_characterDataInit[66];
extern LegoCharacterLOD g_characterLODs[11];
#endif // LEGOCHARACTERS_H

View file

@ -1,40 +1,40 @@
#include "legocharactermanager.h" #include "legocharactermanager.h"
#include "legoanimactor.h" #include "legoanimactor.h"
#include "legocharacters.h"
#include "legogamestate.h" #include "legogamestate.h"
#include "legovideomanager.h" #include "legovideomanager.h"
#include "misc.h" #include "misc.h"
#include "misc/legocontainer.h"
#include "mxmisc.h" #include "mxmisc.h"
#include "realtime/realtime.h"
#include "roi/legolod.h"
#include "roi/legoroi.h" #include "roi/legoroi.h"
DECOMP_SIZE_ASSERT(LegoCharacter, 0x08) DECOMP_SIZE_ASSERT(LegoCharacter, 0x08)
DECOMP_SIZE_ASSERT(LegoCharacterManager, 0x08) DECOMP_SIZE_ASSERT(LegoCharacterManager, 0x08)
DECOMP_SIZE_ASSERT(LegoSaveDataEntry3, 0x108)
// GLOBAL: LEGO1 0x100f80c0
LegoSaveDataEntry3 g_saveDataInit[66]; // TODO: add data
// GLOBAL: LEGO1 0x100fc4e4 // GLOBAL: LEGO1 0x100fc4e4
char* LegoCharacterManager::g_customizeAnimFile = NULL; char* LegoCharacterManager::g_customizeAnimFile = NULL;
// GLOBAL: LEGO1 0x10104f20 // GLOBAL: LEGO1 0x10104f20
LegoSaveDataEntry3 g_saveData3[66]; LegoCharacterData g_characterData[66];
// FUNCTION: LEGO1 0x10082a20 // FUNCTION: LEGO1 0x10082a20
LegoCharacterManager::LegoCharacterManager() LegoCharacterManager::LegoCharacterManager()
{ {
m_characters = new LegoCharacterMap(); m_characters = new LegoCharacterMap();
InitSaveData(); Init();
m_customizeAnimFile = new CustomizeAnimFileVariable("CUSTOMIZE_ANIM_FILE"); m_customizeAnimFile = new CustomizeAnimFileVariable("CUSTOMIZE_ANIM_FILE");
VariableTable()->SetVariable(m_customizeAnimFile); VariableTable()->SetVariable(m_customizeAnimFile);
} }
// FUNCTION: LEGO1 0x10083270 // FUNCTION: LEGO1 0x10083270
void LegoCharacterManager::InitSaveData() void LegoCharacterManager::Init()
{ {
for (MxS32 i = 0; i < 66; i++) { for (MxS32 i = 0; i < _countof(g_characterData); i++) {
g_saveData3[i] = g_saveDataInit[i]; g_characterData[i] = g_characterDataInit[i];
} }
} }
@ -45,59 +45,95 @@ void LegoCharacterManager::FUN_100832a0()
} }
// FUNCTION: LEGO1 0x10083310 // FUNCTION: LEGO1 0x10083310
MxResult LegoCharacterManager::WriteSaveData3(LegoStorage* p_storage) MxResult LegoCharacterManager::Write(LegoStorage* p_storage)
{ {
MxResult result = FAILURE; MxResult result = FAILURE;
// This should probably be a for loop but I can't figure out how to for (MxS32 i = 0; i < _countof(g_characterData) - 1; i++) {
// make it match as a for loop. LegoCharacterData* data = &g_characterData[i];
LegoSaveDataEntry3* entry = g_saveData3;
const LegoSaveDataEntry3* end = &g_saveData3[66];
while (TRUE) { if (p_storage->Write(&data->m_unk0x0c, sizeof(data->m_unk0x0c)) != SUCCESS) {
if (p_storage->Write(&entry->m_savePart1, 4) != SUCCESS) { goto done;
break;
} }
if (p_storage->Write(&entry->m_savePart2, 4) != SUCCESS) { if (p_storage->Write(&data->m_unk0x10, sizeof(data->m_unk0x10)) != SUCCESS) {
break; goto done;
} }
if (p_storage->Write(&entry->m_savePart3, 1) != SUCCESS) { if (p_storage->Write(&data->m_unk0x14, sizeof(data->m_unk0x14)) != SUCCESS) {
break; goto done;
} }
if (p_storage->Write(&entry->m_currentFrame, 1) != SUCCESS) { if (p_storage->Write(&data->m_parts[1].m_unk0x08, sizeof(data->m_parts[1].m_unk0x08)) != SUCCESS) {
break; goto done;
} }
if (p_storage->Write(&entry->m_savePart5, 1) != SUCCESS) { if (p_storage->Write(&data->m_parts[1].m_unk0x14, sizeof(data->m_parts[1].m_unk0x14)) != SUCCESS) {
break; goto done;
} }
if (p_storage->Write(&entry->m_savePart6, 1) != SUCCESS) { if (p_storage->Write(&data->m_parts[2].m_unk0x14, sizeof(data->m_parts[2].m_unk0x14)) != SUCCESS) {
break; goto done;
} }
if (p_storage->Write(&entry->m_savePart7, 1) != SUCCESS) { if (p_storage->Write(&data->m_parts[4].m_unk0x14, sizeof(data->m_parts[4].m_unk0x14)) != SUCCESS) {
break; goto done;
} }
if (p_storage->Write(&entry->m_savePart8, 1) != SUCCESS) { if (p_storage->Write(&data->m_parts[5].m_unk0x14, sizeof(data->m_parts[5].m_unk0x14)) != SUCCESS) {
break; goto done;
} }
if (p_storage->Write(&entry->m_savePart9, 1) != SUCCESS) { if (p_storage->Write(&data->m_parts[8].m_unk0x14, sizeof(data->m_parts[8].m_unk0x14)) != SUCCESS) {
break; goto done;
} }
if (p_storage->Write(&entry->m_savePart10, 1) != SUCCESS) { if (p_storage->Write(&data->m_parts[9].m_unk0x14, sizeof(data->m_parts[9].m_unk0x14)) != SUCCESS) {
break; goto done;
} }
if (++entry >= end) { }
result = SUCCESS; result = SUCCESS;
break;
}
}
done:
return result; return result;
} }
// STUB: LEGO1 0x100833f0 // FUNCTION: LEGO1 0x100833f0
MxResult LegoCharacterManager::ReadSaveData3(LegoStorage* p_storage) MxResult LegoCharacterManager::Read(LegoStorage* p_storage)
{ {
return SUCCESS; MxResult result = FAILURE;
for (MxS32 i = 0; i < _countof(g_characterData) - 1; i++) {
LegoCharacterData* data = &g_characterData[i];
if (p_storage->Read(&data->m_unk0x0c, sizeof(data->m_unk0x0c)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&data->m_unk0x10, sizeof(data->m_unk0x10)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&data->m_unk0x14, sizeof(data->m_unk0x14)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&data->m_parts[1].m_unk0x08, sizeof(data->m_parts[1].m_unk0x08)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&data->m_parts[1].m_unk0x14, sizeof(data->m_parts[1].m_unk0x14)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&data->m_parts[2].m_unk0x14, sizeof(data->m_parts[2].m_unk0x14)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&data->m_parts[4].m_unk0x14, sizeof(data->m_parts[4].m_unk0x14)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&data->m_parts[5].m_unk0x14, sizeof(data->m_parts[5].m_unk0x14)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&data->m_parts[8].m_unk0x14, sizeof(data->m_parts[8].m_unk0x14)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&data->m_parts[9].m_unk0x14, sizeof(data->m_parts[9].m_unk0x14)) != SUCCESS) {
goto done;
}
}
result = SUCCESS;
done:
return result;
} }
// FUNCTION: LEGO1 0x10083500 // FUNCTION: LEGO1 0x10083500
@ -139,7 +175,7 @@ LegoROI* LegoCharacterManager::GetROI(const char* p_key, MxBool p_createEntity)
actor->SetROI(character->m_roi, FALSE, FALSE); actor->SetROI(character->m_roi, FALSE, FALSE);
actor->FUN_100114e0(0); actor->FUN_100114e0(0);
actor->SetFlag(LegoActor::c_bit2); actor->SetFlag(LegoActor::c_bit2);
FUN_10084c60(p_key)->m_actor = actor; Find(p_key)->m_actor = actor;
} }
return character->m_roi; return character->m_roi;
@ -160,10 +196,153 @@ void LegoCharacterManager::FUN_10083f10(LegoROI* p_roi)
// TODO // TODO
} }
// STUB: LEGO1 0x10084030 // FUNCTION: LEGO1 0x10084030
LegoROI* LegoCharacterManager::CreateROI(const char* p_key) LegoROI* LegoCharacterManager::CreateROI(const char* p_key)
{ {
return NULL; MxBool success = FALSE;
LegoROI* roi = NULL;
BoundingSphere boundingSphere;
BoundingBox boundingBox;
MxMatrix mat;
CompoundObject* comp;
MxS32 i, j;
Tgl::Renderer* renderer = VideoManager()->GetRenderer();
ViewLODListManager* lodManager = GetViewLODListManager();
LegoTextureContainer* textureContainer = TextureContainer();
LegoCharacterData* characterData = Find(p_key);
if (characterData == NULL) {
goto done;
}
if (!strcmpi(p_key, "pep")) {
LegoCharacterData* pepper = Find("pepper");
characterData->m_unk0x0c = pepper->m_unk0x0c;
characterData->m_unk0x10 = pepper->m_unk0x10;
characterData->m_unk0x14 = pepper->m_unk0x14;
for (i = 0; i < _countof(characterData->m_parts); i++) {
characterData->m_parts[i] = pepper->m_parts[i];
}
}
roi = new LegoROI(renderer);
roi->SetName(p_key);
boundingSphere.Center()[0] = g_characterLODs[0].m_boundingSphere[0];
boundingSphere.Center()[1] = g_characterLODs[0].m_boundingSphere[1];
boundingSphere.Center()[2] = g_characterLODs[0].m_boundingSphere[2];
boundingSphere.Radius() = g_characterLODs[0].m_boundingSphere[3];
roi->SetBoundingSphere(boundingSphere);
boundingBox.Min()[0] = g_characterLODs[0].m_boundingBox[0];
boundingBox.Min()[1] = g_characterLODs[0].m_boundingBox[1];
boundingBox.Min()[2] = g_characterLODs[0].m_boundingBox[2];
boundingBox.Max()[0] = g_characterLODs[0].m_boundingBox[3];
boundingBox.Max()[1] = g_characterLODs[0].m_boundingBox[4];
boundingBox.Max()[2] = g_characterLODs[0].m_boundingBox[5];
roi->SetUnknown0x80(boundingBox);
comp = new CompoundObject();
roi->SetComp(comp);
for (i = 0; i < _countof(g_characterLODs) - 1; i++) {
ViewLODList *lodList, *dupLodList;
LegoROI* childROI;
MxS32 lodSize;
const char* parentName;
char lodName[64];
LegoCharacterData::Part& part = characterData->m_parts[i];
if (i == 0 || i == 1) {
parentName = part.m_unk0x04[part.m_unk0x00[part.m_unk0x08]];
}
else {
parentName = g_characterLODs[i + 1].m_parentName;
}
lodList = lodManager->Lookup(parentName);
lodSize = lodList->Size();
sprintf(lodName, "%s%d", p_key, i);
dupLodList = lodManager->Create(lodName, lodSize);
for (j = 0; j < lodSize; j++) {
dupLodList->PushBack(((LegoLOD*) (*lodList)[j])->Clone(renderer));
}
lodList->Release();
lodList = dupLodList;
childROI = new LegoROI(renderer, lodList);
lodList->Release();
childROI->SetName(g_characterLODs[i + 1].m_name);
childROI->SetParentROI(roi);
BoundingSphere childBoundingSphere;
childBoundingSphere.Center()[0] = g_characterLODs[i + 1].m_boundingSphere[0];
childBoundingSphere.Center()[1] = g_characterLODs[i + 1].m_boundingSphere[1];
childBoundingSphere.Center()[2] = g_characterLODs[i + 1].m_boundingSphere[2];
childBoundingSphere.Radius() = g_characterLODs[i + 1].m_boundingSphere[3];
childROI->SetBoundingSphere(childBoundingSphere);
BoundingBox childBoundingBox;
childBoundingBox.Min()[0] = g_characterLODs[i + 1].m_boundingBox[0];
childBoundingBox.Min()[1] = g_characterLODs[i + 1].m_boundingBox[1];
childBoundingBox.Min()[2] = g_characterLODs[i + 1].m_boundingBox[2];
childBoundingBox.Max()[0] = g_characterLODs[i + 1].m_boundingBox[3];
childBoundingBox.Max()[1] = g_characterLODs[i + 1].m_boundingBox[4];
childBoundingBox.Max()[2] = g_characterLODs[i + 1].m_boundingBox[5];
childROI->SetUnknown0x80(childBoundingBox);
CalcLocalTransform(
Mx3DPointFloat(g_characterLODs[i + 1].m_position),
Mx3DPointFloat(g_characterLODs[i + 1].m_direction),
Mx3DPointFloat(g_characterLODs[i + 1].m_up),
mat
);
childROI->WrappedSetLocalTransform(mat);
if (g_characterLODs[i + 1].m_flags & LegoCharacterLOD::c_flag1 &&
(i != 0 || part.m_unk0x00[part.m_unk0x08] != 0)) {
LegoTextureInfo* textureInfo = textureContainer->Get(part.m_unk0x10[part.m_unk0x0c[part.m_unk0x14]]);
if (textureInfo != NULL) {
childROI->FUN_100a9210(textureInfo);
childROI->FUN_100a9170(1.0F, 1.0F, 1.0F, 0.0F);
}
}
else if (g_characterLODs[i + 1].m_flags & LegoCharacterLOD::c_flag2 || (i == 0 && part.m_unk0x00[part.m_unk0x08] == 0)) {
LegoFloat red, green, blue, alpha;
childROI->FUN_100a9bf0(part.m_unk0x10[part.m_unk0x0c[part.m_unk0x14]], red, green, blue, alpha);
childROI->FUN_100a9170(red, green, blue, alpha);
}
comp->push_back(childROI);
}
CalcLocalTransform(
Mx3DPointFloat(g_characterLODs[0].m_position),
Mx3DPointFloat(g_characterLODs[0].m_direction),
Mx3DPointFloat(g_characterLODs[0].m_up),
mat
);
roi->WrappedSetLocalTransform(mat);
characterData->m_roi = roi;
success = TRUE;
done:
if (!success && roi != NULL) {
delete roi;
roi = NULL;
}
return roi;
} }
// STUB: LEGO1 0x10084c00 // STUB: LEGO1 0x10084c00
@ -173,9 +352,21 @@ MxBool LegoCharacterManager::FUN_10084c00(const LegoChar*)
return FALSE; return FALSE;
} }
// STUB: LEGO1 0x10084c60 // FUNCTION: LEGO1 0x10084c60
LegoSaveDataEntry3* LegoCharacterManager::FUN_10084c60(const char* p_key) LegoCharacterData* LegoCharacterManager::Find(const char* p_key)
{ {
MxU32 i;
for (i = 0; i < _countof(g_characterData) - 1; i++) {
if (!strcmpi(g_characterData[i].m_name, p_key)) {
break;
}
}
if (i < _countof(g_characterData)) {
return &g_characterData[i];
}
return NULL; return NULL;
} }

File diff suppressed because it is too large Load diff

View file

@ -235,7 +235,7 @@ MxResult LegoGameState::Save(MxULong p_slot)
} }
WriteEndOfVariables(&fileStorage); WriteEndOfVariables(&fileStorage);
CharacterManager()->WriteSaveData3(&fileStorage); CharacterManager()->Write(&fileStorage);
PlantManager()->Save(&fileStorage); PlantManager()->Save(&fileStorage);
result = BuildingManager()->Save(&fileStorage); result = BuildingManager()->Save(&fileStorage);
@ -334,7 +334,7 @@ MxResult LegoGameState::Load(MxULong p_slot)
SetLightPosition(atoi(lightPosition)); SetLightPosition(atoi(lightPosition));
} }
if (CharacterManager()->ReadSaveData3(&fileStorage) == FAILURE) { if (CharacterManager()->Read(&fileStorage) == FAILURE) {
goto done; goto done;
} }
if (PlantManager()->Load(&fileStorage) == FAILURE) { if (PlantManager()->Load(&fileStorage) == FAILURE) {
@ -1057,7 +1057,7 @@ void LegoGameState::Init()
SetLightPosition(2); SetLightPosition(2);
PlantManager()->Init(); PlantManager()->Init();
BuildingManager()->Init(); BuildingManager()->Init();
CharacterManager()->InitSaveData(); CharacterManager()->Init();
AnimationManager()->FUN_1005ee80(TRUE); AnimationManager()->FUN_1005ee80(TRUE);
SetColors(); SetColors();
RemoveActor(); RemoveActor();

View file

@ -128,7 +128,7 @@ Mx3DPointFloat LegoCameraController::GetWorldUp()
{ {
if (m_lego3DView && m_lego3DView->GetPointOfView()) { if (m_lego3DView && m_lego3DView->GetPointOfView()) {
Mx3DPointFloat vec; Mx3DPointFloat vec;
vec = Vector3(m_lego3DView->GetPointOfView()->GetWorldUp()); vec = m_lego3DView->GetPointOfView()->GetWorldUp();
return Mx3DPointFloat(vec[0], vec[1], vec[2]); return Mx3DPointFloat(vec[0], vec[1], vec[2]);
} }
else { else {
@ -141,7 +141,7 @@ Mx3DPointFloat LegoCameraController::GetWorldLocation()
{ {
if (m_lego3DView && m_lego3DView->GetPointOfView()) { if (m_lego3DView && m_lego3DView->GetPointOfView()) {
Mx3DPointFloat vec; Mx3DPointFloat vec;
vec = Vector3(m_lego3DView->GetPointOfView()->GetWorldPosition()); vec = m_lego3DView->GetPointOfView()->GetWorldPosition();
return Mx3DPointFloat(vec[0], vec[1] - m_entityOffsetUp, vec[2]); return Mx3DPointFloat(vec[0], vec[1] - m_entityOffsetUp, vec[2]);
} }
else { else {
@ -154,7 +154,7 @@ Mx3DPointFloat LegoCameraController::GetWorldDirection()
{ {
if (m_lego3DView && m_lego3DView->GetPointOfView()) { if (m_lego3DView && m_lego3DView->GetPointOfView()) {
Mx3DPointFloat vec; Mx3DPointFloat vec;
vec = Vector3(m_lego3DView->GetPointOfView()->GetWorldDirection()); vec = m_lego3DView->GetPointOfView()->GetWorldDirection();
return Mx3DPointFloat(vec[0], vec[1], vec[2]); return Mx3DPointFloat(vec[0], vec[1], vec[2]);
} }
else { else {

View file

@ -28,7 +28,7 @@ LegoLOD::LegoLOD(Tgl::Renderer* p_renderer) : ViewLOD(p_renderer)
GetD3DRM(p_renderer)->CreateMaterial(10.0, &g_unk0x101013d4); GetD3DRM(p_renderer)->CreateMaterial(10.0, &g_unk0x101013d4);
} }
m_meshes = NULL; m_melems = NULL;
m_numMeshes = 0; m_numMeshes = 0;
m_numVertices = 0; m_numVertices = 0;
m_numPolys = 0; m_numPolys = 0;
@ -38,17 +38,17 @@ LegoLOD::LegoLOD(Tgl::Renderer* p_renderer) : ViewLOD(p_renderer)
// FUNCTION: LEGO1 0x100aa450 // FUNCTION: LEGO1 0x100aa450
LegoLOD::~LegoLOD() LegoLOD::~LegoLOD()
{ {
if (m_numMeshes && m_meshes != NULL) { if (m_numMeshes && m_melems != NULL) {
for (LegoU32 i = 0; i < m_numMeshes; i++) { for (LegoU32 i = 0; i < m_numMeshes; i++) {
if (m_meshes[i].m_tglMesh != NULL) { if (m_melems[i].m_tglMesh != NULL) {
delete m_meshes[i].m_tglMesh; delete m_melems[i].m_tglMesh;
m_meshes[i].m_tglMesh = NULL; m_melems[i].m_tglMesh = NULL;
} }
} }
} }
if (m_meshes) { if (m_melems) {
delete[] m_meshes; delete[] m_melems;
} }
} }
@ -90,8 +90,8 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
SetFlag(c_bit4); SetFlag(c_bit4);
m_meshes = new Mesh[m_numMeshes]; m_melems = new Mesh[m_numMeshes];
memset(m_meshes, 0, sizeof(*m_meshes) * m_numMeshes); memset(m_melems, 0, sizeof(*m_melems) * m_numMeshes);
meshUnd1 = m_numMeshes - 1; meshUnd1 = m_numMeshes - 1;
meshUnd2 = 0; meshUnd2 = 0;
@ -193,7 +193,7 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
meshUnd2++; meshUnd2++;
} }
m_meshes[meshIndex].m_tglMesh = m_meshBuilder->CreateMesh( m_melems[meshIndex].m_tglMesh = m_meshBuilder->CreateMesh(
numPolys & MAXWORD, numPolys & MAXWORD,
numVertices & MAXWORD, numVertices & MAXWORD,
vertices, vertices,
@ -204,11 +204,11 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
shadingModel shadingModel
); );
if (m_meshes[meshIndex].m_tglMesh == NULL) { if (m_melems[meshIndex].m_tglMesh == NULL) {
goto done; goto done;
} }
m_meshes[meshIndex].m_tglMesh->SetShadingModel(shadingModel); m_melems[meshIndex].m_tglMesh->SetShadingModel(shadingModel);
if (textureName != NULL) { if (textureName != NULL) {
if (mesh->GetUnknown0x21()) { if (mesh->GetUnknown0x21()) {
@ -221,9 +221,9 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
goto done; goto done;
} }
m_meshes[meshIndex].m_tglMesh->SetColor(1.0F, 1.0F, 1.0F, 0.0F); m_melems[meshIndex].m_tglMesh->SetColor(1.0F, 1.0F, 1.0F, 0.0F);
LegoTextureInfo::SetGroupTexture(m_meshes[meshIndex].m_tglMesh, textureInfo); LegoTextureInfo::SetGroupTexture(m_melems[meshIndex].m_tglMesh, textureInfo);
m_meshes[meshIndex].m_unk0x04 = TRUE; m_melems[meshIndex].m_unk0x04 = TRUE;
} }
else { else {
LegoFloat red = 1.0F; LegoFloat red = 1.0F;
@ -241,13 +241,13 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
alpha = mesh->GetAlpha(); alpha = mesh->GetAlpha();
} }
m_meshes[meshIndex].m_tglMesh->SetColor(red, green, blue, alpha); m_melems[meshIndex].m_tglMesh->SetColor(red, green, blue, alpha);
} }
if (mesh->GetUnknown0x0d() > 0) { if (mesh->GetUnknown0x0d() > 0) {
IDirect3DRMMesh* mesh; IDirect3DRMMesh* mesh;
D3DRMGROUPINDEX index; D3DRMGROUPINDEX index;
GetMeshData(mesh, index, m_meshes[meshIndex].m_tglMesh); GetMeshData(mesh, index, m_melems[meshIndex].m_tglMesh);
mesh->SetGroupMaterial(index, g_unk0x101013d4); mesh->SetGroupMaterial(index, g_unk0x101013d4);
} }
@ -302,12 +302,34 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
return FAILURE; 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_unk0x1c = m_unk0x1c;
return dupLod;
}
// FUNCTION: LEGO1 0x100aacb0 // FUNCTION: LEGO1 0x100aacb0
LegoResult LegoLOD::FUN_100aacb0(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha) LegoResult LegoLOD::FUN_100aacb0(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha)
{ {
for (LegoU32 i = m_unk0x1c; i < m_numMeshes; i++) { for (LegoU32 i = m_unk0x1c; i < m_numMeshes; i++) {
if (!m_meshes[i].m_unk0x04) { if (!m_melems[i].m_unk0x04) {
m_meshes[i].m_tglMesh->SetColor(p_red, p_green, p_blue, p_alpha); m_melems[i].m_tglMesh->SetColor(p_red, p_green, p_blue, p_alpha);
} }
} }
@ -318,10 +340,10 @@ LegoResult LegoLOD::FUN_100aacb0(LegoFloat p_red, LegoFloat p_green, LegoFloat p
LegoResult LegoLOD::FUN_100aad00(LegoTextureInfo* p_textureInfo) LegoResult LegoLOD::FUN_100aad00(LegoTextureInfo* p_textureInfo)
{ {
for (LegoU32 i = m_unk0x1c; i < m_numMeshes; i++) { for (LegoU32 i = m_unk0x1c; i < m_numMeshes; i++) {
if (m_meshes[i].m_unk0x04) { if (m_melems[i].m_unk0x04) {
LegoTextureInfo::SetGroupTexture(m_meshes[i].m_tglMesh, p_textureInfo); LegoTextureInfo::SetGroupTexture(m_melems[i].m_tglMesh, p_textureInfo);
m_meshes[i].m_tglMesh->SetColor(1.0F, 1.0F, 1.0F, 0.0F); m_melems[i].m_tglMesh->SetColor(1.0F, 1.0F, 1.0F, 0.0F);
m_meshes[i].m_unk0x04 = TRUE; m_melems[i].m_unk0x04 = TRUE;
} }
} }

View file

@ -27,7 +27,8 @@ class LegoLOD : public ViewLOD {
// FUNCTION: LEGO1 0x100aae80 // FUNCTION: LEGO1 0x100aae80
float VTable0x10() override { return 0.0; } // vtable+0x10 float VTable0x10() override { return 0.0; } // vtable+0x10
LegoResult Read(Tgl::Renderer*, LegoTextureContainer* p_textureContainer, LegoStorage* p_storage); LegoResult Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_textureContainer, LegoStorage* p_storage);
LegoLOD* Clone(Tgl::Renderer* p_renderer);
LegoResult FUN_100aacb0(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); LegoResult FUN_100aacb0(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha);
LegoResult FUN_100aad00(LegoTextureInfo* p_textureInfo); LegoResult FUN_100aad00(LegoTextureInfo* p_textureInfo);
@ -37,7 +38,7 @@ class LegoLOD : public ViewLOD {
// LegoLOD::`scalar deleting destructor' // LegoLOD::`scalar deleting destructor'
protected: protected:
Mesh* m_meshes; // 0x0c Mesh* m_melems; // 0x0c
LegoU32 m_numMeshes; // 0x10 LegoU32 m_numMeshes; // 0x10
LegoU32 m_numVertices; // 0x14 LegoU32 m_numVertices; // 0x14
LegoU32 m_numPolys; // 0x18 LegoU32 m_numPolys; // 0x18

View file

@ -553,6 +553,23 @@ void LegoROI::FUN_100a9d30(ROIHandler p_func)
g_unk0x101013ac = p_func; g_unk0x101013ac = p_func;
} }
// FUNCTION: LEGO1 0x100a9d40
void LegoROI::SetName(const LegoChar* p_name)
{
if (m_name != NULL) {
delete[] m_name;
}
if (p_name != NULL) {
m_name = new LegoChar[strlen(p_name) + 1];
strcpy(m_name, p_name);
strlwr(m_name);
}
else {
m_name = NULL;
}
}
// FUNCTION: LEGO1 0x100a9e10 // FUNCTION: LEGO1 0x100a9e10
void LegoROI::SetDisplayBB(int p_displayBB) void LegoROI::SetDisplayBB(int p_displayBB)
{ {

View file

@ -34,6 +34,7 @@ class LegoROI : public ViewROI {
LegoResult SetFrame(LegoAnim* p_anim, LegoTime p_time); LegoResult SetFrame(LegoAnim* p_anim, LegoTime p_time);
LegoResult FUN_100a9170(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); LegoResult FUN_100a9170(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha);
LegoResult FUN_100a9210(LegoTextureInfo* p_textureInfo); LegoResult FUN_100a9210(LegoTextureInfo* p_textureInfo);
void SetName(const LegoChar* p_name);
float IntrinsicImportance() const override; // vtable+0x04 float IntrinsicImportance() const override; // vtable+0x04
void UpdateWorldBoundingVolumes() override; // vtable+0x18 void UpdateWorldBoundingVolumes() override; // vtable+0x18
@ -58,6 +59,9 @@ class LegoROI : public ViewROI {
inline LegoEntity* GetEntity() { return m_entity; } inline LegoEntity* GetEntity() { return m_entity; }
inline void SetEntity(LegoEntity* p_entity) { m_entity = p_entity; } inline void SetEntity(LegoEntity* p_entity) { m_entity = p_entity; }
inline void SetComp(CompoundObject* p_comp) { comp = p_comp; }
inline void SetBoundingSphere(const BoundingSphere& p_sphere) { m_sphere = m_world_bounding_sphere = p_sphere; }
inline void SetUnknown0x80(const BoundingBox& p_unk0x80) { m_unk0x80 = p_unk0x80; }
// SYNTHETIC: LEGO1 0x100a82b0 // SYNTHETIC: LEGO1 0x100a82b0
// LegoROI::`scalar deleting destructor' // LegoROI::`scalar deleting destructor'

View file

@ -20,7 +20,7 @@ class Mx3DPointFloat : public Vector3 {
// FUNCTION: LEGO1 0x100343a0 // FUNCTION: LEGO1 0x100343a0
inline Mx3DPointFloat(const Mx3DPointFloat& p_other) : Vector3(m_elements) { EqualsImpl(p_other.m_data); } inline Mx3DPointFloat(const Mx3DPointFloat& p_other) : Vector3(m_elements) { EqualsImpl(p_other.m_data); }
inline Mx3DPointFloat(const float* p_other) : Vector3(m_elements) { EqualsImpl((float*) p_other); } inline Mx3DPointFloat(const Vector3& p_other) : Vector3(m_elements) { EqualsImpl(p_other.m_data); }
// SYNTHETIC: LEGO1 0x1001d170 // SYNTHETIC: LEGO1 0x1001d170
// Mx3DPointFloat::Mx3DPointFloat // Mx3DPointFloat::Mx3DPointFloat

View file

@ -52,6 +52,10 @@ typedef MxU8 MxBool;
#define FALSE 0 #define FALSE 0
#endif #endif
#ifndef NULL
#define NULL 0
#endif
#define TWOCC(a, b) (((a) << 0) | ((b) << 8)) #define TWOCC(a, b) (((a) << 0) | ((b) << 8))
#define FOURCC(a, b, c, d) (((a) << 0) | ((b) << 8) | ((c) << 16) | ((d) << 24)) #define FOURCC(a, b, c, d) (((a) << 0) | ((b) << 8) | ((c) << 16) | ((d) << 24))

View file

@ -45,6 +45,8 @@ class OrientableROI : public ROI {
const float* GetWorldUp() const { return m_local2world[1]; } const float* GetWorldUp() const { return m_local2world[1]; }
OrientableROI* GetParentROI() const { return m_parentROI; } OrientableROI* GetParentROI() const { return m_parentROI; }
void SetParentROI(OrientableROI* p_parentROI) { m_parentROI = p_parentROI; }
void ToggleUnknown0xd8(BOOL p_enable) void ToggleUnknown0xd8(BOOL p_enable)
{ {
if (p_enable) { if (p_enable) {

View file

@ -178,7 +178,7 @@ Result MeshBuilderImpl::GetBoundingBox(float min[3], float max[3])
MeshBuilder* MeshBuilderImpl::Clone() MeshBuilder* MeshBuilderImpl::Clone()
{ {
MeshBuilderImpl* mesh = new MeshBuilderImpl(); MeshBuilderImpl* mesh = new MeshBuilderImpl();
int ret = m_data->Clone(0, IID_IDirect3DRMMeshBuilder, (void**) &mesh->m_data); int ret = m_data->Clone(0, IID_IDirect3DRMMesh, (void**) &mesh->m_data);
if (ret < 0) { if (ret < 0) {
delete mesh; delete mesh;
mesh = NULL; mesh = NULL;