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

📄 studio_utils.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***
*
*	Copyright (c) 1998, Valve LLC. All rights reserved.
*	
*	This product contains software technology licensed from Id 
*	Software, Inc. ("Id Technology").  Id Technology (c) 1996 Id Software, Inc. 
*	All Rights Reserved.
*
****/
// updates:
// 1-4-99	fixed file texture load and file read bug

////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include "StudioModel.h"
#include "vphysics/constraints.h"
#include "physmesh.h"
#include "materialsystem/imaterialsystem.h"
#include "ViewerSettings.h"
#include "bone_setup.h"
#include "UtlMemory.h"
#include "mx/mx.h"
#include "cmdlib.h"
#include "IStudioRender.h"
#include "materialsystem/IMaterialSystemHardwareConfig.h"
#include "MDLViewer.h"

extern IMaterialSystem *g_pMaterialSystem;
extern IMaterialSystemHardwareConfig *g_pMaterialSystemHardwareConfig;
extern char g_appTitle[];
IStudioRender	*StudioModel::m_pStudioRender;
Vector		    *StudioModel::m_AmbientLightColors;
Vector		    *StudioModel::m_TotalLightColors;

#pragma warning( disable : 4244 ) // double to float


static StudioModel g_studioModel;

// Expose it to the rest of the app
StudioModel *g_pStudioModel = &g_studioModel;

////////////////////////////////////////////////////////////////////////


void StudioModel::Init()
{
	// Load up the IStudioRender interface
	extern CreateInterfaceFn g_MaterialSystemClientFactory;
	extern CreateInterfaceFn g_MaterialSystemFactory;

	CSysModule *studioRenderDLL = NULL;
	char workingdir[ 256 ];
	workingdir[0] = 0;
	Q_getwd( workingdir );

	// If they didn't specify -game on the command line, use VPROJECT.
	CmdLib_InitFileSystem( workingdir, true );

	studioRenderDLL = Sys_LoadModule( "StudioRender.dll" );
	if( !studioRenderDLL )
	{
//		Msg( mwWarning, "Can't load StudioRender.dll\n" );
		assert( 0 ); // garymcthack
		return;
	}
	CreateInterfaceFn studioRenderFactory = Sys_GetFactory( "StudioRender.dll" );
	if (!studioRenderFactory )
	{
//		Msg( mwWarning, "Can't get studio render factory\n" );
		assert( 0 ); // garymcthack
		return;
	}
	m_pStudioRender = ( IStudioRender * )studioRenderFactory( STUDIO_RENDER_INTERFACE_VERSION, NULL );
	if (!m_pStudioRender)
	{
//		Msg( mwWarning, "Can't get version %s of StudioRender.dll\n", STUDIO_RENDER_INTERFACE_VERSION );
		assert( 0 ); // garymcthack
		return;
	}

	if( !m_pStudioRender->Init( g_MaterialSystemFactory, g_MaterialSystemClientFactory ) )
	{
//		Msg( mwWarning, "Can't initialize StudioRender.dll\n" );
		assert( 0 ); // garymcthack
		m_pStudioRender = NULL;
	}
	m_AmbientLightColors = new Vector[m_pStudioRender->GetNumAmbientLightSamples()];
	m_TotalLightColors = new Vector[m_pStudioRender->GetNumAmbientLightSamples()];
	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.
}

void StudioModel::Shutdown( void )
{
	g_pStudioModel->FreeModel();
	if( m_pStudioRender )
	{
		m_pStudioRender->Shutdown();
		m_pStudioRender = NULL;
	}
	delete [] m_AmbientLightColors;
	delete [] m_TotalLightColors;
}


void StudioModel::ReleaseStudioModel()
{
	g_pStudioModel->FreeModel(); 
}

void StudioModel::RestoreStudioModel()
{
	if (g_pStudioModel->LoadModel(g_pStudioModel->m_pModelName))
	{
		g_pStudioModel->PostLoadModel( g_pStudioModel->m_pModelName );
	}
}



//-----------------------------------------------------------------------------
// Purpose: Frees the model data and releases textures from OpenGL.
//-----------------------------------------------------------------------------
void StudioModel::FreeModel ()
{
	if (!m_pStudioRender)
		return;

	m_pStudioRender->UnloadModel( &m_HardwareData );
	
	if (m_pstudiohdr)
		free (m_pstudiohdr);

	m_pstudiohdr = 0;

	int i;
	for (i = 0; i < 32; i++)
	{
		if (m_panimhdr[i])
		{
			free (m_panimhdr[i]);
			m_panimhdr[i] = 0;
		}
	}

#if 0
	// deleting textures
	g_texnum -= 3;
	int textures[MAXSTUDIOSKINS];
	for (i = 0; i < g_texnum; i++)
		textures[i] = i + 3;

	//glDeleteTextures (g_texnum, (const GLuint *) textures);
	g_texnum = 3;
#endif

	memset( &m_HardwareData, 0, sizeof( m_HardwareData ) );

	m_SurfaceProps.Purge();
	// BUG: Jay, when I call this it crashes
	// delete m_pPhysics;
}

void *StudioModel::operator new( size_t stAllocateBlock )
{
	// call into engine to get memory
	Assert( stAllocateBlock != 0 );
	return calloc( 1, stAllocateBlock );
}

void StudioModel::operator delete( void *pMem )
{
#ifdef _DEBUG
	// set the memory to a known value
	int size = _msize( pMem );
	memset( pMem, 0xcd, size );
#endif

	// get the engine to free the memory
	free( pMem );
}

bool StudioModel::LoadModel( const char *modelname )
{
	FILE *fp;
	long size;
	void *buffer;

	if (!modelname)
		return 0;

	// In the case of restore, m_pModelName == modelname
	if (m_pModelName != modelname)
	{
		// Copy over the model name; we'll need it later...
		if (m_pModelName)
			delete[] m_pModelName;
		m_pModelName = new char[strlen(modelname) + 1];
		strcpy( m_pModelName, modelname );
	}

	// load the model
	if( (fp = fopen( modelname, "rb" )) == NULL)
		return 0;

	fseek( fp, 0, SEEK_END );
	size = ftell( fp );
	fseek( fp, 0, SEEK_SET );

	buffer = malloc( size );
	if (!buffer)
	{
		fclose (fp);
		return 0;
	}

	fread( buffer, size, 1, fp );
	fclose( fp );

	byte				*pin;
	studiohdr_t			*phdr;

	pin = (byte *)buffer;
	phdr = (studiohdr_t *)pin;

	if (strncmp ((const char *) buffer, "IDST", 4) &&
		strncmp ((const char *) buffer, "IDSQ", 4))
	{
		free (buffer);
		return 0;
	}

	if (!strncmp ((const char *) buffer, "IDSQ", 4) && !m_pstudiohdr)
	{
		free (buffer);
		return 0;
	}

	Studio_ConvertStudioHdrToNewVersion( phdr );
	
	if( phdr->version != STUDIO_VERSION )
	{
		free( buffer );
		return 0;
	}

	if (!m_pstudiohdr)
		m_pstudiohdr = (studiohdr_t *)buffer;

	// Load the VTX file.
	char* pExtension;
	if (g_pMaterialSystemHardwareConfig->SupportsVertexAndPixelShaders())
	{
		pExtension = ".dx80.vtx";
	}
	else
	{
		if( g_pMaterialSystemHardwareConfig->MaxBlendMatrices() > 2 )
		{
			pExtension = ".dx7_3bone.vtx";
		}
		else
		{
			pExtension = ".dx7_2bone.vtx";
		}
	}

	int vtxFileNameLen = strlen( modelname ) - strlen( ".mdl" ) + strlen( pExtension ) + 1;
	char *vtxFileName = ( char * )_alloca( vtxFileNameLen );
	strcpy( vtxFileName, modelname );
	strcpy( vtxFileName + strlen( vtxFileName ) - 4, pExtension );
	assert( ( int )strlen( vtxFileName ) == vtxFileNameLen - 1 );
	
	CUtlMemory<unsigned char> tmpVtxMem; // This goes away when we leave this scope.
	
	if( (fp = fopen( vtxFileName, "rb" )) == NULL)
	{
		// Fallback
		pExtension = ".dx7_2bone.vtx";
		vtxFileNameLen = strlen( modelname ) - strlen( ".mdl" ) + strlen( pExtension ) + 1;
		vtxFileName = ( char * )_alloca( vtxFileNameLen );
		strcpy( vtxFileName, modelname );
		strcpy( vtxFileName + strlen( vtxFileName ) - 4, pExtension );
		assert( ( int )strlen( vtxFileName ) == vtxFileNameLen - 1 );
		if( (fp = fopen( vtxFileName, "rb" )) == NULL)
		{
			// garymcthack - need to spew an error
			//		mxMessageBox (this, "Error reading vtx header.", g_appTitle, MX_MB_OK | MX_MB_ERROR);
			free( buffer );
			m_pstudiohdr = NULL;
			return false;
		}
	}

	fseek( fp, 0, SEEK_END );
	size = ftell( fp );
	fseek( fp, 0, SEEK_SET );

	tmpVtxMem.EnsureCapacity( size );
	
	fread( tmpVtxMem.Base(), size, 1, fp );
	fclose( fp );

	if( !m_pStudioRender->LoadModel( m_pstudiohdr, tmpVtxMem.Base(), &m_HardwareData ) )
	{
		// garymcthack - need to spew an error
//		Msg( mwWarning, "error loading model: %s\n", modelname );
		free( buffer );
		m_pstudiohdr = NULL;
		return false;
	}

	m_pPhysics = LoadPhysics( m_pstudiohdr, modelname );

	// Copy over all of the hitboxes; we may add and remove elements
	m_HitboxSets.RemoveAll();

	int i;
	int s;
	for ( s = 0; s < m_pstudiohdr->numhitboxsets; s++ )
	{
		mstudiohitboxset_t *set = m_pstudiohdr->pHitboxSet( s );
		if ( !set )
			continue;

		m_HitboxSets.AddToTail();

		for ( i = 0; i < set->numhitboxes; ++i )
		{
			mstudiobbox_t *pHit = set->pHitbox(i);
			m_HitboxSets[ s ].AddToTail( *set->pHitbox(i) );
		}

		// Set the name
		hbsetname_s *n = &m_HitboxSetNames[ m_HitboxSetNames.AddToTail() ];
		strcpy( n->name, set->pszName() );
	}

	// Copy over all of the surface props; we may change them...
	for ( i = 0; i < m_pstudiohdr->numbones; ++i )
	{
		mstudiobone_t* pBone = m_pstudiohdr->pBone(i);

		CUtlSymbol prop( pBone->pszSurfaceProp() );
		m_SurfaceProps.AddToTail( prop );
	}

	m_physPreviewBone = -1;
	return true;
}



bool StudioModel::PostLoadModel( const char *modelname )
{
	if (m_pstudiohdr == NULL)
	{
		return(false);
	}

	SetSequence (0);
	SetController (0, 0.0f);
	SetController (1, 0.0f);
	SetController (2, 0.0f);
	SetController (3, 0.0f);
	SetBlendTime( DEFAULT_BLEND_TIME );

	int n;
	for (n = 0; n < m_pstudiohdr->numbodyparts; n++)
		SetBodygroup (n, 0);

	SetSkin (0);

/*
	Vector mins, maxs;
	ExtractBbox (mins, maxs);
	if (mins[2] < 5.0f)
		m_origin[2] = -mins[2];
*/
	return true;
}



bool StudioModel::SaveModel ( const char *modelname )
{
	if (!modelname)
		return false;

	if (!m_pstudiohdr)
		return false;

	FILE *file;
	
	file = fopen (modelname, "wb");
	if (!file)
		return false;

	fwrite (m_pstudiohdr, sizeof (byte), m_pstudiohdr->length, file);
	fclose (file);

	// write seq groups
	if (m_pstudiohdr->numseqgroups > 1)
	{
		for (int i = 1; i < m_pstudiohdr->numseqgroups; i++)
		{
			char seqgroupname[256];

			strcpy( seqgroupname, modelname );
			sprintf( &seqgroupname[strlen(seqgroupname) - 4], "%02d.mdl", i );

			file = fopen (seqgroupname, "wb");
			if (file)
			{
				fwrite (m_panimhdr[i], sizeof (byte), m_panimhdr[i]->length, file);
				fclose (file);
			}
		}
	}

	return true;
}


////////////////////////////////////////////////////////////////////////


int StudioModel::GetSequence( )
{
	return m_sequence;
}

int StudioModel::SetSequence( int iSequence )
{
	if ( !m_pstudiohdr )
		return 0;

	if (iSequence < 0)
		return 0;

	if (iSequence > m_pstudiohdr->numseq)
		return m_sequence;

	m_prevsequence = m_sequence;
	m_sequence = iSequence;
	m_cycle = 0;
	m_sequencetime = 0.0;

	return m_sequence;
}

void StudioModel::ClearOverlaysSequences( void )
{
	ClearAnimationLayers( );
	memset( m_Layer, 0, sizeof( m_Layer ) );
}

void StudioModel::ClearAnimationLayers( void )
{
	m_iActiveLayers = 0;
}

int	StudioModel::GetNewAnimationLayer( int iPriority )
{
	if ( !m_pstudiohdr )
		return 0;

	if ( m_iActiveLayers >= MAXSTUDIOANIMLAYERS )
	{
		Assert( 0 );
		return MAXSTUDIOANIMLAYERS - 1;
	}

	m_Layer[m_iActiveLayers].m_priority = iPriority;

	return m_iActiveLayers++;
}

int StudioModel::SetOverlaySequence( int iLayer, int iSequence, float flWeight )
{
	if ( !m_pstudiohdr )
		return 0;

	if (iSequence < 0)
		return 0;

	if (iLayer < 0 || iLayer >= MAXSTUDIOANIMLAYERS)
	{
		Assert(0);
		return 0;
	}

	if (iSequence > m_pstudiohdr->numseq)
		return m_Layer[iLayer].m_sequence;

	m_Layer[iLayer].m_sequence = iSequence;
	m_Layer[iLayer].m_weight = flWeight;
	m_Layer[iLayer].m_playbackrate = 1.0;

	return iSequence;
}

float StudioModel::SetOverlayRate( int iLayer, float flCycle, float flPlaybackRate )
{
	if (iLayer >= 0 && iLayer < MAXSTUDIOANIMLAYERS)
	{
		m_Layer[iLayer].m_cycle = flCycle;
		m_Layer[iLayer].m_playbackrate = flPlaybackRate;
	}
	return flCycle;
}

int StudioModel::LookupSequence( const char *szSequence )
{
	int i;

	if ( !m_pstudiohdr )
		return -1;

	for (i = 0; i < m_pstudiohdr->numseq; i++)
	{
		if (!stricmp( szSequence, m_pstudiohdr->pSeqdesc( i )->pszLabel() ))
		{
			return i;
		}
	}
	return -1;
}

int StudioModel::SetSequence( const char *szSequence )
{
	return SetSequence( LookupSequence( szSequence ) );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -