Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.

This commit is contained in:
LFeenanEA 2025-02-27 17:34:39 +00:00
parent 2e338c00cb
commit 3d0ee53a05
No known key found for this signature in database
GPG key ID: C6EBE8C2EA08F7E0
6072 changed files with 2283311 additions and 0 deletions

View file

@ -0,0 +1,46 @@
/*
** Command & Conquer Generals(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/>.
*/
/*****************************************************************
*
* Project: 3DTEST1 (3d Test Program)
*
* File: bittype.h
*
* Start Date: Dec 18, 1996
*
* Programmer: Greg Hjelstrom
*
*****************************************************************/
#ifndef BITTYPE_H
#define BITTYPE_H
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
typedef signed char sint8;
typedef signed short sint16;
typedef signed long sint32;
typedef float float32;
typedef double float64;
#endif //BITTYPE_H

View file

@ -0,0 +1,334 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/max2w3d/EULER.CPP 5 12/02/97 10:14p Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G 3D Engine *
* *
* $Archive:: /Commando/Code/Tools/max2w3d/EULER.CPP $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 11/13/97 7:16p $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "euler.h"
#include <float.h>
/*********************************************************************
There are 24 possible conventions for Euler angles. They can
be designated by:
EulerAxis = Axis used initially
EulerParity = parity of axis permutation (even = x,y,z)
EulerRepeat = is last axis a repeat of the initial axis?
EulerFrame = frame from which axes are taken (rotating or static)
*********************************************************************/
#define EULER_FRAME_STATIC 0x00000000
#define EULER_FRAME_ROTATING 0x00000001
#define EULER_FRAME(order) ((unsigned)(order) & 1)
#define EULER_REPEAT_NO 0x00000000
#define EULER_REPEAT_YES 0x00000001
#define EULER_REPEAT(order) (((unsigned)(order) >> 1) & 1)
#define EULER_PARITY_EVEN 0x00000000
#define EULER_PARITY_ODD 0x00000001
#define EULER_PARITY(order) (((unsigned)(order) >> 2) & 1)
#define EULER_BUILD_ORDER(i,p,r,f) (((((((i) << 1) + (p)) << 1) + (r)) << 1) + (f))
/* static axes */
int EulerOrderXYZs = EULER_BUILD_ORDER(0, EULER_PARITY_EVEN, EULER_REPEAT_NO, EULER_FRAME_STATIC);
int EulerOrderXYXs = EULER_BUILD_ORDER(0, EULER_PARITY_EVEN, EULER_REPEAT_YES, EULER_FRAME_STATIC);
int EulerOrderXZYs = EULER_BUILD_ORDER(0, EULER_PARITY_ODD, EULER_REPEAT_NO, EULER_FRAME_STATIC);
int EulerOrderXZXs = EULER_BUILD_ORDER(0, EULER_PARITY_ODD, EULER_REPEAT_YES, EULER_FRAME_STATIC);
int EulerOrderYZXs = EULER_BUILD_ORDER(1, EULER_PARITY_EVEN, EULER_REPEAT_NO, EULER_FRAME_STATIC);
int EulerOrderYZYs = EULER_BUILD_ORDER(1, EULER_PARITY_EVEN, EULER_REPEAT_YES, EULER_FRAME_STATIC);
int EulerOrderYXZs = EULER_BUILD_ORDER(1, EULER_PARITY_ODD, EULER_REPEAT_NO, EULER_FRAME_STATIC);
int EulerOrderYXYs = EULER_BUILD_ORDER(1, EULER_PARITY_ODD, EULER_REPEAT_YES, EULER_FRAME_STATIC);
int EulerOrderZXYs = EULER_BUILD_ORDER(2, EULER_PARITY_EVEN, EULER_REPEAT_NO, EULER_FRAME_STATIC);
int EulerOrderZXZs = EULER_BUILD_ORDER(2, EULER_PARITY_EVEN, EULER_REPEAT_YES, EULER_FRAME_STATIC);
int EulerOrderZYXs = EULER_BUILD_ORDER(2, EULER_PARITY_ODD, EULER_REPEAT_NO, EULER_FRAME_STATIC);
int EulerOrderZYZs = EULER_BUILD_ORDER(2, EULER_PARITY_ODD, EULER_REPEAT_YES, EULER_FRAME_STATIC);
/* rotating axes */
int EulerOrderZYXr = EULER_BUILD_ORDER(0, EULER_PARITY_EVEN, EULER_REPEAT_NO, EULER_FRAME_ROTATING);
int EulerOrderXYXr = EULER_BUILD_ORDER(0, EULER_PARITY_EVEN, EULER_REPEAT_YES, EULER_FRAME_ROTATING);
int EulerOrderYZXr = EULER_BUILD_ORDER(0, EULER_PARITY_ODD, EULER_REPEAT_NO, EULER_FRAME_ROTATING);
int EulerOrderXZXr = EULER_BUILD_ORDER(0, EULER_PARITY_ODD, EULER_REPEAT_YES, EULER_FRAME_ROTATING);
int EulerOrderXZYr = EULER_BUILD_ORDER(1, EULER_PARITY_EVEN, EULER_REPEAT_NO, EULER_FRAME_ROTATING);
int EulerOrderYZYr = EULER_BUILD_ORDER(1, EULER_PARITY_EVEN, EULER_REPEAT_YES, EULER_FRAME_ROTATING);
int EulerOrderZXYr = EULER_BUILD_ORDER(1, EULER_PARITY_ODD, EULER_REPEAT_NO, EULER_FRAME_ROTATING);
int EulerOrderYXYr = EULER_BUILD_ORDER(1, EULER_PARITY_ODD, EULER_REPEAT_YES, EULER_FRAME_ROTATING);
int EulerOrderYXZr = EULER_BUILD_ORDER(2, EULER_PARITY_EVEN, EULER_REPEAT_NO, EULER_FRAME_ROTATING);
int EulerOrderZXZr = EULER_BUILD_ORDER(2, EULER_PARITY_EVEN, EULER_REPEAT_YES, EULER_FRAME_ROTATING);
int EulerOrderXYZr = EULER_BUILD_ORDER(2, EULER_PARITY_ODD, EULER_REPEAT_NO, EULER_FRAME_ROTATING);
int EulerOrderZYZr = EULER_BUILD_ORDER(2, EULER_PARITY_ODD, EULER_REPEAT_YES, EULER_FRAME_ROTATING);
/* local functions */
static void _euler_unpack_order(int order,int &i,int &j,int &k,int &h,int &n,int &s,int &f);
static int _euler_axis_i(int order);
static int _euler_axis_j(int order);
static int _euler_axis_k(int order);
static int _euler_axis_h(int order);
static void _mat_to_array(const Matrix3 & tm, float M[3][4]);
static void _array_to_mat(float M[3][4], Matrix3 & tm);
EulerAnglesClass::EulerAnglesClass(const Matrix3 & M,int order)
{
this->From_Matrix(M,order);
}
double EulerAnglesClass::Get_Angle(int i)
{
return Angle[i];
}
void EulerAnglesClass::From_Matrix(const Matrix3 & tm, int order)
{
float M[3][4];
_mat_to_array(tm,M);
int i,j,k,h,n,s,f;
Order = order;
_euler_unpack_order(order,i,j,k,h,n,s,f);
if (s == EULER_REPEAT_YES) {
double sy = sqrt(M[i][j]*M[i][j] + M[i][k]*M[i][k]);
if (sy > 16*FLT_EPSILON) {
Angle[0] = atan2(M[i][j],M[i][k]);
Angle[1] = atan2(sy,M[i][i]);
Angle[2] = atan2(M[j][i],-M[k][i]);
} else {
Angle[0] = atan2(-M[j][k],M[j][j]);
Angle[1] = atan2(sy,M[i][i]);
Angle[2] = 0.0;
}
} else {
double cy = sqrt(M[i][i]*M[i][i] + M[j][i]*M[j][i]);
if (cy > 16*FLT_EPSILON) {
Angle[0] = atan2(M[k][j],M[k][k]);
Angle[1] = atan2(-M[k][i],cy);
Angle[2] = atan2(M[j][i],M[i][i]);
} else {
Angle[0] = atan2(-M[j][k],M[j][j]);
Angle[1] = atan2(-M[k][i],cy);
Angle[2] = 0;
}
}
if (n==EULER_PARITY_ODD) { Angle[0] = -Angle[0]; Angle[1] = -Angle[1]; Angle[2] = -Angle[2]; }
if (f==EULER_FRAME_ROTATING) { double t = Angle[0]; Angle[0] = Angle[2]; Angle[2] = t; }
// Trying to "clean" up the eulers, special cased for XYZr
if (order == EulerOrderXYZr) {
double x2 = PI + Angle[0];
double y2 = PI - Angle[1];
double z2 = PI + Angle[2];
if (x2 > PI) {
x2 = x2 - 2*PI;
}
if (y2 > PI) {
y2 = y2 - 2*PI;
}
if (z2 > PI) {
z2 = z2 - 2*PI;
}
double mag0 = Angle[0]*Angle[0] + Angle[1]*Angle[1] + Angle[2]*Angle[2];
double mag1 = x2*x2 + y2*y2 + z2*z2;
if (mag1 < mag0) {
Angle[0] = x2;
Angle[1] = y2;
Angle[2] = z2;
}
}
}
void EulerAnglesClass::To_Matrix(Matrix3 & tm)
{
float M[3][4] = {
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f }
};
double a0,a1,a2;
double ti,tj,th,ci,cj,ch,si,sj,sh,cc,cs,sc,ss;
int i,j,k,h,n,s,f;
a0 = Angle[0];
a1 = Angle[1];
a2 = Angle[2];
_euler_unpack_order(Order,i,j,k,h,n,s,f);
if (f == EULER_FRAME_ROTATING) {
double t = a0; a0 = a2; a2 = t;
}
if (n == EULER_PARITY_ODD) {
a0 = -a0; a1 = -a1; a2 = -a2;
}
ti = a0; tj = a1; th = a2;
ci = cos(ti); cj = cos(tj); ch = cos(th);
si = sin(ti); sj = sin(tj); sh = sin(th);
cc = ci*ch;
cs = ci*sh;
sc = si*ch;
ss = si*sh;
if (s == EULER_REPEAT_YES) {
M[i][i] = (float)(cj); M[i][j] = (float)(sj*si); M[i][k] = (float)(sj*ci);
M[j][i] = (float)(sj*sh); M[j][j] = (float)(-cj*ss+cc); M[j][k] = (float)(-cj*cs-sc);
M[k][i] = (float)(-sj*ch); M[k][j] = (float)(cj*sc+cs); M[k][k] = (float)(cj*cc-ss);
} else {
M[i][i] = (float)(cj*ch); M[i][j] = (float)(sj*sc-cs); M[i][k] = (float)(sj*cc+ss);
M[j][i] = (float)(cj*sh); M[j][j] = (float)(sj*ss+cc); M[j][k] = (float)(sj*cs-sc);
M[k][i] = (float)(-sj); M[k][j] = (float)(cj*si); M[k][k] = (float)(cj*ci);
}
_array_to_mat(M,tm);
}
static int _euler_safe[] = { 0,1,2,0 };
static int _euler_next[] = { 1,2,0,1 };
int _euler_axis_i(int order)
{
return _euler_safe[ (order>>3) & 3 ];
}
int _euler_axis_j(int order)
{
int index = _euler_axis_i(order);
if (EULER_PARITY(order) == 1) {
index++;
}
return _euler_next[ index ];
}
int _euler_axis_k(int order)
{
int index = _euler_axis_i(order);
if (EULER_PARITY(order) != 1) {
index++;
}
return _euler_next[ index ];
}
int _euler_axis_h(int order)
{
if (EULER_REPEAT(order) == 1) {
return _euler_axis_k(order);
} else {
return _euler_axis_i(order);
}
}
void _euler_unpack_order(int order,int &i,int &j,int &k,int &h,int &n,int &s,int &f)
{
f = order & 1;
order >>= 1;
s = order & 1;
order >>= 1;
n = order & 1;
order >>= 1;
i = _euler_safe[order & 3];
j = _euler_next[i+n];
k = _euler_next[i+1-n];
h = (s ? k : i);
}
void _mat_to_array(const Matrix3 & tm, float M[3][4])
{
// Translation vector
Point3 trans = tm.GetRow(3);
M[0][3] = trans.x;
M[1][3] = trans.y;
M[2][3] = trans.z;
// Rotation matrix
for (int k=0; k<3; k++) {
Point3 v = tm.GetRow(k);
M[0][k] = v.x;
M[1][k] = v.y;
M[2][k] = v.z;
}
}
void _array_to_mat(float M[3][4], Matrix3 & tm)
{
// translation
Point3 row(M[3][0],M[3][1],M[3][2]);
tm.SetRow(3, row);
// rotation
for (int k=0; k<3; k++) {
row = Point3(M[0][k],M[1][k],M[2][k]);
tm.SetRow(k, row);
}
}

View file

@ -0,0 +1,119 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/max2w3d/EULER.H 3 10/28/97 6:08p Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G 3D Engine *
* *
* $Archive:: /Commando/Code/Tools/max2w3d/EULER.H $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 10/14/97 3:08p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef EULER_H
#define EULER_H
#include <Max.h>
/*********************************************************************
Euler Order Types
When creating an EulerAngles object, use one of the below
constants to describe the axis convention.
XYZ - order of the axes
s/r - whether the rotations are applied to the static or
rotating frame.
*********************************************************************/
/* static axes */
extern int EulerOrderXYZs;
extern int EulerOrderXYXs;
extern int EulerOrderXZYs;
extern int EulerOrderXZXs;
extern int EulerOrderYZXs;
extern int EulerOrderYZYs;
extern int EulerOrderYXZs;
extern int EulerOrderYXYs;
extern int EulerOrderZXYs;
extern int EulerOrderZXZs;
extern int EulerOrderZYXs;
extern int EulerOrderZYZs;
/* rotating axes */
extern int EulerOrderXYZr;
extern int EulerOrderXYXr;
extern int EulerOrderXZYr;
extern int EulerOrderXZXr;
extern int EulerOrderYZXr;
extern int EulerOrderYZYr;
extern int EulerOrderYXZr;
extern int EulerOrderYXYr;
extern int EulerOrderZXYr;
extern int EulerOrderZXZr;
extern int EulerOrderZYXr;
extern int EulerOrderZYZr;
/*********************************************************************
EulerAnglesClass
The purpose for this class is mainly for conversion. You can
choose a convention for the order of your rotations and then
convert matrices into a set of euler angles.
This implementation is based on the code in Graphics Gems IV
by Ken Shoemake. The original article is on page 222.
*********************************************************************/
class EulerAnglesClass
{
public:
EulerAnglesClass(void) : Order(0) { Angle[0] = 0.0; Angle[1] = 0.0; Angle[2] = 0.0; };
EulerAnglesClass(const Matrix3 & from,int order);
void From_Matrix(const Matrix3 & from,int order);
void To_Matrix(Matrix3 & M);
double Get_Angle(int i);
private:
double Angle[3];
int Order;
};
#endif /*EULER_H*/

View file

@ -0,0 +1,125 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/max2w3d/PROGRESS.H 5 10/28/97 6:08p Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G 3D engine *
* *
* File Name : PROGRESS.H *
* *
* Programmer : James McNeil *
* *
* Start Date : 06/19/97 *
* *
* Last Update : June 19, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef PROGRESS_H
#define PROGRESS_H
#include "always.h"
class Progress_Meter_Class
{
public:
Progress_Meter_Class
(
Interface * gi,
float base,
float range
):
Max ( gi ),
Base ( base ),
Range ( range ),
Amount_Done ( 0.0f ),
Increment ( 0.0f ),
Accum( 0.0f ),
Cancel_Requested ( FALSE )
{
}
Progress_Meter_Class ( Progress_Meter_Class & other, float sub_amount ):
Max ( other.Max ),
Base ( other.Base + other.Amount_Done * other.Range ),
Range ( other.Range * sub_amount ),
Amount_Done ( 0.0f ),
Increment ( 0.0f ),
Accum ( other.Accum ),
Cancel_Requested ( other.Cancel_Requested )
{
}
void Finish_In_Steps ( int number_of_steps )
{
Increment = (1.0f - Amount_Done) / number_of_steps;
}
void Add_Increment ()
{
Set_Amount_Done ( Amount_Done + Increment );
}
void Set_Amount_Done ( float percentage )
{
Accum += percentage;
Amount_Done = percentage;
if (Accum > 0.01f) {
Max->ProgressUpdate ( (int) (Amount_Done * Range + Base) );
Accum = 0.0f;
}
if (Max->GetCancel())
{
int choice = MessageBox
(
Max->GetMAXHWnd(),
_T("Do you really want to cancel the export?"),
_T("Cancel Export?"), MB_ICONQUESTION | MB_YESNO
);
if ( choice == IDYES )
Cancel_Requested = TRUE;
else
Max->SetCancel ( FALSE );
}
}
BOOL Cancelled () { return Cancel_Requested; }
float Increment;
private:
Interface * Max;
float Base;
float Range;
float Amount_Done;
float Accum;
BOOL Cancel_Requested;
};
#endif /* PROGRESS_H */

View file

@ -0,0 +1,355 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Code/Tools/pluglib/Vector.CPP $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 3/29/98 10:42a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* BooleanVectorClass::BooleanVectorClass -- Copy constructor for boolean array. *
* BooleanVectorClass::BooleanVectorClass -- Explicit data buffer constructor. *
* BooleanVectorClass::Clear -- Resets boolean vector to empty state. *
* BooleanVectorClass::Fixup -- Updates the boolean vector to a known state. *
* BooleanVectorClass::Reset -- Clear all boolean values in array. *
* BooleanVectorClass::Resize -- Resizes a boolean vector object. *
* BooleanVectorClass::Set -- Forces all boolean elements to true. *
* BooleanVectorClass::operator = -- Assignment operator. *
* BooleanVectorClass::operator == -- Comparison operator for boolean vector. *
* VectorClass<T>::Clear -- Frees and clears the vector. *
* VectorClass<T>::ID -- Finds object ID based on value. *
* VectorClass<T>::ID -- Pointer based conversion to index number. *
* VectorClass<T>::Resize -- Changes the size of the vector. *
* VectorClass<T>::VectorClass -- Constructor for vector class. *
* VectorClass<T>::VectorClass -- Copy constructor for vector object. *
* VectorClass<T>::operator = -- The assignment operator. *
* VectorClass<T>::operator == -- Equality operator for vector objects. *
* VectorClass<T>::~VectorClass -- Default destructor for vector class. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "vector.h"
#include <string.h>
/*
** The following template function can be located here ONLY if all the instantiations are
** declared in a header file this module includes. By placing the template functions here,
** it speeds up compiler operation and reduces object module size.
*/
//----------------------------------------------------------------------------------------------
/***********************************************************************************************
* BooleanVectorClass::BooleanVectorClass -- Explicit data buffer constructor. *
* *
* This is the constructor for a boolean array. This constructor takes the memory pointer *
* provided as assigns that as the array data pointer. *
* *
* INPUT: size -- The size of the array (in bits). *
* *
* array -- Pointer to the memory that the array is to use. *
* *
* OUTPUT: none *
* *
* WARNINGS: You must make sure that the memory specified is large enough to contain the *
* bits specified. *
* *
* HISTORY: *
* 07/18/1995 JLB : Created. *
*=============================================================================================*/
BooleanVectorClass::BooleanVectorClass(unsigned size, unsigned char * array) :
BitCount(size),
Copy(false),
LastIndex(-1),
BitArray(0, 0)
{
BitArray.Resize(((size + (8-1)) / 8), array);
// LastIndex = -1;
// BitCount = size;
}
/***********************************************************************************************
* BooleanVectorClass::BooleanVectorClass -- Copy constructor of boolean array. *
* *
* This is the copy constructor for a boolean array. It is used to make a duplicate of the *
* boolean array. *
* *
* INPUT: vector -- Reference to the vector to be duplicated. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/18/1995 JLB : Created. *
*=============================================================================================*/
BooleanVectorClass::BooleanVectorClass(BooleanVectorClass const & vector)
{
LastIndex = -1;
*this = vector;
}
/***********************************************************************************************
* BooleanVectorClass::operator = -- Assignment operator. *
* *
* This routine will make a copy of the specified boolean vector array. The vector is *
* copied into an already constructed existing vector. The values from the existing vector *
* are destroyed by this copy. *
* *
* INPUT: vector -- Reference to the vector to make a copy of. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/18/1995 JLB : Created. *
*=============================================================================================*/
BooleanVectorClass & BooleanVectorClass::operator =(BooleanVectorClass const & vector)
{
Fixup();
Copy = vector.Copy;
LastIndex = vector.LastIndex;
BitArray = vector.BitArray;
BitCount = vector.BitCount;
return(*this);
}
/***********************************************************************************************
* BooleanVectorClass::operator == -- Comparison operator for boolean vector. *
* *
* This is the comparison operator for a boolean vector class. Boolean vectors are equal *
* if the bit count and bit values are identical. *
* *
* INPUT: vector -- Reference to the vector to compare to. *
* *
* OUTPUT: Are the boolean vectors identical? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/18/1995 JLB : Created. *
*=============================================================================================*/
bool BooleanVectorClass::operator == (const BooleanVectorClass & vector)
{
Fixup(LastIndex);
return(BitCount == vector.BitCount && BitArray == vector.BitArray);
}
/***********************************************************************************************
* BooleanVectorClass::Resize -- Resizes a boolean vector object. *
* *
* This routine will resize the boolean vector object. An index value used with a boolean *
* vector must be less than the value specified in as the new size. *
* *
* INPUT: size -- The new maximum size of this boolean vector. *
* *
* OUTPUT: Was the boolean vector sized successfully? *
* *
* WARNINGS: The boolean array might be reallocated or even deleted by this routine. *
* *
* HISTORY: *
* 07/18/1995 JLB : Created. *
*=============================================================================================*/
int BooleanVectorClass::Resize(unsigned size)
{
Fixup();
if (size > 0) {
/*
** Record the previous bit count of the boolean vector. This is used
** to determine if the array has grown in size and thus clearing is
** necessary.
*/
unsigned oldsize = BitCount;
/*
** Actually resize the bit array. Since this is a bit packed array,
** there are 8 elements per byte (rounded up).
*/
int success = BitArray.Resize(((size + (8-1)) / 8));
/*
** Since there is no default constructor for bit packed integers, a manual
** clearing of the bits is required.
*/
BitCount = size;
if (success && oldsize < size) {
for (unsigned index = oldsize; index < size; index++) {
(*this)[index] = 0;
}
}
return(success);
}
/*
** Resizing to zero is the same as clearing and deallocating the array.
** This is always successful.
*/
Clear();
return(true);
}
/***********************************************************************************************
* BooleanVectorClass::Clear -- Resets boolean vector to empty state. *
* *
* This routine will clear out the boolean array. This will free any allocated memory and *
* result in the boolean vector being unusable until the Resize function is subsequently *
* called. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: The boolean vector cannot be used until it is resized to a non null condition. *
* *
* HISTORY: *
* 07/18/1995 JLB : Created. *
*=============================================================================================*/
void BooleanVectorClass::Clear(void)
{
Fixup();
BitCount = 0;
BitArray.Clear();
}
/***********************************************************************************************
* BooleanVectorClass::Reset -- Clear all boolean values in array. *
* *
* This is the preferred (and quick) method to clear the boolean array to a false condition.*
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/18/1995 JLB : Created. *
*=============================================================================================*/
void BooleanVectorClass::Reset(void)
{
LastIndex = -1;
if (BitArray.Length() > 0) {
memset(&BitArray[0], '\0', BitArray.Length());
}
}
/***********************************************************************************************
* BooleanVectorClass::Set -- Forces all boolean elements to true. *
* *
* This is the preferred (and fast) way to set all boolean elements to true. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/18/1995 JLB : Created. *
*=============================================================================================*/
void BooleanVectorClass::Set(void)
{
LastIndex = -1;
if (BitArray.Length() > 0) {
memset(&BitArray[0], '\xFF', BitArray.Length());
}
}
/***********************************************************************************************
* BooleanVectorClass::Fixup -- Updates the boolean vector to a known state. *
* *
* Use this routine to set the boolean value copy to match the appropriate bit in the *
* boolean array. The boolean array will be updated with any changes from the last time *
* a value was fetched from the boolean vector. By using this update method, the boolean *
* array can be treated as a normal array even though the elements are composed of *
* otherwise inaccessible bits. *
* *
* INPUT: index -- The index to set the new copy value to. If the index is -1, then the *
* previous value will be updated into the vector array, but no new value *
* will be fetched from it. *
* *
* OUTPUT: none *
* *
* WARNINGS: Always call this routine with "-1" if any direct manipulation of the bit *
* array is to occur. This ensures that the bit array is accurate. *
* *
* HISTORY: *
* 07/18/1995 JLB : Created. *
*=============================================================================================*/
void BooleanVectorClass::Fixup(int index) const
{
/*
** If the requested index value is illegal, then force the index
** to be -1. This is the default non-index value.
*/
if ((unsigned)index >= (unsigned)BitCount) {
index = -1;
}
/*
** If the new index is different than the previous index, there might
** be some fixing up required.
*/
if (index != LastIndex) {
/*
** If the previously fetched boolean value was changed, then update
** the boolean array accordingly.
*/
if (LastIndex != -1) {
assert(unsigned(LastIndex) < unsigned(BitCount));
Set_Bit((void*)&BitArray[0], LastIndex, Copy);
}
/*
** If this new current index is valid, then fill in the reference boolean
** value with the appropriate data from the bit array.
*/
if (index != -1) {
assert(unsigned(index) < unsigned(BitCount));
((unsigned char &)Copy) = (unsigned char)Get_Bit((void*)&BitArray[0], index);
// ((unsigned char&)Copy) = Get_Bit((void*)&BitArray[0], index);
}
((BooleanVectorClass *)this)->LastIndex = index;
}
}

View file

@ -0,0 +1,999 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Code/Library/Vector.H $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 3/12/98 2:09p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* VectorClass<T>::VectorClass -- Constructor for vector class. *
* VectorClass<T>::~VectorClass -- Default destructor for vector class. *
* VectorClass<T>::VectorClass -- Copy constructor for vector object. *
* VectorClass<T>::operator = -- The assignment operator. *
* VectorClass<T>::operator == -- Equality operator for vector objects. *
* VectorClass<T>::Clear -- Frees and clears the vector. *
* VectorClass<T>::Resize -- Changes the size of the vector. *
* DynamicVectorClass<T>::DynamicVectorClass -- Constructor for dynamic vector. *
* DynamicVectorClass<T>::Resize -- Changes the size of a dynamic vector. *
* DynamicVectorClass<T>::Add -- Add an element to the vector. *
* DynamicVectorClass<T>::Delete -- Remove the specified object from the vector. *
* DynamicVectorClass<T>::Delete -- Deletes the specified index from the vector. *
* VectorClass<T>::ID -- Pointer based conversion to index number. *
* VectorClass<T>::ID -- Finds object ID based on value. *
* DynamicVectorClass<T>::ID -- Find matching value in the dynamic vector. *
* DynamicVectorClass<T>::Uninitialized_Add -- Add an empty place to the vector. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef VECTOR_H
#define VECTOR_H
#include "noinit.h"
#include <assert.h>
#include <new.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
/**************************************************************************
** This is a general purpose vector class. A vector is defined by this
** class, as an array of arbitrary objects where the array can be dynamically
** sized. Because is deals with arbitrary object types, it can handle everything.
** As a result of this, it is not terribly efficient for integral objects (such
** as char or int). It will function correctly, but the copy constructor and
** equality operator could be highly optimized if the integral type were known.
** This efficiency can be implemented by deriving an integral vector template
** from this one in order to supply more efficient routines.
*/
// Why, oh why does Visual C need this!!! It's bugged. <sigh>
#pragma warning(disable : 4505)
template<class T>
class VectorClass
{
public:
VectorClass(NoInitClass const &) {};
VectorClass(int size=0, T const * array=0);
VectorClass(VectorClass<T> const &); // Copy constructor.
virtual ~VectorClass(void);
T & operator[](int index) {assert(unsigned(index) < unsigned(VectorMax));return(Vector[index]);};
T const & operator[](int index) const {assert(unsigned(index) < unsigned(VectorMax));return(Vector[index]);};
VectorClass<T> & operator = (VectorClass<T> const &); // Assignment operator.
virtual bool operator == (VectorClass<T> const &) const; // Equality operator.
virtual bool Resize(int newsize, T const * array=0);
virtual void Clear(void);
int Length(void) const {return VectorMax;};
virtual int ID(T const * ptr); // Pointer based identification.
virtual int ID(T const & ptr); // Value based identification.
protected:
/*
** This is a pointer to the allocated vector array of elements.
*/
T * Vector;
/*
** This is the maximum number of elements allowed in this vector.
*/
int VectorMax;
/*
** This indicates if the vector is in a valid (even if empty) state.
*/
bool IsValid;
/*
** Does the vector data pointer refer to memory that this class has manually
** allocated? If so, then this class is responsible for deleting it.
*/
bool IsAllocated;
};
/***********************************************************************************************
* VectorClass<T>::VectorClass -- Constructor for vector class. *
* *
* This constructor for the vector class is passed the initial size of the vector and an *
* optional pointer to a preallocated block of memory that the vector will be placed in. *
* If this optional pointer is NULL (or not provided), then the vector is allocated out *
* of free store (with the "new" operator). *
* *
* INPUT: size -- The number of elements to initialize this vector to. *
* *
* array -- Optional pointer to a previously allocated memory block to hold the *
* vector. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
VectorClass<T>::VectorClass(int size, T const * array) :
Vector(0),
VectorMax(size),
IsValid(true),
IsAllocated(false)
{
/*
** Allocate the vector. The default constructor will be called for every
** object in this vector.
*/
if (size) {
if (array) {
Vector = new((void*)array) T[size];
} else {
Vector = new T[size];
IsAllocated = true;
}
}
}
/***********************************************************************************************
* VectorClass<T>::~VectorClass -- Default destructor for vector class. *
* *
* This is the default destructor for the vector class. It will deallocate any memory *
* that it may have allocated. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
VectorClass<T>::~VectorClass(void)
{
VectorClass<T>::Clear();
}
/***********************************************************************************************
* VectorClass<T>::VectorClass -- Copy constructor for vector object. *
* *
* This is the copy constructor for the vector class. It will duplicate the provided *
* vector into the new vector being created. *
* *
* INPUT: vector -- Reference to the vector to use as a copy. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
VectorClass<T>::VectorClass(VectorClass<T> const & vector) :
Vector(0),
VectorMax(0),
IsValid(true),
IsAllocated(false)
{
*this = vector;
}
/***********************************************************************************************
* VectorClass<T>::operator = -- The assignment operator. *
* *
* This the the assignment operator for vector objects. It will alter the existing lvalue *
* vector to duplicate the rvalue one. *
* *
* INPUT: vector -- The rvalue vector to copy into the lvalue one. *
* *
* OUTPUT: Returns with reference to the newly copied vector. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
VectorClass<T> & VectorClass<T>::operator =(VectorClass<T> const & vector)
{
if (this != &vector) {
Clear();
VectorMax = vector.Length();
if (VectorMax) {
Vector = new T[VectorMax];
if (Vector) {
IsAllocated = true;
for (int index = 0; index < VectorMax; index++) {
Vector[index] = vector[index];
}
}
} else {
Vector = 0;
IsAllocated = false;
}
}
return(*this);
}
/***********************************************************************************************
* VectorClass<T>::operator == -- Equality operator for vector objects. *
* *
* This operator compares two vectors for equality. It does this by performing an object *
* by object comparison between the two vectors. *
* *
* INPUT: vector -- The right vector expression. *
* *
* OUTPUT: bool; Are the two vectors essentially equal? (do they contain comparable elements *
* in the same order?) *
* *
* WARNINGS: The equality operator must exist for the objects that this vector contains. *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
bool VectorClass<T>::operator == (VectorClass<T> const & vector) const
{
if (VectorMax == vector.Length()) {
for (int index = 0; index < VectorMax; index++) {
if (Vector[index] != vector[index]) {
return(false);
}
}
return(true);
}
return(false);
}
/***********************************************************************************************
* VectorClass<T>::ID -- Pointer based conversion to index number. *
* *
* Use this routine to convert a pointer to an element in the vector back into the index *
* number of that object. This routine ONLY works with actual pointers to object within *
* the vector. For "equivalent" object index number (such as with similar integral values) *
* then use the "by value" index number ID function. *
* *
* INPUT: pointer -- Pointer to an actual object in the vector. *
* *
* OUTPUT: Returns with the index number for the object pointed to by the parameter. *
* *
* WARNINGS: This routine is only valid for actual pointers to object that exist within *
* the vector. All other object pointers will yield undefined results. *
* *
* HISTORY: *
* 03/13/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
inline int VectorClass<T>::ID(T const * ptr)
{
if (!IsValid) return(0);
return(((unsigned long)ptr - (unsigned long)&(*this)[0]) / sizeof(T));
}
/***********************************************************************************************
* VectorClass<T>::ID -- Finds object ID based on value. *
* *
* Use this routine to find the index value of an object with equivalent value in the *
* vector. Typical use of this would be for integral types. *
* *
* INPUT: object -- Reference to the object that is to be looked up in the vector. *
* *
* OUTPUT: Returns with the index number of the object that is equivalent to the one *
* specified. If no matching value could be found then -1 is returned. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/13/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
int VectorClass<T>::ID(T const & object)
{
if (!IsValid) return(0);
for (int index = 0; index < VectorMax; index++) {
if ((*this)[index] == object) {
return(index);
}
}
return(-1);
}
/***********************************************************************************************
* VectorClass<T>::Clear -- Frees and clears the vector. *
* *
* Use this routine to reset the vector to an empty (non-allocated) state. A vector will *
* free all allocated memory when this routine is called. In order for the vector to be *
* useful after this point, the Resize function must be called to give it element space. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
void VectorClass<T>::Clear(void)
{
if (Vector && IsAllocated) {
delete[] Vector;
Vector = 0;
}
IsAllocated = false;
VectorMax = 0;
}
/***********************************************************************************************
* VectorClass<T>::Resize -- Changes the size of the vector. *
* *
* This routine is used to change the size (usually to increase) the size of a vector. This *
* is the only way to increase the vector's working room (number of elements). *
* *
* INPUT: newsize -- The desired size of the vector. *
* *
* array -- Optional pointer to a previously allocated memory block that the *
* array will be located in. If this parameter is not supplied, then *
* the array will be allocated from free store. *
* *
* OUTPUT: bool; Was the array resized successfully? *
* *
* WARNINGS: Failure to succeed could be the result of running out of memory. *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
bool VectorClass<T>::Resize(int newsize, T const * array)
{
if (newsize) {
/*
** Allocate a new vector of the size specified. The default constructor
** will be called for every object in this vector.
*/
T * newptr;
/*
** Either create a new memory block for the object array or initialize
** an existing block as indicated by the array parameter. When creating a new
** memory block, flag that the vector object is currently in an invalid
** state. This is necessary because the default constructor for the object
** elements may look to the vector to fetch their ID number.
*/
IsValid = false;
if (!array) {
newptr = new T[newsize];
} else {
newptr = new((void*)array) T[newsize];
}
IsValid = true;
if (!newptr) {
return(false);
}
/*
** If there is an old vector, then it must be copied (as much as is feasible)
** to the new vector.
*/
if (Vector != NULL) {
/*
** Copy as much of the old vector into the new vector as possible. This
** presumes that there is a functional assignment operator for each
** of the objects in the vector.
*/
int copycount = (newsize < VectorMax) ? newsize : VectorMax;
for (int index = 0; index < copycount; index++) {
newptr[index] = Vector[index];
}
/*
** Delete the old vector. This might cause the destructors to be called
** for all of the old elements. This makes the implementation of suitable
** assignment operator very important. The default assignment operator will
** only work for the simplest of objects.
*/
if (IsAllocated) {
delete[] Vector;
Vector = 0;
}
}
/*
** Assign the new vector data to this class.
*/
Vector = newptr;
VectorMax = newsize;
IsAllocated = (Vector && !array);
} else {
/*
** Resizing to zero is the same as clearing the vector.
*/
Clear();
}
return(true);
}
/**************************************************************************
** This derivative vector class adds the concept of adding and deleting
** objects. The objects are packed to the beginning of the vector array.
** If this is instantiated for a class object, then the assignment operator
** and the equality operator must be supported. If the vector allocates its
** own memory, then the vector can grow if it runs out of room adding items.
** The growth rate is controlled by setting the growth step rate. A growth
** step rate of zero disallows growing.
*/
template<class T>
class DynamicVectorClass : public VectorClass<T>
{
public:
DynamicVectorClass(unsigned size=0, T const * array=0);
// Change maximum size of vector.
virtual bool Resize(int newsize, T const * array=0);
// Resets and frees the vector array.
virtual void Clear(void) {ActiveCount = 0;VectorClass<T>::Clear();};
// Fetch number of "allocated" vector objects.
int Count(void) const {return(ActiveCount);};
// Add object to vector (growing as necessary).
bool Add(T const & object);
bool Add_Head(T const & object);
// Delete object just like this from vector.
bool Delete(T const & object);
// Delete object at this vector index.
bool Delete(int index);
// Deletes all objects in the vector.
void Delete_All(void) {ActiveCount = 0;};
// Set amount that vector grows by.
int Set_Growth_Step(int step) {return(GrowthStep = step);};
// Fetch current growth step rate.
int Growth_Step(void) {return GrowthStep;};
virtual int ID(T const * ptr) {return(VectorClass<T>::ID(ptr));};
virtual int ID(T const & ptr);
DynamicVectorClass<T> & operator =(DynamicVectorClass<T> const & rvalue) {
VectorClass<T>::operator = (rvalue);
ActiveCount = rvalue.ActiveCount;
GrowthStep = rvalue.GrowthStep;
return(*this);
}
// Uninitialized Add - does everything an Add does, except copying an
// object into the 'new' spot in the array. It returns a pointer to
// the 'new' spot. (NULL if the Add failed). NOTE - you must then fill
// this memory area with a valid object (e.g. by using placement new),
// or chaos will result!
T * Uninitialized_Add(void);
protected:
/*
** This is a count of the number of active objects in this
** vector. The memory array often times is bigger than this
** value.
*/
int ActiveCount;
/*
** If there is insufficient room in the vector array for a new
** object to be added, then the vector will grow by the number
** of objects specified by this value. This is controlled by
** the Set_Growth_Step() function.
*/
int GrowthStep;
};
/***********************************************************************************************
* DynamicVectorClass<T>::DynamicVectorClass -- Constructor for dynamic vector. *
* *
* This is the normal constructor for the dynamic vector class. It is similar to the normal *
* vector class constructor. The vector is initialized to contain the number of elements *
* specified in the "size" parameter. The memory is allocated from free store unless the *
* optional array parameter is provided. In this case it will place the vector at the *
* memory location specified. *
* *
* INPUT: size -- The maximum number of objects allowed in this vector. *
* *
* array -- Optional pointer to the memory area to place the vector at. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
DynamicVectorClass<T>::DynamicVectorClass(unsigned size, T const * array)
: VectorClass<T>(size, array)
{
GrowthStep = 10;
ActiveCount = 0;
}
/***********************************************************************************************
* DynamicVectorClass<T>::Resize -- Changes the size of a dynamic vector. *
* *
* Use this routine to change the size of the vector. The size changed is the maximum *
* number of allocated objects within this vector. If a memory buffer is provided, then *
* the vector will be located there. Otherwise, the memory will be allocated out of free *
* store. *
* *
* INPUT: newsize -- The desired maximum size of this vector. *
* *
* array -- Optional pointer to a previously allocated memory array. *
* *
* OUTPUT: bool; Was vector successfully resized according to specifications? *
* *
* WARNINGS: Failure to resize the vector could be the result of lack of free store. *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
bool DynamicVectorClass<T>::Resize(int newsize, T const * array)
{
if (VectorClass<T>::Resize(newsize, array)) {
if (Length() < ActiveCount) ActiveCount = Length();
return(true);
}
return(false);
}
/***********************************************************************************************
* DynamicVectorClass<T>::ID -- Find matching value in the dynamic vector. *
* *
* Use this routine to find a matching object (by value) in the vector. Unlike the base *
* class ID function of similar name, this one restricts the scan to the current number *
* of valid objects. *
* *
* INPUT: object -- A reference to the object that a match is to be found in the *
* vector. *
* *
* OUTPUT: Returns with the index number of the object that is equivalent to the one *
* specified. If no equivalent object could be found then -1 is returned. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/13/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
int DynamicVectorClass<T>::ID(T const & object)
{
for (int index = 0; index < Count(); index++) {
if ((*this)[index] == object) return(index);
}
return(-1);
}
/***********************************************************************************************
* DynamicVectorClass<T>::Add -- Add an element to the vector. *
* *
* Use this routine to add an element to the vector. The vector will automatically be *
* resized to accomodate the new element IF the vector was allocated previously and the *
* growth rate is not zero. *
* *
* INPUT: object -- Reference to the object that will be added to the vector. *
* *
* OUTPUT: bool; Was the object added successfully? If so, the object is added to the end *
* of the vector. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
bool DynamicVectorClass<T>::Add(T const & object)
{
if (ActiveCount >= Length()) {
if ((IsAllocated || !VectorMax) && GrowthStep > 0) {
if (!Resize(Length() + GrowthStep)) {
/*
** Failure to increase the size of the vector is an error condition.
** Return with the error flag.
*/
return(false);
}
} else {
/*
** Increasing the size of this vector is not allowed! Bail this
** routine with the error code.
*/
return(false);
}
}
/*
** There is room for the new object now. Add it to the end of the object vector.
*/
(*this)[ActiveCount++] = object;
return(true);
}
/***********************************************************************************************
* DynamicVectorClass<T>::Add_Head -- Adds element to head of the list. *
* *
* This routine will add the specified element to the head of the vector. If necessary, *
* the vector will be expanded accordingly. *
* *
* INPUT: object -- Reference to the object to add to the head of this vector. *
* *
* OUTPUT: bool; Was the object added without error? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 09/21/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
bool DynamicVectorClass<T>::Add_Head(T const & object)
{
if (ActiveCount >= Length()) {
if ((IsAllocated || !VectorMax) && GrowthStep > 0) {
if (!Resize(Length() + GrowthStep)) {
/*
** Failure to increase the size of the vector is an error condition.
** Return with the error flag.
*/
return(false);
}
} else {
/*
** Increasing the size of this vector is not allowed! Bail this
** routine with the error code.
*/
return(false);
}
}
/*
** There is room for the new object now. Add it to the end of the object vector.
*/
if (ActiveCount) {
memmove(&(*this)[1], &(*this)[0], ActiveCount * sizeof(T));
}
(*this)[0] = object;
ActiveCount++;
// (*this)[ActiveCount++] = object;
return(true);
}
/***********************************************************************************************
* DynamicVectorClass<T>::Delete -- Remove the specified object from the vector. *
* *
* This routine will delete the object referenced from the vector. All objects in the *
* vector that follow the one deleted will be moved "down" to fill the hole. *
* *
* INPUT: object -- Reference to the object in this vector that is to be deleted. *
* *
* OUTPUT: bool; Was the object deleted successfully? This should always be true. *
* *
* WARNINGS: Do no pass a reference to an object that is NOT part of this vector. The *
* results of this are undefined and probably catastrophic. *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
bool DynamicVectorClass<T>::Delete(T const & object)
{
int id = ID(object);
if (id != -1) {
return(Delete(id));
}
return(false);
}
/***********************************************************************************************
* DynamicVectorClass<T>::Delete -- Deletes the specified index from the vector. *
* *
* Use this routine to delete the object at the specified index from the objects in the *
* vector. This routine will move all the remaining objects "down" in order to fill the *
* hole. *
* *
* INPUT: index -- The index number of the object in the vector that is to be deleted. *
* *
* OUTPUT: bool; Was the object index deleted successfully? Failure might mean that the index *
* specified was out of bounds. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/10/1995 JLB : Created. *
*=============================================================================================*/
template<class T>
bool DynamicVectorClass<T>::Delete(int index)
{
if (index < ActiveCount) {
ActiveCount--;
/*
** If there are any objects past the index that was deleted, copy those
** objects down in order to fill the hole. A simple memory copy is
** not sufficient since the vector could contain class objects that
** need to use the assignment operator for movement.
*/
for (int i = index; i < ActiveCount; i++) {
(*this)[i] = (*this)[i+1];
}
return(true);
}
return(false);
}
/***********************************************************************************************
* DynamicVectorClass<T>::Uninitialized_Add -- Add an empty place to the vector. *
* *
* To avoid copying when creating an object and adding it to the vector, use this and *
* immediately fill the area that the return value points to with a valid object (by hand *
* for a struct or by using placement new for a class object). *
* This function does everything Add does except copying an object into the new space, *
* thus leaving an uninitialized area of memory. *
* *
* INPUT: none. *
* *
* OUTPUT: T *; Points to the empty space where the new object is to be created. (If the *
* space was not added succesfully, returns NULL). *
* *
* WARNINGS: If memory area is left uninitialized, Very Bad Things will happen. *
* *
* HISTORY: *
* 03/04/1998 NH : Created. *
*=============================================================================================*/
template<class T>
T * DynamicVectorClass<T>::Uninitialized_Add(void)
{
if (ActiveCount >= Length()) {
if ((IsAllocated || !VectorMax) && GrowthStep > 0) {
if (!Resize(Length() + GrowthStep)) {
/*
** Failure to increase the size of the vector is an error condition.
** Return with the error value.
*/
return(NULL);
}
} else {
/*
** Increasing the size of this vector is not allowed! Bail this
** routine with the error value.
*/
return(NULL);
}
}
/*
** There is room for the new space now. Add it to the end of the object
** vector. and return a pointer to it.
*/
return &((*this)[ActiveCount++]);
}
void Set_Bit(void * array, int bit, int value);
int Get_Bit(void const * array, int bit);
int First_True_Bit(void const * array);
int First_False_Bit(void const * array);
/**************************************************************************
** This is a derivative of a vector class that supports boolean flags. Since
** a boolean flag can be represented by a single bit, this class packs the
** array of boolean flags into an array of bytes containing 8 boolean values
** each. For large boolean arrays, this results in an 87.5% savings. Although
** the indexing "[]" operator is supported, DO NOT pass pointers to sub elements
** of this bit vector class. A pointer derived from the indexing operator is
** only valid until the next call. Because of this, only simple
** direct use of the "[]" operator is allowed.
*/
class BooleanVectorClass
{
public:
BooleanVectorClass(unsigned size=0, unsigned char * array=0);
BooleanVectorClass(BooleanVectorClass const & vector);
// Assignment operator.
BooleanVectorClass & operator =(BooleanVectorClass const & vector);
// Equivalency operator.
bool operator == (BooleanVectorClass const & vector);
// Fetch number of boolean objects in vector.
int Length(void) {return BitCount;};
// Set all boolean values to false;
void Reset(void);
// Set all boolean values to true.
void Set(void);
// Resets vector to zero length (frees memory).
void Clear(void);
// Change size of this boolean vector.
int Resize(unsigned size);
// Fetch reference to specified index.
bool const & operator[](int index) const {
if (LastIndex != index) Fixup(index);
return(Copy);
};
bool & operator[](int index) {
if (LastIndex != index) Fixup(index);
return(Copy);
};
// Quick check on boolean state.
bool Is_True(int index) const {
if (index == LastIndex) return(Copy);
return(Get_Bit(&BitArray[0], index) != 0);
};
// Find first index that is false.
int First_False(void) const {
if (LastIndex != -1) Fixup(-1);
int retval = First_False_Bit(&BitArray[0]);
if (retval < BitCount) return(retval);
/*
** Failure to find a false boolean value in the vector. Return this
** fact in the form of an invalid index number.
*/
return(-1);
}
// Find first index that is true.
int First_True(void) const {
if (LastIndex != -1) Fixup(-1);
int retval = First_True_Bit(&BitArray[0]);
if (retval < BitCount) return(retval);
/*
** Failure to find a true boolean value in the vector. Return this
** fact in the form of an invalid index number.
*/
return(-1);
}
private:
void Fixup(int index=-1) const;
/*
** This is the number of boolean values in the vector. This value is
** not necessarily a multiple of 8, even though the underlying character
** vector contains a multiple of 8 bits.
*/
int BitCount;
/*
** This is a referential copy of an element in the bit vector. The
** purpose of this copy is to allow normal reference access to this
** object (for speed reasons). This hides the bit packing scheme from
** the user of this class.
*/
bool Copy;
/*
** This records the index of the value last fetched into the reference
** boolean variable. This index is used to properly restore the value
** when the reference copy needs updating.
*/
int LastIndex;
/*
** This points to the allocated bitfield array.
*/
VectorClass<unsigned char> BitArray;
};
template<class T>
int Pointer_Vector_Add(T * ptr, VectorClass<T *> & vec)
{
int id = 0;
bool foundspot = false;
for (int index = 0; index < vec.Length(); index++) {
if (vec[index] == NULL) {
id = index;
foundspot = true;
break;
}
}
if (!foundspot) {
id = vec.Length();
vec.Resize((vec.Length()+1) * 2);
for (int index = id; index < vec.Length(); index++) {
vec[index] = NULL;
}
}
vec[id] = ptr;
return(id);
}
template<class T>
bool Pointer_Vector_Remove(T const * ptr, VectorClass<T *> & vec)
{
int id = vec.ID((T *)ptr);
if (id != -1) {
vec[id] = NULL;
return(true);
}
return(false);
}
#endif

