mirror of
https://github.com/HarbourMasters/SpaghettiKart
synced 2026-08-04 01:23:11 -04:00
@@ -0,0 +1,94 @@
|
||||
#include "ModelLoader.h"
|
||||
#include "port/Engine.h"
|
||||
#include "engine/courses/Course.h"
|
||||
|
||||
extern "C" {
|
||||
#include "memory.h"
|
||||
}
|
||||
|
||||
void ModelLoader::Add(LoadModelList list) {
|
||||
_deferredList.push_back(list);
|
||||
}
|
||||
|
||||
void ModelLoader::Load() {
|
||||
if (_hasRan) { // Ensure this does not get ran multiple times
|
||||
printf("ModelLoader.cpp has already been ran once.\n");
|
||||
return;
|
||||
}
|
||||
_hasRan = true;
|
||||
|
||||
// Set to track processed courses
|
||||
std::unordered_set<Course*> processedCourses;
|
||||
|
||||
for (auto& list : _deferredList) {
|
||||
// Check if the course has already been processed
|
||||
if (processedCourses.find(list.course) != processedCourses.end()) {
|
||||
continue; // Skip if already processed
|
||||
}
|
||||
|
||||
// Process the course
|
||||
ModelLoader::Extract(list.course);
|
||||
|
||||
// Mark this course as processed
|
||||
processedCourses.insert(list.course);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelLoader::Extract(Course* course) {
|
||||
Course* saveCourse = gWorldInstance.CurrentCourse;
|
||||
gWorldInstance.CurrentCourse = course; // Quick hack so that `get_texture` will find the right textures.
|
||||
|
||||
size_t vtxSize = (ResourceGetSizeByName(course->vtx) / sizeof(CourseVtx)) * sizeof(Vtx);
|
||||
size_t texSegSize;
|
||||
|
||||
// Convert course vtx to vtx
|
||||
Vtx* vtx = reinterpret_cast<Vtx*>(malloc(vtxSize));
|
||||
if (vtx == NULL) {
|
||||
printf("ModelLoader: Failed to allocate vertex buffer for course: %s\n", course->Props.Name);
|
||||
return;
|
||||
}
|
||||
func_802A86A8(reinterpret_cast<CourseVtx*>(LOAD_ASSET_RAW(course->vtx)), vtx, vtxSize / sizeof(Vtx));
|
||||
|
||||
// Extract packed DLs
|
||||
u8* packed = reinterpret_cast<u8*>(LOAD_ASSET_RAW(course->gfx));
|
||||
Gfx* gfx = reinterpret_cast<Gfx*>(malloc(sizeof(Gfx) * course->gfxSize)); // Size of unpacked DLs
|
||||
if (gfx == NULL) {
|
||||
printf("ModelLoader: Failed to allocate course displaylist memory for course: %s\n", course->Props.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
displaylist_unpack(reinterpret_cast<uintptr_t*>(gfx), reinterpret_cast<uintptr_t>(packed), 0);
|
||||
|
||||
// Now that the data has been retrieved, extract the model data and save to provided buffers.
|
||||
for (auto& list : _deferredList) {
|
||||
// Ensure the list matches the course being extracted.
|
||||
if (list.course != course) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(list.vtxBuffer, &vtx[list.vtxStart], list.vtxBufferSize * sizeof(Vtx));
|
||||
memcpy(list.gfxBuffer, &gfx[list.gfxStart], list.gfxBufferSize * sizeof(Gfx));
|
||||
|
||||
UpdateVtx(list);
|
||||
|
||||
}
|
||||
|
||||
free(vtx);
|
||||
free(gfx);
|
||||
|
||||
_deferredList.clear();
|
||||
gWorldInstance.CurrentCourse = saveCourse;
|
||||
}
|
||||
|
||||
void ModelLoader::UpdateVtx(LoadModelList list) {
|
||||
for (size_t i = 0; i < list.gfxStart + list.gfxBufferSize; i++) {
|
||||
Gfx* gfx = &list.gfxBuffer[i];
|
||||
|
||||
// Check if the current Gfx command is G_VTX
|
||||
if (GFX_GET_OPCODE(gfx->words.w0) == (G_VTX << 24)) {
|
||||
// Re-write the vtx to point at the provided vtx buffer.
|
||||
size_t vtxIndex = (gfx->words.w1 / sizeof(Vtx)) - list.vtxStart;
|
||||
gfx->words.w1 = reinterpret_cast<uintptr_t>(&list.vtxBuffer[vtxIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <libultraship.h>
|
||||
#include "engine/courses/Course.h"
|
||||
|
||||
extern "C" {
|
||||
#include "common_structs.h"
|
||||
}
|
||||
|
||||
class Course;
|
||||
|
||||
/**
|
||||
*
|
||||
* Lists are deferred until load time so that models that use the same course may all use the same extraction
|
||||
*
|
||||
* Note ensure that the buffers passed to LoadModelList are big enough for the requested data.
|
||||
*
|
||||
* This class should only be ran once.
|
||||
*
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* ModelLoader::LoadModelList bowserStatueList = {
|
||||
.course = gBowsersCastle,
|
||||
.gfxBuffer = &gBowserStatueGfx[0],
|
||||
.gfxBufferSize = 162,
|
||||
.gfxStart = (0x2BB8 / 8), // This is 0x2BB8 / sizeof(N64Gfx) not sizeof(Gfx)
|
||||
.vtxBuffer = &gBowserStatueVtx[0],
|
||||
.vtxBufferSize = 717,
|
||||
.vtxStart = 1942,
|
||||
};
|
||||
*
|
||||
* gModelLoader.Add(bowserStatueList);
|
||||
*/
|
||||
|
||||
class ModelLoader {
|
||||
|
||||
public:
|
||||
struct LoadModelList {
|
||||
Course* course;
|
||||
|
||||
Gfx* gfxBuffer; // buffer for output gfx
|
||||
size_t gfxBufferSize;
|
||||
size_t gfxStart; // The starting point to extract data in NumGfx
|
||||
|
||||
Vtx* vtxBuffer; // buffer for output vtx
|
||||
size_t vtxBufferSize;
|
||||
size_t vtxStart; // The starting point to extract data in NumVtx
|
||||
};
|
||||
|
||||
void Add(LoadModelList list);
|
||||
void Load();
|
||||
private:
|
||||
struct CourseMap {
|
||||
|
||||
};
|
||||
|
||||
void Extract(Course* course);
|
||||
void UpdateVtx(LoadModelList list);
|
||||
|
||||
std::vector<LoadModelList> _deferredList;
|
||||
bool _hasRan = false;
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "BowserStatue.h"
|
||||
|
||||
#include <libultra/gbi.h>
|
||||
|
||||
extern "C" {
|
||||
#include "common_structs.h"
|
||||
#include "math_util.h"
|
||||
#include "main.h"
|
||||
#include "assets/bowsers_castle_data.h"
|
||||
}
|
||||
|
||||
Vtx gBowserStatueVtx[717];
|
||||
Gfx gBowserStatueGfx[162];
|
||||
|
||||
ABowserStatue::ABowserStatue(FVector pos, ABowserStatue::Behaviour behaviour) {
|
||||
Pos = pos;
|
||||
ABowserStatue::Behaviour _behaviour = behaviour;
|
||||
}
|
||||
|
||||
void ABowserStatue::Tick() {
|
||||
switch(_behaviour) {
|
||||
case DEFAULT:
|
||||
break;
|
||||
case CRUSH:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ABowserStatue::Draw(Camera *camera) {
|
||||
Mat4 mtx;
|
||||
Vec3f pos;
|
||||
pos[0] = Pos.x + 76;
|
||||
pos[1] = Pos.y;
|
||||
pos[2] = Pos.z + 1846;
|
||||
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
|
||||
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
|
||||
|
||||
mtxf_pos_rotation_xyz(mtx, pos, Rot);
|
||||
if (render_set_position(mtx, 0) != 0) {
|
||||
|
||||
gSPDisplayList(gDisplayListHead++, gBowserStatueGfx);
|
||||
}
|
||||
}
|
||||
|
||||
bool ABowserStatue::IsMod() { return true; }
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <libultraship.h>
|
||||
#include <libultra/gbi.h>
|
||||
#include "engine/Actor.h"
|
||||
#include "CoreMath.h"
|
||||
|
||||
extern "C" {
|
||||
#include "common_structs.h"
|
||||
#include "assets/other_textures.h"
|
||||
}
|
||||
|
||||
extern Vtx gBowserStatueVtx[717];
|
||||
extern Gfx gBowserStatueGfx[162];
|
||||
|
||||
class ABowserStatue : public AActor {
|
||||
public:
|
||||
enum Behaviour {
|
||||
DEFAULT,
|
||||
CRUSH
|
||||
};
|
||||
|
||||
virtual ~ABowserStatue() = default;
|
||||
explicit ABowserStatue(FVector pos, ABowserStatue::Behaviour behaviour);
|
||||
|
||||
virtual void Tick() override;
|
||||
virtual void Draw(Camera*) override;
|
||||
virtual bool IsMod() override;
|
||||
|
||||
FVector Pos;
|
||||
private:
|
||||
ABowserStatue::Behaviour _behaviour;
|
||||
f32 scale;
|
||||
};
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "TestCourse.h"
|
||||
#include "World.h"
|
||||
#include "engine/actors/AFinishline.h"
|
||||
#include "engine/actors/BowserStatue.h"
|
||||
#include "engine/objects/Object.h"
|
||||
#include "engine/objects/BombKart.h"
|
||||
#include "assets/mario_raceway_data.h"
|
||||
@@ -207,14 +208,15 @@ void TestCourse::SpawnActors() {
|
||||
// gWorldInstance.AddObject(new OCheepCheep(FVector(0, 40, 0), OCheepCheep::CheepType::RACE, IPathSpan(0, 10)));
|
||||
// gWorldInstance.AddObject(new OTrophy(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH));
|
||||
//gWorldInstance.AddObject(new OSnowman(FVector(0, 0, 0)));
|
||||
//gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), FRotation(0, 90, 0), 1.0f));
|
||||
//gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), FRotation(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
|
||||
|
||||
//gWorldInstance.AddEmitter(new StarEmitter(FVector(0,50,0)));
|
||||
//gWorldInstance.AddObject(new OHedgehog(FVector(0, 0, 0), FVector2D(0, -200), 9));
|
||||
//gWorldInstance.AddObject(new OFlagpole(FVector(0, 0, -200), 0x400));
|
||||
// gWorldInstance.AddObject(new OHotAirBalloon(FVector(0.0, 20.0f, -200.0f)));
|
||||
|
||||
gWorldInstance.AddObject(new OCrab(FVector2D(0, 0), FVector2D(0, -200)));
|
||||
//gWorldInstance.AddObject(new OCrab(FVector2D(0, 0), FVector2D(0, -200)));
|
||||
gWorldInstance.AddActor(new ABowserStatue(FVector(-200, 0, 0), ABowserStatue::Behaviour::CRUSH));
|
||||
}
|
||||
|
||||
// Likely sets minimap boundaries
|
||||
|
||||
@@ -35,7 +35,7 @@ typedef struct {
|
||||
freecamSaveState fState;
|
||||
|
||||
u32 fRankIndex = 0;
|
||||
u32 fTargetPlayer = true;
|
||||
u32 fTargetPlayer = false;
|
||||
u32 fMode; // freecam mode should probably be an enum
|
||||
u32 fModeInit = false;
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
#include "engine/courses/PodiumCeremony.h"
|
||||
|
||||
#include "engine/ModelLoader.h"
|
||||
#include "engine/actors/BowserStatue.h"
|
||||
|
||||
#include "engine/GarbageCollector.h"
|
||||
|
||||
#include "engine/TrainCrossing.h"
|
||||
@@ -86,6 +89,8 @@ Cup* gStarCup;
|
||||
Cup* gSpecialCup;
|
||||
Cup* gBattleCup;
|
||||
|
||||
ModelLoader gModelLoader;
|
||||
|
||||
void CustomEngineInit() {
|
||||
|
||||
gMarioRaceway = new MarioRaceway();
|
||||
@@ -152,6 +157,20 @@ void CustomEngineInit() {
|
||||
gWorldInstance.CurrentCup = gMushroomCup;
|
||||
gWorldInstance.CurrentCup->CursorPosition = 3;
|
||||
gWorldInstance.CupIndex = 0;
|
||||
|
||||
ModelLoader::LoadModelList bowserStatueList = {
|
||||
.course = gBowsersCastle,
|
||||
.gfxBuffer = &gBowserStatueGfx[0],
|
||||
.gfxBufferSize = 162,
|
||||
.gfxStart = (0x2BB8 / 8), // 0x2BB8 / sizeof(OldGfx)
|
||||
.vtxBuffer = &gBowserStatueVtx[0],
|
||||
.vtxBufferSize = 717,
|
||||
.vtxStart = 1942,
|
||||
};
|
||||
|
||||
gModelLoader.Add(bowserStatueList);
|
||||
|
||||
gModelLoader.Load();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
Reference in New Issue
Block a user