void DTerrain::SetEnvironment( const DProjector& ViewFrustum, float FogStart, float FogEnd, float LODStartFromFogStart, float LODEndFromFogStart ) { s_aOriginalViewPlane[0] = SPlane( ViewFrustum.m_plLeftPlane.a, ViewFrustum.m_plLeftPlane.b, ViewFrustum.m_plLeftPlane.c, -ViewFrustum.m_plLeftPlane.d ); s_aOriginalViewPlane[1] = SPlane( ViewFrustum.m_plRightPlane.a, ViewFrustum.m_plRightPlane.b, ViewFrustum.m_plRightPlane.c, -ViewFrustum.m_plRightPlane.d ); s_aOriginalViewPlane[2] = SPlane( ViewFrustum.m_plTopPlane.a, ViewFrustum.m_plTopPlane.b, ViewFrustum.m_plTopPlane.c, -ViewFrustum.m_plTopPlane.d ); s_aOriginalViewPlane[3] = SPlane( ViewFrustum.m_plBottomPlane.a, ViewFrustum.m_plBottomPlane.b, ViewFrustum.m_plBottomPlane.c, -ViewFrustum.m_plBottomPlane.d ); s_aOriginalViewPlane[4] = SPlane( SVector( 0.f, 0.f, ViewFrustum.Near() ), SVector( 0.f, 0.f, -1.f )); s_fFarCullDistance = FogEnd; s_fFarCullDistance *= s_fFarCullDistance; //hjk s_fDistOfNearPlane = ViewFrustum.Near(); s_fDistOfFarPlane = ViewFrustum.Far(); s_fFOV = ViewFrustum.Fov(); //hjk end }
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 ); } }
SCollisionResult CMovement::Trace( CArray<STriangle> &triangles, Vector3 start, Vector3 bboxMax, Vector3 boxdir[3], Vector3 displacement ) { float fraction = 1.0f; SCollisionResult trace, closest; float dist, mindist = 99999.0f; CArray<STriangle> colliding; ZeroMemory(&closest, sizeof(closest)); ZeroMemory(&trace, sizeof(trace)); // Find the collisions with the closest triangles for (int i=0; i<triangles.Size(); i++) { STriangle &t = triangles[i]; CArray<Vector3> vlist; vlist.AddToTail(t.v[0]); vlist.AddToTail(t.v[1]); vlist.AddToTail(t.v[2]); if ( CCollision::OBBPolygon( vlist, start, bboxMax, boxdir, displacement, OUT trace ) ) { if ( trace.fraction <= fraction + 0.1f ) { //if ( trace.fraction < fraction + 0.1f ) colliding.Clear(); // check if all points of our bbox are in front of the face SPlane plane = SPlane( t.v[0], t.v[1], t.v[2] ); Vector3 size = bboxMax * 2.0f; Vector3 min = start - bboxMax; Vector3 max = start + bboxMax; //Debug("collided: %f %f %f", plane.normal.x, plane.normal.y, plane.normal.z); if ( plane.GetSide( min, OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( max, OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( min + Vector3( size.x, 0, 0 ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( min + Vector3( 0, size.y, 0 ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( min + Vector3( 0, 0, size.z ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( max - Vector3( size.x, 0, 0 ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( max - Vector3( 0, size.y, 0 ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; if ( plane.GetSide( max - Vector3( 0, 0, size.z ), OUT dist ) == EPlaneSide::Back ) continue; if ( dist < mindist ) mindist = dist; fraction = trace.fraction; closest = trace; t.normal = -(t.v[2] - t.v[0]).Cross(t.v[1] - t.v[0]).Normalize(); closest.normal = t.normal; colliding.AddToTail( t ); // add triangle to colliding triangles list //triangleList.Add( t ); //Debug("COLLIDED!"); } } } Vector3 dir = displacement; Vector3 normal = closest.normal; Vector3 endpoint = start; // If collided, process the collision if ( fraction < 1 ) { // OK float m = 0.005f; // distance from the surface float f = closest.fraction; // fraction of the full dir distance to the contact point Vector3 dirNorm = dir; dirNorm.Normalize(); if ( Vector3::Dot( -dir, normal ) != 0 ) { // PERFECT !!! float ndir = dir.Length() * (m / Vector3::Dot( -dir, normal )); float x = (f * dir.Length() - ndir); // distance we move along the dir direction to stay away from the surface //Debug.WriteLine( "normal: " + closest.normal + " x: " + x + " f: " + f + " ndir: " + ndir + " distance to surf: " + mindist + " ndir.Y: " ); endpoint = start + dirNorm * x; Vector3 slide = ClipVelocity( dir, closest.normal, 1.00f ); float left = 1.0f - (f - ndir / dir.Length()); closest.slide = slide * left; } } else endpoint = start + dir; closest.collision = fraction != 1.0f; closest.endpoint = endpoint; return closest; }