View file

@ -0,0 +1,404 @@
/*
** Command & Conquer Generals(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/Tools/max2w3d/WWmatrix3.cpp $*
* *
* Author:: Greg_h *
* *
* $Modtime:: 2/02/00 2:05p $*
* *
* $Revision:: 17 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "wwmatrix3.h"
#include "matrix3d.h"
#include "matrix4.h"
#include "w3dquat.h"
/*
** Some pre-initialized Matrix3's
*/
const Matrix3 Matrix3::Identity
(
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
);
const Matrix3 Matrix3::RotateX90
(
1.0, 0.0, 0.0,
0.0, 0.0, -1.0,
0.0, 1.0, 0.0
);
const Matrix3 Matrix3::RotateX180
(
1.0, 0.0, 0.0,
0.0, -1.0, 0.0,
0.0, 0.0, -1.0
);
const Matrix3 Matrix3::RotateX270
(
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
0.0, -1.0, 0.0
);
const Matrix3 Matrix3::RotateY90
(
0.0, 0.0, 1.0,
0.0, 1.0, 0.0,
-1.0, 0.0, 0.0
);
const Matrix3 Matrix3::RotateY180
(
-1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, -1.0
);
const Matrix3 Matrix3::RotateY270
(
0.0, 0.0, -1.0,
0.0, 1.0, 0.0,
1.0, 0.0, 0.0
);
const Matrix3 Matrix3::RotateZ90
(
0.0, -1.0, 0.0,
1.0, 0.0, 0.0,
0.0, 0.0, 1.0
);
const Matrix3 Matrix3::RotateZ180
(
-1.0, 0.0, 0.0,
0.0, -1.0, 0.0,
0.0, 0.0, 1.0
);
const Matrix3 Matrix3::RotateZ270
(
0.0, 1.0, 0.0,
-1.0, 0.0, 0.0,
0.0, 0.0, 1.0
);
/***********************************************************************************************
* Matrix3::Matrix3 -- Convert a Matrix3D (fake 4x4) to a Matrix3 *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
Matrix3::Matrix3(const Matrix3D & m)
{
Row[0].Set(m[0][0],m[0][1],m[0][2]);
Row[1].Set(m[1][0],m[1][1],m[1][2]);
Row[2].Set(m[2][0],m[2][1],m[2][2]);
}
Matrix3::Matrix3(const Matrix4 & m)
{
Row[0].Set(m[0][0],m[0][1],m[0][2]);
Row[1].Set(m[1][0],m[1][1],m[1][2]);
Row[2].Set(m[2][0],m[2][1],m[2][2]);
}
void Matrix3::Set(const Matrix3D & m)
{
Row[0].Set(m[0][0],m[0][1],m[0][2]);
Row[1].Set(m[1][0],m[1][1],m[1][2]);
Row[2].Set(m[2][0],m[2][1],m[2][2]);
}
void Matrix3::Set(const Matrix4 & m)
{
Row[0].Set(m[0][0],m[0][1],m[0][2]);
Row[1].Set(m[1][0],m[1][1],m[1][2]);
Row[2].Set(m[2][0],m[2][1],m[2][2]);
}
void Matrix3::Set(const Quaternion & q)
{
Row[0][0] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]));
Row[0][1] = (float)(2.0 * (q[0] * q[1] - q[2] * q[3]));
Row[0][2] = (float)(2.0 * (q[2] * q[0] + q[1] * q[3]));
Row[1][0] = (float)(2.0 * (q[0] * q[1] + q[2] * q[3]));
Row[1][1] = (float)(1.0 - 2.0f * (q[2] * q[2] + q[0] * q[0]));
Row[1][2] = (float)(2.0 * (q[1] * q[2] - q[0] * q[3]));
Row[2][0] = (float)(2.0 * (q[2] * q[0] - q[1] * q[3]));
Row[2][1] = (float)(2.0 * (q[1] * q[2] + q[0] * q[3]));
Row[2][2] =(float)(1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]));
}
Matrix3 & Matrix3::operator = (const Matrix3D & m)
{
Row[0].Set(m[0][0],m[0][1],m[0][2]);
Row[1].Set(m[1][0],m[1][1],m[1][2]);
Row[2].Set(m[2][0],m[2][1],m[2][2]);
return *this;
}
Matrix3 & Matrix3::operator = (const Matrix4 & m)
{
Row[0].Set(m[0][0],m[0][1],m[0][2]);
Row[1].Set(m[1][0],m[1][1],m[1][2]);
Row[2].Set(m[2][0],m[2][1],m[2][2]);
return *this;
}
void Matrix3::Multiply(const Matrix3D & a, const Matrix3 & b,Matrix3 * res)
{
#define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
(*res)[0][0] = ROWCOL(0,0);
(*res)[0][1] = ROWCOL(0,1);
(*res)[0][2] = ROWCOL(0,2);
(*res)[1][0] = ROWCOL(1,0);
(*res)[1][1] = ROWCOL(1,1);
(*res)[1][2] = ROWCOL(1,2);
(*res)[2][0] = ROWCOL(2,0);
(*res)[2][1] = ROWCOL(2,1);
(*res)[2][2] = ROWCOL(2,2);
#undef ROWCOL
}
void Matrix3::Multiply(const Matrix3 & a, const Matrix3D & b,Matrix3 * res)
{
#define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
(*res)[0][0] = ROWCOL(0,0);
(*res)[0][1] = ROWCOL(0,1);
(*res)[0][2] = ROWCOL(0,2);
(*res)[1][0] = ROWCOL(1,0);
(*res)[1][1] = ROWCOL(1,1);
(*res)[1][2] = ROWCOL(1,2);
(*res)[2][0] = ROWCOL(2,0);
(*res)[2][1] = ROWCOL(2,1);
(*res)[2][2] = ROWCOL(2,2);
#undef ROWCOL
}
Matrix3 operator * (const Matrix3D & a, const Matrix3 & b)
{
#define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
return Matrix3(
Vector3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2) ),
Vector3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2) ),
Vector3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2) )
);
#undef ROWCOL
}
Matrix3 operator * (const Matrix3 & a, const Matrix3D & b)
{
#define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
return Matrix3(
Vector3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2) ),
Vector3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2) ),
Vector3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2) )
);
#undef ROWCOL
}
#if 0
void Matrix3::Compute_Jacobi_Rotation(int i,int j,Matrix3 * r,Matrix3 * rinv)
{
}
void Matrix3::Symmetric_Eigen_Solve(void)
{
Matrix3 eigen_vals = *this;
Matrix3 eigen_vecs(1);
Matrix3 jr,jrinv;
while (!done) {
eigen_vals.Compute_Jacobi_Rotation(i,j,&jr,&jrinv);
eigen_vals = jr * (eigenvals) * jrinv;
eigen_vecs = eigen_vecs * jr;
}
/*
** Done! Eigen values are the diagonals of
** the eigen_vals matrix and the eigen vectors
** are the columns of the eigen_vecs matrix
*/
}
#endif
void Matrix3::Multiply(const Matrix3 & A,const Matrix3 & B,Matrix3 * set_res)
{
Matrix3 tmp;
Matrix3 * Aptr;
float tmp1,tmp2,tmp3;
// Check for aliased parameters, copy the 'A' matrix into a temporary if the
// result is going into 'A'. (in this case, this function is no better than
// the overloaded C++ operator...)
if (set_res == &A) {
tmp = A;
Aptr = &tmp;
} else {
Aptr = (Matrix3 *)&A;
}
tmp1 = B[0][0];
tmp2 = B[1][0];
tmp3 = B[2][0];
(*set_res)[0][0] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
(*set_res)[1][0] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
(*set_res)[2][0] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
tmp1 = B[0][1];
tmp2 = B[1][1];
tmp3 = B[2][1];
(*set_res)[0][1] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
(*set_res)[1][1] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
(*set_res)[2][1] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
tmp1 = B[0][2];
tmp2 = B[1][2];
tmp3 = B[2][2];
(*set_res)[0][2] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
(*set_res)[1][2] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
(*set_res)[2][2] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
}
int Matrix3::Is_Orthogonal(void) const
{
Vector3 x(Row[0].X,Row[0].Y,Row[0].Z);
Vector3 y(Row[1].X,Row[1].Y,Row[1].Z);
Vector3 z(Row[2].X,Row[2].Y,Row[2].Z);
if (Vector3::Dot_Product(x,y) > WWMATH_EPSILON) return 0;
if (Vector3::Dot_Product(y,z) > WWMATH_EPSILON) return 0;
if (Vector3::Dot_Product(z,x) > WWMATH_EPSILON) return 0;
if (WWMath::Fabs(x.Length() - 1.0f) > WWMATH_EPSILON) return 0;
if (WWMath::Fabs(y.Length() - 1.0f) > WWMATH_EPSILON) return 0;
if (WWMath::Fabs(z.Length() - 1.0f) > WWMATH_EPSILON) return 0;
return 1;
}
void Matrix3::Re_Orthogonalize(void)
{
Vector3 x(Row[0][0],Row[0][1],Row[0][2]);
Vector3 y(Row[1][0],Row[1][1],Row[1][2]);
Vector3 z;
Vector3::Cross_Product(x,y,&z);
Vector3::Cross_Product(z,x,&y);
float len = x.Length();
if (len < WWMATH_EPSILON) {
Make_Identity();
return;
} else {
x /= len;
}
len = y.Length();
if (len < WWMATH_EPSILON) {
Make_Identity();
return;
} else {
y /= len;
}
len = z.Length();
if (len < WWMATH_EPSILON) {
Make_Identity();
return;
} else {
z /= len;
}
Row[0][0] = x.X;
Row[0][1] = x.Y;
Row[0][2] = x.Z;
Row[1][0] = y.X;
Row[1][1] = y.Y;
Row[1][2] = y.Z;
Row[2][0] = z.X;
Row[2][1] = z.Y;
Row[2][2] = z.Z;
}
void Matrix3::Rotate_AABox_Extent(const Vector3 & extent,Vector3 * set_extent)
{
// push each extent out to the projections of the original extents
for (int i=0; i<3; i++) {
// start the center out at the translation portion of the matrix
// and the extent at zero
(*set_extent)[i] = 0.0f;
for (int j=0; j<3; j++) {
(*set_extent)[i] += WWMath::Fabs(Row[i][j] * extent[j]);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,83 @@
/*
** Command & Conquer Generals(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/aaplane.h $*
* *
* Author:: Greg Hjelstrom *
* *
* $Modtime:: 5/19/00 3:12p $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef AAPLANE_H
#define AAPLANE_H
#include "always.h"
#include "vector3.h"
/*
** This class is used to describe an "axis-aligned" plane. I.e, the normal
** of the plane is one of the three coordinate axes.
*/
class AAPlaneClass
{
public:
enum AxisEnum { XNORMAL = 0, YNORMAL = 1, ZNORMAL = 2 };
AAPlaneClass(void) { }
AAPlaneClass(AxisEnum normal,float dist) : Normal(normal),Dist(dist) { }
void Set(AxisEnum normal,float dist);
void Get_Normal(Vector3 * normal) const;
public:
AxisEnum Normal;
float Dist;
};
inline void AAPlaneClass::Set(AxisEnum normal,float dist)
{
Normal = normal;
Dist = dist;
}
inline void AAPlaneClass::Get_Normal(Vector3 * normal) const
{
normal->Set(0,0,0);
(*normal)[Normal] = 1.0f;
}
#endif

View file

@ -0,0 +1,170 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/always.h $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 8/28/01 3:21p $*
* *
* $Revision:: 13 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef ALWAYS_H
#define ALWAYS_H
// Disable warning about exception handling not being enabled. It's used as part of STL - in a part of STL we don't use.
#pragma warning(disable : 4530)
/*
** Define for debug memory allocation to include __FILE__ and __LINE__ for every memory allocation.
** This helps find leaks.
*/
//#define STEVES_NEW_CATCHER
#ifdef _DEBUG
#ifdef _MSC_VER
#ifdef STEVES_NEW_CATCHER
#include <crtdbg.h>
#include <stdlib.h>
#include <malloc.h>
#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
#define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__)
#define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
#define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
#define _msize(p) _msize_dbg(p, _NORMAL_BLOCK)
void* __cdecl operator new(unsigned int s);
#endif //STEVES_NEW_CATCHER
#endif //_MSC_VER
#endif //_DEBUG
// Jani: Intel's C++ compiler issues too many warnings in WW libraries when using warning level 4
#if defined (__ICL) // Detect Intel compiler
#pragma warning (3)
#pragma warning ( disable: 981 ) // parameters defined in unspecified order
#pragma warning ( disable: 279 ) // controlling expressaion is constant
#pragma warning ( disable: 271 ) // trailing comma is nonstandard
#pragma warning ( disable: 171 ) // invalid type conversion
#pragma warning ( disable: 1 ) // last line of file ends without a newline
#endif
// Jani: MSVC doesn't necessarily inline code with inline keyword. Using __forceinline results better inlining
// and also prints out a warning if inlining wasn't possible. __forceinline is MSVC specific.
#if defined(_MSC_VER)
#define WWINLINE __forceinline
#else
#define WWINLINE inline
#endif
/*
** Define the MIN and MAX macros.
** NOTE: Joe used to #include <minmax.h> in the various compiler header files. This
** header defines 'min' and 'max' macros which conflict with the surrender code so
** I'm relpacing all occurances of 'min' and 'max with 'MIN' and 'MAX'. For code which
** is out of our domain (e.g. Max sdk) I'm declaring template functions for 'min' and 'max'
*/
#define NOMINMAX
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
template <class T> T min(T a,T b)
{
if (a<b) {
return a;
} else {
return b;
}
}
template <class T> T max(T a,T b)
{
if (a>b) {
return a;
} else {
return b;
}
}
/*
** This includes the minimum set of compiler defines and pragmas in order to bring the
** various compilers to a common behavior such that the C&C engine will compile without
** error or warning.
*/
#if defined(__BORLANDC__)
#include "borlandc.h"
#endif
#if defined(_MSC_VER)
#include "visualc.h"
#endif
#if defined(__WATCOMC__)
#include "watcom.h"
#endif
#ifndef NULL
#define NULL 0
#endif
/**********************************************************************
** This macro serves as a general way to determine the number of elements
** within an array.
*/
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) int(sizeof(x)/sizeof(x[0]))
#endif
#ifndef size_of
#define size_of(typ,id) sizeof(((typ*)0)->id)
#endif
#endif

View file

@ -0,0 +1,64 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /G/wwlib/bool.h $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 9/23/99 1:46p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#if !defined(TRUE_FALSE_DEFINED) && !defined(__BORLANDC__) && (_MSC_VER < 1100) && !defined(__WATCOMC__)
#define TRUE_FALSE_DEFINED
/**********************************************************************
** The "bool" integral type was defined by the C++ comittee in
** November of '94. Until the compiler supports this, use the following
** definition.
*/
#ifdef _MSC_VER
#include "yvals.h"
#define bool unsigned
#elif defined(_UNIX)
/////#define bool unsigned
#else
enum {false=0,true=1};
typedef int bool;
#endif
#endif

View file

@ -0,0 +1,48 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /G/wwlib/borlandc.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:57a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#if !defined(BORLANDC_H) && defined(__BORLANDC__)
#define BORLANDC_H
/*
** Funny, but there are no required overrides to make Borland C match C++ standards. This
** is because Borland C more closely matches the C++ standard than the other compilers.
*/
#endif

View file

@ -0,0 +1,796 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/wwlib/chunkio.cpp 11 7/12/01 7:44p Jani_p $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Tiberian Sun / Commando / G Library *
* *
* $Archive:: /Commando/Code/wwlib/chunkio.cpp $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 7/10/01 7:38p $*
* *
* $Revision:: 11 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* ChunkSaveClass::ChunkSaveClass -- Constructor *
* ChunkSaveClass::Begin_Chunk -- Begin a new chunk in the file *
* ChunkSaveClass::End_Chunk -- Close a chunk, computes the size and adds to the header *
* ChunkSaveClass::Begin_Micro_Chunk -- begins a new "micro-chunk" *
* ChunkSaveClass::End_Micro_Chunk -- close a micro-chunk *
* ChunkSaveClass::Write -- Write data into the current chunk *
* ChunkSaveClass::Write -- write an IOVector2Struct *
* ChunkSaveClass::Write -- write an IOVector3Struct *
* ChunkSaveClass::Write -- write an IOVector4Struct *
* ChunkSaveClass::Write -- write an IOQuaternionStruct *
* ChunkSaveClass::Cur_Chunk_Depth -- returns the current chunk recursion depth (debugging) *
* ChunkLoadClass::ChunkLoadClass -- Constructor *
* ChunkLoadClass::Open_Chunk -- Open a chunk in the file, reads in the chunk header *
* ChunkLoadClass::Close_Chunk -- Close a chunk, seeks to the end if needed *
* ChunkLoadClass::Cur_Chunk_ID -- Returns the ID of the current chunk *
* ChunkLoadClass::Cur_Chunk_Length -- Returns the current length of the current chunk *
* ChunkLoadClass::Cur_Chunk_Depth -- returns the current chunk recursion depth *
* ChunkLoadClass::Contains_Chunks -- Test whether the current chunk contains chunks (or dat *
* ChunkLoadClass::Open_Micro_Chunk -- reads in a micro-chunk header *
* ChunkLoadClass::Close_Micro_Chunk -- closes a micro-chunk *
* ChunkLoadClass::Cur_Micro_Chunk_ID -- returns the ID of the current micro-chunk (asserts *
* ChunkLoadClass::Cur_Micro_Chunk_Length -- returns the size of the current micro chunk *
* ChunkLoadClass::Read -- Read data from the file *
* ChunkLoadClass::Read -- read an IOVector2Struct *
* ChunkLoadClass::Read -- read an IOVector3Struct *
* ChunkLoadClass::Read -- read an IOVector4Struct *
* ChunkLoadClass::Read -- read an IOQuaternionStruct *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "chunkio.h"
#include <string.h>
#include <assert.h>
/***********************************************************************************************
* ChunkSaveClass::ChunkSaveClass -- Constructor *
* *
* INPUT: *
* file - pointer to a FileClass object to write to *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
ChunkSaveClass::ChunkSaveClass(FileClass * file) :
File(file),
StackIndex(0),
InMicroChunk(false),
MicroChunkPosition(0)
{
memset(PositionStack,0,sizeof(PositionStack));
memset(HeaderStack,0,sizeof(HeaderStack));
memset(&MCHeader,0,sizeof(MCHeader));
}
/***********************************************************************************************
* ChunkSaveClass::Begin_Chunk -- Begin a new chunk in the file *
* *
* INPUT: *
* id - id of the chunk *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
bool ChunkSaveClass::Begin_Chunk(uint32 id)
{
ChunkHeader chunkh;
int filepos;
// If we have a parent chunk, set its 'Contains_Chunks' flag
if (StackIndex > 0) {
HeaderStack[StackIndex-1].Set_Sub_Chunk_Flag(true);
}
// Save the current file position and chunk header
// for the call to End_Chunk.
chunkh.Set_Type(id);
chunkh.Set_Size(0);
filepos = File->Seek(0);
PositionStack[StackIndex] = filepos;
HeaderStack[StackIndex] = chunkh;
StackIndex++;
// write a temporary chunk header (size = 0)
if (File->Write(&chunkh,sizeof(chunkh)) != sizeof(chunkh)) {
return false;
}
return true;
}
/***********************************************************************************************
* ChunkSaveClass::End_Chunk -- Close a chunk, computes the size and adds to the header *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
bool ChunkSaveClass::End_Chunk(void)
{
// If the user didn't close his micro chunks bad things are gonna happen
assert(!InMicroChunk);
// Save the current position
int curpos = File->Seek(0);
// Pop the position and chunk header off the stacks
StackIndex--;
int chunkpos = PositionStack[StackIndex];
ChunkHeader chunkh = HeaderStack[StackIndex];
// write the completed header
File->Seek(chunkpos,SEEK_SET);
if (File->Write(&chunkh,sizeof(chunkh)) != sizeof(chunkh)) {
return false;
}
// Add the total bytes written to any encompasing chunk
if (StackIndex != 0) {
HeaderStack[StackIndex-1].Add_Size(chunkh.Get_Size() + sizeof(chunkh));
}
// Go back to the end of the file
File->Seek(curpos,SEEK_SET);
return true;
}
/***********************************************************************************************
* ChunkSaveClass::Begin_Micro_Chunk -- begins a new "micro-chunk" *
* *
* Micro chunks are used to wrap individual variables. They aren't hierarchical so if you *
* attempt to open a micro chunk while already in one, an assert will occur. *
* *
* INPUT: *
* id - 8bit id *
* *
* OUTPUT: *
* *
* WARNINGS: *
* id is asserted to be between 0 and 255 *
* cannot nest micro chunks so it asserts that you are currently not in another micro-chunk *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
bool ChunkSaveClass::Begin_Micro_Chunk(uint32 id)
{
assert(id < 256);
assert(!InMicroChunk);
// Save the current file position and chunk header
// for the call to End_Micro_Chunk.
MCHeader.Set_Type(id);
MCHeader.Set_Size(0);
MicroChunkPosition = File->Seek(0);
// Write a temporary chunk header
// NOTE: I'm calling the ChunkSaveClass::Write method so that the bytes for
// this header are tracked in the wrapping chunk. This is because micro-chunks
// are simply data inside the normal chunks...
if (Write(&MCHeader,sizeof(MCHeader)) != sizeof(MCHeader)) {
return false;
}
InMicroChunk = true;
return true;
}
/***********************************************************************************************
* ChunkSaveClass::End_Micro_Chunk -- close a micro-chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
bool ChunkSaveClass::End_Micro_Chunk(void)
{
assert(InMicroChunk);
// Save the current position
int curpos = File->Seek(0);
// Seek back and write the micro chunk header
File->Seek(MicroChunkPosition,SEEK_SET);
if (File->Write(&MCHeader,sizeof(MCHeader)) != sizeof(MCHeader)) {
return false;
}
// Go back to the end of the file
File->Seek(curpos,SEEK_SET);
InMicroChunk = false;
return true;
}
/***********************************************************************************************
* ChunkSaveClass::Write -- Write data into the current chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
uint32 ChunkSaveClass::Write(const void * buf, uint32 nbytes)
{
// If this assert hits, you mixed data and chunks within the same chunk NO NO!
assert(HeaderStack[StackIndex-1].Get_Sub_Chunk_Flag() == 0);
// If this assert hits, you didnt open any chunks yet
assert(StackIndex > 0);
// write the bytes into the file
if (File->Write(buf,nbytes) != (int)nbytes) return 0;
// track them in the wrapping chunk
HeaderStack[StackIndex-1].Add_Size(nbytes);
// track them if you are using a micro-chunk too.
if (InMicroChunk) {
assert(MCHeader.Get_Size() < 255 - nbytes); // micro chunks can only be 255 bytes
MCHeader.Add_Size(nbytes);
}
return nbytes;
}
/***********************************************************************************************
* ChunkSaveClass::Write -- write an IOVector2Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkSaveClass::Write(const IOVector2Struct & v)
{
return Write(&v,sizeof(v));
}
/***********************************************************************************************
* ChunkSaveClass::Write -- write an IOVector3Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkSaveClass::Write(const IOVector3Struct & v)
{
return Write(&v,sizeof(v));
}
/***********************************************************************************************
* ChunkSaveClass::Write -- write an IOVector4Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkSaveClass::Write(const IOVector4Struct & v)
{
return Write(&v,sizeof(v));
}
/***********************************************************************************************
* ChunkSaveClass::Write -- write an IOQuaternionStruct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkSaveClass::Write(const IOQuaternionStruct & q)
{
return Write(&q,sizeof(q));
}
/***********************************************************************************************
* ChunkSaveClass::Cur_Chunk_Depth -- returns the current chunk recursion depth (debugging) *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
int ChunkSaveClass::Cur_Chunk_Depth(void)
{
return StackIndex;
}
/***********************************************************************************************
* ChunkLoadClass::ChunkLoadClass -- Constructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
ChunkLoadClass::ChunkLoadClass(FileClass * file) :
File(file),
StackIndex(0),
InMicroChunk(false),
MicroChunkPosition(0)
{
memset(PositionStack,0,sizeof(PositionStack));
memset(HeaderStack,0,sizeof(HeaderStack));
memset(&MCHeader,0,sizeof(MCHeader));
}
/***********************************************************************************************
* ChunkLoadClass::Open_Chunk -- Open a chunk in the file, reads in the chunk header *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
bool ChunkLoadClass::Open_Chunk()
{
// if user didn't close any micro chunks that he opened, bad things could happen
assert(InMicroChunk == false);
// check for stack overflow
assert(StackIndex < MAX_STACK_DEPTH-1);
// if the parent chunk has been completely eaten, return false
if ((StackIndex > 0) && (PositionStack[StackIndex-1] == HeaderStack[StackIndex-1].Get_Size())) {
return false;
}
// read the chunk header
if (File->Read(&HeaderStack[StackIndex],sizeof(ChunkHeader)) != sizeof(ChunkHeader)) {
return false;
}
PositionStack[StackIndex] = 0;
StackIndex++;
return true;
}
/***********************************************************************************************
* ChunkLoadClass::Close_Chunk -- Close a chunk, seeks to the end if needed *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
bool ChunkLoadClass::Close_Chunk()
{
// if user didn't close any micro chunks that he opened, bad things could happen
assert(InMicroChunk == false);
// check for stack overflow
assert(StackIndex > 0);
int csize = HeaderStack[StackIndex-1].Get_Size();
int pos = PositionStack[StackIndex-1];
if (pos < csize) {
File->Seek(csize - pos,SEEK_CUR);
}
StackIndex--;
if (StackIndex > 0) {
PositionStack[StackIndex - 1] += csize + sizeof(ChunkHeader);
}
return true;
}
/***********************************************************************************************
* ChunkLoadClass::Cur_Chunk_ID -- Returns the ID of the current chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Cur_Chunk_ID()
{
assert(StackIndex >= 1);
return HeaderStack[StackIndex-1].Get_Type();
}
/***********************************************************************************************
* ChunkLoadClass::Cur_Chunk_Length -- Returns the current length of the current chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Cur_Chunk_Length()
{
assert(StackIndex >= 1);
return HeaderStack[StackIndex-1].Get_Size();
}
/***********************************************************************************************
* ChunkLoadClass::Cur_Chunk_Depth -- returns the current chunk recursion depth *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
int ChunkLoadClass::Cur_Chunk_Depth()
{
return StackIndex;
}
/***********************************************************************************************
* ChunkLoadClass::Contains_Chunks -- Test whether the current chunk contains chunks (or data) *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/24/99 GTH : Created. *
*=============================================================================================*/
int ChunkLoadClass::Contains_Chunks()
{
return HeaderStack[StackIndex-1].Get_Sub_Chunk_Flag();
}
/***********************************************************************************************
* ChunkLoadClass::Open_Micro_Chunk -- reads in a micro-chunk header *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
bool ChunkLoadClass::Open_Micro_Chunk()
{
assert(!InMicroChunk);
// read the chunk header
// calling the ChunkLoadClass::Read fn so that if we exhaust the chunk, the read will fail
if (Read(&MCHeader,sizeof(MCHeader)) != sizeof(MCHeader)) {
return false;
}
InMicroChunk = true;
MicroChunkPosition = 0;
return true;
}
/***********************************************************************************************
* ChunkLoadClass::Close_Micro_Chunk -- closes a micro-chunk (seeks to end) *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
bool ChunkLoadClass::Close_Micro_Chunk()
{
assert(InMicroChunk);
InMicroChunk = false;
int csize = MCHeader.Get_Size();
int pos = MicroChunkPosition;
// seek the file past this micro chunk
if (pos < csize) {
File->Seek(csize - pos,SEEK_CUR);
// update the tracking variables for where we are in the normal chunk.
if (StackIndex > 0) {
PositionStack[StackIndex-1] += csize - pos;
}
}
return true;
}
/***********************************************************************************************
* ChunkLoadClass::Cur_Micro_Chunk_ID -- returns the ID of the current micro-chunk (asserts if *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* Asserts if you are not currently inside a micro-chunk *
* Micro chunks have an id between 0 and 255 *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Cur_Micro_Chunk_ID()
{
assert(InMicroChunk);
return MCHeader.Get_Type();
}
/***********************************************************************************************
* ChunkLoadClass::Cur_Micro_Chunk_Length -- returns the size of the current micro chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* Asserts if you are not currently inside a micro-chunk *
* Micro chunks have a maximum size of 255 bytes *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Cur_Micro_Chunk_Length()
{
assert(InMicroChunk);
return MCHeader.Get_Size();
}
// Seek over nbytes in the stream
uint32 ChunkLoadClass::Seek(uint32 nbytes)
{
assert(StackIndex >= 1);
// Don't seek if we would go past the end of the current chunk
if (PositionStack[StackIndex-1] + nbytes > (int)HeaderStack[StackIndex-1].Get_Size()) {
return 0;
}
// Don't read if we are in a micro chunk and would go past the end of it
if (InMicroChunk && MicroChunkPosition + nbytes > MCHeader.Get_Size()) {
return 0;
}
uint32 curpos=File->Tell();
if (File->Seek(nbytes,SEEK_CUR)-curpos != (int)nbytes) {
return 0;
}
// Update our position in the chunk
PositionStack[StackIndex-1] += nbytes;
// Update our position in the micro chunk if we are in one
if (InMicroChunk) {
MicroChunkPosition += nbytes;
}
return nbytes;
}
/***********************************************************************************************
* ChunkLoadClass::Read -- Read data from the file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Read(void * buf,uint32 nbytes)
{
assert(StackIndex >= 1);
// Don't read if we would go past the end of the current chunk
if (PositionStack[StackIndex-1] + nbytes > (int)HeaderStack[StackIndex-1].Get_Size()) {
return 0;
}
// Don't read if we are in a micro chunk and would go past the end of it
if (InMicroChunk && MicroChunkPosition + nbytes > MCHeader.Get_Size()) {
return 0;
}
if (File->Read(buf,nbytes) != (int)nbytes) {
return 0;
}
// Update our position in the chunk
PositionStack[StackIndex-1] += nbytes;
// Update our position in the micro chunk if we are in one
if (InMicroChunk) {
MicroChunkPosition += nbytes;
}
return nbytes;
}
/***********************************************************************************************
* ChunkLoadClass::Read -- read an IOVector2Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Read(IOVector2Struct * v)
{
assert(v != NULL);
return Read(v,sizeof(v));
}
/***********************************************************************************************
* ChunkLoadClass::Read -- read an IOVector3Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Read(IOVector3Struct * v)
{
assert(v != NULL);
return Read(v,sizeof(v));
}
/***********************************************************************************************
* ChunkLoadClass::Read -- read an IOVector4Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Read(IOVector4Struct * v)
{
assert(v != NULL);
return Read(v,sizeof(v));
}
/***********************************************************************************************
* ChunkLoadClass::Read -- read an IOQuaternionStruct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Read(IOQuaternionStruct * q)
{
assert(q != NULL);
return Read(q,sizeof(q));
}

View file

@ -0,0 +1,380 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/wwlib/chunkio.h 21 7/31/01 6:41p Patrick $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Tiberian Sun / Commando / G Library *
* *
* $Archive:: /Commando/Code/wwlib/chunkio.h $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 7/27/01 2:47p $*
* *
* $Revision:: 21 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef CHUNKIO_H
#define CHUNKIO_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef BITTYPE_H
#include "bittype.h"
#endif
#ifndef WWFILE_H
#include "wwfile.h"
#endif
#ifndef IOSTRUCT_H
#include "iostruct.h"
#endif
/************************************************************************************
ChunkIO
(gth) This module provides classes for reading and writing chunk-based files.
For example, all of the w3d files are stored in a hierarchical-chunk format.
Basically the format is similar to IFF. All data in the file has chunk headers
wrapped around it. A chunk header contains an ID, and a Size. The size
is the number of bytes in the chunk (not including the header). The
contents of a chunk may be either: more "sub-chunks" or raw data. These classes
will automatically keep track of your positions within all of the sub and parent
chunks (to some maximum recursion depth).
Sept 3, 1999
(gth) Adding the new concept of "micro-chunks". Instead of filling the contents of a
chunk with data, you can fill it with "micro-chunks" which contain a single byte
id and a single byte size. Micro-chunks are used for storing simple variables
in a form that can survive revisions to the file format without paying the price
for a full chunk header. You CANNOT recursively embed micro-chunks due to their
size limitations....
Sept 24, 1999
(gth) Using the MSB of the chunksize to indicate whether a chunk contains other
chunks or pure data. If the MSB is 0, the chunk contains data (so that the reader
I'm going to write doesn't break on older files) and if it is 1 then it is
assumed to contain other chunks. This does not apply to micro-chunks as they
are considered data.
**************************************************************************************/
struct ChunkHeader
{
// Functions.
ChunkHeader() : ChunkType(0), ChunkSize(0) {}
ChunkHeader(uint32 type, uint32 size) {ChunkType = type; ChunkSize = size;}
// Use these accessors to ensure you correctly deal with the data in the chunk header
void Set_Type(uint32 type) { ChunkType = type; }
uint32 Get_Type(void) { return ChunkType; }
void Set_Size(uint32 size) { ChunkSize &= 0x80000000; ChunkSize |= (size & 0x7FFFFFFF); }
void Add_Size(uint32 add) { Set_Size(Get_Size() + add); }
uint32 Get_Size(void) { return (ChunkSize & 0x7FFFFFFF); }
void Set_Sub_Chunk_Flag(bool onoff) { if (onoff) { ChunkSize |= 0x80000000; } else { ChunkSize &= 0x7FFFFFFF; } }
int Get_Sub_Chunk_Flag(void) { return (ChunkSize & 0x80000000); }
// Chunk type and size.
// Note: MSB of ChunkSize is used to indicate whether this chunk
// contains other chunks or data.
uint32 ChunkType;
uint32 ChunkSize;
};
struct MicroChunkHeader
{
MicroChunkHeader() {}
MicroChunkHeader(uint8 type, uint8 size) { ChunkType = type, ChunkSize = size; }
void Set_Type(uint8 type) { ChunkType = type; }
uint8 Get_Type(void) { return ChunkType; }
void Set_Size(uint8 size) { ChunkSize = size; }
void Add_Size(uint8 add) { Set_Size(Get_Size() + add); }
uint8 Get_Size(void) { return ChunkSize; }
uint8 ChunkType;
uint8 ChunkSize;
};
/**************************************************************************************
**
** ChunkSaveClass
** Wrap an instance of this class around an opened file for easy chunk
** creation.
**
**************************************************************************************/
class ChunkSaveClass
{
public:
ChunkSaveClass(FileClass * file);
// Chunk methods
bool Begin_Chunk(uint32 id);
bool End_Chunk();
int Cur_Chunk_Depth();
// Micro chunk methods
bool Begin_Micro_Chunk(uint32 id);
bool End_Micro_Chunk();
// Write data into the file
uint32 Write(const void *buf, uint32 nbytes);
uint32 Write(const IOVector2Struct & v);
uint32 Write(const IOVector3Struct & v);
uint32 Write(const IOVector4Struct & v);
uint32 Write(const IOQuaternionStruct & q);
private:
enum { MAX_STACK_DEPTH = 256 };
FileClass * File;
// Chunk building support
int StackIndex;
int PositionStack[MAX_STACK_DEPTH];
ChunkHeader HeaderStack[MAX_STACK_DEPTH];
// MicroChunk building support
bool InMicroChunk;
int MicroChunkPosition;
MicroChunkHeader MCHeader;
};
/**************************************************************************************
**
** ChunkLoadClass
** wrap an instance of one of these objects around an opened file
** to easily parse the chunks in the file
**
**************************************************************************************/
class ChunkLoadClass
{
public:
ChunkLoadClass(FileClass * file);
// Chunk methods
bool Open_Chunk();
bool Close_Chunk();
uint32 Cur_Chunk_ID();
uint32 Cur_Chunk_Length();
int Cur_Chunk_Depth();
int Contains_Chunks();
// Micro Chunk methods
bool Open_Micro_Chunk();
bool Close_Micro_Chunk();
uint32 Cur_Micro_Chunk_ID();
uint32 Cur_Micro_Chunk_Length();
// Read a block of bytes from the output stream.
uint32 Read(void *buf, uint32 nbytes);
uint32 Read(IOVector2Struct * v);
uint32 Read(IOVector3Struct * v);
uint32 Read(IOVector4Struct * v);
uint32 Read(IOQuaternionStruct * q);
// Seek over a block of bytes in the stream (same as Read but don't copy the data to a buffer)
uint32 Seek(uint32 nbytes);
private:
enum { MAX_STACK_DEPTH = 256 };
FileClass * File;
// Chunk reading support
int StackIndex;
uint32 PositionStack[MAX_STACK_DEPTH];
ChunkHeader HeaderStack[MAX_STACK_DEPTH];
// Micro-chunk reading support
bool InMicroChunk;
int MicroChunkPosition;
MicroChunkHeader MCHeader;
};
/*
** WRITE_WWSTRING_CHUNK - use this one-line macro to easily create a chunk to save a potentially
** long string. Note: This macro does NOT create a micro chunk...
** Example:
**
** csave.Begin_Chunk(CHUNKID_PARENT);
** ParentClass::Save (csave);
** csave.End_Chunk();
**
** WRITE_WWSTRING_CHUNK(csave, CHUNKID_NAME, string);
** WRITE_WIDESTRING_CHUNK(csave, CHUNKID_WIDE_NAME, wide_string);
**
** csave.Begin_Chunk(PHYSGRID_CHUNK_VARIABLES);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_VERSION,version);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_DUMMYVISID,DummyVisId);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_BASEVISID,BaseVisId);
** csave.End_Chunk();
**
*/
#define WRITE_WWSTRING_CHUNK(csave,id,var) { \
csave.Begin_Chunk(id); \
csave.Write((const TCHAR *)var, var.Get_Length () + 1); \
csave.End_Chunk(); }
#define WRITE_WIDESTRING_CHUNK(csave,id,var) { \
csave.Begin_Chunk(id); \
csave.Write((const WCHAR *)var, (var.Get_Length () + 1) * 2); \
csave.End_Chunk(); }
/*
** READ_WWSTRING_CHUNK - use this macro in a switch statement to read the contents
** of a chunk into a string object.
** Example:
**
** while (cload.Open_Chunk()) {
**
** switch(cload.Cur_Chunk_ID()) {
** READ_WWSTRING_CHUNK(cload,CHUNKID_NAME,string);
** READ_WIDESTRING_CHUNK(cload,CHUNKID_WIDE_NAME,wide_string);
** }
** cload.Close_Chunk();
** }
**
*/
#define READ_WWSTRING_CHUNK(cload,id,var) \
case (id): cload.Read(var.Get_Buffer(cload.Cur_Chunk_Length()),cload.Cur_Chunk_Length()); break; \
#define READ_WIDESTRING_CHUNK(cload,id,var) \
case (id): cload.Read(var.Get_Buffer((cload.Cur_Chunk_Length()+1)/2),cload.Cur_Chunk_Length()); break; \
/*
** WRITE_MICRO_CHUNK - use this one-line macro to easily make a micro chunk for an individual variable.
** Note that you should always wrap your micro-chunks inside a normal chunk.
** Example:
**
** csave.Begin_Chunk(PHYSGRID_CHUNK_VARIABLES);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_VERSION,version);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_DUMMYVISID,DummyVisId);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_BASEVISID,BaseVisId);
** csave.End_Chunk();
*/
#define WRITE_MICRO_CHUNK(csave,id,var) { \
csave.Begin_Micro_Chunk(id); \
csave.Write(&var,sizeof(var)); \
csave.End_Micro_Chunk(); }
#define WRITE_SAFE_MICRO_CHUNK(csave,id,var,type) { \
csave.Begin_Micro_Chunk(id); \
type data = (type)var; \
csave.Write(&data,sizeof(data)); \
csave.End_Micro_Chunk(); }
#define WRITE_MICRO_CHUNK_STRING(csave,id,var) { \
csave.Begin_Micro_Chunk(id); \
csave.Write(var, strlen(var) + 1); \
csave.End_Micro_Chunk(); }
#define WRITE_MICRO_CHUNK_WWSTRING(csave,id,var) { \
csave.Begin_Micro_Chunk(id); \
csave.Write((const TCHAR *)var, var.Get_Length () + 1); \
csave.End_Micro_Chunk(); }
#define WRITE_MICRO_CHUNK_WIDESTRING(csave,id,var) { \
csave.Begin_Micro_Chunk(id); \
csave.Write((const WCHAR *)var, (var.Get_Length () + 1) * 2); \
csave.End_Micro_Chunk(); }
/*
** READ_MICRO_CHUNK - use this macro in a switch statement to read a micro chunk into a variable
** Example:
**
** while (cload.Open_Micro_Chunk()) {
**
** switch(cload.Cur_Micro_Chunk_ID()) {
** READ_MICRO_CHUNK(cload,PHYSGRID_VARIABLE_VERSION,version);
** READ_MICRO_CHUNK(cload,PHYSGRID_VARIABLE_DUMMYVISID,DummyVisId);
** READ_MICRO_CHUNK(cload,PHYSGRID_VARIABLE_BASEVISID,BaseVisId);
** }
** cload.Close_Micro_Chunk();
** }
*/
#define READ_MICRO_CHUNK(cload,id,var) \
case (id): cload.Read(&var,sizeof(var)); break; \
/*
** Like READ_MICRO_CHUNK but reads items straight into the data safe.
*/
#define READ_SAFE_MICRO_CHUNK(cload,id,var,type) \
case (id): { \
void *temp_read_buffer_on_the_stack = _alloca(sizeof(var)); \
cload.Read(temp_read_buffer_on_the_stack, sizeof(var)); \
var = *((type*)temp_read_buffer_on_the_stack); \
break; \
}
#define READ_MICRO_CHUNK_STRING(cload,id,var,size) \
case (id): WWASSERT(cload.Cur_Micro_Chunk_Length() <= size); cload.Read(var,cload.Cur_Micro_Chunk_Length()); break; \
#define READ_MICRO_CHUNK_WWSTRING(cload,id,var) \
case (id): cload.Read(var.Get_Buffer(cload.Cur_Micro_Chunk_Length()),cload.Cur_Micro_Chunk_Length()); break; \
#define READ_MICRO_CHUNK_WIDESTRING(cload,id,var) \
case (id): cload.Read(var.Get_Buffer((cload.Cur_Micro_Chunk_Length()+1)/2),cload.Cur_Micro_Chunk_Length()); break; \
/*
** These load macros make it easier to add extra code to a specifc case
*/
#define LOAD_MICRO_CHUNK(cload,var) \
cload.Read(&var,sizeof(var)); \
#define LOAD_MICRO_CHUNK_WWSTRING(cload,var) \
cload.Read(var.Get_Buffer(cload.Cur_Micro_Chunk_Length()),cload.Cur_Micro_Chunk_Length()); \
#define LOAD_MICRO_CHUNK_WIDESTRING(cload,var) \
cload.Read(var.Get_Buffer((cload.Cur_Micro_Chunk_Length()+1)/2),cload.Cur_Micro_Chunk_Length()); \
/*
** OBSOLETE_MICRO_CHUNK - use this macro in a switch statement when you want your code
** to skip a given micro chunk but not fall through to your 'default' case statement which
** prints an "unrecognized chunk" warning message.
*/
#define OBSOLETE_MICRO_CHUNK(id) \
case (id): break;
#endif CHUNKIO_H

View file

@ -0,0 +1,88 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/pluglib/errclass.h 5 6/25/99 10:46a Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando Tools - W3D export *
* *
* $Archive:: /Commando/Code/Tools/pluglib/errclass.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 6/24/99 3:38p $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef ERRCLASS_H
#define ERRCLASS_H
#include <stdarg.h>
class ErrorClass
{
public:
ErrorClass(char * format,...);
ErrorClass(const ErrorClass & that);
~ErrorClass(void) { if (error_message != NULL) free(error_message); }
ErrorClass & operator = (const ErrorClass & that);
char * error_message;
};
inline ErrorClass::ErrorClass(char * format,...)
{
va_list va;
char tmp[1024];
va_start(va,format);
vsprintf(tmp,format,va);
assert(strlen(tmp) < 1024);
va_end(va);
error_message = strdup(tmp);
}
inline ErrorClass::ErrorClass(const ErrorClass & that) :
error_message(NULL)
{
*this = that;
}
inline ErrorClass & ErrorClass::operator = (const ErrorClass & that)
{
if (error_message != NULL) {
free(error_message);
error_message = NULL;
}
if (that.error_message != NULL) {
error_message = strdup(that.error_message);
}
return *this;
}
#endif //ERRCLASS_H

View file

@ -0,0 +1,74 @@
/*
** Command & Conquer Generals(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 : Westwood Library *
* *
* $Archive:: /G/wwlib/hashcalc.h $*
* *
* Author:: Greg Hjelstrom *
* *
* $Modtime:: 4/02/99 11:59a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef HASHCALC_H
#define HASHCALC_H
/*
** HashCalculatorClass
** The hash calculator is used to abstract the process of computing a hash
** value for an object. Also, when dealing with floating point values, you
** may need to have a fudge factor and therefore have several valid hash
** values for a particular object (generated by adding and subtracting an
** epsilon to the number(s)). This class lets you define any number
** of hash values. This class is used by the UniqueArrayClass and the HashTableClass
** templates. Basically, you give one of these to the UniqueArrayClass at
** construction time. It will call the Num_Hash_Bits function in order to
** properly allocate its hash table. Then, for each object you pass into the
** Add function, it will call Compute_Hash, then it will loop through
** Num_Hash_Values, calling Get_Hash_Value for each index and see if the object
** is found in the indicated slot. Also, when it is checking to see if it has
** the object you "Added", the Items_Match function is called. This again
** allows you to do epsilon tests. Make sense?
*/
template <class T> class HashCalculatorClass
{
public:
virtual bool Items_Match(const T & a, const T & b) = 0;
virtual void Compute_Hash(const T & item) = 0;
virtual int Num_Hash_Bits(void) = 0;
virtual int Num_Hash_Values(void) = 0;
virtual int Get_Hash_Value(int index = 0) = 0;
};
#endif

View file

@ -0,0 +1,191 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Library/HSV.CPP $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* HSVClass::Adjust -- Adjust an HSV color toward specified color. *
* HSVClass::Difference -- Finds the difference between two HSV color objects. *
* HSVClass::operator RGBClass -- Conversion operator for RGBClass object. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "hsv.h"
#include "rgb.h"
HSVClass const HSVClass::BlackColor(0, 0, 0);
/***********************************************************************************************
* HSVClass::Adjust -- Adjust an HSV color toward specified color. *
* *
* This routine will adjust the HSV color object toward the color of the specified HSV *
* object. Typical users of this would be palette morphing or fading routines. *
* *
* INPUT: ratio -- The ratio to move the HSV object toward the color specified. A value *
* of zero means no movement at all. A value of 255 means move completely *
* toward the specified color (changed completely). *
* *
* hsv -- A reference to the color that the current HSV object is to change *
* toward. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/20/1996 JLB : Created. *
*=============================================================================================*/
void HSVClass::Adjust(int ratio, HSVClass const & hsv)
{
/*
** Ratio conversion is limited to 0 through 100%. This is
** the range of 0 to 255.
*/
ratio &= 0x00FF;
/*
** Adjust the color guns by the ratio specified toward the
** destination color.
*/
int value = hsv.Get_Value() - Get_Value();
Value = (unsigned char)(Get_Value() + (value * ratio) / 256);
int saturation = hsv.Get_Saturation() - Get_Saturation();
Saturation = (unsigned char)(Get_Saturation() + (saturation * ratio) / 256);
int hue = hsv.Get_Hue() - Get_Hue();
Hue = (unsigned char)(Get_Hue() + (hue * ratio) / 256);
}
/***********************************************************************************************
* HSVClass::Difference -- Finds the difference between two HSV color objects. *
* *
* This routine will determine a color difference between two HSV objects. The difference *
* has no particular meaning other that larger numbers meaning greater difference. *
* *
* INPUT: hsv -- The other HSV object to compare this HSV object to. *
* *
* OUTPUT: Returns with a relative distance (in arbitrary units) between this HSV object and *
* the HSV object supplied. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/20/1996 JLB : Created. *
*=============================================================================================*/
int HSVClass::Difference(HSVClass const & hsv) const
{
int hue = (int)Hue - (int)hsv.Hue;
if (hue < 0) hue = -hue;
int saturation = (int)Saturation - (int)hsv.Saturation;
if (saturation < 0) saturation = -saturation;
int value = (int)Value - (int)hsv.Value;
if (value < 0) value = -value;
return(hue*hue + saturation*saturation + value*value);
}
/***********************************************************************************************
* HSVClass::operator RGBClass -- Conversion operator for RGBClass object. *
* *
* This conversion operator will convert the HSV object into an RGB object. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with a reference (implied) of the RGBClass object that most closely *
* matches this HSVClass object. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/20/1996 JLB : Created. *
*=============================================================================================*/
HSVClass::operator RGBClass (void) const
{
unsigned int i; // Integer part.
unsigned int f; // Fractional or remainder part. f/HSV_BASE gives fraction.
unsigned int tmp; // Temporary variable to help with calculations.
unsigned int values[7]; // Possible rgb values. Don't use zero.
int hue = Get_Hue();
int saturation = Get_Saturation();
int value = Get_Value();
int red, green, blue;
hue *= 6;
f = hue % 255;
// Set up possible red, green and blue values.
values[1] =
values[2] = value;
//
// The following lines of code change
// values[3] = (v * (255 - ( (s * f) / 255) )) / 255;
// values[4] = values[5] = (v * (255 - s)) / 255;
// values[6] = (v * (255 - (s * (255 - f)) / 255)) / 255;
// so that the are rounded divides.
//
tmp = (saturation * f) / 255;
values[3] = (value * (255 - tmp)) / 255;
values[4] =
values[5] = (value * (255 - saturation)) / 255;
tmp = 255 - (saturation * (255 - f)) / 255;
values[6] = (value * tmp) / 255;
// This should not be rounded.
i = hue / 255;
i += (i > 4) ? -4 : 2;
red = values[i];
i += (i > 4) ? -4 : 2;
blue = values[i];
i += (i > 4) ? -4 : 2;
green = values[i];
RGBClass rgb((unsigned char)red, (unsigned char)green, (unsigned char)blue);
return(rgb);
}

View file

@ -0,0 +1,81 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Library/HSV.H $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef HSV_H
#define HSV_H
class RGBClass;
class HSVClass;
/*
** Each color entry is represented by this class. It holds the values for the color
** attributes. The values are recorded in a range from 0 to 255 with 255 being the
** maximum.
*/
class HSVClass
{
private:
static HSVClass const BlackColor;
public:
HSVClass(void) : Hue(0), Saturation(0), Value(0) {};
HSVClass(unsigned char hue, unsigned char saturation, unsigned char value) :
Hue(hue),
Saturation(saturation),
Value(value)
{};
operator RGBClass (void) const;
enum {
MAX_VALUE=255
};
void Adjust(int ratio, HSVClass const & hsv);
int Difference(HSVClass const & hsv) const;
int Get_Hue(void) const {return(Hue);};
int Get_Saturation(void) const {return(Saturation);};
int Get_Value(void) const {return(Value);};
void Set_Hue(unsigned char value) {Hue = value;}
void Set_Saturation(unsigned char value) {Saturation = value;}
void Set_Value(unsigned char value) {Value = value;}
private:
unsigned char Hue;
unsigned char Saturation;
unsigned char Value;
};
#endif

View file

@ -0,0 +1,85 @@
/*
** Command & Conquer Generals(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 : WWLib *
* *
* $Archive:: /G/wwlib/iostruct.h $*
* *
* Author:: Greg Hjelstrom *
* *
* $Modtime:: 4/02/99 11:59a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef IOSTRUCT_H
#define IOSTRUCT_H
#ifndef BITTYPE_H
#include "bittype.h"
#endif
/*
** Some useful structures for writing/writing (safe from changes).
** The chunk IO classes contain code for reading and writing these.
*/
struct IOVector2Struct
{
float32 X;
float32 Y;
};
struct IOVector3Struct
{
float32 X; // X,Y,Z coordinates
float32 Y;
float32 Z;
};
struct IOVector4Struct
{
float32 X;
float32 Y;
float32 Z;
float32 W;
};
struct IOQuaternionStruct
{
float32 Q[4];
};
#endif

View file

@ -0,0 +1,162 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Code/Tools/pluglib/jshell.cpp $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 11/07/00 2:32p $*
* *
* $Revision:: 28 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Fatal -- General purpose fatal error handler. *
* Set_Bit -- Set bit in a bit array. *
* Get_Bit -- Fetch the bit value from a bit array. *
* First_True_Bit -- Return with the first true bit index. *
* First_False_Bit -- Find the first false bit in the bit array. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
/***********************************************************************************************
* Set_Bit -- Set bit in a bit array. *
* *
* This routine is used to set (or clear) a bit in a bit array. *
* *
* INPUT: array -- Pointer to the bit array. *
* *
* bit -- The bit number to set. I.e., bit 32 is the first bit in the second *
* long word of memory. *
* *
* value -- The value to set the bit. The only values supported are 0 and 1. *
* *
* OUTPUT: none *
* *
* WARNINGS: Be sure that the array is big enough to set the specified bit. *
* *
* HISTORY: *
* 10/06/1997 JLB : Created. *
*=============================================================================================*/
void Set_Bit(void * array, int bit, int value)
{
unsigned char mask = (unsigned char)(1 << (bit % 8));
if (value != 0) {
*((unsigned char *)array + (bit/8)) |= mask;
} else {
*((unsigned char *)array + (bit/8)) &= (unsigned char)~mask;
}
}
/***********************************************************************************************
* Get_Bit -- Fetch the bit value from a bit array. *
* *
* This routine will fetch the specified bit value from the bit array. This is the *
* counterpart function to the Set_Bit() function. *
* *
* INPUT: array -- Pointer to the bit array to fetch the bit value from. *
* *
* bit -- The bit number to fetch. *
* *
* OUTPUT: Returns with the value of the bit. This return value will be either 1 or 0. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/06/1997 JLB : Created. *
*=============================================================================================*/
int Get_Bit(void const * array, int bit)
{
unsigned char mask = (unsigned char)(1 << (bit % 8));
return((*((unsigned char *)array + (bit/8)) & mask) != 0);
}
/***********************************************************************************************
* First_True_Bit -- Return with the first true bit index. *
* *
* This routine will scan the bit array and return with the index for the first true bit *
* in the array. *
* *
* INPUT: array -- Pointer to the bit array to scan. *
* *
* OUTPUT: Returns with the index of the first true (set to 1) bit in the array. *
* *
* WARNINGS: This routine does not stop at the end of the array (it doesn't know where the *
* end is) so there must be at least one true bit in the array or else it will *
* end up scanning past the end (undefined results in that case). *
* *
* HISTORY: *
* 10/06/1997 JLB : Created. *
*=============================================================================================*/
int First_True_Bit(void const * array)
{
int index = 0;
while (*((unsigned char *)array) == 0) {
index++;
array = ((char*)array) + 1;
}
int subindex;
for (subindex = 0; subindex < 8; subindex++) {
if (Get_Bit(array, subindex)) break;
}
return(index * 8 + subindex);
}
/***********************************************************************************************
* First_False_Bit -- Find the first false bit in the bit array. *
* *
* This routine will scan the bit array and return with the index of the first false (set *
* to 0) bit found. *
* *
* INPUT: array -- Pointer to the bit array to scan. *
* *
* OUTPUT: Returns with the index of the first false bit found in the array. *
* *
* WARNINGS: This routine will not stop scanning until a false bit was found. This means *
* that there must be at least one false bit in the array or else it will scan *
* past the end of the array. *
* *
* HISTORY: *
* 10/06/1997 JLB : Created. *
*=============================================================================================*/
int First_False_Bit(void const * array)
{
int index = 0;
while (*((unsigned char *)array) == 0xFF) {
index++;
array = ((char*)array) + 1;
}
int subindex;
for (subindex = 0; subindex < 8; subindex++) {
if (!Get_Bit(array, subindex)) break;
}
return(index * 8 + subindex);
}

View file

@ -0,0 +1,841 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/max2w3d/matrix3d.cpp 39 2/03/00 4:55p Jason_a $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Voxel Technology *
* *
* File Name : MATRIX3D.CPP *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 02/24/97 *
* *
* Last Update : February 28, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
* Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
* Matrix3D::Set -- Init a matrix3D from a matrix3 and a position *
* Matrix3D::Set -- Init a matrix3D from a quaternion and a position *
* Matrix3D::Get_X_Rotation -- approximates the rotation about the X axis *
* Matrix3D::Get_Y_Rotation -- approximates the rotation about the Y axis *
* Matrix3D::Get_Z_Rotation -- approximates the rotation about the Z axis *
* Matrix3D::Multiply -- matrix multiplication without temporaries. *
* Matrix3D::Inverse_Rotate_Vector -- rotates a vector by the inverse of the 3x3 sub-matrix *
* Matrix3D::Transform_Min_Max_AABox -- compute transformed axis-aligned box *
* Matrix3D::Transform_Center_Extent_AABox -- compute transformed axis-aligned box *
* Matrix3D::Get_Inverse -- calculate the inverse of this matrix *
* Matrix3D::Get_Orthogonal_Inverse -- Returns the inverse of the matrix *
* Matrix3D::Re_Orthogonalize -- makes this matrix orthogonal. *
* Matrix3D::Is_Orthogonal -- checks whether this matrix is orthogonal *
* Lerp - linearly interpolate matrices (orientation is slerped) *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "matrix3d.h"
#include <math.h>
#include <assert.h>
#include <stdlib.h>
//#include <stdio.h>
#include "vector3.h"
#include "wwmatrix3.h"
#include "matrix4.h"
#include "w3dquat.h"
// some static matrices which are sometimes useful
const Matrix3D Matrix3D::Identity
(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0
);
const Matrix3D Matrix3D::RotateX90
(
1.0, 0.0, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0,
0.0, 1.0, 0.0, 0.0
);
const Matrix3D Matrix3D::RotateX180
(
1.0, 0.0, 0.0, 0.0,
0.0, -1.0, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0
);
const Matrix3D Matrix3D::RotateX270
(
1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, -1.0, 0.0, 0.0
);
const Matrix3D Matrix3D::RotateY90
(
0.0, 0.0, 1.0, 0.0,
0.0, 1.0, 0.0, 0.0,
-1.0, 0.0, 0.0, 0.0
);
const Matrix3D Matrix3D::RotateY180
(
-1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0
);
const Matrix3D Matrix3D::RotateY270
(
0.0, 0.0, -1.0, 0.0,
0.0, 1.0, 0.0, 0.0,
1.0, 0.0, 0.0, 0.0
);
const Matrix3D Matrix3D::RotateZ90
(
0.0, -1.0, 0.0, 0.0,
1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0
);
const Matrix3D Matrix3D::RotateZ180
(
-1.0, 0.0, 0.0, 0.0,
0.0, -1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0
);
const Matrix3D Matrix3D::RotateZ270
(
0.0, 1.0, 0.0, 0.0,
-1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0
);
/***********************************************************************************************
* Matrix3D::Set -- Init a matrix3D from a matrix3 and a position *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
void Matrix3D::Set(const Matrix3 & rot,const Vector3 & pos)
{
Row[0].Set( rot[0][0], rot[0][1], rot[0][2], pos[0]);
Row[1].Set( rot[1][0], rot[1][1], rot[1][2], pos[1]);
Row[2].Set( rot[2][0], rot[2][1], rot[2][2], pos[2]);
}
/***********************************************************************************************
* Matrix3D::Set -- Init a matrix3D from a quaternion and a position *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
void Matrix3D::Set(const Quaternion & rot,const Vector3 & pos)
{
Set_Rotation(rot);
Set_Translation(pos);
}
/***********************************************************************************************
* Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/11/98 GTH : Created. *
*=============================================================================================*/
void Matrix3D::Set_Rotation(const Matrix3 & m)
{
Row[0][0] = m[0][0];
Row[0][1] = m[0][1];
Row[0][2] = m[0][2];
Row[1][0] = m[1][0];
Row[1][1] = m[1][1];
Row[1][2] = m[1][2];
Row[2][0] = m[2][0];
Row[2][1] = m[2][1];
Row[2][2] = m[2][2];
}
/***********************************************************************************************
* Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/11/98 GTH : Created. *
*=============================================================================================*/
void Matrix3D::Set_Rotation(const Quaternion & q)
{
Row[0][0] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]));
Row[0][1] = (float)(2.0 * (q[0] * q[1] - q[2] * q[3]));
Row[0][2] = (float)(2.0 * (q[2] * q[0] + q[1] * q[3]));
Row[1][0] = (float)(2.0 * (q[0] * q[1] + q[2] * q[3]));
Row[1][1] = (float)(1.0 - 2.0f * (q[2] * q[2] + q[0] * q[0]));
Row[1][2] = (float)(2.0 * (q[1] * q[2] - q[0] * q[3]));
Row[2][0] = (float)(2.0 * (q[2] * q[0] - q[1] * q[3]));
Row[2][1] = (float)(2.0 * (q[1] * q[2] + q[0] * q[3]));
Row[2][2] =(float)(1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]));
}
/***********************************************************************************************
* Matrix3D::Get_X_Rotation -- approximates the rotation about the X axis *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/11/1997 GH : Created. *
*=============================================================================================*/
float Matrix3D::Get_X_Rotation(void) const
{
return atan2(Row[2][1], Row[1][1]);
}
/***********************************************************************************************
* Matrix3D::Get_Y_Rotation -- approximates the rotation about the Y axis *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/11/1997 GH : Created. *
*=============================================================================================*/
float Matrix3D::Get_Y_Rotation(void) const
{
return atan2(Row[0][2], Row[2][2]);
}
/***********************************************************************************************
* Matrix3D::Get_Z_Rotation -- approximates the rotation about the Z axis *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/11/1997 GH : Created. *
*=============================================================================================*/
float Matrix3D::Get_Z_Rotation(void) const
{
return atan2(Row[1][0], Row[0][0]);
}
/***********************************************************************************************
* M3DC::Rotate_Vector -- Uses the 3x3 sub-matrix to rotate a vector *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
Vector3 Matrix3D::Rotate_Vector(const Vector3 &vect) const
{
return Vector3(
(Row[0][0]*vect[0] + Row[0][1]*vect[1] + Row[0][2]*vect[2]),
(Row[1][0]*vect[0] + Row[1][1]*vect[1] + Row[1][2]*vect[2]),
(Row[2][0]*vect[0] + Row[2][1]*vect[1] + Row[2][2]*vect[2])
);
}
/***********************************************************************************************
* Matrix3D::Inverse_Rotate_Vector -- rotates a vector by the inverse of the 3x3 sub-matrix *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 4/27/98 GTH : Created. *
*=============================================================================================*/
Vector3 Matrix3D::Inverse_Rotate_Vector(const Vector3 &vect) const
{
return Vector3(
(Row[0][0]*vect[0] + Row[1][0]*vect[1] + Row[2][0]*vect[2]),
(Row[0][1]*vect[0] + Row[1][1]*vect[1] + Row[2][1]*vect[2]),
(Row[0][2]*vect[0] + Row[1][2]*vect[1] + Row[2][2]*vect[2])
);
}
/***********************************************************************************************
* M3DC::Look_At -- Creates a "look at" transformation. *
* *
* Builds a transformation matrix which positions the origin at p, *
* points the negative z-axis towards a target t, and rolls about the z-axis *
* by the angle specified by roll. *
* *
* This can be useful for creating a camera matrix, just invert *
* the matrix after initializing it with this function... *
* *
* INPUT: *
* p - position of the coordinate system *
* t - target of the coordinate system *
* roll - roll angle (in radians) *
* *
* OUTPUT: *
* *
* WARNINGS: *
* This function is written assuming the convention that the "ground" is the X-Y plane and *
* Z is altitude. *
* *
* HISTORY: *
*=============================================================================================*/
void Matrix3D::Look_At(const Vector3 &p,const Vector3 &t,float roll)
{
float dx,dy,dz; //vector from p to t
float len1,len2;
float sinp,cosp; //sine and cosine of the pitch ("up-down" tilt about x)
float siny,cosy; //sine and cosine of the yaw ("left-right"tilt about z)
dx = (t[0] - p[0]);
dy = (t[1] - p[1]);
dz = (t[2] - p[2]);
len1 = (float)WWMath::Sqrt(dx*dx + dy*dy + dz*dz);
len2 = (float)WWMath::Sqrt(dx*dx + dy*dy);
if (len1 != 0.0f) {
sinp = dz/len1;
cosp = len2/len1;
} else {
sinp = 0.0f;
cosp = 1.0f;
}
if (len2 != 0.0f) {
siny = dy/len2;
cosy = dx/len2;
} else {
siny = 0.0f;
cosy = 1.0f;
}
// init the matrix with position p and -z pointing down +x and +y up
Row[0].X = 0.0f; Row[0].Y = 0.0f; Row[0].Z = -1.0f;
Row[1].X = -1.0f; Row[1].Y = 0.0f; Row[1].Z = 0.0f;
Row[2].X = 0.0f; Row[2].Y = 1.0f; Row[2].Z = 0.0f;
Row[0].W = p.X;
Row[1].W = p.Y;
Row[2].W = p.Z;
// Yaw rotation to make the matrix look at the projection of the target
// into the x-y plane
Rotate_Y(siny,cosy);
// rotate about local x axis to pitch up to the targets position
Rotate_X(sinp,cosp);
// roll about the local z axis (negate since we look down -z)
Rotate_Z(-roll);
}
/***********************************************************************************************
* M3DC::Obj_Look_At -- Commando Object "look at" transformation. *
* *
* Builds a transformation matrix which positions the origin at p, *
* points the positive X axis towards a target t, and rolls about the X axis *
* by the angle specified by roll. *
* *
* The object convention used by Commando and G is Forward = +X, Left = +Y, Up = +Z. The *
* world is basically the x-y plane with z as altitude and +x is the default "forward". *
* *
* INPUT: *
* p - position of the coordinate system *
* t - target of the coordinate system *
* roll - roll angle (in radians) *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
void Matrix3D::Obj_Look_At(const Vector3 &p,const Vector3 &t,float roll)
{
float dx,dy,dz; //vector from p to t
float len1,len2;
float sinp,cosp; //sine and cosine of the pitch ("up-down" tilt about y)
float siny,cosy; //sine and cosine of the yaw ("left-right"tilt about z)
dx = (t[0] - p[0]);
dy = (t[1] - p[1]);
dz = (t[2] - p[2]);
len1 = (float)sqrt(dx*dx + dy*dy + dz*dz);
len2 = (float)sqrt(dx*dx + dy*dy);
if (len1 != 0.0f) {
sinp = dz/len1;
cosp = len2/len1;
} else {
sinp = 0.0f;
cosp = 1.0f;
}
if (len2 != 0.0f) {
siny = dy/len2;
cosy = dx/len2;
} else {
siny = 0.0f;
cosy = 1.0f;
}
Make_Identity();
Translate(p);
// Yaw rotation to projection of target in x-y plane
Rotate_Z(siny,cosy);
// Pitch rotation
Rotate_Y(-sinp,cosp);
// Roll rotation
Rotate_X(roll);
}
/***********************************************************************************************
* Matrix3D::Get_Inverse -- calculate the inverse of this matrix *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/7/98 GTH : Created. *
*=============================================================================================*/
void Matrix3D::Get_Inverse(Matrix3D & inv) const
{
// TODO: Implement the general purpose inverse function here (once we need it :-)
Get_Orthogonal_Inverse(inv);
}
/***********************************************************************************************
* Matrix3D::Get_Orthogonal_Inverse -- Returns the inverse of the matrix *
* *
* NOTE!!! This only works if the matrix is really ORTHOGONAL!!! *
* *
***********************************************************************************************
* Inverting an orthogonal Matrix3D *
* *
* M is the original transform, *
* R is rotation submatrix, *
* T is translation vector in M. *
* *
* To build MINV *
* *
* R' = transpose of R (inverse of orthogonal 3x3 matrix is transpose) *
* T' = -R'T *
* *
* Build MINV with R'and T' *
* MINV is the inverse of M *
* *
***********************************************************************************************
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
void Matrix3D::Get_Orthogonal_Inverse(Matrix3D & inv) const
{
// Transposing the rotation submatrix
inv.Row[0][0] = Row[0][0];
inv.Row[0][1] = Row[1][0];
inv.Row[0][2] = Row[2][0];
inv.Row[1][0] = Row[0][1];
inv.Row[1][1] = Row[1][1];
inv.Row[1][2] = Row[2][1];
inv.Row[2][0] = Row[0][2];
inv.Row[2][1] = Row[1][2];
inv.Row[2][2] = Row[2][2];
// Now, calculate translation portion of matrix:
// T' = -R'T
Vector3 trans = Get_Translation();
trans = inv.Rotate_Vector(trans);
trans = -trans;
inv.Row[0][3] = trans[0];
inv.Row[1][3] = trans[1];
inv.Row[2][3] = trans[2];
}
/***********************************************************************************************
* Copy_3x3_Matrix(float *matrix) -- Copies a 3x3 (float[9]) matrix into this matrix *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/16/98 EHC : Created. *
*=============================================================================================*/
void Matrix3D::Copy_3x3_Matrix(float matrix[3][3])
{
Row[0][0] = matrix[0][0];
Row[0][1] = matrix[0][1];
Row[0][2] = matrix[0][2];
Row[0][3] = 0;
Row[1][0] = matrix[1][0];
Row[1][1] = matrix[1][1];
Row[1][2] = matrix[1][2];
Row[1][3] = 0;
Row[2][0] = matrix[2][0];
Row[2][1] = matrix[2][1];
Row[2][2] = matrix[2][2];
Row[2][3] = 0;
}
/***********************************************************************************************
* Matrix3D::Multiply -- matrix multiplication without temporaries. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 4/22/98 GTH : Created. *
*=============================================================================================*/
//void print_matrix(const Matrix3D & m);
void Matrix3D::Multiply(const Matrix3D & A,const Matrix3D & B,Matrix3D * set_res)
{
assert(set_res != NULL);
Matrix3D tmp;
Matrix3D * Aptr;
float tmp1,tmp2,tmp3;
// Check for aliased parameters, copy the 'A' matrix into a temporary if the
// result is going into 'A'. (in this case, this function is no better than
// the overloaded C++ operator...)
if (set_res == &A) {
tmp = A;
Aptr = &tmp;
} else {
Aptr = (Matrix3D *)&A;
}
tmp1 = B[0][0];
tmp2 = B[1][0];
tmp3 = B[2][0];
(*set_res)[0][0] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
(*set_res)[1][0] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
(*set_res)[2][0] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
tmp1 = B[0][1];
tmp2 = B[1][1];
tmp3 = B[2][1];
(*set_res)[0][1] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
(*set_res)[1][1] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
(*set_res)[2][1] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
tmp1 = B[0][2];
tmp2 = B[1][2];
tmp3 = B[2][2];
(*set_res)[0][2] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
(*set_res)[1][2] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
(*set_res)[2][2] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
tmp1 = B[0][3];
tmp2 = B[1][3];
tmp3 = B[2][3];
(*set_res)[0][3] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3 + (*Aptr)[0][3];
(*set_res)[1][3] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3 + (*Aptr)[1][3];
(*set_res)[2][3] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3 + (*Aptr)[2][3];
}
/***********************************************************************************************
* Matrix3D::Transform_Min_Max_AABox -- compute transformed axis-aligned box *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/17/98 GTH : Created. *
*=============================================================================================*/
void Matrix3D::Transform_Min_Max_AABox
(
const Vector3 & min,
const Vector3 & max,
Vector3 * set_min,
Vector3 * set_max
) const
{
assert(set_min != &min);
assert(set_max != &max);
float tmp0,tmp1;
// init the min and max to the translation of the transform
set_min->X = set_max->X = Row[0][3];
set_min->Y = set_max->Y = Row[1][3];
set_min->Z = set_max->Z = Row[2][3];
// now push them both out by the projections of the original intervals
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
tmp0 = Row[i][j] * min[j];
tmp1 = Row[i][j] * max[j];
if (tmp0 < tmp1) {
(*set_min)[i] += tmp0;
(*set_max)[i] += tmp1;
} else {
(*set_min)[i] += tmp1;
(*set_max)[i] += tmp0;
}
}
}
}
/***********************************************************************************************
* Matrix3D::Transform_Center_Extent_AABox -- compute transformed axis-aligned box *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/17/98 GTH : Created. *
*=============================================================================================*/
void Matrix3D::Transform_Center_Extent_AABox
(
const Vector3 & center,
const Vector3 & extent,
Vector3 * set_center,
Vector3 * set_extent
) const
{
assert(set_center != &center);
assert(set_extent != &extent);
// push each extent out to the projections of the original extents
for (int i=0; i<3; i++) {
// start the center out at the translation portion of the matrix
// and the extent at zero
(*set_center)[i] = Row[i][3];
(*set_extent)[i] = 0.0f;
for (int j=0; j<3; j++) {
(*set_center)[i] += Row[i][j] * center[j];
(*set_extent)[i] += WWMath::Fabs(Row[i][j] * extent[j]);
}
}
}
/***********************************************************************************************
* Matrix3D::Is_Orthogonal -- checks whether this matrix is orthogonal *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/16/98 GTH : Created. *
*=============================================================================================*/
int Matrix3D::Is_Orthogonal(void) const
{
Vector3 x(Row[0].X,Row[0].Y,Row[0].Z);
Vector3 y(Row[1].X,Row[1].Y,Row[1].Z);
Vector3 z(Row[2].X,Row[2].Y,Row[2].Z);
if (Vector3::Dot_Product(x,y) > WWMATH_EPSILON) return 0;
if (Vector3::Dot_Product(y,z) > WWMATH_EPSILON) return 0;
if (Vector3::Dot_Product(z,x) > WWMATH_EPSILON) return 0;
if (WWMath::Fabs(x.Length() - 1.0f) > WWMATH_EPSILON) return 0;
if (WWMath::Fabs(y.Length() - 1.0f) > WWMATH_EPSILON) return 0;
if (WWMath::Fabs(z.Length() - 1.0f) > WWMATH_EPSILON) return 0;
return 1;
}
/***********************************************************************************************
* Matrix3D::Re_Orthogonalize -- makes this matrix orthogonal. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* This function is rather expensive, should only be used if you *know* numerical error is *
* killing you. *
* *
* HISTORY: *
* 9/16/98 GTH : Created. *
*=============================================================================================*/
void Matrix3D::Re_Orthogonalize(void)
{
Vector3 x(Row[0][0],Row[0][1],Row[0][2]);
Vector3 y(Row[1][0],Row[1][1],Row[1][2]);
Vector3 z;
Vector3::Cross_Product(x,y,&z);
Vector3::Cross_Product(z,x,&y);
float len = x.Length();
if (len < WWMATH_EPSILON) {
Make_Identity();
return;
} else {
x *= 1.0f/len;
}
len = y.Length();
if (len < WWMATH_EPSILON) {
Make_Identity();
return;
} else {
y *= 1.0f/len;
}
len = z.Length();
if (len < WWMATH_EPSILON) {
Make_Identity();
return;
} else {
z *= 1.0f/len;
}
Row[0][0] = x.X;
Row[0][1] = x.Y;
Row[0][2] = x.Z;
Row[1][0] = y.X;
Row[1][1] = y.Y;
Row[1][2] = y.Z;
Row[2][0] = z.X;
Row[2][1] = z.Y;
Row[2][2] = z.Z;
}
/***********************************************************************************************
* Lerp - linearly interpolate matrices (orientation is slerped) *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/05/1998 NH : Created. *
*=============================================================================================*/
Matrix3D Lerp(const Matrix3D &A, const Matrix3D &B, float factor)
{
assert(factor >= 0.0f);
assert(factor <= 1.0f);
// Lerp position
Vector3 pos = Lerp(A.Get_Translation(), B.Get_Translation(), factor);
Quaternion rot = Slerp(Build_Quaternion(A), Build_Quaternion(B), factor);
return Matrix3D(rot, pos);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,174 @@
/*
** Command & Conquer Generals(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/matrix4.cpp $*
* *
* Author:: Greg_h *
* *
* $Modtime:: 11/13/99 10:50a $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Matrix4::Multiply -- Multiply two Matrix4's together *
* Matrix4::Multiply -- Multiply a Matrix3D * Matrix4 *
* Matrix4::Multiply -- Multiply a Matrix4 * Matrix3D *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "matrix4.h"
#include <assert.h>
/***********************************************************************************************
* Matrix4::Multiply -- Multiply two Matrix4's together *
* *
* INPUT: *
* a - first operand *
* b - second operand *
* res - pointer to matrix to store the result in (must not point to a or b) *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/13/99 gth : Created. *
*=============================================================================================*/
void Matrix4::Multiply(const Matrix4 &a,const Matrix4 &b,Matrix4 * res)
{
assert(res != &a);
assert(res != &b);
#define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j] + a[i][3]*b[3][j]
(*res)[0][0] = ROWCOL(0,0);
(*res)[0][1] = ROWCOL(0,1);
(*res)[0][2] = ROWCOL(0,2);
(*res)[0][3] = ROWCOL(0,3);
(*res)[1][0] = ROWCOL(1,0);
(*res)[1][1] = ROWCOL(1,1);
(*res)[1][2] = ROWCOL(1,2);
(*res)[1][3] = ROWCOL(1,3);
(*res)[2][0] = ROWCOL(2,0);
(*res)[2][1] = ROWCOL(2,1);
(*res)[2][2] = ROWCOL(2,2);
(*res)[2][3] = ROWCOL(2,3);
(*res)[3][0] = ROWCOL(3,0);
(*res)[3][1] = ROWCOL(3,1);
(*res)[3][2] = ROWCOL(3,2);
(*res)[3][3] = ROWCOL(3,3);
#undef ROWCOL
}
/***********************************************************************************************
* Matrix4::Multiply -- Multiply a Matrix3D * Matrix4 *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/13/99 gth : Created. *
*=============================================================================================*/
void Matrix4::Multiply(const Matrix3D &a,const Matrix4 &b,Matrix4 * res)
{
assert(res != &b);
#define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j] + a[i][3]*b[3][j]
(*res)[0][0] = ROWCOL(0,0);
(*res)[0][1] = ROWCOL(0,1);
(*res)[0][2] = ROWCOL(0,2);
(*res)[0][3] = ROWCOL(0,3);
(*res)[1][0] = ROWCOL(1,0);
(*res)[1][1] = ROWCOL(1,1);
(*res)[1][2] = ROWCOL(1,2);
(*res)[1][3] = ROWCOL(1,3);
(*res)[2][0] = ROWCOL(2,0);
(*res)[2][1] = ROWCOL(2,1);
(*res)[2][2] = ROWCOL(2,2);
(*res)[2][3] = ROWCOL(2,3);
(*res)[3][0] = b[3][0]; // last row of a is 0,0,0,1
(*res)[3][1] = b[3][1]; // this leaves the last row of b unchanged
(*res)[3][2] = b[3][2];
(*res)[3][3] = b[3][3];
#undef ROWCOL
}
/***********************************************************************************************
* Matrix4::Multiply -- Multiply a Matrix4 * Matrix3D *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
void Matrix4::Multiply(const Matrix4 & a,const Matrix3D & b,Matrix4 * res)
{
assert(res != &a);
// ROWCOL multiplies a row of 'a' by one of the first three columns of 'b' (4th entry in b is zero)
// ROWCOL4 multiplies a row of 'a' by the fourth column of 'b' (4th entry in b is one)
#define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
#define ROWCOL4(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j] + a[i][3]
(*res)[0][0] = ROWCOL(0,0);
(*res)[0][1] = ROWCOL(0,1);
(*res)[0][2] = ROWCOL(0,2);
(*res)[0][3] = ROWCOL4(0,3);
(*res)[1][0] = ROWCOL(1,0);
(*res)[1][1] = ROWCOL(1,1);
(*res)[1][2] = ROWCOL(1,2);
(*res)[1][3] = ROWCOL4(1,3);
(*res)[2][0] = ROWCOL(2,0);
(*res)[2][1] = ROWCOL(2,1);
(*res)[2][2] = ROWCOL(2,2);
(*res)[2][3] = ROWCOL4(2,3);
(*res)[3][0] = ROWCOL(3,0);
(*res)[3][1] = ROWCOL(3,1);
(*res)[3][2] = ROWCOL(3,2);
(*res)[3][3] = ROWCOL4(3,3);
#undef ROWCOL
#undef ROWCOL4
}

View file

@ -0,0 +1,716 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/max2w3d/matrix4.h 15 2/03/00 4:55p Jason_a $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* File Name : MATRIX4.H *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 06/02/97 *
* *
* Last Update : June 2, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Matrix4::Matrix4 -- Constructor, optionally initialize to Identitiy matrix *
* Matrix4::Matrix4 -- Copy Constructor *
* Matrix4::Matrix4 -- Convert a Matrix3D (fake 4x4) to a Matrix4 *
* Matrix4::Matrix4 -- Constructor *
* Matrix4::Make_Identity -- Initializes the matrix to Identity *
* Matrix4::Init -- Initializes from the contents of the give Matrix3D *
* Matrix4::Init -- Initializes the rows from the given Vector4s *
* Matrix4::Init_Ortho -- Initialize to an orthographic projection matrix *
* Matrix4::Init_Perspective -- Initialize to a perspective projection matrix *
* Matrix4::Init_Perspective -- Initialize to a perspective projection matrix *
* Matrix4::Transpose -- Returns transpose of the matrix *
* Matrix4::Inverse -- returns the inverse of the matrix *
* Matrix4::operator = -- assignment operator *
* Matrix4::operator += -- "plus equals" operator *
* Matrix4::operator-= -- "minus equals" operator *
* Matrix4::operator *= -- "times equals" operator *
* Matrix4::operator /= -- "divide equals" operator *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef MATRIX4_H
#define MATRIX4_H
#include "always.h"
#include "vector4.h"
#include "matrix3d.h"
#include "wwmatrix3.h"
class Matrix4
{
public:
/*
** Constructors
*/
Matrix4(void) {};
Matrix4(const Matrix4 & m);
explicit Matrix4(bool identity);
explicit Matrix4(const Matrix3D & m);
explicit Matrix4(const Matrix3 & m);
explicit Matrix4(const Vector4 & v0, const Vector4 & v1, const Vector4 & v2, const Vector4 & v3);
void Make_Identity(void);
void Init(const Matrix3D & m);
void Init(const Matrix3 & m);
void Init(const Vector4 & v0, const Vector4 & v1, const Vector4 & v2, const Vector4 & v3);
void Init_Ortho(float left,float right,float bottom,float top,float znear,float zfar);
void Init_Perspective(float hfov,float vfov,float znear,float zfar);
void Init_Perspective(float left,float right,float bottom,float top,float znear,float zfar);
/*
** Access operators
*/
Vector4 & operator [] (int i) { return Row[i]; }
const Vector4 & operator [] (int i) const { return Row[i]; }
/*
** Transpose and Inverse
*/
Matrix4 Transpose(void) const;
Matrix4 Inverse(void) const;
/*
** Assignment operators
*/
Matrix4 & operator = (const Matrix4 & m);
Matrix4 & operator += (const Matrix4 & m);
Matrix4 & operator -= (const Matrix4 & m);
Matrix4 & operator *= (float d);
Matrix4 & operator /= (float d);
/*
** Negation
*/
friend Matrix4 operator - (const Matrix4& a);
/*
** Scalar multiplication and division
*/
friend Matrix4 operator * (const Matrix4& a,float d);
friend Matrix4 operator * (float d,const Matrix4& a);
friend Matrix4 operator / (const Matrix4& a,float d);
/*
** matrix addition
*/
friend Matrix4 operator + (const Matrix4& a, const Matrix4& b);
friend Matrix4 Add(const Matrix4& a);
/*
** matrix subtraction
*/
friend Matrix4 operator - (const Matrix4 & a, const Matrix4 & b);
friend Matrix4 Subtract(const Matrix4 & a, const Matrix4 & b);
/*
** matrix multiplication
*/
friend Matrix4 operator * (const Matrix4 & a, const Matrix4 & b);
friend Matrix4 Multiply(const Matrix4 & a, const Matrix4 & b);
/*
** Comparison operators
*/
friend int operator == (const Matrix4 & a, const Matrix4 & b);
friend int operator != (const Matrix4 & a, const Matrix4 & b);
/*
** Swap two matrices in place
*/
friend void Swap(Matrix4 & a,Matrix4 & b);
/*
** Linear Transforms
*/
friend Vector4 operator * (const Matrix4 & a, const Vector4 & v);
friend Vector4 operator * (const Matrix4 & a, const Vector3 & v);
/*
** Matrix multiplication without temporaries...
*/
static void Multiply(const Matrix4 &A,const Matrix4 &B,Matrix4 * set_result);
static void Multiply(const Matrix3D &A,const Matrix4 &B,Matrix4 * set_result);
static void Multiply(const Matrix4 &A,const Matrix3D &B,Matrix4 * set_result);
static void Transform_Vector(const Matrix4 & tm,const Vector3 & in,Vector3 * out);
protected:
Vector4 Row[4];
};
/***********************************************************************************************
* Matrix4::Matrix4 -- Constructor, optionally initialize to Identitiy matrix *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4::Matrix4(bool identity)
{
if (identity) {
Make_Identity();
}
}
/***********************************************************************************************
* Matrix4::Matrix4 -- Copy Constructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4::Matrix4(const Matrix4 & m)
{
Row[0] = m.Row[0]; Row[1] = m.Row[1]; Row[2] = m.Row[2]; Row[3] = m.Row[3];
}
/***********************************************************************************************
* Matrix4::Matrix4 -- Convert a Matrix3D (fake 4x4) to a Matrix4 *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4::Matrix4(const Matrix3D & m)
{
Init(m);
}
/***********************************************************************************************
* Matrix4::Matrix4 -- Constructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4::Matrix4(const Vector4 & r0, const Vector4 & r1, const Vector4 & r2, const Vector4 & r3)
{
Init(r0,r1,r2,r3);
}
/***********************************************************************************************
* Matrix4::Make_Identity -- Initializes the matrix to Identity *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/5/99 gth : Created. *
*=============================================================================================*/
inline void Matrix4::Make_Identity(void)
{
Row[0].Set(1.0,0.0,0.0,0.0);
Row[1].Set(0.0,1.0,0.0,0.0);
Row[2].Set(0.0,0.0,1.0,0.0);
Row[3].Set(0.0,0.0,0.0,1.0);
}
/***********************************************************************************************
* Matrix4::Init -- Initializes from the contents of the give Matrix3D *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/5/99 gth : Created. *
*=============================================================================================*/
inline void Matrix4::Init(const Matrix3D & m)
{
Row[0] = m[0]; Row[1] = m[1]; Row[2] = m[2]; Row[3] = Vector4(0.0,0.0,0.0,1.0);
}
/***********************************************************************************************
* Matrix4::Init -- Initializes the rows from the given Vector4s *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/5/99 gth : Created. *
*=============================================================================================*/
inline void Matrix4::Init(const Vector4 & r0, const Vector4 & r1, const Vector4 & r2, const Vector4 & r3)
{
Row[0] = r0; Row[1] = r1; Row[2] = r2; Row[3] = r3;
}
/***********************************************************************************************
* Matrix4::Init_Ortho -- Initialize to an orthographic projection matrix *
* *
* You can find the formulas for this in the appendix of the OpenGL programming guide. Also *
* this happens to be the same convention used by Surrender. *
* *
* The result of this projection will be that points inside the volume will have all coords *
* between -1 and +1. A point at znear will project to z=-1. A point at zfar will project *
* to z=+1... *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* Note that the znear and zfar parameters are positive distances to the clipping planes *
* even though in the camera coordinate system, the clipping planes are at negative z *
* coordinates. This holds for all of the projection initializations and is consistent *
* with OpenGL's convention. *
* *
* HISTORY: *
* 11/5/99 gth : Created. *
*=============================================================================================*/
inline void Matrix4::Init_Ortho
(
float left,
float right,
float bottom,
float top,
float znear,
float zfar
)
{
assert(znear >= 0.0f);
assert(zfar > znear);
Make_Identity();
Row[0][0] = 2.0f / (right - left);
Row[0][3] = -(right + left) / (right - left);
Row[1][1] = 2.0f / (top - bottom);
Row[1][3] = -(top + bottom) / (top - bottom);
Row[2][2] = -2.0f / (zfar - znear);
Row[2][3] = -(zfar + znear) / (zfar - znear);
}
/***********************************************************************************************
* Matrix4::Init_Perspective -- Initialize to a perspective projection matrix *
* *
* You can find the formulas for this matrix in the appendix of the OpenGL programming guide. *
* Also, this happens to be the same convention used by Surrender. *
* *
* INPUT: *
* hfov - horizontal field of view (in radians) *
* vfov - vertical field of view (in radians) *
* znear - distance to near z clipping plane (positive) *
* zfar - distance to the far z clipping plane (positive) *
* *
* OUTPUT: *
* *
* WARNINGS: *
* Note that the znear and zfar parameters are positive distances to the clipping planes *
* even though in the camera coordinate system, the clipping planes are at negative z *
* coordinates. This holds for all of the projection initializations and is consistent *
* with OpenGL's convention. *
* *
* HISTORY: *
* 11/5/99 gth : Created. *
*=============================================================================================*/
inline void Matrix4::Init_Perspective(float hfov,float vfov,float znear,float zfar)
{
assert(znear > 0.0f);
assert(zfar > znear);
Make_Identity();
Row[0][0] = (1.0 / tan(hfov*0.5));
Row[1][1] = (1.0 / tan(vfov*0.5));
Row[2][2] = -(zfar + znear) / (zfar - znear);
Row[2][3] = -(2.0*zfar*znear) / (zfar - znear);
Row[3][2] = -1.0f;
Row[3][3] = 0.0f;
}
/***********************************************************************************************
* Matrix4::Init_Perspective -- Initialize to a perspective projection matrix *
* *
* You can find the formulas for this matrix in the appendix of the OpenGL programming guide. *
* Also, this happens to be the same convention used by Surrender. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* Note that the znear and zfar parameters are positive distances to the clipping planes *
* even though in the camera coordinate system, the clipping planes are at negative z *
* coordinates. This holds for all of the projection initializations and is consistent *
* with OpenGL's convention. *
* *
* HISTORY: *
* 11/5/99 gth : Created. *
*=============================================================================================*/
inline void Matrix4::Init_Perspective
(
float left,
float right,
float bottom,
float top,
float znear,
float zfar
)
{
assert(znear > 0.0f);
assert(zfar > 0.0f);
Make_Identity();
Row[0][0] = 2.0*znear / (right - left);
Row[0][2] = (right + left) / (right - left);
Row[1][1] = 2.0*znear / (top - bottom);
Row[1][2] = (top + bottom) / (top - bottom);
Row[2][2] = -(zfar + znear) / (zfar - znear);
Row[2][3] = -(2.0*zfar*znear) / (zfar - znear);
Row[3][2] = -1.0f;
Row[3][3] = 0.0f;
}
/***********************************************************************************************
* Matrix4::Transpose -- Returns transpose of the matrix *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4 Matrix4::Transpose() const
{
return Matrix4(
Vector4(Row[0][0], Row[1][0], Row[2][0], Row[3][0]),
Vector4(Row[0][1], Row[1][1], Row[2][1], Row[3][1]),
Vector4(Row[0][2], Row[1][2], Row[2][2], Row[3][2]),
Vector4(Row[0][3], Row[1][3], Row[2][3], Row[3][3])
);
}
/***********************************************************************************************
* Matrix4::Inverse -- returns the inverse of the matrix *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4 Matrix4::Inverse() const // Gauss-Jordan elimination with partial pivoting
{
Matrix4 a(*this); // As a evolves from original mat into identity
Matrix4 b(true); // b evolves from identity into inverse(a)
int i, j, i1;
// Loop over cols of a from left to right, eliminating above and below diagonal
for (j=0; j<4; j++) {
// Find largest pivot in column j among rows j..3
i1 = j;
for (i=j+1; i<4; i++) {
if (WWMath::Fabs(a[i][j]) > WWMath::Fabs(a[i1][j])) {
i1 = i;
}
}
// Swap rows i1 and j in a and b to put pivot on diagonal
Swap(a.Row[i1], a.Row[j]);
Swap(b.Row[i1], b.Row[j]);
// Scale row j to have a unit diagonal
if (a[j][j]==0.) {
//ALGEBRA_ERROR("Matrix4::inverse: singular matrix; can't invert\n");
}
b.Row[j] /= a.Row[j][j];
a.Row[j] /= a.Row[j][j];
// Eliminate off-diagonal elems in col j of a, doing identical ops to b
for (i=0; i<4; i++) {
if (i != j) {
b.Row[i] -= a[i][j] * b.Row[j];
a.Row[i] -= a[i][j] * a.Row[j];
}
}
}
return b;
}
/***********************************************************************************************
* Matrix4::operator = -- assignment operator *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4 & Matrix4::operator = (const Matrix4 & m)
{
Row[0] = m.Row[0]; Row[1] = m.Row[1]; Row[2] = m.Row[2]; Row[3] = m.Row[3];
return *this;
}
/***********************************************************************************************
* Matrix4::operator += -- "plus equals" operator *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4& Matrix4::operator += (const Matrix4 & m)
{
Row[0] += m.Row[0]; Row[1] += m.Row[1]; Row[2] += m.Row[2]; Row[3] += m.Row[3];
return *this;
}
/***********************************************************************************************
* Matrix4::operator-= -- "minus equals" operator *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4& Matrix4::operator -= (const Matrix4 & m)
{
Row[0] -= m.Row[0]; Row[1] -= m.Row[1]; Row[2] -= m.Row[2]; Row[3] -= m.Row[3];
return *this;
}
/***********************************************************************************************
* Matrix4::operator *= -- "times equals" operator *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4& Matrix4::operator *= (float d)
{
Row[0] *= d; Row[1] *= d; Row[2] *= d; Row[3] *= d;
return *this;
}
/***********************************************************************************************
* Matrix4::operator /= -- "divide equals" operator *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline Matrix4& Matrix4::operator /= (float d)
{
float ood = d;
Row[0] *= ood; Row[1] *= ood; Row[2] *= ood; Row[3] *= ood;
return *this;
}
inline Matrix4 operator - (const Matrix4 & a)
{
return Matrix4(-a.Row[0], -a.Row[1], -a.Row[2], -a.Row[3]);
}
inline Matrix4 operator * (const Matrix4 & a, float d)
{
return Matrix4(a.Row[0] * d, a.Row[1] * d, a.Row[2] * d, a.Row[3] * d);
}
inline Matrix4 operator * (float d, const Matrix4 & a)
{
return a*d;
}
inline Matrix4 operator / (const Matrix4 & a, float d)
{
float ood = 1.0f / d;
return Matrix4(a.Row[0] * ood, a.Row[1] * ood, a.Row[2] * ood, a.Row[3] * ood);
}
/*
** matrix addition
*/
inline Matrix4 operator + (const Matrix4 & a, const Matrix4 & b)
{
return Matrix4(
a.Row[0] + b.Row[0],
a.Row[1] + b.Row[1],
a.Row[2] + b.Row[2],
a.Row[3] + b.Row[3]
);
}
inline Matrix4 Add(const Matrix4 & a, const Matrix4 & b)
{ return a+b; }
/*
** matrix subtraction
*/
inline Matrix4 operator - (const Matrix4 & a, const Matrix4 & b)
{
return Matrix4(
a.Row[0] - b.Row[0],
a.Row[1] - b.Row[1],
a.Row[2] - b.Row[2],
a.Row[3] - b.Row[3]
);
}
inline Matrix4 Subtract(const Matrix4 & a, const Matrix4 & b)
{ return a-b; }
/*
** matrix multiplication
*/
inline Matrix4 operator * (const Matrix4 & a, const Matrix4 & b)
{
#define ROWCOL(i, j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j] + a[i][3]*b[3][j]
return Matrix4(
Vector4(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)),
Vector4(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)),
Vector4(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)),
Vector4(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3))
);
#undef ROWCOL
}
inline Matrix4 Multiply(const Matrix4 & a, const Matrix4 & b)
{ return a*b; }
/*
** Multiply a Matrix4 by a Vector3 (assumes w=1.0!!!). Yeilds a Vector4 result
*/
inline Vector4 operator * (const Matrix4 & a, const Vector3 & v) {
return Vector4(
a[0][0] * v[0] + a[0][1] * v[1] + a[0][2] * v[2] + a[0][3] * 1.0,
a[1][0] * v[0] + a[1][1] * v[1] + a[1][2] * v[2] + a[1][3] * 1.0,
a[2][0] * v[0] + a[2][1] * v[1] + a[2][2] * v[2] + a[2][3] * 1.0,
a[3][0] * v[0] + a[3][1] * v[1] + a[3][2] * v[2] + a[3][3] * 1.0
);
}
/*
** Multiply a Matrix4 by a Vector4
*/
inline Vector4 operator * (const Matrix4 & a, const Vector4 & v) {
return Vector4(
a[0][0] * v[0] + a[0][1] * v[1] + a[0][2] * v[2] + a[0][3] * v[3],
a[1][0] * v[0] + a[1][1] * v[1] + a[1][2] * v[2] + a[1][3] * v[3],
a[2][0] * v[0] + a[2][1] * v[1] + a[2][2] * v[2] + a[2][3] * v[3],
a[3][0] * v[0] + a[3][1] * v[1] + a[3][2] * v[2] + a[3][3] * v[3]
);
}
/*
** Multiply a Matrix4 by a Vector4
*/
inline void Matrix4::Transform_Vector(const Matrix4 & A,const Vector3 & in,Vector3 * out)
{
Vector3 tmp;
Vector3 * v;
// check for aliased parameters
if (out == &in) {
tmp = in;
v = &tmp;
} else {
v = (Vector3 *)&in; // whats the right way to do this...
}
out->X = (A[0][0] * v->X + A[0][1] * v->Y + A[0][2] * v->Z + A[0][3]);
out->Y = (A[1][0] * v->X + A[1][1] * v->Y + A[1][2] * v->Z + A[1][3]);
out->Z = (A[2][0] * v->X + A[2][1] * v->Y + A[2][2] * v->Z + A[2][3]);
}
#endif /*MATRIX4_H*/

View file

@ -0,0 +1,286 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/max2w3d/nodefilt.cpp 9 1/16/98 10:34a Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G *
* *
* File Name : NODEFILT.CPP *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 06/09/97 *
* *
* Last Update : June 9, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* VisibleMeshINodeFilter::Accept_Node -- Accepts visible meshes *
* AnimatedINodeFilter::Accept_Node -- Accepts animated INodes *
* RootINodeFilter::Accept_Node -- Accepts root INodes *
* VisibleHelperINodeFilter::Accept_Node -- Accepts visible helper objects *
* VisibleMeshOrHelperINodeFilter::Accept_Node -- Accepts visible helper or mesh objects *
* HelperINodeFilter::Accept_Node -- Accepts all helper inodes (including hidden) *
* MeshINodeFilter::Accept_Node -- Accepts all mesh inodes (including hidden) *
* VisibleSelectedINodeFilter::Accept_Node -- Accepts Visible and selected inodes *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "nodefilt.h"
#include <istdplug.h>
/*
** The default node filter:
*/
VisibleMeshINodeFilter DefaultINodeFilter;
/***********************************************************************************************
* HelperINodeFilter::Accept_Node -- Accepts all helper inodes (including hidden) *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/10/1997 GH : Created. *
*=============================================================================================*/
BOOL HelperINodeFilter::Accept_Node(INode * node,TimeValue time)
{
Object * obj = node->EvalWorldState(time).obj;
if (obj && obj->SuperClassID() == HELPER_CLASS_ID) {
return TRUE;
}
return FALSE;
}
/***********************************************************************************************
* MeshINodeFilter::Accept_Node -- Accepts all mesh inodes (including hidden) *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/10/1997 GH : Created. *
*=============================================================================================*/
BOOL MeshINodeFilter::Accept_Node(INode * node,TimeValue time)
{
Object * obj = node->EvalWorldState(time).obj;
if (obj &&
obj->CanConvertToType(triObjectClassID) &&
obj->SuperClassID() == GEOMOBJECT_CLASS_ID)
{
return TRUE;
} else {
return FALSE;
}
}
/***********************************************************************************************
* VisibleMeshINodeFilter::Accept_Node -- Accepts visible meshes *
* *
* Accepts nodes which: *
* - can be converted to tri-meshes *
* - are not hidden *
* - whose visibility > 0.0 *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/09/1997 GH : Created. *
*=============================================================================================*/
BOOL VisibleMeshINodeFilter::Accept_Node(INode * node, TimeValue time)
{
Object * obj = node->EvalWorldState(time).obj;
if
(
obj
&& !node->IsHidden ()
&& obj->CanConvertToType(triObjectClassID)
&& obj->SuperClassID() == GEOMOBJECT_CLASS_ID
// && node->GetVisibility (time) > 0.0f
)
{
return TRUE;
} else {
return FALSE;
}
}
/***********************************************************************************************
* VisibleHelperINodeFilter::Accept_Node -- Accepts visible helper objects *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/03/1997 GH : Created. *
*=============================================================================================*/
BOOL VisibleHelperINodeFilter::Accept_Node(INode * node, TimeValue time)
{
Object * obj = node->EvalWorldState(time).obj;
if ((!obj) || (node->IsHidden()) /*|| (node->GetVisibility(time) <= 0.0f)*/) {
return FALSE;
}
if (obj->SuperClassID() == HELPER_CLASS_ID) {
return TRUE;
}
return FALSE;
}
/***********************************************************************************************
* VisibleMeshOrHelperINodeFilter::Accept_Node -- Accepts visible helper or mesh objects *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/03/1997 GH : Created. *
*=============================================================================================*/
BOOL VisibleMeshOrHelperINodeFilter::Accept_Node(INode * node, TimeValue time)
{
Object * obj = node->EvalWorldState(time).obj;
if ((!obj) || (node->IsHidden()) /*|| (node->GetVisibility(time) <= 0.0f)*/) {
return FALSE;
}
if (obj->CanConvertToType(triObjectClassID) && obj->SuperClassID() == GEOMOBJECT_CLASS_ID) {
return TRUE;
}
if (obj->SuperClassID() == HELPER_CLASS_ID) {
return TRUE;
}
return FALSE;
}
/***********************************************************************************************
* AnimatedINodeFilter::Accept_Node -- Accepts animated INodes *
* *
* Accepts nodes which: *
* - can be converted to tri-meshes *
* - are not hidden *
* - whose visibility > 0.0 *
* - have animation keys! *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/09/1997 GH : Created. *
*=============================================================================================*/
BOOL AnimatedINodeFilter::Accept_Node(INode * node, TimeValue time)
{
Object * obj = node->EvalWorldState(time).obj;
Control * poscon = node->GetTMController()->GetPositionController();
Control * rotcon = node->GetTMController()->GetRotationController();
int numkeys = 0;
if (poscon != NULL) {
IKeyControl * poskeys = GetKeyControlInterface(poscon);
if (poskeys != NULL) numkeys += poskeys->GetNumKeys();
}
if (rotcon != NULL) {
IKeyControl * rotkeys = GetKeyControlInterface(rotcon);
if (rotkeys != NULL) numkeys += rotkeys->GetNumKeys();
}
if (obj && !node->IsHidden() && numkeys > 0) {
return TRUE;
}
return FALSE;
}
/***********************************************************************************************
* VisibleSelectedINodeFilter::Accept_Node -- Accepts Visible and selected inodes *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/13/98 GTH : Created. *
*=============================================================================================*/
BOOL VisibleSelectedINodeFilter::Accept_Node(INode * node, TimeValue time)
{
if (!node->IsHidden() && node->Selected()) {
return TRUE;
} else {
return FALSE;
}
}

View file

@ -0,0 +1,178 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/max2w3d/nodefilt.h 6 1/14/98 10:23a Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G *
* *
* File Name : NODEFILT.H *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 06/09/97 *
* *
* Last Update : June 9, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef NODEFILT_H
#define NODEFILT_H
#include "always.h"
#include <Max.h>
/***************************************************************
*
* INodeFilterClass
*
* This is simply an object used to accept or reject INodes
* based on whatever criteria you desire. There are some
* default node filters defined in this module or you can
* create your own by inheriting the Abstract Base Class
* INodeFilterClass and implementing the Accept_Node method.
*
***************************************************************/
class INodeFilterClass
{
public:
virtual BOOL Accept_Node(INode * node, TimeValue time) = 0;
};
/***************************************************************
*
* AnyINodeFilter
*
* Accepts all INodes...
*
***************************************************************/
class AnyINodeFilter : public INodeFilterClass
{
public:
virtual BOOL Accept_Node(INode * node, TimeValue time) { return TRUE; }
};
/***************************************************************
*
* HelperINodeFilter
*
* Accepts INodes which are Helper objects
*
***************************************************************/
class HelperINodeFilter : public INodeFilterClass
{
public:
virtual BOOL Accept_Node(INode * node, TimeValue time);
};
/***************************************************************
*
* MeshINodeFilter
*
* Only accepts INodes which are Triangle meshes
*
***************************************************************/
class MeshINodeFilter : public INodeFilterClass
{
public:
virtual BOOL Accept_Node(INode * node, TimeValue time);
};
/***************************************************************
*
* VisibleMeshINodeFilter
*
* Only accepts INodes which are Triangle meshes and are
* currently visible
*
***************************************************************/
class VisibleMeshINodeFilter : public INodeFilterClass
{
public:
virtual BOOL Accept_Node(INode * node, TimeValue time);
};
/***************************************************************
*
* VisibleHelperINodeFilter
*
* Only accepts INodes which are Helper objects and are
* currently visible
*
***************************************************************/
class VisibleHelperINodeFilter : public INodeFilterClass
{
public:
virtual BOOL Accept_Node(INode * node, TimeValue time);
};
/***************************************************************
*
* VisibleMeshOrHelperINodeFilter
*
* Only accepts INodes which are Triangle meshes or helper
* objects and are currently visible
*
***************************************************************/
class VisibleMeshOrHelperINodeFilter : public INodeFilterClass
{
public:
virtual BOOL Accept_Node(INode * node, TimeValue time);
};
/***************************************************************
*
* AnimatedINodeFilter
*
* Only accepts INodes which contain at least on animation
* key.
*
***************************************************************/
class AnimatedINodeFilter : public INodeFilterClass
{
public:
virtual BOOL Accept_Node(INode * node, TimeValue time);
};
/***************************************************************
*
* VisibleSelectedINodeFilter
*
* Only accepts INodes which are Visible and Selected
*
***************************************************************/
class VisibleSelectedINodeFilter : public INodeFilterClass
{
public:
virtual BOOL Accept_Node(INode * node, TimeValue time);
};
#endif /*NODEFILT_H*/

View file

