コード例 #1
0
ファイル: vradstaticprops.cpp プロジェクト: chrizonix/RCBot2
//-----------------------------------------------------------------------------
// 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;
						}
					}
				}
			}
		}
	}
}
コード例 #2
0
ファイル: ToolMapping.cpp プロジェクト: artemeliy/inf4715
void UnwrapMod::fnAlignAndFit(int axis)
{



	//get our selection
	Box3 bounds;
	bounds.Init();
	//get the bounding box
	Point3 pnorm(0.0f,0.0f,0.0f);
	int ct = 0;
	TimeValue t = GetCOREInterface()->GetTime();
	for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
	{
		MeshTopoData *ld = mMeshTopoData[ldID];
		Matrix3 tm = mMeshTopoData.GetNodeTM(t,ldID);
		for (int k = 0; k < ld->GetNumberFaces(); k++) 
		{
			if (ld->GetFaceSelected(k))
			{
					// Grap the three points, xformed
				int pcount = 3;
					//				if (gfaces[k].flags & FLAG_QUAD) pcount = 4;
				pcount = ld->GetFaceDegree(k);//gfaces[k]->count;

				Point3 temp_point[4];
				for (int j=0; j<pcount; j++) 
				{
					int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j];
					bounds += ld->GetGeomVert(index) *tm;//gverts.d[index].p;
					if (j < 4)
						temp_point[j] = ld->GetGeomVert(index);//gverts.d[index].p;
				}
				pnorm += VectorTransform(Normalize(temp_point[1]-temp_point[0]^temp_point[2]-temp_point[1]),tm);
				ct++;
			}
		}	
	}

	if (ct == 0) return;

	theHold.Begin();
	SuspendAnimate();
	AnimateOff();

	pnorm = pnorm / (float) ct;
	Matrix3 tm(1);
	
	//if just a primary axis set the tm;
	Point3 center = bounds.Center();
		// build the scale
	Point3 scale(bounds.Width().x ,bounds.Width().y , bounds.Width().z);
	if (scale.x == 0.0f) scale.x = 1.0f;
	if (scale.y == 0.0f) scale.y = 1.0f;
 	if (scale.z == 0.0f) scale.z = 1.0f;
	
 	if (axis == 0) // x axi
	{

  		tm.SetRow(0,Point3(0.0f,-scale.y,0.0f));
		tm.SetRow(1,Point3(0.0f,0.0f,scale.z));
		tm.SetRow(2,Point3(scale.x,0.0f,0.0f));
		if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP)  || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP))
			tm.SetRow(3,center);
		else if (fnGetMapMode() == CYLINDRICALMAP)
		{
			center.x = bounds.pmin.x;
			tm.SetRow(3,center);
		}		

		Matrix3 ptm(1), id(1);
		tm = tm ;
		SetXFormPacket tmpck(tm,ptm);
		tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE);
	}
	else if (axis == 1) // y axi
	{
  		tm.SetRow(0,Point3(scale.x,0.0f,0.0f));
 		tm.SetRow(1,Point3(0.0f,0.0f,scale.z));
		tm.SetRow(2,Point3(0.0f,scale.y,0.0f));
		if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP)|| (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP))
			tm.SetRow(3,center);
		else if (fnGetMapMode() == CYLINDRICALMAP)
		{
			center.y = bounds.pmin.y;
			tm.SetRow(3,center);
		}
		

		Matrix3 ptm(1), id(1);
		tm = tm;
		SetXFormPacket tmpck(tm,ptm);
		tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE);
	}
	else if (axis == 2) //z axi
	{
		tm.SetRow(0,Point3(scale.x,0.0f,0.0f));
		tm.SetRow(1,Point3(0.0f,scale.y,0.0f));
		tm.SetRow(2,Point3(0.0f,0.0f,scale.z));
		if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP)|| (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP))
			tm.SetRow(3,center);
		else if (fnGetMapMode() == CYLINDRICALMAP)
		{
			center.z = bounds.pmin.z;
			tm.SetRow(3,center);
		}
		

		Matrix3 ptm(1), id(1);
		tm = tm;
		SetXFormPacket tmpck(tm,ptm);
		tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE);
	}
	else if (axis == 3) // normal
	{
		int numberOfSelectionGroups = 0;
		for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
		{
			MeshTopoData *ld = mMeshTopoData[ldID];
			if (ld->GetFaceSelection().NumberSet())
				numberOfSelectionGroups++;
		}
		if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP) || (numberOfSelectionGroups > 1))
		{
			//get our tm
			Matrix3 tm;
			UnwrapMatrixFromNormal(pnorm,tm);
 			Matrix3 itm = Inverse(tm);
			//find our x and y scale
			float xmax = 0.0f;
			float ymax = 0.0f;
			float zmax = 0.0f;
			Box3 localBounds;
			localBounds.Init();
			for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
			{
				MeshTopoData *ld = mMeshTopoData[ldID];
				Matrix3 tm = mMeshTopoData.GetNodeTM(t,ldID);
				for (int k = 0; k < ld->GetNumberFaces(); k++) 
				{
					if (ld->GetFaceSelected(k))
					{
							// Grap the three points, xformed
						int pcount = 3;
							//				if (gfaces[k].flags & FLAG_QUAD) pcount = 4;
						pcount = ld->GetFaceDegree(k);//gfaces[k]->count;

						Point3 temp_point[4];
						for (int j=0; j<pcount; j++) 
						{
							int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j];
							Point3 p = ld->GetGeomVert(index) * tm * itm;//gverts.d[index].p * itm;
							localBounds += p;
						}
					}
				}
			}

//			center = localBounds.Center();
			xmax = localBounds.pmax.x - localBounds.pmin.x;
			ymax = localBounds.pmax.y - localBounds.pmin.y;
			zmax = localBounds.pmax.z - localBounds.pmin.z;

			if (xmax < 0.001f)
				xmax = 1.0f;
			if (ymax < 0.001f)
				ymax = 1.0f;
			if (zmax < 0.001f)
				zmax = 1.0f;

			Point3 vec;
			vec = Normalize(tm.GetRow(0)) * xmax;
			tm.SetRow(0,vec);

			vec = Normalize(tm.GetRow(1)) * ymax;
			tm.SetRow(1,vec);

			vec = Normalize(tm.GetRow(2)) * zmax;
			tm.SetRow(2,vec);


			tm.SetRow(3,center);
			

			Matrix3 ptm(1), id(1);
			tm = tm ;
			SetXFormPacket tmpck(tm,ptm);
			tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE);
		}		
		else if ((fnGetMapMode() == CYLINDRICALMAP) || (fnGetMapMode() == SPHERICALMAP)|| (fnGetMapMode() == BOXMAP))
		{

			for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
			{


				//get our first 2 rings
				Tab<int> openEdges;
				Tab<int> startRing;
				Tab<int> endRing;

				MeshTopoData *ld =  mMeshTopoData[ldID];

				//skip any local data that has no selections
				if (ld->GetFaceSelection().NumberSet() == 0)
					continue;

				Matrix3 nodeTM = mMeshTopoData.GetNodeTM(t,ldID);

				for (int i = 0; i < ld->GetNumberGeomEdges(); i++)//TVMaps.gePtrList.Count(); i++)
				{
					int numberSelectedFaces = 0;
					int ct = ld->GetGeomEdgeNumberOfConnectedFaces(i);//TVMaps.gePtrList[i]->faceList.Count();
					for (int j = 0; j < ct; j++)
					{
						int faceIndex = ld->GetGeomEdgeConnectedFace(i,j);//TVMaps.gePtrList[i]->faceList[j];
						if (ld->GetFaceSelected(faceIndex))//fsel[faceIndex])
							numberSelectedFaces++;
					}
					if (numberSelectedFaces == 1)
					{
						openEdges.Append(1,&i,1000);
						
					}
				}

				GetOpenEdges(ld,openEdges, startRing);
				GetOpenEdges(ld,openEdges, endRing);
				Point3 zVec = pnorm;

				Point3 centerS(0.0f,0.0f,0.0f), centerE;
				if ((startRing.Count() != 0) && (endRing.Count() != 0))
				{
					//get the center start
					Box3 BoundsS, BoundsE;
					BoundsS.Init();
					BoundsE.Init();

					//get the center end
					for (int i = 0; i < startRing.Count(); i++)
					{
						int eIndex = startRing[i];
						int a = ld->GetGeomEdgeVert(eIndex,0);//TVMaps.gePtrList[eIndex]->a;
						int b = ld->GetGeomEdgeVert(eIndex,1);//TVMaps.gePtrList[eIndex]->b;

						BoundsS += ld->GetGeomVert(a) * nodeTM;//TVMaps.geomPoints[a];
						BoundsS += ld->GetGeomVert(b) * nodeTM;//TVMaps.geomPoints[b];
					}


					for (int i = 0; i < endRing.Count(); i++)
					{
						int eIndex = endRing[i];
						int a = ld->GetGeomEdgeVert(eIndex,0);//TVMaps.gePtrList[eIndex]->a;
						int b = ld->GetGeomEdgeVert(eIndex,1);//TVMaps.gePtrList[eIndex]->b;

						BoundsE += ld->GetGeomVert(a) * nodeTM;//TVMaps.geomPoints[a];
						BoundsE += ld->GetGeomVert(b) * nodeTM;//TVMaps.geomPoints[b];
					}

					
					centerS = BoundsS.Center();
					centerE = BoundsE.Center();
					//create the vec
					zVec = centerE - centerS;

				}
				else if ((startRing.Count() != 0) && (endRing.Count() == 0))
				{
					//get the center start
					Box3 BoundsS;
					BoundsS.Init();
					

					//get the center end
					for (int i = 0; i < startRing.Count(); i++)
					{
						int eIndex = startRing[i];
						int a =  ld->GetGeomEdgeVert(eIndex,0);//TVMaps.gePtrList[eIndex]->a;
						int b =  ld->GetGeomEdgeVert(eIndex,1);//TVMaps.gePtrList[eIndex]->b;

						BoundsS += ld->GetGeomVert(a) * nodeTM;//TVMaps.geomPoints[a];
						BoundsS += ld->GetGeomVert(b) * nodeTM;//TVMaps.geomPoints[b];
					}

					centerS = BoundsS.Center();
					

					int farthestPoint= -1;
					Point3 fp;
					float farthestDist= 0.0f;
					for (int k=0; k < ld->GetNumberFaces(); k++) 
					{
						if (ld->GetFaceSelected(k))
						{
								// Grap the three points, xformed
							int pcount = 3;
								//				if (gfaces[k].flags & FLAG_QUAD) pcount = 4;
							pcount = ld->GetFaceDegree(k);//gfaces[k]->count;

							
							for (int j=0; j<pcount; j++) 
							{
								int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j];
								
								Point3 p = ld->GetGeomVert(index)* nodeTM;//gverts.d[index].p;
								float d = LengthSquared(p-centerS);
								if ((d > farthestDist) || (farthestPoint == -1))
								{
									farthestDist = d;
									farthestPoint = index;
									fp = p;
								}							
							}
						}
					}

					
					
					centerE = fp;
					//create the vec
					zVec = centerE - centerS;

				}
				else
				{
					zVec = Point3(0.0f,0.0f,1.0f);
				}


				//get our tm
				Matrix3 tm;
				UnwrapMatrixFromNormal(zVec,tm);
				tm.SetRow(3,centerS);
 				Matrix3 itm = Inverse(tm);
				//find our x and y scale
				float xmax = 0.0f;
				float ymax = 0.0f;
				float zmax = 0.0f;
				Box3 localBounds;
				localBounds.Init();
				for (int k = 0; k < ld->GetNumberFaces(); k++)//gfaces.Count(); k++) 
				{
					if (ld->GetFaceSelected(k))
					{
							// Grap the three points, xformed
						int pcount = 3;
							//				if (gfaces[k].flags & FLAG_QUAD) pcount = 4;
						pcount = ld->GetFaceDegree(k);//gfaces[k]->count;

						Point3 temp_point[4];
						for (int j=0; j<pcount; j++) 
						{
							int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j];
							Point3 p = ld->GetGeomVert(index) * nodeTM * itm;//gverts.d[index].p * itm;
							localBounds += p;
						}
					}
				}

				center = localBounds.Center() * tm;

				if (fnGetMapMode() == CYLINDRICALMAP)
				{
					if ((startRing.Count() == 0) && (endRing.Count() == 0))
					{
						centerS = center;
						centerS.z = localBounds.pmin.z;					
					}
					else
					{

						centerS = centerS * itm;
						centerS.z = localBounds.pmin.z;
						centerS = centerS * tm;
					}
				}
				else if ((fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP))
				{
					centerS = center;
				}

				Point3 bc = localBounds.Center();
				bc.z = localBounds.pmin.z;
				bc = bc * tm;

				xmax = localBounds.pmax.x - localBounds.pmin.x;
				ymax = localBounds.pmax.y - localBounds.pmin.y;
				zmax = localBounds.pmax.z - localBounds.pmin.z;

				Point3 vec;
				vec = Normalize(tm.GetRow(0)) * xmax;
				tm.SetRow(0,vec);

				vec = Normalize(tm.GetRow(1)) * ymax;
				tm.SetRow(1,vec);

				vec = Normalize(tm.GetRow(2)) * zmax;
				tm.SetRow(2,vec);


				
				tm.SetRow(3,centerS);
				

				Matrix3 ptm(1), id(1);
				tm = tm;
				SetXFormPacket tmpck(tm,ptm);
				tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE);
			}
			
		}
	}
	ResumeAnimate();

	if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == CYLINDRICALMAP) || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP))
		ApplyGizmo();

	theHold.Accept(GetString(IDS_MAPPING_ALIGN));

	fnGetGizmoTM();

	if (ip) ip->RedrawViews(ip->GetTime());

}
コード例 #3
0
void MorphByBone::MirrorMorph(int sourceIndex, int targetIndex, BOOL mirrorData)
{
	//validate the indices
	if ((sourceIndex < 0) || (sourceIndex >= boneData.Count())) return;
	if ((targetIndex < 0) || (targetIndex >= boneData.Count())) return;

	float threshold = 0.0f;
	pblock->GetValue(pb_mirrorthreshold,0,threshold,FOREVER);

	//get our mirror tm

	theHold.Begin();
	theHold.Put(new MorphUIRestore(this));  //stupid Hack to handle UI update after redo
	

	for (int i = 0; i < localDataList.Count(); i++)
	{

		MorphByBoneLocalData *ld = localDataList[i];
		if (ld)
		{
			//build our vertex look up index
			ld->tempPoints = ld->preDeform;
			ld->tempMatchList.SetCount(ld->tempPoints.Count());
			for (int j = 0; j < ld->preDeform.Count(); j++)
			{
				Matrix3 tm(1);
				//need to put our original points
				ld->tempPoints[j] = ld->tempPoints[j] * mirrorTM;
				ld->tempMatchList[j] = -1;
			}
		
			for (int j = 0; j < ld->tempPoints.Count(); j++)
			{
				Point3 sourcePoint = ld->preDeform[j];
				float closest =  3.4e+38;
				int closestID = -1;
				for (int k = 0; k < ld->tempPoints.Count(); k++)
				{
					Point3 mirrorPoint = ld->tempPoints[k];
					float dist = Length(sourcePoint-mirrorPoint);
					if ((dist < threshold) && (dist < closest))
					{
						closest = dist;
						closestID = k;
					}

				}
				if (closestID != -1)
					ld->tempMatchList[closestID] = j;
			}
	//loop through our targets
			int numberOfNewMorphs = boneData[sourceIndex]->morphTargets.Count();
	
			int currentSourceMorph = 0;
			Matrix3 initialDriverTargetTM = GetNode(targetIndex)->GetNodeTM(GetCOREInterface()->GetTime());
//			Matrix3 initialDriverTargetTM = boneData[targetIndex]->intialBoneNodeTM;
			Matrix3 initialDriverSourceTM = GetNode(sourceIndex)->GetNodeTM(GetCOREInterface()->GetTime());// boneData[sourceIndex]->intialBoneNodeTM;

			Matrix3 tm(1);
			//from world to local
			tm = Inverse(ld->selfNodeCurrentTM); 
			//morph tm in local object space and mirrored
			tm = tm * mirrorTM;
			//back to world space
			tm  = tm  * ld->selfNodeCurrentTM; 
			//now in local space of the target bone
//			tm = tm * Inverse(boneData[targetIndex]->parentBoneNodeCurrentTM);
			
			//now intitial driver tm in world space
			initialDriverSourceTM *= tm;


			for (int j = 0; j < numberOfNewMorphs; j++)
			{
	//create a new morph 
				MorphTargets *morphTarget = boneData[sourceIndex]->morphTargets[currentSourceMorph]->Clone();

		//remap the indices
				
				morphTarget->d.ZeroCount();
				for (int k = 0; k < boneData[sourceIndex]->morphTargets[currentSourceMorph]->d.Count(); k++)
				{
					int vertID = boneData[sourceIndex]->morphTargets[currentSourceMorph]->d[k].vertexID;
					int index = ld->tempMatchList[vertID];
					if (index != -1)
					{
						morphTarget->d.Append(1,&boneData[sourceIndex]->morphTargets[currentSourceMorph]->d[k],500);		
						morphTarget->d[morphTarget->d.Count()-1].vertexID = index;
						morphTarget->d[morphTarget->d.Count()-1].originalPt = morphTarget->d[morphTarget->d.Count()-1].originalPt * mirrorTM;
					}
				}
				if (mirrorData)		
				{
					
					morphTarget->parentTM = boneData[targetIndex]->parentBoneNodeCurrentTM;


	//mirror the source tms
					Matrix3 morphTM = morphTarget->boneTMInParentSpace;
					//put in world space
					morphTM = morphTM * boneData[sourceIndex]->parentBoneNodeCurrentTM;
					//now in world space
					morphTM *= tm;										
	//rebuild the tms
					//put the driver tm in the morph tm space
					Matrix3 newTM = initialDriverTargetTM;
					newTM = newTM * Inverse(initialDriverSourceTM);
					newTM = newTM * morphTM;
					newTM = newTM * Inverse(boneData[targetIndex]->parentBoneNodeCurrentTM);
					
					morphTarget->boneTMInParentSpace = newTM;
					
	//mirror the source deltas
					for (int k = 0; k < morphTarget->d.Count(); k++)
					{
						Point3 vec = morphTarget->d[k].vec; // current bone space
						vec = VectorTransform(vec,boneData[sourceIndex]->intialBoneNodeTM); //world space
						vec = VectorTransform(vec,tm); //world space after mirror
						vec = VectorTransform(vec,Inverse(boneData[targetIndex]->intialBoneNodeTM)); //bone space
						morphTarget->d[k].vec = vec;

						vec = morphTarget->d[k].vecParentSpace; //parent space
						vec = VectorTransform(vec,boneData[sourceIndex]->intialParentNodeTM); //world space
						vec = VectorTransform(vec,tm); //world space after mirror
						vec = VectorTransform(vec,Inverse(boneData[targetIndex]->intialParentNodeTM)); //bone space
						morphTarget->d[k].vecParentSpace = vec;
						
					}


				}

				float angle = 0.0f;

				Matrix3 currentBoneTM = boneData[targetIndex]->currentBoneNodeTM;
				Matrix3 currentParentBoneTM = boneData[targetIndex]->parentBoneNodeCurrentTM;
				currentBoneTM *= Inverse(currentParentBoneTM);
				angle = AngleBetweenTMs(currentBoneTM,morphTarget->boneTMInParentSpace);
				float per = 1.0f - angle/morphTarget->influenceAngle;
				per = GetFalloff(per, morphTarget->falloff,morphTarget->curve);
				if (per < 0.0f) 
					per = 0.0f;
				morphTarget->weight = per;	


				boneData[targetIndex]->morphTargets.Append(1,&morphTarget);
				theHold.Put(new CreateMorphRestore(this,morphTarget));
				currentSourceMorph++;
			}

		}
	}
	theHold.Put(new MorphUIRestore(this));  //stupid Hack to handle UI update after redo

	theHold.Accept(GetString(IDS_MIRRORMORPHS));

	BuildTreeList();

}
コード例 #4
0
	//-----------------------------------------------------------------------------
	// This is called by the base object when it's time to spawn the control panels
	//-----------------------------------------------------------------------------
	void CPlantedC4::SpawnControlPanels()
	{
		char buf[64];

		// FIXME: Deal with dynamically resizing control panels?

		// If we're attached to an entity, spawn control panels on it instead of use
		CBaseAnimating *pEntityToSpawnOn = this;
		char *pOrgLL = "controlpanel%d_ll";
		char *pOrgUR = "controlpanel%d_ur";
		char *pAttachmentNameLL = pOrgLL;
		char *pAttachmentNameUR = pOrgUR;

		Assert( pEntityToSpawnOn );

		// Lookup the attachment point...
		int nPanel;
		for ( nPanel = 0; true; ++nPanel )
		{
			Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel );
			int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
			if (nLLAttachmentIndex <= 0)
			{
				// Try and use my panels then
				pEntityToSpawnOn = this;
				Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel );
				nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
				if (nLLAttachmentIndex <= 0)
					return;
			}

			Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel );
			int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
			if (nURAttachmentIndex <= 0)
			{
				// Try and use my panels then
				Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel );
				nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
				if (nURAttachmentIndex <= 0)
					return;
			}

			const char *pScreenName;
			GetControlPanelInfo( nPanel, pScreenName );
			if (!pScreenName)
				continue;

			const char *pScreenClassname;
			GetControlPanelClassName( nPanel, pScreenClassname );
			if ( !pScreenClassname )
				continue;

			// Compute the screen size from the attachment points...
			matrix3x4_t	panelToWorld;
			pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld );

			matrix3x4_t	worldToPanel;
			MatrixInvert( panelToWorld, worldToPanel );

			// Now get the lower right position + transform into panel space
			Vector lr, lrlocal;
			pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld );
			MatrixGetColumn( panelToWorld, 3, lr );
			VectorTransform( lr, worldToPanel, lrlocal );

			float flWidth = lrlocal.x;
			float flHeight = lrlocal.y;

			CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex );
			pScreen->ChangeTeam( GetTeamNumber() );
			pScreen->SetActualSize( flWidth, flHeight );
			pScreen->SetActive( true );
			pScreen->MakeVisibleOnlyToTeammates( false );
			int nScreen = m_hScreens.AddToTail( );
			m_hScreens[nScreen].Set( pScreen );			
		}
	}
