/* ============ idBox::GetParallelProjectionSilhouetteVerts ============ */ int idBox::GetParallelProjectionSilhouetteVerts( const idVec3& projectionDir, idVec3 silVerts[6] ) const { float f; int i, planeBits, *index; idVec3 points[8]; ToPoints( points ); planeBits = 0; f = projectionDir * axis[0]; if( IEEE_FLT_ISNOTZERO( f ) ) { planeBits = 1 << IEEE_FLT_SIGNBITSET( f ); } f = projectionDir * axis[1]; if( IEEE_FLT_ISNOTZERO( f ) ) { planeBits |= 4 << IEEE_FLT_SIGNBITSET( f ); } f = projectionDir * axis[2]; if( IEEE_FLT_ISNOTZERO( f ) ) { planeBits |= 16 << IEEE_FLT_SIGNBITSET( f ); } index = boxPlaneBitsSilVerts[planeBits]; for( i = 0; i < index[0]; i++ ) { silVerts[i] = points[index[i + 1]]; } return index[0]; }
/* ============= idWinding2D::PlaneDistance ============= */ float idWinding2D::PlaneDistance( const idVec3 &plane ) const { int i; float d, min, max; min = idMath::INFINITY; max = -min; for ( i = 0; i < numPoints; i++ ) { d = plane.x * p[i].x + plane.y * p[i].y + plane.z; if ( d < min ) { min = d; if ( IEEE_FLT_SIGNBITSET( min ) & IEEE_FLT_SIGNBITNOTSET( max ) ) { return 0.0f; } } if ( d > max ) { max = d; if ( IEEE_FLT_SIGNBITSET( min ) & IEEE_FLT_SIGNBITNOTSET( max ) ) { return 0.0f; } } } if ( IEEE_FLT_SIGNBITNOTSET( min ) ) { return min; } if ( IEEE_FLT_SIGNBITSET( max ) ) { return max; } return 0.0f; }
/* ============ idBox::GetProjectionSilhouetteVerts ============ */ int idBox::GetProjectionSilhouetteVerts( const idVec3& projectionOrigin, idVec3 silVerts[6] ) const { float f; int i, planeBits, *index; idVec3 points[8], dir1, dir2; ToPoints( points ); dir1 = points[0] - projectionOrigin; dir2 = points[6] - projectionOrigin; f = dir1 * axis[0]; planeBits = IEEE_FLT_SIGNBITNOTSET( f ); f = dir2 * axis[0]; planeBits |= IEEE_FLT_SIGNBITSET( f ) << 1; f = dir1 * axis[1]; planeBits |= IEEE_FLT_SIGNBITNOTSET( f ) << 2; f = dir2 * axis[1]; planeBits |= IEEE_FLT_SIGNBITSET( f ) << 3; f = dir1 * axis[2]; planeBits |= IEEE_FLT_SIGNBITNOTSET( f ) << 4; f = dir2 * axis[2]; planeBits |= IEEE_FLT_SIGNBITSET( f ) << 5; index = boxPlaneBitsSilVerts[planeBits]; for( i = 0; i < index[0]; i++ ) { silVerts[i] = points[index[i + 1]]; } return index[0]; }
/* ============ idAASLocal::EdgeSplitPoint calculates split point of the edge with the plane returns true if the split point is between the edge vertices ============ */ bool idAASLocal::EdgeSplitPoint( idVec3 &split, int edgeNum, const idPlane &plane ) const { const aasEdge_t *edge; idVec3 v1, v2; float d1, d2; edge = &file->GetEdge( edgeNum ); v1 = file->GetVertex( edge->vertexNum[0] ); v2 = file->GetVertex( edge->vertexNum[1] ); d1 = v1 * plane.Normal() - plane.Dist(); d2 = v2 * plane.Normal() - plane.Dist(); //if ( (d1 < CM_CLIP_EPSILON && d2 < CM_CLIP_EPSILON) || (d1 > -CM_CLIP_EPSILON && d2 > -CM_CLIP_EPSILON) ) { if ( IEEE_FLT_SIGNBITSET( d1 ) == IEEE_FLT_SIGNBITSET( d2 ) ) { return false; } split = v1 + (d1 / (d1 - d2)) * (v2 - v1); return true; }
/* ============ GetAxialBevel ============ */ bool GetAxialBevel( const idVec3 &plane1, const idVec3 &plane2, const idVec2 &point, idVec3 &bevel ) { if ( IEEE_FLT_SIGNBITSET( plane1.x ) ^ IEEE_FLT_SIGNBITSET( plane2.x ) ) { if ( idMath::Fabs( plane1.x ) > 0.1f && idMath::Fabs( plane2.x ) > 0.1f ) { bevel.x = 0.0f; if ( IEEE_FLT_SIGNBITSET( plane1.y ) ) { bevel.y = -1.0f; } else { bevel.y = 1.0f; } bevel.z = - ( point.x * bevel.x + point.y * bevel.y ); return true; } } if ( IEEE_FLT_SIGNBITSET( plane1.y ) ^ IEEE_FLT_SIGNBITSET( plane2.y ) ) { if ( idMath::Fabs( plane1.y ) > 0.1f && idMath::Fabs( plane2.y ) > 0.1f ) { bevel.y = 0.0f; if ( IEEE_FLT_SIGNBITSET( plane1.x ) ) { bevel.x = -1.0f; } else { bevel.x = 1.0f; } bevel.z = - ( point.x * bevel.x + point.y * bevel.y ); return true; } } return false; }
/* ============ idWinding2D::ExpandForAxialBox ============ */ void idWinding2D::ExpandForAxialBox( const idVec2 bounds[2] ) { int i, j, numPlanes; idVec2 v; idVec3 planes[MAX_POINTS_ON_WINDING_2D], plane, bevel; // get planes for the edges and add bevels for ( numPlanes = i = 0; i < numPoints; i++ ) { j = (i+1) % numPoints; if ( ( p[j] - p[i] ).LengthSqr() < 0.01f ) { continue; } plane = Plane2DFromPoints( p[i], p[j], true ); if ( i ) { if ( GetAxialBevel( planes[numPlanes-1], plane, p[i], bevel ) ) { planes[numPlanes++] = bevel; } } assert( numPlanes < MAX_POINTS_ON_WINDING_2D ); planes[numPlanes++] = plane; } assert( numPlanes < MAX_POINTS_ON_WINDING_2D && numPlanes > 0 ); if ( GetAxialBevel( planes[numPlanes-1], planes[0], p[0], bevel ) ) { planes[numPlanes++] = bevel; } // expand the planes for ( i = 0; i < numPlanes; i++ ) { v.x = bounds[ IEEE_FLT_SIGNBITSET( planes[i].x ) ].x; v.y = bounds[ IEEE_FLT_SIGNBITSET( planes[i].y ) ].y; planes[i].z += v.x * planes[i].x + v.y * planes[i].y; } // get intersection points of the planes for ( numPoints = i = 0; i < numPlanes; i++ ) { if ( Plane2DIntersection( planes[(i+numPlanes-1) % numPlanes], planes[i], p[numPoints] ) ) { numPoints++; } } }
/* ================ idBrittleFracture::ProjectDecal ================ */ void idBrittleFracture::ProjectDecal( const idVec3& point, const idVec3& dir, const int time, const char* damageDefName ) { int i, j, bits, clipBits; float a, c, s; idVec2 st[MAX_POINTS_ON_WINDING]; idVec3 origin; idMat3 axis, axistemp; idPlane textureAxis[2]; if( common->IsServer() ) { idBitMsg msg; byte msgBuf[MAX_EVENT_PARAM_SIZE]; msg.InitWrite( msgBuf, sizeof( msgBuf ) ); msg.BeginWriting(); msg.WriteFloat( point[0] ); msg.WriteFloat( point[1] ); msg.WriteFloat( point[2] ); msg.WriteFloat( dir[0] ); msg.WriteFloat( dir[1] ); msg.WriteFloat( dir[2] ); ServerSendEvent( EVENT_PROJECT_DECAL, &msg, true ); } // store the event so we can rebuilt the fracture after loading a save fractureEvent_s fractureEvent; fractureEvent.eventType = EVENT_PROJECT_DECAL; fractureEvent.point = point; fractureEvent.vector = dir; storedEvents.Append( fractureEvent ); if( time >= gameLocal.time ) { // try to get the sound from the damage def const idDeclEntityDef* damageDef = NULL; const idSoundShader* sndShader = NULL; if( damageDefName ) { damageDef = gameLocal.FindEntityDef( damageDefName, false ); if( damageDef ) { const char* sndName = damageDef->dict.GetString( "snd_shatter", "" ); if( sndName[0] != 0 ) { sndShader = declManager->FindSound( sndName ); } } } if( sndShader ) { StartSoundShader( sndShader, SND_CHANNEL_ANY, 0, false, NULL ); } else { StartSound( "snd_bullethole", SND_CHANNEL_ANY, 0, false, NULL ); } } a = gameLocal.random.RandomFloat() * idMath::TWO_PI; c = cos( a ); s = -sin( a ); axis[2] = -dir; axis[2].Normalize(); axis[2].NormalVectors( axistemp[0], axistemp[1] ); axis[0] = axistemp[ 0 ] * c + axistemp[ 1 ] * s; axis[1] = axistemp[ 0 ] * s + axistemp[ 1 ] * -c; textureAxis[0] = axis[0] * ( 1.0f / decalSize ); textureAxis[0][3] = -( point * textureAxis[0].Normal() ) + 0.5f; textureAxis[1] = axis[1] * ( 1.0f / decalSize ); textureAxis[1][3] = -( point * textureAxis[1].Normal() ) + 0.5f; for( i = 0; i < shards.Num(); i++ ) { idFixedWinding& winding = shards[i]->winding; origin = shards[i]->clipModel->GetOrigin(); axis = shards[i]->clipModel->GetAxis(); float d0, d1; clipBits = -1; for( j = 0; j < winding.GetNumPoints(); j++ ) { idVec3 p = origin + winding[j].ToVec3() * axis; st[j].x = d0 = textureAxis[0].Distance( p ); st[j].y = d1 = textureAxis[1].Distance( p ); bits = IEEE_FLT_SIGNBITSET( d0 ); d0 = 1.0f - d0; bits |= IEEE_FLT_SIGNBITSET( d1 ) << 2; d1 = 1.0f - d1; bits |= IEEE_FLT_SIGNBITSET( d0 ) << 1; bits |= IEEE_FLT_SIGNBITSET( d1 ) << 3; clipBits &= bits; } if( clipBits ) { continue; } idFixedWinding* decal = new( TAG_PARTICLE ) idFixedWinding; shards[i]->decals.Append( decal ); decal->SetNumPoints( winding.GetNumPoints() ); for( j = 0; j < winding.GetNumPoints(); j++ ) { ( *decal )[j].ToVec3() = winding[j].ToVec3(); ( *decal )[j].s = st[j].x; ( *decal )[j].t = st[j].y; } } BecomeActive( TH_UPDATEVISUALS ); }
/* ================= idSurface::Split ================= */ int idSurface::Split( const idPlane& plane, const float epsilon, idSurface** front, idSurface** back, int* frontOnPlaneEdges, int* backOnPlaneEdges ) const { float* dists; float f; byte* sides; int counts[3]; int* edgeSplitVertex; int numEdgeSplitVertexes; int* vertexRemap[2]; int vertexIndexNum[2][2]; int* vertexCopyIndex[2]; int* indexPtr[2]; int indexNum[2]; int* index; int* onPlaneEdges[2]; int numOnPlaneEdges[2]; int maxOnPlaneEdges; int i; idSurface* surface[2]; idDrawVert v; dists = ( float* ) _alloca( verts.Num() * sizeof( float ) ); sides = ( byte* ) _alloca( verts.Num() * sizeof( byte ) ); counts[0] = counts[1] = counts[2] = 0; // determine side for each vertex for( i = 0; i < verts.Num(); i++ ) { dists[i] = f = plane.Distance( verts[i].xyz ); if( f > epsilon ) { sides[i] = SIDE_FRONT; } else if( f < -epsilon ) { sides[i] = SIDE_BACK; } else { sides[i] = SIDE_ON; } counts[sides[i]]++; } *front = *back = NULL; // if coplanar, put on the front side if the normals match if( !counts[SIDE_FRONT] && !counts[SIDE_BACK] ) { f = ( verts[indexes[1]].xyz - verts[indexes[0]].xyz ).Cross( verts[indexes[0]].xyz - verts[indexes[2]].xyz ) * plane.Normal(); if( IEEE_FLT_SIGNBITSET( f ) ) { *back = new( TAG_IDLIB_SURFACE ) idSurface( *this ); return SIDE_BACK; } else { *front = new( TAG_IDLIB_SURFACE ) idSurface( *this ); return SIDE_FRONT; } } // if nothing at the front of the clipping plane if( !counts[SIDE_FRONT] ) { *back = new( TAG_IDLIB_SURFACE ) idSurface( *this ); return SIDE_BACK; } // if nothing at the back of the clipping plane if( !counts[SIDE_BACK] ) { *front = new( TAG_IDLIB_SURFACE ) idSurface( *this ); return SIDE_FRONT; } // allocate front and back surface *front = surface[0] = new( TAG_IDLIB_SURFACE ) idSurface(); *back = surface[1] = new( TAG_IDLIB_SURFACE ) idSurface(); edgeSplitVertex = ( int* ) _alloca( edges.Num() * sizeof( int ) ); numEdgeSplitVertexes = 0; maxOnPlaneEdges = 4 * counts[SIDE_ON]; counts[SIDE_FRONT] = counts[SIDE_BACK] = counts[SIDE_ON] = 0; // split edges for( i = 0; i < edges.Num(); i++ ) { int v0 = edges[i].verts[0]; int v1 = edges[i].verts[1]; int sidesOr = ( sides[v0] | sides[v1] ); // if both vertexes are on the same side or one is on the clipping plane if( !( sides[v0] ^ sides[v1] ) || ( sidesOr & SIDE_ON ) ) { edgeSplitVertex[i] = -1; counts[sidesOr & SIDE_BACK]++; counts[SIDE_ON] += ( sidesOr & SIDE_ON ) >> 1; } else {
/* ==================== R_OverlayPointCullSkinned ==================== */ static void R_OverlayPointCullSkinned( byte* cullBits, halfFloat_t* texCoordS, halfFloat_t* texCoordT, const idPlane* planes, const idDrawVert* verts, const int numVerts, const idJointMat* joints ) { assert_16_byte_aligned( cullBits ); assert_16_byte_aligned( texCoordS ); assert_16_byte_aligned( texCoordT ); assert_16_byte_aligned( verts ); #if defined(USE_INTRINSICS) idODSStreamedArray< idDrawVert, 16, SBT_DOUBLE, 4 > vertsODS( verts, numVerts ); const __m128 vector_float_zero = { 0.0f, 0.0f, 0.0f, 0.0f }; const __m128 vector_float_one = { 1.0f, 1.0f, 1.0f, 1.0f }; const __m128i vector_int_mask0 = _mm_set1_epi32( 1 << 0 ); const __m128i vector_int_mask1 = _mm_set1_epi32( 1 << 1 ); const __m128i vector_int_mask2 = _mm_set1_epi32( 1 << 2 ); const __m128i vector_int_mask3 = _mm_set1_epi32( 1 << 3 ); const __m128 p0 = _mm_loadu_ps( planes[0].ToFloatPtr() ); const __m128 p1 = _mm_loadu_ps( planes[1].ToFloatPtr() ); const __m128 p0X = _mm_splat_ps( p0, 0 ); const __m128 p0Y = _mm_splat_ps( p0, 1 ); const __m128 p0Z = _mm_splat_ps( p0, 2 ); const __m128 p0W = _mm_splat_ps( p0, 3 ); const __m128 p1X = _mm_splat_ps( p1, 0 ); const __m128 p1Y = _mm_splat_ps( p1, 1 ); const __m128 p1Z = _mm_splat_ps( p1, 2 ); const __m128 p1W = _mm_splat_ps( p1, 3 ); for( int i = 0; i < numVerts; ) { const int nextNumVerts = vertsODS.FetchNextBatch() - 4; for( ; i <= nextNumVerts; i += 4 ) { const __m128 v0 = LoadSkinnedDrawVertPosition( vertsODS[i + 0], joints ); const __m128 v1 = LoadSkinnedDrawVertPosition( vertsODS[i + 1], joints ); const __m128 v2 = LoadSkinnedDrawVertPosition( vertsODS[i + 2], joints ); const __m128 v3 = LoadSkinnedDrawVertPosition( vertsODS[i + 3], joints ); const __m128 r0 = _mm_unpacklo_ps( v0, v2 ); // v0.x, v2.x, v0.z, v2.z const __m128 r1 = _mm_unpackhi_ps( v0, v2 ); // v0.y, v2.y, v0.w, v2.w const __m128 r2 = _mm_unpacklo_ps( v1, v3 ); // v1.x, v3.x, v1.z, v3.z const __m128 r3 = _mm_unpackhi_ps( v1, v3 ); // v1.y, v3.y, v1.w, v3.w const __m128 vX = _mm_unpacklo_ps( r0, r2 ); // v0.x, v1.x, v2.x, v3.x const __m128 vY = _mm_unpackhi_ps( r0, r2 ); // v0.y, v1.y, v2.y, v3.y const __m128 vZ = _mm_unpacklo_ps( r1, r3 ); // v0.z, v1.z, v2.z, v3.z const __m128 d0 = _mm_madd_ps( vX, p0X, _mm_madd_ps( vY, p0Y, _mm_madd_ps( vZ, p0Z, p0W ) ) ); const __m128 d1 = _mm_madd_ps( vX, p1X, _mm_madd_ps( vY, p1Y, _mm_madd_ps( vZ, p1Z, p1W ) ) ); const __m128 d2 = _mm_sub_ps( vector_float_one, d0 ); const __m128 d3 = _mm_sub_ps( vector_float_one, d1 ); __m128i flt16S = FastF32toF16( __m128c( d0 ) ); __m128i flt16T = FastF32toF16( __m128c( d1 ) ); _mm_storel_epi64( ( __m128i* )&texCoordS[i], flt16S ); _mm_storel_epi64( ( __m128i* )&texCoordT[i], flt16T ); __m128i c0 = __m128c( _mm_cmplt_ps( d0, vector_float_zero ) ); __m128i c1 = __m128c( _mm_cmplt_ps( d1, vector_float_zero ) ); __m128i c2 = __m128c( _mm_cmplt_ps( d2, vector_float_zero ) ); __m128i c3 = __m128c( _mm_cmplt_ps( d3, vector_float_zero ) ); c0 = _mm_and_si128( c0, vector_int_mask0 ); c1 = _mm_and_si128( c1, vector_int_mask1 ); c2 = _mm_and_si128( c2, vector_int_mask2 ); c3 = _mm_and_si128( c3, vector_int_mask3 ); c0 = _mm_or_si128( c0, c1 ); c2 = _mm_or_si128( c2, c3 ); c0 = _mm_or_si128( c0, c2 ); c0 = _mm_packs_epi32( c0, c0 ); c0 = _mm_packus_epi16( c0, c0 ); *( unsigned int* )&cullBits[i] = _mm_cvtsi128_si32( c0 ); } } #else idODSStreamedArray< idDrawVert, 16, SBT_DOUBLE, 1 > vertsODS( verts, numVerts ); for( int i = 0; i < numVerts; ) { const int nextNumVerts = vertsODS.FetchNextBatch() - 1; for( ; i <= nextNumVerts; i++ ) { const idVec3 transformed = Scalar_LoadSkinnedDrawVertPosition( vertsODS[i], joints ); const float d0 = planes[0].Distance( transformed ); const float d1 = planes[1].Distance( transformed ); const float d2 = 1.0f - d0; const float d3 = 1.0f - d1; halfFloat_t s = Scalar_FastF32toF16( d0 ); halfFloat_t t = Scalar_FastF32toF16( d1 ); texCoordS[i] = s; texCoordT[i] = t; byte bits; bits = IEEE_FLT_SIGNBITSET( d0 ) << 0; bits |= IEEE_FLT_SIGNBITSET( d1 ) << 1; bits |= IEEE_FLT_SIGNBITSET( d2 ) << 2; bits |= IEEE_FLT_SIGNBITSET( d3 ) << 3; cullBits[i] = bits; } } #endif }