mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-05-10 10:51:39 +00:00
Scale bone anim support (#1215)
* Scale bone anim support Code changes provided by ExcellentGamer. Supports model anims which modify scale. * Peachy code changes by ExcellentGamer * Autogen constants * changed vc3f_set to vec3f_copy
This commit is contained in:
parent
95782f447c
commit
f688416483
6 changed files with 87 additions and 25 deletions
|
|
@ -11220,6 +11220,9 @@ ANIM_FLAG_7 = (1 << 7)
|
|||
--- @type integer
|
||||
ANIM_FLAG_BONE_TRANS = (1 << 8)
|
||||
|
||||
--- @type integer
|
||||
ANIM_FLAG_BONE_SCALE = (1 << 9)
|
||||
|
||||
--- @type integer
|
||||
OBJECT_MAX_BHV_STACK = 16
|
||||
|
||||
|
|
|
|||
|
|
@ -45,8 +45,16 @@ static s32 RetrieveCurrentAnimationIndex(struct Object *aObject) {
|
|||
void DynOS_Anim_Swap(void *aPtr) {
|
||||
if (!aPtr) { return; }
|
||||
|
||||
static Animation *pDefaultAnimation = NULL;
|
||||
static Animation sGfxDataAnimation;
|
||||
// Must support nested calls (held objects render inside other object render)
|
||||
// and interleaving objects without corrupting swap state.
|
||||
struct AnimSwapFrame {
|
||||
struct Object *obj;
|
||||
Animation *defaultAnim;
|
||||
Animation gfxDataAnim;
|
||||
};
|
||||
|
||||
static AnimSwapFrame sAnimSwapFrames[32] = { 0 };
|
||||
static s32 sCurrAnimSwapIndex = 0;
|
||||
|
||||
// Does the object have a model?
|
||||
struct Object *_Object = (struct Object *) aPtr;
|
||||
|
|
@ -54,9 +62,20 @@ void DynOS_Anim_Swap(void *aPtr) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Determine if this call is the "swap" phase or "restore" phase.
|
||||
// The engine calls DynOS_Anim_Swap twice around geo_set_animation_globals.
|
||||
const bool restoring = (sCurrAnimSwapIndex > 0 && sAnimSwapFrames[sCurrAnimSwapIndex - 1].obj == _Object);
|
||||
|
||||
// Swap the current animation with the one from the Gfx data
|
||||
if (!pDefaultAnimation) {
|
||||
pDefaultAnimation = _Object->header.gfx.animInfo.curAnim;
|
||||
if (!restoring) {
|
||||
if (sCurrAnimSwapIndex >= (s32) ARRAY_COUNT(sAnimSwapFrames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AnimSwapFrame *frame = &sAnimSwapFrames[sCurrAnimSwapIndex];
|
||||
frame->obj = _Object;
|
||||
frame->defaultAnim = _Object->header.gfx.animInfo.curAnim;
|
||||
sCurrAnimSwapIndex++;
|
||||
|
||||
// ActorGfx data
|
||||
ActorGfx* _ActorGfx = DynOS_Actor_GetActorGfx(_Object->header.gfx.sharedChild);
|
||||
|
|
@ -100,23 +119,26 @@ void DynOS_Anim_Swap(void *aPtr) {
|
|||
// Animation data
|
||||
const AnimData *_AnimData = (const AnimData *) _GfxData->mAnimationTable[_AnimIndex].second;
|
||||
if (_AnimData) {
|
||||
sGfxDataAnimation.flags = _AnimData->mFlags;
|
||||
sGfxDataAnimation.animYTransDivisor = _AnimData->mUnk02;
|
||||
sGfxDataAnimation.startFrame = _AnimData->mUnk04;
|
||||
sGfxDataAnimation.loopStart = _AnimData->mUnk06;
|
||||
sGfxDataAnimation.loopEnd = _AnimData->mUnk08;
|
||||
sGfxDataAnimation.unusedBoneCount = _AnimData->mUnk0A.second;
|
||||
sGfxDataAnimation.values = (u16*)_AnimData->mValues.second.begin();
|
||||
sGfxDataAnimation.index = (u16*)_AnimData->mIndex.second.begin();
|
||||
sGfxDataAnimation.valuesLength = _AnimData->mValues.second.Count();
|
||||
sGfxDataAnimation.indexLength = _AnimData->mIndex.second.Count();
|
||||
sGfxDataAnimation.length = _AnimData->mLength;
|
||||
_Object->header.gfx.animInfo.curAnim = &sGfxDataAnimation;
|
||||
frame->gfxDataAnim.flags = _AnimData->mFlags;
|
||||
frame->gfxDataAnim.animYTransDivisor = _AnimData->mUnk02;
|
||||
frame->gfxDataAnim.startFrame = _AnimData->mUnk04;
|
||||
frame->gfxDataAnim.loopStart = _AnimData->mUnk06;
|
||||
frame->gfxDataAnim.loopEnd = _AnimData->mUnk08;
|
||||
frame->gfxDataAnim.unusedBoneCount = _AnimData->mUnk0A.second;
|
||||
frame->gfxDataAnim.values = (u16*) _AnimData->mValues.second.begin();
|
||||
frame->gfxDataAnim.index = (u16*) _AnimData->mIndex.second.begin();
|
||||
frame->gfxDataAnim.valuesLength = _AnimData->mValues.second.Count();
|
||||
frame->gfxDataAnim.indexLength = _AnimData->mIndex.second.Count();
|
||||
frame->gfxDataAnim.length = _AnimData->mLength;
|
||||
_Object->header.gfx.animInfo.curAnim = &frame->gfxDataAnim;
|
||||
}
|
||||
|
||||
// Restore the default animation
|
||||
} else {
|
||||
_Object->header.gfx.animInfo.curAnim = pDefaultAnimation;
|
||||
pDefaultAnimation = NULL;
|
||||
sCurrAnimSwapIndex--;
|
||||
AnimSwapFrame *frame = &sAnimSwapFrames[sCurrAnimSwapIndex];
|
||||
_Object->header.gfx.animInfo.curAnim = frame->defaultAnim;
|
||||
frame->obj = NULL;
|
||||
frame->defaultAnim = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4730,6 +4730,7 @@
|
|||
- ANIM_FLAG_6
|
||||
- ANIM_FLAG_7
|
||||
- ANIM_FLAG_BONE_TRANS
|
||||
- ANIM_FLAG_BONE_SCALE
|
||||
- OBJECT_MAX_BHV_STACK
|
||||
- OBJECT_NUM_REGULAR_FIELDS
|
||||
- OBJECT_NUM_CUSTOM_FIELDS
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ struct VblankHandler
|
|||
#define ANIM_FLAG_6 (1 << 6) // 0x40
|
||||
#define ANIM_FLAG_7 (1 << 7) // 0x80
|
||||
#define ANIM_FLAG_BONE_TRANS (1 << 8)
|
||||
#define ANIM_FLAG_BONE_SCALE (1 << 9)
|
||||
|
||||
struct Animation {
|
||||
// TODO: Optimize this later if possible.
|
||||
|
|
|
|||
|
|
@ -383,7 +383,6 @@ void patch_mtx_interpolated(f32 delta) {
|
|||
/**
|
||||
* Graph node interpolation
|
||||
*/
|
||||
|
||||
static void *sGraphNodeInterpDataMap = NULL;
|
||||
|
||||
struct GraphNodeInterpData *geo_get_interp_data(void *node, struct GraphNodeObject *obj) {
|
||||
|
|
@ -1059,7 +1058,7 @@ static void geo_process_background(struct GraphNodeBackground *node) {
|
|||
}
|
||||
}
|
||||
|
||||
static void anim_process(Vec3f translation, Vec3s rotation, u8 *animType, s16 animFrame, u16 **animAttribute) {
|
||||
static void anim_process(Vec3f translation, Vec3s rotation, Vec3f scale, u8 *animType, s16 animFrame, u16 **animAttribute) {
|
||||
if (*animType == ANIM_TYPE_TRANSLATION) {
|
||||
translation[0] += retrieve_animation_value(gCurAnim, animFrame, animAttribute) * gCurAnimTranslationMultiplier;
|
||||
translation[1] += retrieve_animation_value(gCurAnim, animFrame, animAttribute) * gCurAnimTranslationMultiplier;
|
||||
|
|
@ -1090,6 +1089,19 @@ static void anim_process(Vec3f translation, Vec3s rotation, u8 *animType, s16 an
|
|||
rotation[0] += retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
rotation[1] += retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
rotation[2] += retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
|
||||
if (gCurAnim->flags & ANIM_FLAG_BONE_SCALE) {
|
||||
s16 scaleX = retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
s16 scaleY = retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
s16 scaleZ = retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
|
||||
if (scale != NULL) {
|
||||
scale[0] *= ((f32) scaleX) / 256.0f;
|
||||
scale[1] *= ((f32) scaleY) / 256.0f;
|
||||
scale[2] *= ((f32) scaleZ) / 256.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (gCurAnim->flags & ANIM_FLAG_BONE_TRANS) {
|
||||
*animType = ANIM_TYPE_TRANSLATION;
|
||||
}
|
||||
|
|
@ -1108,6 +1120,7 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
|
|||
Mat4 matrix;
|
||||
Vec3s rotation;
|
||||
Vec3f translation;
|
||||
Vec3f scale;
|
||||
|
||||
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
||||
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
||||
|
|
@ -1118,8 +1131,10 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
|
|||
// current frame
|
||||
vec3s_copy(rotation, gVec3sZero);
|
||||
vec3s_to_vec3f(translation, node->translation);
|
||||
anim_process(translation, rotation, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
|
||||
vec3f_copy(scale, gVec3fOne);
|
||||
anim_process(translation, rotation, scale, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
|
||||
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
||||
mtxf_scale_vec3f(matrix, matrix, scale);
|
||||
mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]);
|
||||
|
||||
// previous frame
|
||||
|
|
@ -1130,8 +1145,10 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
|
|||
node->translation
|
||||
);
|
||||
vec3s_copy(rotation, gVec3sZero);
|
||||
anim_process(translation, rotation, &animType, gPrevAnimFrame, &animAttribute);
|
||||
vec3f_copy(scale, gVec3fOne);
|
||||
anim_process(translation, rotation, scale, &animType, gPrevAnimFrame, &animAttribute);
|
||||
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
||||
mtxf_scale_vec3f(matrix, matrix, scale);
|
||||
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]);
|
||||
);
|
||||
|
||||
|
|
@ -1420,8 +1437,12 @@ static s32 obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) {
|
|||
|
||||
static void geo_sanitize_object_gfx(void) {
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_OPAQUE);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_OPAQUE_DECAL);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_OPAQUE_INTER);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_ALPHA);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_TRANSPARENT);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_TRANSPARENT_DECAL);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_TRANSPARENT_INTER);
|
||||
}
|
||||
|
||||
static struct MarioBodyState *get_mario_body_state_from_mario_object(struct Object *marioObj) {
|
||||
|
|
@ -1688,6 +1709,7 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
|
|||
node->fnNode.func(GEO_CONTEXT_HELD_OBJ, &node->fnNode.node, (struct DynamicPool *) gMatStack[gMatStackIndex + 1]);
|
||||
}
|
||||
|
||||
s32 savedMatStackIndex = gMatStackIndex;
|
||||
// Increment the matrix stack, If we fail to do so. Just return.
|
||||
if (!increment_mat_stack()) { return; }
|
||||
|
||||
|
|
@ -1708,7 +1730,13 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
|
|||
}
|
||||
|
||||
geo_sanitize_object_gfx();
|
||||
// While rendering the held object's geo tree, ensure "current object" globals
|
||||
// refer to the held object, otherwise Lua geo callbacks can accidentally
|
||||
// mutate the holder's render state (e.g. make Wario limbs disappear).
|
||||
struct GraphNodeObject *savedCurGraphNodeObject = gCurGraphNodeObject;
|
||||
gCurGraphNodeObject = &node->objNode->header.gfx;
|
||||
geo_process_node_and_siblings(node->objNode->header.gfx.sharedChild);
|
||||
gCurGraphNodeObject = savedCurGraphNodeObject;
|
||||
gCurGraphNodeHeldObject = NULL;
|
||||
gCurAnimType = gGeoTempState.type;
|
||||
gCurAnimEnabled = gGeoTempState.enabled;
|
||||
|
|
@ -1717,7 +1745,13 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
|
|||
gCurrAnimAttribute = gGeoTempState.attribute;
|
||||
gCurAnim = gGeoTempState.anim;
|
||||
gPrevAnimFrame = gGeoTempState.prevFrame;
|
||||
gMatStackIndex--;
|
||||
// Force-restore matrix stack index to avoid any imbalance caused by
|
||||
// held object geo trees (including Lua geo callbacks).
|
||||
gMatStackIndex = savedMatStackIndex;
|
||||
|
||||
// Reset any render-state changes performed by the held object's geo tree
|
||||
// so the holder's remaining body parts render correctly.
|
||||
geo_sanitize_object_gfx();
|
||||
}
|
||||
|
||||
if (node->fnNode.node.children != NULL) {
|
||||
|
|
@ -1748,7 +1782,7 @@ static void geo_process_bone(struct GraphNodeBone *node) {
|
|||
vec3s_copy(rotation, node->rotation);
|
||||
vec3s_to_vec3f(translation, node->translation);
|
||||
vec3f_copy(scale, node->scale);
|
||||
anim_process(translation, rotation, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
|
||||
anim_process(translation, rotation, scale, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
|
||||
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
||||
mtxf_scale_vec3f(matrix, matrix, scale);
|
||||
mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]);
|
||||
|
|
@ -1764,7 +1798,7 @@ static void geo_process_bone(struct GraphNodeBone *node) {
|
|||
vec3s_to_vec3f(translation, node->translation);
|
||||
vec3f_copy(scale, node->scale);
|
||||
}
|
||||
anim_process(translation, rotation, &animType, gPrevAnimFrame, &animAttribute);
|
||||
anim_process(translation, rotation, scale, &animType, gPrevAnimFrame, &animAttribute);
|
||||
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
||||
mtxf_scale_vec3f(matrix, matrix, scale);
|
||||
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]);
|
||||
|
|
|
|||
|
|
@ -4666,6 +4666,7 @@ char gSmluaConstants[] = ""
|
|||
"ANIM_FLAG_6=(1 << 6)\n"
|
||||
"ANIM_FLAG_7=(1 << 7)\n"
|
||||
"ANIM_FLAG_BONE_TRANS=(1 << 8)\n"
|
||||
"ANIM_FLAG_BONE_SCALE=(1 << 9)\n"
|
||||
"OBJECT_MAX_BHV_STACK=16\n"
|
||||
"OBJECT_NUM_REGULAR_FIELDS=0x50\n"
|
||||
"OBJECT_NUM_CUSTOM_FIELDS=0x40\n"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue