From e54913f8afbc482c92ca52a32afad429a29647de Mon Sep 17 00:00:00 2001 From: Ivan Avdeev Date: Mon, 15 May 2023 09:27:35 -0700 Subject: [PATCH] rt: improve prev frame bone matrix tracking for studio models Still has some artifacts, but is generally rather close. Will look at this again when caching studio model BLASes, as we'd be able to look at them without extra animations. --- ref/vk/vk_previous_frame.c | 24 ++++++++++-------------- ref/vk/vk_previous_frame.h | 4 ++-- ref/vk/vk_render.h | 2 +- ref/vk/vk_studio.c | 18 +++++++++++++----- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/ref/vk/vk_previous_frame.c b/ref/vk/vk_previous_frame.c index f0a57c77..f6c87e58 100644 --- a/ref/vk/vk_previous_frame.c +++ b/ref/vk/vk_previous_frame.c @@ -58,8 +58,8 @@ prev_state_t* prevStateInArrayBounds( int frame_storage_id, int entity_id ) return &g_prev.prev_states[frame_storage_id][clamped_entity_id]; } -#define PREV_FRAME() prevStateInArrayBounds( g_prev.previous_frame_id, entity_id ) -#define CURRENT_FRAME() prevStateInArrayBounds( g_prev.current_frame_id, entity_id ) +#define PREV_FRAME(entity_id) prevStateInArrayBounds( g_prev.previous_frame_id, (entity_id) ) +#define CURRENT_FRAME(entity_id) prevStateInArrayBounds( g_prev.current_frame_id, (entity_id) ) void R_PrevFrame_StartFrame( void ) { @@ -70,7 +70,7 @@ void R_PrevFrame_StartFrame( void ) void R_PrevFrame_SaveCurrentBoneTransforms( int entity_id, matrix3x4* bones_transforms, const matrix4x4 rotationmatrix_inv ) { - prev_state_t *current_frame = CURRENT_FRAME(); + prev_state_t *current_frame = CURRENT_FRAME(entity_id); if (current_frame->bones_frame_updated == g_prev.frame_index) return; // already updated for this entity @@ -78,16 +78,12 @@ void R_PrevFrame_SaveCurrentBoneTransforms( int entity_id, matrix3x4* bones_tran current_frame->bones_frame_updated = g_prev.frame_index; for( int i = 0; i < MAXSTUDIOBONES; i++ ) - { - // FIXME I don't see how this can work. It has only a single copy of bones transforms, but they are not global, they're per-model - // Better way to handle this would be to avoid messing with bones_transforms at all, and just cache post-transformed vertices - Matrix3x4_ConcatTransforms( current_frame->bones_worldtransform[i], bones_transforms[i], rotationmatrix_inv ); - } + Matrix3x4_ConcatTransforms( current_frame->bones_worldtransform[i], rotationmatrix_inv, bones_transforms[i] ); } void R_PrevFrame_SaveCurrentState( int entity_id, matrix4x4 model_transform ) { - prev_state_t* current_frame = CURRENT_FRAME(); + prev_state_t* current_frame = CURRENT_FRAME(entity_id); if (current_frame->frame_updated == g_prev.frame_index) return; // already updated for this entity @@ -99,29 +95,29 @@ void R_PrevFrame_SaveCurrentState( int entity_id, matrix4x4 model_transform ) matrix3x4* R_PrevFrame_BoneTransforms( int entity_id ) { - prev_state_t* prev_frame = PREV_FRAME(); + prev_state_t* prev_frame = PREV_FRAME(entity_id); // fallback to current frame if previous is outdated if (prev_frame->bones_frame_updated != g_prev.frame_index - 1) - return CURRENT_FRAME()->bones_worldtransform; + return CURRENT_FRAME(entity_id)->bones_worldtransform; return prev_frame->bones_worldtransform; } void R_PrevFrame_ModelTransform( int entity_id, matrix4x4 model_matrix ) { - prev_state_t* prev_frame = PREV_FRAME(); + prev_state_t* prev_frame = PREV_FRAME(entity_id); // fallback to current frame if previous is outdated if (prev_frame->frame_updated != g_prev.frame_index - 1) - prev_frame = CURRENT_FRAME(); + prev_frame = CURRENT_FRAME(entity_id); Matrix4x4_Copy(model_matrix, prev_frame->model_transform); } float R_PrevFrame_Time( int entity_id ) { - prev_state_t* prev_frame = PREV_FRAME(); + prev_state_t* prev_frame = PREV_FRAME(entity_id); // fallback to current frame if previous is outdated if (prev_frame->frame_updated != g_prev.frame_index - 1) diff --git a/ref/vk/vk_previous_frame.h b/ref/vk/vk_previous_frame.h index 853d11d4..5841dc70 100644 --- a/ref/vk/vk_previous_frame.h +++ b/ref/vk/vk_previous_frame.h @@ -3,8 +3,8 @@ #include "vk_common.h" void R_PrevFrame_StartFrame(void); -void R_PrevFrame_SaveCurrentBoneTransforms( int entity_id, matrix3x4* bones_transforms, const matrix4x4 rotationmatrix_inv ); +void R_PrevFrame_SaveCurrentBoneTransforms(int entity_id, matrix3x4* bones_transforms, const matrix4x4 rotationmatrix_inv); void R_PrevFrame_SaveCurrentState(int entity_id, matrix4x4 model_transform); matrix3x4* R_PrevFrame_BoneTransforms(int entity_id); -void R_PrevFrame_ModelTransform( int entity_id, matrix4x4 model_matrix ); +void R_PrevFrame_ModelTransform(int entity_id, matrix4x4 model_matrix); float R_PrevFrame_Time(int entity_id); diff --git a/ref/vk/vk_render.h b/ref/vk/vk_render.h index 3764cea0..6ee50cfb 100644 --- a/ref/vk/vk_render.h +++ b/ref/vk/vk_render.h @@ -134,7 +134,7 @@ qboolean VK_RenderModelInit( vk_render_model_t* model ); void VK_RenderModelDestroy( vk_render_model_t* model ); void VK_RenderModelDraw( const cl_entity_t *ent, vk_render_model_t* model ); -void VK_RenderModelDynamicBegin( vk_render_type_e render_type, const vec4_t color, const matrix4x4 transform, const char *debug_name_fmt, ... ); +void VK_RenderModelDynamicBegin( vk_render_type_e render_type, const vec4_t color, const matrix3x4 transform, const char *debug_name_fmt, ... ); void VK_RenderModelDynamicAddGeometry( const vk_render_geometry_t *geom ); void VK_RenderModelDynamicCommit( void ); diff --git a/ref/vk/vk_studio.c b/ref/vk/vk_studio.c index 75d0113b..3a3f4764 100644 --- a/ref/vk/vk_studio.c +++ b/ref/vk/vk_studio.c @@ -874,7 +874,7 @@ void R_StudioMergeBones( cl_entity_t *e, model_t *m_pSubModel ) Matrix3x4_FromOriginQuat( bonematrix, q[i], pos[i] ); if( pbones[i].parent == -1 ) { - Matrix3x4_Copy( g_studio.bonestransform[i], bonematrix ); + Matrix3x4_ConcatTransforms( g_studio.bonestransform[i], g_studio.rotationmatrix, bonematrix ); Matrix3x4_Copy( g_studio.lighttransform[i], g_studio.bonestransform[i] ); // apply client-side effects to the transformation matrix @@ -1032,7 +1032,7 @@ void R_StudioSetupBones( cl_entity_t *e ) if( pbones[i].parent == -1 ) { - Matrix3x4_Copy( g_studio.bonestransform[i], bonematrix ); + Matrix3x4_ConcatTransforms( g_studio.bonestransform[i], g_studio.rotationmatrix, bonematrix ); Matrix3x4_Copy( g_studio.lighttransform[i], g_studio.bonestransform[i] ); // apply client-side effects to the transformation matrix @@ -2178,7 +2178,11 @@ static void R_StudioDrawPoints( void ) for( i = 0; i < m_pSubModel->numverts; i++ ) { R_StudioComputeSkinMatrix( &pvertweight[i], g_studio.worldtransform, skinMat ); - Matrix3x4_VectorTransform( skinMat, pstudioverts[i], g_studio.verts[i] ); + + vec3_t v; + Matrix3x4_VectorTransform( skinMat, pstudioverts[i], v); + Matrix3x4_VectorTransform( rotationmatrix_inv, v, g_studio.verts[i] ); + R_LightStrength( pvertbone[i], pstudioverts[i], g_studio.lightpos[i] ); } @@ -2193,7 +2197,10 @@ static void R_StudioDrawPoints( void ) for( i = 0; i < m_pSubModel->numnorms; i++ ) { R_StudioComputeSkinMatrix( &pnormweight[i], g_studio.worldtransform, skinMat ); - Matrix3x4_VectorRotate( skinMat, pstudionorms[i], g_studio.norms[i] ); + + vec3_t v; + Matrix3x4_VectorRotate( skinMat, pstudionorms[i], v); + Matrix3x4_VectorRotate( rotationmatrix_inv, v, g_studio.norms[i] ); } } else @@ -2206,8 +2213,9 @@ static void R_StudioDrawPoints( void ) vec3_t v; Matrix3x4_VectorTransform( g_studio.bonestransform[pvertbone[i]], pstudioverts[i], v); Matrix3x4_VectorTransform( rotationmatrix_inv, v, g_studio.verts[i] ); - Matrix3x4_VectorTransform( prev_bones_transforms[pvertbone[i]], pstudioverts[i], g_studio.prev_verts[i] ); R_LightStrength( pvertbone[i], pstudioverts[i], g_studio.lightpos[i] ); + + Matrix3x4_VectorTransform( prev_bones_transforms[pvertbone[i]], pstudioverts[i], g_studio.prev_verts[i] ); } }