/* ============ 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 ); }
/* ================ 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; }