⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 studio_render.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	// 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 + -