Exemple #1
0
//
//  returns true if line (L1, L2) intersects with triangle( PV1, PV2, PV3 )
//  The point of intersection is returned in HitP
//
bool CheckLineTri( const CVec3 &L1, const CVec3 &L2, const CVec3 &PV1, const CVec3 &PV2, const CVec3 &PV3, CVec3 &HitP )
{
CVec3 VIntersect;

// Find Triangle Normal, would be quicker to have these computed already
CVec3 VNorm;
VNorm = ( PV2 - PV1 ).CrossProduct( PV3 - PV1 );
VNorm.Normalize();

// Find distance from L1 and L2 to the plane defined by the triangle
float fDst1 = (L1-PV1).Dot( VNorm );
float fDst2 = (L2-PV1).Dot( VNorm );

if ( (fDst1 * fDst2) >= 0.0f) return false;  // line doesn't cross the triangle.
if ( fDst1 == fDst2) {return false;} // line and plane are parallel

// Find point on the line that intersects with the plane
VIntersect = L1 + (L2-L1) * ( -fDst1/(fDst2-fDst1) );

// Find if the interesection point lies inside the triangle by testing it against all edges
CVec3 VTest;
VTest = VNorm.CrossProduct( PV2-PV1 );
if ( VTest.Dot( VIntersect-PV1 ) < 0.0f ) return false;
VTest = VNorm.CrossProduct( PV3-PV2 );
if ( VTest.Dot( VIntersect-PV2 ) < 0.0f ) return false;
VTest = VNorm.CrossProduct( PV1-PV3 );
if ( VTest.Dot( VIntersect-PV1 ) < 0.0f ) return false;

HitP = VIntersect;

return true;
}
Exemple #2
0
void UVertMesh::BuildNormals()
{
	// UE1 meshes have no stored normals, should build them
	// This function is similar to BuildNormals() from SkelMeshInstance.cpp
	int numVerts = Verts.Num();
	int i;
	Normals.Empty(numVerts);
	Normals.AddZeroed(numVerts);
	TArray<CVec3> tmpVerts, tmpNormals;
	tmpVerts.AddZeroed(numVerts);
	tmpNormals.AddZeroed(numVerts);
	// convert verts
	for (i = 0; i < numVerts; i++)
	{
		const FMeshVert &SV = Verts[i];
		CVec3           &DV = tmpVerts[i];
		DV[0] = SV.X * MeshScale.X;
		DV[1] = SV.Y * MeshScale.Y;
		DV[2] = SV.Z * MeshScale.Z;
	}
	// iterate faces
	for (i = 0; i < Faces.Num(); i++)
	{
		const FMeshFace &F = Faces[i];
		// get vertex indices
		int i1 = Wedges[F.iWedge[0]].iVertex;
		int i2 = Wedges[F.iWedge[2]].iVertex;		// note: reverse order in comparison with SkeletalMesh
		int i3 = Wedges[F.iWedge[1]].iVertex;
		// iterate all frames
		for (int j = 0; j < FrameCount; j++)
		{
			int base = VertexCount * j;
			// compute edges
			const CVec3 &V1 = tmpVerts[base + i1];
			const CVec3 &V2 = tmpVerts[base + i2];
			const CVec3 &V3 = tmpVerts[base + i3];
			CVec3 D1, D2, D3;
			VectorSubtract(V2, V1, D1);
			VectorSubtract(V3, V2, D2);
			VectorSubtract(V1, V3, D3);
			// compute normal
			CVec3 norm;
			cross(D2, D1, norm);
			norm.Normalize();
			// compute angles
			D1.Normalize();
			D2.Normalize();
			D3.Normalize();
			float angle1 = acos(-dot(D1, D3));
			float angle2 = acos(-dot(D1, D2));
			float angle3 = acos(-dot(D2, D3));
			// add normals for triangle verts
			VectorMA(tmpNormals[base + i1], angle1, norm);
			VectorMA(tmpNormals[base + i2], angle2, norm);
			VectorMA(tmpNormals[base + i3], angle3, norm);
		}
	}
	// normalize and convert computed normals
	for (i = 0; i < numVerts; i++)
	{
		CVec3 &SN     = tmpNormals[i];
		FMeshNorm &DN = Normals[i];
		SN.Normalize();
		DN.X = appRound(SN[0] * 511 + 512);
		DN.Y = appRound(SN[1] * 511 + 512);
		DN.Z = appRound(SN[2] * 511 + 512);
	}
}
Exemple #3
0
static void SV_ClipMoveToEntities(trace_t &trace, const CVec3 &start, const CVec3 &end, const CBox &bounds, edict_t *passedict, int contentmask)
{
	guard(SV_ClipMoveToEntities);

	if (trace.allsolid) return;

	int		i;

	CVec3 amins, amaxs;
	for (i = 0; i < 3; i++)
	{
		if (start[i] < end[i])
		{
			amins[i] = bounds.mins[i] + start[i];
			amaxs[i] = bounds.maxs[i] + end[i];
		}
		else
		{
			amins[i] = bounds.mins[i] + end[i];
			amaxs[i] = bounds.maxs[i] + start[i];
		}
	}
	edict_t	*list[MAX_EDICTS];
	int num = SV_AreaEdicts(amins, amaxs, ARRAY_ARG(list), AREA_SOLID);
	if (!num) return;

	float b1 = dot(bounds.mins, bounds.mins);
	float b2 = dot(bounds.maxs, bounds.maxs);
	float t = max(b1, b2);
	float traceWidth = SQRTFAST(t);
	CVec3 traceDir;
	VectorSubtract(end, start, traceDir);
	float traceLen = traceDir.Normalize() + traceWidth;

	for (i = 0; i < num; i++)
	{
		edict_t *edict = list[i];
		entityHull_t &ent = ents[NUM_FOR_EDICT(edict)];
//		if (!ent->linked) continue;

		if (edict->solid == SOLID_NOT || edict == passedict) continue;
		if (passedict)
		{
		 	if (edict->owner == passedict)
				continue;	// don't clip against own missiles
			if (passedict->owner == edict)
				continue;	// don't clip against owner
		}
		if (!(contentmask & CONTENTS_DEADMONSTER) && (edict->svflags & SVF_DEADMONSTER))
			continue;

		CVec3 eCenter;
		VectorSubtract(ent.center, start, eCenter);
		// check position of point projection on line
		float entPos = dot(eCenter, traceDir);
		if (entPos < -traceWidth - ent.radius || entPos > traceLen + ent.radius)
			continue;		// too near / too far

		// check distance between point and line
		CVec3 tmp;
		VectorMA(eCenter, -entPos, traceDir, tmp);
		float dist2 = dot(tmp, tmp);
		float dist0 = ent.radius + traceWidth;
		if (dist2 >= dist0 * dist0) continue;

		trace_t	tr;
		if (ent.model)
			CM_TransformedBoxTrace(tr, start, end, bounds, ent.model->headnode, contentmask, edict->s.origin, ent.axis);
		else
			CM_TransformedBoxTrace(tr, start, end, bounds, CM_HeadnodeForBox(ent.bounds), contentmask, edict->s.origin, nullVec3);
		if (CM_CombineTrace(trace, tr))
			trace.ent = edict;
		if (trace.allsolid) return;
	}

	unguard;
}
Exemple #4
0
///////////////////////////////////////////////////////////////////////////////
//		_Create_caustic_photonmap
// Build the caustic photon map after the creation of global photon map
///////////////////////////////////////////////////////////////////////////////
void CMcBspTR::_Create_caustic_photonmap(void)
{
	int     i, j;
	CCol4   cCurrPow;
	int     nStored = 0;
	TBspRay ray;
	float   fLen;

	printf("\nBuilding caustic photon map ...\n");

	TCausDir *p = m_tCausDir.next;

	for (i = 0; i < m_nCausDir; i ++)
	{
		printf (".");
		CCol4 cPow = m_tpLigPatches[p->nLID].cPhotonPow / m_nCauPhoSubd * 5;

		if (m_bDirectionalLight)
		{
			CBspTriangle *tri = &m_pTriangles[m_tpLigPatches[p->nLID].nTID];
			fLen = sqrt(tri->Calc_area() / m_tpLigPatches[p->nLID].nPhotonNum);
			CVec3 vZ = tri->Calc_normal();
			CVec3 vY = RANDOM_VEC;
			CVec3 vX = vY.Cross(vZ);
			vX.Normalize();
			vY = vZ.Cross(vX);

			vX *= fLen;
			vY *= fLen;

			for (j = 0; j < m_nCauPhoSubd; j ++)
			{
				ray.vOrg = p->vPos + vX * RANDOM_N1_P1 + vY * RANDOM_N1_P1;
				ray.vDir = p->vDir;
				ray.vEnd = ray.vOrg + ray.vDir * m_fSceneSize;
				_Trace_caustic_photon (ray, cPow, m_tpLigPatches[p->nLID].nTID,
					nStored);
			}
		}
		else
		{
			double fCos = cos(PI/sqrt(m_tpLigPatches[p->nLID].nPhotonNum*4.));
			fLen = 2.f * (float) tan( acos(fCos) );

			for (j = 0; j < m_nCauPhoSubd; j ++)
			{
				ray.vOrg = p->vPos;
				ray.vDir = p->vDir + (RANDOM_VEC * fLen);
				ray.vDir.Normalize();
				ray.vEnd = ray.vOrg + ray.vDir * m_fSceneSize;
				_Trace_caustic_photon (ray, cPow, m_tpLigPatches[p->nLID].nTID,
					nStored);
			}
		}
		
		m_tCausDir.next = p->next;
		delete p;
		p = m_tCausDir.next;
	}
	m_tCausDir.next = NULL;

	// Balance photon map kd-tree
	printf("\n Balance KD tree");
	m_pCausticPhotonMap->balance();
	printf("\nFinish building caustic photon map, %d photons stored\n", nStored);
}