mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 07:31:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
458
Code/Tests/mathtest/raytest.cpp
Normal file
458
Code/Tests/mathtest/raytest.cpp
Normal file
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
** 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 : MathTest *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tests/mathtest/raytest.cpp $*
|
||||
* *
|
||||
* $Author:: Greg_h $*
|
||||
* *
|
||||
* $Modtime:: 3/17/00 9:34a $*
|
||||
* *
|
||||
* $Revision:: 10 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "raytest.h"
|
||||
#include "output.h"
|
||||
#include "wwmath.h"
|
||||
#include "tri.h"
|
||||
#include "vector3.h"
|
||||
#include "lineseg.h"
|
||||
#include "aabox.h"
|
||||
#include "obbox.h"
|
||||
#include "colmath.h"
|
||||
#include "p_timer.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void line_box_test(const LineSegClass & line,const OBBoxClass & box,CastResultStruct * res);
|
||||
|
||||
/************************************************************************************************
|
||||
**
|
||||
** Ray - Triangle Test Cases
|
||||
**
|
||||
************************************************************************************************/
|
||||
|
||||
class RayTriTestClass
|
||||
{
|
||||
public:
|
||||
Vector3 P0;
|
||||
Vector3 P1;
|
||||
Vector3 V0;
|
||||
Vector3 V1;
|
||||
Vector3 V2;
|
||||
Vector3 N;
|
||||
float Fraction;
|
||||
bool StartBad;
|
||||
LineSegClass LineSeg;
|
||||
TriClass Tri;
|
||||
|
||||
RayTriTestClass
|
||||
(
|
||||
const Vector3 p0, // p0 of ray
|
||||
const Vector3 p1, // p1 of ray
|
||||
const Vector3 v0, // v0 of triangle
|
||||
const Vector3 v1, // v1 of triangle
|
||||
const Vector3 v2, // v2 of triangle
|
||||
float frac, // expected fraction
|
||||
bool sol // expected start solid
|
||||
) :
|
||||
P0(p0),P1(p1),V0(v0),V1(v1),V2(v2),Fraction(frac),StartBad(sol),LineSeg(P0,P1)
|
||||
{
|
||||
Tri.V[0] = &V0;
|
||||
Tri.V[1] = &V1;
|
||||
Tri.V[2] = &V2;
|
||||
Tri.N = & N;
|
||||
Tri.Compute_Normal();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
RayTriTestClass RayTriTestCases[] =
|
||||
{
|
||||
RayTriTestClass
|
||||
(
|
||||
Vector3(0,0,0),
|
||||
Vector3(1,0,0),
|
||||
Vector3(1,1,1),
|
||||
Vector3(1,-1,1),
|
||||
Vector3(1,0,-1),
|
||||
1.0,
|
||||
false
|
||||
),
|
||||
RayTriTestClass // ray going down +x, hitting a triangle at x=0.75
|
||||
(
|
||||
Vector3(0,0,0),
|
||||
Vector3(1,0,0),
|
||||
Vector3(0.5,1,1),
|
||||
Vector3(1,-1,1),
|
||||
Vector3(0.75,0,-1),
|
||||
0.75,
|
||||
false
|
||||
),
|
||||
RayTriTestClass // ray going down the -z axis hitting an x-y triangle
|
||||
(
|
||||
Vector3(0,0,5), // ray start
|
||||
Vector3(0,0,-5), // ray end
|
||||
Vector3(0,1,0), // p0
|
||||
Vector3(-1,-1,0), // p1
|
||||
Vector3(1,-1,0), // p2
|
||||
0.5,
|
||||
false
|
||||
),
|
||||
RayTriTestClass // ray going down the -z axis, hitting back of an x-y triangle
|
||||
(
|
||||
Vector3(0,0,5), // ray start
|
||||
Vector3(0,0,-5), // ray end
|
||||
Vector3(0,1,0), // p0
|
||||
Vector3(1,-1,0), // p1
|
||||
Vector3(-1,-1,0), // p2
|
||||
0.5,
|
||||
false
|
||||
),
|
||||
RayTriTestClass // ray going down the +x axis, hitting a y-z triangle
|
||||
(
|
||||
Vector3(0,0,0), // ray start
|
||||
Vector3(5,0,0), // ray end
|
||||
Vector3(2,0,1), // p0
|
||||
Vector3(2,1,-1), // p1
|
||||
Vector3(2,-1,-1), // p2
|
||||
2.0f / 5.0f,
|
||||
false
|
||||
),
|
||||
RayTriTestClass // ray going down the -z axis, hitting vertex 2 of the triangle
|
||||
(
|
||||
Vector3(0,0,5), // ray start
|
||||
Vector3(0,0,-5), // ray end
|
||||
Vector3(0,1,0), // p0
|
||||
Vector3(0,0,0), // p1
|
||||
Vector3(1,0,0), // p2
|
||||
0.5f,
|
||||
false
|
||||
),
|
||||
|
||||
RayTriTestClass // ray going down the -z axis, hitting center of edge between p0 and p2
|
||||
(
|
||||
Vector3(0,0,5), // ray start
|
||||
Vector3(0,0,-5), // ray end
|
||||
Vector3(-1,1,0), // p0
|
||||
Vector3(-1,-1,0), // p1
|
||||
Vector3(1,-1,0), // p2
|
||||
0.5f,
|
||||
false
|
||||
),
|
||||
};
|
||||
|
||||
/************************************************************************************************
|
||||
**
|
||||
** Ray - AABox Test Cases
|
||||
**
|
||||
************************************************************************************************/
|
||||
|
||||
class RayAABoxTestClass
|
||||
{
|
||||
public:
|
||||
Vector3 P0;
|
||||
Vector3 P1;
|
||||
AABoxClass Box;
|
||||
float Fraction;
|
||||
bool StartBad;
|
||||
LineSegClass LineSeg;
|
||||
TriClass Tri;
|
||||
|
||||
RayAABoxTestClass
|
||||
(
|
||||
const Vector3 p0, // p0 of ray
|
||||
const Vector3 p1, // p1 of ray
|
||||
const Vector3 center, // center of the box
|
||||
const Vector3 extent, // extent of the box
|
||||
float frac, // expected fraction
|
||||
bool sol // expected start solid
|
||||
) :
|
||||
P0(p0),P1(p1),Box(center,extent),Fraction(frac),StartBad(sol),LineSeg(P0,P1)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
RayAABoxTestClass RayAABoxTestCases[] =
|
||||
{
|
||||
RayAABoxTestClass
|
||||
(
|
||||
Vector3(5,0,0), // p0 of ray
|
||||
Vector3(0,0,0), // p1 of ray
|
||||
Vector3(0,0,0), // center of the box
|
||||
Vector3(1,1,1), // extent of the box
|
||||
4.0f / 5.0f, // expected fraction
|
||||
false
|
||||
),
|
||||
RayAABoxTestClass
|
||||
(
|
||||
Vector3(-2,-5,0), // p0 of ray
|
||||
Vector3(0,0,0), // p1 of ray
|
||||
Vector3(0,0,0), // center of the box
|
||||
Vector3(2,2,2), // extent of the box
|
||||
3.0f / 5.0f, // expected fraction
|
||||
false
|
||||
),
|
||||
RayAABoxTestClass
|
||||
(
|
||||
Vector3(-2,5,0), // p0 of ray
|
||||
Vector3(0,0,0), // p1 of ray
|
||||
Vector3(0,0,0), // center of the box
|
||||
Vector3(10,1,1), // extent of the box
|
||||
4.0f / 5.0f, // expected fraction
|
||||
false
|
||||
),
|
||||
RayAABoxTestClass // ray just clips the corner of the box (in x-y plane)
|
||||
(
|
||||
Vector3(2,0,0), // p0 of ray
|
||||
Vector3(0,2,0), // p1 of ray
|
||||
Vector3(0,0,0), // center of the box
|
||||
Vector3(1,1,1), // extent of the box
|
||||
0.5f, // expected fraction
|
||||
false
|
||||
),
|
||||
RayAABoxTestClass // ray misses box
|
||||
(
|
||||
Vector3(1.01f,-3,0), // p0 of ray
|
||||
Vector3(1.01f,3,0), // p1 of ray
|
||||
Vector3(0,0,0), // center of the box
|
||||
Vector3(1,1,1), // extent of the box
|
||||
1.0f, // expected fraction
|
||||
false
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
void Test_Rays(void)
|
||||
{
|
||||
CastResultStruct result;
|
||||
CastResultStruct result_check;
|
||||
volatile unsigned cycles;
|
||||
int numtests;
|
||||
int i;
|
||||
|
||||
/*
|
||||
** Test the Cast_Ray function with a bunch of ray-triangle pairs.
|
||||
*/
|
||||
Print_Title("Testing ray-triangle intersection.");
|
||||
|
||||
numtests = sizeof(RayTriTestCases)/sizeof(RayTriTestClass);
|
||||
for (i=0; i<numtests; i++) {
|
||||
|
||||
RayTriTestClass * testcase = &(RayTriTestCases[i]);
|
||||
|
||||
result.Fraction = 1.0;
|
||||
result.StartBad = false;
|
||||
result.Normal.Set(0,0,0);
|
||||
|
||||
cycles = Get_CPU_Clock();
|
||||
CollisionMath::Collide(testcase->LineSeg,testcase->Tri,&result);
|
||||
cycles = Get_CPU_Clock() - cycles;
|
||||
|
||||
printf("Ray -> Tri cycles: %d\n",cycles);
|
||||
|
||||
CHECK(i,(fabs(testcase->Fraction - result.Fraction) < 0.001f));
|
||||
}
|
||||
|
||||
/*
|
||||
** Test the Cast_Ray function with a bunch of ray-aabox pairs.
|
||||
*/
|
||||
Print_Title("Testing ray-aabox intersection.");
|
||||
|
||||
numtests = sizeof(RayAABoxTestCases)/sizeof(RayAABoxTestClass);
|
||||
for (i=0; i<numtests; i++) {
|
||||
|
||||
RayAABoxTestClass * testcase = &(RayAABoxTestCases[i]);
|
||||
|
||||
result.Fraction = 1.0;
|
||||
result.StartBad = false;
|
||||
result.Normal.Set(0,0,0);
|
||||
|
||||
cycles = Get_CPU_Clock();
|
||||
CollisionMath::Collide(testcase->LineSeg,testcase->Box,&result);
|
||||
cycles = Get_CPU_Clock() - cycles;
|
||||
|
||||
printf("Ray -> AABox cycles: %d\n",cycles);
|
||||
|
||||
CHECK(i,(fabs(testcase->Fraction - result.Fraction) < 0.001f));
|
||||
}
|
||||
|
||||
/*
|
||||
** Test the Cast_Ray function on some random oriented boxes
|
||||
*/
|
||||
Print_Title("Testing ray-obbox intersection.");
|
||||
for (i=0; i<30; i++) {
|
||||
|
||||
result.Fraction = 1.0;
|
||||
result.StartBad = false;
|
||||
result.Normal.Set(0,0,0);
|
||||
|
||||
// create a random box
|
||||
OBBoxClass box;
|
||||
box.Init_Random(1.0f,2.75f);
|
||||
|
||||
// create a random line
|
||||
LineSegClass line;
|
||||
line.Set_Random(Vector3(-3,-3,-3),Vector3(3,3,3));
|
||||
|
||||
// use the ray-box test
|
||||
cycles = Get_CPU_Clock();
|
||||
CollisionMath::Collide(line,box,&result);
|
||||
cycles = Get_CPU_Clock() - cycles;
|
||||
|
||||
// double-check the result
|
||||
result_check.Fraction = 1.0f;
|
||||
result_check.StartBad = false;
|
||||
result_check.Normal.Set(0,0,0);
|
||||
line_box_test(line,box,&result_check);
|
||||
|
||||
// print what happened
|
||||
bool passed = false;
|
||||
if (fabs(result_check.Fraction - result.Fraction) < 0.001f) {
|
||||
passed = true;
|
||||
}
|
||||
|
||||
printf("test %3d cycles: %6d\tfraction: %1.8f\t",i,cycles,result.Fraction);
|
||||
if (passed) {
|
||||
printf("passed\n");
|
||||
} else if (result.StartBad) {
|
||||
printf("(start inside)\n");
|
||||
} else {
|
||||
printf("<<failed!>>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Test the Overlap_Test function on some random AABoxes
|
||||
*/
|
||||
int total_tests = 0;
|
||||
int total_cycles = 0;
|
||||
int outside_tests = 0;
|
||||
int outside_cycles = 0;
|
||||
int overlap_tests = 0;
|
||||
int overlap_cycles = 0;
|
||||
|
||||
CollisionMath::OverlapType overlap;
|
||||
Print_Title("Testing ray-aabox overlap.");
|
||||
for (i=0; i<10000; i++) {
|
||||
|
||||
// create a random box
|
||||
AABoxClass box;
|
||||
box.Init_Random(-1.0f,1.0f,1.0f,2.0f);
|
||||
|
||||
// create a random line
|
||||
const float DIMENSION = 5.0f;
|
||||
LineSegClass line;
|
||||
line.Set_Random(Vector3(-DIMENSION,-DIMENSION,-DIMENSION),Vector3(DIMENSION,DIMENSION,DIMENSION));
|
||||
|
||||
// use the overlap_test
|
||||
cycles = Get_CPU_Clock();
|
||||
overlap = CollisionMath::Overlap_Test(box,line);
|
||||
cycles = Get_CPU_Clock() - cycles;
|
||||
|
||||
// print what happened
|
||||
printf("test %3d cycles: %6d\tfraction: %1.8f\t",i,cycles,result.Fraction);
|
||||
if (overlap == CollisionMath::OUTSIDE) {
|
||||
printf("outside\n");
|
||||
} else if (overlap == CollisionMath::INSIDE) {
|
||||
printf("inside\n");
|
||||
} else {
|
||||
printf("overlapped\n");
|
||||
}
|
||||
|
||||
// stats
|
||||
total_tests++;
|
||||
total_cycles += cycles;
|
||||
if (overlap == CollisionMath::OUTSIDE) {
|
||||
outside_tests++;
|
||||
outside_cycles += cycles;
|
||||
} else {
|
||||
overlap_tests++;
|
||||
overlap_cycles += cycles;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Total Tests: %d\n",total_tests);
|
||||
printf("Average Cycles: %f\n",(float)total_cycles / (float)total_tests);
|
||||
printf("Outside Tests: %d\n",outside_tests);
|
||||
printf("Average Outside Cycles: %f\n",(float)outside_cycles / (float)outside_tests);
|
||||
printf("Overlap Tests: %d\n",overlap_tests);
|
||||
printf("Average Overlap Cycles: %f\n",(float)overlap_cycles / (float)overlap_tests);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void line_box_test(const LineSegClass & line,const OBBoxClass & box,CastResultStruct * res)
|
||||
{
|
||||
Vector3 point[8];
|
||||
|
||||
point[0] = box.Center + box.Basis * Vector3( box.Extent.X, box.Extent.Y, box.Extent.Z);
|
||||
point[1] = box.Center + box.Basis * Vector3(-box.Extent.X, box.Extent.Y, box.Extent.Z);
|
||||
point[2] = box.Center + box.Basis * Vector3(-box.Extent.X,-box.Extent.Y, box.Extent.Z);
|
||||
point[3] = box.Center + box.Basis * Vector3( box.Extent.X,-box.Extent.Y, box.Extent.Z);
|
||||
|
||||
point[4] = box.Center + box.Basis * Vector3( box.Extent.X, box.Extent.Y,-box.Extent.Z);
|
||||
point[5] = box.Center + box.Basis * Vector3(-box.Extent.X, box.Extent.Y,-box.Extent.Z);
|
||||
point[6] = box.Center + box.Basis * Vector3(-box.Extent.X,-box.Extent.Y,-box.Extent.Z);
|
||||
point[7] = box.Center + box.Basis * Vector3( box.Extent.X,-box.Extent.Y,-box.Extent.Z);
|
||||
|
||||
static int triverts[12][3] =
|
||||
{
|
||||
{ 0,1,2 },
|
||||
{ 0,2,3 },
|
||||
{ 4,5,1 },
|
||||
{ 4,1,0 },
|
||||
{ 1,5,6 },
|
||||
{ 1,6,2 },
|
||||
{ 3,2,6 },
|
||||
{ 3,6,7 },
|
||||
{ 4,0,3 },
|
||||
{ 4,3,7 },
|
||||
{ 4,7,6 },
|
||||
{ 4,6,5 }
|
||||
};
|
||||
|
||||
// first, check if ray starts inside box?
|
||||
|
||||
// now, check for collision with each triangle
|
||||
for (int i=0; i<12; i++) {
|
||||
|
||||
TriClass tri;
|
||||
Vector3 normal;
|
||||
|
||||
tri.V[0] = &point[triverts[i][0]];
|
||||
tri.V[1] = &point[triverts[i][1]];
|
||||
tri.V[2] = &point[triverts[i][2]];
|
||||
tri.N = &normal;
|
||||
tri.Compute_Normal();
|
||||
|
||||
CollisionMath::Collide(line,tri,res);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user