mirror of
https://github.com/w23/xash3d-fwgs
synced 2025-01-07 09:26:01 +01:00
e54913f8af
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.
128 lines
3.6 KiB
C
128 lines
3.6 KiB
C
#include "vk_studio.h"
|
|
#include "vk_common.h"
|
|
#include "vk_textures.h"
|
|
#include "vk_render.h"
|
|
#include "vk_geometry.h"
|
|
#include "camera.h"
|
|
|
|
#include "xash3d_mathlib.h"
|
|
#include "const.h"
|
|
#include "r_studioint.h"
|
|
#include "triangleapi.h"
|
|
#include "studio.h"
|
|
#include "pm_local.h"
|
|
#include "pmtrace.h"
|
|
#include "protocol.h"
|
|
#include "enginefeatures.h"
|
|
#include "pm_movevars.h"
|
|
#include "xash3d_types.h"
|
|
|
|
#include <memory.h>
|
|
#include <stdlib.h>
|
|
|
|
#define PREV_STATES_COUNT 1024
|
|
#define PREV_FRAMES_COUNT 2
|
|
|
|
typedef struct {
|
|
matrix3x4 bones_worldtransform[MAXSTUDIOBONES];
|
|
matrix4x4 model_transform;
|
|
float time;
|
|
uint bones_frame_updated;
|
|
uint frame_updated;
|
|
} prev_state_t;
|
|
|
|
typedef struct {
|
|
prev_state_t prev_states[PREV_FRAMES_COUNT][PREV_STATES_COUNT];
|
|
uint frame_index;
|
|
uint prev_frame_index;
|
|
uint current_frame_id;
|
|
uint previous_frame_id;
|
|
} prev_states_storage_t;
|
|
|
|
prev_states_storage_t g_prev = { 0 };
|
|
|
|
prev_state_t* prevStateInArrayBounds( int frame_storage_id, int entity_id )
|
|
{
|
|
int clamped_entity_id = entity_id;
|
|
|
|
if (entity_id >= PREV_STATES_COUNT)
|
|
{
|
|
gEngine.Con_Printf("Previous frame states data for entity %d overflows storage (size is %d). Increase it\n", entity_id, PREV_STATES_COUNT);
|
|
clamped_entity_id = PREV_STATES_COUNT - 1; // fallback to last correct value
|
|
}
|
|
else if (entity_id < 0)
|
|
{
|
|
clamped_entity_id = 0; // fallback to correct value
|
|
}
|
|
|
|
return &g_prev.prev_states[frame_storage_id][clamped_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 )
|
|
{
|
|
g_prev.frame_index++;
|
|
g_prev.current_frame_id = g_prev.frame_index % PREV_FRAMES_COUNT;
|
|
g_prev.previous_frame_id = (g_prev.frame_index - 1) % PREV_FRAMES_COUNT;
|
|
}
|
|
|
|
void R_PrevFrame_SaveCurrentBoneTransforms( int entity_id, matrix3x4* bones_transforms, const matrix4x4 rotationmatrix_inv )
|
|
{
|
|
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
|
|
|
|
current_frame->bones_frame_updated = g_prev.frame_index;
|
|
|
|
for( int i = 0; i < MAXSTUDIOBONES; i++ )
|
|
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(entity_id);
|
|
|
|
if (current_frame->frame_updated == g_prev.frame_index)
|
|
return; // already updated for this entity
|
|
|
|
Matrix4x4_Copy( current_frame->model_transform, model_transform );
|
|
current_frame->time = gpGlobals->time;
|
|
current_frame->frame_updated = g_prev.frame_index;
|
|
}
|
|
|
|
matrix3x4* R_PrevFrame_BoneTransforms( int entity_id )
|
|
{
|
|
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(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(entity_id);
|
|
|
|
// fallback to current frame if previous is outdated
|
|
if (prev_frame->frame_updated != g_prev.frame_index - 1)
|
|
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(entity_id);
|
|
|
|
// fallback to current frame if previous is outdated
|
|
if (prev_frame->frame_updated != g_prev.frame_index - 1)
|
|
return gpGlobals->time;
|
|
|
|
return prev_frame->time;
|
|
}
|