示例#1
0
void CVisualADSView::OnInitialUpdate() 
{
	CVisualADSDoc* pDoc = GetDocument();
	SetCurrentModel(pDoc->m_pDataModel);
	//GetCurrentModel()->DisplayPreviewBmp()
	LockUpdate(TRUE);
	
	
	/*
	for (int i = 0; i < 20; i ++)
	{
		addGroup(_T("Group组"), 100 + 50 * i, 100);
		addUser(_T("chaoge"), 200, 200 + 50 * i);
	}
	addComputer(_T("VEOTAX"), 150, 500);
	addResource(_T("NRDC1001"), 400, 100);
	addInheritRelation(_T("PermitRWX"), m_shapes[0], m_shapes[1]);

	FOPRect rect;
	rect.left = 100;
	rect.top = 100;
	rect.right = 500;
	rect.bottom = 500;

	addDomain(_T("domaintest.net"), 500, 500, 700, 700);
	*/

	CFODrawView::OnInitialUpdate();
}
示例#2
0
void StudioModel::scaleMeshes (float scale)
{
	CStudioHdr *pStudioHdr = GetStudioHdr();
	if (!pStudioHdr)
		return;

	int i, j, k;

	// manadatory to access correct verts
	SetCurrentModel();

	// scale verts
	int tmp = m_bodynum;
	for (i = 0; i < pStudioHdr->numbodyparts(); i++)
	{
		mstudiobodyparts_t *pbodypart = pStudioHdr->pBodypart( i );
		for (j = 0; j < pbodypart->nummodels; j++)
		{
			SetBodygroup (i, j);
			SetupModel (i);

			const mstudio_modelvertexdata_t *vertData = m_pmodel->GetVertexData();

			for (k = 0; k < m_pmodel->numvertices; k++)
			{
				*vertData->Position(k) *= scale;
			}
		}
	}

	m_bodynum = tmp;

	// scale complex hitboxes
	int hitboxset = g_MDLViewer->GetCurrentHitboxSet();

	mstudiobbox_t *pbboxes = pStudioHdr->pHitbox( 0, hitboxset );
	for (i = 0; i < pStudioHdr->iHitboxCount( hitboxset ); i++)
	{
		VectorScale (pbboxes[i].bbmin, scale, pbboxes[i].bbmin);
		VectorScale (pbboxes[i].bbmax, scale, pbboxes[i].bbmax);
	}

	// scale bounding boxes
	for (i = 0; i < pStudioHdr->GetNumSeq(); i++)
	{
		mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( i );
		Vector tmp;

		tmp = seqdesc.bbmin;
		VectorScale( tmp, scale, tmp );
		seqdesc.bbmin = tmp;

		tmp = seqdesc.bbmax;
		VectorScale( tmp, scale, tmp );
		seqdesc.bbmax = tmp;

	}

	// maybe scale exeposition, pivots, attachments
}
void cCustomTitleModelTable::resizeEvent(QResizeEvent *ev) {
    if (ModelTable) {

        QString Current=GetCurrentModel();
        // Update view
        int ColumnWidth   =ModelTable->ThumbnailSize.width()+20;
        int RowHeight     =ModelTable->ThumbnailSize.height()+20;
        int NewColumnCount=width()/ColumnWidth;                         if (NewColumnCount<=0) NewColumnCount=1;
        int NewRowCount   =ModelTable->List.count()/NewColumnCount;     if (NewRowCount*NewColumnCount<ModelTable->List.count()) NewRowCount++;

        if ((NewColumnCount!=columnCount())||(NewRowCount!=rowCount())) {
            setColumnCount(NewColumnCount);
            setRowCount(NewRowCount);
        }
        for (int i=0;i<columnCount();i++)  setColumnWidth(i,ColumnWidth);
        for (int i=0;i<rowCount();i++)     setRowHeight(i,RowHeight);

        SetCurrentModel(Current);
    }
    QTableWidget::resizeEvent(ev);
}
int StudioModel::FlexVerts( mstudiomesh_t *pmesh )
{
	// Gotta start at one here, since g_flexages defaults to 0
	static int flextag = 1;

	mstudioflex_t	*pflex = pmesh->pFlex( 0 );
	
	// apply flex weights
	int i, j, n;

	// manadatory to access correct verts
	SetCurrentModel();
	const mstudio_meshvertexdata_t *vertData = pmesh->GetVertexData();
	Assert( vertData ); // This can only return NULL on X360 for now

	for (i = 0; i < pmesh->numflexes; i++)
	{
		float w = g_flexdescweight[pflex[i].flexdesc];

		if (w <= pflex[i].target0 || w >= pflex[i].target3)
		{
			// value outside of range
			continue;
		}
		else if (w < pflex[i].target1)
		{
			// 0 to 1 ramp
			w = (w - pflex[i].target0) / (pflex[i].target1 - pflex[i].target0);
		}
		else if (w > pflex[i].target2)
		{
			// 1 to 0 ramp
			w = (pflex[i].target3 - w) / (pflex[i].target3 - pflex[i].target2);
		}
		else
		{
			// plateau
			w = 1.0;
		}

		if (w > -0.001 && w < 0.001)
			continue;

		// We may have wrinkle information for this flex, but if we're software skinning
		// we're going to ignore it.
		byte *pvanim = pflex[i].pBaseVertanim();
		int nVAnimSizeBytes = pflex[i].VertAnimSizeBytes();

		// JasonM TODO: fix this so there's a float path?
		// If we have a separate stream for flexes, use fixed point
		for (j = 0; j < pflex[i].numverts; j++, pvanim += nVAnimSizeBytes );
		{
			mstudiovertanim_t *pAnim = (mstudiovertanim_t*)( pvanim );

			n = pAnim->index;
			// only flex the indicies that are (still) part of this mesh
			if (n < (int)pmesh->numvertices)
			{
				if (g_flexages[n] < flextag)
				{
					g_flexages[n] = flextag;
					VectorCopy( *vertData->Position(n), g_flexedverts[n] );
					VectorCopy( *vertData->Normal(n), g_flexednorms[n] );
				}
				VectorMA( g_flexedverts[n], w, pAnim->GetDeltaFixed(), g_flexedverts[n] );
				VectorMA( g_flexednorms[n], w, pAnim->GetNDeltaFixed(), g_flexednorms[n] );
			}
			else
			{
				n = 0;
			}
		}
	}

	return flextag++;
	// Con_DPrintf("\n" );
}
示例#5
0
bool StudioModel::LoadModel( const char *pModelName )
{
	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

	if (!pModelName)
		return 0;

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

	m_MDLHandle = g_pMDLCache->FindMDL( pModelName );

	// allocate a pool for a studiohdr cache
	if (m_pStudioHdr != NULL)
	{
		delete m_pStudioHdr;
	}
	m_pStudioHdr = new CStudioHdr( g_pMDLCache->GetStudioHdr( m_MDLHandle ), g_pMDLCache );

	// manadatory to access correct verts
	SetCurrentModel();

	m_pPhysics = LoadPhysics( m_MDLHandle );

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

	CStudioHdr *pStudioHdr = GetStudioHdr();

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

		m_HitboxSets.AddToTail();

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

		// 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 < pStudioHdr->numbones(); ++i )
	{
		mstudiobone_t* pBone = pStudioHdr->pBone(i);

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

	m_physPreviewBone = -1;

	bool forceOpaque = (pStudioHdr->flags() & STUDIOHDR_FLAGS_FORCE_OPAQUE) != 0;
	bool vertexLit = false;
	m_bIsTransparent = false;
	m_bHasProxy = false;

	studiohwdata_t *pHardwareData = g_pMDLCache->GetHardwareData( m_MDLHandle );
	if ( !pHardwareData )
	{
		Assert( 0 );
		return false;
	}

	for( int lodID = pHardwareData->m_RootLOD; lodID < pHardwareData->m_NumLODs; lodID++ )
	{
		studioloddata_t *pLODData = &pHardwareData->m_pLODs[lodID];
		for ( i = 0; i < pLODData->numMaterials; ++i )
		{
			if (pLODData->ppMaterials[i]->IsVertexLit())
			{
				vertexLit = true;
			}
			if ((!forceOpaque) && pLODData->ppMaterials[i]->IsTranslucent())
			{
				m_bIsTransparent = true;
				//Msg("Translucent material %s for model %s\n", pLODData->ppMaterials[i]->GetName(), pStudioHdr->name );
			}
			if (pLODData->ppMaterials[i]->HasProxy())
			{
				m_bHasProxy = true;
			}
		}
	}

	return true;
}
示例#6
0
int StudioModel::FlexVerts( mstudiomesh_t *pmesh )
{
	// Gotta start at one here, since g_flexages defaults to 0
	static int flextag = 1;

	mstudioflex_t	*pflex = pmesh->pFlex( 0 );
	
	// apply flex weights
	int i, j, n;

	// manadatory to access correct verts
	SetCurrentModel();
	const mstudio_meshvertexdata_t *vertData = pmesh->GetVertexData();

	for (i = 0; i < pmesh->numflexes; i++)
	{
		float w = g_flexdescweight[pflex[i].flexdesc];

		if (w <= pflex[i].target0 || w >= pflex[i].target3)
		{
			// value outside of range
			continue;
		}
		else if (w < pflex[i].target1)
		{
			// 0 to 1 ramp
			w = (w - pflex[i].target0) / (pflex[i].target1 - pflex[i].target0);
		}
		else if (w > pflex[i].target2)
		{
			// 1 to 0 ramp
			w = (pflex[i].target3 - w) / (pflex[i].target3 - pflex[i].target2);
		}
		else
		{
			// plateau
			w = 1.0;
		}

		if (w > -0.001 && w < 0.001)
			continue;

		mstudiovertanim_t *pvanim = pflex[i].pVertanim( 0 );

		// JasonM TODO: fix this so there's a float path?
		// If we have a separate stream for flexes, use fixed point
		for (j = 0; j < pflex[i].numverts; j++)
		{
			n = pvanim[j].index;
			// only flex the indicies that are (still) part of this mesh
			if (n < (int)pmesh->numvertices)
			{
				if (g_flexages[n] < flextag)
				{
					g_flexages[n] = flextag;
					VectorCopy( *vertData->Position(n), g_flexedverts[n] );
					VectorCopy( *vertData->Normal(n), g_flexednorms[n] );
				}
				VectorMA( g_flexedverts[n], w, pvanim[j].GetDeltaFixed(), g_flexedverts[n] );
				VectorMA( g_flexednorms[n], w, pvanim[j].GetNDeltaFixed(), g_flexednorms[n] );
			}
			else
			{
				n = 0;
			}
		}
	}

	return flextag++;
	// Con_DPrintf("\n" );
}
示例#7
0
//-----------------------------------------------------------------------------
// Trace rays from each unique vertex, accumulating direct and indirect
// sources at each ray termination. Use the winding data to distribute the unique vertexes
// into the rendering layout.
//-----------------------------------------------------------------------------
void CVradStaticPropMgr::ComputeLighting( CStaticProp &prop, int iThread, int prop_index )
{
	Vector						samplePosition;
	Vector						sampleNormal;
	CUtlVector<colorVertex_t>	colorVerts; 
	CUtlVector<badVertex_t>		badVerts;

	StaticPropDict_t &dict = m_StaticPropDict[prop.m_ModelIdx];
	studiohdr_t	*pStudioHdr = dict.m_pStudioHdr;
	OptimizedModel::FileHeader_t *pVtxHdr = (OptimizedModel::FileHeader_t *)dict.m_VtxBuf.Base();
	if ( !pStudioHdr || !pVtxHdr )
	{
		// must have model and its verts for lighting computation
		// game will fallback to fullbright
		return;
	}

	// for access to this model's vertexes
	SetCurrentModel( pStudioHdr );

	for ( int bodyID = 0; bodyID < pStudioHdr->numbodyparts; ++bodyID )
	{
		OptimizedModel::BodyPartHeader_t* pVtxBodyPart = pVtxHdr->pBodyPart( bodyID );
		mstudiobodyparts_t *pBodyPart = pStudioHdr->pBodypart( bodyID );

		for ( int modelID = 0; modelID < pBodyPart->nummodels; ++modelID )
		{
			OptimizedModel::ModelHeader_t* pVtxModel = pVtxBodyPart->pModel( modelID );
			mstudiomodel_t *pStudioModel = pBodyPart->pModel( modelID );

			// light all unique vertexes
			colorVerts.EnsureCount( pStudioModel->numvertices );
			memset( colorVerts.Base(), 0, colorVerts.Count() * sizeof(colorVertex_t) );

			int numVertexes = 0;
			for ( int meshID = 0; meshID < pStudioModel->nummeshes; ++meshID )
			{
				mstudiomesh_t *pStudioMesh = pStudioModel->pMesh( meshID );
				const mstudio_meshvertexdata_t *vertData = pStudioMesh->GetVertexData();
				for ( int vertexID = 0; vertexID < pStudioMesh->numvertices; ++vertexID )
				{
					// transform position and normal into world coordinate system
					matrix3x4_t	matrix;
					AngleMatrix( prop.m_Angles, prop.m_Origin, matrix );
					VectorTransform( *vertData->Position( vertexID ), matrix, samplePosition );
					AngleMatrix( prop.m_Angles, matrix );
					VectorTransform( *vertData->Normal( vertexID ), matrix, sampleNormal );

					if ( (! (prop.m_Flags & STATIC_PROP_NO_PER_VERTEX_LIGHTING ) ) &&
						 PositionInSolid( samplePosition ) )
					{
						// vertex is in solid, add to the bad list, and recover later
						badVertex_t badVertex;
						badVertex.m_ColorVertex = numVertexes;
						badVertex.m_Position = samplePosition;
						badVertex.m_Normal = sampleNormal;
						badVerts.AddToTail( badVertex );			
					}
					else
					{
						Vector direct_pos=samplePosition;
						int skip_prop=-1;

						Vector directColor(0,0,0);
						if (prop.m_Flags & STATIC_PROP_NO_PER_VERTEX_LIGHTING )
						{
							if (prop.m_bLightingOriginValid)
								VectorCopy( prop.m_LightingOrigin, direct_pos );
							else
								VectorCopy( prop.m_Origin, direct_pos );
							skip_prop = prop_index;
						}
						if ( prop.m_Flags & STATIC_PROP_NO_SELF_SHADOWING )
							skip_prop = prop_index;

						
						ComputeDirectLightingAtPoint( direct_pos,
													  sampleNormal, directColor, iThread,
													  skip_prop );
						Vector indirectColor(0,0,0);

						if (g_bShowStaticPropNormals)
						{
							directColor= sampleNormal;
							directColor += Vector(1.0,1.0,1.0);
							directColor *= 50.0;
						}
						else
							if (numbounce >= 1)
								ComputeIndirectLightingAtPoint( samplePosition, sampleNormal, 
																indirectColor, iThread, true );

						colorVerts[numVertexes].m_bValid = true;
						colorVerts[numVertexes].m_Position = samplePosition;
						VectorAdd( directColor, indirectColor, colorVerts[numVertexes].m_Color );
					}

					numVertexes++;
				}
			}

			// color in the bad vertexes
			// when entire model has no lighting origin and no valid neighbors
			// must punt, leave black coloring
			if ( badVerts.Count() && ( prop.m_bLightingOriginValid || badVerts.Count() != numVertexes ) )
			{
				for ( int nBadVertex = 0; nBadVertex < badVerts.Count(); nBadVertex++ )
				{		
					Vector bestPosition;
					if ( prop.m_bLightingOriginValid )
					{
						// use the specified lighting origin
						VectorCopy( prop.m_LightingOrigin, bestPosition );
					}
					else
					{
						// find the closest valid neighbor
						int best = 0;
						float closest = FLT_MAX;
						for ( int nColorVertex = 0; nColorVertex < numVertexes; nColorVertex++ )
						{
							if ( !colorVerts[nColorVertex].m_bValid )
							{
								// skip invalid neighbors
								continue;
							}
							Vector delta;
							VectorSubtract( colorVerts[nColorVertex].m_Position, badVerts[nBadVertex].m_Position, delta );
							float distance = VectorLength( delta );
							if ( distance < closest )
							{
								closest = distance;
								best    = nColorVertex;
							}
						}

						// use the best neighbor as the direction to crawl
						VectorCopy( colorVerts[best].m_Position, bestPosition );
					}

					// crawl toward best position
					// sudivide to determine a closer valid point to the bad vertex, and re-light
					Vector midPosition;
					int numIterations = 20;
					while ( --numIterations > 0 )
					{
						VectorAdd( bestPosition, badVerts[nBadVertex].m_Position, midPosition );
						VectorScale( midPosition, 0.5f, midPosition );
						if ( PositionInSolid( midPosition ) )
							break;
						bestPosition = midPosition;
					}

					// re-light from better position
					Vector directColor;
					ComputeDirectLightingAtPoint( bestPosition, badVerts[nBadVertex].m_Normal, directColor, iThread );

					Vector indirectColor;
					ComputeIndirectLightingAtPoint( bestPosition, badVerts[nBadVertex].m_Normal,
													indirectColor, iThread, true );

					// save results, not changing valid status
					// to ensure this offset position is not considered as a viable candidate
					colorVerts[badVerts[nBadVertex].m_ColorVertex].m_Position = bestPosition;
					VectorAdd( directColor, indirectColor, colorVerts[badVerts[nBadVertex].m_ColorVertex].m_Color );
				}
			}
			
			// discard bad verts
			badVerts.Purge();

			// distribute the lighting results
			for ( int nLod = 0; nLod < pVtxHdr->numLODs; nLod++ )
			{
				OptimizedModel::ModelLODHeader_t *pVtxLOD = pVtxModel->pLOD( nLod );

				for ( int nMesh = 0; nMesh < pStudioModel->nummeshes; ++nMesh )
				{
					mstudiomesh_t* pMesh = pStudioModel->pMesh( nMesh );
					OptimizedModel::MeshHeader_t* pVtxMesh = pVtxLOD->pMesh( nMesh );

					for ( int nGroup = 0; nGroup < pVtxMesh->numStripGroups; ++nGroup )
					{
						OptimizedModel::StripGroupHeader_t* pStripGroup = pVtxMesh->pStripGroup( nGroup );
						int nMeshIdx = prop.m_MeshData.AddToTail();
						prop.m_MeshData[nMeshIdx].m_Verts.AddMultipleToTail( pStripGroup->numVerts );
						prop.m_MeshData[nMeshIdx].m_nLod = nLod;

						for ( int nVertex = 0; nVertex < pStripGroup->numVerts; ++nVertex )
						{
							int nIndex = pMesh->vertexoffset + pStripGroup->pVertex( nVertex )->origMeshVertID;

							Assert( nIndex < pStudioModel->numvertices );
							prop.m_MeshData[nMeshIdx].m_Verts[nVertex] = colorVerts[nIndex].m_Color;
						}
					}
				}
			}
		}
	}
}
示例#8
0
//-----------------------------------------------------------------------------
// Creates a collision model (based on the render geometry!)
//-----------------------------------------------------------------------------
void CVradStaticPropMgr::CreateCollisionModel( char const* pModelName )
{
	CUtlBuffer buf;
	CUtlBuffer bufvtx;
	CUtlBuffer bufphy;

	int i = m_StaticPropDict.AddToTail();
	m_StaticPropDict[i].m_pModel = NULL;
	m_StaticPropDict[i].m_pStudioHdr = NULL;

	if ( !LoadStudioModel( pModelName, buf ) )
	{
		VectorCopy( vec3_origin, m_StaticPropDict[i].m_Mins );
		VectorCopy( vec3_origin, m_StaticPropDict[i].m_Maxs );
		return;
	}

	studiohdr_t* pHdr = (studiohdr_t*)buf.Base();

	// necessary for vertex access
	SetCurrentModel( pHdr );

	VectorCopy( pHdr->hull_min, m_StaticPropDict[i].m_Mins );
	VectorCopy( pHdr->hull_max, m_StaticPropDict[i].m_Maxs );

	if ( LoadStudioCollisionModel( pModelName, bufphy ) )
	{
		phyheader_t header;
		bufphy.Get( &header, sizeof(header) );

		vcollide_t *pCollide = &m_StaticPropDict[i].m_loadedModel;
		s_pPhysCollision->VCollideLoad( pCollide, header.solidCount, (const char *)bufphy.PeekGet(), bufphy.TellPut() - bufphy.TellGet() );
		m_StaticPropDict[i].m_pModel = m_StaticPropDict[i].m_loadedModel.solids[0];

		/*
		static int propNum = 0;
		char tmp[128];
		sprintf( tmp, "staticprop%03d.txt", propNum );
		DumpCollideToGlView( pCollide, tmp );
		++propNum;
		*/
	}
	else
	{
		// mark this as unused
		m_StaticPropDict[i].m_loadedModel.solidCount = 0;

		// CPhysCollide* pPhys = CreatePhysCollide( pHdr, pVtxHdr );
		m_StaticPropDict[i].m_pModel = ComputeConvexHull( pHdr );
	}

	// clone it
	m_StaticPropDict[i].m_pStudioHdr = (studiohdr_t *)malloc( buf.Size() );
	memcpy( m_StaticPropDict[i].m_pStudioHdr, (studiohdr_t*)buf.Base(), buf.Size() );

	if ( !LoadVTXFile( pModelName, m_StaticPropDict[i].m_pStudioHdr, m_StaticPropDict[i].m_VtxBuf ) )
	{
		// failed, leave state identified as disabled
		m_StaticPropDict[i].m_VtxBuf.Purge();
	}
}
示例#9
0
//-----------------------------------------------------------------------------
// Adds all static prop polys to the ray trace store.
//-----------------------------------------------------------------------------
void CVradStaticPropMgr::AddPolysForRayTrace( void )
{
	int count = m_StaticProps.Count();
	if ( !count )
	{
		// nothing to do
		return;
	}

	for ( int nProp = 0; nProp < count; ++nProp )
	{
		CStaticProp &prop = m_StaticProps[nProp];
		if ( prop.m_Flags & STATIC_PROP_NO_SHADOW )
			continue;

		StaticPropDict_t &dict = m_StaticPropDict[prop.m_ModelIdx];
		studiohdr_t	*pStudioHdr = dict.m_pStudioHdr;
		OptimizedModel::FileHeader_t *pVtxHdr = (OptimizedModel::FileHeader_t *)dict.m_VtxBuf.Base();
		if ( !pStudioHdr || !pVtxHdr )
		{
			// must have model and its verts for decoding triangles
			return;
		}

		// for access to this model's vertexes
		SetCurrentModel( pStudioHdr );
	
		// meshes are deeply hierarchial, divided between three stores, follow the white rabbit
		// body parts -> models -> lod meshes -> strip groups -> strips
		// the vertices and indices are pooled, the trick is knowing the offset to determine your indexed base 
		for ( int bodyID = 0; bodyID < pStudioHdr->numbodyparts; ++bodyID )
		{
			OptimizedModel::BodyPartHeader_t* pVtxBodyPart = pVtxHdr->pBodyPart( bodyID );
			mstudiobodyparts_t *pBodyPart = pStudioHdr->pBodypart( bodyID );

			for ( int modelID = 0; modelID < pBodyPart->nummodels; ++modelID )
			{
				OptimizedModel::ModelHeader_t* pVtxModel = pVtxBodyPart->pModel( modelID );
				mstudiomodel_t *pStudioModel = pBodyPart->pModel( modelID );

				// assuming lod 0, could iterate if required
				int nLod = 0;
				OptimizedModel::ModelLODHeader_t *pVtxLOD = pVtxModel->pLOD( nLod );

				for ( int nMesh = 0; nMesh < pStudioModel->nummeshes; ++nMesh )
				{
					mstudiomesh_t* pMesh = pStudioModel->pMesh( nMesh );
					OptimizedModel::MeshHeader_t* pVtxMesh = pVtxLOD->pMesh( nMesh );
					const mstudio_meshvertexdata_t *vertData = pMesh->GetVertexData();

					for ( int nGroup = 0; nGroup < pVtxMesh->numStripGroups; ++nGroup )
					{
						OptimizedModel::StripGroupHeader_t* pStripGroup = pVtxMesh->pStripGroup( nGroup );

						int nStrip;
						for ( nStrip = 0; nStrip < pStripGroup->numStrips; nStrip++ )
						{
							OptimizedModel::StripHeader_t *pStrip = pStripGroup->pStrip( nStrip );

							if ( pStrip->flags & OptimizedModel::STRIP_IS_TRILIST )
							{
								for ( int i = 0; i < pStrip->numIndices; i += 3 )
								{
									int idx = pStrip->indexOffset + i;

									unsigned short i1 = *pStripGroup->pIndex( idx );
									unsigned short i2 = *pStripGroup->pIndex( idx + 1 );
									unsigned short i3 = *pStripGroup->pIndex( idx + 2 );

									int vertex1 = pStripGroup->pVertex( i1 )->origMeshVertID;
									int vertex2 = pStripGroup->pVertex( i2 )->origMeshVertID;
									int vertex3 = pStripGroup->pVertex( i3 )->origMeshVertID;

									// transform position into world coordinate system
									matrix3x4_t	matrix;
									AngleMatrix( prop.m_Angles, prop.m_Origin, matrix );

									Vector position1;
									Vector position2;
									Vector position3;
									VectorTransform( *vertData->Position( vertex1 ), matrix, position1 );
									VectorTransform( *vertData->Position( vertex2 ), matrix, position2 );
									VectorTransform( *vertData->Position( vertex3 ), matrix, position3 );
// 		printf( "\ngl 3\n" );
// 		printf( "gl %6.3f %6.3f %6.3f 1 0 0\n", XYZ(position1));
// 		printf( "gl %6.3f %6.3f %6.3f 0 1 0\n", XYZ(position2));
// 		printf( "gl %6.3f %6.3f %6.3f 0 0 1\n", XYZ(position3));
									g_RtEnv.AddTriangle( nProp,
														 position1, position2, position3,
														 Vector(0,0,0));
								}
							}
							else
							{
								// all tris expected to be discrete tri lists
								// must fixme if stripping ever occurs
								printf("unexpected strips found\n");
								Assert( 0 );
								return;
							}
						}
					}
				}
			}
		}
	}
}
示例#10
0
//-----------------------------------------------------------------------------
// Add, find collision model in cache
//-----------------------------------------------------------------------------
static CPhysCollide* GetCollisionModel( char const* pModelName )
{
	// Convert to a common string
	char* pTemp = (char*)_alloca(strlen(pModelName) + 1);
	strcpy( pTemp, pModelName );
	_strlwr( pTemp );

	char* pSlash = strchr( pTemp, '\\' );
	while( pSlash )
	{
		*pSlash = '/';
		pSlash = strchr( pTemp, '\\' );
	}

	// Find it in the cache
	ModelCollisionLookup_t lookup;
	lookup.m_Name = pTemp;
	int i = s_ModelCollisionCache.Find( lookup );
	if (i != s_ModelCollisionCache.InvalidIndex())
		return s_ModelCollisionCache[i].m_pCollide;

	// Load the studio model file
	CUtlBuffer buf;
	if (!LoadStudioModel(pModelName, "prop_static", buf))
	{
		Warning("Error loading studio model \"%s\"!\n", pModelName );

		// This way we don't try to load it multiple times
		lookup.m_pCollide = 0;
		s_ModelCollisionCache.Insert( lookup );

		return 0;
	}

	// Compute the convex hull of the model...
	studiohdr_t* pStudioHdr = (studiohdr_t*)buf.PeekGet();

	// necessary for vertex access
	SetCurrentModel( pStudioHdr );

	lookup.m_pCollide = ComputeConvexHull( pStudioHdr );
	s_ModelCollisionCache.Insert( lookup );

	if ( !lookup.m_pCollide )
	{
		Warning("Bad geometry on \"%s\"!\n", pModelName );
	}

	// Debugging
	if (g_DumpStaticProps)
	{
		static int propNum = 0;
		char tmp[128];
		sprintf( tmp, "staticprop%03d.txt", propNum );
		DumpCollideToGlView( lookup.m_pCollide, tmp );
		++propNum;
	}

	FreeCurrentModelVertexes();

	// Insert into cache...
	return lookup.m_pCollide;
}