📄 studio_render.cpp
字号:
// reduce deflection the more the eye is off center
// FIXME: this angles make no damn sense
eyeDeflect = eyeDeflect * (local.x * local.x);
local = local + eyeDeflect;
VectorNormalize( local );
// check to see if the eye is aiming outside a 30 degree cone
if (local.x < 0.866) // cos(30)
{
// if so, clamp it to 30 degrees offset
// debugoverlay->AddTextOverlay( m_vecOrigin + Vector( 0, 0, 64 ), 0, 0, "%.2f %.2f %.2f", local.x, local.y, local.z );
local.x = 0;
float d = local.LengthSqr();
if (d > 0.0)
{
d = sqrt( (1.0 - 0.866 * 0.866) / (local.y*local.y + local.z*local.z) );
local.x = 0.866;
local.y = local.y * d;
local.z = local.z * d;
}
else
{
local.x = 1.0;
}
}
local = local * flDist;
VectorTransform( local, attToWorld, tmp );
m_pStudioRender->SetEyeViewTarget( tmp );
}
float UTIL_VecToYaw( const matrix3x4_t& matrix, const Vector &vec )
{
Vector tmp = vec;
VectorNormalize( tmp );
float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z;
float y = matrix[0][1] * tmp.x + matrix[1][1] * tmp.y + matrix[2][1] * tmp.z;
if (x == 0.0f && y == 0.0f)
return 0.0f;
float yaw = atan2( -y, x );
yaw = RAD2DEG(yaw);
if (yaw < 0)
yaw += 360;
return yaw;
}
float UTIL_VecToPitch( const matrix3x4_t& matrix, const Vector &vec )
{
Vector tmp = vec;
VectorNormalize( tmp );
float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z;
float z = matrix[0][2] * tmp.x + matrix[1][2] * tmp.y + matrix[2][2] * tmp.z;
if (x == 0.0f && z == 0.0f)
return 0.0f;
float pitch = atan2( z, x );
pitch = RAD2DEG(pitch);
if (pitch < 0)
pitch += 360;
return pitch;
}
float UTIL_AngleDiff( float destAngle, float srcAngle )
{
float delta;
delta = destAngle - srcAngle;
if ( destAngle > srcAngle )
{
while ( delta >= 180 )
delta -= 360;
}
else
{
while ( delta <= -180 )
delta += 360;
}
return delta;
}
void StudioModel::UpdateBoneChain(
Vector pos[],
Quaternion q[],
int iBone,
matrix3x4_t *pBoneToWorld )
{
matrix3x4_t bonematrix;
QuaternionMatrix( q[iBone], pos[iBone], bonematrix );
int parent = m_pstudiohdr->pBone( iBone )->parent;
if (parent == -1)
{
ConcatTransforms( g_viewtransform, bonematrix, pBoneToWorld[iBone] );
}
else
{
// evil recursive!!!
UpdateBoneChain( pos, q, parent, pBoneToWorld );
ConcatTransforms( pBoneToWorld[parent], bonematrix, pBoneToWorld[iBone] );
}
}
void StudioModel::GetBodyPoseParametersFromFlex( )
{
float flGoal;
flGoal = GetFlexController( "move_rightleft" );
SetPoseParameter( "body_trans_Y", flGoal );
flGoal = GetFlexController( "move_forwardback" );
SetPoseParameter( "body_trans_X", flGoal );
flGoal = GetFlexController( "move_updown" );
SetPoseParameter( "body_lift", flGoal );
flGoal = GetFlexController( "body_rightleft" );
SetPoseParameter( "body_yaw", flGoal );
flGoal = GetFlexController( "body_updown" );
SetPoseParameter( "body_pitch", flGoal );
flGoal = GetFlexController( "body_tilt" );
SetPoseParameter( "body_roll", flGoal );
flGoal = GetFlexController( "chest_rightleft" );
SetPoseParameter( "spine_yaw", flGoal );
flGoal = GetFlexController( "chest_updown" );
SetPoseParameter( "spine_pitch", flGoal );
flGoal = GetFlexController( "chest_tilt" );
SetPoseParameter( "spine_roll", flGoal );
flGoal = GetFlexController( "head_forwardback" );
SetPoseParameter( "neck_trans", flGoal );
}
void StudioModel::SetHeadPosition( Vector pos[], Quaternion q[] )
{
static Vector pos2[MAXSTUDIOBONES];
static Quaternion q2[MAXSTUDIOBONES];
Vector vTargetPos = Vector( 0, 0, 0 );
if (g_viewerSettings.solveHeadTurn == 0)
return;
if (m_dt == 0.0f)
{
m_dt = m_dt;
}
else
{
m_dt = m_dt;
}
// GetAttachment( "eyes", vEyePosition, vEyeAngles );
int iEyeAttachment = LookupAttachment( "eyes" );
if (iEyeAttachment == -1)
return;
mstudioattachment_t *patt = m_pstudiohdr->pAttachment( iEyeAttachment );
int iLoops = 1;
float dt = m_dt;
if (g_viewerSettings.solveHeadTurn == 2)
{
iLoops = 100;
dt = 0.1;
}
Vector vDefault;
CalcDefaultView( patt, pos, q, vDefault );
float flMoved = 0.0f;
do
{
for (int j = 0; j < m_pstudiohdr->numbones; j++)
{
pos2[j] = pos[j];
q2[j] = q[j];
}
CalcAutoplaySequences( m_pstudiohdr, NULL, pos2, q2, m_poseparameter, BONE_USED_BY_ANYTHING, GetAutoPlayTime() );
UpdateBoneChain( pos2, q2, patt->bone, m_pStudioRender->GetBoneToWorldArray() );
matrix3x4_t attToWorld;
ConcatTransforms( *m_pStudioRender->GetBoneToWorld( patt->bone ), patt->local, attToWorld );
vTargetPos = g_viewerSettings.vecHeadTarget * g_viewerSettings.flHeadTurn + vDefault * (1 - g_viewerSettings.flHeadTurn);
flMoved = SetHeadPosition( attToWorld, vTargetPos, dt );
} while (flMoved > 1.0 && --iLoops > 0);
// Msg( "yaw %f pitch %f\n", vEyeAngles.y, vEyeAngles.x );
}
float StudioModel::SetHeadPosition( matrix3x4_t& attToWorld, Vector const &vTargetPos, float dt )
{
float flDiff;
int iPose;
float flWeight;
Vector vEyePosition;
QAngle vEyeAngles;
float flPrev;
float flMoved = 0.0f;
MatrixAngles( attToWorld, vEyeAngles, vEyePosition );
// Msg( "yaw %f pitch %f\n", vEyeAngles.y, vEyeAngles.x );
#if 1
//--------------------------------------
// Set head yaw
//--------------------------------------
float flActualYaw = UTIL_VecToYaw(attToWorld, vTargetPos - vEyePosition);
float flDesiredYaw = GetFlexController( "head_rightleft" );
flDiff = UTIL_AngleDiff( flDesiredYaw, flActualYaw );
flWeight = 1.0 - ExponentialDecay( 0.1, 0.1, dt );
iPose = LookupPoseParameter( "head_yaw" );
flPrev = GetPoseParameter( iPose );
SetPoseParameter( iPose, flPrev + flDiff * flWeight );
flMoved += fabs( GetPoseParameter( iPose ) - flPrev );
#endif
#if 0
//--------------------------------------
// Lag body yaw
//--------------------------------------
float flHead = GetPoseParameter( iPose );
iPose = LookupPoseParameter( "spine_yaw" );
flWeight = 1.0 - ExponentialDecay( 0.875, 0.1, dt );
if (fabs( GetPoseParameter( iPose ) + flHead * flWeight) < 45)
{
SetPoseParameter( iPose, GetPoseParameter( iPose ) + flHead * flWeight );
}
#endif
#if 1
//--------------------------------------
// Set head pitch
//--------------------------------------
float flActualPitch = UTIL_VecToPitch( attToWorld, vTargetPos - vEyePosition );
float flDesiredPitch = GetFlexController( "head_updown" );
flDiff = UTIL_AngleDiff( flDesiredPitch, flActualPitch );
flWeight = 1.0 - ExponentialDecay( 0.1, 0.1, dt );
iPose = LookupPoseParameter( "head_pitch" );
flPrev = GetPoseParameter( iPose );
SetPoseParameter( iPose, flPrev + flDiff * flWeight );
flMoved += fabs( GetPoseParameter( iPose ) - flPrev );
#endif
// Msg("rightleft %.1f updown %.1f\n", GetFlexWeight( "head_rightleft" ), GetFlexWeight( "head_updown" ) );
//iPose = LookupPoseParameter( "body_pitch" );
//SetPoseParameter( iPose, GetPoseParameter( iPose ) + flDiff / 8.0 );
#if 1
//--------------------------------------
// Set head roll
//--------------------------------------
float flDesiredRoll = GetFlexController( "head_tilt" );
flDiff = UTIL_AngleDiff( flDesiredRoll, vEyeAngles.z );
iPose = LookupPoseParameter( "head_roll" );
flPrev = GetPoseParameter( iPose );
flWeight = 1.0 - ExponentialDecay( 0.1, 0.1, dt );
SetPoseParameter( iPose, flPrev + flDiff * flWeight );
flMoved += fabs( GetPoseParameter( iPose ) - flPrev );
#endif
return flMoved;
}
void StudioModel::CalcDefaultView( mstudioattachment_t *patt, Vector pos[], Quaternion q[], Vector &vDefault )
{
Vector pos2[MAXSTUDIOBONES];
Quaternion q2[MAXSTUDIOBONES];
float tmpPoseParameter[MAXSTUDIOPOSEPARAM];
int i;
for ( i = 0; i < m_pstudiohdr->numposeparameters; i++)
{
// tmpPoseParameter[i] = m_poseparameter[i];
Studio_SetPoseParameter( m_pstudiohdr, i, 0.0, tmpPoseParameter[i] );
}
/*
if ((i = LookupPoseParameter( "head_yaw")) != -1)
{
Studio_SetPoseParameter( m_pstudiohdr, i, 0.0, tmpPoseParameter[i] );
}
if ((i = LookupPoseParameter( "head_pitch")) != -1)
{
Studio_SetPoseParameter( m_pstudiohdr, i, 0.0, tmpPoseParameter[i] );
}
if ((i = LookupPoseParameter( "head_roll")) != -1)
{
Studio_SetPoseParameter( m_pstudiohdr, i, 0.0, tmpPoseParameter[i] );
}
*/
for (int j = 0; j < m_pstudiohdr->numbones; j++)
{
pos2[j] = pos[j];
q2[j] = q[j];
}
CalcAutoplaySequences( m_pstudiohdr, NULL, pos2, q2, tmpPoseParameter, BONE_USED_BY_ANYTHING, GetAutoPlayTime() );
UpdateBoneChain( pos2, q2, patt->bone, m_pStudioRender->GetBoneToWorldArray() );
matrix3x4_t attToWorld;
ConcatTransforms( *m_pStudioRender->GetBoneToWorld( patt->bone ), patt->local, attToWorld );
VectorTransform( Vector( 100, 0, 0 ), attToWorld, vDefault );
}
/*
================
StudioModel::DrawModel
inputs:
currententity
r_entorigin
================
*/
int StudioModel::DrawModel( )
{
if (!m_pstudiohdr)
return 0;
g_smodels_total++; // render data cache cookie
UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_FLATSHADED ||
g_viewerSettings.renderMode == RM_SMOOTHSHADED,
g_viewerSettings.renderMode == RM_WIREFRAME,
g_viewerSettings.showNormals ); // garymcthack - should really only do this once a frame and at init time.
if (m_pstudiohdr->numbodyparts == 0)
return 0;
// Construct a transform to apply to the model. The camera is stuck in a fixed position
AngleMatrix( g_viewerSettings.rot, g_viewtransform );
Vector vecModelOrigin;
VectorMultiply( g_viewerSettings.trans, -1.0f, vecModelOrigin );
MatrixSetColumn( vecModelOrigin, 3, g_viewtransform );
// These values HAVE to be sent down for LOD to work correctly.
Vector viewOrigin, viewRight, viewUp, viewPlaneNormal;
m_pStudioRender->SetViewState( vec3_origin, Vector(0, 1, 0), Vector(0, 0, 1), Vector( 1, 0, 0 ) );
// m_pStudioRender->SetEyeViewTarget( viewOrigin );
SetUpBones ( );
SetViewTarget( );
SetupLighting( );
extern float g_flexdescweight[MAXSTUDIOFLEXDESC]; // garymcthack
RunFlexRules();
m_pStudioRender->SetFlexWeights( MAXSTUDIOFLEXDESC, g_flexdescweight );
m_pStudioRender->SetAlphaModulation( 1.0f );
int count = 0;
DrawModelInfo_t info;
info.m_pStudioHdr = m_pstudiohdr;
info.m_pHardwareData = &m_HardwareData;
info.m_Decals = STUDIORENDER_DECAL_INVALID;
info.m_Skin = m_skinnum;
info.m_Body = m_bodynum;
info.m_HitboxSet = g_MDLViewer->GetCurrentHitboxSet();
info.m_pClientEntity = NULL;
info.m_Lod = g_viewerSettings.autoLOD ? -1 : g_viewerSettings.lod;
info.m_ppColorMeshes = NULL;
count = m_pStudioRender->DrawModel( info, vecModelOrigin, &m_LodUsed, &m_LodMetric );
DrawBones();
DrawAttachments();
DrawEditAttachment();
DrawHitboxes();
DrawPhysicsModel();
return count;
}
void StudioModel::DrawPhysmesh( CPhysmesh *pMesh, int boneIndex, IMaterial* pMaterial, float* color )
{
matrix3x4_t *pMatrix;
if ( boneIndex >= 0 )
{
pMatrix = m_pStudioRender->GetBoneToWorld( boneIndex );
}
else
{
pMatrix = &g_viewtransform;
}
g_pMaterialSystem->Bind( pMaterial );
IMesh* pMatMesh = g_pMaterialSystem->GetDynamicMesh( );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMatMesh, MATERIAL_TRIANGLES, pMesh->m_vertCount/3 );
int vertIndex = 0;
for ( int i = 0; i < pMesh->m_vertCount; i+=3 )
{
Vector v;
VectorTransform (pMesh->m_pVerts[vertIndex], *pMatrix, v);
meshBuilder.Position3fv( v.Base() );
meshBuilder.Color4fv( color );
meshBuilder.AdvanceVertex();
vertIndex ++;
VectorTransform (pMesh->m_pVerts[vertIndex], *pMatrix, v);
meshBuilder.Position3fv( v.Base() );
meshBuilder.Color4fv( color );
meshBuilder.AdvanceVertex();
vertIndex ++;
VectorTransform (pMesh->m_pVerts[vertIndex], *pMatrix, v);
meshBuilder.Position3fv( v.Base() );
meshBuilder.Color4fv( color );
meshBuilder.AdvanceVertex();
vertIndex ++;
}
meshBuilder.End();
pMatMesh->Draw();
}
void RandomColor( float *color, int key )
{
static bool first = true;
static colorVec colors[256];
if ( first )
{
int r, g, b;
first = false;
for ( int i = 0; i < 256; i++ )
{
do
{
r = rand()&255;
g = rand()&255;
b = rand()&255;
} while ( (r+g+b)<256 );
colors[i].r = r;
colors[i].g = g;
colors[i].b = b;
colors[i].a = 255;
}
}
int index = key & 255;
color[0] = colors[index].r * (1.f / 255.f);
color[1] = colors[index].g * (1.f / 255.f);
color[2] = colors[index].b * (1.f / 255.f);
color[3] = colors[index].a * (1.f / 255.f);
}
void StudioModel::DrawPhysConvex( CPhysmesh *pMesh, IMaterial* pMaterial )
{
matrix3x4_t &matrix = g_viewtransform;
g_pMaterialSystem->Bind( pMaterial );
int vertIndex = 0;
for ( int i = 0; i < pMesh->m_pCollisionModel->ConvexCount(); i++ )
{
float color[4];
RandomColor( color, i );
IMesh* pMatMesh = g_pMaterialSystem->GetDynamicMesh( );
CMeshBuilder meshBuilder;
int triCount = pMesh->m_pCollisionModel->TriangleCount( i );
meshBuilder.Begin( pMatMesh, MATERIAL_TRIANGLES, triCount );
for ( int j = 0; j < triCount; j++ )
{
Vector objectSpaceVerts[3];
pMesh->m_pCollisionModel->GetTriangleVerts( i, j, objectSpaceVerts );
for ( int k = 0; k < 3; k++ )
{
Vector v;
VectorTransform (objectSpaceVerts[k], matrix, v);
meshBuilder.Position3fv( v.Base() );
meshBuilder.Color4fv( color );
meshBuilder.AdvanceVertex();
}
}
meshBuilder.End();
pMatMesh->Draw();
}
}
void StudioModel::Transform( Vector const &in1, mstudioboneweight_t const *pboneweight, Vector &out1 )
{
if (pboneweight->numbones == 1)
{
VectorTransform( in1, *m_pStudioRender->GetPoseToWorld(pboneweight->bone[0]), out1 );
}
else
{
Vector out2;
VectorFill( out1, 0 );
for (int i = 0; i < pboneweight->numbones; i++)
{
VectorTransform( in1, *m_pStudioRender->GetPoseToWorld(pboneweight->bone[i]), out2 );
VectorMA( out1, pboneweight->weight[i], out2, out1 );
}
}
}
void StudioModel::Rotate( Vector const &in1, mstudioboneweight_t const *pboneweight, Vector &out1 )
{
if (pboneweight->numbones == 1)
{
VectorRotate( in1, *m_pStudioRender->GetPoseToWorld(pboneweight->bone[0]), out1 );
}
else
{
Vector out2;
VectorFill( out1, 0 );
for (int i = 0; i < pboneweight->numbones; i++)
{
VectorRotate( in1, *m_pStudioRender->GetPoseToWorld(pboneweight->bone[i]), out2 );
VectorMA( out1, pboneweight->weight[i], out2, out1 );
}
VectorNormalize( out1 );
}
}
/*
================
================
*/
int StudioModel::GetLodUsed( void )
{
return m_LodUsed;
}
float StudioModel::GetLodMetric( void )
{
return m_LodMetric;
}
const char *StudioModel::GetKeyValueText( int iSequence )
{
return Studio_GetKeyValueText( m_pstudiohdr, iSequence );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -