summaryrefslogtreecommitdiffstats
path: root/game/code/roads/roadsegment.cpp
diff options
context:
space:
mode:
authorSvxy <aidan61605@gmail.com>2023-05-31 23:31:32 +0200
committerSvxy <aidan61605@gmail.com>2023-05-31 23:31:32 +0200
commiteb4b3404aa00220d659e532151dab13d642c17a3 (patch)
tree7e1107c4995489a26c4007e41b53ea8d00ab2134 /game/code/roads/roadsegment.cpp
downloadThe-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.gz
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.bz2
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.lz
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.xz
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.zst
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.zip
Diffstat (limited to 'game/code/roads/roadsegment.cpp')
-rw-r--r--game/code/roads/roadsegment.cpp792
1 files changed, 792 insertions, 0 deletions
diff --git a/game/code/roads/roadsegment.cpp b/game/code/roads/roadsegment.cpp
new file mode 100644
index 0000000..e21c40a
--- /dev/null
+++ b/game/code/roads/roadsegment.cpp
@@ -0,0 +1,792 @@
+/*===========================================================================
+ Copyright (C) 2000 Radical Entertainment Ltd. All rights reserved.
+
+ Component: RoadSegment
+
+ Description:
+
+
+ Authors: Travis Brown-John
+
+ Revisions Date Author Revision
+ 2002/02/25 Tbrown-John Created
+
+===========================================================================*/
+
+#include <roads/road.h>
+#include <roads/roadsegment.h>
+#include <roads/roadsegmentdata.h>
+
+RoadSegment::RoadSegment()
+:
+mRoad( NULL ),
+mSegmentIndex( 0 )
+{
+}
+
+RoadSegment::~RoadSegment( void )
+{
+}
+
+/*
+void RoadSegment::Init( RoadSegmentData* rsd, rmt::Matrix& hierarchy, float scaleAlongFacing )
+{
+ ////////////////////////////////////////////////////////////////
+ // Transform segment data based on given matrix & scale-along-facing
+ //
+ rmt::Vector vector;
+
+ // First, do the corners and the edgenormals
+ for( int i=0; i<4; i++ )
+ {
+ // transform the corner
+ vector = rsd->GetCorner( i );
+ vector.z *= scaleAlongFacing;
+ vector.Transform( hierarchy );
+ mCorners[ i ] = vector;
+
+ // transform the edge normals
+ vector = rsd->GetEdgeNormal( i );
+ vector.Rotate( hierarchy );
+ mEdgeNormals[ i ] = vector;
+ }
+
+ // Now, transform the segment normal
+ vector = rsd->GetSegmentNormal();
+ vector.Rotate( hierarchy );
+ mNormal = vector;
+
+ // Now, calculate and store segment length
+ rmt::Vector segStart = (mCorners[0] + mCorners[3]) * 0.5f;
+ rmt::Vector segEnd = (mCorners[1] + mCorners[2]) * 0.5f;
+ mfSegmentLength = (segEnd - segStart).Length(); // *** SQUARE ROOT! ***
+
+ // Now, calculate and store the bounding sphere
+ rmt::Box3D box;
+ GetBoundingBox( &box ); // find the box on the fly (based on extents of corners)
+
+ // compute & store the bounding sphere based on bbox
+ rmt::Vector vectorBetween;
+ vectorBetween = ( box.high - box.low ) * 0.5f;
+ mSphere.centre = box.low + vectorBetween;
+ mSphere.radius = vectorBetween.Magnitude(); // *** SQUARE ROOT! ***
+
+
+
+ //////////////////////////////
+ // TODO:
+ // This stuff is dubious. It won't be accurate given that we can no
+ // longer assume interior and exterior edges are parallel.
+ //
+ // Now, Calculate the width of the leading edge of the segment.
+ float fWidth = segStart.Magnitude();
+ mfLaneWidth = fWidth / (float)rsd->GetNumLanes();
+
+ // Calculate a turn radius.
+ //
+ float fCosTheta = mEdgeNormals[0].DotProduct( mEdgeNormals[1] );
+ if ( fCosTheta < 0.0f )
+ {
+ fCosTheta = 0.0f - fCosTheta;
+ }
+ if ( fCosTheta < 0.001f ) //Clamp me.
+ {
+ fCosTheta = 0.0f;
+ }
+
+ rmt::Vector temp;
+ temp.Sub( mCorners[0], mCorners[1] );
+ float fInteriorEdgeLength = temp.Magnitude( );
+ temp.Sub( mCorners[2], mCorners[3] );
+ float fExteriorEdgeLength = temp.Magnitude( );
+
+ if ( fCosTheta != 0.0f )
+ {
+ // take the shortest length.
+ float length = ( fInteriorEdgeLength < fExteriorEdgeLength )? fInteriorEdgeLength : fExteriorEdgeLength;
+ length = length / 2.0f;
+ mfRadius = length / fCosTheta;
+ mfAngle = rmt::PI_BY2 - rmt::ACos( fCosTheta );
+ //rmt::RadianToDeg( mfAngle );
+ }
+ else
+ {
+ // Not a curved segment.
+ //
+ mfRadius = 0.0f;
+ mfAngle = 0.0f;
+ }
+}
+*/
+void RoadSegment::Init( RoadSegmentData* rsd, rmt::Matrix& hierarchy, float scaleAlongFacing )
+{
+ ////////////////////////////////////////////////////////////////
+ // Transform segment data based on given matrix & scale-along-facing
+ //
+ rmt::Vector vector;
+
+ // store the unmodified values
+ for( int i=0; i<4; i++ )
+ {
+ vector = rsd->GetCorner( i );
+ mCorners[ i ] = vector;
+
+ vector = rsd->GetEdgeNormal( i );
+ mEdgeNormals[ i ] = vector;
+ }
+
+
+ //////////////////////////////
+ // TODO:
+ // This stuff is dubious. It won't be accurate given that we can no
+ // longer assume interior and exterior edges are parallel. AND
+ // somehow it's able to work quite accurately from the corner
+ // and edgenormal values that have not yet been transformed. *shudder*
+ //
+ // Now, Calculate the width of the leading edge of the segment.
+ float fWidth = ((mCorners[0] + mCorners[3]) * 0.5f).Magnitude();
+ mfLaneWidth = fWidth / (float)rsd->GetNumLanes();
+
+ // Calculate a turn radius.
+ //
+ float fCosTheta = mEdgeNormals[0].DotProduct( mEdgeNormals[1] );
+ if ( fCosTheta < 0.0f )
+ {
+ fCosTheta = 0.0f - fCosTheta;
+ }
+ if ( fCosTheta < 0.001f ) //Clamp me.
+ {
+ fCosTheta = 0.0f;
+ }
+
+ rmt::Vector temp;
+ temp.Sub( mCorners[0], mCorners[1] );
+ float fInteriorEdgeLength = temp.Magnitude( );
+ temp.Sub( mCorners[2], mCorners[3] );
+ float fExteriorEdgeLength = temp.Magnitude( );
+
+ if ( fCosTheta != 0.0f )
+ {
+ // take the shortest length.
+ float length = ( fInteriorEdgeLength < fExteriorEdgeLength )? fInteriorEdgeLength : fExteriorEdgeLength;
+ length = length / 2.0f;
+ mfRadius = length / fCosTheta;
+ mfAngle = rmt::PI_BY2 - rmt::ACos( fCosTheta );
+ //rmt::RadianToDeg( mfAngle );
+ }
+ else
+ {
+ // Not a curved segment.
+ //
+ mfRadius = 0.0f;
+ mfAngle = 0.0f;
+ }
+ ///////////////////////////////////////////
+
+
+
+ // Ok, so first, transform the corners and the edgenormals
+ for( int i=0; i<4; i++ )
+ {
+ // transform the corner
+ vector = rsd->GetCorner( i );
+ vector.z *= scaleAlongFacing;
+ vector.Transform( hierarchy );
+ mCorners[ i ] = vector;
+
+ // transform the edge normals
+ vector = rsd->GetEdgeNormal( i );
+ vector.Rotate( hierarchy );
+ mEdgeNormals[ i ] = vector;
+ }
+
+ // Now, transform the segment normal
+ vector = rsd->GetSegmentNormal();
+ vector.Rotate( hierarchy );
+ mNormal = vector;
+
+ // Now, calculate and store segment length
+ rmt::Vector segStart = (mCorners[0] + mCorners[3]) * 0.5f;
+ rmt::Vector segEnd = (mCorners[1] + mCorners[2]) * 0.5f;
+ mfSegmentLength = (segEnd - segStart).Length(); // *** SQUARE ROOT! ***
+
+ // Now, calculate and store the bounding sphere
+ rmt::Box3D box;
+ GetBoundingBox( &box ); // find the box on the fly (based on extents of corners)
+
+ // compute & store the bounding sphere based on bbox
+ rmt::Vector vectorBetween;
+ vectorBetween = ( box.high - box.low ) * 0.5f;
+ mSphere.centre = box.low + vectorBetween;
+ mSphere.radius = vectorBetween.Magnitude(); // *** SQUARE ROOT! ***
+
+
+}
+
+
+void RoadSegment::GetBoundingBox(rmt::Box3D* box)
+{
+ // get axis-aligned bounding box from vertices...
+ unsigned int numVertices = 4;
+ rmt::Vector vertex;
+ unsigned int i = 0;
+ for ( i = 0; i < numVertices; i++ )
+ {
+ vertex = mCorners[i];
+ if ( 0 == i )
+ {
+ // This is the first time.
+ // Initialize to some value.
+ //
+ box->low = box->high = vertex;
+ }
+ else
+ {
+ if ( box->low.x > vertex.x )
+ {
+ box->low.x = vertex.x;
+ }
+ if ( box->low.y > vertex.y )
+ {
+ box->low.y = vertex.y;
+ }
+ if ( box->low.z > vertex.z )
+ {
+ box->low.z = vertex.z;
+ }
+
+ if ( box->high.x < vertex.x )
+ {
+ box->high.x = vertex.x;
+ }
+ if ( box->high.y < vertex.y )
+ {
+ box->high.y = vertex.y;
+ }
+ if ( box->high.z < vertex.z )
+ {
+ box->high.z = vertex.z;
+ }
+ }
+ }
+}
+
+void RoadSegment::GetBoundingSphere(rmt::Sphere* sphere)
+{
+ *sphere = mSphere;
+}
+
+
+
+
+/*
+==============================================================================
+RoadSegment::CalculateUnitDistIntoRoadSegment
+==============================================================================
+Description: Adapted from GameGems Article by Steven Ranck. pp412-pp420.
+ Implements a fast and simple algm for determing where a point
+ in between the edges of a 2D quad (RoadSegment). The result
+ is a unit floting point number, where 0 indicates that the point
+ lies on the leading edge, and where 1 indicates that the point
+ lies on the opposite edge. The RoadSegment may be any 4 sided
+ 2D convex shape.
+
+Constraints: The RoadSegment must be convex and have 4 sides.
+ The RoadSegment must have a non zero area.
+ The point must lie within the sector. ***** What if it doesn't?
+
+Parameters: ( float fPointX, float fPointZ )
+
+Return: A scalar from 0 to 1.
+ 0 if point lies on the leading edge.
+ 1 if point lies on the trailing edge.
+ Smoothly interpolated value for all points in between.
+
+=============================================================================
+*/
+float RoadSegment::CalculateUnitDistIntoRoadSegment( float fPointX, float fPointZ )
+{
+ rmt::Vector VLP, VTP;
+ float fDotL, fDotT;
+
+ // Get and cache the leading edge top corner
+ // and the trailing edge bottom corner.
+ //
+ rmt::Vector vertices[ 2 ];
+ GetCorner( 0, vertices[ 0 ] );
+ GetCorner( 2, vertices[ 1 ] );
+
+ // Get and cache the leading edge normal
+ // and the trailing edge normal.
+ //
+ rmt::Vector unitNormals[ 2 ];
+ GetEdgeNormal( 0, unitNormals[ 0 ] );
+ GetEdgeNormal( 2, unitNormals[ 1 ] );
+
+ //for this to work, the normals must both point into
+ //the volume...
+ //so, I need to reverse the second edge normal
+ unitNormals[1] *= -1;
+
+ // Compute vector from point on Leading Edge to P:
+ //
+ VLP.x = fPointX - vertices[0].x;
+ VLP.y = 0.0f;
+ VLP.z = fPointZ - vertices[0].z;
+
+ // Compute vector from point on Trailing Edge to P:
+ //
+ VTP.x = fPointX - vertices[1].x;
+ VTP.y = 0.0f;
+ VTP.z = fPointZ - vertices[1].z;
+
+ // Compute (VLP dot Leading Edge Normal):
+ //
+ fDotL = VLP.x*unitNormals[0].x + VLP.z*unitNormals[0].z;
+
+ // Compute (VTP dot Trailing Edge Normal):
+ //
+ fDotT = VTP.x*unitNormals[1].x + VTP.z*unitNormals[1].z;
+
+ // Compute unit distance into sector and return it:
+ //
+ return ( fDotL / (fDotL + fDotT) );
+}
+
+float RoadSegment::CalculateUnitHeightInRoadSegment( float fPointX, float fPointZ )
+{
+ rmt::Vector VLP, VTP;
+ float fDotL, fDotT;
+
+ // Get and cache the leading edge top corner
+ // and the trailing edge bottom corner.
+ //
+ rmt::Vector vertices[ 2 ];
+ GetCorner( 0, vertices[ 0 ] );
+ GetCorner( 2, vertices[ 1 ] );
+
+ // Get and cache the leading edge normal
+ // and the trailing edge normal.
+ //
+ rmt::Vector unitNormals[ 2 ];
+ GetEdgeNormal( 1, unitNormals[ 0 ] );
+ GetEdgeNormal( 3, unitNormals[ 1 ] );
+
+ // Compute vector from point on Leading Edge to P:
+ //
+ VLP.x = fPointX - vertices[0].x;
+ VLP.y = 0.0f;
+ VLP.z = fPointZ - vertices[0].z;
+
+ // Compute vector from point on Trailing Edge to P:
+ //
+ VTP.x = fPointX - vertices[1].x;
+ VTP.y = 0.0f;
+ VTP.z = fPointZ - vertices[1].z;
+
+ // Compute (VLP dot Leading Edge Normal):
+ //
+ fDotL = VLP.x*unitNormals[0].x + VLP.z*unitNormals[0].z;
+
+ // Compute (VTP dot Trailing Edge Normal):
+ //
+ fDotT = VTP.x*unitNormals[1].x + VTP.z*unitNormals[1].z;
+
+ // Compute unit distance into sector and return it:
+ //
+ return ( fDotL / (fDotL + fDotT) );
+}
+
+
+/*
+float RoadSegment::CalculateYHeight( float fPointX, float fPointZ )
+{
+ // Get and cache the leading edge top corner
+ // and the trailing edge bottom corner.
+ //
+ rmt::Vector vertices[ 2 ];
+ GetCorner( 0, vertices[ 0 ] );
+ GetCorner( 2, vertices[ 1 ] );
+
+ float fDistance = CalculateUnitDistIntoRoadSegment( fPointX, fPointZ );
+ float y = LERP( fDistance, vertices[ 0 ].y, vertices[ 1 ].y );
+ return y;
+}
+*/
+
+void RoadSegment::GetPosition( float t, float w, rmt::Vector* pos )
+{
+ // Get and cache the corners.
+ //
+ rmt::Vector vertices[ 4 ];
+ GetCorner( 0, vertices[ 0 ] );
+ GetCorner( 1, vertices[ 1 ] );
+ GetCorner( 2, vertices[ 2 ] );
+ GetCorner( 3, vertices[ 3 ] );
+
+ rmt::Vector position;
+
+ // Interpolate the Normal vector across the Segment.
+ //
+ rmt::Vector leadingEdge;
+ leadingEdge.Sub( vertices[ 3 ], vertices[ 0 ] );
+ rmt::Vector leadingPoint = leadingEdge;
+ leadingPoint.Scale( w );
+ leadingPoint.Add( vertices[ 0 ] );
+
+ rmt::Vector trailingEdge;
+ trailingEdge.Sub( vertices[ 2 ], vertices[ 1 ] );
+ rmt::Vector trailingPoint = trailingEdge;
+ trailingPoint.Scale( w );
+ trailingPoint.Add( vertices[ 1 ] );
+
+ position.Sub( trailingPoint, leadingPoint );
+ position.Scale( t );
+ position.Add( leadingPoint );
+ *pos = position;
+}
+
+
+void RoadSegment::GetLaneLocation( float t, int index, rmt::Vector& position, rmt::Vector& facing )
+{
+ //
+ // Get the world space point and facing at time 't'.
+ //
+ // Interpolate the facing.
+ //
+ rmt::Vector facingNormals[ 2 ];
+ GetEdgeNormal( 0, facingNormals[ 0 ] );
+ GetEdgeNormal( 2, facingNormals[ 1 ] );
+ facing.x = LERP( t, facingNormals[ 0 ].x, facingNormals[ 1 ].x );
+ facing.y = LERP( t, facingNormals[ 0 ].y, facingNormals[ 1 ].y );
+ facing.z = LERP( t, facingNormals[ 0 ].z, facingNormals[ 1 ].z );
+
+ // [Dusit: July 6th, 2003]
+ // NOTE:
+ // This is the CORRECT way to produce the lane length value when
+ // the width of the roadsegment isn't guaranteed across its length.
+ // The only thing that it assumes (and is always correct) is that
+ // each lane is as wide as the other lanes at any given point along
+ // the length of the segment
+ //
+ float edgeT = ((float)(index<<1) + 1.0f) / ((float)(GetNumLanes()<<1));
+
+ // find start & end points of the lane
+ rmt::Vector vec0, vec1, vec2, vec3;
+
+ GetCorner( 0, vec0 );
+ GetCorner( 1, vec1 );
+ GetCorner( 2, vec2 );
+ GetCorner( 3, vec3 );
+
+ // lane indices go from 0 to n, right to left ( n <=== 0 )
+ rmt::Vector bottomEdgeDir = vec0 - vec3; // points frm 3 to 0
+ rmt::Vector topEdgeDir = vec1 - vec2; // points frm 2 to 1
+
+ // now we figure out the starting point and ending point of the
+ // lane segment
+ rmt::Vector start = vec3 + bottomEdgeDir * edgeT;
+ rmt::Vector end = vec2 + topEdgeDir * edgeT;
+
+ // now find the t position along the lane
+ rmt::Vector laneDir = end - start;
+ position = start + laneDir * t;
+
+ /*
+
+ // Get and cache the corners.
+ //
+ rmt::Vector vertices[ 4 ];
+ GetCorner( 0, vertices[ 0 ] );
+ GetCorner( 1, vertices[ 1 ] );
+ GetCorner( 2, vertices[ 2 ] );
+ GetCorner( 3, vertices[ 3 ] );
+
+ //There is an assumption here that the road does not get wider or thinner
+ //across its length...
+ // Scale unnormalized vector by normalized center of desired lane.
+ // ( ( index * fLaneWidth ) + ( fLaneWidth / 2.0f ) ) / roadWidth;
+ //
+ float fCentreOfLane = ( index * mfLaneWidth ) + ( mfLaneWidth / 2.0f );
+
+ //I call this parametric variable w;
+ float w = fCentreOfLane / GetRoadWidth();
+
+ // Interpolate the Normal vector across the Segment.
+ //
+ rmt::Vector leadingEdge;
+ leadingEdge.Sub( vertices[ 0 ], vertices[ 3 ] );
+ rmt::Vector leadingPoint = leadingEdge;
+ leadingPoint.Scale( w );
+ leadingPoint.Add( vertices[ 3 ] );
+
+
+ rmt::Vector trailingEdge;
+ trailingEdge.Sub( vertices[ 1 ], vertices[ 2 ] );
+ rmt::Vector trailingPoint = trailingEdge;
+ trailingPoint.Scale( w );
+ trailingPoint.Add( vertices[ 2 ] );
+
+ //This gives the point between the leading and trailing point by parameter t.
+ position.x = LERP( t, leadingPoint.x, trailingPoint.x );
+ position.y = LERP( t, leadingPoint.y, trailingPoint.y );
+ position.z = LERP( t, leadingPoint.z, trailingPoint.z );
+ */
+
+
+}
+
+
+/*
+//==============================================================================
+//RoadSegment::GetJoinPoint
+//==============================================================================
+//Description: RoadSegmentData pieces are always joined at the left corner
+// of the trailing edge. The normal of the leading edge of the
+// new piece is always the inverse normal of the trailing edge
+// of the previous piece.
+//
+// This function returns the join vertex and facing in world space.
+//
+//Parameters: ( rmt::Vector& position, rmt::Vector& facing )
+//
+//Return: void
+//
+//=============================================================================
+void RoadSegment::GetJoinPoint( rmt::Vector& position, rmt::Vector& facing )
+{
+ // All segments are joined at the left top corner.
+ //
+ position = GetRoadSegmentData( )->GetCorner( 1 );
+
+ facing = GetRoadSegmentData( )->GetEdgeNormal( 2 );
+ facing.Scale( -1.0f );
+}
+*/
+
+void RoadSegment::GetCorner( int index, rmt::Vector& out )
+{
+ rAssert( 0 <= index && index < 4 );
+ out = mCorners[ index ];
+}
+void RoadSegment::GetEdgeNormal( int index, rmt::Vector& out )
+{
+ rAssert( 0 <= index && index < 4 );
+ out = mEdgeNormals[ index ];
+}
+void RoadSegment::GetSegmentNormal( rmt::Vector& out )
+{
+ out = mNormal;
+}
+unsigned int RoadSegment::GetNumLanes( void )
+{
+ return GetRoad()->GetNumLanes();
+}
+float RoadSegment::GetLaneLength( unsigned int lane )
+{
+ // [Dusit: July 6th, 2003]
+ // NOTE:
+ // This is the CORRECT way to produce the lane length value when
+ // the width of the roadsegment isn't guaranteed across its length.
+ // The only thing that it assumes (and is always correct) is that
+ // each lane is as wide as the other lanes at any given point along
+ // the length of the segment
+ //
+ // The problem with using this is that it requires a Sqrt (because
+ // it's too late for us to rearrange the data so that we can avoid
+ // this). So we continue using the old way because we're never off
+ // by more than 5 centimeters anyway.
+ //
+ float edgeT = ((float)(lane<<1) + 1.0f) / ((float)(GetNumLanes()<<1));
+
+ // find start & end points of the lane
+ rmt::Vector vec0, vec1, vec2, vec3;
+
+ GetCorner( 0, vec0 );
+ GetCorner( 1, vec1 );
+ GetCorner( 2, vec2 );
+ GetCorner( 3, vec3 );
+
+ // lane indices go from 0 to n, right to left ( n <=== 0 )
+ rmt::Vector bottomEdgeDir = vec0 - vec3; // points frm 3 to 0
+ rmt::Vector topEdgeDir = vec1 - vec2; // points frm 2 to 1
+
+ rmt::Vector start = vec3 + bottomEdgeDir * edgeT;
+ rmt::Vector end = vec2 + topEdgeDir * edgeT;
+
+ float expectedLength = (end - start).Magnitude();
+ return expectedLength;
+
+ /*
+ float computedLength = 0.0f;
+
+ // TODO:
+ // Because we can't assume that a lane is constant-width, this
+ // code is totally bogus...
+ if ( mfAngle > 0.0f )
+ {
+ // 2*PI*r for a circle.
+ // Theta*r for arc of theta degrees.
+ //
+ float fLaneOffset = mfLaneWidth * lane + mfLaneWidth;
+ computedLength = 2.0f * mfAngle * ( mfRadius + fLaneOffset );
+ }
+ else
+ {
+ // it's not a curve, both edge lengths will be equal.
+ //
+ computedLength = mfSegmentLength;
+ }
+
+ //rAssert( rmt::Epsilon( computedLength, expectedLength, 0.01f ) );
+ return computedLength;
+ */
+}
+
+float RoadSegment::GetRoadWidth()
+{
+ return mRoad->GetNumLanes() * mfLaneWidth;
+}
+
+
+/*
+
+/////////////////////////////////////////////////////////////////
+// TransformRoadSegment
+/////////////////////////////////////////////////////////////////
+//
+TransformRoadSegment::TransformRoadSegment() :
+ RoadSegment( NULL )
+{
+ mTransform.Identity();
+ mfScaleAlongFacing = 0.0f;
+}
+
+TransformRoadSegment::TransformRoadSegment(
+ const RoadSegmentData* pRoadSegmentData,
+ rmt::Matrix& transform )
+ :
+ RoadSegment( pRoadSegmentData )
+{
+ mTransform = transform;
+}
+
+TransformRoadSegment::TransformRoadSegment(
+ const RoadSegmentData* pRoadSegmentData,
+ rmt::Matrix& transform,
+ float fScaleAlongFacing )
+ :
+ RoadSegment( pRoadSegmentData ),
+ mfScaleAlongFacing( fScaleAlongFacing )
+{
+ mTransform = transform;
+}
+
+TransformRoadSegment::TransformRoadSegment(
+ const RoadSegmentData* pRoadSegmentData,
+ const rmt::Vector& facing,
+ const rmt::Vector& position )
+ :
+ RoadSegment( pRoadSegmentData )
+{
+ rmt::Vector sApproximateUp( 0.0f, 1.0f, 0.0f );
+
+ mTransform.Identity( );
+ mTransform.FillHeading( facing, sApproximateUp );
+ mTransform.FillTranslate( position );
+}
+
+TransformRoadSegment::TransformRoadSegment(
+ const RoadSegmentData* pRoadSegmentData,
+ const rmt::Vector& facing,
+ const rmt::Vector& position,
+ float fScaleAlongFacing )
+ :
+ RoadSegment( pRoadSegmentData ),
+ mfScaleAlongFacing( fScaleAlongFacing )
+{
+ rmt::Vector sApproximateUp( 0.0f, 1.0f, 0.0f );
+
+ mTransform.Identity( );
+ mTransform.FillHeading( facing, sApproximateUp );
+ mTransform.FillTranslate( position );
+}
+void TransformRoadSegment::GetCorner( int index, rmt::Vector& out ) const
+{
+ out = GetRoadSegmentData( )->GetCorner( index );
+ out.z *= mfScaleAlongFacing;
+ out.Transform( mTransform );
+}
+void TransformRoadSegment::GetEdgeNormal( int index, rmt::Vector& out ) const
+{
+ out = GetRoadSegmentData( )->GetEdgeNormal( index );
+ out.Rotate( mTransform );
+}
+void TransformRoadSegment::GetSegmentNormal( rmt::Vector& out ) const
+{
+ out = GetRoadSegmentData( )->GetSegmentNormal( );
+ out.Rotate( mTransform );
+}
+
+//==============================================================================
+//TransformRoadSegment::GetJoinPoint
+//==============================================================================
+//Description: RoadSegmentData pieces are always joined at the left corner
+// of the trailing edge. The normal of the leading edge of the
+// new piece is always the inverse normal of the trailing edge
+// of the previous piece.
+//
+// This function returns the join vertex and facing in world space.
+//
+//Parameters: ( rmt::Vector& position, rmt::Vector& facing )
+//
+//Return: void
+//
+//=============================================================================
+void TransformRoadSegment::GetJoinPoint( rmt::Vector& position, rmt::Vector& facing ) const
+{
+ // All segments are joined at the left top corner.
+ //
+ facing = GetRoadSegmentData( )->GetEdgeNormal( 2 );
+ facing.Scale( -1.0f );
+ facing.Rotate( mTransform );
+
+ position = GetRoadSegmentData( )->GetCorner( 1 );
+ position.z *= mfScaleAlongFacing;
+ position.Transform( mTransform );
+}
+void TransformRoadSegment::GetBoundingBox(rmt::Box3D* box)
+{
+ GetRoadSegmentData()->GetBoundingBox( *box );
+ (*box).high.z *= mfScaleAlongFacing;
+ (*box).high.Transform( mTransform );
+ (*box).low.Transform( mTransform );
+}
+void TransformRoadSegment::GetBoundingSphere(rmt::Sphere* sphere)
+{
+ GetRoadSegmentData( )->GetBoundingSphere( *sphere );
+ (*sphere).radius *= mfScaleAlongFacing;
+ (*sphere).centre.Transform( mTransform );
+}
+
+void TransformRoadSegment::GetBoundingBox( rmt::Box3D& out ) const
+{
+ GetRoadSegmentData( )->GetBoundingBox( out );
+ out.high.z *= mfScaleAlongFacing;
+ out.high.Transform( mTransform );
+ out.low.Transform( mTransform );
+}
+
+void TransformRoadSegment::GetBoundingSphere( rmt::Sphere& out ) const
+{
+ out = GetRoadSegmentData( )->GetBoundingSphere( );
+ out.radius *= mfScaleAlongFacing;
+ out.centre.Transform( mTransform );
+}
+
+void TransformRoadSegment::GetTransform( rmt::Matrix &out ) const
+{
+ out = mTransform;
+}
+
+*/ \ No newline at end of file