コード例 #5
0
ファイル: evalcol.cpp プロジェクト: artemeliy/inf4715
// Geometric normal (face normal)
Point3 SContext::GNormal(void)
{
	// The face normals are already in camera space
	return VectorTransform(tmAfterWSM, mesh->getFaceNormal(faceNum));
}
コード例 #6
0
/*
================

================
*/
void StudioModel::DrawPoints ( )
{
	int					i, j;
	mstudiomesh_t		*pmesh;
	byte				*pvertbone;
	byte				*pnormbone;
	vec3_t				*pstudioverts;
	vec3_t				*pstudionorms;
	mstudiotexture_t	*ptexture;
	float 				*av;
	float				*lv;
	float				lv_tmp;
	short				*pskinref;

	pvertbone = ((byte *)m_pstudiohdr + m_pmodel->vertinfoindex);
	pnormbone = ((byte *)m_pstudiohdr + m_pmodel->norminfoindex);
	ptexture = (mstudiotexture_t *)((byte *)m_ptexturehdr + m_ptexturehdr->textureindex);

	pmesh = (mstudiomesh_t *)((byte *)m_pstudiohdr + m_pmodel->meshindex);

	pstudioverts = (vec3_t *)((byte *)m_pstudiohdr + m_pmodel->vertindex);
	pstudionorms = (vec3_t *)((byte *)m_pstudiohdr + m_pmodel->normindex);

	pskinref = (short *)((byte *)m_ptexturehdr + m_ptexturehdr->skinindex);
	if (m_skinnum != 0 && m_skinnum < m_ptexturehdr->numskinfamilies)
		pskinref += (m_skinnum * m_ptexturehdr->numskinref);

	for (i = 0; i < m_pmodel->numverts; i++)
	{
		VectorTransform (pstudioverts[i], g_bonetransform[pvertbone[i]], g_pxformverts[i]);
	}

//
// clip and draw all triangles
//

	lv = (float *)g_pvlightvalues;
	for (j = 0; j < m_pmodel->nummesh; j++) 
	{
		int flags;
		flags = ptexture[pskinref[pmesh[j].skinref]].flags;
		for (i = 0; i < pmesh[j].numnorms; i++, lv += 3, pstudionorms++, pnormbone++)
		{
			Lighting (&lv_tmp, *pnormbone, flags, (float *)pstudionorms);

			// FIX: move this check out of the inner loop
			if (flags & STUDIO_NF_CHROME)
				Chrome( g_chrome[(float (*)[3])lv - g_pvlightvalues], *pnormbone, (float *)pstudionorms );

			lv[0] = lv_tmp * g_lightcolor[0];
			lv[1] = lv_tmp * g_lightcolor[1];
			lv[2] = lv_tmp * g_lightcolor[2];
		}
	}

	glCullFace(GL_FRONT);

	for (j = 0; j < m_pmodel->nummesh; j++) 
	{
		float s, t;
		short		*ptricmds;

		pmesh = (mstudiomesh_t *)((byte *)m_pstudiohdr + m_pmodel->meshindex) + j;
		ptricmds = (short *)((byte *)m_pstudiohdr + pmesh->triindex);

		s = 1.0/(float)ptexture[pskinref[pmesh->skinref]].width;
		t = 1.0/(float)ptexture[pskinref[pmesh->skinref]].height;

		glBindTexture( GL_TEXTURE_2D, ptexture[pskinref[pmesh->skinref]].index );

		if (ptexture[pskinref[pmesh->skinref]].flags & STUDIO_NF_CHROME)
		{
			while (i = *(ptricmds++))
			{
				if (i < 0)
				{
					glBegin( GL_TRIANGLE_FAN );
					i = -i;
				}
				else
				{
					glBegin( GL_TRIANGLE_STRIP );
				}


				for( ; i > 0; i--, ptricmds += 4)
				{
					// FIX: put these in as integer coords, not floats
					glTexCoord2f(g_chrome[ptricmds[1]][0]*s, g_chrome[ptricmds[1]][1]*t);
					
					lv = g_pvlightvalues[ptricmds[1]];
					glColor4f( lv[0], lv[1], lv[2], 1.0 );

					av = g_pxformverts[ptricmds[0]];
					glVertex3f(av[0], av[1], av[2]);
				}
				glEnd( );
			}	
		} 
		else 
		{
			while (i = *(ptricmds++))
			{
				if (i < 0)
				{
					glBegin( GL_TRIANGLE_FAN );
					i = -i;
				}
				else
				{
					glBegin( GL_TRIANGLE_STRIP );
				}


				for( ; i > 0; i--, ptricmds += 4)
				{
					// FIX: put these in as integer coords, not floats
					glTexCoord2f(ptricmds[2]*s, ptricmds[3]*t);
					
					lv = g_pvlightvalues[ptricmds[1]];
					glColor4f( lv[0], lv[1], lv[2], 1.0 );

					av = g_pxformverts[ptricmds[0]];
					glVertex3f(av[0], av[1], av[2]);
				}
				glEnd( );
			}	
		}
	}
}
コード例 #7
0
//-----------------------------------------------------------------------------
// Purpose: Attaches fire to the hitboxes of an animating character. The fire
//			is distributed based on hitbox volumes -- it attaches to the larger
//			hitboxes first.
//-----------------------------------------------------------------------------
void C_EntityFlame::AttachToHitBoxes( void )
{
	m_pCachedModel = NULL;

	C_BaseCombatCharacter *pAnimating = (C_BaseCombatCharacter *)m_hEntAttached.Get();
	if (!pAnimating || !pAnimating->GetModel())
	{
		return;
	}

	studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
	if (!pStudioHdr)
	{
		return;
	}

	mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->m_nHitboxSet );
	if ( !set )
	{
		return;
	}

	if ( !set->numhitboxes )
	{
		return;
	}

	m_pCachedModel = pAnimating->GetModel();

	int boneMask = BONE_USED_BY_HITBOX | BONE_USED_BY_ATTACHMENT;
	studiocache_t *pcache = Studio_GetBoneCache( pStudioHdr, pAnimating->GetSequence(), pAnimating->m_flAnimTime, pAnimating->GetAbsAngles(), pAnimating->GetAbsOrigin(), boneMask );
	if ( !pcache )
	{
		matrix3x4_t bonetoworld[MAXSTUDIOBONES];

		pAnimating->SetupBones( bonetoworld, MAXSTUDIOBONES, boneMask, gpGlobals->curtime );
		pcache = Studio_SetBoneCache( pStudioHdr, pAnimating->GetSequence(), pAnimating->m_flAnimTime, pAnimating->GetAbsAngles(), pAnimating->GetAbsOrigin(), boneMask, bonetoworld );
	}
	matrix3x4_t	*hitboxbones[MAXSTUDIOBONES];
	Studio_LinkHitboxCache( hitboxbones, pcache, pStudioHdr, set );

	//
	// Sort the hitboxes by volume.
	//
	HitboxVolume_t hitboxvolume[MAXSTUDIOBONES];
	for ( int i = 0; i < set->numhitboxes; i++ )
	{
		mstudiobbox_t *pBox = set->pHitbox(i);
		hitboxvolume[i].nIndex = i;
		hitboxvolume[i].flVolume = CalcBoxVolume(pBox->bbmin, pBox->bbmax);
	}
	qsort(hitboxvolume, set->numhitboxes, sizeof(hitboxvolume[0]), (int (__cdecl *)(const void *, const void *))SortHitboxVolumes);

	//
	// Attach fire to the hitboxes.
	//
	for ( i = 0; i < NUM_HITBOX_FIRES; i++ )
	{
		//
		// Pick the 5 biggest hitboxes, or random ones if there are less than 5 hitboxes,
		// then pick random ones after that.
		//
		if (( i < 5 ) && ( i < set->numhitboxes ))
		{
			m_nHitbox[i] = hitboxvolume[i].nIndex;
		}
		else
		{
			m_nHitbox[i] = random->RandomInt( 0, set->numhitboxes - 1 );
		}
		mstudiobbox_t *pBox = set->pHitbox(m_nHitbox[i]);

		m_pFireSmoke[i] = new C_FireSmoke;

		//
		// Calculate a position within the hitbox to place the fire.
		//
		m_vecFireOrigin[i] = Vector(random->RandomFloat(pBox->bbmin.x, pBox->bbmax.x), random->RandomFloat(pBox->bbmin.y, pBox->bbmax.y), random->RandomFloat(pBox->bbmin.z, pBox->bbmax.z));
		Vector vecAbsOrigin;
		VectorTransform(m_vecFireOrigin[i], *hitboxbones[m_nHitbox[i]], vecAbsOrigin);
		m_pFireSmoke[i]->SetLocalOrigin( vecAbsOrigin );

		//
		// The first 2 fires emit smoke, the rest do not.
		//
		m_pFireSmoke[i]->m_nFlags = bitsFIRESMOKE_ACTIVE | bitsFIRESMOKE_GLOW;
		if ( i < 2 )
		{
			m_pFireSmoke[i]->m_nFlags |= bitsFIRESMOKE_SMOKE;
		}

		m_pFireSmoke[i]->m_nFlameModelIndex	= modelinfo->GetModelIndex("sprites/fire1.vmt");
		m_pFireSmoke[i]->m_flScale = 0;
		m_pFireSmoke[i]->m_flStartScale = 0;
		m_pFireSmoke[i]->m_flScaleTime = 1.5;
		m_pFireSmoke[i]->m_flScaleRegister = 0.1;
		m_pFireSmoke[i]->m_flChildFlameSpread = 20.0;
		m_pFireSmoke[i]->m_flScaleStart = 0;
		m_pFireSmoke[i]->m_flScaleEnd = 0.00012f * hitboxvolume[i].flVolume;
		m_pFireSmoke[i]->m_flScaleTimeStart = Helper_GetTime();
		m_pFireSmoke[i]->m_flScaleTimeEnd = Helper_GetTime() + 2.0;

		m_pFireSmoke[i]->StartClientOnly();
	}

	m_bAttachedToHitboxes = true;
}
コード例 #8
0
ファイル: overview.cpp プロジェクト: cia48621793/hlsdk-xash3d
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : flTime - 
//			intermission - 
//-----------------------------------------------------------------------------
int CHudOverview::Draw(float flTime)
{
#if 0
	// only draw in overview mode
	if (!gEngfuncs.Overview_GetOverviewState())
		return 1;

	// make sure we have player info
//	gViewPort->GetAllPlayersInfo();
	gHUD.m_Scoreboard.GetAllPlayersInfo();

	// calculate player size on the overview
	int x1, y1, x2, y2;
	float v0[3]={0,0,0}, v1[3]={64,64,0};
	gEngfuncs.Overview_WorldToScreen(v0, &x1, &y1);
	gEngfuncs.Overview_WorldToScreen(v1, &x2, &y2);
	float scale = abs(x2 - x1);

	// loop through all the players and draw them on the map
	for (int i = 1; i < MAX_PLAYERS; i++)
	{
		cl_entity_t *pl = gEngfuncs.GetEntityByIndex(i);

		if (pl && pl->player && pl->curstate.health > 0 && pl->curstate.solid != SOLID_NOT)
		{
			int x, y, z = 0;
			float v[3]={pl->origin[0], pl->origin[1], 0};
			gEngfuncs.Overview_WorldToScreen(v, &x, &y);

			// hack in some team colors
			float r, g, bc;
			if (g_PlayerExtraInfo[i].teamnumber == 1)
			{
				r = 0.0f; g = 0.0f; bc = 1.0f;
			}
			else if (g_PlayerExtraInfo[i].teamnumber == 2)
			{
				r = 1.0f; g = 0.0f; bc = 0.0f;
			}
			else
			{
				// just use the default orange color if the team isn't set
				r = 1.0f; g = 0.7f; bc = 0.0f;
			}

			// set the current texture
			gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer(m_hsprPlayer), 0);

			// additive render mode
			gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd);

			// no culling
			gEngfuncs.pTriAPI->CullFace(TRI_NONE);

			// draw a square
			gEngfuncs.pTriAPI->Begin(TRI_QUADS);

			// set the color to be that of the team
			gEngfuncs.pTriAPI->Color4f(r, g, bc, 1.0f);

			// calculate rotational matrix
			vec3_t a, b, angles;
			float rmatrix[3][4];	// transformation matrix
			VectorCopy(pl->angles, angles);
			angles[0] = 0.0f;
			angles[1] += 90.f;
			angles[1] = -angles[1];
			angles[2] = 0.0f;
			AngleMatrix(angles, rmatrix);
			a[2] = 0;

			a[0] = -scale; a[1] = -scale;
			VectorTransform(a, rmatrix , b );
			gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
			gEngfuncs.pTriAPI->Vertex3f(x + b[0], y + b[1], z);

			a[0]=-scale; a[1] = scale;
			VectorTransform(a, rmatrix , b );
			gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
			gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z);
			
			a[0]=scale; a[1] = scale;
			VectorTransform(a, rmatrix , b );
			gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
			gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z);

			a[0]=scale; a[1] = -scale;
			VectorTransform(a, rmatrix , b );
			gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
			gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z);

			// finish up
			gEngfuncs.pTriAPI->End();
			gEngfuncs.pTriAPI->RenderMode( kRenderNormal );

			// draw the players name and health underneath
			char string[256];
			sprintf(string, "%s (%i%%)", g_PlayerInfoList[i].name, pl->curstate.health);
			DrawConsoleString(x, y + (1.1 * scale), string);
		}
	}

