mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 15:41:39 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
681
Code/WWMath/vehiclecurve.cpp
Normal file
681
Code/WWMath/vehiclecurve.cpp
Normal file
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwmath/vehiclecurve.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 6/12/01 10:02a $*
|
||||
* *
|
||||
* $Revision:: 8 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "vehiclecurve.h"
|
||||
#include "vector3.h"
|
||||
#include "matrix3d.h"
|
||||
#include "persistfactory.h"
|
||||
#include "wwmathids.h"
|
||||
#include "wwmemlog.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Save-Load stuff
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
SimplePersistFactoryClass<VehicleCurveClass,WWMATH_CHUNKID_VEHICLECURVE> _VehicleCurveFactory;
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Save/Load constants
|
||||
////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
CHUNKID_PARENT = 0x11071217,
|
||||
CHUNKID_ARC_INFO,
|
||||
CHUNKID_VARIABLES
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VARID_IS_DIRTY = 1,
|
||||
VARID_RADIUS,
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Local prototypes
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool Find_Tangent (const Vector3 ¢er, float radius, const Vector3 &point, bool clockwise, float *result);
|
||||
float Get_Angle_Delta (float angle1, float angle2, bool clockwise);
|
||||
void Find_Turn_Arc (const Matrix3D &transform, float radius, const Vector3 &prev_pt, const Vector3 &curr_pt, const Vector3 &next_pt, Vector3 *arc_center, bool *is_right_turn);
|
||||
void Find_Tangents (float radius, const Vector3 &prev_pt, const Vector3 &curr_pt, const Vector3 &next_pt, const Vector3 &arc_center, bool is_right_turn, float *point_angle, float *angle_in_delta, float *angle_out_delta);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Find_Tangent
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
Find_Tangent
|
||||
(
|
||||
const Vector3 & center,
|
||||
float radius,
|
||||
const Vector3 & point,
|
||||
bool clockwise,
|
||||
float * result
|
||||
)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
//
|
||||
// Calculate the distance from the point to the center of the circle
|
||||
//
|
||||
float delta_x = point.X - center.X;
|
||||
float delta_y = point.Y - center.Y;
|
||||
float dist = ::sqrt (delta_x * delta_x + delta_y * delta_y);
|
||||
if (dist >= radius) {
|
||||
|
||||
//
|
||||
// Determine the offset angle (from the line between the point and center)
|
||||
// where the 2 tangent points lie.
|
||||
//
|
||||
float angle_offset = WWMath::Acos (radius / dist);
|
||||
float base_angle = WWMath::Atan2 (delta_x, -delta_y);
|
||||
base_angle = WWMath::Wrap (base_angle, 0, DEG_TO_RADF (360));
|
||||
|
||||
//
|
||||
// Determine which tangent angle we would come across first, depending
|
||||
// on our orientation
|
||||
//
|
||||
float angle = 0;
|
||||
if (clockwise) {
|
||||
angle = base_angle - angle_offset;
|
||||
} else {
|
||||
angle = base_angle + angle_offset;
|
||||
}
|
||||
angle = WWMath::Wrap (angle, 0, DEG_TO_RADF (360));
|
||||
(*result) = angle;
|
||||
|
||||
retval = true;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Angle_Delta
|
||||
//
|
||||
// Angle deltas need to be wrapped around 360 degrees differently
|
||||
// depending on the orientation (clockwise/counterclockwise). This
|
||||
// function takes orientation into consideration when determining
|
||||
// the delta.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
float
|
||||
Get_Angle_Delta
|
||||
(
|
||||
float angle1,
|
||||
float angle2,
|
||||
bool clockwise
|
||||
)
|
||||
{
|
||||
float result = angle1 - angle2;
|
||||
|
||||
if (clockwise) {
|
||||
if (angle1 < angle2) {
|
||||
result = angle1 - (angle2 - DEG_TO_RADF (360));
|
||||
}
|
||||
} else {
|
||||
if (angle1 > angle2) {
|
||||
result = (angle1 - DEG_TO_RADF (360)) - angle2;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Find_Turn_Arc
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Find_Turn_Arc
|
||||
(
|
||||
const Matrix3D & transform,
|
||||
float radius,
|
||||
const Vector3 & prev_pt,
|
||||
const Vector3 & curr_pt,
|
||||
const Vector3 & next_pt,
|
||||
Vector3 * arc_center,
|
||||
bool * is_right_turn
|
||||
)
|
||||
{
|
||||
//
|
||||
// The center of the turn arc can lie anywhere on the circle centered
|
||||
// at the current point and 'radius' meters in radius.
|
||||
//
|
||||
// We will assume the optimal center of the turn arc will lie at
|
||||
// the point halfway between the angles formed by the (prev-curr) and
|
||||
// (next-curr) vectors.
|
||||
//
|
||||
float angle1 = ::WWMath::Atan2 ((prev_pt.Y - curr_pt.Y), prev_pt.X - curr_pt.X);
|
||||
angle1 = WWMath::Wrap (angle1, 0, DEG_TO_RADF (360));
|
||||
|
||||
float angle2 = ::WWMath::Atan2 ((next_pt.Y - curr_pt.Y), next_pt.X - curr_pt.X);
|
||||
angle2 = WWMath::Wrap (angle2, 0, DEG_TO_RADF (360));
|
||||
|
||||
float avg_angle = (angle1 + angle2) * 0.5F;
|
||||
|
||||
//
|
||||
// Find the shortest delta between the two angles (either clockwise or
|
||||
// counterclockwise).
|
||||
//
|
||||
float delta1 = WWMath::Fabs (::Get_Angle_Delta (angle1, angle2, true));
|
||||
float delta2 = WWMath::Fabs (::Get_Angle_Delta (angle1, angle2, false));
|
||||
if (delta1 < delta2) {
|
||||
avg_angle = angle1 - (delta1 * 0.5F);
|
||||
} else {
|
||||
avg_angle = angle1 + (delta2 * 0.5F);
|
||||
}
|
||||
|
||||
//
|
||||
// Find the point on the circle at this angle
|
||||
//
|
||||
arc_center->X = curr_pt.X + (radius * ::WWMath::Cos (avg_angle));
|
||||
arc_center->Y = curr_pt.Y + (radius * ::WWMath::Sin (avg_angle));
|
||||
arc_center->Z = curr_pt.Z;
|
||||
|
||||
//
|
||||
// Will we be making a right turn or a left turn?
|
||||
//
|
||||
Vector3 rel_center;
|
||||
Matrix3D::Inverse_Transform_Vector (transform, *arc_center, &rel_center);
|
||||
(*is_right_turn) = (rel_center.Y > 0);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Find_Tangents
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Find_Tangents
|
||||
(
|
||||
float radius,
|
||||
const Vector3 & prev_pt,
|
||||
const Vector3 & curr_pt,
|
||||
const Vector3 & next_pt,
|
||||
const Vector3 & arc_center,
|
||||
bool is_right_turn,
|
||||
float * point_angle,
|
||||
float * angle_in_delta,
|
||||
float * angle_out_delta
|
||||
)
|
||||
{
|
||||
|
||||
//
|
||||
// Find the 'in' and 'out' tangent angles
|
||||
//
|
||||
float angle_in = 0;
|
||||
float angle_out = 0;
|
||||
bool valid_in = ::Find_Tangent (arc_center, radius, prev_pt, is_right_turn, &angle_in);
|
||||
bool valid_out = ::Find_Tangent (arc_center, radius, next_pt, !is_right_turn, &angle_out);
|
||||
|
||||
//
|
||||
// Find the angle where the current position lies on the turn arc
|
||||
//
|
||||
(*point_angle) = ::WWMath::Atan2 (curr_pt.X - arc_center.X, -(curr_pt.Y - arc_center.Y));
|
||||
(*point_angle) = WWMath::Wrap ((*point_angle), 0, DEG_TO_RADF (360));
|
||||
|
||||
//
|
||||
// If the tangent-in is valid, find its delta from the 'point angle.
|
||||
//
|
||||
if (valid_in) {
|
||||
(*angle_in_delta) = ::Get_Angle_Delta (angle_in, (*point_angle), is_right_turn);
|
||||
} else {
|
||||
(*angle_in_delta) = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// If the tangent-out is valid, find its delta from the 'point angle.
|
||||
//
|
||||
if (valid_out) {
|
||||
(*angle_out_delta) = ::Get_Angle_Delta (angle_out, (*point_angle), !is_right_turn);
|
||||
} else {
|
||||
(*angle_out_delta) = 0;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Arc_List
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
VehicleCurveClass::Update_Arc_List (void)
|
||||
{
|
||||
WWMEMLOG(MEM_PATHFIND);
|
||||
m_ArcList.Delete_All ();
|
||||
|
||||
//
|
||||
// Bail out if there is nothing to do
|
||||
//
|
||||
int count = Key_Count ();
|
||||
if (count == 0) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Add a record for the starting point of the arc...
|
||||
//
|
||||
ArcInfoStruct arc_start;
|
||||
arc_start.point_in = Keys[0].Point;
|
||||
arc_start.point_out = Keys[0].Point;
|
||||
arc_start.center = Keys[0].Point;
|
||||
arc_start.point_angle = 0;
|
||||
arc_start.radius = 0;
|
||||
arc_start.angle_in_delta = 0;
|
||||
arc_start.angle_out_delta = 0;
|
||||
m_ArcList.Add (arc_start);
|
||||
|
||||
//
|
||||
// Loop over each 'interior' point and generate arc information
|
||||
// for each.
|
||||
//
|
||||
for (int index = 1; index < count - 1; index ++) {
|
||||
|
||||
//
|
||||
// Get information about the previous, next, and current points.
|
||||
//
|
||||
Vector3 prev_pt;
|
||||
Vector3 next_pt;
|
||||
Vector3 curr_pt;
|
||||
float time = 0;
|
||||
Get_Key (index-1, &prev_pt, &time);
|
||||
Get_Key (index, &curr_pt, &time);
|
||||
Get_Key (index+1, &next_pt, &time);
|
||||
|
||||
//
|
||||
// Determine the last known point on the path
|
||||
//
|
||||
Vector3 last_path_pt = m_ArcList[index-1].point_out;
|
||||
|
||||
//
|
||||
// Create a transformation matrix to simulate the vehicle's position and
|
||||
// orientation at the last point...
|
||||
//
|
||||
Vector3 x_vector (curr_pt - last_path_pt);
|
||||
Vector3 z_vector (0, 0, 1);
|
||||
x_vector.Normalize ();
|
||||
Vector3 y_vector = Vector3::Cross_Product (x_vector, z_vector);
|
||||
Matrix3D tm (x_vector, y_vector, z_vector, last_path_pt);
|
||||
|
||||
//
|
||||
// Find where the turn arc should be centered and whether we should
|
||||
// make a right-turn or a left turn...
|
||||
//
|
||||
bool is_right_turn = false;
|
||||
Vector3 arc_center (0, 0, 0);
|
||||
::Find_Turn_Arc ( tm,
|
||||
m_Radius,
|
||||
last_path_pt,
|
||||
curr_pt,
|
||||
next_pt,
|
||||
&arc_center,
|
||||
&is_right_turn);
|
||||
|
||||
//
|
||||
// Determine where the vehicle should enter and exit the turn
|
||||
//
|
||||
float angle_in_delta = 0;
|
||||
float angle_out_delta = 0;
|
||||
float point_angle = 0;
|
||||
::Find_Tangents ( m_Radius,
|
||||
last_path_pt,
|
||||
curr_pt,
|
||||
next_pt,
|
||||
arc_center,
|
||||
is_right_turn,
|
||||
&point_angle,
|
||||
&angle_in_delta,
|
||||
&angle_out_delta);
|
||||
|
||||
//
|
||||
// Determine at what points these angles intersect the arc
|
||||
//
|
||||
Vector3 point_in (0, 0, 0);
|
||||
point_in.X = arc_center.X + (m_Radius * ::WWMath::Sin (point_angle + angle_in_delta));
|
||||
point_in.Y = arc_center.Y + (m_Radius * -::WWMath::Cos (point_angle + angle_in_delta));
|
||||
|
||||
Vector3 point_out (0, 0, 0);
|
||||
point_out.X = arc_center.X + (m_Radius * ::WWMath::Sin (point_angle + angle_out_delta));
|
||||
point_out.Y = arc_center.Y + (m_Radius * -::WWMath::Cos (point_angle + angle_out_delta));
|
||||
|
||||
//
|
||||
// Sanity check to ensure the vehicle doesn't try to go the long way around the
|
||||
// turn arc...
|
||||
//
|
||||
if ( angle_in_delta > DEG_TO_RADF (200) || angle_out_delta > DEG_TO_RADF (200) ||
|
||||
angle_in_delta < -DEG_TO_RADF (200) || angle_out_delta < -DEG_TO_RADF (200) )
|
||||
{
|
||||
//
|
||||
// Record information about this arc
|
||||
//
|
||||
ArcInfoStruct arc_info;
|
||||
arc_info.center = curr_pt;
|
||||
arc_info.point_angle = 0;
|
||||
arc_info.point_in = curr_pt;
|
||||
arc_info.point_out = curr_pt;
|
||||
arc_info.radius = 0;
|
||||
arc_info.angle_in_delta = 0;
|
||||
arc_info.angle_out_delta = 0;
|
||||
m_ArcList.Add (arc_info);
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// Record information about this arc
|
||||
//
|
||||
ArcInfoStruct arc_info;
|
||||
arc_info.center = arc_center;
|
||||
arc_info.point_angle = point_angle;
|
||||
arc_info.point_in = point_in;
|
||||
arc_info.point_out = point_out;
|
||||
arc_info.radius = m_Radius;
|
||||
arc_info.angle_in_delta = angle_in_delta;
|
||||
arc_info.angle_out_delta = angle_out_delta;
|
||||
m_ArcList.Add (arc_info);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Add a record for the starting point of the arc...
|
||||
//
|
||||
if (count > 1) {
|
||||
ArcInfoStruct arc_end;
|
||||
arc_end.point_in = Keys[count-1].Point;
|
||||
arc_end.point_out = Keys[count-1].Point;
|
||||
arc_end.center = Keys[count-1].Point;
|
||||
arc_end.point_angle = 0;
|
||||
arc_end.radius = 0;
|
||||
arc_end.angle_in_delta = 0;
|
||||
arc_end.angle_out_delta = 0;
|
||||
m_ArcList.Add (arc_end);
|
||||
}
|
||||
|
||||
m_IsDirty = false;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Evaluate
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
VehicleCurveClass::Evaluate (float time, Vector3 *set_val)
|
||||
{
|
||||
int count = Keys.Count ();
|
||||
m_Sharpness = 0;
|
||||
|
||||
if (time < Keys[0].Time) {
|
||||
*set_val = Keys[0].Point;
|
||||
m_LastTime = Keys[0].Time;
|
||||
return;
|
||||
}
|
||||
|
||||
if (time >= Keys[count - 1].Time) {
|
||||
*set_val = Keys[count - 1].Point;
|
||||
m_LastTime = Keys[count - 1].Time;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the arc information if any of the keys have changed...
|
||||
//
|
||||
if (m_IsDirty) {
|
||||
Update_Arc_List ();
|
||||
}
|
||||
|
||||
//
|
||||
// Determine which segment we are on
|
||||
//
|
||||
int index0 = 0;
|
||||
int index1 = 0;
|
||||
float seg_time = 0;
|
||||
Find_Interval (time, &index0, &index1, &seg_time);
|
||||
|
||||
ArcInfoStruct &arc_info0 = m_ArcList[index0];
|
||||
ArcInfoStruct &arc_info1 = m_ArcList[index1];
|
||||
|
||||
//
|
||||
// Determine the lengths of each segment of this curve.
|
||||
// The segments are:
|
||||
// - Exit curve from prev point
|
||||
// - Straight line from exit of last curve to enter of this curve
|
||||
// - Enter curve for the current point
|
||||
//
|
||||
float arc_length0 = arc_info0.radius * WWMath::Fabs (arc_info0.angle_out_delta);
|
||||
float arc_length1 = arc_info1.radius * WWMath::Fabs (arc_info1.angle_in_delta);
|
||||
float other_length = ((arc_info1.point_in - arc_info0.point_out).Length ()) / 2;
|
||||
float total_length = arc_length0 + arc_length1 + other_length;
|
||||
|
||||
//
|
||||
// Determine at what times we should switch between parts of the segment
|
||||
//
|
||||
float time1 = arc_length0 / total_length;
|
||||
float time2 = (arc_length0 + other_length) / total_length;
|
||||
|
||||
//
|
||||
// Determine which part of the segment we are on
|
||||
//
|
||||
if (seg_time < time1) {
|
||||
|
||||
//
|
||||
// We are on the initial curve of the segment, so calculate where
|
||||
// on the curve we are...
|
||||
//
|
||||
//float percent = seg_time / time1;
|
||||
//float angle = arc_info0.point_angle + (arc_info0.angle_out_delta) * percent;
|
||||
float angle = arc_info0.point_angle + arc_info0.angle_out_delta;
|
||||
|
||||
set_val->X = arc_info0.center.X + (arc_info0.radius * ::WWMath::Sin (angle));
|
||||
set_val->Y = arc_info0.center.Y + (arc_info0.radius * -::WWMath::Cos (angle));
|
||||
|
||||
m_Sharpness = WWMath::Clamp (WWMath::Fabs (arc_info0.angle_out_delta) / DEG_TO_RADF (15), 0, 1.0F);
|
||||
m_SharpnessPos.X = set_val->X;
|
||||
m_SharpnessPos.Y = set_val->Y;
|
||||
m_SharpnessPos.Z = Keys[index0].Point.Z + (Keys[index1].Point.Z - Keys[index0].Point.Z) * seg_time;
|
||||
|
||||
m_LastTime = Keys[index0].Time + (Keys[index1].Time - Keys[index0].Time) * time1;
|
||||
|
||||
} else if (seg_time < time2) {
|
||||
|
||||
//
|
||||
// We are on the line between the two curves, so calculate where on
|
||||
// the line we are
|
||||
//
|
||||
float percent = (seg_time - time1) / (time2 - time1);
|
||||
|
||||
if (percent == 0) {
|
||||
set_val->X = arc_info0.point_out.X;
|
||||
set_val->Y = arc_info0.point_out.Y;
|
||||
} else {
|
||||
set_val->X = arc_info1.point_in.X;
|
||||
set_val->Y = arc_info1.point_in.Y;
|
||||
}
|
||||
|
||||
//set_val->X = arc_info0.point_out.X + (arc_info1.point_in.X - arc_info0.point_out.X) * percent;
|
||||
//set_val->Y = arc_info0.point_out.Y + (arc_info1.point_in.Y - arc_info0.point_out.Y) * percent;
|
||||
|
||||
m_Sharpness = WWMath::Clamp (WWMath::Fabs (arc_info1.angle_out_delta) / DEG_TO_RADF (15), 0, 1.0F);
|
||||
m_SharpnessPos = arc_info1.point_in;
|
||||
|
||||
m_LastTime = Keys[index0].Time + (Keys[index1].Time - Keys[index0].Time) * time2;
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// We are on the ending curve of the segment, so calculate where
|
||||
// on the curve we are...
|
||||
//
|
||||
/*float percent = 1.0F - ((seg_time - time2) / (1.0F - time2));
|
||||
float angle = arc_info1.point_angle + (arc_info1.angle_in_delta * percent);
|
||||
|
||||
set_val->X = arc_info1.center.X + (arc_info1.radius * ::WWMath::Sin (angle));
|
||||
set_val->Y = arc_info1.center.Y + (arc_info1.radius * -::WWMath::Cos (angle)); */
|
||||
|
||||
float angle = arc_info1.point_angle + (arc_info1.angle_out_delta);
|
||||
|
||||
set_val->X = arc_info1.center.X + (arc_info1.radius * ::WWMath::Sin (angle));
|
||||
set_val->Y = arc_info1.center.Y + (arc_info1.radius * -::WWMath::Cos (angle));
|
||||
|
||||
m_Sharpness = WWMath::Clamp (WWMath::Fabs (arc_info1.angle_out_delta) / DEG_TO_RADF (15), 0, 1.0F);
|
||||
m_SharpnessPos.X = set_val->X;
|
||||
m_SharpnessPos.Y = set_val->Y;
|
||||
m_SharpnessPos.Z = Keys[index0].Point.Z + (Keys[index1].Point.Z - Keys[index0].Point.Z) * seg_time;
|
||||
|
||||
m_LastTime = Keys[index1].Time;
|
||||
}
|
||||
|
||||
//
|
||||
// Our Z value is just a linear interpolation
|
||||
//
|
||||
set_val->Z = Keys[index0].Point.Z + (Keys[index1].Point.Z - Keys[index0].Point.Z) * seg_time;
|
||||
return ;
|
||||
}
|
||||
|
||||
const PersistFactoryClass & VehicleCurveClass::Get_Factory(void) const
|
||||
{
|
||||
return _VehicleCurveFactory;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
VehicleCurveClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
csave.Begin_Chunk (CHUNKID_PARENT);
|
||||
Curve3DClass::Save (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_VARIABLES);
|
||||
|
||||
//
|
||||
// Save each variable to its own microchunk
|
||||
//
|
||||
WRITE_MICRO_CHUNK (csave, VARID_IS_DIRTY, m_IsDirty);
|
||||
WRITE_MICRO_CHUNK (csave, VARID_RADIUS, m_Radius);
|
||||
|
||||
csave.End_Chunk ();
|
||||
|
||||
//
|
||||
// Save each arc info struct to its own chunk
|
||||
//
|
||||
for (int index = 0; index < m_ArcList.Count (); index ++) {
|
||||
ArcInfoStruct &arc_info = m_ArcList[index];
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_ARC_INFO);
|
||||
csave.Write (&arc_info, sizeof (arc_info));
|
||||
csave.End_Chunk ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
VehicleCurveClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
case CHUNKID_PARENT:
|
||||
Curve3DClass::Load (cload);
|
||||
break;
|
||||
|
||||
case CHUNKID_ARC_INFO:
|
||||
{
|
||||
ArcInfoStruct arc_info;
|
||||
cload.Read (&arc_info, sizeof (arc_info));
|
||||
m_ArcList.Add (arc_info);
|
||||
}
|
||||
break;
|
||||
|
||||
case CHUNKID_VARIABLES:
|
||||
Load_Variables (cload);
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Variables
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
VehicleCurveClass::Load_Variables (ChunkLoadClass &cload)
|
||||
{
|
||||
//
|
||||
// Loop through all the microchunks that define the variables
|
||||
//
|
||||
while (cload.Open_Micro_Chunk ()) {
|
||||
switch (cload.Cur_Micro_Chunk_ID ()) {
|
||||
|
||||
READ_MICRO_CHUNK (cload, VARID_IS_DIRTY, m_IsDirty);
|
||||
READ_MICRO_CHUNK (cload, VARID_RADIUS, m_Radius);
|
||||
}
|
||||
|
||||
cload.Close_Micro_Chunk ();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
Reference in New Issue
Block a user