@ -0,0 +1,373 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/pluglib/nodelist.cpp 8 1/02/01 6:31p Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G *
* *
* File Name : NODELIST.CPP *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 06/09/97 *
* *
* Last Update : June 9, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* INodeListClass::INodeListClass -- Create an INodeList *
* INodeListClass::~INodeListClass -- Delete the INode List *
* INode * INodeListClass::operator[] -- Array-like access to the list members *
* INodeListClass::callback -- callback function for MAX *
* INodeListClass::INodeListClass -- A "copy" contstructor with filtering... *
* INodeListClass::INodeListClass -- constructor *
* INodeListClass::INodeListClass -- Constructor *
* INodeListClass::Insert -- insert a list of nodes into this list *
* INodeListClass::Insert -- Inserts an INode into the list *
* INodeListClass::Add_Tree -- Add a tree of INodes to the list *
* INodeListClass::Remove -- Remove the i'th element of the list *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "nodelist.h"
static AnyINodeFilter _AnyFilter;
/*******************************************************************************
* ListEntryClass
*
* Used to implement a linked list of INodes.
*
*******************************************************************************/
class INodeListEntryClass
{
public:
INodeListEntryClass(INode * n,TimeValue /*time*/) { Node = n; }
~INodeListEntryClass(void) {}
INode * Node;
INodeListEntryClass * Next;
};
/***********************************************************************************************
* INodeListClass::INodeListClass -- Constructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/02/1997 GH : Created. *
*=============================================================================================*/
INodeListClass::INodeListClass(TimeValue time,INodeFilterClass * inodefilter) :
NumNodes(0),
Time(time),
ListHead(NULL),
INodeFilter(inodefilter)
{
if (INodeFilter == NULL) {
INodeFilter = &_AnyFilter;
}
}
/***********************************************************************************************
* INodeListClass::INodeListClass -- Create an INodeList *
* *
* INPUT: *
* scene - 3dsMAX scene to enumerate *
* time - time at which to create the list of INodes *
* inodefilter - object which will accept or reject each INode in the scene *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/09/1997 GH : Created. *
*=============================================================================================*/
INodeListClass::INodeListClass(IScene * scene,TimeValue time,INodeFilterClass * inodefilter) :
NumNodes(0),
Time(time),
ListHead(NULL),
INodeFilter(inodefilter)
{
if (INodeFilter == NULL) {
INodeFilter = &_AnyFilter;
}
scene->EnumTree(this);
}
/***********************************************************************************************
* INodeListClass::INodeListClass -- Constructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/13/98 GTH : Created. *
*=============================================================================================*/
INodeListClass::INodeListClass(INode * root,TimeValue time,INodeFilterClass * nodefilter) :
NumNodes(0),
Time(time),
ListHead(NULL),
INodeFilter(nodefilter)
{
if (INodeFilter == NULL) {
INodeFilter = &_AnyFilter;
}
Add_Tree(root);
}
/***********************************************************************************************
* INodeListClass::INodeListClass -- A "copy" contstructor with filtering... *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/02/1997 GH : Created. *
*=============================================================================================*/
INodeListClass::INodeListClass(INodeListClass & copyfrom,TimeValue time,INodeFilterClass * inodefilter) :
NumNodes(0),
Time(time),
ListHead(NULL),
INodeFilter(inodefilter)
{
if (INodeFilter == NULL) {
INodeFilter = &_AnyFilter;
}
for (unsigned i=0; i<copyfrom.Num_Nodes(); i++) {
Insert(copyfrom[i]);
}
}
/***********************************************************************************************
* INodeListClass::~INodeListClass -- Delete the INode List *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/09/1997 GH : Created. *
*=============================================================================================*/
INodeListClass::~INodeListClass(void)
{
while (ListHead)
{
INodeListEntryClass * next = ListHead->Next;
delete ListHead;
ListHead = next;
}
NumNodes = 0;
ListHead = NULL;
}
/***********************************************************************************************
* INode * INodeListClass::operator[] -- Array-like access to the list members *
* *
* INPUT: *
* index - index of the list entry *
* *
* OUTPUT: *
* pointer to an INode *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/09/1997 GH : Created. *
*=============================================================================================*/
INode * INodeListClass::operator[] ( int index ) const
{
INodeListEntryClass * entry = ListHead;
while (index > 0 && entry != NULL )
{
entry = entry->Next;
index--;
}
return entry->Node;
}
/***********************************************************************************************
* INodeListClass::Insert -- insert a list of nodes into this list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/14/98 GTH : Created. *
*=============================================================================================*/
void INodeListClass::Insert(INodeListClass & insertlist)
{
for (unsigned int i=0; i<insertlist.Num_Nodes(); i++) {
Insert(insertlist[i]);
}
}
/***********************************************************************************************
* INodeListClass::Insert -- Inserts an INode into the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/02/1997 GH : Created. *
*=============================================================================================*/
void INodeListClass::Insert(INode * node)
{
if (INodeFilter->Accept_Node(node,Time))
{
INodeListEntryClass * newentry = new INodeListEntryClass(node, Time);
newentry->Next = ListHead;
ListHead = newentry;
NumNodes++;
}
}
/***********************************************************************************************
* INodeListClass::Remove -- Remove the i'th element of the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/27/2000 gth : Created. *
*=============================================================================================*/
void INodeListClass::Remove(int i)
{
if ((i < 0) || (i > Num_Nodes())) {
return;
}
INodeListEntryClass * prev = ListHead;
while (i > 1) {
prev = prev->Next;
}
INodeListEntryClass * deleteme = prev->Next;
if (deleteme != NULL) {
prev->Next = prev->Next->Next;
delete deleteme;
}
}
/***********************************************************************************************
* INodeListClass::Add_Tree -- Add a tree of INodes to the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/13/98 GTH : Created. *
*=============================================================================================*/
void INodeListClass::Add_Tree(INode * root)
{
if (root == NULL) return;
Insert(root);
for (int i=0; i<root->NumberOfChildren(); i++) {
Add_Tree(root->GetChildNode(i));
}
}
/***********************************************************************************************
* INodeListClass::callback -- callback function for MAX *
* *
* 3dsMAX calls this function with a pointer to each INode in the scene. We keep a pointer *
* to the ones we like. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/09/1997 GH : Created. *
*=============================================================================================*/
int INodeListClass::callback(INode * node)
{
Insert(node);
return TREE_CONTINUE; // Keep on enumerating....
}
void INodeListClass::Sort(const INodeCompareClass & node_compare)
{
for (unsigned int i=0; i<Num_Nodes(); i++) {
for (unsigned int j=0; j<Num_Nodes(); j++) {
INodeListEntryClass * ni = get_nth_item(i);
INodeListEntryClass * nj = get_nth_item(j);
if (node_compare(ni->Node,nj->Node) > 0) {
INode * tmp = ni->Node;
ni->Node = nj->Node;
nj->Node = tmp;
}
}
}
}
INodeListEntryClass * INodeListClass::get_nth_item(int index)
{
INodeListEntryClass * entry = ListHead;
while (index > 0 && entry != NULL )
{
entry = entry->Next;
index--;
}
return entry;
}

View file

@ -0,0 +1,102 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/pluglib/nodelist.h 7 1/02/01 6:31p Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G *
* *
* File Name : NODELIST.H *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 06/09/97 *
* *
* Last Update : June 9, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef NODELIST_H
#define NODELIST_H
#include "always.h"
#include <Max.h>
#ifndef NODEFILT_H
#include "nodefilt.h"
#endif
class INodeListEntryClass;
class INodeCompareClass;
/*******************************************************************************
* INodeListClass
*
* This is a class that can enumerate a 3dsMax scene and build a list of
* all of the INodes that meet your desired criteria.
*
*******************************************************************************/
class INodeListClass : public ITreeEnumProc
{
public:
INodeListClass(TimeValue time,INodeFilterClass * nodefilter = NULL);
INodeListClass(IScene * scene,TimeValue time,INodeFilterClass * nodefilter = NULL);
INodeListClass(INode * root,TimeValue time,INodeFilterClass * nodefilter = NULL);
INodeListClass(INodeListClass & copyfrom,TimeValue time,INodeFilterClass * inodefilter = NULL);
~INodeListClass();
void Set_Filter(INodeFilterClass * inodefilter) { INodeFilter = inodefilter; }
void Insert(INodeListClass & insertlist);
void Insert(INode * node);
void Remove(int i);
unsigned Num_Nodes(void) const { return NumNodes; }
INode * operator[] (int index) const;
void Sort(const INodeCompareClass & node_compare);
void Add_Tree(INode * root);
private:
unsigned NumNodes;
TimeValue Time;
INodeListEntryClass * ListHead;
INodeFilterClass * INodeFilter;
INodeListEntryClass * get_nth_item(int index);
int callback(INode * node);
};
class INodeCompareClass
{
public:
// returns <0 if nodea < node b.
// returns =0 if nodea = node b.
// returns >0 if nodea > node b.
virtual int operator() (INode * nodea,INode * nodeb) const = 0;
};
#endif /*NODELIST_H*/

View file

@ -0,0 +1,57 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /G/wwlib/noinit.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 3/23/99 5:20p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef NOINIT_H
#define NOINIT_H
/**********************************************************************
** This class is solely used as a parameter to a constructor that does
** absolutely no initialization to the object being constructed. By using
** this method, it is possible to load and save data directly from a
** class that has virtual functions. The construction process automatically
** takes care of initializing the virtual function table pointer and the
** rest of the constructor doesn't initialize any data members. After loading
** into a class object, simply perform an in-place new operation.
*/
#ifndef NoInitClass
class NoInitClass {
public:
void operator () (void) const {};
};
#endif
#endif

View file

@ -0,0 +1,268 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Library/PALETTE.CPP $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* PaletteClass::Adjust -- Adjusts the palette toward another palette. *
* PaletteClass::Adjust -- Adjusts this palette toward black. *
* PaletteClass::Closest_Color -- Finds closest match to color specified. *
* PaletteClass::PaletteClass -- Constructor that fills palette with color specified. *
* PaletteClass::operator = -- Assignment operator for palette objects. *
* PaletteClass::operator == -- Equality operator for palette objects. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "palette.h"
#include <string.h>
/***********************************************************************************************
* PaletteClass::PaletteClass -- Constructor that fills palette with color specified. *
* *
* This constructor will fill the palette with the color specified. *
* *
* INPUT: rgb -- Reference to the color to fill the entire palette with. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 12/02/1995 JLB : Created. *
*=============================================================================================*/
PaletteClass::PaletteClass(RGBClass const & rgb)
{
for (int index = 0; index < COLOR_COUNT; index++) {
Palette[index] = rgb;
}
}
PaletteClass::PaletteClass(unsigned char *binary_palette)
{
memcpy(&Palette[0], binary_palette, sizeof(Palette));
}
/***********************************************************************************************
* PaletteClass::operator == -- Equality operator for palette objects. *
* *
* This is the comparison for equality operator. It will compare palette objects to *
* determine if they are identical. *
* *
* INPUT: palette -- Reference to the palette to compare to this palette. *
* *
* OUTPUT: Are the two palettes identical? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 12/02/1995 JLB : Created. *
*=============================================================================================*/
int PaletteClass::operator == (PaletteClass const & palette) const
{
if (this == &palette) return(true);
return(memcmp(&Palette[0], &palette.Palette[0], sizeof(Palette)) == 0);
}
/***********************************************************************************************
* PaletteClass::operator = -- Assignment operator for palette objects. *
* *
* This is the assignment operator for palette objects. Although the default C++ generated *
* assignment operator would function correctly, it would not check for self-assignment *
* and thus this routine can be faster. *
* *
* INPUT: palette -- Reference to that palette that will be copied into this palette. *
* *
* OUTPUT: Returns with a reference to the newly copied to palette. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 12/02/1995 JLB : Created. *
*=============================================================================================*/
PaletteClass & PaletteClass::operator = (PaletteClass const & palette)
{
if (this == &palette) return(*this);
memcpy(&Palette[0], &palette.Palette[0], sizeof(Palette));
return(*this);
}
/***********************************************************************************************
* PaletteClass::Adjust -- Adjusts this palette toward black. *
* *
* This routine is used to adjust this palette toward black. Typical use of this routine *
* is when fading the palette to black. *
* *
* INPUT: ratio -- The ratio to fade this palette to black. 0 means no fading at all. 255 *
* means 100% faded to black. *
* *
* OUTPUT: none *
* *
* WARNINGS: This routine doesn't actually set the palette to the video card. Use the Set() *
* function to achieve that purpose. *
* *
* HISTORY: *
* 12/02/1995 JLB : Created. *
*=============================================================================================*/
void PaletteClass::Adjust(int ratio)
{
for (int index = 0; index < COLOR_COUNT; index++) {
Palette[index].Adjust(ratio, BlackColor);
}
}
/***********************************************************************************************
* PaletteClass::Adjust -- Adjusts the palette toward another palette. *
* *
* This routine is used to adjust a palette toward a destination palette by the ratio *
* specified. This is primarily used by the palette fading routines. *
* *
* INPUT: palette -- Reference to the destination palette. *
* *
* ratio -- The ratio to adjust this palette toward the destination palette. A *
* value of 0 means no adjustment at all. A value of 255 means 100% *
* adjustment. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 12/02/1995 JLB : Created. *
*=============================================================================================*/
void PaletteClass::Adjust(int ratio, PaletteClass const & palette)
{
for (int index = 0; index < COLOR_COUNT; index++) {
Palette[index].Adjust(ratio, palette[index]);
}
}
/***********************************************************************************************
* PaletteClass::Partial_Adjust -- Adjusts the specified parts of this palette toward black. *
* *
* This routine is used to adjust this palette toward black. Typical use of this routine *
* is when fading the palette to black. The input lookup table is used to determine *
* which entries should fade and which should stay the same *
* *
* INPUT: ratio -- The ratio to fade this palette to black. 0 means no fading at all. 255 *
* means 100% faded to black. *
* *
* lookup -- ptr to lookup table *
* *
* OUTPUT: none *
* *
* WARNINGS: This routine doesn't actually set the palette to the video card. Use the Set() *
* function to achieve that purpose. *
* *
* HISTORY: *
* 12/02/1995 JLB : Created. *
*=============================================================================================*/
void PaletteClass::Partial_Adjust(int ratio, char *lut)
{
for (int index = 0; index < COLOR_COUNT; index++) {
if (lut[index]) {
Palette[index].Adjust(ratio, BlackColor);
}
}
}
/***********************************************************************************************
* PaletteClass::Partial_Adjust -- Adjusts the palette toward another palette. *
* *
* This routine is used to adjust a palette toward a destination palette by the ratio *
* specified. This is primarily used by the palette fading routines. The input lookup *
* table is used to determine which entries should fade and which should stay the same *
* *
* *
* INPUT: palette -- Reference to the destination palette. *
* *
* ratio -- The ratio to adjust this palette toward the destination palette. A *
* value of 0 means no adjustment at all. A value of 255 means 100% *
* adjustment. *
* *
* lookup -- ptr to lookup table *
* *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 12/02/1995 JLB : Created. *
*=============================================================================================*/
void PaletteClass::Partial_Adjust(int ratio, PaletteClass const & palette, char *lut)
{
for (int index = 0; index < COLOR_COUNT; index++) {
if (lut[index]) {
Palette[index].Adjust(ratio, palette[index]);
}
}
}
/***********************************************************************************************
* PaletteClass::Closest_Color -- Finds closest match to color specified. *
* *
* This routine will examine the palette and return with the color index number for the *
* color that most closely matches the color specified. Remap operations rely heavily on *
* this routine to allow working with a constant palette. *
* *
* INPUT: rgb -- Reference to a color to search for in the current palette. *
* *
* OUTPUT: Returns with a color index value to most closely matches the specified color. *
* *
* WARNINGS: This routine will quite likely not find an exact match. *
* *
* HISTORY: *
* 12/02/1995 JLB : Created. *
*=============================================================================================*/
int PaletteClass::Closest_Color(RGBClass const & rgb) const
{
int closest = 0;
int value = -1;
RGBClass const * ptr = &Palette[0];
for (int index = 0; index < COLOR_COUNT; index++) {
int difference = rgb.Difference(*ptr++);
if (value == -1 || difference < value) {
value = difference;
closest = index;
}
}
return(closest);
}

View file

@ -0,0 +1,81 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /G/wwlib/PALETTE.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 12:00p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef PALETTE_H
#define PALETTE_H
#include "rgb.h"
/*
** The palette class is used to manipulate a palette as a whole. All 256 colors are
** represented by the palette class object.
*/
class PaletteClass
{
public:
enum {
COLOR_COUNT=256 // Number of color indices on the palette.
};
PaletteClass(void) {};
PaletteClass(RGBClass const & rgb);
PaletteClass(unsigned char *binary_palette);
RGBClass & operator[] (int index) {return(Palette[index % COLOR_COUNT]);};
RGBClass const & operator[] (int index) const {return(Palette[index % COLOR_COUNT]);};
RGBClass & Get_Color(int index) {return(Palette[index % COLOR_COUNT]);};
RGBClass const & Get_Color(int index) const {return(Palette[index % COLOR_COUNT]);};
int operator == (PaletteClass const & palette) const;
int operator != (PaletteClass const & palette) const {return(!(operator ==(palette)));};
PaletteClass & operator = (PaletteClass const & palette);
operator const unsigned char * (void) const {return((const unsigned char *)&Palette[0]);};
operator unsigned char * (void) {return((unsigned char *)&Palette[0]);};
void Adjust(int ratio);
void Adjust(int ratio, PaletteClass const & palette);
void Partial_Adjust(int ratio, char *lut);
void Partial_Adjust(int ratio, PaletteClass const & palette, char *lut);
int Closest_Color(RGBClass const & rgb) const;
protected:
RGBClass Palette[COLOR_COUNT];
};
#endif

View file

@ -0,0 +1,99 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/pluglib/plane.h 8 4/22/98 6:36p Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Voxel Technology *
* *
* File Name : PLANE.H *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 03/17/97 *
* *
* Last Update : March 17, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef PLANE_H
#define PLANE_H
#ifndef VECTOR3_H
#include "vector3.h"
#endif
/*
** PlaneClass
**
** 3D-planes. This class needs to be fleshed out but it does what I need for now.
*/
class PlaneClass
{
public:
Vector3 N;
float D;
PlaneClass(void) : N(0.0f,0.0f,1.0f), D(0.0f) { }
PlaneClass(float a,float b,float c,float d) : N(a,b,c),D(d) { }
PlaneClass(const Vector3 & normal,float dist) : N(normal), D(dist) { }
// Create a plane given the normal and a point on the plane
PlaneClass(const Vector3 & normal,const Vector3 & point);
// Create a plane out of three points, ordered according to a right-hand convention.
PlaneClass(const Vector3 & point1, const Vector3 & point2, const Vector3 & point3);
void Set(float a,float b,float c,float d) { N[0] = a; N[1] = b; N[2] = c; D = d; }
};
inline PlaneClass::PlaneClass(const Vector3 & normal,const Vector3 & point)
{
N = normal;
D = Vector3::Dot_Product(normal , point);
}
inline PlaneClass::PlaneClass(const Vector3 & point1, const Vector3 & point2, const Vector3 & point3)
{
N = Vector3::Cross_Product((point2 - point1), (point3 - point1));
if (N != Vector3(0.0f, 0.0f, 0.0f)) {
// Points are not colinear. Normalize N and calculate D.
N.Normalize();
D = N * point1;
} else {
// They are colinear - return default plane (constructors can't fail).
N = Vector3(0.0f, 0.0f, 1.0f);
D = 0.0f;
}
}
inline bool In_Front(const Vector3 & point,const PlaneClass & plane)
{
double dist = point * plane.N;
return (dist > plane.D);
}
#endif /*PLANE_H*/

View file

@ -0,0 +1,441 @@
# Microsoft Developer Studio Project File - Name="pluglib" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=pluglib - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "pluglib.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "pluglib.mak" CFG="pluglib - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "pluglib - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "pluglib - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE "pluglib - Win32 Hybrid" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""$/Commando/Code/Tools/pluglib", TSJAAAAA"
# PROP Scc_LocalPath "."
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "pluglib - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\Release"
# PROP BASE Intermediate_Dir ".\Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\Release"
# PROP Intermediate_Dir ".\Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "D:\3dsmax4\maxsdk\Include" /I "D:\3dsmax4\maxsdk\Include\Maxscrpt" /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /YX /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\Debug"
# PROP BASE Intermediate_Dir ".\Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\Debug"
# PROP Intermediate_Dir ".\Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /D "_DEBUG" /D "_WINDOWS" /YX /FD "WIN32" /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:".\Debug\pluglibd.lib"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "pluglib_"
# PROP BASE Intermediate_Dir "pluglib_"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Hybrid"
# PROP Intermediate_Dir "Hybrid"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /Z7 /Od /I "D:\3dsmax4\maxsdk\Include" /I "D:\3dsmax4\maxsdk\Include\Maxscrpt" /D "WIN32" /D "_WINDOWS" /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:".\Lib\pluglib.lib"
# ADD LIB32 /nologo /out:".\Hybrid\pluglib.lib"
!ENDIF
# Begin Target
# Name "pluglib - Win32 Release"
# Name "pluglib - Win32 Debug"
# Name "pluglib - Win32 Hybrid"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
# Begin Source File
SOURCE=.\chunkio.cpp
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\EULER.CPP
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\HSV.CPP
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\JShell.CPP
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\matrix3d.cpp
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\matrix4.cpp
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\nodefilt.cpp
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\nodelist.cpp
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\PALETTE.CPP
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\RAWFILE.CPP
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\realcrc.cpp
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\RGB.CPP
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\Vector.CPP
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\w3dquat.cpp
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\wwmath.cpp
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\WWmatrix3.cpp
!IF "$(CFG)" == "pluglib - Win32 Release"
!ELSEIF "$(CFG)" == "pluglib - Win32 Debug"
!ELSEIF "$(CFG)" == "pluglib - Win32 Hybrid"
!ENDIF
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=.\aaplane.h
# End Source File
# Begin Source File
SOURCE=.\always.h
# End Source File
# Begin Source File
SOURCE=.\bool.h
# End Source File
# Begin Source File
SOURCE=.\borlandc.h
# End Source File
# Begin Source File
SOURCE=.\chunkio.h
# End Source File
# Begin Source File
SOURCE=.\errclass.h
# End Source File
# Begin Source File
SOURCE=.\EULER.H
# End Source File
# Begin Source File
SOURCE=.\hsv.h
# End Source File
# Begin Source File
SOURCE=.\iostruct.h
# End Source File
# Begin Source File
SOURCE=.\matrix3d.h
# End Source File
# Begin Source File
SOURCE=.\matrix4.h
# End Source File
# Begin Source File
SOURCE=.\nodefilt.h
# End Source File
# Begin Source File
SOURCE=.\nodelist.h
# End Source File
# Begin Source File
SOURCE=.\palette.h
# End Source File
# Begin Source File
SOURCE=.\PROGRESS.H
# End Source File
# Begin Source File
SOURCE=.\rawfile.h
# End Source File
# Begin Source File
SOURCE=.\realcrc.h
# End Source File
# Begin Source File
SOURCE=.\rgb.h
# End Source File
# Begin Source File
SOURCE=.\Vector.H
# End Source File
# Begin Source File
SOURCE=.\vector2.h
# End Source File
# Begin Source File
SOURCE=.\vector3i.h
# End Source File
# Begin Source File
SOURCE=.\visualc.h
# End Source File
# Begin Source File
SOURCE=.\w3dquat.h
# End Source File
# Begin Source File
SOURCE=.\watcom.h
# End Source File
# Begin Source File
SOURCE=.\win.h
# End Source File
# Begin Source File
SOURCE=.\wwfile.h
# End Source File
# Begin Source File
SOURCE=.\wwmath.h
# End Source File
# Begin Source File
SOURCE=.\WWmatrix3.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,205 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /G/wwlib/rawfile.h $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 10/04/99 10:25a $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* RawFileClass::File_Name -- Returns with the filename associate with the file object. *
* RawFileClass::RawFileClass -- Default constructor for a file object. *
* RawFileClass::~RawFileClass -- Default deconstructor for a file object. *
* RawFileClass::Is_Open -- Checks to see if the file is open or not. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef RAWFILE_Hx
#define RAWFILE_Hx
//#include <errno.h>
// #include "win.h"
#ifdef _UNIX
#include <stdio.h>
#include "osdep.h"
#define NULL_HANDLE NULL
#define HANDLE_TYPE FILE*
#else
#define NULL_HANDLE INVALID_HANDLE_VALUE
#define HANDLE_TYPE HANDLE
#endif
#include "wwfile.h"
#ifndef WWERROR
#define WWERROR -1
#endif
/*
** This is the definition of the raw file class. It is derived from the abstract base FileClass
** and handles the interface to the low level DOS routines. This is the first class in the
** chain of derived file classes that actually performs a useful function. With this class,
** I/O is possible. More sophisticated features, such as packed files, CD-ROM support,
** file caching, and XMS/EMS memory support, are handled by derived classes.
**
** Of particular importance is the need to override the error routine if more sophisticated
** error handling is required. This is more than likely if greater functionality is derived
** from this base class.
*/
class RawFileClass : public FileClass
{
typedef FileClass BASECLASS;
public:
/*
** This is a record of the access rights used to open the file. These rights are
** used if the file object is duplicated.
*/
int Rights;
RawFileClass(char const *filename);
RawFileClass(void);
RawFileClass (RawFileClass const & f);
RawFileClass & operator = (RawFileClass const & f);
virtual ~RawFileClass(void);
virtual char const * File_Name(void) const;
virtual char const * Set_Name(char const *filename);
virtual int Create(void);
virtual int Delete(void);
virtual bool Is_Available(int forced=false);
virtual bool Is_Open(void) const;
virtual int Open(char const *filename, int rights=READ);
virtual int Open(int rights=READ);
virtual int Read(void *buffer, int size);
virtual int Seek(int pos, int dir=SEEK_CUR);
virtual int Size(void);
virtual int Write(void const *buffer, int size);
virtual void Close(void);
virtual unsigned long Get_Date_Time(void);
virtual bool Set_Date_Time(unsigned long datetime);
virtual void Error(int error, int canretry = false, char const * filename=NULL);
void Bias(int start, int length=-1);
virtual void * Get_File_Handle(void) { return Handle; }
virtual void Attach (void *handle, int rights=READ);
virtual void Detach (void);
/*
** These bias values enable a sub-portion of a file to appear as if it
** were the whole file. This comes in very handy for multi-part files such as
** mixfiles.
*/
int BiasStart;
int BiasLength;
protected:
/*
** This function returns the largest size a low level DOS read or write may
** perform. Larger file transfers are performed in chunks of this size or less.
*/
int Transfer_Block_Size(void);
int Raw_Seek(int pos, int dir=SEEK_CUR);
void Reset(void);
private:
/*
** This is the low level DOS handle. A -1 indicates an empty condition.
*/
#ifdef _UNIX
FILE* Handle;
#else
void * Handle;
#endif
/*
** This points to the filename as a NULL terminated string. It may point to either a
** constant or an allocated string as indicated by the "Allocated" flag.
*/
char const * Filename;
//
// file date and time are in the following formats:
//
// date bits 0-4 day (0-31)
// bits 5-8 month (1-12)
// bits 9-15 year (0-119 representing 1980-2099)
//
// time bits 0-4 second/2 (0-29)
// bits 5-10 minutes (0-59)
// bits 11-15 hours (0-23)
//
unsigned short Date;
unsigned short Time;
/*
** Filenames that were assigned as part of the construction process
** are not allocated. It is assumed that the filename string is a
** constant in that case and thus making duplication unnecessary.
** This value will be non-zero if the filename has be allocated
** (using strdup()).
*/
bool Allocated;
};
/***********************************************************************************************
* RawFileClass::File_Name -- Returns with the filename associate with the file object. *
* *
* Use this routine to determine what filename is associated with this file object. If no *
* filename has yet been assigned, then this routing will return NULL. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with a pointer to the file name associated with this file object or NULL *
* if one doesn't exist. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/18/1994 JLB : Created. *
*=============================================================================================*/
inline char const * RawFileClass::File_Name(void) const
{
return(Filename);
}
#endif

View file

@ -0,0 +1,176 @@
/*
** Command & Conquer Generals(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 : Westwood Library *
* *
* $Archive:: /Commando/Code/wwlib/realcrc.cpp $*
* *
* Author:: Byon Garrabrant *
* *
* $Modtime:: 7/09/99 1:44p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* CRC_Memory -- calculates a CRC for a block of memory *
* CRC_String -- Calculates a CRC for a NULL-terminated string *
* CRC_Stringi -- Calculates a CRC for a string, case-insensitive *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "realcrc.h"
#include <ctype.h>
// CRC for poly 0x04C11DB7
unsigned long CRC32_Table[ 256 ] =
{
0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
};
#define CRC32(c,crc) (CRC32_Table[((unsigned long)(crc) ^ (c)) & 0xFFL] ^ (((crc) >> 8) & 0x00FFFFFFL))
/***********************************************************************************************
* CRC_Memory -- calculates a CRC for a block of memory *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
unsigned long CRC_Memory( const unsigned char *data, unsigned long length, unsigned long crc )
{
crc ^= 0xFFFFFFFF; // invert previous CRC
while ( length-- ) {
crc = CRC32( *data++, crc ); // calc crc for each byte
}
return (crc ^ 0xFFFFFFFF); // invert new CRC and return it
}
/***********************************************************************************************
* CRC_String -- Calculates a CRC for a NULL-terminated string *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
unsigned long CRC_String( const char *string, unsigned long crc )
{
crc ^= 0xFFFFFFFF; // invert previous CRC
while ( *string ) {
crc = CRC32( *string++, crc ); // calc crc for each byte
}
return (crc ^ 0xFFFFFFFF); // invert new CRC and return it
}
/***********************************************************************************************
* CRC_Stringi -- Calculates a CRC for a string, case-insensitive *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
unsigned long CRC_Stringi( const char *string, unsigned long crc )
{
crc ^= 0xFFFFFFFF; // invert previous CRC
while ( *string ) {
char c = (char)toupper(*string++);
crc = CRC32( c, crc ); // calc crc for each byte
}
return (crc ^ 0xFFFFFFFF); // invert new CRC and return it
}

View file

@ -0,0 +1,49 @@
/*
** Command & Conquer Generals(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 : Westwood Library *
* *
* $Archive:: /G/wwlib/realcrc.h $*
* *
* Author:: Byon Garrabrant *
* *
* $Modtime:: 4/02/99 12:00p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef REALCRC_H
#define REALCRC_H
unsigned long CRC_Memory( const unsigned char *data, unsigned long length, unsigned long crc = 0 );
unsigned long CRC_String( const char *string, unsigned long crc = 0 );
unsigned long CRC_Stringi( const char *string, unsigned long crc = 0 );
#endif

View file

@ -0,0 +1,231 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Library/RGB.CPP $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* RGBClass::Adjust -- Adjust one RGB value toward another. *
* RGBClass::Difference -- Determines the "distance" between two colors. *
* RGBClass::operator HSVClass -- Conversion operator for RGB to HSV object. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "hsv.h"
#include "palette.h"
#include "rgb.h"
RGBClass const BlackColor(0, 0, 0);
/***********************************************************************************************
* RGBClass::Adjust -- Adjust one RGB value toward another. *
* *
* This routine is used to modify an RGB value to proportionately match another RGB value *
* according to the ratio parameter specified. Typical use of this routine is in palette *
* fading from one palette to another or to black. *
* *
* INPUT: ratio -- The ration of transformation. This value is in the form of 0 to 255, *
* with 0 being no change, and 255 being 100% transformed into the *
* destination color. *
* *
* rgb -- Reference to the destination RGB color to transform this color into. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 12/02/1995 JLB : Created. *
*=============================================================================================*/
void RGBClass::Adjust(int ratio, RGBClass const & rgb)
{
/*
** Ratio conversion is limited to 0 through 100%. This is
** the range of 0 to 255.
*/
ratio &= 0x00FF;
/*
** Adjust the color guns by the ratio specified toward the
** destination color.
*/
int value = (int)rgb.Red - (int)Red;
Red = (unsigned char)((int)Red + (value * ratio) / 256);
value = (int)rgb.Green - (int)Green;
Green = (unsigned char)((int)Green + (value * ratio) / 256);
value = (int)rgb.Blue - (int)Blue;
Blue = (unsigned char)((int)Blue + (value * ratio) / 256);
}
/***********************************************************************************************
* RGBClass::Difference -- Determines the "distance" between two colors. *
* *
* This routine is used to calculate a relative distance between two colors. The value is *
* relative only to itself and thus is useful only for determining the magnitude of *
* color difference rather than the nature of the color difference. Palette remapping *
* code uses this routine to find closest matches for colors. *
* *
* INPUT: rgb -- Reference to the color to be compared to this color. *
* *
* OUTPUT: Returns the difference between the two colors. The value returned is zero if the *
* colors exactly match. The greater the positive value the greater the difference *
* between the colors. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 12/02/1995 JLB : Created. *
*=============================================================================================*/
int RGBClass::Difference(RGBClass const & rgb) const
{
int r = (int)Red - (int)rgb.Red;
if (r < 0) r = -r;
int g = (int)Green - (int)rgb.Green;
if (g < 0) g = -g;
int b = (int)Blue - (int)rgb.Blue;
if (b < 0) b = -b;
/*
** At first crack, the difference algorithm might be coded as the sum of the color differences
** (or sum of the square of the color distances). However, this would not take advantage of the
** fact that the human eye is most sensative to green, followed by the color blue. With this
** thought in mind, the following difference algorithm is used.
*/
return(4*g + 3*b + 2*r);
}
/***********************************************************************************************
* RGBClass::operator HSVClass -- Conversion operator for RGB to HSV object. *
* *
* This conversion operator will convert an RGBClass object into an HSVClass object. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with a reference (implicit) to the HSVClass object that most closely *
* represents the RGBClass object. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/20/1996 JLB : Created. *
*=============================================================================================*/
RGBClass::operator HSVClass (void) const
{
int hue;
int saturation;
int value;
/*
** Fetch working component values for the color guns.
*/
int red = Get_Red();
int green = Get_Green();
int blue = Get_Blue();
/*
** The hue defaults to none. Only if there is a saturation value will the
** hue be calculated.
*/
hue = 0;
/*
** Set the value (brightness) to match the brightest color gun.
*/
value = (red > green) ? red : green;
if (blue > value) value = blue;
/*
** Determine the amount of true white present in the color. This is the
** minimum color gun value. The white component is used to determine
** color saturation.
*/
int white = (red < green) ? red : green;
if (blue < white) white = blue;
/*
** Determine the saturation (intensity) of the color by comparing the
** ratio of true white as a component of the overall color. The more
** white component, the less saturation.
*/
saturation = 0;
if (value) {
saturation = ((value - white) * 255) / value;
}
/*
** If there is any saturation at all, then the hue must be calculated. The
** hue is based on a six sided color wheel.
*/
if (saturation != 0) {
unsigned int tmp = value - white;
unsigned int r1 = ((value - red) * 255) / tmp;
unsigned int g1 = ((value - green) * 255) / tmp;
unsigned int b1 = ((value - blue) * 255) / tmp;
// Find effect of second most predominant color.
// In which section of the hexagon of colors does the color lie?
if (value == red) {
if (white == green) {
tmp = 5 * 256 + b1;
} else {
tmp = 1 * 256 - g1;
}
} else {
if (value == green) {
if (white == blue) {
tmp = 1 * 256 + r1;
} else {
tmp = 3 * 256 - b1;
}
} else {
if (white == red) {
tmp = 3 * 256 + g1;
} else {
tmp = 5 * 256 - r1;
}
}
}
// Divide by six and round.
hue = tmp / 6;
}
HSVClass hsv((unsigned char)hue, (unsigned char)saturation, (unsigned char)value);
return(hsv);
}

View file

@ -0,0 +1,95 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /G/wwlib/RGB.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 12:00p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef RGB_H
#define RGB_H
class PaletteClass;
class HSVClass;
/*
** Each color entry is represented by this class. It holds the values for the color
** guns. The gun values are recorded in device dependant format, but the interface
** uses gun values from 0 to 255.
*/
class RGBClass
{
public:
RGBClass(void) : Red(0), Green(0), Blue(0) {}
RGBClass(unsigned char red, unsigned char green, unsigned char blue) : Red(red), Green(green), Blue(blue) {}
operator HSVClass (void) const;
RGBClass & operator = (RGBClass const & rgb) {
if (this == &rgb) return(*this);
Red = rgb.Red;
Green = rgb.Green;
Blue = rgb.Blue;
return(*this);
}
enum {
MAX_VALUE=255
};
void Adjust(int ratio, RGBClass const & rgb);
int Difference(RGBClass const & rgb) const;
int Get_Red(void) const {return (Red);}
int Get_Green(void) const {return(Green);}
int Get_Blue(void) const {return(Blue);}
void Set_Red(unsigned char value) {Red = value;}
void Set_Green(unsigned char value) {Green = value;}
void Set_Blue(unsigned char value) {Blue = value;}
private:
friend class PaletteClass;
/*
** These hold the actual color gun values in machine independant scale. This
** means the values range from 0 to 255.
*/
unsigned char Red;
unsigned char Green;
unsigned char Blue;
};
extern RGBClass const BlackColor;
#endif

View file

@ -0,0 +1,228 @@
/*
** Command & Conquer Generals(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 : Library *
* *
* $Archive:: /G/wwlib/uarray.h $*
* *
* Author:: Greg Hjelstrom *
* *
* $Modtime:: 9/24/99 1:56p $*
* *
* $Revision:: 7 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* UniqueArrayClass<T>::UniqueArrayClass -- constructor *
* UniqueArrayClass<T>::~UniqueArrayClass -- destructor *
* UniqueArrayClass<T>::Add -- Add an item to the array *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef UARRAY_H
#define UARRAY_H
#ifndef HASHCALC_H
#include "hashcalc.h"
#endif
#ifndef VECTOR_H
#include "vector.h"
#endif
/*
** UniqueArrayClass
** This template class can be used to generate an array of unique objects
** amongst a huge list of objects which may or may not be unique. However,
** in order to use the UniqueArrayClass, you will need to implement a
** HashCalculatorClass for the type you are using.
**
** Note that the UniqueArrayClass does *copies* of the objects you are
** giving it. It is meant to be used with relatively lightweight objects.
*/
template <class T> class UniqueArrayClass
{
public:
UniqueArrayClass(int initialsize,int growthrate,HashCalculatorClass<T> * hasher);
~UniqueArrayClass(void);
int Add(const T & new_item);
int Count(void) const { return Get_Unique_Count(); }
int Get_Unique_Count(void) const { return UniqueItems.Count(); }
const T & Get(int index) const { return UniqueItems[index].Item; }
const T & operator [] (int index) const { return Get(index); }
private:
enum { NO_ITEM = 0xFFFFFFFF };
class HashItem
{
public:
T Item;
int NextHashIndex;
bool operator == (const HashItem & that) { return ((Item == that.Item) && (NextHashIndex == that.NextHashIndex)); }
bool operator != (const HashItem & that) { return !(*this == that); }
};
// Dynamic Vector of the unique items:
DynamicVectorClass<HashItem> UniqueItems;
// Hash table:
int HashTableSize;
int * HashTable;
// object which does the hashing for the type
HashCalculatorClass<T> * HashCalculator;
friend class VectorClass<T>;
friend class DynamicVectorClass<T>;
};
/***********************************************************************************************
* UniqueArrayClass<T>::UniqueArrayClass -- constructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/29/98 GTH : Created. *
*=============================================================================================*/
template <class T>
UniqueArrayClass<T>::UniqueArrayClass(int initial_size,int growth_rate,HashCalculatorClass<T> * hasher) :
UniqueItems(initial_size),
HashCalculator(hasher)
{
// set the growth rate.
UniqueItems.Set_Growth_Step(growth_rate);
// sizing and allocating the actual hash table
int bits = HashCalculator->Num_Hash_Bits();
assert(bits > 0);
assert(bits < 24);
HashTableSize = 1<<bits;
HashTable = new int[HashTableSize];
for (int hidx=0; hidx < HashTableSize; hidx++) {
HashTable[hidx] = NO_ITEM;
}
}
/***********************************************************************************************
* UniqueArrayClass<T>::~UniqueArrayClass -- destructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/29/98 GTH : Created. *
*=============================================================================================*/
template <class T>
UniqueArrayClass<T>::~UniqueArrayClass(void)
{
if (HashTable != NULL) {
delete[] HashTable;
HashTable = NULL;
}
}
/***********************************************************************************************
* UniqueArrayClass<T>::Add -- Add an item to the array *
* *
* Only adds the item to the end of the array if another duplicate item is not found. Returns *
* the array index of where the item is stored. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/29/98 GTH : Created. *
*=============================================================================================*/
template <class T>
inline int UniqueArrayClass<T>::Add(const T & new_item)
{
/*
** Use the hash table to quickly (hopefully :-) detect
** whether this item is already in the array
*/
int num_hash_vals;
HashCalculator->Compute_Hash(new_item);
num_hash_vals = HashCalculator->Num_Hash_Values();
unsigned int lasthash = 0xFFFFFFFF;
unsigned int hash;
for (int hidx = 0; hidx < num_hash_vals; hidx++) {
hash = HashCalculator->Get_Hash_Value(hidx);
if (hash != lasthash) {
int test_item_index = HashTable[hash];
while (test_item_index != 0xFFFFFFFF) {
if (HashCalculator->Items_Match(UniqueItems[test_item_index].Item,new_item)) {
return test_item_index;
}
test_item_index = UniqueItems[test_item_index].NextHashIndex;
}
}
lasthash = hash;
}
/*
** Ok, this is a new item so add it (copy it!) into the array
*/
int index = UniqueItems.Count();
int hash_index = HashCalculator->Get_Hash_Value(0);
HashItem entry;
entry.Item = new_item;
entry.NextHashIndex = HashTable[hash_index];
HashTable[hash_index] = index;
UniqueItems.Add(entry);
return index;
}
#endif // UARRAY_H

