This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/WWMath/lineseg.cpp

217 lines
10 KiB
C++

/*
** 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 : WWMath *
* *
* $Archive:: /Commando/Code/wwmath/lineseg.cpp $*
* *
* Author:: Greg_h *
* *
* $Modtime:: 3/16/00 3:16p $*
* *
* $Revision:: 25 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* LineSegClass::Set -- Initialize this 'lineseg' by transforming another 'lineseg' *
* LineSegClass::Set_Random -- create a random linesegment within the given space *
* LineSegClass::Find_Point_Closest_To -- Finds point on line closest to point supplied. *
* LineSegClass::Find_Intersection -- Finds the closest points on the two lines *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "lineseg.h"
//#include <stdlib.h>
#include "matrix3d.h"
/***********************************************************************************************
* LineSegClass::Set -- Initialize this 'lineseg' by transforming another 'lineseg' *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 6/17/98 GTH : Created. *
*=============================================================================================*/
void LineSegClass::Set(const LineSegClass & that,const Matrix3D & tm)
{
/*
** Transform P0 and P1
*/
Matrix3D::Transform_Vector(tm,that.P0,&P0);
Matrix3D::Transform_Vector(tm,that.P1,&P1);
/*
** Just calculate DP
*/
DP = P1 - P0;
/*
** Rotate the direction vector
*/
Matrix3D::Rotate_Vector(tm,that.Dir,&Dir);
/*
** Length should be un-changed
*/
Length = that.Length;
}
/***********************************************************************************************
* LineSegClass::Set_Random -- create a random linesegment within the given space *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 4/21/98 GTH : Created. *
*=============================================================================================*/
void LineSegClass::Set_Random(const Vector3 & min,const Vector3 & max)
{
float frac;
frac = WWMath::Random_Float();
P0.X = min.X + frac * (max.X - min.X);
frac = WWMath::Random_Float();
P0.Y = min.Y + frac * (max.Y - min.Y);
frac = WWMath::Random_Float();
P0.Z = min.Z + frac * (max.Z - min.Z);
frac = WWMath::Random_Float();
P1.X = min.X + frac * (max.X - min.X);
frac = WWMath::Random_Float();
P1.Y = min.Y + frac * (max.Y - min.Y);
frac = WWMath::Random_Float();
P1.Z = min.Z + frac * (max.Z - min.Z);
DP = P1 - P0;
Dir = DP;
Dir.Normalize();
Length = DP.Length();
}
/***********************************************************************************************
* LineSegClass::Find_Point_Closest_To -- Finds point on line closest to point supplied. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/26/1999 SKB : Created. *
*=============================================================================================*/
Vector3 LineSegClass::Find_Point_Closest_To(const Vector3 &pos) const
{
// Get a vector from one line endpoint to point in question.
Vector3 v_0_pos = (pos - P0);
float dotprod = Vector3::Dot_Product(Dir, v_0_pos);
// Check to see if point is past either of the endpoints.
// (Unable to draw a perpendicular line from the point to the line segment.)
if (dotprod <= 0.0) {
return(P0);
} else if (dotprod >= Length) {
return(P1);
}
// Find point on line seg that is closest to pos passed in.
Vector3 point = P0 + (dotprod * Dir);
return(point);
}
/***********************************************************************************************
* LineSegClass::Find_Intersection -- Finds the closest points on the two lines.. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/03/2000 PDS : Created. *
*=============================================================================================*/
bool
LineSegClass::Find_Intersection
(
const LineSegClass & other_line,
Vector3 * p1,
float * fraction1,
Vector3 * p2,
float * fraction2
) const
{
bool retval = false;
Vector3 cross1 = Vector3::Cross_Product (Dir, other_line.Dir);
Vector3 cross2 = Vector3::Cross_Product (other_line.P0 - P0, other_line.Dir);
float top1 = cross2 * cross1;
float bottom1 = cross1 * cross1;
Vector3 cross3 = Vector3::Cross_Product (other_line.Dir, Dir);
Vector3 cross4 = Vector3::Cross_Product (P0 - other_line.P0, Dir);
float top2 = cross4 * cross3;
float bottom2 = cross3 * cross3;
//
// If either of the divisors are 0, then the lines are parallel
//
if (bottom1 != 0 && bottom2 != 0) {
float length1 = top1 / bottom1;
float length2 = top2 / bottom2;
//
// Calculate the closest points on both lines.
// Note: If the points are the same, then the lines intersect.
//
(*p1) = P0 + (Dir * length1);
(*p2) = other_line.P0 + (other_line.Dir * length2);
//
// Return the fractions if they caller wants them
//
if (fraction1 != NULL) {
(*fraction1) = length1 / Length;
}
if (fraction2 != NULL) {
(*fraction2) = length2 / Length;
}
retval = true;
}
return retval;
}