mirror of
https://github.com/BanjoRecomp/BanjoRecomp
synced 2026-05-23 06:34:20 -04:00
Add vertex position overrides for water mesh in TTC. (#51)
* Add vertex position overrides for water mesh in TTC. * Fix missing geometry. * Change asset ID. * Fix iterators. * Add bounds check. * Fix shrapnel by unconditionally setting up skinning data.
This commit is contained in:
@@ -188,10 +188,10 @@ RECOMP_PATCH void actor_predrawMethod(Actor *this){
|
||||
}
|
||||
}
|
||||
|
||||
if(this->unkF4_30){
|
||||
// @recomp Set up skinning data for this actor.
|
||||
recomp_setup_marker_skinning(this->marker);
|
||||
// @recomp Set up skinning data for this actor.
|
||||
recomp_setup_marker_skinning(this->marker);
|
||||
|
||||
if(this->unkF4_30){
|
||||
sp40 = func_80330C74(this);
|
||||
if(this->unk138_29){
|
||||
sp34[0] = this->pitch;
|
||||
|
||||
@@ -44,6 +44,7 @@ extern u32 heap_occupiedBytes;
|
||||
extern u32 dynamic_camera_target_index;
|
||||
|
||||
extern void recomp_reset_skinning_stack();
|
||||
extern void recomp_reset_map_model_skinning();
|
||||
extern void recomp_advance_dynamic_camera_targets();
|
||||
|
||||
// @recomp Patched to not free anything.
|
||||
@@ -89,8 +90,9 @@ RECOMP_PATCH void game_draw(s32 arg0){
|
||||
getGraphicsStacks(&gfx, &mtx, &vtx);
|
||||
}
|
||||
|
||||
// @recomp Reset the high precision position skinning stack.
|
||||
// @recomp Reset the high precision position skinning stacks.
|
||||
recomp_reset_skinning_stack();
|
||||
recomp_reset_map_model_skinning();
|
||||
|
||||
// @recomp Advance the frame used as reference by the dynamic camera target changes for analog camera.
|
||||
recomp_advance_dynamic_camera_targets();
|
||||
|
||||
@@ -4,6 +4,27 @@
|
||||
#include "core2/anctrl.h"
|
||||
#include "core2/modelRender.h"
|
||||
|
||||
typedef struct struct_1D_s {
|
||||
BKModel *model;
|
||||
s16 unk4;
|
||||
u8 xform_id;
|
||||
// u8 pad7[1];
|
||||
Struct70s unk8;//union of subtypes
|
||||
}struct1Ds;
|
||||
|
||||
extern struct {
|
||||
u8 unk0;
|
||||
vector(struct1Ds) *unk4;
|
||||
} D_80386140;
|
||||
|
||||
typedef struct struct_1E_s {
|
||||
void (*unk0)(void *arg0, s32 arg1, s32 arg2, s32 arg3);
|
||||
void (*unk4)(void *arg0, s32 arg1, s32 arg2);
|
||||
void (*unk8)(void *arg0);
|
||||
}struct1Es;
|
||||
|
||||
extern struct1Es D_80372030[];
|
||||
|
||||
s32 func_80320708(void);
|
||||
s32 levelSpecificFlags_validateCRC2(void);
|
||||
s32 dummy_func_80320248(void);
|
||||
@@ -18,6 +39,11 @@ bool fileProgressFlag_get(enum file_progress_e index);
|
||||
void modelRender_setAnimatedTexturesCacheId(s32 arg0);
|
||||
bool mapModel_has_xlu_bin(void);
|
||||
void func_802F7BC0(Gfx **, Mtx **, Vtx **);
|
||||
void func_8034E660(s32 arg0, BKVtxRef *src, Vtx *dst, s32 arg3);
|
||||
void BKModel_transformMesh(BKModel *model, s32 mesh_id, void (*fn)(s32, BKVtxRef *, Vtx *, s32), s32 arg3);
|
||||
|
||||
void recomp_setup_map_skinning(int map_model_id, float *pos_floats);
|
||||
void recomp_clear_map_skinning();
|
||||
|
||||
typedef struct {
|
||||
s16 map_id; //enum map_e
|
||||
@@ -173,6 +199,97 @@ RECOMP_PATCH void mapModel_opa_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Reserve a static amount of memory to be used for storing the current modifications to the map model with higher precision floats.
|
||||
#define MAP_MODEL_XLU_VERTEX_COUNT_MAX 0x400
|
||||
f32 map_model_xlu_pos_floats[MAP_MODEL_XLU_VERTEX_COUNT_MAX * 3];
|
||||
u32 map_model_xlu_pos_floats_count = 0;
|
||||
|
||||
void recomp_reset_map_model_skinning() {
|
||||
map_model_xlu_pos_floats_count = 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to store the moved water vertices with higher precision floats.
|
||||
RECOMP_PATCH void func_8034E8E4(Struct73s *arg0, BKModel *arg1, s32 arg2) {
|
||||
f32 sp3C;
|
||||
f32 sp38;
|
||||
f32 sp30[2];
|
||||
f32 sin;
|
||||
f32 cos;
|
||||
f32 sp2C;
|
||||
f32 sp28;
|
||||
|
||||
sp38 = time_getDelta();
|
||||
arg0->unk4 += sp38;
|
||||
cos = cosf(arg0->unk4 * 0.2 * BAD_PI);
|
||||
sin = sinf(arg0->unk4 * 0.08 * BAD_PI);
|
||||
sp30[0] = (sin * 100.0f + 150.0f * cos) * 0.8;
|
||||
|
||||
|
||||
cos = sinf(arg0->unk4 * 0.5 * BAD_PI);
|
||||
sin = cosf(arg0->unk4 * 0.22 * BAD_PI);
|
||||
sp30[1] = (sin * 100.0f + 50.0f * cos) * 0.8;
|
||||
|
||||
arg0->d_tc[0] = (sp30[0] >= 0.0) ? sp30[0] + 0.5 : sp30[0] - 0.5;
|
||||
arg0->d_tc[1] = (sp30[1] >= 0.0) ? sp30[1] + 0.5 : sp30[1] - 0.5;
|
||||
|
||||
cos = cosf(arg0->unk4 * 0.5 * BAD_PI);
|
||||
sin = sinf(arg0->unk4 * 0.11 * BAD_PI);
|
||||
sp2C = sin * (arg0->unk8 * 0.25) + (arg0->unk8 * 0.75) * cos;
|
||||
|
||||
if (arg0->unk14 < arg0->unk1C) {
|
||||
arg0->unk18 = arg0->unk14;
|
||||
arg0->unk14 += sp38;
|
||||
if (arg0->unk1C < arg0->unk14) {
|
||||
arg0->unk14 = arg0->unk1C;
|
||||
}
|
||||
}
|
||||
sp28 = ((arg0->unk14 < arg0->unk1C) ? arg0->unkC + ((arg0->unk14 / arg0->unk1C) * (arg0->unkE - arg0->unkC)) : arg0->unkE);
|
||||
sp28 += sp2C;
|
||||
arg0->dy = (sp28 >= 0.0) ? sp28 + 0.5 : sp28 - 0.5;
|
||||
BKModel_transformMesh(arg1, arg2, func_8034E660, (s32)arg0);
|
||||
|
||||
// @recomp Don't use high precision floats if the model exceeds the bounds of the floats array, in case the model was modified.
|
||||
if (arg1->vtxList_4->count <= MAP_MODEL_XLU_VERTEX_COUNT_MAX) {
|
||||
// @recomp Make sure to copy all the vertices from the model to the higher precision floats at least once per frame.
|
||||
s32 i, j = 0;
|
||||
if (map_model_xlu_pos_floats_count < arg1->vtxList_4->count) {
|
||||
Vtx *vtx = vtxList_getVertices(arg1->vtxList_4);
|
||||
for (i = 0; i < arg1->vtxList_4->count; i++) {
|
||||
map_model_xlu_pos_floats[j++] = vtx->v.ob[0];
|
||||
map_model_xlu_pos_floats[j++] = vtx->v.ob[1];
|
||||
map_model_xlu_pos_floats[j++] = vtx->v.ob[2];
|
||||
vtx++;
|
||||
}
|
||||
|
||||
map_model_xlu_pos_floats_count = arg1->vtxList_4->count;
|
||||
}
|
||||
|
||||
// @recomp Run the logic of BKModel_transformMesh again with only the modification of the Y component as seen in func_8034E660.
|
||||
// The result is stored in the higher precision floats instead of the model binary itself. The original value of dy is used
|
||||
// before it's rounded to make the animation smoother.
|
||||
BKMesh *iMesh = (BKMesh *)(arg1 + 1);
|
||||
BKVtxRef *iVtx;
|
||||
BKVtxRef *start_vtx_ref;
|
||||
BKVtxRef *end_vtx_ref;
|
||||
for (i = 0; i < arg1->meshList_0->meshCount_0; i++) {
|
||||
if (arg2 == iMesh->uid_0) {
|
||||
start_vtx_ref = (BKVtxRef *)(iMesh + 1);
|
||||
end_vtx_ref = start_vtx_ref + iMesh->vtxCount_2;
|
||||
for (iVtx = start_vtx_ref; iVtx < end_vtx_ref; iVtx++) {
|
||||
j = iVtx->unk10 * 3;
|
||||
map_model_xlu_pos_floats[j + 0] = iVtx->v.v.ob[0];
|
||||
map_model_xlu_pos_floats[j + 1] = iVtx->v.v.ob[1] + sp28;
|
||||
map_model_xlu_pos_floats[j + 2] = iVtx->v.v.ob[2];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
iMesh = (BKMesh *)(((BKVtxRef *)(iMesh + 1)) + iMesh->vtxCount_2);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set the transform ID when drawing the map's translucent model.
|
||||
RECOMP_PATCH void mapModel_xlu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
s32 temp_a0;
|
||||
@@ -192,11 +309,27 @@ RECOMP_PATCH void mapModel_xlu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
cur_drawn_model_is_map = TRUE;
|
||||
cur_drawn_model_transform_id = MAP_MODEL_XLU_TRANSFORM_ID_START;
|
||||
|
||||
// @recomp Because func_8034E8E4 runs after this function, run through the vector and see if there's a model that uses
|
||||
// the vertex modification function that was patched. The address must be hardcoded as it's not possible to retrieve
|
||||
// the right function address inside a recompiled patch by referencing func_8034E8E4 instead.
|
||||
BKVertexList *vtxList = (BKVertexList *)((s32)mapModel.model_bin_xlu + mapModel.model_bin_xlu->vtx_list_offset_10);
|
||||
if (vtxList->count <= MAP_MODEL_XLU_VERTEX_COUNT_MAX) {
|
||||
struct1Ds *iPtr;
|
||||
struct1Ds *endPtr = vector_getEnd(D_80386140.unk4);
|
||||
for (iPtr = vector_getBegin(D_80386140.unk4); iPtr < endPtr; iPtr++) {
|
||||
if (D_80372030[iPtr->xform_id].unk4 == 0x8034E8E4) {
|
||||
recomp_setup_map_skinning(mapModel.description->xlu_model_id, map_model_xlu_pos_floats);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modelRender_draw(gfx, mtx, NULL, NULL, mapModel.description->scale, NULL, mapModel.model_bin_xlu);
|
||||
|
||||
// @recomp Clear the current model transform id after drawing.
|
||||
cur_drawn_model_is_map = FALSE;
|
||||
cur_drawn_model_transform_id = 0;
|
||||
recomp_clear_map_skinning();
|
||||
|
||||
func_802F7BC0(gfx, mtx, vtx);
|
||||
}
|
||||
|
||||
+70
-43
@@ -217,7 +217,7 @@ bool set_model_matrix_group(Gfx **gfx, void *geo_list, bool skip_rotation) {
|
||||
// Use decomposed matrix interpolation on any other model.
|
||||
u8 interpolation_mode = cur_model_uses_bones ? G_EX_INTERPOLATE_SIMPLE : G_EX_INTERPOLATE_DECOMPOSE;
|
||||
u8 rotation_mode = skip_rotation ? G_EX_COMPONENT_SKIP : G_EX_COMPONENT_INTERPOLATE;
|
||||
u8 vertex_interpolation_mode = cur_drawn_model_is_map ? G_EX_COMPONENT_INTERPOLATE : G_EX_COMPONENT_SKIP;
|
||||
u8 vertex_interpolation_mode = cur_drawn_model_is_map && !cur_model_uses_ex_vertex ? G_EX_COMPONENT_INTERPOLATE : G_EX_COMPONENT_SKIP;
|
||||
u8 texcoord_interpolation_mode = cur_drawn_model_is_map ? G_EX_COMPONENT_INTERPOLATE : G_EX_COMPONENT_SKIP;
|
||||
gEXMatrixGroup((*gfx)++, group_id, interpolation_mode, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_COMPONENT_INTERPOLATE, rotation_mode,
|
||||
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, vertex_interpolation_mode, G_EX_COMPONENT_INTERPOLATE,
|
||||
@@ -464,6 +464,8 @@ ModelSkinningData *sCurModelSkinningData;
|
||||
u32 sCurModelId;
|
||||
|
||||
ModelSkinningData sOverlaySkinningData;
|
||||
ModelSkinningData sMapSkinningData;
|
||||
f32 *sMapSkinningPosFloats;
|
||||
|
||||
void recomp_setup_overlay_skinning(int overlay_id) {
|
||||
sCurModelSkinningData = &sOverlaySkinningData;
|
||||
@@ -489,7 +491,19 @@ void recomp_setup_marker_skinning(ActorMarker *marker) {
|
||||
sCurModelId = marker->modelId;
|
||||
}
|
||||
|
||||
bool recomp_apply_cpu_skinning(BKModelUnk28List *arg0, BKVertexList *arg1, AnimMtxList *mtx_list, float **pos, float **vel) {
|
||||
void recomp_setup_map_skinning(int map_model_id, float *pos_floats) {
|
||||
sCurModelSkinningData = &sMapSkinningData;
|
||||
sCurModelId = map_model_id;
|
||||
sMapSkinningPosFloats = pos_floats;
|
||||
}
|
||||
|
||||
void recomp_clear_map_skinning() {
|
||||
sCurModelSkinningData = NULL;
|
||||
sCurModelId = 0;
|
||||
sMapSkinningPosFloats = NULL;
|
||||
}
|
||||
|
||||
bool recomp_apply_cpu_skinning(BKModelUnk28List *arg0, BKVertexList *arg1, AnimMtxList *mtx_list, float *pos_override, float **pos, float **vel) {
|
||||
*pos = NULL;
|
||||
*vel = NULL;
|
||||
|
||||
@@ -509,12 +523,18 @@ bool recomp_apply_cpu_skinning(BKModelUnk28List *arg0, BKVertexList *arg1, AnimM
|
||||
}
|
||||
|
||||
// Copy unmodified positions.
|
||||
float *dst_pos = &sSkinningPosFloats[sSkinningFloatFrame & 0x1][sSkinningFloatCount];
|
||||
s32 i, j = 0;
|
||||
for (i = 0; i < arg1->count; i++) {
|
||||
dst_pos[j++] = arg1->vtx_18[i].v.ob[0];
|
||||
dst_pos[j++] = arg1->vtx_18[i].v.ob[1];
|
||||
dst_pos[j++] = arg1->vtx_18[i].v.ob[2];
|
||||
float *dst_pos = &sSkinningPosFloats[sSkinningFloatFrame & 0x1][sSkinningFloatCount];
|
||||
float *dst_vel = &sSkinningVelFloats[sSkinningFloatCount];
|
||||
if (pos_override != NULL) {
|
||||
memcpy(dst_pos, pos_override, sizeof(float) * arg1->count * 3);
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < arg1->count; i++) {
|
||||
dst_pos[j++] = arg1->vtx_18[i].v.ob[0];
|
||||
dst_pos[j++] = arg1->vtx_18[i].v.ob[1];
|
||||
dst_pos[j++] = arg1->vtx_18[i].v.ob[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Increase the current float count. Always align to multiples of 2.
|
||||
@@ -523,38 +543,39 @@ bool recomp_apply_cpu_skinning(BKModelUnk28List *arg0, BKVertexList *arg1, AnimM
|
||||
sSkinningFloatCount++;
|
||||
}
|
||||
|
||||
// Apply animation.
|
||||
BKModelUnk28 *i_ptr = (BKModelUnk28 *)(arg0 + 1);
|
||||
s32 mtx_index = -2;
|
||||
f32 src_coord[3];
|
||||
f32 dst_coord[3];
|
||||
s32 vertex_index;
|
||||
for (i = 0; i < arg0->count; i++) {
|
||||
if (mtx_index != i_ptr->anim_index) {
|
||||
mtx_index = i_ptr->anim_index;
|
||||
mlMtxSet(animMtxList_get(mtx_list, mtx_index));
|
||||
if (arg0 != NULL) {
|
||||
// Apply animation.
|
||||
BKModelUnk28 *i_ptr = (BKModelUnk28 *)(arg0 + 1);
|
||||
s32 mtx_index = -2;
|
||||
f32 src_coord[3];
|
||||
f32 dst_coord[3];
|
||||
s32 vertex_index;
|
||||
for (i = 0; i < arg0->count; i++) {
|
||||
if (mtx_index != i_ptr->anim_index) {
|
||||
mtx_index = i_ptr->anim_index;
|
||||
mlMtxSet(animMtxList_get(mtx_list, mtx_index));
|
||||
}
|
||||
|
||||
src_coord[0] = i_ptr->coord[0];
|
||||
src_coord[1] = i_ptr->coord[1];
|
||||
src_coord[2] = i_ptr->coord[2];
|
||||
mlMtx_apply_vec3f(dst_coord, src_coord);
|
||||
|
||||
for (j = 0; j < i_ptr->vtx_count; j++) {
|
||||
vertex_index = i_ptr->vtx_list[j] * 3;
|
||||
dst_pos[vertex_index++] = dst_coord[0];
|
||||
dst_pos[vertex_index++] = dst_coord[1];
|
||||
dst_pos[vertex_index] = dst_coord[2];
|
||||
}
|
||||
|
||||
i_ptr = (BKModelUnk28 *)((s16 *)(i_ptr + 1) + (i_ptr->vtx_count - 1));
|
||||
}
|
||||
|
||||
src_coord[0] = i_ptr->coord[0];
|
||||
src_coord[1] = i_ptr->coord[1];
|
||||
src_coord[2] = i_ptr->coord[2];
|
||||
mlMtx_apply_vec3f(dst_coord, src_coord);
|
||||
|
||||
for (j = 0; j < i_ptr->vtx_count; j++) {
|
||||
vertex_index = i_ptr->vtx_list[j] * 3;
|
||||
dst_pos[vertex_index++] = dst_coord[0];
|
||||
dst_pos[vertex_index++] = dst_coord[1];
|
||||
dst_pos[vertex_index] = dst_coord[2];
|
||||
}
|
||||
|
||||
i_ptr = (BKModelUnk28 *)((s16 *)(i_ptr + 1) + (i_ptr->vtx_count - 1));
|
||||
}
|
||||
|
||||
// Compute velocities if applicable.
|
||||
// To apply, the frame index stored on the extended marker data must be exactly the previous frame and the model ID must match.
|
||||
if (prev_skinning_data.frameCount == sSkinningFloatFrame - 1 && prev_skinning_data.modelId == cur_model_id) {
|
||||
const float *prev_pos = &sSkinningPosFloats[(sSkinningFloatFrame & 0x1) ^ 1][prev_skinning_data.floatStart];
|
||||
float *dst_vel = &sSkinningVelFloats[sSkinningFloatCount];
|
||||
j = 0;
|
||||
for (i = 0; i < arg1->count; i++) {
|
||||
for (s32 k = 0; k < 3; k++) {
|
||||
@@ -562,6 +583,7 @@ bool recomp_apply_cpu_skinning(BKModelUnk28List *arg0, BKVertexList *arg1, AnimM
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
*vel = dst_vel;
|
||||
}
|
||||
|
||||
@@ -826,23 +848,28 @@ RECOMP_PATCH BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3],
|
||||
}
|
||||
|
||||
// @recomp Use higher precision vertex buffer when the model requires CPU skinning.
|
||||
f32 *skinned_pos = NULL, *skinned_vel = NULL;
|
||||
cur_model_uses_ex_vertex = FALSE;
|
||||
|
||||
if(model_bin->unk28 != NULL && D_8038371C != NULL){
|
||||
func_802E6BD0((u8*)modelRenderModelBin + modelRenderModelBin->unk28, modelRendervertexList, D_8038371C);
|
||||
|
||||
// @recomp Do the skinning again on a high precision version of the vertex buffer. Force its usage for any subsequent display lists.
|
||||
f32 *skinned_pos, *skinned_vel;
|
||||
if (recomp_apply_cpu_skinning((u8 *)modelRenderModelBin + modelRenderModelBin->unk28, modelRendervertexList, D_8038371C, &skinned_pos, &skinned_vel)) {
|
||||
gEXSetVertexSegment((*gfx)++, G_EX_VERTEX_POSITION, G_EX_ENABLED, skinned_pos, &modelRendervertexList->vtx_18);
|
||||
if (skinned_vel != NULL) {
|
||||
gEXSetVertexSegment((*gfx)++, G_EX_VERTEX_VELOCITY, G_EX_ENABLED, skinned_vel, &modelRendervertexList->vtx_18);
|
||||
}
|
||||
else {
|
||||
gEXSetVertexSegment((*gfx)++, G_EX_VERTEX_VELOCITY, G_EX_DISABLED, 0, 0);
|
||||
}
|
||||
cur_model_uses_ex_vertex = TRUE;
|
||||
recomp_apply_cpu_skinning((u8 *)modelRenderModelBin + modelRenderModelBin->unk28, modelRendervertexList, D_8038371C, NULL, &skinned_pos, &skinned_vel);
|
||||
}
|
||||
// @recomp Apply skinning using the floats applied by the map model.
|
||||
else if (sMapSkinningPosFloats != NULL) {
|
||||
recomp_apply_cpu_skinning(NULL, modelRendervertexList, NULL, sMapSkinningPosFloats, &skinned_pos, &skinned_vel);
|
||||
}
|
||||
|
||||
if (skinned_pos != NULL) {
|
||||
gEXSetVertexSegment((*gfx)++, G_EX_VERTEX_POSITION, G_EX_ENABLED, skinned_pos, &modelRendervertexList->vtx_18);
|
||||
|
||||
if (skinned_vel != NULL) {
|
||||
gEXSetVertexSegment((*gfx)++, G_EX_VERTEX_VELOCITY, G_EX_ENABLED, skinned_vel, &modelRendervertexList->vtx_18);
|
||||
}
|
||||
|
||||
cur_model_uses_ex_vertex = TRUE;
|
||||
}
|
||||
|
||||
mlMtxIdent();
|
||||
@@ -874,7 +901,7 @@ RECOMP_PATCH BKModelBin *modelRender_draw(Gfx **gfx, Mtx **mtx, f32 position[3],
|
||||
gEXMatrixGroupSkipAll((*gfx)++, cur_drawn_model_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
pushed_matrix_group = TRUE;
|
||||
}
|
||||
else if (cur_drawn_model_is_map) {
|
||||
else if (cur_drawn_model_is_map && !cur_model_uses_ex_vertex) {
|
||||
gEXMatrixGroupDecomposedVerts((*gfx)++, cur_drawn_model_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
pushed_matrix_group = TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user