View file

@ -0,0 +1,640 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/wwmath/vector2.h 19 9/01/00 5:30p Ian_l $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Westwood 3D *
* *
* File Name : VECTOR2.H *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 02/24/97 *
* *
* Last Update : February 24, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Scalar Division Operator -- Divide a vector by a scalar *
* Scalar Multiply Operator -- Multiply a vector by a scalar *
* Vector Addition Operator -- Add two vectors *
* Vector Subtraction Operator -- Subract two vectors *
* Vector Inner Product Operator -- Compute the inner or dot product *
* Vector Equality Operator -- Detemine if two vectors are identical *
* Equal_Within_Epsilon -- Determine if two vectors are identical within *
* Vector Inequality Operator -- Detemine if two vectors are identical *
* Swap -- swap two Vector2's *
* Vector2::Is_Valid -- Verifies that all components are valid floats *
* Vector2::Update_Min -- sets each component of the vector to the min of this and a. *
* Vector2::Update_Max -- sets each component of the vector to the max of this and a. *
* Vector2::Scale -- multiply components of a vector by independant scaling factors. *
* Vector2::Lerp -- linearly interpolates two Vector2's *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef VECTOR2_H
#define VECTOR2_H
#include "always.h"
#include "wwmath.h"
#include <math.h>
/*
** 2-Dimensional Vectors
*/
class Vector2
{
public:
union {
float X;
float U;
};
union {
float Y;
float V;
};
// Constructors
Vector2(void) {};
Vector2(const Vector2 & v) { X = v.X; Y = v.Y; }
Vector2(float x, float y) { X = x; Y = y; }
Vector2(const float vector[2]) { X = vector[0]; Y = vector[1]; }
// Assignment
Vector2 & operator = (const Vector2 & v) { X = v[0]; Y = v[1]; return *this; }
void Set(float x, float y) { X = x; Y = y; }
void Set(const Vector2 & v) { X = v.X; Y = v.Y; }
// Array access
float & operator [](int i) { return (&X)[i]; }
const float & operator [](int i) const { return (&X)[i]; }
// normalize, compute length
void Normalize(void);
float Length(void) const;
float Length2(void) const;
// unary operators
Vector2 operator-() const { return Vector2(-X,-Y); }
Vector2 operator+() const { return *this; }
Vector2 & operator += (const Vector2 & v) { X += v.X; Y += v.Y; return *this; }
Vector2 & operator -= (const Vector2 & v) { X -= v.X; Y -= v.Y; return *this; }
Vector2 & operator *= (float k) { X = (float)(X*k); Y=(float)(Y*k); return *this; }
Vector2 & operator /= (float k) { k=1.0f/k; X*=k; Y*=k; return *this; }
// scalar multiplication, division
friend Vector2 operator * (const Vector2 &a,float k);
friend Vector2 operator * (float k,const Vector2 &a);
friend Vector2 operator / (const Vector2 &a,float k);
// vector addition,subtraction
friend Vector2 operator + (const Vector2 &a,const Vector2 &b);
friend Vector2 operator - (const Vector2 &a,const Vector2 &b);
// dot product / inner product
friend float operator * (const Vector2 &a,const Vector2 &b);
static float Dot_Product(const Vector2 &a,const Vector2 &b);
// dot product between a and perpendicular vector to b
static float Perp_Dot_Product(const Vector2 &a,const Vector2 &b);
// Equality operators
friend bool operator == (const Vector2 &a,const Vector2 &b);
friend bool operator != (const Vector2 &a,const Vector2 &b);
friend bool Equal_Within_Epsilon(const Vector2 &a,const Vector2 &b,float epsilon);
// Rotation
void Rotate(float theta);
void Rotate(float s, float c);
bool Rotate_Towards_Vector(Vector2 &target, float max_theta, bool & positive_turn);
bool Rotate_Towards_Vector(Vector2 &target, float max_s, float max_c, bool & positive_turn);
// verify that none of the members of this vector are invalid floats
bool Is_Valid(void) const;
// make this vector the min or max of itself and the passed vector
void Update_Min (const Vector2 & a);
void Update_Max (const Vector2 & a);
void Scale (float a, float b);
static float Distance(const Vector2 &p1, const Vector2 &p2);
static float Quick_Distance(const Vector2 &p1, const Vector2 &p2);
// interpolate between two Vector2's
static void Lerp(const Vector2 & a,const Vector2 & b,float t,Vector2 * set_result);
};
/**************************************************************************
* Scalar Multiply Operator -- Multiply a vector by a scalar *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*========================================================================*/
inline Vector2 operator * (const Vector2 &a,float k)
{
return Vector2((a[0] * k),(a[1] * k));
}
inline Vector2 operator * (float k, const Vector2 &a)
{
return Vector2((a[0] * k),(a[1] * k));
}
/**************************************************************************
* Scalar Division Operator -- Divide a vector by a scalar *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline Vector2 operator / (const Vector2 &a,float k)
{
float ook=1.0f/k;
return Vector2((a[0] * ook),(a[1] * ook));
}
/**************************************************************************
* Vector Addition Operator -- Add two vectors *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*========================================================================*/
inline Vector2 operator + (const Vector2 &a,const Vector2 &b)
{
return Vector2(
a.X + b.X,
a.Y + b.Y
);
}
/**************************************************************************
* Vector Subtraction Operator -- Subract two vectors *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*========================================================================*/
inline Vector2 operator - (const Vector2 &a,const Vector2 &b)
{
return Vector2(
a.X - b.X,
a.Y - b.Y
);
}
/**************************************************************************
* Vector Inner Product -- Compute the inner or dot product of two vector *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline float operator * (const Vector2 &a,const Vector2 &b)
{
return a.X*b.X + a.Y*b.Y;
}
inline float Vector2::Dot_Product(const Vector2 &a,const Vector2 &b)
{
return a*b;
}
inline float Vector2::Perp_Dot_Product(const Vector2 &a,const Vector2 &b)
{
return a.X * -b.Y + a.Y * b.X;
}
/**************************************************************************
* Vector Equality Operator -- Detemine if two vectors are identical *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline bool operator == (const Vector2 &a,const Vector2 &b)
{
return ( (a[0] == b[0]) && (a[1] == b[1]));
}
/**************************************************************************
* Vector Inequality Operator -- Detemine if two vectors are identical *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline bool operator != (const Vector2 &a,const Vector2 &b)
{
return ( (a[0] != b[0]) || (a[1] != b[1]));
}
/**************************************************************************
* Equal_Within_Epsilon -- Determine if two vectors are identical within e*
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline bool Equal_Within_Epsilon(const Vector2 &a,const Vector2 &b,float epsilon)
{
return( (WWMath::Fabs(a.X - b.X) < epsilon) && (WWMath::Fabs(a.Y - b.Y) < epsilon) );
}
/**************************************************************************
* Vector2::Normalize -- Normalizes the vector. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline void Vector2::Normalize()
{
float len2 = Length2();
if (len2 != 0.0f) {
float oolen = WWMath::Inv_Sqrt(len2);
X *= oolen;
Y *= oolen;
}
}
inline Vector2 Normalize(const Vector2 & vec)
{
float len2 = vec.Length2();
if (len2 != 0.0f) {
float oolen = WWMath::Inv_Sqrt(len2);
return vec / oolen;
}
}
/**************************************************************************
* Vector2::Length -- Returns the length of the vector *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline float Vector2::Length() const
{
return (float)WWMath::Sqrt(Length2());
}
/**************************************************************************
* Vector2::Length -- Returns the square of the length of the vector *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline float Vector2::Length2() const
{
return (X*X + Y*Y);
}
/**************************************************************************
* Vector2::Rotate -- Rotate vector *
* *
* INPUT: *
* float theta - angle to rotate *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline void Vector2::Rotate(float theta)
{
Rotate(sin(theta), cos(theta));
}
/**************************************************************************
* Vector2::Rotate -- Rotate vector *
* *
* INPUT: *
* s - sine of the angle *
* c - cosine of the angle *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline void Vector2::Rotate(float s, float c)
{
float new_x = X * c + Y * -s;
float new_y = X * s + Y * c;
X = new_x;
Y = new_y;
}
/**************************************************************************
* Vector2::Rotate -- Rotate towards given vector (stop on reaching it) *
* *
* INPUT: *
* float theta - angle to rotate *
* *
* OUTPUT: *
* bool - true if we have reached the desired vector *
* *
* WARNINGS: *
* This function assumes both vectors are normalized! *
* *
* HISTORY: *
*========================================================================*/
inline bool Vector2::Rotate_Towards_Vector(Vector2 &target, float max_theta, bool & positive_turn)
{
return Rotate_Towards_Vector(target, sin(max_theta), cos(max_theta), positive_turn);
}
/**************************************************************************
* Vector2::Rotate -- Rotate towards given vector (stop on reaching it) *
* *
* INPUT: *
* s - sine of the angle *
* c - cosine of the angle *
* *
* OUTPUT: *
* bool - true if we have reached the desired vector *
* *
* WARNINGS: *
* This function assumes both vectors are normalized! *
* *
* HISTORY: *
*========================================================================*/
inline bool Vector2::Rotate_Towards_Vector(Vector2 &target, float max_s, float max_c, bool & positive_turn)
{
bool return_value = false;
positive_turn = Vector2::Perp_Dot_Product(target, *this) > 0.0f;
if (Vector2::Dot_Product(*this, target) >= max_c) {
Set(target);
return_value = true;
} else {
// Determine turn direction and rotate accordingly.
if (positive_turn) {
Rotate(max_s, max_c);
} else {
Rotate(-max_s, max_c);
}
}
return return_value;
}
/***********************************************************************************************
* Swap -- swap two Vector2's *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/11/1997 GH : Created. *
*=============================================================================================*/
inline void Swap(Vector2 & a,Vector2 & b)
{
Vector2 tmp(a);
a = b;
b = tmp;
}
/***********************************************************************************************
* Vector2::Is_Valid -- Verifies that all components are valid floats *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
inline bool Vector2::Is_Valid(void) const
{
return (WWMath::Is_Valid_Float(X) && WWMath::Is_Valid_Float(Y));
}
/***********************************************************************************************
* Vector2::Update_Min -- Set each component of the vector to the min of this and a. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/12/00 IML : Created. *
*=============================================================================================*/
inline void Vector2::Update_Min (const Vector2 & a)
{
if (a.X < X) X = a.X;
if (a.Y < Y) Y = a.Y;
}
/***********************************************************************************************
* Vector2::Update_Max -- Set each component of the vector to the max of this and a. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/12/00 IML : Created. *
*=============================================================================================*/
inline void Vector2::Update_Max (const Vector2 & a)
{
if (a.X > X) X = a.X;
if (a.Y > Y) Y = a.Y;
}
/***********************************************************************************************
* Vector2::Scale -- multiply components of a vector by independant scaling factors. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/19/2000 IML : Created. *
*=============================================================================================*/
inline void Vector2::Scale (float a, float b)
{
X *= a;
Y *= b;
}
/***********************************************************************************************
* Quick_Distance -- Fast but inaccurate 2D distance calculation. *
* *
* *
* *
* *
* HISTORY: *
* 11/29/1999MLL: Created. *
*=============================================================================================*/
inline float Quick_Distance(float x1, float y1, float x2, float y2)
{
// From Graphic Gems I.
float x_diff = x1 - x2;
float y_diff = y1 - y2;
WWMath::Fabs(x_diff);
WWMath::Fabs(y_diff);
if (x_diff > y_diff)
{
return ((y_diff / 2) + x_diff);
}
else
{
return ((x_diff / 2) + y_diff);
}
}
inline float Vector2::Quick_Distance(const Vector2 &a, const Vector2 &b)
{
return ::Quick_Distance(a.X, a.Y, b.X, b.Y);
}
/***********************************************************************************************
* Distance -- Accurate distance 2D calculation. *
* *
* *
* *
* *
* HISTORY: *
* 11/29/1999MLL: Created. *
*=============================================================================================*/
inline float Vector2::Distance(const Vector2 &a, const Vector2 &b)
{
Vector2 temp;
temp = a - b;
return (temp.Length());
}
inline float Distance(float x1, float y1, float x2, float y2)
{
float x_diff = x1 - x2;
float y_diff = y1 - y2;
return (WWMath::Sqrt((x_diff * x_diff) + (y_diff * y_diff)));
}
/***********************************************************************************************
* Vector2::Lerp -- linearly interpolates two Vector2's *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 4/14/2000 gth : Created. *
*=============================================================================================*/
inline void Vector2::Lerp(const Vector2 & a,const Vector2 & b,float t,Vector2 * set_result)
{
assert(set_result != NULL);
set_result->X = (a.X + (b.X - a.X)*t);
set_result->Y = (a.Y + (b.Y - a.Y)*t);
}
#endif /* VECTOR2_H */

View file

@ -0,0 +1,930 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/wwmath/vector3.h 40 5/11/01 7:11p Jani_p $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Westwood 3D *
* *
* File Name : VECTOR3.H *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 02/24/97 *
* *
* Last Update : February 24, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Scalar Division Operator -- Divide a vector by a scalar *
* Scalar Multiply Operator -- Multiply a vector by a scalar *
* Vector Addition Operator -- Add two vectors *
* Vector Subtraction Operator -- Subract two vectors *
* Vector Inner Product Operator -- Compute the inner or dot product *
* Vector Equality Operator -- Determine if two vectors are identical *
* Vector Inequality Operator -- Determine if two vectors are identical *
* Equal_Within_Epsilon -- Determine if two vectors are identical within *
* Cross_Product -- compute the cross product of two vectors *
* Vector3::Normalize -- Normalizes the vector. *
* Vector3::Length -- Returns the length of the vector *
* Vector3::Length2 -- Returns the square of the length of the vector *
* Vector3::Quick_Length -- returns a quick approximation of the length *
* Swap -- swap two Vector3's *
* Lerp -- linearly interpolate two Vector3's by an interpolation factor. *
* Lerp -- linearly interpolate two Vector3's without return-by-value *
* Vector3::Add -- Add two vector3's without return-by-value *
* Vector3::Subtract -- Subtract two vector3's without return-by-value *
* Vector3::Update_Min -- sets each component of the vector to the min of this and a *
* Vector3::Update_Max -- Sets each component of the vector to the max of this and a *
* Vector3::Scale -- scale this vector by 3 independent scale factors *
* Vector3::Rotate_X -- rotates this vector around the X axis *
* Vector3::Rotate_X -- Rotates this vector around the x axis *
* Vector3::Rotate_Y -- Rotates this vector around the y axis *
* Vector3::Rotate_Y -- Rotates this vector around the Y axis *
* Vector3::Rotate_Z -- Rotates this vector around the Z axis *
* Vector3::Rotate_Z -- Rotates this vector around the Z axis *
* Vector3::Is_Valid -- Verifies that each component of this vector is a valid float *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef VECTOR3_H
#define VECTOR3_H
#include "always.h"
#include "wwmath.h"
#include <assert.h>
#ifdef _UNIX
#include "osdep.h"
#endif
/*
** Vector3 - 3-Dimensional Vectors
*/
class Vector3
{
public:
float X;
float Y;
float Z;
// Constructors
WWINLINE Vector3(void) {};
WWINLINE Vector3(const Vector3 & v) { X = v.X; Y = v.Y; Z = v.Z; }
WWINLINE Vector3(float x, float y, float z) { X = x; Y = y; Z = z; }
WWINLINE Vector3(const float vector[3]) { X = vector[0]; Y = vector[1]; Z = vector[2]; }
// Assignment
WWINLINE Vector3 & operator = (const Vector3 & v) { X = v.X; Y = v.Y; Z = v.Z; return *this; }
WWINLINE void Set(float x, float y, float z) { X = x; Y = y; Z = z; }
WWINLINE void Set(const Vector3 & that) { X = that.X; Y = that.Y; Z = that.Z; }
// Array access
WWINLINE float & operator [](int i) { return (&X)[i]; }
WWINLINE const float & operator [](int i) const { return (&X)[i]; }
// normalize, compute length
void Normalize(void);
WWINLINE float Length(void) const;
WWINLINE float Length2(void) const;
float Quick_Length(void) const;
void Scale(const Vector3 & scale);
// rotation, (warning, modifies this vector!)
WWINLINE void Rotate_X(float angle);
WWINLINE void Rotate_X(float s_angle,float c_angle);
WWINLINE void Rotate_Y(float angle);
WWINLINE void Rotate_Y(float s_angle,float c_angle);
WWINLINE void Rotate_Z(float angle);
WWINLINE void Rotate_Z(float s_angle,float c_angle);
// unary operators
WWINLINE Vector3 operator-() const { return(Vector3(-X,-Y,-Z)); }
WWINLINE Vector3 operator+() const { return *this; }
WWINLINE Vector3 & operator += (const Vector3 & v) { X += v.X; Y += v.Y; Z += v.Z; return *this; }
WWINLINE Vector3 & operator -= (const Vector3 & v) { X -= v.X; Y -= v.Y; Z -= v.Z; return *this; }
WWINLINE Vector3 & operator *= (float k) { X = X*k; Y=Y*k; Z=Z*k; return *this; }
WWINLINE Vector3 & operator /= (float k) { float ook=1.0f/k; X=X*ook; Y=Y*ook; Z=Z*ook; return *this; }
// scalar multiplication, division
WWINLINE friend Vector3 operator * (const Vector3 &a,float k);
WWINLINE friend Vector3 operator * (float k,const Vector3 &a);
WWINLINE friend Vector3 operator / (const Vector3 &a,float k);
// vector addition,subtraction
WWINLINE friend Vector3 operator + (const Vector3 &a,const Vector3 &b);
WWINLINE friend Vector3 operator - (const Vector3 &a,const Vector3 &b);
// Equality operators
friend bool operator == (const Vector3 &a,const Vector3 &b);
friend bool operator != (const Vector3 &a,const Vector3 &b);
WWINLINE friend bool Equal_Within_Epsilon(const Vector3 &a,const Vector3 &b,float epsilon);
// dot product / inner product
WWINLINE friend float operator * (const Vector3 &a,const Vector3 &b);
static WWINLINE float Dot_Product(const Vector3 &a,const Vector3 &b);
// cross product / outer product
static WWINLINE Vector3 Cross_Product(const Vector3 &a,const Vector3 &b);
static WWINLINE void Cross_Product(const Vector3 &a,const Vector3 &b,Vector3 * result);
static WWINLINE float Cross_Product_X(const Vector3 &a,const Vector3 &b);
static WWINLINE float Cross_Product_Y(const Vector3 &a,const Vector3 &b);
static WWINLINE float Cross_Product_Z(const Vector3 &a,const Vector3 &b);
// add and subtract without return by value
static WWINLINE void Add(const Vector3 & a,const Vector3 & b,Vector3 * c);
static WWINLINE void Subtract(const Vector3 & a,const Vector3 & b,Vector3 * c);
// Line intersection functions.
static WWINLINE float Find_X_At_Y(float y, const Vector3 &p1, const Vector3 &p2);
static WWINLINE float Find_X_At_Z(float z, const Vector3 &p1, const Vector3 &p2);
static WWINLINE float Find_Y_At_X(float x, const Vector3 &p1, const Vector3 &p2);
static WWINLINE float Find_Y_At_Z(float z, const Vector3 &p1, const Vector3 &p2);
static WWINLINE float Find_Z_At_X(float x, const Vector3 &p1, const Vector3 &p2);
static WWINLINE float Find_Z_At_Y(float z, const Vector3 &p1, const Vector3 &p2);
// make this vector the min or max of itself and the passed vector
WWINLINE void Update_Min(const Vector3 & a);
WWINLINE void Update_Max(const Vector3 & a);
WWINLINE void Cap_Absolute_To(const Vector3 & a);
// verify that none of the members of this vector are invalid floats
WWINLINE bool Is_Valid(void) const;
static WWINLINE float Quick_Distance(const Vector3 &p1, const Vector3 &p2);
static WWINLINE float Distance(const Vector3 &p1, const Vector3 &p2);
// Linearly interpolate two Vector3's
static void Lerp(const Vector3 & a, const Vector3 & b, float alpha,Vector3 * set_result);
// Color Conversion
WWINLINE unsigned long Convert_To_ABGR( void ) const;
WWINLINE unsigned long Convert_To_ARGB( void ) const;
};
/**************************************************************************
* Scalar Multiply Operator -- Multiply a vector by a scalar *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*========================================================================*/
WWINLINE Vector3 operator * (const Vector3 &a,float k)
{
return Vector3((a.X * k),(a.Y * k),(a.Z * k));
}
WWINLINE Vector3 operator * (float k, const Vector3 &a)
{
return Vector3((a.X * k),(a.Y * k),(a.Z * k));
}
/**************************************************************************
* Scalar Division Operator -- Divide a vector by a scalar *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
WWINLINE Vector3 operator / (const Vector3 &a,float k)
{
float ook = 1.0f/k;
return Vector3((a.X * ook),(a.Y * ook),(a.Z * ook));
}
/**************************************************************************
* Vector Addition Operator -- Add two vectors *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*========================================================================*/
WWINLINE Vector3 operator + (const Vector3 &a,const Vector3 &b)
{
return Vector3(
a.X+b.X,
a.Y+b.Y,
a.Z+b.Z
);
}
/**************************************************************************
* Vector Subtraction Operator -- Subract two vectors *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*========================================================================*/
WWINLINE Vector3 operator - (const Vector3 &a,const Vector3 &b)
{
return Vector3(
a.X-b.X,
a.Y-b.Y,
a.Z-b.Z
);
}
/**************************************************************************
* Vector Inner Product -- Compute the inner or dot product of two vector *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
WWINLINE float operator * (const Vector3 &a,const Vector3 &b)
{
return a.X*b.X +
a.Y*b.Y +
a.Z*b.Z;
}
WWINLINE float Vector3::Dot_Product(const Vector3 &a,const Vector3 &b)
{
return a*b;
}
/**************************************************************************
* Vector Equality Operator -- Determine if two vectors are identical *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
WWINLINE bool operator == (const Vector3 &a,const Vector3 &b)
{
return ( (a.X == b.X) && (a.Y == b.Y) && (a.Z == b.Z));
}
/**************************************************************************
* Vector Inequality Operator -- Determine if two vectors are identical *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
WWINLINE bool operator != (const Vector3 &a,const Vector3 &b)
{
return ( (a.X != b.X) || (a.Y != b.Y) || (a.Z != b.Z));
}
/**************************************************************************
* Equal_Within_Epsilon -- Determine if two vectors are identical within e*
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
WWINLINE bool Equal_Within_Epsilon(const Vector3 &a,const Vector3 &b,float epsilon)
{
return( (WWMath::Fabs(a.X - b.X) < epsilon) &&
(WWMath::Fabs(a.Y - b.Y) < epsilon) &&
(WWMath::Fabs(a.Z - b.Z) < epsilon) );
}
/**************************************************************************
* Cross_Product -- compute the cross product of two vectors *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
WWINLINE Vector3 Vector3::Cross_Product(const Vector3 &a,const Vector3 &b)
{
return Vector3(
(a.Y * b.Z - a.Z * b.Y),
(a.Z * b.X - a.X * b.Z),
(a.X * b.Y - a.Y * b.X)
);
}
WWINLINE void Vector3::Cross_Product(const Vector3 &a,const Vector3 &b,Vector3 * set_result)
{
assert(set_result != &a);
set_result->X = (a.Y * b.Z - a.Z * b.Y);
set_result->Y = (a.Z * b.X - a.X * b.Z);
set_result->Z = (a.X * b.Y - a.Y * b.X);
}
WWINLINE float Vector3::Cross_Product_X(const Vector3 &a,const Vector3 &b)
{
return a.Y * b.Z - a.Z * b.Y;
}
WWINLINE float Vector3::Cross_Product_Y(const Vector3 &a,const Vector3 &b)
{
return a.Z * b.X - a.X * b.Z;
}
WWINLINE float Vector3::Cross_Product_Z(const Vector3 &a,const Vector3 &b)
{
return a.X * b.Y - a.Y * b.X;
}
/**************************************************************************
* Vector3::Normalize -- Normalizes the vector. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
WWINLINE void Vector3::Normalize()
{
float len2 = Length2();
if (len2 != 0.0f)
{
float oolen = WWMath::Inv_Sqrt(len2);
X *= oolen;
Y *= oolen;
Z *= oolen;
}
}
#ifdef ALLOW_TEMPORARIES
WWINLINE Vector3 Normalize(const Vector3 & vec)
{
float len2 = vec.Length2();
if (len2 != 0.0f)
{
float oolen = WWMath::Inv_Sqrt(len2);
return vec * oolen;
}
return vec;
}
#endif
/**************************************************************************
* Vector3::Length -- Returns the length of the vector *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
WWINLINE float Vector3::Length() const
{
return WWMath::Sqrt(Length2());
}
/**************************************************************************
* Vector3::Length2 -- Returns the square of the length of the vector *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
WWINLINE float Vector3::Length2() const
{
return X*X + Y*Y + Z*Z;
}
/***********************************************************************************************
* Vector3::Quick_Length -- returns a quick approximation of the length *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/15/98 GTH : Created. *
*=============================================================================================*/
WWINLINE float Vector3::Quick_Length(void) const
{
// this method of approximating the length comes from Graphics Gems 1 and
// supposedly gives an error of +/- 8%
float max = WWMath::Fabs(X);
float mid = WWMath::Fabs(Y);
float min = WWMath::Fabs(Z);
float tmp;
if (max < mid) { tmp = max; max = mid; mid = tmp; }
if (max < min) { tmp = max; max = min; min = tmp; }
if (mid < min) { tmp = mid; mid = min; min = mid; }
return max + (11.0f / 32.0f)*mid + (1.0f / 4.0f)*min;
}
/***********************************************************************************************
* Swap -- swap two Vector3's *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/11/1997 GH : Created. *
*=============================================================================================*/
WWINLINE void Swap(Vector3 & a,Vector3 & b)
{
Vector3 tmp(a);
a = b;
b = tmp;
}
/***********************************************************************************************
* Lerp -- linearly interpolate two Vector3's by an interpolation factor. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: No checking is done to ensure that alpha is between 0 and 1. *
* *
* HISTORY: *
* 08/11/1997 GH : Created. *
*=============================================================================================*/
WWINLINE Vector3 Lerp(const Vector3 & a, const Vector3 & b, float alpha)
{
return Vector3(
(a.X + (b.X - a.X)*alpha),
(a.Y + (b.Y - a.Y)*alpha),
(a.Z + (b.Z - a.Z)*alpha)
);
}
/***********************************************************************************************
* Lerp -- linearly interpolate two Vector3's without return-by-value *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Lerp(const Vector3 & a, const Vector3 & b, float alpha,Vector3 * set_result)
{
assert(set_result != NULL);
set_result->X = (a.X + (b.X - a.X)*alpha);
set_result->Y = (a.Y + (b.Y - a.Y)*alpha);
set_result->Z = (a.Z + (b.Z - a.Z)*alpha);
}
WWINLINE void Vector3::Lerp(const Vector3 & a, const Vector3 & b, float alpha,Vector3 * set_result)
{
assert(set_result != NULL);
set_result->X = (a.X + (b.X - a.X)*alpha);
set_result->Y = (a.Y + (b.Y - a.Y)*alpha);
set_result->Z = (a.Z + (b.Z - a.Z)*alpha);
}
/***********************************************************************************************
* Vector3::Add -- Add two vector3's without return-by-value *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Add(const Vector3 &a,const Vector3 &b,Vector3 * set_result)
{
assert(set_result != NULL);
set_result->X = a.X + b.X;
set_result->Y = a.Y + b.Y;
set_result->Z = a.Z + b.Z;
}
/***********************************************************************************************
* Vector3::Subtract -- Subtract two vector3's without return-by-value *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Subtract(const Vector3 &a,const Vector3 &b,Vector3 * set_result)
{
assert(set_result != NULL);
set_result->X = a.X - b.X;
set_result->Y = a.Y - b.Y;
set_result->Z = a.Z - b.Z;
}
/***********************************************************************************************
* Vector3::Update_Min -- sets each component of the vector to the min of this and a *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Update_Min(const Vector3 & a)
{
if (a.X < X) X = a.X;
if (a.Y < Y) Y = a.Y;
if (a.Z < Z) Z = a.Z;
}
/***********************************************************************************************
* Vector3::Update_Max -- Sets each component of the vector to the max of this and a *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Update_Max(const Vector3 & a)
{
if (a.X > X) X = a.X;
if (a.Y > Y) Y = a.Y;
if (a.Z > Z) Z = a.Z;
}
/***********************************************************************************************
* Vector3::Cap_To_Absolute_Of -- Sets each component of the vector to no larger than the -ve or +ve of*
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/29/99 wst : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Cap_Absolute_To(const Vector3 & a)
{
if (X > 0)
{
if (a.X < X) X = a.X;
}
else
{
if (-a.X > X) X = -a.X;
}
if (Y > 0)
{
if (a.Y < Y) Y = a.Y;
}
else
{
if (-a.Y > Y) Y = -a.Y;
}
if (Z > 0)
{
if (a.Z < Z) Z = a.Z;
}
else
{
if (-a.Z > Z) Z = -a.Z;
}
}
/***********************************************************************************************
* Vector3::Scale -- scale this vector by 3 independent scale factors *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Scale(const Vector3 & scale)
{
X *= scale.X;
Y *= scale.Y;
Z *= scale.Z;
}
/***********************************************************************************************
* Vector3::Rotate_X -- rotates this vector around the X axis *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Rotate_X(float angle)
{
Rotate_X(sinf(angle),cosf(angle));
}
/***********************************************************************************************
* Vector3::Rotate_X -- Rotates this vector around the x axis *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Rotate_X(float s_angle,float c_angle)
{
float tmp_y = Y;
float tmp_z = Z;
Y = c_angle * tmp_y - s_angle * tmp_z;
Z = s_angle * tmp_y + c_angle * tmp_z;
}
/***********************************************************************************************
* Vector3::Rotate_Y -- Rotates this vector around the y axis *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Rotate_Y(float angle)
{
Rotate_Y(sinf(angle),cosf(angle));
}
/***********************************************************************************************
* Vector3::Rotate_Y -- Rotates this vector around the Y axis *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Rotate_Y(float s_angle,float c_angle)
{
float tmp_x = X;
float tmp_z = Z;
X = c_angle * tmp_x + s_angle * tmp_z;
Z = -s_angle * tmp_x + c_angle * tmp_z;
}
/***********************************************************************************************
* Vector3::Rotate_Z -- Rotates this vector around the Z axis *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Rotate_Z(float angle)
{
Rotate_Z(sinf(angle),cosf(angle));
}
/***********************************************************************************************
* Vector3::Rotate_Z -- Rotates this vector around the Z axis *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE void Vector3::Rotate_Z(float s_angle,float c_angle)
{
float tmp_x = X;
float tmp_y = Y;
X = c_angle * tmp_x - s_angle * tmp_y;
Y = s_angle * tmp_x + c_angle * tmp_y;
}
/***********************************************************************************************
* Vector3::Is_Valid -- Verifies that each component of this vector is a valid float *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
WWINLINE bool Vector3::Is_Valid(void) const
{
return (WWMath::Is_Valid_Float(X) && WWMath::Is_Valid_Float(Y) && WWMath::Is_Valid_Float(Z));
}
WWINLINE float Vector3::Find_X_At_Y(float y, const Vector3 &p1, const Vector3 &p2)
{
return(p1.X + ((y - p1.Y) * ((p2.X - p1.X) / (p2.Y - p1.Y))));
}
WWINLINE float Vector3::Find_X_At_Z(float z, const Vector3 &p1, const Vector3 &p2)
{
return(p1.X + ((z - p1.Z) * ((p2.X - p1.X) / (p2.Z - p1.Z))));
}
WWINLINE float Vector3::Find_Y_At_X(float x, const Vector3 &p1, const Vector3 &p2)
{
return(p1.Y + ((x - p1.X) * ((p2.Y - p1.Y) / (p2.X - p1.X))));
}
WWINLINE float Vector3::Find_Y_At_Z(float z, const Vector3 &p1, const Vector3 &p2)
{
return(p1.Y + ((z - p1.Z) * ((p2.Y - p1.Y) / (p2.Z - p1.Z))));
}
WWINLINE float Vector3::Find_Z_At_X(float x, const Vector3 &p1, const Vector3 &p2)
{
return(p1.Z + ((x - p1.X) * ((p2.Z - p1.Z) / (p2.X - p1.X))));
}
WWINLINE float Vector3::Find_Z_At_Y(float y, const Vector3 &p1, const Vector3 &p2)
{
return(p1.Z + ((y - p1.Y) * ((p2.Z - p1.Z) / (p2.Y - p1.Y))));
}
/***********************************************************************************************
* Vector3::Distance -- Accurate distance calculation. *
* *
* *
* *
* *
* HISTORY: *
* 11/29/1999MLL: Created. *
*=============================================================================================*/
WWINLINE float Vector3::Distance(const Vector3 &p1, const Vector3 &p2)
{
Vector3 temp;
temp = p1 - p2;
return (temp.Length());
}
/***********************************************************************************************
* Vector3::Quick_Distance -- Fast but inaccurate distance calculation. *
* *
* *
* *
* *
* HISTORY: *
* 11/29/1999MLL: Created. *
*=============================================================================================*/
WWINLINE float Vector3::Quick_Distance(const Vector3 &p1, const Vector3 &p2)
{
Vector3 temp;
temp = p1 - p2;
return (temp.Quick_Length());
}
/***********************************************************************************************
* Vector3::Convert_To_ABGR -- Converts to SR packed color . *
* *
* *
* *
* *
* HISTORY: *
* 11/29/1999MLL: Created. *
*=============================================================================================*/
WWINLINE unsigned long Vector3::Convert_To_ABGR( void ) const
{
return (unsigned(255)<<24) |
(unsigned(Z*255.0f)<<16) |
(unsigned(Y*255.0f)<<8) |
(unsigned(X*255.0f));
}
/***********************************************************************************************
* Vector3::Convert_To_ARGB -- Converts to packed color . *
* *
* *
* *
* *
* HISTORY: *
* 11/29/1999MLL: Created. *
*=============================================================================================*/
WWINLINE unsigned long Vector3::Convert_To_ARGB( void ) const
{
return (unsigned(255)<<24) |
(unsigned(X*255.0f)<<16) |
(unsigned(Y*255.0f)<<8) |
(unsigned(Z*255.0f));
}
#endif /* Vector3_H */

View file

