예제 #1
0
/*
============
idClip::GetModelContactFeature
============
*/
bool idClip::GetModelContactFeature( const contactInfo_t &contact, const idClipModel *clipModel, idFixedWinding &winding ) const {
	int i;
	cmHandle_t handle;
	idVec3 start, end;

	handle = -1;
	winding.Clear();

	if ( clipModel == NULL ) {
		handle = 0;
	} else {
		if ( clipModel->renderModelHandle != -1 ) {
			winding += contact.point;
			return true;
		} else if ( clipModel->traceModelIndex != -1 ) {
			handle = collisionModelManager->SetupTrmModel( *idClipModel::GetCachedTraceModel( clipModel->traceModelIndex ), clipModel->material );
		} else {
			handle = clipModel->collisionModelHandle;
		}
	}

	// if contact with a collision model
	if ( handle != -1 ) {
		switch( contact.type ) {
			case CONTACT_EDGE: {
				// the model contact feature is a collision model edge
				collisionModelManager->GetModelEdge( handle, contact.modelFeature, start, end );
				winding += start;
				winding += end;
				break;
			}
			case CONTACT_MODELVERTEX: {
				// the model contact feature is a collision model vertex
				collisionModelManager->GetModelVertex( handle, contact.modelFeature, start );
				winding += start;
				break;
			}
			case CONTACT_TRMVERTEX: {
				// the model contact feature is a collision model polygon
				collisionModelManager->GetModelPolygon( handle, contact.modelFeature, winding );
				break;
			}
		}
	}

	// transform the winding to world space
	if ( clipModel ) {
		for ( i = 0; i < winding.GetNumPoints(); i++ ) {
			winding[i].ToVec3() *= clipModel->axis;
			winding[i].ToVec3() += clipModel->origin;
		}
	}

	return true;
}
/*
================
idBrittleFracture::Fracture_r
================
*/
void idBrittleFracture::Fracture_r( idFixedWinding &w ) {
	int i, j, bestPlane;
	float a, c, s, dist, bestDist;
	idVec3 origin;
	idPlane windingPlane, splitPlanes[2];
	idMat3 axis, axistemp;
	idFixedWinding back;
	idTraceModel trm;
	idClipModel *clipModel;
	while( 1 ) {
		origin = w.GetCenter();
		w.GetPlane( windingPlane );
		if( w.GetArea() < maxShardArea ) {
			break;
		}
		// randomly create a split plane
		a = gameLocal.random.RandomFloat() * idMath::TWO_PI;
		c = cos( a );
		s = -sin( a );
		axis[2] = windingPlane.Normal();
		axis[2].NormalVectors( axistemp[0], axistemp[1] );
		axis[0] = axistemp[ 0 ] * c + axistemp[ 1 ] * s;
		axis[1] = axistemp[ 0 ] * s + axistemp[ 1 ] * -c;
		// get the best split plane
		bestDist = 0.0f;
		bestPlane = 0;
		for( i = 0; i < 2; i++ ) {
			splitPlanes[i].SetNormal( axis[i] );
			splitPlanes[i].FitThroughPoint( origin );
			for( j = 0; j < w.GetNumPoints(); j++ ) {
				dist = splitPlanes[i].Distance( w[j].ToVec3() );
				if( dist > bestDist ) {
					bestDist = dist;
					bestPlane = i;
				}
			}
		}
		// split the winding
		if( !w.Split( &back, splitPlanes[bestPlane] ) ) {
			break;
		}
		// recursively create shards for the back winding
		Fracture_r( back );
	}
	// translate the winding to it's center
	origin = w.GetCenter();
	for( j = 0; j < w.GetNumPoints(); j++ ) {
		w[j].ToVec3() -= origin;
	}
	w.RemoveEqualPoints();
	trm.SetupPolygon( w );
	trm.Shrink( CM_CLIP_EPSILON );
	clipModel = new idClipModel( trm );
	physicsObj.SetClipModel( clipModel, 1.0f, shards.Num() );
	physicsObj.SetOrigin( GetPhysics()->GetOrigin() + origin, shards.Num() );
	physicsObj.SetAxis( GetPhysics()->GetAxis(), shards.Num() );
	AddShard( clipModel, w );
}
예제 #3
0
/*
================
idBrittleFracture::AddShard
================
*/
void idBrittleFracture::AddShard( idClipModel *clipModel, idFixedWinding &w ) {
	shard_t *shard = new shard_t;
	shard->clipModel = clipModel;
	shard->droppedTime = -1;
	shard->winding = w;
	shard->decals.Clear();
	shard->edgeHasNeighbour.AssureSize( w.GetNumPoints(), false );
	shard->neighbours.Clear();
	shard->atEdge = false;
	shards.Append( shard );
}
/*
=================
idRenderModelDecal::CreateProjectionInfo
=================
*/
bool idRenderModelDecal::CreateProjectionInfo( decalProjectionInfo_t &info, const idFixedWinding &winding, const idVec3 &projectionOrigin, const bool parallel, const float fadeDepth, const idMaterial *material, const int startTime ) {
	if( winding.GetNumPoints() != NUM_DECAL_BOUNDING_PLANES - 2 ) {
		common->Printf( "idRenderModelDecal::CreateProjectionInfo: winding must have %d points\n", NUM_DECAL_BOUNDING_PLANES - 2 );
		return false;
	}
	assert( material != NULL );
	info.projectionOrigin = projectionOrigin;
	info.material = material;
	info.parallel = parallel;
	info.fadeDepth = fadeDepth;
	info.startTime = startTime;
	info.force = false;
	// get the winding plane and the depth of the projection volume
	idPlane windingPlane;
	winding.GetPlane( windingPlane );
	float depth = windingPlane.Distance( projectionOrigin );
	// find the bounds for the projection
	winding.GetBounds( info.projectionBounds );
	if( parallel ) {
		info.projectionBounds.ExpandSelf( depth );
	} else {
		info.projectionBounds.AddPoint( projectionOrigin );
	}
	// calculate the world space projection volume bounding planes, positive sides face outside the decal
	if( parallel ) {
		for( int i = 0; i < winding.GetNumPoints(); i++ ) {
			idVec3 edge = winding[( i + 1 ) % winding.GetNumPoints()].ToVec3() - winding[i].ToVec3();
			info.boundingPlanes[i].Normal().Cross( windingPlane.Normal(), edge );
			info.boundingPlanes[i].Normalize();
			info.boundingPlanes[i].FitThroughPoint( winding[i].ToVec3() );
		}
	} else {
		for( int i = 0; i < winding.GetNumPoints(); i++ ) {
			info.boundingPlanes[i].FromPoints( projectionOrigin, winding[i].ToVec3(), winding[( i + 1 ) % winding.GetNumPoints()].ToVec3() );
		}
	}
	info.boundingPlanes[NUM_DECAL_BOUNDING_PLANES - 2] = windingPlane;
	info.boundingPlanes[NUM_DECAL_BOUNDING_PLANES - 2][3] -= depth;
	info.boundingPlanes[NUM_DECAL_BOUNDING_PLANES - 1] = -windingPlane;
	// fades will be from these plane
	info.fadePlanes[0] = windingPlane;
	info.fadePlanes[0][3] -= fadeDepth;
	info.fadePlanes[1] = -windingPlane;
	info.fadePlanes[1][3] += depth - fadeDepth;
	// calculate the texture vectors for the winding
	float	len, texArea, inva;
	idVec3	temp;
	idVec5	d0, d1;
	const idVec5 &a = winding[0];
	const idVec5 &b = winding[1];
	const idVec5 &c = winding[2];
	d0 = b.ToVec3() - a.ToVec3();
	d0.s = b.s - a.s;
	d0.t = b.t - a.t;
	d1 = c.ToVec3() - a.ToVec3();
	d1.s = c.s - a.s;
	d1.t = c.t - a.t;
	texArea = ( d0[3] * d1[4] ) - ( d0[4] * d1[3] );
	inva = 1.0f / texArea;
	temp[0] = ( d0[0] * d1[4] - d0[4] * d1[0] ) * inva;
	temp[1] = ( d0[1] * d1[4] - d0[4] * d1[1] ) * inva;
	temp[2] = ( d0[2] * d1[4] - d0[4] * d1[2] ) * inva;
	len = temp.Normalize();
	info.textureAxis[0].Normal() = temp * ( 1.0f / len );
	info.textureAxis[0][3] = winding[0].s - ( winding[0].ToVec3() * info.textureAxis[0].Normal() );
	temp[0] = ( d0[3] * d1[0] - d0[0] * d1[3] ) * inva;
	temp[1] = ( d0[3] * d1[1] - d0[1] * d1[3] ) * inva;
	temp[2] = ( d0[3] * d1[2] - d0[2] * d1[3] ) * inva;
	len = temp.Normalize();
	info.textureAxis[1].Normal() = temp * ( 1.0f / len );
	info.textureAxis[1][3] = winding[0].t - ( winding[0].ToVec3() * info.textureAxis[1].Normal() );
	return true;
}