예제 #1
0
/*
====================
idRenderModelMD5::LoadModel

used for initial loads, reloadModel, and reloading the data of purged models
Upon exit, the model will absolutely be valid, but possibly as a default model
====================
*/
void idRenderModelMD5::LoadModel()
{

	int			version;
	int			num;
	int			parentNum;
	idToken		token;
	idLexer		parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
	
	if( !purged )
	{
		PurgeModel();
	}
	purged = false;
	
	if( !parser.LoadFile( name ) )
	{
		MakeDefaultModel();
		return;
	}
	
	parser.ExpectTokenString( MD5_VERSION_STRING );
	version = parser.ParseInt();
	
	if( version != MD5_VERSION )
	{
		parser.Error( "Invalid version %d.  Should be version %d\n", version, MD5_VERSION );
	}
	
	//
	// skip commandline
	//
	parser.ExpectTokenString( "commandline" );
	parser.ReadToken( &token );
	
	// parse num joints
	parser.ExpectTokenString( "numJoints" );
	num  = parser.ParseInt();
	joints.SetGranularity( 1 );
	joints.SetNum( num );
	defaultPose.SetGranularity( 1 );
	defaultPose.SetNum( num );
	
	// parse num meshes
	parser.ExpectTokenString( "numMeshes" );
	num = parser.ParseInt();
	if( num < 0 )
	{
		parser.Error( "Invalid size: %d", num );
	}
	meshes.SetGranularity( 1 );
	meshes.SetNum( num );
	
	//
	// parse joints
	//
	parser.ExpectTokenString( "joints" );
	parser.ExpectTokenString( "{" );
	idJointMat* poseMat = ( idJointMat* )_alloca16( joints.Num() * sizeof( poseMat[0] ) );
	for( int i = 0; i < joints.Num(); i++ )
	{
		idMD5Joint* joint = &joints[i];
		idJointQuat*	 pose = &defaultPose[i];
		
		ParseJoint( parser, joint, pose );
		poseMat[ i ].SetRotation( pose->q.ToMat3() );
		poseMat[ i ].SetTranslation( pose->t );
		if( joint->parent )
		{
			parentNum = joint->parent - joints.Ptr();
			pose->q = ( poseMat[ i ].ToMat3() * poseMat[ parentNum ].ToMat3().Transpose() ).ToQuat();
			pose->t = ( poseMat[ i ].ToVec3() - poseMat[ parentNum ].ToVec3() ) * poseMat[ parentNum ].ToMat3().Transpose();
		}
	}
	parser.ExpectTokenString( "}" );
	
	//-----------------------------------------
	// create the inverse of the base pose joints to support tech6 style deformation
	// of base pose vertexes, normals, and tangents.
	//
	// vertex * joints * inverseJoints == vertex when joints is the base pose
	// When the joints are in another pose, it gives the animated vertex position
	//-----------------------------------------
	invertedDefaultPose.SetNum( SIMD_ROUND_JOINTS( joints.Num() ) );
	for( int i = 0; i < joints.Num(); i++ )
	{
		invertedDefaultPose[i] = poseMat[i];
		invertedDefaultPose[i].Invert();
	}
	SIMD_INIT_LAST_JOINT( invertedDefaultPose.Ptr(), joints.Num() );
	
	for( int i = 0; i < meshes.Num(); i++ )
	{
		parser.ExpectTokenString( "mesh" );
		meshes[i].ParseMesh( parser, defaultPose.Num(), poseMat );
	}
	
	// calculate the bounds of the model
	bounds.Clear();
	for( int i = 0; i < meshes.Num(); i++ )
	{
		idBounds meshBounds;
		meshes[i].CalculateBounds( poseMat, meshBounds );
		bounds.AddBounds( meshBounds );
	}
	
	// set the timestamp for reloadmodels
	fileSystem->ReadFile( name, NULL, &timeStamp );
	
	common->UpdateLevelLoadPacifier(true);
}
예제 #2
0
/*
====================
idRenderModelLiquid::InitFromFile
====================
*/
void idRenderModelLiquid::InitFromFile( const char* fileName )
{
	int				i, x, y;
	idToken			token;
	idParser		parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
	idList<int>		tris;
	float			size_x, size_y;
	float			rate;
	
	name = fileName;
	
	if( !parser.LoadFile( fileName ) )
	{
		MakeDefaultModel();
		return;
	}
	
	size_x = scale_x * verts_x;
	size_y = scale_y * verts_y;
	
	while( parser.ReadToken( &token ) )
	{
		if( !token.Icmp( "seed" ) )
		{
			seed = parser.ParseInt();
		}
		else if( !token.Icmp( "size_x" ) )
		{
			size_x = parser.ParseFloat();
		}
		else if( !token.Icmp( "size_y" ) )
		{
			size_y = parser.ParseFloat();
		}
		else if( !token.Icmp( "verts_x" ) )
		{
			verts_x = parser.ParseFloat();
			if( verts_x < 2 )
			{
				parser.Warning( "Invalid # of verts.  Using default model." );
				MakeDefaultModel();
				return;
			}
		}
		else if( !token.Icmp( "verts_y" ) )
		{
			verts_y = parser.ParseFloat();
			if( verts_y < 2 )
			{
				parser.Warning( "Invalid # of verts.  Using default model." );
				MakeDefaultModel();
				return;
			}
		}
		else if( !token.Icmp( "liquid_type" ) )
		{
			liquid_type = parser.ParseInt() - 1;
			if( ( liquid_type < 0 ) || ( liquid_type >= LIQUID_MAX_TYPES ) )
			{
				parser.Warning( "Invalid liquid_type.  Using default model." );
				MakeDefaultModel();
				return;
			}
		}
		else if( !token.Icmp( "density" ) )
		{
			density = parser.ParseFloat();
		}
		else if( !token.Icmp( "drop_height" ) )
		{
			drop_height = parser.ParseFloat();
		}
		else if( !token.Icmp( "drop_radius" ) )
		{
			drop_radius = parser.ParseInt();
		}
		else if( !token.Icmp( "drop_delay" ) )
		{
			drop_delay = SEC2MS( parser.ParseFloat() );
		}
		else if( !token.Icmp( "shader" ) )
		{
			parser.ReadToken( &token );
			shader = declManager->FindMaterial( token );
		}
		else if( !token.Icmp( "update_rate" ) )
		{
			rate = parser.ParseFloat();
			if( ( rate <= 0.0f ) || ( rate > 60.0f ) )
			{
				parser.Warning( "Invalid update_rate.  Must be between 0 and 60.  Using default model." );
				MakeDefaultModel();
				return;
			}
			update_tics = 1000 / rate;
		}
		else
		{
			parser.Warning( "Unknown parameter '%s'.  Using default model.", token.c_str() );
			MakeDefaultModel();
			return;
		}
	}
	
	scale_x = size_x / ( verts_x - 1 );
	scale_y = size_y / ( verts_y - 1 );
	
	pages.SetNum( 2 * verts_x * verts_y );
	page1 = pages.Ptr();
	page2 = page1 + verts_x * verts_y;
	
	verts.SetNum( verts_x * verts_y );
	for( i = 0, y = 0; y < verts_y; y++ )
	{
		for( x = 0; x < verts_x; x++, i++ )
		{
			page1[ i ] = 0.0f;
			page2[ i ] = 0.0f;
			verts[ i ].Clear();
			verts[ i ].xyz.Set( x * scale_x, y * scale_y, 0.0f );
			verts[ i ].SetTexCoord( ( float ) x / ( float )( verts_x - 1 ), ( float ) - y / ( float )( verts_y - 1 ) );
		}
	}
	
	tris.SetNum( ( verts_x - 1 ) * ( verts_y - 1 ) * 6 );
	for( i = 0, y = 0; y < verts_y - 1; y++ )
	{
		for( x = 1; x < verts_x; x++, i += 6 )
		{
			tris[ i + 0 ] = y * verts_x + x;
			tris[ i + 1 ] = y * verts_x + x - 1;
			tris[ i + 2 ] = ( y + 1 ) * verts_x + x - 1;
			
			tris[ i + 3 ] = ( y + 1 ) * verts_x + x - 1;
			tris[ i + 4 ] = ( y + 1 ) * verts_x + x;
			tris[ i + 5 ] = y * verts_x + x;
		}
	}
	
	// build the information that will be common to all animations of this mesh:
	// sil edge connectivity and normal / tangent generation information
	deformInfo = R_BuildDeformInfo( verts.Num(), verts.Ptr(), tris.Num(), tris.Ptr(), true );
	
	bounds.Clear();
	bounds.AddPoint( idVec3( 0.0f, 0.0f, drop_height * -10.0f ) );
	bounds.AddPoint( idVec3( ( verts_x - 1 ) * scale_x, ( verts_y - 1 ) * scale_y, drop_height * 10.0f ) );
	
	// set the timestamp for reloadmodels
	fileSystem->ReadFile( name, NULL, &timeStamp );
	
	Reset();
}
예제 #3
0
/*
====================
idRenderModelMD5::LoadModel

used for initial loads, reloadModel, and reloading the data of purged models
Upon exit, the model will absolutely be valid, but possibly as a default model
====================
*/
void idRenderModelMD5::LoadModel() {
	int			version;
	int			i;
	int			num;
	int			parentNum;
	idToken		token;
	idLexer		parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
	idJointQuat	*pose;
	idMD5Joint	*joint;
	idJointMat *poseMat3;

	if ( !purged ) {
		PurgeModel();
	}
	purged = false;

	if ( !parser.LoadFile( name ) ) {
		MakeDefaultModel();
		return;
	}

	parser.ExpectTokenString( MD5_VERSION_STRING );
	version = parser.ParseInt();

	if ( version != MD5_VERSION ) {
		parser.Error( "Invalid version %d.  Should be version %d\n", version, MD5_VERSION );
	}

	//
	// skip commandline
	//
	parser.ExpectTokenString( "commandline" );
	parser.ReadToken( &token );

	// parse num joints
	parser.ExpectTokenString( "numJoints" );
	num  = parser.ParseInt();
	joints.SetGranularity( 1 );
	joints.SetNum( num );
	defaultPose.SetGranularity( 1 );
	defaultPose.SetNum( num );
	poseMat3 = ( idJointMat * )_alloca16( num * sizeof( *poseMat3 ) );

	// parse num meshes
	parser.ExpectTokenString( "numMeshes" );
	num = parser.ParseInt();
	if ( num < 0 ) {
		parser.Error( "Invalid size: %d", num );
	}
	meshes.SetGranularity( 1 );
	meshes.SetNum( num );

	//
	// parse joints
	//
	parser.ExpectTokenString( "joints" );
	parser.ExpectTokenString( "{" );
	pose = defaultPose.Ptr();
	joint = joints.Ptr();
	for( i = 0; i < joints.Num(); i++, joint++, pose++ ) {
		ParseJoint( parser, joint, pose );
		poseMat3[ i ].SetRotation( pose->q.ToMat3() );
		poseMat3[ i ].SetTranslation( pose->t );
		if ( joint->parent ) {
			parentNum = joint->parent - joints.Ptr();
			pose->q = ( poseMat3[ i ].ToMat3() * poseMat3[ parentNum ].ToMat3().Transpose() ).ToQuat();
			pose->t = ( poseMat3[ i ].ToVec3() - poseMat3[ parentNum ].ToVec3() ) * poseMat3[ parentNum ].ToMat3().Transpose();
		}
	}
	parser.ExpectTokenString( "}" );

	for( i = 0; i < meshes.Num(); i++ ) {
		parser.ExpectTokenString( "mesh" );
		meshes[ i ].ParseMesh( parser, defaultPose.Num(), poseMat3 );
	}

	//
	// calculate the bounds of the model
	//
	CalculateBounds( poseMat3 );

	// set the timestamp for reloadmodels
	fileSystem->ReadFile( name, NULL, &timeStamp );
}