Пример #1
0
//
// Look at the sloped edges to see if they meet at a particular point;
// if so, set that as the Level's story height.  Return true on success.
//
bool vtLevel::DetermineHeightFromSlopes()
{
	// In order to find a roof point, we need 3 adjacent edges whose
	// edges intersect.
	int i, edges = NumEdges();

	bool bFoundASolution = false;
	FPlane *planes = new FPlane[edges];
	float fMinHeight = 1E10;
	for (i = 0; i < edges; i++)
	{
		GetEdgePlane(i, planes[i]);
	}
	for (i = 0; i < edges; i++)
	{
		int i0 = i;
		int i1 = (i+1)%edges;
		int i2 = (i+2)%edges;
		vtEdge *edge0 = m_Edges[i0];
		vtEdge *edge1 = m_Edges[i1];
		vtEdge *edge2 = m_Edges[i2];
		if (edge0->m_iSlope == 90 &&
			edge1->m_iSlope == 90 &&
			edge2->m_iSlope == 90)
		{
			// skip this one; 3 vertical edges aren't useful
			continue;
		}
		FPoint3 point;
		bool valid = PlaneIntersection(planes[i0], planes[i1], planes[i2], point);
		if (valid)
		{
			// take this point as the height of the roof
			float fHeight = (point.y - m_LocalFootprint[0][0].y);

			if (fHeight < 0)	// shouldn't happen, but just a safety check
				continue;

			if (fHeight < fMinHeight)
				fMinHeight = fHeight;
			bFoundASolution = true;
		}
	}
	if (bFoundASolution)
		m_fStoryHeight = fMinHeight;
	delete [] planes;
	return bFoundASolution;
}
Пример #2
0
Frustum::Frustum( const SMatrix4x4& matrix )
{
	//  build a view frustum based on the current view & projection matrices...
	SVector4 column4( matrix._14, matrix._24, matrix._34, matrix._44 );
	SVector4 column1( matrix._11, matrix._21, matrix._31, matrix._41 );
	SVector4 column2( matrix._12, matrix._22, matrix._32, matrix._42 );
	SVector4 column3( matrix._13, matrix._23, matrix._33, matrix._43 );

	SVector4 planes[6];
	planes[0] = column4 - column1;  // left
	planes[1] = column4 + column1;  // right
	planes[2] = column4 - column2;  // bottom
	planes[3] = column4 + column2;  // top
	planes[4] = column4 - column3;  // near
	planes[5] = column4 + column3;  // far

	int p;

	for (p=0; p<6; p++)  // normalize the planes
	{
		float dot = planes[p].x*planes[p].x + planes[p].y*planes[p].y + planes[p].z*planes[p].z;
		dot = 1.0f / sqrtf(dot);
		planes[p] = planes[p] * dot;
	}

	for (p=0; p<6; p++)
		camPlanes[p] = SPlane( planes[p].x, planes[p].y, planes[p].z, planes[p].w );

	//  build a bit-field that will tell us the indices for the nearest and farthest vertices from each plane...
	for (int i=0; i<6; i++)
		nVertexLUT[i] = ((planes[i].x<0.f)?1:0) | ((planes[i].y<0.f)?2:0) | ((planes[i].z<0.f)?4:0);

	for( int i=0; i<8; ++i ) // compute extrema
	{
		const SPlane& p0 = (i&1)?camPlanes[4] : camPlanes[5];
		const SPlane& p1 = (i&2)?camPlanes[3] : camPlanes[2];
		const SPlane& p2 = (i&4)?camPlanes[0] : camPlanes[1];

		PlaneIntersection( &pntList[i], p0, p1, p2 );
	}
}
//-----------------------------------------------------------------------------
// Copies the texture coordinate system from pFrom into pTo. Then it rotates 
// the texture around the edge until it's as close to pTo's normal as possible.
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::CopyTCoordSystem( const CMapFace *pFrom, CMapFace *pTo )
{
	Vector		axis[2], vEdge, vEdgePt, vOrigin;
	Vector		vFromPt, vNextFromPt;
	Vector		vToPt, vPrevToPt;
	Vector		vTestTextureNormal, vTextureNormal;
	VMatrix		mEdgeRotation, mOriginRotation, mTranslation;
	float		fAngle, fDot;
	bool		bRotate;
	float		fShift[2];
	Vector		vProjTexNormal;
	Vector		vProjPolyNormal;

	// The edge vector lies on both planes.
	vEdge = pFrom->plane.normal.Cross(pTo->plane.normal);
	VectorNormalize( vEdge );

	// To find a point on the plane, we make a plane from the edge vector and find the intersection
	// between the three planes (without the third plane, there are an infinite number of solutions).
	if( PlaneIntersection( VPlane(pFrom->plane.normal, pFrom->plane.dist),
		                   VPlane(pTo->plane.normal, pTo->plane.dist),
		                   VPlane(vEdge, 0.0f), vEdgePt ) )
	{
		bRotate = true;
	}
	else
	{
		// Ok, in this case, the planes are parallel so we don't need to rotate around the edge anyway!
		bRotate = false;
	}

	// Copy the texture coordinate system.
	axis[0] = pFrom->texture.UAxis.AsVector3D();
	axis[1] = pFrom->texture.VAxis.AsVector3D();
	fShift[0] = pFrom->texture.UAxis[3];
	fShift[1] = pFrom->texture.VAxis[3];
	vOrigin = axis[0]*fShift[0]*pFrom->texture.scale[0] + axis[1]*fShift[1]*pFrom->texture.scale[1];
	
	vTextureNormal = axis[0].Cross(axis[1]);
	VectorNormalize(vTextureNormal);
	if(bRotate)
	{
		// Project texture normal and poly normal into the plane of rotation
		// to get the angle between them.
		vProjTexNormal = vTextureNormal - vEdge * vEdge.Dot(vTextureNormal);
		vProjPolyNormal = pTo->plane.normal - vEdge * vEdge.Dot(pTo->plane.normal);

		VectorNormalize( vProjTexNormal );
		VectorNormalize( vProjPolyNormal );

		fDot = vProjTexNormal.Dot(vProjPolyNormal);
		fAngle = (float)(acos(fDot) * (180.0f / M_PI));
		if(fDot < 0.0f)
			fAngle = 180.0f - fAngle;

		// Ok, rotate them for the final values.
		mEdgeRotation = SetupMatrixAxisRot(vEdge, fAngle);
		axis[0] = mEdgeRotation.ApplyRotation(axis[0]);
		axis[1] = mEdgeRotation.ApplyRotation(axis[1]);

		// Origin needs translation and rotation to rotate around the edge.
		mTranslation = SetupMatrixTranslation(vEdgePt);
		mOriginRotation = ~mTranslation * mEdgeRotation * mTranslation;
		vOrigin = mOriginRotation * vOrigin;
	}

	pTo->texture.UAxis.AsVector3D() = axis[0];
	pTo->texture.VAxis.AsVector3D() = axis[1];

	pTo->texture.UAxis[3] = axis[0].Dot(vOrigin) / pFrom->texture.scale[0];
	pTo->texture.VAxis[3] = axis[1].Dot(vOrigin) / pFrom->texture.scale[1];
	pTo->NormalizeTextureShifts();

	pTo->texture.scale[0] = pFrom->texture.scale[0];
	pTo->texture.scale[1] = pFrom->texture.scale[1];

	// rotate is only for UI purposes, it doesn't actually do anything.
	pTo->texture.rotate = 0.0f;

	pTo->CalcTextureCoords();
}