#endif
	return 1;
}
コード例 #9
0
void	MeshTopoData::AlignCluster(Tab<ClusterClass*> &clusterList, int baseCluster, int moveCluster, int innerFaceIndex, int outerFaceIndex,int edgeIndex,UnwrapMod *mod)
{

	//get edges that are coincedent
	int vInner[2];
	int vOuter[2];

	int vInnerVec[2];
	int vOuterVec[2];


	int ct = 0;
	int vct = 0;
	for (int i = 0; i < TVMaps.f[innerFaceIndex]->count; i++)
	{
		int innerIndex = TVMaps.f[innerFaceIndex]->v[i];
		for (int j = 0; j < TVMaps.f[outerFaceIndex]->count; j++)
		{
			int outerIndex = TVMaps.f[outerFaceIndex]->v[j];
			if (innerIndex == outerIndex)
			{
				vInner[ct] = TVMaps.f[innerFaceIndex]->t[i];


				vOuter[ct] = TVMaps.f[outerFaceIndex]->t[j];
				ct++;
			}

		}

	}

	vInnerVec[0] = -1;
	vInnerVec[1] = -1;
	vOuterVec[0] = -1;
	vOuterVec[1] = -1;
	ct = 0;

	if ( (TVMaps.f[innerFaceIndex]->flags & FLAG_CURVEDMAPPING) && (TVMaps.f[innerFaceIndex]->vecs) &&
		(TVMaps.f[outerFaceIndex]->flags & FLAG_CURVEDMAPPING) && (TVMaps.f[outerFaceIndex]->vecs) 
		)
	{
		for (int i = 0; i < TVMaps.f[innerFaceIndex]->count*2; i++)
		{
			int innerIndex = TVMaps.f[innerFaceIndex]->vecs->vhandles[i];
			for (int j = 0; j < TVMaps.f[outerFaceIndex]->count*2; j++)
			{
				int outerIndex = TVMaps.f[outerFaceIndex]->vecs->vhandles[j];
				if (innerIndex == outerIndex)
				{
					int vec = TVMaps.f[innerFaceIndex]->vecs->handles[i];
					vInnerVec[ct] = vec;


					vec = TVMaps.f[outerFaceIndex]->vecs->handles[j];
					vOuterVec[ct] = vec;
					ct++;
				}

			}

		}
	}



	//get  align vector
	Point3 pInner[2];
	Point3 pOuter[2];

	pInner[0] = TVMaps.v[vInner[0]].GetP();
	pInner[1] = TVMaps.v[vInner[1]].GetP();

	pOuter[0] = TVMaps.v[vOuter[0]].GetP();
	pOuter[1] = TVMaps.v[vOuter[1]].GetP();

	Point3 offset = pInner[0] - pOuter[0];

	Point3 vecA, vecB;
	vecA = Normalize(pInner[1] - pInner[0]);
	vecB = Normalize(pOuter[1] - pOuter[0]);
	float dot = DotProd(vecA,vecB);

	float angle = 0.0f;
	if (dot == -1.0f)
		angle = PI;
	else if (dot >= 1.0f)
		angle = 0.f;
	else angle = acos(dot);

	if ((_isnan(angle)) || (!_finite(angle)))
		angle = 0.0f;



	Matrix3 tempMat(1);  
	tempMat.RotateZ(angle); 
	Point3 vecC = VectorTransform(tempMat,vecB);




	float negAngle = -angle;
	Matrix3 tempMat2(1); 
	tempMat2.RotateZ(negAngle); 
	Point3 vecD = VectorTransform(tempMat2,vecB);

	float la,lb;
	la = Length(vecA-vecC);
	lb = Length(vecA-vecD);
	if (la > lb)
		angle = negAngle;

	clusterList[moveCluster]->newX = offset.x;
	clusterList[moveCluster]->newY = offset.y;
	//build vert list
	//move those verts
	BitArray processVertList;
	processVertList.SetSize(TVMaps.v.Count());
	processVertList.ClearAll();
	for (int i =0; i < clusterList[moveCluster]->faces.Count(); i++)
	{
		int faceIndex = clusterList[moveCluster]->faces[i];
		for (int j =0; j < TVMaps.f[faceIndex]->count; j++)
		{
			int vertexIndex = TVMaps.f[faceIndex]->t[j];
			processVertList.Set(vertexIndex);


			if ( (patch) && (TVMaps.f[faceIndex]->flags & FLAG_CURVEDMAPPING) && (TVMaps.f[faceIndex]->vecs))
			{
				int vertIndex;

				if (TVMaps.f[faceIndex]->flags & FLAG_INTERIOR)
				{
					vertIndex = TVMaps.f[faceIndex]->vecs->interiors[j];
					if ((vertIndex >=0) && (vertIndex < processVertList.GetSize()))
						processVertList.Set(vertIndex);
				}

				vertIndex = TVMaps.f[faceIndex]->vecs->handles[j*2];
				if ((vertIndex >=0) && (vertIndex < processVertList.GetSize()))
					processVertList.Set(vertIndex);
				vertIndex = TVMaps.f[faceIndex]->vecs->handles[j*2+1];
				if ((vertIndex >=0) && (vertIndex < processVertList.GetSize()))
					processVertList.Set(vertIndex);

			}


		}
	}
	for (int i = 0; i < processVertList.GetSize(); i++)
	{
		if (processVertList[i])
		{
			Point3 p = TVMaps.v[i].GetP();
			//move to origin

			p -= pOuter[0];

			//rotate
			Matrix3 mat(1);   

			mat.RotateZ(angle); 

			p = p * mat;
			//move to anchor point        
			p += pInner[0];

			SetTVVert(0,i,p,mod);//TVMaps.v[i].p = p;
			//if (TVMaps.cont[i]) TVMaps.cont[i]->SetValue(0,&TVMaps.v[i].p);

		}
	}

	if ((vInnerVec[0] != -1) &&   (vInnerVec[1] != -1) && (vOuterVec[0] != -1) && (vOuterVec[1] != -1))
	{
		SetTVVert(0,vOuterVec[0],TVMaps.v[vInnerVec[0]].GetP(),mod);//TVMaps.v[vOuterVec[0]].p = TVMaps.v[vInnerVec[0]].p;
		//if (TVMaps.cont[vOuterVec[0]]) TVMaps.cont[vOuterVec[0]]->SetValue(0,&TVMaps.v[vInnerVec[0]].p);

		SetTVVert(0,vOuterVec[1],TVMaps.v[vInnerVec[1]].GetP(),mod);//TVMaps.v[vOuterVec[1]].p = TVMaps.v[vInnerVec[1]].p;
		//if (TVMaps.cont[vOuterVec[1]]) TVMaps.cont[vOuterVec[1]]->SetValue(0,&TVMaps.v[vInnerVec[1]].p);

	}

}
コード例 #10
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_EntityFlame::UpdateHitBoxFlames( void )
{
	C_BaseCombatCharacter *pAnimating = (C_BaseCombatCharacter *)m_hEntAttached.Get();
	if (!pAnimating)
	{
		return;
	}

	if (pAnimating->GetModel() != m_pCachedModel)
	{
		if (m_pCachedModel != NULL)
		{
			// The model changed, we must reattach the flames.
			DeleteHitBoxFlames();
			AttachToHitBoxes();
		}
		
		if (m_pCachedModel == NULL)
		{
			// We tried to reattach and failed.
			return;
		}
	}

	studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
	if (!pStudioHdr)
	{
		return;
	}

	mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->m_nHitboxSet );
	if ( !set )
	{
		return;
	}

	if ( !set->numhitboxes )
	{
		return;
	}

	int boneMask = BONE_USED_BY_HITBOX | BONE_USED_BY_ATTACHMENT;
	studiocache_t *pcache = Studio_GetBoneCache( pStudioHdr, pAnimating->GetSequence(), pAnimating->m_flAnimTime, pAnimating->GetAbsAngles(), pAnimating->GetAbsOrigin(), boneMask );
	if ( !pcache )
	{
		matrix3x4_t bonetoworld[MAXSTUDIOBONES];

		pAnimating->SetupBones( bonetoworld, MAXSTUDIOBONES, boneMask, gpGlobals->curtime );
		pcache = Studio_SetBoneCache( pStudioHdr, pAnimating->GetSequence(), pAnimating->m_flAnimTime, pAnimating->GetAbsAngles(), pAnimating->GetAbsOrigin(), boneMask, bonetoworld );
	}

	matrix3x4_t	*hitboxbones[MAXSTUDIOBONES];
	Studio_LinkHitboxCache( hitboxbones, pcache, pStudioHdr, set );

	for ( int i = 0; i < NUM_HITBOX_FIRES; i++ )
	{
		Vector vecAbsOrigin;
		VectorTransform(m_vecFireOrigin[i], *hitboxbones[m_nHitbox[i]], vecAbsOrigin);

		m_pFireSmoke[i]->SetLocalOrigin(vecAbsOrigin);
	}
}
コード例 #11
0
//-----------------------------------------------------------------------------
// Debugging methods
//-----------------------------------------------------------------------------
void CFourWheelVehiclePhysics::DrawDebugGeometryOverlays()
{
	Vector vecRad(m_debugRadius,m_debugRadius,m_debugRadius);
	for ( int i = 0; i < m_wheelCount; i++ )
	{
		NDebugOverlay::BoxAngles(m_wheelPosition[i], -vecRad, vecRad, m_wheelRotation[i], 0, 255, 45, 0 ,0);
	}

	for ( int iWheel = 0; iWheel < m_wheelCount; iWheel++ )
	{
		IPhysicsObject *pWheel = m_pVehicle->GetWheel( iWheel );
		
		Vector vecPos;
		QAngle vecRot;
		pWheel->GetPosition( &vecPos, &vecRot );

		NDebugOverlay::BoxAngles( vecPos, -vecRad, vecRad, vecRot, 0, 255, 45, 0 ,0 );
	}

#if 1
	// Render vehicle data.
	IPhysicsObject *pBody = m_pOuter->VPhysicsGetObject();
	if ( pBody )
	{
		const vehicleparams_t vehicleParams = m_pVehicle->GetVehicleParams();

		// Draw a red cube as the "center" of the vehicle.
		Vector vecBodyPosition; 
		QAngle angBodyDirection;
		pBody->GetPosition( &vecBodyPosition, &angBodyDirection );
		NDebugOverlay::BoxAngles( vecBodyPosition, Vector( -5, -5, -5 ), Vector( 5, 5, 5 ), angBodyDirection, 255, 0, 0, 0 ,0 );

		matrix3x4_t matrix;
		AngleMatrix( angBodyDirection, vecBodyPosition, matrix );

		// Draw green cubes at axle centers.
		Vector vecAxlePositions[2], vecAxlePositionsHL[2];
		vecAxlePositions[0] = vehicleParams.axles[0].offset;
		vecAxlePositions[1] = vehicleParams.axles[1].offset;

		VectorTransform( vecAxlePositions[0], matrix, vecAxlePositionsHL[0] );		
		VectorTransform( vecAxlePositions[1], matrix, vecAxlePositionsHL[1] );

		NDebugOverlay::BoxAngles( vecAxlePositionsHL[0], Vector( -3, -3, -3 ), Vector( 3, 3, 3 ), angBodyDirection, 0, 255, 0, 0 ,0 );
		NDebugOverlay::BoxAngles( vecAxlePositionsHL[1], Vector( -3, -3, -3 ), Vector( 3, 3, 3 ), angBodyDirection, 0, 255, 0, 0 ,0 );

		// Draw blue cubes at wheel centers.
		Vector vecWheelPositions[4], vecWheelPositionsHL[4];
		vecWheelPositions[0] = vehicleParams.axles[0].offset;
		vecWheelPositions[0] += vehicleParams.axles[0].wheelOffset;
		vecWheelPositions[1] = vehicleParams.axles[0].offset;
		vecWheelPositions[1] -= vehicleParams.axles[0].wheelOffset;
		vecWheelPositions[2] = vehicleParams.axles[1].offset;
		vecWheelPositions[2] += vehicleParams.axles[1].wheelOffset;
		vecWheelPositions[3] = vehicleParams.axles[1].offset;
		vecWheelPositions[3] -= vehicleParams.axles[1].wheelOffset;

		VectorTransform( vecWheelPositions[0], matrix, vecWheelPositionsHL[0] );
		VectorTransform( vecWheelPositions[1], matrix, vecWheelPositionsHL[1] );
		VectorTransform( vecWheelPositions[2], matrix, vecWheelPositionsHL[2] );
		VectorTransform( vecWheelPositions[3], matrix, vecWheelPositionsHL[3] );

		float flWheelRadius = vehicleParams.axles[0].wheels.radius;
		flWheelRadius = IVP2HL( flWheelRadius );
		Vector vecWheelRadius( flWheelRadius, flWheelRadius, flWheelRadius );

		NDebugOverlay::BoxAngles( vecWheelPositionsHL[0], -vecWheelRadius, vecWheelRadius, angBodyDirection, 0, 0, 255, 0 ,0 );
		NDebugOverlay::BoxAngles( vecWheelPositionsHL[1], -vecWheelRadius, vecWheelRadius, angBodyDirection, 0, 0, 255, 0 ,0 );
		NDebugOverlay::BoxAngles( vecWheelPositionsHL[2], -vecWheelRadius, vecWheelRadius, angBodyDirection, 0, 0, 255, 0 ,0 );
		NDebugOverlay::BoxAngles( vecWheelPositionsHL[3], -vecWheelRadius, vecWheelRadius, angBodyDirection, 0, 0, 255, 0 ,0 );

		// Draw wheel raycasts in yellow
		vehicle_debugcarsystem_t debugCarSystem;
		m_pVehicle->GetCarSystemDebugData( debugCarSystem );
		for ( int iWheel = 0; iWheel < 4; ++iWheel )
		{
			Vector vecStart, vecEnd, vecImpact;

			// Hack for now.
			float tmpY = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][0].z );
			vecStart.z = -IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][0].y );
			vecStart.y = tmpY;
			vecStart.x = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][0].x );

			tmpY = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][1].z );
			vecEnd.z = -IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][1].y );
			vecEnd.y = tmpY;
			vecEnd.x = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][1].x );

			tmpY = IVP2HL( debugCarSystem.vecWheelRaycastImpacts[iWheel].z );
			vecImpact.z = -IVP2HL( debugCarSystem.vecWheelRaycastImpacts[iWheel].y );
			vecImpact.y = tmpY;
			vecImpact.x = IVP2HL( debugCarSystem.vecWheelRaycastImpacts[iWheel].x );

			NDebugOverlay::BoxAngles( vecStart, Vector( -1 , -1, -1 ), Vector( 1, 1, 1 ), angBodyDirection, 0, 255, 0, 0, 0  );
			NDebugOverlay::Line( vecStart, vecEnd, 255, 255, 0, true, 0 );
			NDebugOverlay::BoxAngles( vecEnd, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), angBodyDirection, 255, 0, 0, 0, 0 );

			NDebugOverlay::BoxAngles( vecImpact, Vector( -0.5f , -0.5f, -0.5f ), Vector( 0.5f, 0.5f, 0.5f ), angBodyDirection, 0, 0, 255, 0, 0  );
		}
	}