@ -0,0 +1,94 @@
/*
** Command & Conquer Generals(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/vector3i.h $*
* *
* Author:: Greg Hjelstrom *
* *
* $Modtime:: 5/10/01 11:37p $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef VECTOR3I_H
#define VECTOR3I_H
#include "always.h"
class Vector3i
{
public:
int I;
int J;
int K;
WWINLINE Vector3i(void);
WWINLINE Vector3i(int i,int j,int k);
WWINLINE bool operator== (const Vector3i & v) const;
WWINLINE bool operator!= (const Vector3i& v) const;
WWINLINE const int& operator[] (int n) const;
WWINLINE int& operator[] (int n);
};
WWINLINE Vector3i::Vector3i(void)
{
}
WWINLINE Vector3i::Vector3i(int i,int j,int k)
{
I = i; J = j; K = k;
}
WWINLINE bool Vector3i::operator == (const Vector3i & v) const
{
return (I == v.I && J == v.J && K == v.K);
}
WWINLINE bool Vector3i::operator != (const Vector3i& v) const
{
return !(I == v.I && J == v.J && K == v.K);
}
WWINLINE const int& Vector3i::operator[] (int n) const
{
return ((int*)this)[n];
}
WWINLINE int& Vector3i::operator[] (int n)
{
return ((int*)this)[n];
}
#endif

View file

@ -0,0 +1,390 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/wwmath/vector4.h 12 12/14/99 11:08a Greg_h $ */
/***************************************************************************
*** Confidential - Westwood Studios ***
***************************************************************************
* *
* Project Name : Westwood 3D *
* *
* File Name : VECTOR4.H *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 02/24/97 *
* *
* Last Update : June 2, 1997 [GH] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Scalar Division Operator -- Divide a vector by a scalar *
* Scalar Multiply Operator -- Multiply a vector by a scalar *
* Vector Addition Operator -- Add two vectors *
* Vector Subtraction Operator -- Subract two vectors *
* Vector Inner Product Operator -- Compute the inner or dot product *
* Vector Equality Operator -- Detemine if two vectors are identical *
* Vector Inequality Operator -- Detemine if two vectors are identical *
* Swap -- swap two Vector4's *
* Vector4::Is_Valid -- Vector4::Is_Valid *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef VECTOR4_H
#define VECTOR4_H
#include "always.h"
#include "wwmath.h"
#include <math.h>
/*
** Vector4 - 4 dimensional vectors
*/
class Vector4
{
public:
float X;
float Y;
float Z;
float W;
// Constructors
Vector4(void) {};
Vector4(const Vector4 & v) { X = v.X; Y = v.Y; Z = v.Z; W = v.W; }
Vector4(float x, float y, float z, float w) { X = x; Y = y; Z = z; W = w; }
Vector4(const float vector[4]) { X = vector[0]; Y = vector[1]; Z = vector[2]; W = vector[3]; }
// Assignment
Vector4 & operator = (const Vector4 & v) { X = v.X; Y = v.Y; Z = v.Z; W = v.W; return *this; }
void Set(float x, float y, float z, float w) { X = x; Y = y; Z = z; W = w; }
// Array access
float & operator [](int i) { return (&X)[i]; }
const float & operator [](int i) const { return (&X)[i]; }
// normalize, compute length
void Normalize(void);
float Length(void) const;
float Length2(void) const;
// unary operators
Vector4 operator-() const { return(Vector4(-X,-Y,-Z,-W)); }
Vector4 operator+() const { return *this; }
Vector4 & operator += (const Vector4 & v) { X += v.X; Y += v.Y; Z += v.Z; W += v.W; return *this; }
Vector4 & operator -= (const Vector4 & v) { X -= v.X; Y -= v.Y; Z -= v.Z; W += v.W; return *this; }
Vector4 & operator *= (float k) { X = X*k; Y=Y*k; Z=Z*k; W=W*k; return *this; }
Vector4 & operator /= (float k) { k=1.0f/k; X = X*k; Y=Y*k; Z=Z*k; W=W*k; return *this; }
// scalar multiplication, division
friend Vector4 operator * (const Vector4 &a,float k);
friend Vector4 operator * (float k,const Vector4 &a);
friend Vector4 operator / (const Vector4 &a,float k);
// vector addition,subtraction
friend Vector4 operator + (const Vector4 &a,const Vector4 &b);
friend Vector4 operator - (const Vector4 &a,const Vector4 &b);
// dot product / inner product
friend float operator * (const Vector4 &a,const Vector4 &b);
static float Dot_Product(const Vector4 &a,const Vector4 &b);
// Equality operators
friend bool operator == (const Vector4 &a,const Vector4 &b);
friend bool operator != (const Vector4 &a,const Vector4 &b);
// verify that none of the members of this vector are invalid floats
bool Is_Valid(void) const;
};
/**************************************************************************
* Scalar Multiply Operator -- Multiply a vector by a scalar *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*========================================================================*/
inline Vector4 operator * (const Vector4 &a,float k)
{
return Vector4((a.X * k),(a.Y * k),(a.Z * k),(a.W * k));
}
inline Vector4 operator * (float k, const Vector4 &a)
{
return a*k;
}
/**************************************************************************
* Scalar Division Operator -- Divide a vector by a scalar *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline Vector4 operator / (const Vector4 &a,float k)
{
float ook=1.0f/k;
return Vector4((a[0] * ook),(a[1] * ook),(a[2] * ook),(a[3] * ook));
}
/**************************************************************************
* Vector Addition Operator -- Add two vectors *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*========================================================================*/
inline Vector4 operator + (const Vector4 &a,const Vector4 &b)
{
return Vector4(
a[0]+b[0],
a[1]+b[1],
a[2]+b[2],
a[3]+b[3]
);
}
/**************************************************************************
* Vector Subtraction Operator -- Subract two vectors *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*========================================================================*/
inline Vector4 operator - (const Vector4 &a,const Vector4 &b)
{
return Vector4(
a[0]-b[0],
a[1]-b[1],
a[2]-b[2],
a[3]-b[3]
);
}
/**************************************************************************
* Vector Inner Product -- Compute the inner or dot product of two vector *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline float operator * (const Vector4 &a,const Vector4 &b)
{
return a[0]*b[0] +
a[1]*b[1] +
a[2]*b[2] +
a[3]*b[3];
}
inline float Vector4::Dot_Product(const Vector4 &a,const Vector4 &b)
{
return a*b;
}
/**************************************************************************
* Vector Equality Operator -- Detemine if two vectors are identical *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline bool operator == (const Vector4 &a,const Vector4 &b)
{
return ( (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]));
}
/**************************************************************************
* Vector Inequality Operator -- Detemine if two vectors are identical *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline bool operator != (const Vector4 &a,const Vector4 &b)
{
return ( (a[0] != b[0]) || (a[1] != b[1]) || (a[2] != b[2]) || (a[3] != b[3]));
}
/**************************************************************************
* Vector4::Normalize -- Normalizes the vector. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline void Vector4::Normalize()
{
float len2 = Length2();
if (len2 != 0.0f) {
float oolen = WWMath::Inv_Sqrt(len2);
X *= oolen;
Y *= oolen;
Z *= oolen;
W *= oolen;
}
}
inline Vector4 Normalize(const Vector4 & vec)
{
float len2 = vec.Length2();
if (len2 != 0.0f) {
float oolen = WWMath::Inv_Sqrt(len2);
return vec * oolen;
}
}
/**************************************************************************
* Vector4::Length -- Returns the length of the vector *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline float Vector4::Length() const
{
return WWMath::Sqrt(Length2());
}
/**************************************************************************
* Vector4::Length -- Returns the square of the length of the vector *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*========================================================================*/
inline float Vector4::Length2() const
{
return X*X + Y*Y + Z*Z + W*W;
}
/***********************************************************************************************
* Swap -- swap two Vector4's *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1997 GH : Created. *
*=============================================================================================*/
inline void Swap(Vector4 & a,Vector4 & b)
{
Vector4 tmp(a);
a = b;
b = tmp;
}
/***********************************************************************************************
* Lerp -- linearly interpolate two Vector4's by an interpolation factor. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: No checking is done to ensure that alpha is between 0 and 1. *
* *
* HISTORY: *
* 01/14/1999 NH : Created. *
*=============================================================================================*/
inline Vector4 Lerp(const Vector4 & a, const Vector4 & b, float alpha)
{
return Vector4(
(a.X + (b.X - a.X)*alpha),
(a.Y + (b.Y - a.Y)*alpha),
(a.Z + (b.Z - a.Z)*alpha),
(a.W + (b.W - a.W)*alpha)
);
}
/***********************************************************************************************
* Vector4::Is_Valid -- Vector4::Is_Valid *
* *
* verifies that all members of this vector are valid floats *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/18/99 gth : Created. *
*=============================================================================================*/
inline bool Vector4::Is_Valid(void) const
{
return (WWMath::Is_Valid_Float(X) && WWMath::Is_Valid_Float(Y) && WWMath::Is_Valid_Float(Z) && WWMath::Is_Valid_Float(W));
}
#endif /* VECTOR4_H */

View file

@ -0,0 +1,125 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/visualc.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 5/16/01 4:11p $*
* *
* $Revision:: 9 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#if defined(_MSC_VER)
/**********************************************************************
** The "bool" integral type was defined by the C++ comittee in
** November of '94. Until the compiler supports this, use the following
** definition.
*/
#include "bool.h"
/*
** Make the inline depth 255
*/
#pragma inline_depth(255)
/*
** Turn off some unneeded warnings.
*/
// "unreferenced inline function has been removed" Yea, so what?
#pragma warning(disable : 4514)
// "conversion from 'double' to 'float', possible loss of data" Yea, so what?
#pragma warning(disable : 4244)
// "overflow in floating-point constant arithmetic" This warning occurs even if the
// loss of precision is insignificant.
#pragma warning(disable : 4056)
// "function not inlined" This warning is typically useless. The inline keyword
// only serves as a suggestion to the compiler and it may or may not inline a
// function on a case by case basis. No need to be told of this.
#pragma warning(disable : 4710)
// "'this' used in base member initializer list" Using "this" in a base member
// initializer is valid -- no need for this warning.
#pragma warning(disable : 4355)
// "typedef-name used as a synonym for class-name". This is by design and should
// not be a warning.
#pragma warning(disable : 4097)
// Unreferenced local function removed.
#pragma warning(disable : 4505)
// 'function selected for automatic inlining'
#pragma warning(disable : 4711)
// 'copy constructor could not be generated'
#pragma warning(disable : 4511)
// 'assignment operator could not be generated'
#pragma warning(disable : 4512)
// 'unreferenced formal parameter'
#pragma warning(disable : 4100)
// HIDE WARNING 4786 "identifier was truncated to '255' characters in the browser information"
// Tempates create LLLOOONNNGGG identifiers!
#pragma warning(disable : 4786)
// 'function selected for automatic inline expansion'. Cool, but since we're treating
// warnings as errors, don't warn me about this!
#pragma warning(disable : 4711)
#define M_E 2.71828182845904523536
#define M_LOG2E 1.44269504088896340736
#define M_LOG10E 0.434294481903251827651
#define M_LN2 0.693147180559945309417
#define M_LN10 2.30258509299404568402
#define M_PI 3.14159265358979323846
#define M_PI_2 1.57079632679489661923
#define M_PI_4 0.785398163397448309616
#define M_1_PI 0.318309886183790671538
#define M_2_PI 0.636619772367581343076
#define M_1_SQRTPI 0.564189583547756286948
#define M_2_SQRTPI 1.12837916709551257390
#define M_SQRT2 1.41421356237309504880
#define M_SQRT_2 0.707106781186547524401
#endif

View file

@ -0,0 +1,889 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/ww3d/w3d_file.h 56 8/12/98 11:16a Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G 3D Library *
* *
* $Archive:: /Commando/Code/ww3d/w3d_file.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 8/11/98 4:15p $*
* *
* $Revision:: 56 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef W3D_FILE_H
#define W3D_FILE_H
#include "always.h"
#ifndef BITTYPE_H
#include "bittype.h"
#endif
/********************************************************************************
VERSION NUMBERS:
Each Major chunk type will contain a "header" as its first
sub-chunk. The first member of this header will be a Version
number formatted so that its major revision number is the
high two bytes and its minor revision number is the lower two
bytes.
Version 1.0:
MESHES - contained the following chunks:
W3D_CHUNK_MESH_HEADER, // header for a mesh
W3D_CHUNK_VERTICES, // array of vertices
W3D_CHUNK_VERTEX_NORMALS, // array of normals
W3D_CHUNK_SURRENDER_NORMALS, // array of surrender normals (one per vertex as req. by surrender)
W3D_CHUNK_TEXCOORDS, // array of texture coordinates
W3D_CHUNK_MATERIALS, // array of materials
W3D_CHUNK_TRIANGLES, // array of triangles
W3D_CHUNK_SURRENDER_TRIANGLES,// array of surrender format tris
W3D_CHUNK_MESH_USER_TEXT, // Name of owning hierarchy, text from the MAX comment field
HIERARCHY TREES - contained the following chunks:
W3D_CHUNK_HIERARCHY_HEADER,
W3D_CHUNK_PIVOTS,
W3D_CHUNK_PIVOT_FIXUPS,
HIERARCHY ANIMATIONS - contained the following chunks:
W3D_CHUNK_ANIMATION_HEADER,
W3D_CHUNK_ANIMATION_CHANNEL,
MESH CONNECTIONS - (blueprint for a hierarchical model) contained these chunks:
Version 2.0:
MESHES:
- Mesh header now contains the hierarchy model name. The mesh name will be built
as <HModelName>.<MeshName> instead of the old convention: <HTreeName>.<Meshname>
- The material chunk is replaced with a new material structure which contains
some information for animating materials.
- Vertex Influences link vertices of a mesh to bones in a hierarchy, this is
the information needed for skinning.
- Damage chunks added. A damage chunk contains a new set of materials, a set
of vertex offsets, and a set of vertex colors.
Added the following chunks:
W3D_CHUNK_VERTEX_COLORS,
W3D_CHUNK_VERTEX_INFLUENCES,
W3D_CHUNK_DAMAGE,
W3D_CHUNK_DAMAGE_HEADER,
W3D_CHUNK_DAMAGE_MATERIALS,
W3D_CHUNK_DAMAGE_VERTICES,
W3D_CHUNK_DAMAGE_COLORS,
W3D_CHUNK_MATERIALS2,
MESH CONNECTIONS: Hierarchy models can now contain skins and collision meshes
in addition to the normal meshes.
W3D_CHUNK_COLLISION_CONNECTION, // collision meshes connected to the hierarchy
W3D_CHUNK_SKIN_CONNECTION, // skins connected to the hierarchy
W3D_CHUNK_CONNECTION_AUX_DATA // extension of the connection header
Dec 12, 1997
Changed MESH_CONNECTIONS chunks into HMODEL chunks because the name
mesh connections was becoming more and more inappropriate... This was only
a data structure naming change so no-one other than the coders are affected
Added W3D_CHUNK_LODMODEL. An LOD Model contains a set of names for
render objects, each with a specified distance range.
Feb 6, 1998
Added W3D_CHUNK_SECTMESH and its sub-chunks. This will be the file
format for the terrain geometry exported from POV's Atlas tool.
March 29, 1998 : Version 3.0
- New material chunk which supports the new features of the 3D engine
- Modified HTrees to always have a root transform to remove all of the
special case -1 bone indexes.
- Added new mesh types, A mesh can now be categorized as: normal,
aligned, skin, collision, or shadow.
June 22, 1998
Removed the "SECTMESH" chunks which were never implemented or used.
Adding a new type of object: The 'Tilemap'. This simple-sounding object
is a binary partition tree of tiles where tiles are rectangular regions of
space. In each leaf to the tree, a mesh is referenced. The tile map is
made of several chunks:
- W3D_CHUNK_TILEMAP
- W3D_CHUNK_TILEMAP_HEADER
- W3D_CHUNK_TILES
- W3D_CHUNK_MESH
- W3D_CHUNK_MESH
...
- W3D_CHUNK_PARTITION_TREE
- W3D_CHUNK_PARTITION_TREE_HEADER
- W3D_CHUNK_PARTITION_TREE_NODES
- W3D_CHUNK_TILE_INSTANCES
- W3D_CHUNK_TILE_INSTANCE
********************************************************************************/
#define W3D_MAKE_VERSION(major,minor) (((major) << 16) | (minor))
#define W3D_GET_MAJOR_VERSION(ver) ((ver)>>16)
#define W3D_GET_MINOR_VERSION(ver) ((ver) & 0xFFFF)
#define W3D_CURRENT_VERSION W3D_MAKE_VERSION(3,0)
/********************************************************************************
CHUNK TYPES FOR ALL 3D DATA
All 3d data is stored in chunks similar to an IFF file. Each
chunk will be headed by an ID and size field.
All structures defined in this header file are prefixed with
W3d to prevent naming conflicts with in-game structures which
may be slightly different than the on-disk structures.
********************************************************************************/
enum {
W3D_CHUNK_MESH = 0, // Mesh definition (.WTM file)
W3D_CHUNK_MESH_HEADER, // header for a mesh
W3D_CHUNK_VERTICES, // array of vertices
W3D_CHUNK_VERTEX_NORMALS, // array of normals
W3D_CHUNK_SURRENDER_NORMALS, // array of surrender normals (one per vertex as req. by surrender)
W3D_CHUNK_TEXCOORDS, // array of texture coordinates
W3D_CHUNK_MATERIALS, // array of materials
O_W3D_CHUNK_TRIANGLES, // array of triangles (obsolete)
O_W3D_CHUNK_QUADRANGLES, // array of quads (obsolete)
W3D_CHUNK_SURRENDER_TRIANGLES,// array of surrender format tris
O_W3D_CHUNK_POV_TRIANGLES, // POV format triangles (obsolete)
O_W3D_CHUNK_POV_QUADRANGLES, // POV format quads (obsolete)
W3D_CHUNK_MESH_USER_TEXT, // Name of owning hierarchy, text from the MAX comment field
W3D_CHUNK_VERTEX_COLORS, // Pre-set vertex coloring
W3D_CHUNK_VERTEX_INFLUENCES, // Mesh Deformation vertex connections
W3D_CHUNK_DAMAGE, // Mesh damage, new set of materials, vertex positions, vertex colors
W3D_CHUNK_DAMAGE_HEADER, // Header for the damage data, tells what is coming
W3D_CHUNK_DAMAGE_VERTICES, // Array of modified vertices (W3dMeshDamageVertexStruct's)
W3D_CHUNK_DAMAGE_COLORS, // Array of modified vert colors (W3dMeshDamageColorStruct's)
O_W3D_CHUNK_DAMAGE_MATERIALS, // (OBSOLETE) Damage materials simply wrapped with MATERIALS3 or higher
W3D_CHUNK_MATERIALS2, // array of version 2 materials (with animation frame counts)
W3D_CHUNK_MATERIALS3, // array of version 3 materials (all new surrender features supported)
W3D_CHUNK_MATERIAL3, // Each version 3 material wrapped with this chunk ID
W3D_CHUNK_MATERIAL3_NAME, // Name of the material (array of chars, null terminated)
W3D_CHUNK_MATERIAL3_INFO, // contains a W3dMaterial3Struct, general material info
W3D_CHUNK_MATERIAL3_DC_MAP, // wraps the following two chunks, diffuse color texture
W3D_CHUNK_MAP3_FILENAME, // filename of the texture
W3D_CHUNK_MAP3_INFO, // a W3dMap3Struct
W3D_CHUNK_MATERIAL3_DI_MAP, // diffuse illimination map, same format as other maps
W3D_CHUNK_MATERIAL3_SC_MAP, // specular color map, same format as other maps
W3D_CHUNK_MATERIAL3_SI_MAP, // specular illumination map, same format as other maps
W3D_CHUNK_MESH_HEADER3, // New improved mesh header
W3D_CHUNK_TRIANGLES, // New improved triangles chunk
W3D_CHUNK_PER_TRI_MATERIALS, // Multi-Mtl meshes - An array of uint16 material id's
W3D_CHUNK_HIERARCHY = 0x100, // hierarchy tree definition (.WHT file)
W3D_CHUNK_HIERARCHY_HEADER,
W3D_CHUNK_PIVOTS,
W3D_CHUNK_PIVOT_FIXUPS, // only needed by the exporter...
W3D_CHUNK_ANIMATION = 0x200, // hierarchy animation data (.WHA file)
W3D_CHUNK_ANIMATION_HEADER,
W3D_CHUNK_ANIMATION_CHANNEL,
W3D_CHUNK_BIT_CHANNEL, // channel of boolean values (e.g. visibility)
W3D_CHUNK_HMODEL = 0x300, // blueprint for a hierarchy model
W3D_CHUNK_HMODEL_HEADER, // usually found at end of a .WTM file
W3D_CHUNK_NODE, // render objects connected to the hierarchy
W3D_CHUNK_COLLISION_NODE, // collision meshes connected to the hierarchy
W3D_CHUNK_SKIN_NODE, // skins connected to the hierarchy
W3D_CHUNK_HMODEL_AUX_DATA, // extension of the connection header
W3D_CHUNK_SHADOW_NODE, // shadow object connected to the hierarchy
W3D_CHUNK_LODMODEL = 0x400, // blueprint for an LOD model. This is simply a
W3D_CHUNK_LODMODEL_HEADER, // collection of 'n' render objects, ordered in terms
W3D_CHUNK_LOD, // of their expected rendering costs.
W3D_CHUNK_TILEMAP = 0x600, // Tile Map definition.
W3D_CHUNK_TILEMAP_NAME,
W3D_CHUNK_TILEMAP_HEADER,
W3D_CHUNK_TILEMAP_TILE_INSTANCES,
W3D_CHUNK_TILEMAP_PARTITION_TREE,
W3D_CHUNK_TILEMAP_PARTITION_NODE,
};
struct W3dChunkHeader
{
uint32 ChunkType; // Type of chunk (see above enumeration)
uint32 ChunkSize; // Size of the chunk, (not including the chunk header)
};
/********************************************************************************
WTM ( Westwood Triangle Mesh )
Each mesh will be contained within a WTM_CHUNK_MESH within
this chunk will be the following chunks:
The header will be the first chunk and it tells general
information about the mesh such as how many triangles there
are, how many vertices, the bounding box, center
of mass, inertia matrix, etc.
The vertex array is an array of Vectors giving the object
space location of each vertex
The normal array is an array of all of the unique vertex
normal vectors needed by the mesh. This allows for vertices
with multiple normals so that we can duplicate the effect
of the smoothing groups in 3dsMax.
The surrender normal array is an array of vertex normals which
correspond 1to1 with the vertices. This is because the current
version of surrender can only handle one vertex normal per vertex.
In this case, the application should skip the normal array chunk
and read the surrender normal chunk into its SR_VERTs
The texture coord array is all of the unique texture coordinates
for the mesh. This allows triangles to share vertices but not
necessarily share texture coordinates.
The material array is a list of the names and rgb colors of
all of the unique materials used by the mesh. All triangles will
have a material index into this list.
The triangle array is all of the triangles which make up the
mesh. Each triangle has 3 indices to its vertices, vertex normals,
and texture coordinates. Each also has a material id and the
coefficients for its plane equation.
The Surrender Triangle array is all of the triangles in a slightly
different format. Surrender triangles contain their u-v coordinates
so there is no indirection and no possibility for sharing. To
make the importer faster, the triangles will also be stored in this
format. The application can read whichever chunk it wants to.
The mesh user text chunk is a NULL-terminated text buffer.
********************************************************************************/
#define W3D_NAME_LEN 16
/////////////////////////////////////////////////////////////////////////////////////////////
// vector
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dVectorStruct
{
float32 X; // X,Y,Z coordinates
float32 Y;
float32 Z;
};
/////////////////////////////////////////////////////////////////////////////////////////////
// quaternion
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dQuaternionStruct
{
float32 Q[4];
};
/////////////////////////////////////////////////////////////////////////////////////////////
// texture coordinate
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dTexCoordStruct
{
float32 U; // U,V coordinates
float32 V;
};
/////////////////////////////////////////////////////////////////////////////////////////////
// rgb color, one byte per channel, padded to an even 4 bytes
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dRGBStruct
{
uint8 R;
uint8 G;
uint8 B;
uint8 pad;
};
/////////////////////////////////////////////////////////////////////////////////////////////
// Version 1.0 Material, array of these are found inside the W3D_CHUNK_MATERIALS chunk.
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dMaterialStruct
{
char MaterialName[W3D_NAME_LEN]; // name of the material (NULL terminated)
char PrimaryName[W3D_NAME_LEN]; // primary texture name (NULL terminated)
char SecondaryName[W3D_NAME_LEN]; // secondary texture name (NULL terminated)
uint32 RenderFlags; // Rendering flags
uint8 Red; // Rgb colors
uint8 Green;
uint8 Blue;
};
/////////////////////////////////////////////////////////////////////////////////////////////
// Version 2.0 Material, array of these are found inside the W3D_CHUNK_MATERIALS2 chunk.
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dMaterial2Struct
{
char MaterialName[W3D_NAME_LEN]; // name of the material (NULL terminated)
char PrimaryName[W3D_NAME_LEN]; // primary texture name (NULL terminated)
char SecondaryName[W3D_NAME_LEN]; // secondary texture name (NULL terminated)
uint32 RenderFlags; // Rendering flags
uint8 Red; // Rgb colors
uint8 Green;
uint8 Blue;
uint8 Alpha;
uint16 PrimaryNumFrames; // number of animated frames (if 1, not animated)
uint16 SecondaryNumFrames; // number of animated frames (if 1, not animated)
char Pad[12]; // expansion room
};
/////////////////////////////////////////////////////////////////////////////////////////////
// MATERIAL ATTRIBUTES (version 3.0 onward)
/////////////////////////////////////////////////////////////////////////////////////////////
// Use alpha enables alpha channels, etc, Use sorting causes display lists using
// this material to be sorted (even with z-buf, translucent materials need to be sorted)
#define W3DMATERIAL_USE_ALPHA 0x00000001
#define W3DMATERIAL_USE_SORTING 0x00000002
// Hints for render devices that cannot support all features
#define W3DMATERIAL_HINT_DIT_OVER_DCT 0x00000010
#define W3DMATERIAL_HINT_SIT_OVER_SCT 0x00000020
#define W3DMATERIAL_HINT_DIT_OVER_DIG 0x00000040
#define W3DMATERIAL_HINT_SIT_OVER_SIG 0x00000080
#define W3DMATERIAL_HINT_FAST_SPECULAR_AFTER_ALPHA 0x00000100
// Last byte is for PSX: Translucency type and a lighting disable flag.
#define W3DMATERIAL_PSX_MASK 0xFF000000
#define W3DMATERIAL_PSX_TRANS_MASK 0x07000000
#define W3DMATERIAL_PSX_TRANS_NONE 0x00000000
#define W3DMATERIAL_PSX_TRANS_100 0x01000000
#define W3DMATERIAL_PSX_TRANS_50 0x02000000
#define W3DMATERIAL_PSX_TRANS_25 0x03000000
#define W3DMATERIAL_PSX_TRANS_MINUS_100 0x04000000
#define W3DMATERIAL_PSX_NO_RT_LIGHTING 0x08000000
/////////////////////////////////////////////////////////////////////////////////////////////
// MAPPING TYPES (version 3.0 onward)
/////////////////////////////////////////////////////////////////////////////////////////////
#define W3DMAPPING_UV 0
#define W3DMAPPING_ENVIRONMENT 1
/////////////////////////////////////////////////////////////////////////////////////////////
// Version 3.0 Material, A W3D_CHUNK_MATERIALS3 chunk will wrap a bunch of
// W3D_CHUNK_MATERIAL3 chunks. Inside each chunk will be a name chunk, an 'info' chunk which
// contains the following struct, and one or more map chunks. a mesh with 2 materials might
// look like:
//
// W3D_CHUNK_MATERIALS3 <-- simply a wrapper around the array of mtls
// W3D_CHUNK_MATERIAL3 <-- a wrapper around each material
// W3D_CHUNK_STRING <-- name of the material
// W3D_CHUNK_MATERIAL3_INFO <-- standard material properties, a W3dMaterial3Struct
// W3D_CHUNK_MATERIAL3_DC_MAP <-- a map, W3dMap3Struct
// W3D_CHUNK_STRING <-- filename of the map
// W3D_CHUNK_MAP_INFO <-- map parameters
// W3D_CHUNK_MATERIAL3_SC_MAP
// W3D_CHUNK_STRING <-- filename of the map
// W3D_CHUNK_MAP_INFO
// W3D_CHUNK_MATERIAL3
// W3D_CHUNK_MATERIAL3_NAME
// W3D_CHUNK_MATERIAL3_INFO
// W3D_CHUNK_MATERIAL3_SI_MAP
//
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dMaterial3Struct
{
uint32 Attributes; // flags,hints,etc.
W3dRGBStruct DiffuseColor; // diffuse color
W3dRGBStruct SpecularColor; // specular color
W3dRGBStruct EmissiveCoefficients; // emmissive coefficients, default to 0,0,0
W3dRGBStruct AmbientCoefficients; // ambient coefficients, default to 1,1,1
W3dRGBStruct DiffuseCoefficients; // diffuse coeficients, default to 1,1,1
W3dRGBStruct SpecularCoefficients; // specular coefficients, default to 0,0,0
float32 Shininess; // how tight the specular highlight will be, 1 - 1000 (default = 1)
float32 Opacity; // how opaque the material is, 0.0 = invisible, 1.0 = fully opaque (default = 1)
float32 Translucency; // how much light passes through the material. (default = 0)
float32 FogCoeff; // effect of fog (0.0=not fogged, 1.0=fogged) (default = 1)
};
/////////////////////////////////////////////////////////////////////////////////////////////
// A map, only occurs as part of a material, will be preceeded by its name.
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dMap3Struct
{
uint16 MappingType; // Mapping type, will be one of the above #defines (e.g. W3DMAPPING_UV)
uint16 FrameCount; // Number of frames (1 if not animated)
float32 FrameRate; // Frame rate, frames per second in floating point
};
/////////////////////////////////////////////////////////////////////////////////////////////
// A triangle, occurs inside the W3D_CHUNK_SURRENDER_TRIANGLES chunk
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dSurrenderTriStruct
{
uint32 Vindex[3]; // vertex, vert normal, and texture coord indexes (all use same index)
W3dTexCoordStruct TexCoord[3]; // texture coordinates (OBSOLETE!!!)
uint32 MaterialIdx; // material index
W3dVectorStruct Normal; // Face normal
uint32 Attributes; // collision flags, sort method, etc
W3dRGBStruct Gouraud[3]; // Pre-set shading values (OBSOLETE!!!)
};
/////////////////////////////////////////////////////////////////////////////////////////////
// A triangle, occurs inside the W3D_CHUNK_TRIANGLES chunk
// This is NEW for Version 3.
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dTriStruct
{
uint32 Vindex[3]; // vertex,vnormal,texcoord,color indices
uint32 Attributes; // attributes bits
W3dVectorStruct Normal; // plane normal
float32 Dist; // plane distance
};
/////////////////////////////////////////////////////////////////////////////////////////////
// Flags for the Mesh Attributes member
/////////////////////////////////////////////////////////////////////////////////////////////
#define W3D_MESH_FLAG_NONE 0x00000000 // plain ole normal mesh
#define W3D_MESH_FLAG_COLLISION_BOX 0x00000001 // mesh is a collision box (should be 8 verts, should be hidden, etc)
#define W3D_MESH_FLAG_SKIN 0x00000002 // skin mesh
#define W3D_MESH_FLAG_SHADOW 0x00000004 // intended to be projected as a shadow
#define W3D_MESH_FLAG_ALIGNED 0x00000008 // always aligns with camera
#define W3D_MESH_FLAG_COLLISION_TYPE_MASK 0x00000FF0 // mask for the collision type bits
#define W3D_MESH_FLAG_COLLISION_TYPE_SHIFT 4 // shifting to get to the collision type bits
#define W3D_MESH_FLAG_COLLISION_TYPE_PHYSICAL 0x00000010 // physical collisions
#define W3D_MESH_FLAG_COLLISION_TYPE_PROJECTILE 0x00000020 // projectiles (rays) collide with this
#define W3D_MESH_FLAG_HIDDEN 0x00001000 // this mesh is hidden by default
/////////////////////////////////////////////////////////////////////////////////////////////
// Original (Obsolete) Mesh Header
/////////////////////////////////////////////////////////////////////////////////////////////
struct W3dMeshHeaderStruct
{
uint32 Version; // Currently version 0x100
char MeshName[W3D_NAME_LEN]; // name of the mesh (Null terminated)
uint32 Attributes;
//
// Counts, these can be regarded as an inventory of what is to come in the file.
//
uint32 NumTris; // number of triangles (OBSOLETE!)
uint32 NumQuads; // number of quads; (OBSOLETE!)
uint32 NumSrTris; // number of triangles
uint32 NumPovTris; // (NOT USED)
uint32 NumPovQuads; // (NOT USED)
uint32 NumVertices; // number of unique vertices
uint32 NumNormals; // number of unique normals (OBSOLETE!)
uint32 NumSrNormals; // number of surrender normals (MUST EQUAL NumVertices or 0)
uint32 NumTexCoords; // number of unique texture coords (MUST EQUAL NumVertices or 0)
uint32 NumMaterials; // number of unique materials needed
uint32 NumVertColors; // number of vertex colors (MUST EQUAL NumVertices or 0)
uint32 NumVertInfluences;// vertex influences(MUST EQUAL NumVertices or 0)
uint32 NumDamageStages; // number of damage offset chunks
uint32 FutureCounts[5]; // reserve space for future counts (set to zero).
//
// LOD controls
//
float32 LODMin; // min LOD distance
float32 LODMax; // max LOD distance
//
// Collision / rendering quick-rejection
//
W3dVectorStruct Min; // Min corner of the bounding box
W3dVectorStruct Max; // Max corner of the bounding box
W3dVectorStruct SphCenter; // Center of bounding sphere
float32 SphRadius; // Bounding sphere radius
//
// Default transformation
//
W3dVectorStruct Translation;
float32 Rotation[9];
//
// Physics Properties
//
W3dVectorStruct MassCenter; // Center of mass in object space
float32 Inertia[9]; // Inertia tensor (relative to MassCenter)
float32 Volume; // volume of the object
//
// Name of possible hierarchy this mesh should be attached to
//
char HierarchyTreeName[W3D_NAME_LEN];
char HierarchyModelName[W3D_NAME_LEN];
uint32 FutureUse[24]; // Reserved for future use
};
/////////////////////////////////////////////////////////////////////////////////////////////
// Version 3 Mesh Header, trimmed out some of the junk that was in the
// previous versions.
/////////////////////////////////////////////////////////////////////////////////////////////
#define W3D_VERTEX_CHANNEL_LOCATION 0x00000001 // object-space location of the vertex
#define W3D_VERTEX_CHANNEL_NORMAL 0x00000002 // object-space normal for the vertex
#define W3D_VERTEX_CHANNEL_TEXCOORD 0x00000004 // texture coordinate
#define W3D_VERTEX_CHANNEL_COLOR 0x00000008 // vertex color
#define W3D_VERTEX_CHANNEL_BONEID 0x00000010 // per-vertex bone id for skins
#define W3D_FACE_CHANNEL_FACE 0x00000001 // basic face info, W3dTriStruct...
struct W3dMeshHeader3Struct
{
uint32 Version;
uint32 Attributes;
char MeshName[W3D_NAME_LEN];
char HierarchyModelName[W3D_NAME_LEN];
//
// Counts, these can be regarded as an inventory of what is to come in the file.
//
uint32 NumTris; // number of triangles
uint32 NumVertices; // number of unique vertices
uint32 NumMaterials; // number of unique materials
uint32 NumDamageStages; // number of damage offset chunks
uint32 FutureCounts[3]; // future counts
uint32 VertexChannels; // bits for presence of types of per-vertex info
uint32 FaceChannels; // bits for presence of types of per-face info
//
// Bounding volumes
//
W3dVectorStruct Min; // Min corner of the bounding box
W3dVectorStruct Max; // Max corner of the bounding box
W3dVectorStruct SphCenter; // Center of bounding sphere
float32 SphRadius; // Bounding sphere radius
};
//
// Vertex Influences. For "skins" each vertex can be associated with a
// different bone.
//
struct W3dVertInfStruct
{
uint16 BoneIdx;
uint8 Pad[6];
};
//
// Mesh Damage. This can include a new set of materials for the mesh,
// new positions for certain vertices in the mesh, and new vertex
// colors for certain vertices.
//
struct W3dMeshDamageStruct
{
uint32 NumDamageMaterials; // number of materials to replace
uint32 NumDamageVerts; // number of vertices to replace
uint32 NumDamageColors; // number of vertex colors to replace
uint32 DamageIndex; // what index is this damage chunk assigned to
uint32 FutureUse[4];
};
struct W3dMeshDamageVertexStruct
{
uint32 VertexIndex;
W3dVectorStruct NewVertex;
};
struct W3dMeshDamageColorStruct
{
uint32 VertexIndex;
W3dRGBStruct NewColor;
};
/********************************************************************************
WHT ( Westwood Hierarchy Tree )
A hierarchy tree defines a set of coordinate systems which are connected
hierarchically. The header defines the name, number of pivots, etc.
The pivots chunk will contain a W3dPivotStructs for each node in the
tree.
The W3dPivotFixupStruct contains a transform for each MAX coordinate
system and our version of that same coordinate system (bone). It is
needed when the user exports the base pose using "Translation Only".
These are the matrices which go from the MAX rotated coordinate systems
to a system which is unrotated in the base pose. These transformations
are needed when exporting a hierarchy animation with the given hierarchy
tree file.
Another explanation of these kludgy "fixup" matrices:
What are the "fixup" matrices? These are the transforms which
were applied to the base pose when the user wanted to force the
base pose to use only matrices with certain properties. For
example, if we wanted the base pose to use translations only,
the fixup transform for each node is a transform which when
multiplied by the real node's world transform, yeilds a pure
translation matrix. Fixup matrices are used in the mesh
exporter since all vertices must be transformed by their inverses
in order to make things work. They also show up in the animation
exporter because they are needed to make the animation work with
the new base pose.
********************************************************************************/
struct W3dHierarchyStruct
{
uint32 Version;
char Name[W3D_NAME_LEN]; // Name of the hierarchy
uint32 NumPivots;
W3dVectorStruct Center;
};
struct W3dPivotStruct
{
char Name[W3D_NAME_LEN]; // Name of the node (UR_ARM, LR_LEG, TORSO, etc)
uint32 ParentIdx; // 0xffffffff = root pivot; no parent
W3dVectorStruct Translation; // translation to pivot point
W3dVectorStruct EulerAngles; // orientation of the pivot point
W3dQuaternionStruct Rotation; // orientation of the pivot point
};
struct W3dPivotFixupStruct
{
float32 TM[4][3]; // this is a direct dump of a MAX 3x4 matrix
};
/********************************************************************************
WHA (Westwood Hierarchy Animation)
A Hierarchy Animation is a set of data defining deltas from the base
position of a hierarchy tree. Translation and Rotation channels can be
attached to any node of the hierarchy tree which the animation is
associated with.
********************************************************************************/
struct W3dAnimHeaderStruct
{
uint32 Version;
char Name[W3D_NAME_LEN];
char HierarchyName[W3D_NAME_LEN];
uint32 NumFrames;
uint32 FrameRate;
};
enum
{
ANIM_CHANNEL_X = 0,
ANIM_CHANNEL_Y,
ANIM_CHANNEL_Z,
ANIM_CHANNEL_XR,
ANIM_CHANNEL_YR,
ANIM_CHANNEL_ZR,
ANIM_CHANNEL_Q
};
struct W3dAnimChannelStruct
{
uint16 FirstFrame;
uint16 LastFrame;
uint16 VectorLen; // length of each vector in this channel
uint16 Flags; // channel type.
uint16 Pivot; // pivot affected by this channel
uint16 pad;
float32 Data[1]; // will be (LastFrame - FirstFrame + 1) * VectorLen long
};
enum
{
BIT_CHANNEL_VIS = 0, // turn meshes on and off depending on anim frame.
};
struct W3dBitChannelStruct
{
uint16 FirstFrame; // all frames outside "First" and "Last" are assumed = DefaultVal
uint16 LastFrame;
uint16 Flags; // channel type.
uint16 Pivot; // pivot affected by this channel
uint8 DefaultVal; // default state when outside valid range.
uint8 Data[1]; // will be (LastFrame - FirstFrame + 1) / 8 long
};
/********************************************************************************
(HModel - Hiearchy Model)
A Hierarchy Model is a set of render objects which should be attached to
bones in a hierarchy tree. There can be multiple objects per node
in the tree. Or there may be no objects attached to a particular bone.
********************************************************************************/
struct W3dHModelHeaderStruct
{
uint32 Version;
char Name[W3D_NAME_LEN]; // Name of this connection set (NULL terminated)
char HierarchyName[W3D_NAME_LEN]; // Name of hierarchy associated with these connections (NULL terminated)
uint16 NumConnections;
};
struct W3dHModelAuxDataStruct
{
uint32 Attributes;
uint32 MeshCount;
uint32 CollisionCount;
uint32 SkinCount;
uint32 ShadowCount;
uint32 FutureCounts[7];
float32 LODMin;
float32 LODMax;
uint32 FutureUse[32];
};
struct W3dHModelNodeStruct
{
// Note: the full name of the Render object is expected to be: <HModelName>.<RenderObjName>
char RenderObjName[W3D_NAME_LEN];
uint16 PivotIdx;
};
/********************************************************************************
(LODModel - Level-Of-Detail Model)
An LOD Model is a set of render objects which are interchangeable and
designed to be different resolution versions of the same object.
********************************************************************************/
struct W3dLODModelHeaderStruct
{
uint32 Version;
char Name[W3D_NAME_LEN]; // Name of this LOD Model
uint16 NumLODs;
};
struct W3dLODStruct
{
char RenderObjName[2*W3D_NAME_LEN];
float32 LODMin; // "artist" inspired switching distances
float32 LODMax;
};
/********************************************************************************
TileMap
********************************************************************************/
struct W3dTileMapHeaderStruct
{
uint32 Version;
uint32 TileInstanceCount;
};
#define W3D_TILE_ROTATION_0 0x00
#define W3D_TILE_ROTATION_90 0x01
#define W3D_TILE_ROTATION_180 0x02
#define W3D_TILE_ROTATION_270 0x03
struct W3dTileInstanceStruct
{
char RenderObjName[2*W3D_NAME_LEN];
uint32 Rotation;
W3dVectorStruct Position;
};
#define W3D_TILEMAP_PARTITION_FLAGS_PARTITION 0x0001
#define W3D_TILEMAP_PARTITION_FLAGS_LEAF 0x0002
#define W3D_TILEMAP_PARTITION_FLAGS_XNORMAL 0x0004
#define W3D_TILEMAP_PARTITION_FLAGS_YNORMAL 0x0008
#define W3D_TILEMAP_PARTITION_FLAGS_ZNORMAL 0x0010
#define W3D_TILEMAP_PARTITION_FLAGS_FRONT_CHILD 0x0020
#define W3D_TILEMAP_PARTITION_FLAGS_BACK_CHILD 0x0040
struct W3dTileMapPartitionStruct
{
uint16 Flags; // type of node, type of plane, flags for presence of children.
uint16 InstanceIndex; // if Type==LEAF, this field will store the tile instance index.
float32 Dist; // distance along plane axis.
W3dVectorStruct Min; // min corner of the bounding box
W3dVectorStruct Max; // max corner of the bounding box
};
#endif