#endif
}
コード例 #12
0
ファイル: BoundsTree.cpp プロジェクト: 2asoft/xray
BOOL BoundsTree::HitQuadTree(IPoint2 m, int &nindex, DWORD &findex, Point3 &p, Point3 &norm, Point3 &bary, float &finalZ, Matrix3 &toWorldTm)
{
//int nindex = 0;
Leaf *l = head;
BOOL hit = FALSE;
Point3 hitPoint(0.0f,0.0f,0.0f);
DWORD smgroup;

hitPoint.x = (float) m.x;
hitPoint.y = (float) m.y;
float z = 0.0f;
Point3 bry;
if (l == NULL) 
	{
	z = 0.0f;
	return FALSE;
	}
int ct = 0;
while ( (l!=NULL) && (l->IsBottom() == FALSE))
	{
	int id = l->InWhichQuad(hitPoint);
	l = l->GetQuad(id);
	ct++;
	}
if (l)
	{
	if (l->faceIndex.Count() == 0) 
		return FALSE;
	else
		{
		for (int i = 0; i < l->faceIndex.Count(); i++)
			{
			int faceIndex = l->faceIndex[i].faceIndex;
			int nodeIndex = l->faceIndex[i].nodeIndex;

			LightMesh *lmesh = meshList[nodeIndex];

			Point3 *tempVerts = lmesh->vertsViewSpace.Addr(0);
			Face *tempFaces = lmesh->faces.Addr(faceIndex);

			Box2D b = lmesh->boundingBoxList[faceIndex];
			if ( (hitPoint.x >= b.min.x) && (hitPoint.x <= b.max.x) &&
				 (hitPoint.y >= b.min.y) && (hitPoint.y <= b.max.y) )
				{
//now check bary coords
				Point3 a,b,c;
				a = tempVerts[tempFaces->v[0]];
				b = tempVerts[tempFaces->v[1]];
				c = tempVerts[tempFaces->v[2]];
				Point3 az,bz,cz,hitPointZ;
				az = a;
				bz = b;
				cz = c;
				az.z = 0.0f;
				bz.z = 0.0f;
				cz.z = 0.0f;
				hitPointZ = hitPoint;
				hitPointZ.z = 0.0f;
	
				Point3 bry;
				bry = BaryCoords(az, bz, cz, hitPointZ);
//if inside bary find the the z point			
				if (!( (bry.x<0.0f || bry.x>1.0f || bry.y<0.0f || bry.y>1.0f || bry.z<0.0f || bry.z>1.0f) ||
					(fabs(bry.x + bry.y + bry.z - 1.0f) > EPSILON) ))
					{
					float tz = a.z * bry.x + b.z * bry.y + c.z * bry.z; 
					if ( (tz > z ) || (hit == FALSE) )  
						{
						z = tz;
						findex = faceIndex;
						nindex = nodeIndex;
						bary = bry;
						finalZ = z;
						smgroup = tempFaces->getSmGroup();
						}
					hit = TRUE;
					}
				}
			}
		}	
	}
if (hit)
	{
	Point3 a,b,c;
	int ia,ib,ic;
	LightMesh *lmesh = meshList[nindex];
	Point3 *tempVerts = lmesh->vertsWorldSpace.Addr(0);
	Face *tempFaces = lmesh->faces.Addr(findex);

	ia = tempFaces->v[0];
	ib = tempFaces->v[1];
	ic = tempFaces->v[2];
	a = tempVerts[ia];
	b = tempVerts[ib];
	c = tempVerts[ic];

	ViewExp *vpt = GetCOREInterface()->GetActiveViewport();

	Ray worldRay;
//	vpt->GetAffineTM(tm);
	vpt->MapScreenToWorldRay((float) m.x, (float) m.y, worldRay);
	GetCOREInterface()->ReleaseViewport(vpt);

//intersect ray with the hit face

		// See if the ray intersects the plane (backfaced)
	norm = Normalize((b-a)^(c-b));

	float rn = DotProd(worldRay.dir,norm);
		
	// Use a point on the plane to find d
	float d = DotProd(a,norm);

	// Find the point on the ray that intersects the plane
	float ta = (d - DotProd(worldRay.p,norm)) / rn;


		// The point on the ray and in the plane.
	p = worldRay.p + ta*worldRay.dir;

		// Compute barycentric coords.
	bary = BaryCoords(a, b, c, p);

	finalZ  = ta;

//	p = a * bary.x +  b * bary.y +  c * bary.z;
	p = p * meshList[nindex]->toLocalSpace;

	norm = VectorTransform(meshList[nindex]->toLocalSpace,norm);
	toWorldTm = meshList[nindex]->toWorldSpace;

	


	}

return hit;

}
コード例 #13
0
void PropBreakableCreateAll( int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t &params, CBaseEntity *pEntity, int iPrecomputedBreakableCount, bool bIgnoreGibLimit, bool defaultLocation )
{
        // Check for prop breakable count reset. 
	int nPropCount = props_break_max_pieces_perframe.GetInt(); 
	if ( nPropCount != -1 ) 
	{ 
		if ( nFrameNumber != gpGlobals->framecount ) 
		{ 
			nPropBreakablesPerFrameCount = 0; 
			nFrameNumber = gpGlobals->framecount; 
		} 
      
		// Check for max breakable count for the frame. 
		if ( nPropBreakablesPerFrameCount >= nPropCount ) 
			return; 
	} 
      
	int iMaxBreakCount = bIgnoreGibLimit ? -1 : props_break_max_pieces.GetInt();
	if ( iMaxBreakCount != -1 )
	{
		if ( iPrecomputedBreakableCount != -1 )
		{
			iPrecomputedBreakableCount = MIN( iMaxBreakCount, iPrecomputedBreakableCount );
		}
		else
		{
			iPrecomputedBreakableCount = iMaxBreakCount;
		}
	}

#ifdef GAME_DLL
	// On server limit break model creation
	if ( !PropBreakableCapEdictsOnCreateAll(modelindex, pPhysics, params, pEntity, iPrecomputedBreakableCount ) )
	{
		DevMsg( "Failed to create PropBreakable: would exceed MAX_EDICTS\n" );
		return;
	}
#endif
	
	vcollide_t *pCollide = modelinfo->GetVCollide( modelindex );
	if ( !pCollide )
		return;

	int nSkin = 0;
	CBaseEntity *pOwnerEntity = pEntity;
	CBaseAnimating *pOwnerAnim = NULL;
	if ( pPhysics )
	{
		pOwnerEntity = static_cast<CBaseEntity *>(pPhysics->GetGameData());
	}
	if ( pOwnerEntity )
	{
		pOwnerAnim = pOwnerEntity->GetBaseAnimating();
		if ( pOwnerAnim )
		{
			nSkin = pOwnerAnim->m_nSkin;
		}
	}
	matrix3x4_t localToWorld;

	CStudioHdr studioHdr;
	const model_t *model = modelinfo->GetModel( modelindex );
	if ( model )
	{
		studioHdr.Init( modelinfo->GetStudiomodel( model ) );
	}

	Vector parentOrigin = vec3_origin;
	int parentAttachment = 	Studio_FindAttachment( &studioHdr, "placementOrigin" ) + 1;
	if ( parentAttachment > 0 )
	{
		GetAttachmentLocalSpace( &studioHdr, parentAttachment-1, localToWorld );
		MatrixGetColumn( localToWorld, 3, parentOrigin );
	}
	else
	{
		AngleMatrix( vec3_angle, localToWorld );
	}
	
	CUtlVector<breakmodel_t> list;
	BreakModelList( list, modelindex, params.defBurstScale, params.defCollisionGroup );

	CUtlVector< CBaseEntity* > spawnedGibs;

	if ( list.Count() )
	{
		for ( int i = 0; i < list.Count(); i++ )
		{
			int modelIndex = modelinfo->GetModelIndex( list[i].modelName );
			if ( modelIndex <= 0 )
				continue;

			// Skip multiplayer pieces that should be spawning on the other dll
#ifdef GAME_DLL
			if ( gpGlobals->maxClients > 1 && breakable_multiplayer.GetBool() )
#else
			if ( gpGlobals->maxClients > 1 )
#endif
			{
#ifdef GAME_DLL
				if ( list[i].mpBreakMode == MULTIPLAYER_BREAK_CLIENTSIDE )
					continue;
#else
				if ( list[i].mpBreakMode == MULTIPLAYER_BREAK_SERVERSIDE )
					continue;
#endif

				if ( !defaultLocation && list[i].mpBreakMode == MULTIPLAYER_BREAK_DEFAULT )
					continue;
			}

			if ( ( nPropCount != -1 ) && ( nPropBreakablesPerFrameCount > nPropCount ) )
				break;

			if ( ( iPrecomputedBreakableCount != -1 ) && ( i >= iPrecomputedBreakableCount ) )
				break;

			matrix3x4_t matrix;
			AngleMatrix( params.angles, params.origin, matrix );

			CStudioHdr studioHdr;
			const model_t *model = modelinfo->GetModel( modelIndex );
			if ( model )
			{
				studioHdr.Init( modelinfo->GetStudiomodel( model ) );
			}

			// Increment the number of breakable props this frame.
			++nPropBreakablesPerFrameCount;

			const float flModelScale = pOwnerAnim->GetModelScale();
			Vector position = vec3_origin;
			QAngle angles = params.angles;
			if ( pOwnerAnim && list[i].placementName[0] )
			{
				if ( list[i].placementIsBone )
				{
					int boneIndex = pOwnerAnim->LookupBone( list[i].placementName );
					if ( boneIndex >= 0 )
					{
						pOwnerAnim->GetBonePosition( boneIndex, position, angles );
						AngleMatrix( angles, position, matrix );
					}
				}
				else
				{
					int attachmentIndex = Studio_FindAttachment( &studioHdr, list[i].placementName ) + 1;
					if ( attachmentIndex > 0 )
					{
						pOwnerAnim->GetAttachment( attachmentIndex, matrix );
						MatrixAngles( matrix, angles );
					}
				}
			}
			else
			{
				int placementIndex = Studio_FindAttachment( &studioHdr, "placementOrigin" ) + 1;
				Vector placementOrigin = parentOrigin;
				if ( placementIndex > 0 )
				{
					GetAttachmentLocalSpace( &studioHdr, placementIndex-1, localToWorld );
					MatrixGetColumn( localToWorld, 3, placementOrigin );
					placementOrigin -= parentOrigin;
				}

				VectorTransform( list[i].offset - placementOrigin * flModelScale,
					matrix, position );
			}
			Vector objectVelocity = params.velocity;

			if (pPhysics)
			{
				pPhysics->GetVelocityAtPoint( position, &objectVelocity );
			}

			int nActualSkin = nSkin;
			if ( nActualSkin > studioHdr.numskinfamilies() )
				nActualSkin = 0;

			CBaseEntity *pBreakable = NULL;
			
#ifdef GAME_DLL
			if ( GetGibManager() == NULL || GetGibManager()->AllowedToSpawnGib() )
#endif
			{
				pBreakable = BreakModelCreateSingle( pOwnerEntity, &list[i], position, angles, objectVelocity, params.angularVelocity, nActualSkin, params );
			}

			if ( pBreakable )
			{
				spawnedGibs.AddToTail( pBreakable );

#ifdef GAME_DLL
				if ( GetGibManager() )
				{
					GetGibManager()->AddGibToLRU( pBreakable->GetBaseAnimating() );
				}
#endif
				if ( pOwnerEntity && pOwnerEntity->IsEffectActive( EF_NOSHADOW ) )
				{
					pBreakable->AddEffects( EF_NOSHADOW );
				}

				// If burst scale is set, this piece should 'burst' away from
				// the origin in addition to travelling in the wished velocity.
				if ( list[i].burstScale != 0.0 )
				{
					Vector vecBurstDir = position - params.origin;

					// If $autocenter wasn't used, try the center of the piece
					if ( vecBurstDir == vec3_origin )
					{
						vecBurstDir = pBreakable->WorldSpaceCenter() - params.origin;
					}

					VectorNormalize( vecBurstDir );

					pBreakable->ApplyAbsVelocityImpulse( vecBurstDir * list[i].burstScale * flModelScale *
						params.velocityScale * params.burstScale );
				}

				if ( params.randomAngularVelocity > 0.0f )
				{
					AngularImpulse angRandomImpulse = RandomAngularImpulse( -params.randomAngularVelocity, params.randomAngularVelocity );
					pBreakable->ApplyLocalAngularVelocityImpulse( angRandomImpulse * params.velocityScale );
				}

				// If this piece is supposed to be motion disabled, disable it
				if ( list[i].isMotionDisabled )
				{
					IPhysicsObject *pPhysicsObject = pBreakable->VPhysicsGetObject();
					if ( pPhysicsObject != NULL )
					{
						pPhysicsObject->EnableMotion( false );
					}
				}
			}
		}
	}
	// Then see if the propdata specifies any breakable pieces
	else if ( pEntity )
	{
		IBreakableWithPropData *pBreakableInterface = dynamic_cast<IBreakableWithPropData*>(pEntity);
		if ( pBreakableInterface && pBreakableInterface->GetBreakableModel() != NULL_STRING && pBreakableInterface->GetBreakableCount() )
		{
			breakmodel_t breakModel;

			for ( int i = 0; i < pBreakableInterface->GetBreakableCount(); i++ )
			{
				if ( ( iPrecomputedBreakableCount != -1 ) && ( i >= iPrecomputedBreakableCount ) )
					break;

				Q_strncpy( breakModel.modelName, g_PropDataSystem.GetRandomChunkModel(STRING(pBreakableInterface->GetBreakableModel()), pBreakableInterface->GetMaxBreakableSize()), sizeof(breakModel.modelName) );

				breakModel.health = 1;
				breakModel.fadeTime = RandomFloat(5,10);
				breakModel.fadeMinDist = 0.0f;
				breakModel.fadeMaxDist = 0.0f;
				breakModel.burstScale = params.defBurstScale;
				breakModel.collisionGroup = COLLISION_GROUP_DEBRIS;
				breakModel.isRagdoll = false;
				breakModel.isMotionDisabled = false;
				breakModel.placementName[0] = 0;
				breakModel.placementIsBone = false;

				Vector vecObbSize = pEntity->CollisionProp()->OBBSize();

				// Find a random point on the plane of the original's two largest axis
				int smallestAxis = SmallestAxis( vecObbSize );
				Vector vecMins(0,0,0);
				Vector vecMaxs(1,1,1);
				vecMins[smallestAxis] = 0.5;
				vecMaxs[smallestAxis] = 0.5;
				pEntity->CollisionProp()->RandomPointInBounds( vecMins, vecMaxs, &breakModel.offset );

				// Push all chunks away from the center
				Vector vecBurstDir = breakModel.offset - params.origin;
				VectorNormalize( vecBurstDir );
				Vector vecVelocity = vecBurstDir * params.defBurstScale;

				QAngle vecAngles = pEntity->GetAbsAngles();
				int iSkin = pBreakableInterface->GetBreakableSkin();

				CBaseEntity *pBreakable = NULL;

#ifdef GAME_DLL
				if ( GetGibManager() == NULL || GetGibManager()->AllowedToSpawnGib() )
#endif
				{
					pBreakable = BreakModelCreateSingle( pOwnerEntity, &breakModel, breakModel.offset, vecAngles, vecVelocity, vec3_origin/*params.angularVelocity*/, iSkin, params );
					if ( !pBreakable )
					{
						DevWarning( "PropBreakableCreateAll: Could not create model %s\n", breakModel.modelName );
					}
				}

				if ( pBreakable )
				{
#ifdef GAME_DLL
					if ( GetGibManager() )
					{
						GetGibManager()->AddGibToLRU( pBreakable->GetBaseAnimating() );
					}
#endif
					Vector vecBreakableObbSize = pBreakable->CollisionProp()->OBBSize();

					// Try to align the gibs along the original axis 
					matrix3x4_t matrix;
					AngleMatrix( vecAngles, matrix );
					AlignBoxes( &matrix, vecObbSize, vecBreakableObbSize );
					MatrixAngles( matrix, vecAngles );

					if ( pBreakable->VPhysicsGetObject() )
					{
						Vector pos;
						pBreakable->VPhysicsGetObject()->GetPosition( &pos, NULL );
						pBreakable->VPhysicsGetObject()->SetPosition( pos, vecAngles, true );
					}

					pBreakable->SetAbsAngles( vecAngles );

					if ( pOwnerEntity->IsEffectActive( EF_NOSHADOW ) )
					{
						pBreakable->AddEffects( EF_NOSHADOW );
					}
				}
			}
		}
	}

	if ( params.connectingParticleNames.Count() > 0 && spawnedGibs.Count() > 1 )
	{
		const int iGibCount = spawnedGibs.Count();
		int iParticlesLeft = iGibCount / 2;
		int iEntIndex0 = RandomInt( 0, iGibCount - 1 );
		while ( iParticlesLeft > 0 )
		{
			iParticlesLeft--;
			const int iEntIndex1 = ( iEntIndex0 + RandomInt( 1, iGibCount - 1 ) ) % iGibCount;
			CBaseEntity *pEnt0 = spawnedGibs[ iEntIndex0 ];
			CBaseEntity *pEnt1 = spawnedGibs[ iEntIndex1 ];

			const int iParticleSystemIndex = RandomInt( 0, params.connectingParticleNames.Count() - 1 );
			DispatchParticleEffect( params.connectingParticleNames[ iParticleSystemIndex ], pEnt0, pEnt1 );
			iEntIndex0 = ( iEntIndex0 + RandomInt( 1, iGibCount - 1 ) ) % iGibCount;
		}
	}
}
コード例 #14
0
ファイル: smdlexp.cpp プロジェクト: DeadlyGamer/cs16nd
//=================================================================
// Methods for DumpModelTEP
//
int DumpModelTEP::callback(INode *pnode)
{
	Object*	pobj;
	int	fHasMat = TRUE;

	// clear physique export parameters
	m_mcExport = NULL;
	m_phyExport = NULL;
    m_phyMod = NULL;

	ASSERT_MBOX(!(pnode)->IsRootNode(), "Encountered a root node!");

	if (::FNodeMarkedToSkip(pnode))
		return TREE_CONTINUE;
	
	int iNode = ::GetIndexOfINode(pnode);
	TSTR strNodeName(pnode->GetName());
	
	// The Footsteps node apparently MUST have a dummy mesh attached!  Ignore it explicitly.
	if (FStrEq((char*)strNodeName, "Bip01 Footsteps"))
		return TREE_CONTINUE;

	// Helper nodes don't have meshes
	pobj = pnode->GetObjectRef();
	if (pobj->SuperClassID() == HELPER_CLASS_ID)
		return TREE_CONTINUE;

	// The model's root is a child of the real "scene root"
	INode *pnodeParent = pnode->GetParentNode();
	BOOL fNodeIsRoot = pnodeParent->IsRootNode( );

	// Get node's material: should be a multi/sub (if it has a material at all)
	Mtl *pmtlNode = pnode->GetMtl();
	if (pmtlNode == NULL)
	{
		return TREE_CONTINUE;
		fHasMat = FALSE;
	}
	else if (!(pmtlNode->ClassID() == Class_ID(MULTI_CLASS_ID, 0) && pmtlNode->IsMultiMtl()))
	{
		// sprintf(st_szDBG, "ERROR--Material on node %s isn't a Multi/Sub-Object", (char*)strNodeName);
		// ASSERT_AND_ABORT(FALSE, st_szDBG);
		fHasMat = FALSE;
	}
	
	// Get Node's object, convert to a triangle-mesh object, so I can access the Faces
	ObjectState os = pnode->EvalWorldState(m_tvToDump);
	pobj = os.obj;
	TriObject *ptriobj;
	BOOL fConvertedToTriObject = 
		pobj->CanConvertToType(triObjectClassID) &&
		(ptriobj = (TriObject*)pobj->ConvertToType(m_tvToDump, triObjectClassID)) != NULL;
	if (!fConvertedToTriObject)
		return TREE_CONTINUE;
	Mesh *pmesh = &ptriobj->mesh;

	// Shouldn't have gotten this far if it's a helper object
	if (pobj->SuperClassID() == HELPER_CLASS_ID)
	{
		sprintf(st_szDBG, "ERROR--Helper node %s has an attached mesh, and it shouldn't.", (char*)strNodeName);
		ASSERT_AND_ABORT(FALSE, st_szDBG);
	}

	// Ensure that the vertex normals are up-to-date
	pmesh->buildNormals();

	// We want the vertex coordinates in World-space, not object-space
	Matrix3 mat3ObjectTM = pnode->GetObjectTM(m_tvToDump);


	// initialize physique export parameters
    m_phyMod = FindPhysiqueModifier(pnode);
    if (m_phyMod)
	{
		// Physique Modifier exists for given Node
	    m_phyExport = (IPhysiqueExport *)m_phyMod->GetInterface(I_PHYINTERFACE);

        if (m_phyExport)
        {
            // create a ModContext Export Interface for the specific node of the Physique Modifier
           m_mcExport = (IPhyContextExport *)m_phyExport->GetContextInterface(pnode);

		   if (m_mcExport)
		   {
		       // convert all vertices to Rigid 
                m_mcExport->ConvertToRigid(TRUE);
		   }
		}
	}

	// Dump the triangle face info
	int cFaces = pmesh->getNumFaces();
	for (int iFace = 0; iFace < cFaces; iFace++)
	{
		Face*	pface		= &pmesh->faces[iFace];
		TVFace*	ptvface		= &pmesh->tvFace[iFace];
		DWORD	smGroupFace	= pface->getSmGroup();

		// Get face's 3 indexes into the Mesh's vertex array(s).
		DWORD iVertex0 = pface->getVert(0);
		DWORD iVertex1 = pface->getVert(1);
		DWORD iVertex2 = pface->getVert(2);
		ASSERT_AND_ABORT((int)iVertex0 < pmesh->getNumVerts(), "Bogus Vertex 0 index");
		ASSERT_AND_ABORT((int)iVertex1 < pmesh->getNumVerts(), "Bogus Vertex 1 index");
		ASSERT_AND_ABORT((int)iVertex2 < pmesh->getNumVerts(), "Bogus Vertex 2 index");
		
		// Get the 3 Vertex's for this face
		Point3 pt3Vertex0 = pmesh->getVert(iVertex0);
		Point3 pt3Vertex1 = pmesh->getVert(iVertex1);
		Point3 pt3Vertex2 = pmesh->getVert(iVertex2);

		// Get the 3 RVertex's for this face
		// NOTE: I'm using getRVertPtr instead of getRVert to work around a 3DSMax bug
		RVertex *prvertex0 = pmesh->getRVertPtr(iVertex0);
		RVertex *prvertex1 = pmesh->getRVertPtr(iVertex1);
		RVertex *prvertex2 = pmesh->getRVertPtr(iVertex2);
		
		// Find appropriate normals for each RVertex
		// A vertex can be part of multiple faces, so the "smoothing group"
		// is used to locate the normal for this face's use of the vertex.
		Point3 pt3Vertex0Normal;
		Point3 pt3Vertex1Normal;
		Point3 pt3Vertex2Normal;
		if (smGroupFace) 
		{
			pt3Vertex0Normal = Pt3GetRVertexNormal(prvertex0, smGroupFace);
			pt3Vertex1Normal = Pt3GetRVertexNormal(prvertex1, smGroupFace);
			pt3Vertex2Normal = Pt3GetRVertexNormal(prvertex2, smGroupFace);
		}
		else 
		{
			pt3Vertex0Normal = pmesh->getFaceNormal( iFace );
			pt3Vertex1Normal = pmesh->getFaceNormal( iFace );
			pt3Vertex2Normal = pmesh->getFaceNormal( iFace );
		}
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus orig normal 0" );
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus orig normal 1" );
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus orig normal 2" );
	
		// Get Face's sub-material from node's material, to get the bitmap name.
		// And no, there isn't a simpler way to get the bitmap name, you have to
		// dig down through all these levels.
		TCHAR szBitmapName[256] = "null.bmp";
		if (fHasMat)
		{
			MtlID mtlidFace = pface->getMatID();
			if (mtlidFace >= pmtlNode->NumSubMtls())
			{
				sprintf(st_szDBG, "ERROR--Bogus sub-material index %d in node %s; highest valid index is %d",
					mtlidFace, (char*)strNodeName, pmtlNode->NumSubMtls()-1);
				// ASSERT_AND_ABORT(FALSE, st_szDBG);
				mtlidFace = 0;
			}
			Mtl *pmtlFace = pmtlNode->GetSubMtl(mtlidFace);
			ASSERT_AND_ABORT(pmtlFace != NULL, "NULL Sub-material returned");
 
			if ((pmtlFace->ClassID() == Class_ID(MULTI_CLASS_ID, 0) && pmtlFace->IsMultiMtl()))
			{
				// it's a sub-sub material.  Gads.
				pmtlFace = pmtlFace->GetSubMtl(mtlidFace);			
				ASSERT_AND_ABORT(pmtlFace != NULL, "NULL Sub-material returned");
			}

			if (!(pmtlFace->ClassID() == Class_ID(DMTL_CLASS_ID, 0)))
			{

				sprintf(st_szDBG,
					"ERROR--Sub-material with index %d (used in node %s) isn't a 'default/standard' material [%x].",
					mtlidFace, (char*)strNodeName, pmtlFace->ClassID());
				ASSERT_AND_ABORT(FALSE, st_szDBG);
			}
			StdMat *pstdmtlFace = (StdMat*)pmtlFace;
			Texmap *ptexmap = pstdmtlFace->GetSubTexmap(ID_DI);
			// ASSERT_AND_ABORT(ptexmap != NULL, "NULL diffuse texture")
			if (ptexmap != NULL) 
			{
				if (!(ptexmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)))
				{
					sprintf(st_szDBG,
						"ERROR--Sub-material with index %d (used in node %s) doesn't have a bitmap as its diffuse texture.",
						mtlidFace, (char*)strNodeName);
					ASSERT_AND_ABORT(FALSE, st_szDBG);
				}
				BitmapTex *pbmptex = (BitmapTex*)ptexmap;
				strcpy(szBitmapName, pbmptex->GetMapName());
				TSTR strPath, strFile;
				SplitPathFile(TSTR(szBitmapName), &strPath, &strFile);
				strcpy(szBitmapName,strFile);
			}
		}

		UVVert UVvertex0( 0, 0, 0 );
		UVVert UVvertex1( 1, 0, 0 );
		UVVert UVvertex2( 0, 1, 0 );
		
		// All faces must have textures assigned to them
		if (pface->flags & HAS_TVERTS)
		{
			// Get TVface's 3 indexes into the Mesh's TVertex array(s).
			DWORD iTVertex0 = ptvface->getTVert(0);
			DWORD iTVertex1 = ptvface->getTVert(1);
			DWORD iTVertex2 = ptvface->getTVert(2);
			ASSERT_AND_ABORT((int)iTVertex0 < pmesh->getNumTVerts(), "Bogus TVertex 0 index");
			ASSERT_AND_ABORT((int)iTVertex1 < pmesh->getNumTVerts(), "Bogus TVertex 1 index");
			ASSERT_AND_ABORT((int)iTVertex2 < pmesh->getNumTVerts(), "Bogus TVertex 2 index");

			// Get the 3 TVertex's for this TVFace
			// NOTE: I'm using getRVertPtr instead of getRVert to work around a 3DSMax bug
			UVvertex0 = pmesh->getTVert(iTVertex0);
			UVvertex1 = pmesh->getTVert(iTVertex1);
			UVvertex2 = pmesh->getTVert(iTVertex2);
		}
		else 
		{
			//sprintf(st_szDBG, "ERROR--Node %s has a textureless face.  All faces must have an applied texture.", (char*)strNodeName);
			//ASSERT_AND_ABORT(FALSE, st_szDBG);
		}
		
		/*
		const char *szExpectedExtension = ".bmp";
		if (stricmp(szBitmapName+strlen(szBitmapName)-strlen(szExpectedExtension), szExpectedExtension) != 0)
			{
			sprintf(st_szDBG, "Node %s uses %s, which is not a %s file", (char*)strNodeName, szBitmapName, szExpectedExtension);
			ASSERT_AND_ABORT(FALSE, st_szDBG);
			}
		*/

		// Determine owning bones for the vertices.
		int iNodeV0, iNodeV1, iNodeV2;
		if (m_mcExport)
		{
			// The Physique add-in allows vertices to be assigned to bones arbitrarily
			iNodeV0 = InodeOfPhyVectex( iVertex0 );
			iNodeV1 = InodeOfPhyVectex( iVertex1 );
			iNodeV2 = InodeOfPhyVectex( iVertex2 );
		}
		else
		{
			// Simple 3dsMax model: the vertices are owned by the object, and hence the node
			iNodeV0 = iNode;
			iNodeV1 = iNode;
			iNodeV2 = iNode;
		}
		
		// Rotate the face vertices out of object-space, and into world-space space
		Point3 v0 = pt3Vertex0 * mat3ObjectTM;
		Point3 v1 = pt3Vertex1 * mat3ObjectTM;
		Point3 v2 = pt3Vertex2 * mat3ObjectTM;


		Matrix3 mat3ObjectNTM = mat3ObjectTM;
		mat3ObjectNTM.NoScale( );
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus pre normal 0" );
		pt3Vertex0Normal = VectorTransform(mat3ObjectNTM, pt3Vertex0Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus post normal 0" );
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus pre normal 1" );
		pt3Vertex1Normal = VectorTransform(mat3ObjectNTM, pt3Vertex1Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus post normal 1" );
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus pre normal 2" );
		pt3Vertex2Normal = VectorTransform(mat3ObjectNTM, pt3Vertex2Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus post normal 2" );

		// Finally dump the bitmap name and 3 lines of face info
		fprintf(m_pfile, "%s\n", szBitmapName);
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
				iNodeV0, v0.x, v0.y, v0.z,
				pt3Vertex0Normal.x, pt3Vertex0Normal.y, pt3Vertex0Normal.z,
				UVvertex0.x, UVvertex0.y);
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
				iNodeV1, v1.x, v1.y, v1.z,
				pt3Vertex1Normal.x, pt3Vertex1Normal.y, pt3Vertex1Normal.z,
				UVvertex1.x, UVvertex1.y);
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
				iNodeV2, v2.x, v2.y, v2.z,
				pt3Vertex2Normal.x, pt3Vertex2Normal.y, pt3Vertex2Normal.z,
				UVvertex2.x, UVvertex2.y);
	}

	cleanup( );	
	return TREE_CONTINUE;
}
コード例 #15
0
void CPhysicsObject::LocalToWorld(Vector* worldPosition, const Vector& localPosition) const {
	matrix3x4_t matrix;
	GetPositionMatrix(&matrix);
	VectorTransform(Vector(localPosition), matrix, *worldPosition);
}
コード例 #16
0
//-----------------------------------------------------------------------------
// Compute the bounding box's center, size, and basis
//-----------------------------------------------------------------------------
void ComputeRenderInfo( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, 
										 Vector *pVecAbsOrigin, Vector *pXVec, Vector *pYVec )
{
	// Compute the center of the hitbox in worldspace
	Vector vecHitboxCenter;
	VectorAdd( pHitBox->bbmin, pHitBox->bbmax, vecHitboxCenter );
	vecHitboxCenter *= 0.5f;
	VectorTransform( vecHitboxCenter, hitboxToWorld, *pVecAbsOrigin );

	// Get the object's basis
	Vector vec[3];
	MatrixGetColumn( hitboxToWorld, 0, vec[0] );
	MatrixGetColumn( hitboxToWorld, 1, vec[1] );
	MatrixGetColumn( hitboxToWorld, 2, vec[2] );
//	vec[1] *= -1.0f;

	Vector vecViewDir;
	VectorSubtract( CurrentViewOrigin(), *pVecAbsOrigin, vecViewDir );
	VectorNormalize( vecViewDir );

	// Project the shadow casting direction into the space of the hitbox
	Vector localViewDir;
	localViewDir[0] = DotProduct( vec[0], vecViewDir );
	localViewDir[1] = DotProduct( vec[1], vecViewDir );
	localViewDir[2] = DotProduct( vec[2], vecViewDir );

	// Figure out which vector has the largest component perpendicular
	// to the view direction...
	// Sort by how perpendicular it is
	int vecIdx[3];
	SortAbsVectorComponents( localViewDir, vecIdx );

	// Here's our hitbox basis vectors; namely the ones that are
	// most perpendicular to the view direction
	*pXVec = vec[vecIdx[0]];
	*pYVec = vec[vecIdx[1]];

	// Project them into a plane perpendicular to the view direction
	*pXVec -= vecViewDir * DotProduct( vecViewDir, *pXVec );
	*pYVec -= vecViewDir * DotProduct( vecViewDir, *pYVec );
	VectorNormalize( *pXVec );
	VectorNormalize( *pYVec );

	// Compute the hitbox size
	Vector boxSize;
	VectorSubtract( pHitBox->bbmax, pHitBox->bbmin, boxSize );

	// We project the two longest sides into the vectors perpendicular
	// to the projection direction, then add in the projection of the perp direction
	Vector2D size( boxSize[vecIdx[0]], boxSize[vecIdx[1]] );
	size.x *= fabs( DotProduct( vec[vecIdx[0]], *pXVec ) );
	size.y *= fabs( DotProduct( vec[vecIdx[1]], *pYVec ) );

	// Add the third component into x and y
	size.x += boxSize[vecIdx[2]] * fabs( DotProduct( vec[vecIdx[2]], *pXVec ) );
	size.y += boxSize[vecIdx[2]] * fabs( DotProduct( vec[vecIdx[2]], *pYVec ) );

	// Bloat a bit, since the shadow wants to extend outside the model a bit
	size *= 2.0f;

	// Clamp the minimum size
	Vector2DMax( size, Vector2D(10.0f, 10.0f), size );

	// Factor the size into the xvec + yvec
	(*pXVec) *= size.x * 0.5f;
	(*pYVec) *= size.y * 0.5f;
}
コード例 #17
0
void CRagdollProp::InitRagdoll( const Vector &forceVector, int forceBone, const Vector &forcePos, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll )
{
	SetCollisionGroup( collisionGroup );

	// Make sure it's interactive debris for at most 5 seconds
	if ( collisionGroup == COLLISION_GROUP_INTERACTIVE_DEBRIS )
	{
		SetContextThink( &CRagdollProp::SetDebrisThink, gpGlobals->curtime + 5, s_pDebrisContext );
	}

	SetMoveType( MOVETYPE_VPHYSICS );
	SetSolid( SOLID_VPHYSICS );
	AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST );
	m_takedamage = DAMAGE_EVENTS_ONLY;

	ragdollparams_t params;
	params.pGameData = static_cast<void *>( static_cast<CBaseEntity *>(this) );
	params.modelIndex = GetModelIndex();
	params.pCollide = modelinfo->GetVCollide( params.modelIndex );
	params.pStudioHdr = GetModelPtr();
	params.forceVector = forceVector;
	params.forceBoneIndex = forceBone;
	params.forcePosition = forcePos;
	params.pPrevBones = pPrevBones;
	params.pCurrentBones = pBoneToWorld;
	params.boneDt = dt;
	params.jointFrictionScale = 1.0;
	RagdollCreate( m_ragdoll, params, physenv );
	if ( m_anglesOverrideString != NULL_STRING && Q_strlen(m_anglesOverrideString.ToCStr()) > 0 )
	{
		char szToken[2048];
		const char *pStr = nexttoken(szToken, STRING(m_anglesOverrideString), ',');
		// anglesOverride is index,angles,index,angles (e.g. "1, 22.5 123.0 0.0, 2, 0 0 0, 3, 0 0 180.0")
		while ( szToken[0] != 0 )
		{
			int objectIndex = atoi(szToken);
			// sanity check to make sure this token is an integer
			Assert( atof(szToken) == ((float)objectIndex) );
			pStr = nexttoken(szToken, pStr, ',');
			Assert( szToken[0] );
			if ( objectIndex >= m_ragdoll.listCount )
			{
				Warning("Bad ragdoll pose in entity %s, model (%s) at %s, model changed?\n", GetDebugName(), GetModelName().ToCStr(), VecToString(GetAbsOrigin()) );
			}
			else if ( szToken[0] != 0 )
			{
				QAngle angles;
				Assert( objectIndex >= 0 && objectIndex < RAGDOLL_MAX_ELEMENTS );
				UTIL_StringToVector( angles.Base(), szToken );
				int boneIndex = m_ragdoll.boneIndex[objectIndex];
				AngleMatrix( angles, pBoneToWorld[boneIndex] );
				const ragdollelement_t &element = m_ragdoll.list[objectIndex];
				Vector out;
				if ( element.parentIndex >= 0 )
				{
					int parentBoneIndex = m_ragdoll.boneIndex[element.parentIndex];
					VectorTransform( element.originParentSpace, pBoneToWorld[parentBoneIndex], out );
				}
				else
				{
					out = GetAbsOrigin();
				}
				MatrixSetColumn( out, 3, pBoneToWorld[boneIndex] );
				element.pObject->SetPositionMatrix( pBoneToWorld[boneIndex], true );
			}
			pStr = nexttoken(szToken, pStr, ',');
		}
	}

	if ( activateRagdoll )
	{
		MEM_ALLOC_CREDIT();
		RagdollActivate( m_ragdoll, params.pCollide, GetModelIndex() );
	}

	for ( int i = 0; i < m_ragdoll.listCount; i++ )
	{
		UpdateNetworkDataFromVPhysics( m_ragdoll.list[i].pObject, i );
		g_pPhysSaveRestoreManager->AssociateModel( m_ragdoll.list[i].pObject, GetModelIndex() );
		physcollision->CollideGetAABB( m_ragdollMins[i], m_ragdollMaxs[i], m_ragdoll.list[i].pObject->GetCollide(), vec3_origin, vec3_angle );
	}
	VPhysicsSetObject( m_ragdoll.list[0].pObject );

	CalcRagdollSize();
}
コード例 #18
0
ファイル: evalcol.cpp プロジェクト: artemeliy/inf4715
// Returns the derivative of PObj(), relative to the pixel.
// TBD
Point3 SContext::DPObj(void)
{
	Point3 d = DP();
	return VectorTransform(Inverse(tmAfterWSM),d);
}
コード例 #19
0
ファイル: sv_hitboxes.cpp プロジェクト: ripieces/advancedfx
void FetchHitboxes(struct server_studio_api_s *pstudio,
	float (*bonetransform)[MAXSTUDIOBONES][3][4],
	struct model_s *pModel, float frame, int sequence, const vec3_t angles,
	const vec3_t origin, const byte *pcontroller, const byte *pblending, 
	int iBone, const edict_t *pEdict)
{
	/*pEngfuncs->Con_Printf(
		"FetchHitboxes(0x%08x): 0x%08x,0x%08x,0x%08x,%f,%i,(%f,%f,%f),(%f,%f,%f),0x%08x,0x%08x,%i,0x%08x --> %i\n",
		&FetchHitboxes,
		pstudio, bonetransform, pModel,
		frame, sequence,
		angles[0],angles[1],angles[2],
		origin[0],origin[1],origin[2],
		pcontroller, pblending,
		iBone, pEdict,
		g_engfuncs.pfnIndexOfEdict(pEdict)
	);*/

	if(!draw_sv_hitboxes_enable->value) return;

	studiohdr_t *pstudiohdr = (studiohdr_t *)pstudio->Mod_Extradata(pModel);

	if(!pstudiohdr)
	{
		pEngfuncs->Con_Printf("Error: no model for pEdict (serialnumber=%i)\n",pEdict->serialnumber);
		return;
	}

	mstudiobbox_t *pbbox;
	vec3_t tmp;
	temp_box_t p;
	int i,j;

	pbbox = (mstudiobbox_t *)((byte *)pstudiohdr+ pstudiohdr->hitboxindex);

	temp_edictboxes_t & tempEdict = tempEdicts[g_engfuncs.pfnIndexOfEdict(pEdict)];
	tempEdict.isFresh = true;
	tempEdict.tempBoxes.clear();

	for (i = 0; i < pstudiohdr->numhitboxes; i++)
	{
		/*
		pEngfuncs->Con_Printf("((%f, %f, %f),(%f, %f, %f))\n",
			pbbox[i].bbmin[0], pbbox[i].bbmin[1], pbbox[i].bbmin[2],
			pbbox[i].bbmax[0], pbbox[i].bbmax[1], pbbox[i].bbmax[2]
		);
		*/

		//get the vector positions of the 8 corners of the bounding box
		for (j = 0; j < 8; j++)
		{
			tmp[0] = (j & 1) ? pbbox[i].bbmin[0] : pbbox[i].bbmax[0];
			tmp[1] = (j & 2) ? pbbox[i].bbmin[1] : pbbox[i].bbmax[1];
			tmp[2] = (j & 4) ? pbbox[i].bbmin[2] : pbbox[i].bbmax[2];

			VectorTransform( tmp, (*bonetransform)[pbbox[i].bone], p.data[j] );
		}

		tempEdict.tempBoxes.push_back(p);
	}
}
コード例 #20
0
//-----------------------------------------------------------------------------
// This is called by the base object when it's time to spawn the control panels
//-----------------------------------------------------------------------------
void CBaseViewModel::SpawnControlPanels()
{
#if defined( VGUI_CONTROL_PANELS )
	char buf[64];

	// Destroy existing panels
	DestroyControlPanels();

	CBaseCombatWeapon *weapon = m_hWeapon.Get();

	if ( weapon == NULL )
	{
		return;
	}

	MDLCACHE_CRITICAL_SECTION();

	// FIXME: Deal with dynamically resizing control panels?

	// If we're attached to an entity, spawn control panels on it instead of use
	CBaseAnimating *pEntityToSpawnOn = this;
	char *pOrgLL = "controlpanel%d_ll";
	char *pOrgUR = "controlpanel%d_ur";
	char *pAttachmentNameLL = pOrgLL;
	char *pAttachmentNameUR = pOrgUR;
	/*
	if ( IsBuiltOnAttachment() )
	{
		pEntityToSpawnOn = dynamic_cast<CBaseAnimating*>((CBaseEntity*)m_hBuiltOnEntity.Get());
		if ( pEntityToSpawnOn )
		{
			char sBuildPointLL[64];
			char sBuildPointUR[64];
			Q_snprintf( sBuildPointLL, sizeof( sBuildPointLL ), "bp%d_controlpanel%%d_ll", m_iBuiltOnPoint );
			Q_snprintf( sBuildPointUR, sizeof( sBuildPointUR ), "bp%d_controlpanel%%d_ur", m_iBuiltOnPoint );
			pAttachmentNameLL = sBuildPointLL;
			pAttachmentNameUR = sBuildPointUR;
		}
		else
		{
			pEntityToSpawnOn = this;
		}
	}
	*/

	Assert( pEntityToSpawnOn );

	// Lookup the attachment point...
	int nPanel;
	for ( nPanel = 0; true; ++nPanel )
	{
		Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel );
		int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
		if (nLLAttachmentIndex <= 0)
		{
			// Try and use my panels then
			pEntityToSpawnOn = this;
			Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel );
			nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
			if (nLLAttachmentIndex <= 0)
				return;
		}

		Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel );
		int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
		if (nURAttachmentIndex <= 0)
		{
			// Try and use my panels then
			Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel );
			nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
			if (nURAttachmentIndex <= 0)
				return;
		}

		const char *pScreenName;
		weapon->GetControlPanelInfo( nPanel, pScreenName );
		if (!pScreenName)
			continue;

		const char *pScreenClassname;
		weapon->GetControlPanelClassName( nPanel, pScreenClassname );
		if ( !pScreenClassname )
			continue;

		// Compute the screen size from the attachment points...
		matrix3x4_t	panelToWorld;
		pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld );

		matrix3x4_t	worldToPanel;
		MatrixInvert( panelToWorld, worldToPanel );

		// Now get the lower right position + transform into panel space
		Vector lr, lrlocal;
		pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld );
		MatrixGetColumn( panelToWorld, 3, lr );
		VectorTransform( lr, worldToPanel, lrlocal );

		float flWidth = lrlocal.x;
		float flHeight = lrlocal.y;

		CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex );
		pScreen->ChangeTeam( GetTeamNumber() );
		pScreen->SetActualSize( flWidth, flHeight );
		pScreen->SetActive( false );
		pScreen->MakeVisibleOnlyToTeammates( false );
	
#ifdef INVASION_DLL
		pScreen->SetOverlayMaterial( SCREEN_OVERLAY_MATERIAL );
#endif
		pScreen->SetAttachedToViewModel( true );
		int nScreen = m_hScreens.AddToTail( );
		m_hScreens[nScreen].Set( pScreen );
	}
#endif
}
コード例 #21
0
void C_EnvProjectedTexture::UpdateLight( void )
{
	VPROF("C_EnvProjectedTexture::UpdateLight");
	bool bVisible = true;

	Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b );
	float flLinearFloatLightAlpha = m_LightColor.a;

	if ( m_bAlwaysUpdate )
	{
		m_bForceUpdate = true;
	}

	if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha )
	{
		float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;

		m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
		m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
		m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
		m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );

		m_bForceUpdate = true;
	}
	
	if ( !m_bForceUpdate )
	{
		bVisible = IsBBoxVisible();		
	}

	if ( m_bState == false || !bVisible )
	{
		// Spotlight's extents aren't in view
		ShutDownLightHandle();

		return;
	}

	if ( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || m_bForceUpdate )
	{
		Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
		FlashlightState_t state;

		if ( m_hTargetEntity != NULL )
		{
			if ( m_bCameraSpace )
			{
				const QAngle &angles = GetLocalAngles();

				C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
				if( pPlayer )
				{
					const QAngle playerAngles = pPlayer->GetAbsAngles();

					Vector vPlayerForward, vPlayerRight, vPlayerUp;
					AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp );

					matrix3x4_t	mRotMatrix;
					AngleMatrix( angles, mRotMatrix );

					VectorITransform( vPlayerForward, mRotMatrix, vForward );
					VectorITransform( vPlayerRight, mRotMatrix, vRight );
					VectorITransform( vPlayerUp, mRotMatrix, vUp );

					float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
					vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;

					VectorNormalize( vForward );
					VectorNormalize( vRight );
					VectorNormalize( vUp );
				}
			}
			else
			{
				vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
				VectorNormalize( vForward );

				// JasonM - unimplemented
				Assert (0);

				//Quaternion q = DirectionToOrientation( dir );


				//
				// JasonM - set up vRight, vUp
				//

				//			VectorNormalize( vRight );
				//			VectorNormalize( vUp );
			}
		}
		else
		{
			AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
		}

		state.m_fHorizontalFOVDegrees = m_flLightFOV;
		state.m_fVerticalFOVDegrees = m_flLightFOV;

		state.m_vecLightOrigin = vPos;
		BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );
		state.m_NearZ = m_flNearZ;
		state.m_FarZ = m_flFarZ;

		// quickly check the proposed light's bbox against the view frustum to determine whether we
		// should bother to create it, if it doesn't exist, or cull it, if it does.
		if ( m_bSimpleProjection == false )
		{
#pragma message("OPTIMIZATION: this should be made SIMD")
			// get the half-widths of the near and far planes, 
			// based on the FOV which is in degrees. Remember that
			// on planet Valve, x is forward, y left, and z up. 
			const float tanHalfAngle = tan( m_flLightFOV * ( M_PI/180.0f ) * 0.5f );
			const float halfWidthNear = tanHalfAngle * m_flNearZ;
			const float halfWidthFar = tanHalfAngle * m_flFarZ;
			// now we can build coordinates in local space: the near rectangle is eg 
			// (0, -halfWidthNear, -halfWidthNear), (0,  halfWidthNear, -halfWidthNear), 
			// (0,  halfWidthNear,  halfWidthNear), (0, -halfWidthNear,  halfWidthNear)

			VectorAligned vNearRect[4] = { 
				VectorAligned( m_flNearZ, -halfWidthNear, -halfWidthNear), VectorAligned( m_flNearZ,  halfWidthNear, -halfWidthNear),
				VectorAligned( m_flNearZ,  halfWidthNear,  halfWidthNear), VectorAligned( m_flNearZ, -halfWidthNear,  halfWidthNear) 
			};

			VectorAligned vFarRect[4] = { 
				VectorAligned( m_flFarZ, -halfWidthFar, -halfWidthFar), VectorAligned( m_flFarZ,  halfWidthFar, -halfWidthFar),
				VectorAligned( m_flFarZ,  halfWidthFar,  halfWidthFar), VectorAligned( m_flFarZ, -halfWidthFar,  halfWidthFar) 
			};

			matrix3x4_t matOrientation( vForward, -vRight, vUp, vPos );

			enum
			{
				kNEAR = 0,
				kFAR = 1,
			};
			VectorAligned vOutRects[2][4];

			for ( int i = 0 ; i < 4 ; ++i )
			{
				VectorTransform( vNearRect[i].Base(), matOrientation, vOutRects[0][i].Base() );
			}
			for ( int i = 0 ; i < 4 ; ++i )
			{
				VectorTransform( vFarRect[i].Base(), matOrientation, vOutRects[1][i].Base() );
			}

			// now take the min and max extents for the bbox, and see if it is visible.
			Vector mins = **vOutRects; 
			Vector maxs = **vOutRects; 
			for ( int i = 1; i < 8 ; ++i )
			{
				VectorMin( mins, *(*vOutRects+i), mins );
				VectorMax( maxs, *(*vOutRects+i), maxs );
			}

#if 0 //for debugging the visibility frustum we just calculated
			NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][1], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //first tri
			NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][1], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //make it double sided
			NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][3], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //second tri
			NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][3], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //make it double sided

			NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][1], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //first tri
			NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][1], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //make it double sided
			NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][3], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //second tri
			NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][3], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //make it double sided

			NDebugOverlay::Box( vec3_origin, mins, maxs, 0, 255, 0, 100, 0.0f );
#endif
			
			bool bVisible = IsBBoxVisible( mins, maxs );
			if (!bVisible)
			{
				// Spotlight's extents aren't in view
				if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
				{
					ShutDownLightHandle();
				}

				return;
			}
		}

		float flAlpha = m_flCurrentLinearFloatLightAlpha * ( 1.0f / 255.0f );

		state.m_fQuadraticAtten = 0.0;
		state.m_fLinearAtten = 100;
		state.m_fConstantAtten = 0.0f;
		state.m_FarZAtten = m_flFarZ;
		state.m_fBrightnessScale = m_flBrightnessScale;
		state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha;
		state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha;
		state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha;
		state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
		state.m_flShadowSlopeScaleDepthBias = g_pMaterialSystemHardwareConfig->GetShadowSlopeScaleDepthBias();
		state.m_flShadowDepthBias = g_pMaterialSystemHardwareConfig->GetShadowDepthBias();
		state.m_bEnableShadows = m_bEnableShadows;
		state.m_pSpotlightTexture = m_SpotlightTexture;
		state.m_pProjectedMaterial = NULL; // only complain if we're using material projection
		state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
		state.m_flProjectionSize = m_flProjectionSize;
		state.m_flProjectionRotation = m_flRotation;

		state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality

		if ( m_bSimpleProjection == true )
		{
			state.m_bSimpleProjection = true;
			state.m_bOrtho = true;
			state.m_fOrthoLeft = -m_flProjectionSize;
			state.m_fOrthoTop = -m_flProjectionSize;
			state.m_fOrthoRight = m_flProjectionSize;
			state.m_fOrthoBottom = m_flProjectionSize;
		}

		if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE )
		{
			// Hack: env projected textures don't work like normal flashlights; they're not assigned to a given splitscreen slot,
			// but the flashlight code requires this
			HACK_GETLOCALPLAYER_GUARD( "Env projected texture" );
			if ( m_bSimpleProjection == true )
			{
				m_LightHandle = g_pClientShadowMgr->CreateProjection( state );
			}
			else
			{
				m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state );
			}

			if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
			{
				m_bForceUpdate = false;
			}
		}
		else
		{
			if ( m_bSimpleProjection == true )
			{
				g_pClientShadowMgr->UpdateProjectionState( m_LightHandle, state );
			}
			else
			{
				g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
			}
			m_bForceUpdate = false;
		}

		g_pClientShadowMgr->GetFrustumExtents( m_LightHandle, m_vecExtentsMin, m_vecExtentsMax );

		m_vecExtentsMin = m_vecExtentsMin - GetAbsOrigin();
		m_vecExtentsMax = m_vecExtentsMax - GetAbsOrigin();
	}

	if( m_bLightOnlyTarget )
	{
		g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity );
	}
	else
	{
		g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL );
	}

	g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );

	if ( !asw_perf_wtf.GetBool() && !m_bForceUpdate )
	{
		g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
	}
}
コード例 #22
0
void CParticleSystemQuery::GetRandomPointsOnControllingObjectHitBox( 
	CParticleCollection *pParticles,
	int nControlPointNumber, 
	int nNumPtsOut,
	float flBBoxScale,
	int nNumTrysToGetAPointInsideTheModel,
	Vector *pPntsOut,
	Vector vecDirectionalBias,
	Vector *pHitBoxRelativeCoordOut,
	int *pHitBoxIndexOut
	)
{

	bool bSucesss = false;


#ifndef GAME_DLL

	EHANDLE *phMoveParent = reinterpret_cast<EHANDLE *> ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject );
	CBaseEntity *pMoveParent = NULL;
	if ( phMoveParent )
	{
		pMoveParent = *( phMoveParent );
	}
	if ( pMoveParent )
	{
		float flRandMax = flBBoxScale;
		float flRandMin = 1.0 - flBBoxScale;
		Vector vecBasePos;
		pParticles->GetControlPointAtTime( nControlPointNumber, pParticles->m_flCurTime, &vecBasePos );

		s_BoneMutex.Lock();
		C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating();
		if ( pAnimating )
		{
			
			matrix3x4_t	*hitboxbones[MAXSTUDIOBONES];
			
			if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) )
			{
		
				studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
				
				if ( pStudioHdr )
				{
					mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );
					
					if ( set )
					{
						bSucesss = true;
						
						Vector vecWorldPosition;
						float u = 0, v = 0, w = 0;
						int nHitbox = 0;
						int nNumIters = nNumTrysToGetAPointInsideTheModel;
						if (! vecDirectionalBias.IsZero( 0.0001 ) )
							nNumIters = max( nNumIters, 5 );

						for( int i=0 ; i < nNumPtsOut; i++)
						{
							int nTryCnt = nNumIters;
							float flBestPointGoodness = -1.0e20;
							do
							{
								int nTryHitbox = pParticles->RandomInt( 0, set->numhitboxes - 1 );
								mstudiobbox_t *pBox = set->pHitbox(nTryHitbox);
								
								float flTryU = pParticles->RandomFloat( flRandMin, flRandMax );
								float flTryV = pParticles->RandomFloat( flRandMin, flRandMax );
								float flTryW = pParticles->RandomFloat( flRandMin, flRandMax );

								Vector vecLocalPosition;
								vecLocalPosition.x = GetSurfaceCoord( flTryU, pBox->bbmin.x, pBox->bbmax.x );
								vecLocalPosition.y = GetSurfaceCoord( flTryV, pBox->bbmin.y, pBox->bbmax.y );
								vecLocalPosition.z = GetSurfaceCoord( flTryW, pBox->bbmin.z, pBox->bbmax.z );

								Vector vecTryWorldPosition;

								VectorTransform( vecLocalPosition, *hitboxbones[pBox->bone], vecTryWorldPosition );
								
								
								float flPointGoodness = pParticles->RandomFloat( 0, 72 )
									+ DotProduct( vecTryWorldPosition - vecBasePos, 
												  vecDirectionalBias );

								if ( nNumTrysToGetAPointInsideTheModel )
								{
									// do a point in solid test
									Ray_t ray;
									trace_t tr;
									ray.Init( vecTryWorldPosition, vecTryWorldPosition );
									enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr );
									if ( tr.startsolid )
										flPointGoodness += 1000.; // got a point inside!
								}
								if ( flPointGoodness > flBestPointGoodness )
								{
									u = flTryU;
									v = flTryV;
									w = flTryW;
									vecWorldPosition = vecTryWorldPosition;
									nHitbox = nTryHitbox;
									flBestPointGoodness = flPointGoodness;
								}
							} while ( nTryCnt-- );
							*( pPntsOut++ ) = vecWorldPosition;
							if ( pHitBoxRelativeCoordOut )
								( pHitBoxRelativeCoordOut++ )->Init( u, v, w );
							if ( pHitBoxIndexOut )
								*( pHitBoxIndexOut++ ) = nHitbox;
						}
					}
				}
			}
		}

		if ( pMoveParent->IsBrushModel() )
		{
			Vector vecMin;
			Vector vecMax;
			matrix3x4_t matOrientation;
			Vector VecOrigin;
			pMoveParent->GetRenderBounds( vecMin, vecMax  );
			VecOrigin = pMoveParent->GetRenderOrigin();
			matOrientation = pMoveParent->EntityToWorldTransform();

			

			Vector vecWorldPosition;
			float u = 0, v = 0, w = 0;
			int nHitbox = 0;
			int nNumIters = nNumTrysToGetAPointInsideTheModel;
			if (! vecDirectionalBias.IsZero( 0.0001 ) )
				nNumIters = max( nNumIters, 5 );

			for( int i=0 ; i < nNumPtsOut; i++)
			{
				int nTryCnt = nNumIters;
				float flBestPointGoodness = -1.0e20;
				do
				{
					float flTryU = pParticles->RandomFloat( flRandMin, flRandMax );
					float flTryV = pParticles->RandomFloat( flRandMin, flRandMax );
					float flTryW = pParticles->RandomFloat( flRandMin, flRandMax );

					Vector vecLocalPosition;
					vecLocalPosition.x = GetSurfaceCoord( flTryU, vecMin.x, vecMax.x );
					vecLocalPosition.y = GetSurfaceCoord( flTryV, vecMin.y, vecMax.y );
					vecLocalPosition.z = GetSurfaceCoord( flTryW, vecMin.z, vecMax.z );

					Vector vecTryWorldPosition;
					VectorTransform( vecLocalPosition, matOrientation, vecTryWorldPosition );

					float flPointGoodness = pParticles->RandomFloat( 0, 72 )
						+ DotProduct( vecTryWorldPosition - vecBasePos, 
						vecDirectionalBias );

					if ( nNumTrysToGetAPointInsideTheModel )
					{
						// do a point in solid test
						Ray_t ray;
						trace_t tr;
						ray.Init( vecTryWorldPosition, vecTryWorldPosition );
						enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr );
						if ( tr.startsolid )
							flPointGoodness += 1000.; // got a point inside!
					}
					if ( flPointGoodness > flBestPointGoodness )
					{
						u = flTryU;
						v = flTryV;
						w = flTryW;
						vecWorldPosition = vecTryWorldPosition;
						nHitbox = 0;
						flBestPointGoodness = flPointGoodness;
					}
				} while ( nTryCnt-- );
				*( pPntsOut++ ) = vecWorldPosition;
				if ( pHitBoxRelativeCoordOut )
					( pHitBoxRelativeCoordOut++ )->Init( u, v, w );
				if ( pHitBoxIndexOut )
					*( pHitBoxIndexOut++ ) = nHitbox;
			}
		}

		s_BoneMutex.Unlock();
	}
#endif
	if (! bSucesss )
	{
		// don't have a model or am in editor or something - fill return with control point
		for( int i=0 ; i < nNumPtsOut; i++)
		{
			pPntsOut[i] = pParticles->m_ControlPoints[nControlPointNumber].m_Position; // fallback if anything goes wrong
			
			if ( pHitBoxIndexOut )
				pHitBoxIndexOut[i] = 0;
			
			if ( pHitBoxRelativeCoordOut )
				pHitBoxRelativeCoordOut[i].Init();
		}
	}
}
void C_EnvProjectedTexture::UpdateLight(void)
{
	VPROF_BUDGET("C_EnvProjectedTexture::UpdateLight", "Projected Textures");

	if (CurrentViewID() == VIEW_SHADOW_DEPTH_TEXTURE /*|| CurrentViewID() == VIEW_SUN_SHAFTS*/)
		return;

	bool bVisible = true;

	if (m_bAlwaysUpdate)
	{
		m_bForceUpdate = true;
	}

	float fHighFOV;
	if (m_flLightFOV > m_flLightHorFOV)
		fHighFOV = m_flLightFOV;
	else
		fHighFOV = m_flLightHorFOV;

	if (m_bState == false || !IsWithinFarZ(fHighFOV) || !IsBBoxVisible())
	{
		// Spotlight's extents aren't in view
		ShutDownLightHandle();

		return;
	}
	else
	{
		bVisible = true;
	}

	Vector vLinearFloatLightColor(m_LightColor.r, m_LightColor.g, m_LightColor.b);
	float flLinearFloatLightAlpha = m_LightColor.a;

	if (m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha)
	{
		float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;

		m_CurrentLinearFloatLightColor.x = Approach(vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed);
		m_CurrentLinearFloatLightColor.y = Approach(vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed);
		m_CurrentLinearFloatLightColor.z = Approach(vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed);
		m_flCurrentLinearFloatLightAlpha = Approach(flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed);

		m_bForceUpdate = true;
	}

	if (m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || GetRootMoveParent() != NULL || m_bForceUpdate)
	{
		Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
		FlashlightState_t state;

		if (m_hTargetEntity != NULL)
		{
			if (m_bCameraSpace)
			{
				const QAngle &angles = GetLocalAngles();

				C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
				if (pPlayer)
				{
					const QAngle playerAngles = pPlayer->GetAbsAngles();

					Vector vPlayerForward, vPlayerRight, vPlayerUp;
					AngleVectors(playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp);

					matrix3x4_t	mRotMatrix;
					AngleMatrix(angles, mRotMatrix);

					VectorITransform(vPlayerForward, mRotMatrix, vForward);
					VectorITransform(vPlayerRight, mRotMatrix, vRight);
					VectorITransform(vPlayerUp, mRotMatrix, vUp);

					float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
					vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;

					VectorNormalize(vForward);
					VectorNormalize(vRight);
					VectorNormalize(vUp);
				}
			}
			else
			{
				Vector vecToTarget = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
				QAngle vecAngles;
				VectorAngles(vecToTarget, vecAngles);
				AngleVectors(vecAngles, &vForward, &vRight, &vUp);
			}
		}
		else
		{
			AngleVectors(GetAbsAngles(), &vForward, &vRight, &vUp);
		}

		state.m_fHorizontalFOVDegrees = abs(m_flLightHorFOV);
		state.m_fVerticalFOVDegrees = abs(m_flLightFOV);

		state.m_vecLightOrigin = vPos;
		BasisToQuaternion(vForward, vRight, vUp, state.m_quatOrientation);
		state.m_NearZ = m_flNearZ;
		state.m_FarZ = m_flFarZ;

		// quickly check the proposed light's bbox against the view frustum to determine whether we
		// should bother to create it, if it doesn't exist, or cull it, if it does.
		// get the half-widths of the near and far planes, 
		// based on the FOV which is in degrees. Remember that
		// on planet Valve, x is forward, y left, and z up. 
		const float tanHalfAngle = tan(fHighFOV * (M_PI / 180.0f) * 0.5f);
		const float halfWidthNear = tanHalfAngle * m_flNearZ;
		const float halfWidthFar = tanHalfAngle * m_flFarZ;
		// now we can build coordinates in local space: the near rectangle is eg 
		// (0, -halfWidthNear, -halfWidthNear), (0,  halfWidthNear, -halfWidthNear), 
		// (0,  halfWidthNear,  halfWidthNear), (0, -halfWidthNear,  halfWidthNear)

		VectorAligned vNearRect[4] = {
			VectorAligned(m_flNearZ, -halfWidthNear, -halfWidthNear), VectorAligned(m_flNearZ,  halfWidthNear, -halfWidthNear),
			VectorAligned(m_flNearZ,  halfWidthNear,  halfWidthNear), VectorAligned(m_flNearZ, -halfWidthNear,  halfWidthNear)
		};

		VectorAligned vFarRect[4] = {
			VectorAligned(m_flFarZ, -halfWidthFar, -halfWidthFar), VectorAligned(m_flFarZ,  halfWidthFar, -halfWidthFar),
			VectorAligned(m_flFarZ,  halfWidthFar,  halfWidthFar), VectorAligned(m_flFarZ, -halfWidthFar,  halfWidthFar)
		};

		matrix3x4_t matOrientation(vForward, -vRight, vUp, vPos);

		enum
		{
			kNEAR = 0,
			kFAR = 1,
		};
		VectorAligned vOutRects[2][4];

		for (int i = 0; i < 4; ++i)
		{
			VectorTransform(vNearRect[i].Base(), matOrientation, vOutRects[0][i].Base());
		}
		for (int i = 0; i < 4; ++i)
		{
			VectorTransform(vFarRect[i].Base(), matOrientation, vOutRects[1][i].Base());
		}

		// now take the min and max extents for the bbox, and see if it is visible.
		Vector mins = **vOutRects;
		Vector maxs = **vOutRects;
		for (int i = 1; i < 8; ++i)
		{
			VectorMin(mins, *(*vOutRects + i), mins);
			VectorMax(maxs, *(*vOutRects + i), maxs);
		}

#if 0 //for debugging the visibility frustum we just calculated
		NDebugOverlay::Triangle(vOutRects[0][0], vOutRects[0][1], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f); //first tri
		NDebugOverlay::Triangle(vOutRects[0][2], vOutRects[0][1], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f); //make it double sided
		NDebugOverlay::Triangle(vOutRects[0][2], vOutRects[0][3], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f); //second tri
		NDebugOverlay::Triangle(vOutRects[0][0], vOutRects[0][3], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f); //make it double sided

		NDebugOverlay::Triangle(vOutRects[1][0], vOutRects[1][1], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f); //first tri
		NDebugOverlay::Triangle(vOutRects[1][2], vOutRects[1][1], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f); //make it double sided
		NDebugOverlay::Triangle(vOutRects[1][2], vOutRects[1][3], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f); //second tri
		NDebugOverlay::Triangle(vOutRects[1][0], vOutRects[1][3], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f); //make it double sided

		NDebugOverlay::Box(vec3_origin, mins, maxs, 0, 255, 0, 100, 0.0f);
#endif

		bool bVisible = IsBBoxVisible(mins, maxs);
		if (!bVisible)
		{
			// Spotlight's extents aren't in view
			if (m_LightHandle != CLIENTSHADOW_INVALID_HANDLE)
			{
				ShutDownLightHandle();
			}

			return;
		}

		float flAlpha = m_flCurrentLinearFloatLightAlpha * (1.0f / 255.0f);

		state.m_fQuadraticAtten = m_flQuadratic;
		state.m_fLinearAtten = 100;
		if (m_bAtten)
		{
			state.m_fConstantAtten = 0.0f;
		}
		else
		{
			state.m_fConstantAtten = 1.0f;
		}
		state.m_Color[0] = (m_CurrentLinearFloatLightColor.x * (1.0f / 255.0f) * flAlpha) * m_fBrightness;
		state.m_Color[1] = (m_CurrentLinearFloatLightColor.y * (1.0f / 255.0f) * flAlpha) * m_fBrightness;
		state.m_Color[2] = (m_CurrentLinearFloatLightColor.z * (1.0f / 255.0f) * flAlpha) * m_fBrightness;
		state.m_Color[3] = m_flAmbient;
		state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
		state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
		if (m_bEnableShadows && r_flashlightdepthtexture.GetBool() && m_bClientWantsShadows)
		{
			state.m_bEnableShadows = true;
		}
		else
		{
			state.m_bEnableShadows = false;
		}
		state.m_pSpotlightTexture = m_SpotlightTexture;
		state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
		if (r_dynamicshadows_use_c17_improvements.GetBool())
		{
			//state.m_flShadowFilterSize = m_flBlur;
			if (r_flashlightdepthres.GetInt() == 512)
			{
				state.m_flShadowFilterSize = 0.8f;
			}
			else if (r_flashlightdepthres.GetInt() == 1024)
			{
				state.m_flShadowFilterSize = 0.3f;
			}
			else if (r_flashlightdepthres.GetInt() == 2048)
			{
				state.m_flShadowFilterSize = 0.2f;
			}
			else if (r_flashlightdepthres.GetInt() == 4096)
			{
				state.m_flShadowFilterSize = 0.08f;
			}
			else
			{
				state.m_flShadowFilterSize = 1.0f;
			}
			state.m_flShadowAtten = m_flAtten;
		}
		else
		{
			state.m_flShadowFilterSize = 3.0f;
			state.m_flShadowAtten = 0.35f;
		}
		state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality

		if (m_LightHandle == CLIENTSHADOW_INVALID_HANDLE)
		{
			// Hack: env projected textures don't work like normal flashlights; they're not assigned to a given splitscreen slot,
			// but the flashlight code requires this
			m_LightHandle = g_pClientShadowMgr->CreateFlashlight(state);

			if (m_LightHandle != CLIENTSHADOW_INVALID_HANDLE)
			{
				m_bForceUpdate = false;
			}
		}
		else
		{
			g_pClientShadowMgr->UpdateFlashlightState(m_LightHandle, state);
			m_bForceUpdate = false;
		}

		g_pClientShadowMgr->GetFrustumExtents(m_LightHandle, m_vecExtentsMin, m_vecExtentsMax);

		m_vecExtentsMin = m_vecExtentsMin - GetAbsOrigin();
		m_vecExtentsMax = m_vecExtentsMax - GetAbsOrigin();
	}

	if (m_bLightOnlyTarget)
	{
		g_pClientShadowMgr->SetFlashlightTarget(m_LightHandle, m_hTargetEntity);
	}
	else
	{
		g_pClientShadowMgr->SetFlashlightTarget(m_LightHandle, NULL);
	}

	g_pClientShadowMgr->SetFlashlightLightWorld(m_LightHandle, m_bLightWorld);

	if (!m_bForceUpdate)
	{
		g_pClientShadowMgr->UpdateProjectedTexture(m_LightHandle, true);
	}
}
コード例 #24
0
//tm the mirror tm 
void CopyBuffer::PasteToBuffer(MorphByBone *mod, MorphByBoneData *targ, Matrix3 mirrorTM, float threshold, BOOL flipTM)
{
	if (copyData == NULL) return;
	if (copyData->morphTargets.Count() == 0) return;


	if (targ == NULL) return;

//delete any existing morphs
	for (int i = 0; i < targ->morphTargets.Count(); i++)
		delete targ->morphTargets[i];

	targ->morphTargets.ZeroCount();
	int realCount= 0;
	for (int i = 0; i < copyData->morphTargets.Count(); i++)
		{
		if (!copyData->morphTargets[i]->IsDead()) realCount++;
		}
	targ->morphTargets.SetCount(realCount);

	for (int i = 0; i < mod->localDataList.Count(); i++)
		{
		MorphByBoneLocalData *ld = mod->localDataList[i];
		if (ld)
			{
			ld->tempPoints = ld->preDeform;
			ld->tempMatchList.SetCount(ld->tempPoints.Count());
			for (int j = 0; j < ld->preDeform.Count(); j++)
				{
				Matrix3 tm(1);
				//need to put our original points
				ld->tempPoints[j] = ld->tempPoints[j] * mirrorTM;
				ld->tempMatchList[j] = -1;
				}
			}
		}
//now find closest pairs
	for (int i = 0; i < mod->localDataList.Count(); i++)
		{
		MorphByBoneLocalData *ld = mod->localDataList[i];
		if (ld)
			{			
			for (int j = 0; j < ld->tempPoints.Count(); j++)
				{
				Point3 sourcePoint = ld->preDeform[j];
				float closest = 3.4e+38;
				int closestID = -1;
				for (int k = 0; k < ld->tempPoints.Count(); k++)
					{
					Point3 mirrorPoint = ld->tempPoints[k];
					float dist = Length(sourcePoint-mirrorPoint);
					if ((dist < threshold) && (dist < closest))
						{
						closest = dist;
						closestID = k;
						}

					}
				if (closestID != -1)
					ld->tempMatchList[closestID] = j;
				}
			}
		}
//create a blank set of morphs
	int currentMorph = 0;
	for (int i = 0; i < copyData->morphTargets.Count(); i++)
		{
		if (!copyData->morphTargets[i]->IsDead())
			{
			targ->morphTargets[currentMorph] = new MorphTargets();
			int currentVert=0;
			for (int j = 0; j < mod->localDataList.Count(); j++)
				{
				targ->morphTargets[currentMorph]->d.SetCount(mod->localDataList[j]->preDeform.Count());
				for (int k =0; k < mod->localDataList[j]->preDeform.Count(); k++)
					{
					targ->morphTargets[currentMorph]->d[currentVert].vertexID = k;
					targ->morphTargets[currentMorph]->d[currentVert].vec = Point3(0.0f,0.0f,0.0f);
					targ->morphTargets[currentMorph]->d[currentVert].vecParentSpace = Point3(0.0f,0.0f,0.0f);
					targ->morphTargets[currentMorph]->d[currentVert].originalPt = mod->localDataList[j]->preDeform[k];//*tm;
					targ->morphTargets[currentMorph]->d[currentVert].localOwner = j;
					currentVert++;
					}
				}
			currentMorph++;
			}
		
		}
//this only works if it is not instanced
//loop through morphs
	currentMorph = 0;
	for (int i = 0; i < copyData->morphTargets.Count(); i++)
		{
		if (!copyData->morphTargets[i]->IsDead())
			{

		//loop through points
			for (int j = 0; j <targ->morphTargets[currentMorph]->d.Count(); j++)
				{

		//get the mirror index if there is one
				int ldIndex = targ->morphTargets[currentMorph]->d[j].localOwner;
				MorphByBoneLocalData *ld = mod->localDataList[ldIndex];

				Matrix3 boneTM = copyData->currentBoneNodeTM;
				Matrix3 parentTM = copyData->parentBoneNodeCurrentTM;
				Matrix3 mirror = Inverse(ld->selfNodeTM) * mirrorTM * ld->selfNodeTM;
				Matrix3 mirrorBoneTM = targ->currentBoneNodeTM;
				Matrix3 mirrorParentTM = targ->parentBoneNodeCurrentTM;

				Matrix3 lTM, pTM;
				lTM = boneTM * mirror * Inverse(mirrorBoneTM);
				pTM = parentTM * mirror * Inverse(mirrorParentTM);


				if (ld)
					{
					int  mirrorID = targ->morphTargets[currentMorph]->d[j].vertexID;
					int sourceID = ld->tempMatchList[mirrorID];
					//now look though our list and swap the 2
					if (sourceID != -1)
						{

	////transform the vec into local space, flip them, then back into bone space
	//					targ->morphTargets[i]->d[j].vec = VectorTransform(copyData->morphTargts[i]->d[sourceID].vec,mirrorTM);
						if (1)//(flipTM)
							{
							Point3 vec = copyData->morphTargets[i]->d[sourceID].vec; // in local bone space
							targ->morphTargets[currentMorph]->d[j].vec = VectorTransform(lTM,vec);

							vec = copyData->morphTargets[i]->d[sourceID].vecParentSpace; // in local bone space
							targ->morphTargets[currentMorph]->d[j].vecParentSpace = VectorTransform(pTM,vec);
							//current bone tm
							//current parent tm

							//invserse of the self
							//mirror
							//self tm

							//inverse of mirror bone
							//inverse of mirror parent bone

							}
						else 
							{
							targ->morphTargets[currentMorph]->d[j].vec = copyData->morphTargets[i]->d[sourceID].vec;
							targ->morphTargets[currentMorph]->d[j].vecParentSpace = copyData->morphTargets[i]->d[sourceID].vecParentSpace;
							}


//						Point3 pvec = copyData->morphTargets[i]->d[sourceID].vecParentSpace;

//						Matrix3 selfTM = ld->selfNodeTM;
//						Matrix3 parentTM = copyData->parentBoneNodeCurrentTM;
//						Matrix3 tm = parentTM * Inverse(selfTM) * mirrorTM * selfTM * Inverse(parentTM);

//						pvec = VectorTransform(tm,pvec);

						//do we need to flip the vecs?
						targ->morphTargets[currentMorph]->d[j].originalPt = copyData->morphTargets[i]->d[sourceID].originalPt * mirrorTM;

						}
					}
				}

	//resolve tms
			if (flipTM)
				{
				MorphByBoneLocalData *ld = mod->localDataList[0];
				Matrix3 mirror = Inverse(ld->selfNodeTM) * mirrorTM * ld->selfNodeTM;

		//mirror the initial copy node tm
				Matrix3 copyTM = copyData->currentBoneNodeTM;
				copyTM *= mirror;
				copyTM.SetRow(3,targ->currentBoneNodeTM.GetRow(3));

	//			targ->morphTargets[currentMorph]->boneTMInParentSpace = copyTM * ;


		//put our current targ node tm into the copyTM space
				Matrix3 targTM = targ->currentBoneNodeTM;
				targTM *= Inverse(copyTM);

		//put the morph tm in worldspace
				Matrix3 morphTM = copyData->morphTargets[i]->boneTMInParentSpace * copyData->parentBoneNodeCurrentTM;
		//mirror it
	//			morphTM *= mirror;
	//			morphTM.SetRow(3,targ->currentBoneNodeTM.GetRow(3));

		//now animate it back to world using the morph target tm
				targTM *= morphTM;
		//jam it back into our parent space
				targTM *= Inverse(targ->currentBoneNodeTM);

				targ->morphTargets[currentMorph]->boneTMInParentSpace = targTM;
				}
			else targ->morphTargets[currentMorph]->boneTMInParentSpace = copyData->morphTargets[i]->boneTMInParentSpace;


//puts it in world space
/*
			morphTM = copyData->morphTargets[i]->boneTMInParentSpace * copyData->parentBoneNodeCurrentTM;
			morphTM.SetRow(3,targ->currentBoneNodeTM.GetRow(3));
			morphTM = morphTM * mirror;
			morphTM = morphTM * Inverse(targ->parentBoneNodeCurrentTM);
			targ->morphTargets[currentMorph]->boneTMInParentSpace = morphTM;
*/


/*
	//mirror all the morph tms
			MorphByBoneLocalData *ld = mod->localDataList[0];
			Matrix3 mirror = Inverse(ld->selfNodeTM) * mirrorTM * ld->selfNodeTM;
			Matrix3 ptm = copyData->parentBoneNodeCurrentTM;
			Matrix3 mtm = copyData->morphTargets[i]->boneTMInParentSpace;
			Matrix3 morphWorldSpaceTM = mtm * ptm *mirror;
			morphWorldSpaceTM.SetRow(3,targ->currentBoneNodeTM.GetRow(3));
	

	//link the target bone initial to the mirrored initial copy node tm
			//remcompute the mirror tms
			//but pack into our targ space


			if (flipTM)
				{
				MorphByBoneLocalData *ld = mod->localDataList[0];

				Matrix3 mirror = Inverse(ld->selfNodeTM) * mirrorTM * ld->selfNodeTM;

				//transform the tm into local space
				//flip it thenback in parent space
				Matrix3 mtm = copyData->morphTargets[i]->boneTMInParentSpace;
				mtm = mtm * copyData->parentBoneNodeCurrentTM; //this puts in world space
				Point3 x,y,z;
				x = VectorTransform(mirror,mtm.GetRow(0));
				y = VectorTransform(mirror,mtm.GetRow(1));
				z = VectorTransform(mirror,mtm.GetRow(2));
				mtm.SetRow(0,x);
				mtm.SetRow(1,y);
				mtm.SetRow(2,z);
				mtm = mtm * Inverse(copyData->parentBoneNodeCurrentTM);
				mtm.SetRow(3,copyData->morphTargets[i]->boneTMInParentSpace.GetRow(3));
				//put in world space, then by the mirror then back into parent
				targ->morphTargets[currentMorph]->boneTMInParentSpace = copyData->morphTargets[i]->boneTMInParentSpace;
				}
			else targ->morphTargets[currentMorph]->boneTMInParentSpace = copyData->morphTargets[i]->boneTMInParentSpace;

  */
			targ->morphTargets[currentMorph]->influenceAngle = copyData->morphTargets[i]->influenceAngle;
			targ->morphTargets[currentMorph]->falloff = copyData->morphTargets[i]->falloff;

			targ->morphTargets[currentMorph]->name = copyData->morphTargets[i]->name;
			targ->morphTargets[currentMorph]->treeHWND = NULL;
			targ->morphTargets[currentMorph]->weight = copyData->morphTargets[i]->weight;
			targ->morphTargets[currentMorph]->flags = copyData->morphTargets[i]->flags;
			currentMorph++;
			}
		

		}



//clean up temp data
	for (int i = 0; i < mod->localDataList.Count(); i++)
		{
		MorphByBoneLocalData *ld = mod->localDataList[i];
		if (ld)
			{			
			ld->tempPoints.Resize(0);
			ld->tempMatchList.Resize(0);
			}
		}
}
コード例 #25
0
ファイル: moustrak.cpp プロジェクト: innovatelogic/ilogic-vm
BOOL
TrackMouseCallBack::point_on_obj(ViewExp& vpt, IPoint2 m, Point3& pt, Point3 &norm)
{
	if ( ! vpt.IsAlive() )
	{
		// why are we here
		DbgAssert(!_T("Invalid viewport!"));
		return FALSE;
	}

	// computes the normal ray at the point of intersection
	Ray ray, world_ray;
	float at, best_dist = 0.0f;
	TimeValue t = MAXScript_time();	
	Object *obj = NULL;
	Matrix3 obtm, iobtm;
	Point3 testNorm;

	BOOL found_hit = FALSE;
	
	vl->face_num_val = vl->face_bary = &undefined;
	hit_node = NULL;

	// Calculate a ray from the mouse point
	vpt.MapScreenToWorldRay(float(m.x), float(m.y), world_ray);

	for( int i=(nodeTab.Count()-1); i>=0; i-- ) {
		// Get the object from the node
		INode* node = nodeTab[i];
		ObjectState os = node->EvalWorldState(t);
		obj = os.obj;	

		// Back transform the ray into object space.
		obtm	= node->GetObjectTM(t);
		iobtm	= Inverse(obtm);
		ray.p   = iobtm * world_ray.p;
		ray.dir = VectorTransform(iobtm, world_ray.dir);
		
		// See if we hit the object
		if (obj->IsSubClassOf(triObjectClassID))
		{
			TriObject*  tobj = (TriObject*)obj;
			DWORD		fi;
			Point3		bary;
			if (tobj->mesh.IntersectRay(ray, at, testNorm, fi, bary)  &&
			   ((!found_hit) || (at<=best_dist)) )
			{
				// Calculate the hit point and transform everything back into world space.
				// record the face index and bary coord
				best_dist = at;
				pt = ray.p + ray.dir * at;
				pt = pt * obtm;
				norm = Normalize(VectorTransform(obtm, testNorm));
				vl->face_num_val = Integer::intern(fi + 1);
				vl->face_bary = new Point3Value(bary);
				hit_node = node;
				found_hit = TRUE;
			}
		}
		else if (obj->IntersectRay(t, ray, at, testNorm)  &&
				((!found_hit) || (at<=best_dist)) )
		{
			// Calculate the hit point and transform everything back into world space.
			best_dist = at;
			pt = ray.p + ray.dir * at;
			pt = pt * obtm;
			norm = Normalize(VectorTransform(obtm, testNorm));
			hit_node = node;
			found_hit = TRUE;
		}
	}
	if( found_hit ) return TRUE;

	// Failed to find a hit on any node, look at the Normal Align Vector for the first node
	if ((obj!=NULL) && obj->NormalAlignVector(t, pt, testNorm)) // See if a default NA vector is provided
	{
		pt   = pt * obtm;
		norm = Normalize(VectorTransform(obtm, testNorm));
		return TRUE;
	}
	else
		return FALSE;
}
コード例 #26
0
//-----------------------------------------------------------------------------
// Draws the mesh
//-----------------------------------------------------------------------------
void CDmeMDL::Draw( const matrix3x4_t &shapeToWorld, CDmeDrawSettings *pDrawSettings /* = NULL */ )
{
	if ( !g_pMaterialSystem || !g_pMDLCache || !g_pStudioRender )
		return;

	if ( m_MDLHandle == MDLHANDLE_INVALID )
		return;

	// Color + alpha modulation
	Vector white( m_Color.r() / 255.0f, m_Color.g() / 255.0f, m_Color.b() / 255.0f );
	g_pStudioRender->SetColorModulation( white.Base() );
	g_pStudioRender->SetAlphaModulation( m_Color.a() / 255.0f );

	DrawModelInfo_t info;
	info.m_pStudioHdr = g_pMDLCache->GetStudioHdr( m_MDLHandle );
	info.m_pHardwareData = g_pMDLCache->GetHardwareData( m_MDLHandle );
	info.m_Decals = STUDIORENDER_DECAL_INVALID;
	info.m_Skin = m_nSkin;
	info.m_Body = m_nBody;
	info.m_HitboxSet = 0;
	info.m_pClientEntity = NULL;
	info.m_pColorMeshes = NULL;
	info.m_bStaticLighting = false;
	info.m_Lod = m_nLOD;

	// FIXME: Deal with lighting
	for ( int i = 0; i < 6; ++ i )
	{
		info.m_vecAmbientCube[i].Init( 1, 1, 1 );
	}

	info.m_nLocalLightCount = 0;
//	info.m_LocalLightDescs;
	
	matrix3x4_t *pBoneToWorld = g_pStudioRender->LockBoneMatrices( info.m_pStudioHdr->numbones );
	SetUpBones( shapeToWorld, info.m_pStudioHdr->numbones, pBoneToWorld );
	g_pStudioRender->UnlockBoneMatrices();

	Vector vecWorldViewTarget;
	if ( m_bWorldSpaceViewTarget )
	{
		vecWorldViewTarget = m_vecViewTarget;
	}
	else
	{
		VectorTransform( m_vecViewTarget, shapeToWorld, vecWorldViewTarget );
	}
	g_pStudioRender->SetEyeViewTarget( info.m_pStudioHdr, info.m_Body, vecWorldViewTarget );

	// FIXME: Why is this necessary!?!?!?
	CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
	if ( !m_bDrawInEngine )
	{
		pRenderContext->CullMode(MATERIAL_CULLMODE_CCW);
	}

    // Set default flex values
	float *pFlexWeights = NULL;
	const int nFlexDescCount = info.m_pStudioHdr->numflexdesc;
	if ( nFlexDescCount )
	{
		CStudioHdr cStudioHdr( info.m_pStudioHdr, g_pMDLCache );
		float flexDefaults[ MAXSTUDIOFLEXCTRL * 4 ];
		memset( flexDefaults, 0, MAXSTUDIOFLEXCTRL * 4 * sizeof( float ) );

		g_pStudioRender->LockFlexWeights( info.m_pStudioHdr->numflexdesc, &pFlexWeights );
		cStudioHdr.RunFlexRules( flexDefaults, pFlexWeights );
		g_pStudioRender->UnlockFlexWeights();
	}

	Vector vecModelOrigin;
	MatrixGetColumn( shapeToWorld, 3, vecModelOrigin );
	g_pStudioRender->DrawModel( NULL, info, pBoneToWorld, pFlexWeights, NULL,
		vecModelOrigin, STUDIORENDER_DRAW_ENTIRE_MODEL );

	// FIXME: Why is this necessary!?!?!?
	if ( !m_bDrawInEngine )
	{
		pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
	}
}
コード例 #27
0
ファイル: vradstaticprops.cpp プロジェクト: chrizonix/RCBot2
//-----------------------------------------------------------------------------
// 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;
							}
						}
					}
				}
			}
		}
	}
}