View file

@ -0,0 +1,709 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/max2w3d/w3dquat.cpp 29 2/03/00 4:55p Jason_a $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Voxel Technology *
* *
* File Name : QUAT.CPP *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 02/24/97 *
* *
* Last Update : February 28, 1997 [GH] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Quaternion::Quaternion -- constructor *
* Quaternion::Set -- Set the quaternion *
* Quaternion::operator= -- Assignment operator *
* Quaternion::Make_Closest -- Use nearest representation to the given quaternion. *
* Trackball -- Computes a "trackball" quaternion given 2D mouse coordinates *
* Axis_To_Quat -- Creates a quaternion given an axis and angle of rotation *
* Slerp -- Spherical Linear interpolation! *
* Build_Quaternion -- Creates a quaternion from a Matrix *
* Build_Matrix -- Creates a Matrix from a Quaternion *
* Normalize -- normalizes a quaternion *
* Quaternion::Quaternion -- constructor *
* Slerp_Setup -- Get ready to call "Cached_Slerp" *
* Cached_Slerp -- Quaternion slerping, optimized with cached values *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "w3dquat.h"
#include "matrix3d.h"
#include "matrix4.h"
#include "wwmath.h"
#include <stdio.h>
//#include <iostream.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#define SLERP_EPSILON 0.001
static int _nxt[3] = { 1 , 2 , 0 };
// ------------------------------------------------------------
// local functions
// ------------------------------------------------------------
static float project_to_sphere(float,float,float);
/***********************************************************************************************
* Quaternion::Quaternion -- constructor *
* *
* constructs a quaternion from the given axis and angle of rotation (in RADIANS of course) *
* *
* INPUT: *
* axis - axis of the rotation *
* angle - rotation angle *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 12/10/97 GTH : Created. *
*=============================================================================================*/
Quaternion::Quaternion(const Vector3 & axis,float angle)
{
float s = sinf(angle/2);
float c = cosf(angle/2);
X = s * axis.X;
Y = s * axis.Y;
Z = s * axis.Z;
W = c;
}
/***********************************************************************************************
* Quaternion::Normalize -- Normalize to a unit quaternion *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*=============================================================================================*/
void Quaternion::Normalize()
{
float mag = WWMath::Sqrt(X * X + Y * Y + Z * Z + W * W);
if (0.0f == mag) {
return;
} else {
X /= mag;
Y /= mag;
Z /= mag;
W /= mag;
}
}
/***********************************************************************************************
* Quaternion::operator= -- Assignment operator *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/24/1997 GH : Created. *
*=============================================================================================*/
Quaternion & Quaternion::operator = (const Quaternion & source)
{
X = source[0];
Y = source[1];
Z = source[2];
W = source[3];
return *this;
}
/***********************************************************************************************
* Q::Make_Closest -- Use nearest representation to the given quaternion. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/28/1997 GH : Created. *
*=============================================================================================*/
Quaternion & Quaternion::Make_Closest(const Quaternion & qto)
{
float cos_t = qto.X * X + qto.Y * Y + qto.Z * Z + qto.W * W;
// if we are on opposite hemisphere from qto, negate ourselves
if (cos_t < 0.0) {
X = -X;
Y = -Y;
Z = -Z;
W = -W;
}
return *this;
}
/***********************************************************************************************
* Trackball -- Computes a "trackball" quaternion given 2D mouse coordinates *
* *
* INPUT: *
* x0,y0 - x1,y1 - "normalized" mouse coordinates for the mouse movement *
* sphsize - size of the trackball sphere *
* *
* OUTPUT: *
* a quaternion representing the rotation of a trackball *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/28/1997 GH : Created. *
*=============================================================================================*/
Quaternion Trackball(float x0, float y0, float x1, float y1, float sphsize)
{
Vector3 a;
Vector3 p1;
Vector3 p2;
Vector3 d;
float phi,t;
if ((x0 == x1) && (y0 == y1)) {
return Quaternion(0.0f, 0.0f, 0.0f, 1.0f); // Zero rotation
}
// Compute z coordinates for projection of p1 and p2 to
// deformed sphere
p1[0] = x0;
p1[1] = y0;
p1[2] = project_to_sphere(sphsize, x0, y0);
p2[0] = x1;
p2[1] = y1;
p2[2] = project_to_sphere(sphsize, x1, y1);
// Find their cross product
Vector3::Cross_Product(p2,p1,&a);
// Compute how much to rotate
d = p1 - p2;
t = d.Length() / (2.0f * sphsize);
// Avoid problems with out of control values
if (t > 1.0f) t = 1.0f;
if (t < -1.0f) t = -1.0f;
phi = 2.0f * asin(t);
return Axis_To_Quat(a, phi);
}
/***********************************************************************************************
* Axis_To_Quat -- Creates a quaternion given an axis and angle of rotation *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/28/1997 GH : Created. *
*=============================================================================================*/
Quaternion Axis_To_Quat(const Vector3 &a, float phi)
{
Quaternion q;
Vector3 tmp = a;
tmp.Normalize();
q[0] = tmp[0];
q[1] = tmp[1];
q[2] = tmp[2];
q.Scale(sinf(phi / 2.0f));
q[3] = cosf(phi / 2.0f);
return q;
}
/***********************************************************************************************
* Slerp -- Spherical Linear interpolation! *
* *
* INPUT: *
* p - start quaternion *
* q - end quaternion *
* alpha - interpolating parameter *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/28/1997 GH : Created. *
*=============================================================================================*/
Quaternion Slerp(const Quaternion & p,const Quaternion & q,float alpha)
{
float beta; // complementary interploation parameter
float theta; // angle between p and q
float sin_t,cos_t; // sine, cosine of theta
float oo_sin_t;
int qflip; // use flip of q?
// cos theta = dot product of p and q
cos_t = p.X * q.X + p.Y * q.Y + p.Z * q.Z + p.W * q.W;
// if q is on opposite hemisphere from A, use -B instead
if (cos_t < 0.0) {
cos_t = -cos_t;
qflip = true;
} else {
qflip = false;
}
if (1.0 - cos_t < SLERP_EPSILON) {
// if q is very close to p, just linearly interpolate
// between the two.
beta = 1.0 - alpha;
} else {
// normal slerp!
theta = acos(cos_t);
sin_t = sinf(theta);
oo_sin_t = 1.0 / sin_t;
beta = sinf(theta - alpha*theta) * oo_sin_t;
alpha = sinf(alpha*theta) * oo_sin_t;
}
if (qflip) {
alpha = -alpha;
}
Quaternion res;
res.X = beta*p.X + alpha*q.X;
res.Y = beta*p.Y + alpha*q.Y;
res.Z = beta*p.Z + alpha*q.Z;
res.W = beta*p.W + alpha*q.W;
return res;
}
/***********************************************************************************************
* Slerp_Setup -- Get ready to call "Cached_Slerp" *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 2/27/98 GTH : Created. *
*=============================================================================================*/
void Slerp_Setup(const Quaternion & p,const Quaternion & q,SlerpInfoStruct * slerpinfo)
{
float cos_t;
assert(slerpinfo != NULL);
// cos theta = dot product of p and q
cos_t = p.X * q.X + p.Y * q.Y + p.Z * q.Z + p.W * q.W;
// if q is on opposite hemisphere from A, use -B instead
if (cos_t < 0.0) {
cos_t = -cos_t;
slerpinfo->Flip = true;
} else {
slerpinfo->Flip = false;
}
if (1.0 - cos_t < SLERP_EPSILON) {
slerpinfo->Linear = true;
slerpinfo->Theta = 0.0f;
slerpinfo->SinT = 0.0f;
} else {
slerpinfo->Linear = false;
slerpinfo->Theta = acos(cos_t);
slerpinfo->SinT = sinf(slerpinfo->Theta);
}
}
/***********************************************************************************************
* Cached_Slerp -- Quaternion slerping, optimized with cached values *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 2/27/98 GTH : Created. *
*=============================================================================================*/
Quaternion Cached_Slerp(const Quaternion & p,const Quaternion & q,float alpha,SlerpInfoStruct * slerpinfo)
{
float beta; // complementary interploation parameter
float oo_sin_t;
if (slerpinfo->Linear) {
// if q is very close to p, just linearly interpolate
// between the two.
beta = 1.0 - alpha;
} else {
// normal slerp!
oo_sin_t = 1.0 / slerpinfo->Theta;
beta = sin(slerpinfo->Theta - alpha*slerpinfo->Theta) * oo_sin_t;
alpha = sin(alpha*slerpinfo->Theta) * oo_sin_t;
}
if (slerpinfo->Flip) {
alpha = -alpha;
}
Quaternion res;
res.X = beta*p.X + alpha*q.X;
res.Y = beta*p.Y + alpha*q.Y;
res.Z = beta*p.Z + alpha*q.Z;
res.W = beta*p.W + alpha*q.W;
return res;
}
void Cached_Slerp(const Quaternion & p,const Quaternion & q,float alpha,SlerpInfoStruct * slerpinfo,Quaternion * set_q)
{
float beta; // complementary interploation parameter
float oo_sin_t;
if (slerpinfo->Linear) {
// if q is very close to p, just linearly interpolate
// between the two.
beta = 1.0 - alpha;
} else {
// normal slerp!
oo_sin_t = 1.0 / slerpinfo->Theta;
beta = sin(slerpinfo->Theta - alpha*slerpinfo->Theta) * oo_sin_t;
alpha = sin(alpha*slerpinfo->Theta) * oo_sin_t;
}
if (slerpinfo->Flip) {
alpha = -alpha;
}
set_q->X = beta*p.X + alpha*q.X;
set_q->Y = beta*p.Y + alpha*q.Y;
set_q->Z = beta*p.Z + alpha*q.Z;
set_q->W = beta*p.W + alpha*q.W;
}
/***********************************************************************************************
* Build_Quaternion -- Creates a quaternion from a Matrix *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* Matrix MUST NOT have scaling! *
* *
* HISTORY: *
* 02/28/1997 GH : Created. *
*=============================================================================================*/
Quaternion Build_Quaternion(const Matrix3D & mat)
{
float tr,s;
int i,j,k;
Quaternion q;
// sum the diagonal of the rotation matrix
tr = mat[0][0] + mat[1][1] + mat[2][2];
if (tr > 0.0f) {
s = sqrt(tr + 1.0);
q[3] = s * 0.5;
s = 0.5 / s;
q[0] = (mat[2][1] - mat[1][2]) * s;
q[1] = (mat[0][2] - mat[2][0]) * s;
q[2] = (mat[1][0] - mat[0][1]) * s;
} else {
i=0;
if (mat[1][1] > mat[0][0]) i = 1;
if (mat[2][2] > mat[i][i]) i = 2;
j = _nxt[i];
k = _nxt[j];
s = sqrt((mat[i][i] - (mat[j][j] + mat[k][k])) + 1.0);
q[i] = s * 0.5;
if (s != 0.0) {
s = 0.5 / s;
}
q[3] = ( mat[k][j] - mat[j][k] ) * s;
q[j] = ( mat[j][i] + mat[i][j] ) * s;
q[k] = ( mat[k][i] + mat[i][k] ) * s;
}
return q;
}
Quaternion Build_Quaternion(const Matrix3 & mat)
{
float tr,s;
int i,j,k;
Quaternion q;
// sum the diagonal of the rotation matrix
tr = mat[0][0] + mat[1][1] + mat[2][2];
if (tr > 0.0) {
s = sqrt(tr + 1.0);
q[3] = s * 0.5;
s = 0.5 / s;
q[0] = (mat[2][1] - mat[1][2]) * s;
q[1] = (mat[0][2] - mat[2][0]) * s;
q[2] = (mat[1][0] - mat[0][1]) * s;
} else {
i = 0;
if (mat[1][1] > mat[0][0]) i = 1;
if (mat[2][2] > mat[i][i]) i = 2;
j = _nxt[i];
k = _nxt[j];
s = sqrt( (mat[i][i] - (mat[j][j]+mat[k][k])) + 1.0);
q[i] = s * 0.5;
if (s != 0.0) {
s = 0.5/s;
}
q[3] = ( mat[k][j] - mat[j][k] ) * s;
q[j] = ( mat[j][i] + mat[i][j] ) * s;
q[k] = ( mat[k][i] + mat[i][k] ) * s;
}
return q;
}
Quaternion Build_Quaternion(const Matrix4 & mat)
{
float tr,s;
int i,j,k;
Quaternion q;
// sum the diagonal of the rotation matrix
tr = mat[0][0] + mat[1][1] + mat[2][2];
if (tr > 0.0) {
s = sqrt(tr + 1.0);
q[3] = s * 0.5;
s = 0.5 / s;
q[0] = (mat[2][1] - mat[1][2]) * s;
q[1] = (mat[0][2] - mat[2][0]) * s;
q[2] = (mat[1][0] - mat[0][1]) * s;
} else {
i = 0;
if (mat[1][1] > mat[0][0]) i = 1;
if (mat[2][2] > mat[i][i]) i = 2;
j = _nxt[i];
k = _nxt[j];
s = sqrt( (mat[i][i] - (mat[j][j]+mat[k][k])) + 1.0);
q[i] = s * 0.5;
if (s != 0.0) {
s = 0.5/s;
}
q[3] = ( mat[k][j] - mat[j][k] ) * s;
q[j] = ( mat[j][i] + mat[i][j] ) * s;
q[k] = ( mat[k][i] + mat[i][k] ) * s;
}
return q;
}
/***********************************************************************************************
* Build_Matrix -- Creates a Matrix from a Quaternion *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/28/1997 GH : Created. *
*=============================================================================================*/
Matrix3 Build_Matrix3(const Quaternion & q)
{
Matrix3 m;
m[0][0] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]));
m[0][1] = (float)(2.0 * (q[0] * q[1] - q[2] * q[3]));
m[0][2] = (float)(2.0 * (q[2] * q[0] + q[1] * q[3]));
m[1][0] = (float)(2.0 * (q[0] * q[1] + q[2] * q[3]));
m[1][1] = (float)(1.0 - 2.0f * (q[2] * q[2] + q[0] * q[0]));
m[1][2] = (float)(2.0 * (q[1] * q[2] - q[0] * q[3]));
m[2][0] = (float)(2.0 * (q[2] * q[0] - q[1] * q[3]));
m[2][1] = (float)(2.0 * (q[1] * q[2] + q[0] * q[3]));
m[2][2] =(float)(1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]));
return m;
}
Matrix3D Build_Matrix3D(const Quaternion & q)
{
Matrix3D m;
// initialize the rotation sub-matrix
m[0][0] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]));
m[0][1] = (float)(2.0 * (q[0] * q[1] - q[2] * q[3]));
m[0][2] = (float)(2.0 * (q[2] * q[0] + q[1] * q[3]));
m[1][0] = (float)(2.0 * (q[0] * q[1] + q[2] * q[3]));
m[1][1] = (float)(1.0 - 2.0f * (q[2] * q[2] + q[0] * q[0]));
m[1][2] = (float)(2.0 * (q[1] * q[2] - q[0] * q[3]));
m[2][0] = (float)(2.0 * (q[2] * q[0] - q[1] * q[3]));
m[2][1] = (float)(2.0 * (q[1] * q[2] + q[0] * q[3]));
m[2][2] =(float)(1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]));
// no translation
m[0][3] = m[1][3] = m[2][3] = 0.0f;
return m;
}
Matrix4 Build_Matrix4(const Quaternion & q)
{
Matrix4 m;
// initialize the rotation sub-matrix
m[0][0] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]));
m[0][1] = (float)(2.0 * (q[0] * q[1] - q[2] * q[3]));
m[0][2] = (float)(2.0 * (q[2] * q[0] + q[1] * q[3]));
m[1][0] = (float)(2.0 * (q[0] * q[1] + q[2] * q[3]));
m[1][1] = (float)(1.0 - 2.0f * (q[2] * q[2] + q[0] * q[0]));
m[1][2] = (float)(2.0 * (q[1] * q[2] - q[0] * q[3]));
m[2][0] = (float)(2.0 * (q[2] * q[0] - q[1] * q[3]));
m[2][1] = (float)(2.0 * (q[1] * q[2] + q[0] * q[3]));
m[2][2] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]));
// no translation
m[0][3] = m[1][3] = m[2][3] = 0.0f;
// last row
m[3][0] = m[3][1] = m[3][2] = 0.0f;
m[3][3] = 1.0f;
return m;
}
void Quaternion::Rotate_X(float theta)
{
// TODO: optimize this
*this = (*this) * Quaternion(Vector3(1,0,0),theta);
}
void Quaternion::Rotate_Y(float theta)
{
// TODO: optimize this
*this = (*this) * Quaternion(Vector3(0,1,0),theta);
}
void Quaternion::Rotate_Z(float theta)
{
// TODO: optimize this
*this = (*this) * Quaternion(Vector3(0,0,1),theta);
}
float project_to_sphere(float r, float x, float y)
{
const float SQRT2 = 1.41421356f;
float t, z;
float d = WWMath::Sqrt(x * x + y * y);
if (d < r * (SQRT2/(2.0f))) // inside sphere
z = WWMath::Sqrt(r * r - d * d);
else { // on hyperbola
t = r / SQRT2;
z = t * t / d;
}
return z;
}
void Quaternion::Randomize(void)
{
X = ((float) (rand() & 0xFFFF)) / 65536.0f;
Y = ((float) (rand() & 0xFFFF)) / 65536.0f;
Z = ((float) (rand() & 0xFFFF)) / 65536.0f;
W = ((float) (rand() & 0xFFFF)) / 65536.0f;
Normalize();
}

View file

@ -0,0 +1,262 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/Tools/max2w3d/w3dquat.h 27 2/03/00 4:55p Jason_a $ */
/***************************************************************************
*** Confidential - Westwood Studios ***
***************************************************************************
* *
* Project Name : Voxel Technology *
* *
* File Name : QUAT.H *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 02/24/97 *
* *
* Last Update : February 24, 1997 [GH] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef QUAT_H
#define QUAT_H
#include "always.h"
#include "wwmath.h"
#include "wwmatrix3.h"
#include "vector3.h"
class Quaternion
{
private:
public:
// X,Y,Z are the imaginary parts of the quaterion
// W is the real part
float X;
float Y;
float Z;
float W;
public:
Quaternion(void) {};
explicit Quaternion(bool init) { if (init) { X = 0.0f; Y = 0.0f; Z = 0.0f; W = 1.0f; } }
explicit Quaternion(float a, float b, float c, float d) { X=a; Y=b; Z=c; W=d; }
explicit Quaternion(const Vector3 & axis,float angle);
Quaternion & operator=(const Quaternion & source);
void Set(float a = 0.0, float b = 0.0, float c = 0.0, float d = 1.0) { X = a; Y = b; Z = c; W = d; }
void Make_Identity(void) { Set(); };
void Scale(float s) { X = (float)(s*X); Y = (float)(s*Y); Z = (float)(s*Z); W = (float)(s*W); }
// Array access
float & operator [](int i) { return (&X)[i]; }
const float & operator [](int i) const { return (&X)[i]; }
// Unary operators.
// Remember that q and -q represent the same 3D rotation.
Quaternion operator-() const { return(Quaternion(-X,-Y,-Z,-W)); }
Quaternion operator+() const { return *this; }
// Every 3D rotation can be expressed by two different quaternions, This
// function makes the current quaternion convert itself to the representation
// which is closer on the 4D unit-hypersphere to the given quaternion.
Quaternion & Make_Closest(const Quaternion & qto);
// Square of the magnitude of the quaternion
float Length2(void) const { return (X*X + Y*Y + Z*Z + W*W); }
// Magnitude of the quaternion
float Length(void) const { return WWMath::Sqrt(Length2()); }
// Make the quaternion unit length
void Normalize(void);
// post-concatenate rotations about the coordinate axes
void Rotate_X(float theta);
void Rotate_Y(float theta);
void Rotate_Z(float theta);
// initialize this quaternion randomly (creates a random *unit* quaternion)
void Randomize(void);
// transform (rotate) a vector with this quaternion
Vector3 Rotate_Vector(const Vector3 & v) const;
void Rotate_Vector(const Vector3 & v,Vector3 * set_result) const;
// verify that none of the members of this quaternion are invalid floats
bool Is_Valid(void) const;
};
// Inverse of the quaternion (1/q)
inline Quaternion Inverse(const Quaternion & a)
{
return Quaternion(-a[0],-a[1],-a[2],a[3]);
}
// Conjugate of the quaternion
inline Quaternion Conjugate(const Quaternion & a)
{
return Quaternion(-a[0],-a[1],-a[2],a[3]);
}
// Add two quaternions
inline Quaternion operator + (const Quaternion & a,const Quaternion & b)
{
return Quaternion(a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]);
}
// Subract two quaternions
inline Quaternion operator - (const Quaternion & a,const Quaternion & b)
{
return Quaternion(a[0] - b[0], a[1] - b[1], a[2] - b[2], a[3] - b[3]);
}
// Multiply a quaternion by a scalar:
inline Quaternion operator * (float scl, const Quaternion & a)
{
return Quaternion(scl*a[0], scl*a[1], scl*a[2], scl*a[3]);
}
// Multiply a quaternion by a scalar
inline Quaternion operator * (const Quaternion & a, float scl)
{
return scl*a;
}
// Multiply two quaternions
inline Quaternion operator * (const Quaternion & a,const Quaternion & b)
{
return Quaternion
(
a.W*b.X + b.W*a.X + (a.Y*b.Z - b.Y*a.Z),
a.W*b.Y + b.W*a.Y - (a.X*b.Z - b.X*a.Z),
a.W*b.Z + b.W*a.Z + (a.X*b.Y - b.X*a.Y),
a.W * b.W - (a.X * b.X + a.Y * b.Y + a.Z * b.Z)
);
}
// Divide two quaternions
inline Quaternion operator / (const Quaternion & a,const Quaternion & b)
{
return a * Inverse(b);
}
// Normalized version of the quaternion
inline Quaternion Normalize(const Quaternion & a)
{
float mag = a.Length();
if (0.0f == mag) {
return a;
} else {
float oomag = 1.0f / mag;
return Quaternion(a[0] * oomag, a[1] * oomag, a[2] * oomag, a[3] * oomag);
}
}
// This function computes a quaternion based on an axis
// (defined by the given Vector a) and an angle about
// which to rotate. The angle is expressed in radians.
Quaternion Axis_To_Quat(const Vector3 &a, float angle);
// Pass the x and y coordinates of the last and current position
// of the mouse, scaled so they are from -1.0 to 1.0
// The quaternion is the computed as the rotation of a trackball
// between the two points projected onto a sphere. This can
// be used to implement an intuitive viewing control system.
Quaternion Trackball(float x0, float y0, float x1, float y1, float sphsize);
// Spherical Linear interpolation of quaternions
Quaternion Slerp(const Quaternion & a,const Quaternion & b,float t);
// Convert a rotation matrix into a quaternion
Quaternion Build_Quaternion(const Matrix3 & matrix);
Quaternion Build_Quaternion(const Matrix3D & matrix);
Quaternion Build_Quaternion(const Matrix4 & matrix);
// Convert a quaternion into a rotation matrix
Matrix3 Build_Matrix3(const Quaternion & quat);
Matrix3D Build_Matrix3D(const Quaternion & quat);
Matrix4 Build_Matrix4(const Quaternion & quat);
// Some values can be cached if you are performing multiple slerps
// between the same two quaternions...
struct SlerpInfoStruct
{
float SinT;
float Theta;
bool Flip;
bool Linear;
};
// Cached slerp implementation
void Slerp_Setup(const Quaternion & p,const Quaternion & q,SlerpInfoStruct * slerpinfo);
void Cached_Slerp(const Quaternion & p,const Quaternion & q,float alpha,SlerpInfoStruct * slerpinfo,Quaternion * set_q);
Quaternion Cached_Slerp(const Quaternion & p,const Quaternion & q,float alpha,SlerpInfoStruct * slerpinfo);
inline Vector3 Quaternion::Rotate_Vector(const Vector3 & v) const
{
float x = W*v.X + (Y*v.Z - v.Y*Z);
float y = W*v.Y - (X*v.Z - v.X*Z);
float z = W*v.Z + (X*v.Y - v.X*Y);
float w = -(X*v.X + Y*v.Y + Z*v.Z);
return Vector3
(
w*(-X) + W*x + (y*(-Z) - (-Y)*z),
w*(-Y) + W*y - (x*(-Z) - (-X)*z),
w*(-Z) + W*z + (x*(-Y) - (-X)*y)
);
}
inline void Quaternion::Rotate_Vector(const Vector3 & v,Vector3 * result) const
{
assert(result != NULL);
float x = W*v.X + (Y*v.Z - v.Y*Z);
float y = W*v.Y - (X*v.Z - v.X*Z);
float z = W*v.Z + (X*v.Y - v.X*Y);
float w = -(X*v.X + Y*v.Y + Z*v.Z);
result->X = w*(-X) + W*x + (y*(-Z) - (-Y)*z);
result->Y = w*(-Y) + W*y - (x*(-Z) - (-X)*z);
result->Z = w*(-Z) + W*z + (x*(-Y) - (-X)*y);
}
inline bool Quaternion::Is_Valid(void) const
{
return ( WWMath::Is_Valid_Float(X) &&
WWMath::Is_Valid_Float(Y) &&
WWMath::Is_Valid_Float(Z) &&
WWMath::Is_Valid_Float(W) );
}
#endif /* QUAT_H */

View file

@ -0,0 +1,118 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /G/wwlib/WATCOM.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:56a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#if !defined(WATCOM_H) && defined(__WATCOMC__)
#define WATCOM_H
/**********************************************************************
** The "bool" integral type was defined by the C++ comittee in
** November of '94. Until the compiler supports this, use the following
** definition.
*/
#include "bool.h"
// Turn all warnings into errors.
#pragma warning * 0
// Disables warning when "sizeof" is used on an object with virtual functions.
#pragma warning 549 9
// Disable the "Integral value may be truncated during assignment or initialization".
#pragma warning 389 9
// Allow constructing a temporary to be used as a parameter.
#pragma warning 604 9
// Disable the construct resolved as an expression warning.
#pragma warning 595 9
// Disable the strange "construct resolved as a declaration/type" warning.
#pragma warning 594 9
// Disable the "pre-compiled header file cannot be used" warning.
#pragma warning 698 9
// Disable the "temporary object used to initialize a non-constant reference" warning.
#pragma warning 665 9
// Disable the "pointer or reference truncated by cast. Cast is supposed to REMOVE warnings, not create them.
#pragma warning 579 9
// Disable the warning that suggests a null destructor be placed in class definition.
#pragma warning 656 9
// Disable the warning about moving empty constructors/destructors to the class declaration.
#pragma warning 657 9
// No virtual destructor is not an error in C&C.
#pragma warning 004 9
// Integral constant will be truncated warning is usually ok when dealing with bitfields.
#pragma warning 388 9
// Turns off unreferenced function parameter warning.
//#pragma off(unreferenced)
/*
** The "bool" integral type was defined by the C++ comittee in
** November of '94. Until the compiler supports this, use the following
** definition.
*/
#include "bool.h"
#if !defined(__BORLANDC__)
#define M_E 2.71828182845904523536
#define M_LOG2E 1.44269504088896340736
#define M_LOG10E 0.434294481903251827651
#define M_LN2 0.693147180559945309417
#define M_LN10 2.30258509299404568402
#define M_PI 3.14159265358979323846
#define M_PI_2 1.57079632679489661923
#define M_PI_4 0.785398163397448309616
#define M_1_PI 0.318309886183790671538
#define M_2_PI 0.636619772367581343076
#define M_1_SQRTPI 0.564189583547756286948
#define M_2_SQRTPI 1.12837916709551257390
#define M_SQRT2 1.41421356237309504880
#define M_SQRT_2 0.707106781186547524401
#endif
#endif

View file

@ -0,0 +1,91 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/win.h $*
* *
* $Author:: Denzil_l $*
* *
* $Modtime:: 6/26/01 1:59p $*
* *
* $Revision:: 10 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef WIN_H
#define WIN_H
/*
** This header file includes the Windows headers. If there are any special pragmas that need
** to occur around this process, they are performed here. Typically, certain warnings will need
** to be disabled since the Windows headers are repleat with illegal and dangerous constructs.
**
** Within the windows headers themselves, Microsoft has disabled the warnings 4290, 4514,
** 4069, 4200, 4237, 4103, 4001, 4035, 4164. Makes you wonder, eh?
*/
// When including windows, lets just bump the warning level back to 3...
#if (_MSC_VER >= 1200)
#pragma warning(push, 3)
#endif
// this define should also be in the DSP just in case someone includes windows stuff directly
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
//#include <mmsystem.h>
//#include <windowsx.h>
//#include <winnt.h>
//#include <winuser.h>
#if (_MSC_VER >= 1200)
#pragma warning(pop)
#endif
#ifdef _WINDOWS
extern HINSTANCE ProgramInstance;
extern HWND MainWindow;
extern bool GameInFocus;
#ifdef _DEBUG
void __cdecl Print_Win32Error(unsigned long win32Error);
#else // _DEBUG
#define Print_Win32Error
#endif // _DEBUG
#else // _WINDOWS
#include <unistd.h>
#endif // _WINDOWS
#endif // WIN_H

View file

@ -0,0 +1,112 @@
/*
** Command & Conquer Generals(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 : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/wwfile.h $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 5/04/01 7:43p $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef WWFILE_Hx
#define WWFILE_Hx
#ifdef _UNIX
#include "osdep.h"
#endif
#define YEAR(dt) (((dt & 0xFE000000) >> (9 + 16)) + 1980)
#define MONTH(dt) ((dt & 0x01E00000) >> (5 + 16))
#define DAY(dt) ((dt & 0x001F0000) >> (0 + 16))
#define HOUR(dt) ((dt & 0x0000F800) >> 11)
#define MINUTE(dt) ((dt & 0x000007E0) >> 5)
#define SECOND(dt) ((dt & 0x0000001F) << 1)
#ifndef SEEK_SET
#define SEEK_SET 0 // Seek from start of file.
#define SEEK_CUR 1 // Seek relative from current location.
#define SEEK_END 2 // Seek from end of file.
#endif
#ifndef NULL
#define NULL 0
#endif
class FileClass
{
public:
enum
{
READ = 1,
WRITE = 2,
PRINTF_BUFFER_SIZE = 1024
};
virtual ~FileClass(void) {};
virtual char const * File_Name(void) const = 0;
virtual char const * Set_Name(char const *filename) = 0;
virtual int Create(void) = 0;
virtual int Delete(void) = 0;
virtual bool Is_Available(int forced=false) = 0;
virtual bool Is_Open(void) const = 0;
virtual int Open(char const *filename, int rights=READ) = 0;
virtual int Open(int rights=READ) = 0;
virtual int Read(void *buffer, int size) = 0;
virtual int Seek(int pos, int dir=SEEK_CUR) = 0;
virtual int Tell(void) { return Seek(0); }
virtual int Size(void) = 0;
virtual int Write(void const *buffer, int size) = 0;
virtual void Close(void) = 0;
virtual unsigned long Get_Date_Time(void) {return(0);}
virtual bool Set_Date_Time(unsigned long ) {return(false);}
virtual void Error(int error, int canretry = false, char const * filename=NULL) = 0;
virtual void * Get_File_Handle(void) { return reinterpret_cast<void *>(-1); }
operator char const * ()
{
return File_Name();
}
// this form uses a stack buffer of PRINTF_BUFFER_SIZE
int Printf(char *str, ...);
// this form uses the supplied buffer if PRINTF_BUFFER_SIZE is expected to be too small.
int Printf(char *buffer, int bufferSize, char *str, ...);
// this form uses the stack buffer but will prepend any output with the indicated number of tab characters '\t'
int Printf_Indented(unsigned depth, char *str, ...);
};
#endif

View file

@ -0,0 +1,47 @@
/*
** Command & Conquer Generals(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/wwmath.cpp $*
* *
* Author:: Eric_c *
* *
* $Modtime:: 3/18/99 10:39a $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "wwmath.h"
#include <stdlib.h>
/*
**
*/
float WWMath::Random_Float(void)
{
return ((float)(rand() & 0xFFF)) / (float)(0xFFF);
}

View file

@ -0,0 +1,257 @@
/*
** Command & Conquer Generals(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/wwmath.h $*
* *
* Author:: Greg Hjelstrom *
* *
* $Modtime:: 3/16/00 8:28p $*
* *
* $Revision:: 40 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef WWMATH_H
#define WWMATH_H
#include "always.h"
#include <math.h>
#include <assert.h>
/*
** Some global constants.
*/
#define WWMATH_EPSILON 0.0001f
#define WWMATH_EPSILON2 WWMATH_EPSILON * WWMATH_EPSILON
#define WWMATH_PI 3.141592654f
#define WWMATH_FLOAT_MAX (FLT_MAX)
#define WWMATH_SQRT2 1.414213562f
#define WWMATH_SQRT3 1.732050808f
#define WWMATH_OOSQRT2 0.707106781f
#define WWMATH_OOSQRT3 0.577350269f
/*
** Macros to convert between degrees and radians
*/
#ifndef RAD_TO_DEG
#define RAD_TO_DEG(x) (((double)x)*180.0/WWMATH_PI)
#endif
#ifndef DEG_TO_RAD
#define DEG_TO_RAD(x) (((double)x)*WWMATH_PI/180.0)
#endif
#ifndef RAD_TO_DEGF
#define RAD_TO_DEGF(x) (((float)x)*180.0f/WWMATH_PI)
#endif
#ifndef DEG_TO_RADF
#define DEG_TO_RADF(x) (((float)x)*WWMATH_PI/180.0f)
#endif
/*
** Some simple math functions which work on the built-in types.
** Include the various other header files in the WWMATH library
** in order to get matrices, quaternions, etc.
*/
class WWMath
{
public:
static float Fabs(float val) { return (float)fabs(val); }
static float Sqrt(float val) { return (float)sqrt(val); }
static float Inv_Sqrt(float val) { return 1.0f / (float)sqrt(val); }
static float Sign(float val);
static float Floor(float val) { return (float)floor(val); }
static bool Fast_Is_Float_Positive(const float & val);
static float Random_Float(void);
static float Random_Float(float min,float max);
static float Clamp(float val, float min = 0.0f, float max = 1.0f);
static double Clamp(double val, double min = 0.0f, double max = 1.0f);
static float Wrap(float val, float min = 0.0f, float max = 1.0f);
static double Wrap(double val, double min = 0.0f, double max = 1.0f);
static float Min(float a, float b);
static float Max(float a, float b);
static float Lerp(float a, float b, float lerp );
static double Lerp(double a, double b, float lerp );
static long Float_To_Long(float f);
static long Float_To_Long(double f);
static unsigned char Unit_Float_To_Byte(float f) { return (unsigned char)(f*255.0f); }
static float Byte_To_Unit_Float(unsigned char byte) { return ((float)byte) / 255.0f; }
static bool Is_Valid_Float(float x);
static bool Is_Valid_Double(double x);
};
inline float WWMath::Sign(float val)
{
if (val > 0.0f) {
return +1.0f;
}
if (val < 0.0f) {
return -1.0f;
}
return 0.0f;
}
inline bool WWMath::Fast_Is_Float_Positive(const float & val)
{
return !((*(int *)(&val)) & 0x80000000);
}
inline float WWMath::Random_Float(float min,float max)
{
return Random_Float() * (max-min) + min;
}
inline float WWMath::Clamp(float val, float min /*= 0.0f*/, float max /*= 1.0f*/)
{
if(val < min) return min;
if(val > max) return max;
return val;
}
inline double WWMath::Clamp(double val, double min /*= 0.0f*/, double max /*= 1.0f*/)
{
if(val < min) return min;
if(val > max) return max;
return val;
}
inline float WWMath::Wrap(float val, float min /*= 0.0f*/, float max /*= 1.0f*/)
{
// Implemented as an if rather than a while, to long loops
if ( val >= max ) val -= (max-min);
if ( val < min ) val += (max-min);
if ( val < min ) {
val = min;
}
if ( val > max ) {
val = max;
}
return val;
}
inline double WWMath::Wrap(double val, double min /*= 0.0f*/, double max /*= 1.0f*/)
{
// Implemented as an if rather than a while, to long loops
if ( val >= max ) val -= (max-min);
if ( val < min ) val += (max-min);
if ( val < min ) {
val = min;
}
if ( val > max ) {
val = max;
}
return val;
}
inline float WWMath::Min(float a, float b)
{
if (a<b) return a;
return b;
}
inline float WWMath::Max(float a, float b)
{
if (a>b) return a;
return b;
}
inline float WWMath::Lerp(float a, float b, float lerp )
{
return (a + (b - a)*lerp);
}
inline double WWMath::Lerp(double a, double b, float lerp )
{
return (a + (b - a)*lerp);
}
inline long WWMath::Float_To_Long (float f)
{
#if defined(_MSC_VER) && defined(_M_IX86)
long retval;
__asm fld dword ptr [f]
__asm fistp dword ptr [retval]
return retval;
#else
return (long) f;
#endif
}
inline long WWMath::Float_To_Long (double f)
{
#if defined(_MSC_VER) && defined(_M_IX86)
long retval;
__asm fld qword ptr [f]
__asm fistp dword ptr [retval]
return retval;
#else
return (long) f;
#endif
}
inline bool WWMath::Is_Valid_Float(float x)
{
unsigned long * plong = (unsigned long *)(&x);
unsigned long exponent = ((*plong) & 0x7F800000) >> (32-9);
// if exponent is 0xFF, this is a NAN
if (exponent == 0xFF) {
return false;
}
return true;
}
inline bool WWMath::Is_Valid_Double(double x)
{
unsigned long * plong = (unsigned long *)(&x) + 1;
unsigned long exponent = ((*plong) & 0x7FF00000) >> (32-12);
// if exponent is 0x7FF, this is a NAN
if (exponent == 0x7FF) {
return false;
}
return true;
}
#endif