mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 23:51:41 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
88
Code/Tools/W3DShellExt/External/FindDialog.cpp
vendored
Normal file
88
Code/Tools/W3DShellExt/External/FindDialog.cpp
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// FindDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "wdump.h"
|
||||
#include "FindDialog.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
// Static data.
|
||||
char FindDialog::_FindString [MAX_FIND_STRING_LENGTH + 1] = "";
|
||||
bool FindDialog::_Found;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FindDialog dialog
|
||||
|
||||
|
||||
FindDialog::FindDialog(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(FindDialog::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(FindDialog)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
}
|
||||
|
||||
|
||||
void FindDialog::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(FindDialog)
|
||||
// NOTE: the ClassWizard will add DDX and DDV calls here
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(FindDialog, CDialog)
|
||||
//{{AFX_MSG_MAP(FindDialog)
|
||||
ON_EN_CHANGE(IDC_FIND_STRING, OnChangeFindString)
|
||||
ON_EN_UPDATE(IDC_FIND_STRING, OnUpdateFindString)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FindDialog message handlers
|
||||
|
||||
BOOL FindDialog::OnInitDialog()
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
((CEdit*) GetDlgItem (IDC_FIND_STRING))->SetLimitText (MAX_FIND_STRING_LENGTH);
|
||||
GetDlgItem (IDC_FIND_STRING)->SetWindowText (_FindString);
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
// EXCEPTION: OCX Property Pages should return FALSE
|
||||
}
|
||||
|
||||
|
||||
void FindDialog::OnChangeFindString()
|
||||
{
|
||||
GetDlgItem (IDC_FIND_STRING)->GetWindowText (_FindString, MAX_FIND_STRING_LENGTH);
|
||||
}
|
||||
|
||||
void FindDialog::OnUpdateFindString()
|
||||
{
|
||||
GetDlgItem (IDOK)->EnableWindow (GetDlgItem (IDC_FIND_STRING)->GetWindowTextLength() > 0);
|
||||
}
|
||||
2334
Code/Tools/W3DShellExt/External/chunk_d.cpp
vendored
Normal file
2334
Code/Tools/W3DShellExt/External/chunk_d.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
379
Code/Tools/W3DShellExt/External/matrix3.cpp
vendored
Normal file
379
Code/Tools/W3DShellExt/External/matrix3.cpp
vendored
Normal file
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WW3D PS2 *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/W3DShellExt/External/matrix3.cpp $*
|
||||
* *
|
||||
* Programmer : Kenny Mitchell *
|
||||
* *
|
||||
* Start Date : 11/16/99 *
|
||||
* *
|
||||
* Last Update : 11/16/99 *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Based on Greg Hjelstrom 97 *
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "matrix3.h"
|
||||
#include "matrix3d.h"
|
||||
#include "matrix4.h"
|
||||
#include "quat.h"
|
||||
|
||||
|
||||
/*
|
||||
** Some pre-initialized Matrix3's
|
||||
*/
|
||||
const Matrix3 Matrix3::Identity
|
||||
(
|
||||
1.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f
|
||||
);
|
||||
|
||||
const Matrix3 Matrix3::RotateX90
|
||||
(
|
||||
1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, -1.0f,
|
||||
0.0f, 1.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3 Matrix3::RotateX180
|
||||
(
|
||||
1.0f, 0.0f, 0.0f,
|
||||
0.0f, -1.0f, 0.0f,
|
||||
0.0f, 0.0f, -1.0f
|
||||
);
|
||||
|
||||
const Matrix3 Matrix3::RotateX270
|
||||
(
|
||||
1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f,
|
||||
0.0f, -1.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3 Matrix3::RotateY90
|
||||
(
|
||||
0.0f, 0.0f, 1.0f,
|
||||
0.0f, 1.0f, 0.0f,
|
||||
-1.0f, 0.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3 Matrix3::RotateY180
|
||||
(
|
||||
-1.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, -1.0f
|
||||
);
|
||||
|
||||
const Matrix3 Matrix3::RotateY270
|
||||
(
|
||||
0.0f, 0.0f, -1.0f,
|
||||
0.0f, 1.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3 Matrix3::RotateZ90
|
||||
(
|
||||
0.0f, -1.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f
|
||||
);
|
||||
|
||||
const Matrix3 Matrix3::RotateZ180
|
||||
(
|
||||
-1.0f, 0.0f, 0.0f,
|
||||
0.0f, -1.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f
|
||||
);
|
||||
|
||||
const Matrix3 Matrix3::RotateZ270
|
||||
(
|
||||
0.0f, 1.0f, 0.0f,
|
||||
-1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f
|
||||
);
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* 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.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]));
|
||||
Row[0][1] = (float)(2.0f * (q[0] * q[1] - q[2] * q[3]));
|
||||
Row[0][2] = (float)(2.0f * (q[2] * q[0] + q[1] * q[3]));
|
||||
|
||||
Row[1][0] = (float)(2.0f * (q[0] * q[1] + q[2] * q[3]));
|
||||
Row[1][1] = (float)(1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]));
|
||||
Row[1][2] = (float)(2.0f * (q[1] * q[2] - q[0] * q[3]));
|
||||
|
||||
Row[2][0] = (float)(2.0f * (q[2] * q[0] - q[1] * q[3]));
|
||||
Row[2][1] = (float)(2.0f * (q[1] * q[2] + q[0] * q[3]));
|
||||
Row[2][2] =(float)(1.0f - 2.0f * (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 0
|
||||
if (Vector3::Dot_Product(x,y) > EPSILON) return 0;
|
||||
if (Vector3::Dot_Product(y,z) > EPSILON) return 0;
|
||||
if (Vector3::Dot_Product(z,x) > EPSILON) return 0;
|
||||
|
||||
if (Get_Float_ABS(x.Length() - 1.0f) > EPSILON) return 0;
|
||||
if (Get_Float_ABS(y.Length() - 1.0f) > EPSILON) return 0;
|
||||
if (Get_Float_ABS(z.Length() - 1.0f) > EPSILON) return 0;
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
#if 0
|
||||
x*=Inv_Sqrt(x.Length2());
|
||||
y*=Inv_Sqrt(y.Length2());
|
||||
z*=Inv_Sqrt(z.Length2());
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
910
Code/Tools/W3DShellExt/External/matrix3d.cpp
vendored
Normal file
910
Code/Tools/W3DShellExt/External/matrix3d.cpp
vendored
Normal file
@@ -0,0 +1,910 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Header: /Commando/Code/Tools/W3DShellExt/External/matrix3d.cpp 1 1/02/02 1:18p Moumine_ballo $ */
|
||||
/***********************************************************************************************
|
||||
*** Confidential - Westwood Studios ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WW3D PS2 *
|
||||
* *
|
||||
* File Name : MATRIX3D.CPP *
|
||||
* *
|
||||
* Programmer : Kenny Mitchell *
|
||||
* *
|
||||
* Start Date : 11/16/99 *
|
||||
* *
|
||||
* Last Update : 11/16/99 *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Based on Greg Hjelstrom 97 *
|
||||
* 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 <stdlib.h>
|
||||
#include "vector3.h"
|
||||
#include "matrix3.h"
|
||||
#include "matrix4.h"
|
||||
#include "quat.h"
|
||||
|
||||
// some static matrices which are sometimes useful
|
||||
const Matrix3D Matrix3D::Identity
|
||||
(
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3D Matrix3D::RotateX90
|
||||
(
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, -1.0f,0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3D Matrix3D::RotateX180
|
||||
(
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, -1.0f,0.0f, 0.0f,
|
||||
0.0f, 0.0f,-1.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3D Matrix3D::RotateX270
|
||||
(
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, -1.0f,0.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3D Matrix3D::RotateY90
|
||||
(
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
-1.0f, 0.0f, 0.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3D Matrix3D::RotateY180
|
||||
(
|
||||
-1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, -1.0f,0.0f
|
||||
);
|
||||
|
||||
const Matrix3D Matrix3D::RotateY270
|
||||
(
|
||||
0.0f, 0.0f, -1.0f,0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3D Matrix3D::RotateZ90
|
||||
(
|
||||
0.0f, -1.0f,0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3D Matrix3D::RotateZ180
|
||||
(
|
||||
-1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, -1.0f,0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f
|
||||
);
|
||||
|
||||
const Matrix3D Matrix3D::RotateZ270
|
||||
(
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
-1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f
|
||||
);
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* 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.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]));
|
||||
Row[0][1] = (float)(2.0f * (q[0] * q[1] - q[2] * q[3]));
|
||||
Row[0][2] = (float)(2.0f * (q[2] * q[0] + q[1] * q[3]));
|
||||
|
||||
Row[1][0] = (float)(2.0f * (q[0] * q[1] + q[2] * q[3]));
|
||||
Row[1][1] = (float)(1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]));
|
||||
Row[1][2] = (float)(2.0f * (q[1] * q[2] - q[0] * q[3]));
|
||||
|
||||
Row[2][0] = (float)(2.0f * (q[2] * q[0] - q[1] * q[3]));
|
||||
Row[2][1] = (float)(2.0f * (q[1] * q[2] + q[0] * q[3]));
|
||||
Row[2][2] =(float)(1.0f - 2.0f * (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 atan2f(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 atan2f(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 atan2f(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 = 1.0f / (float)sqrt(dx*dx + dy*dy + dz*dz);
|
||||
len2 = 1.0f / (float)sqrt(dx*dx + dy*dy);
|
||||
|
||||
sinp = dz*len1;
|
||||
cosp = len2*len1;
|
||||
// sinp = 0.0f;
|
||||
// cosp = 1.0f;
|
||||
|
||||
siny = dy*len2;
|
||||
cosy = dx*len2;
|
||||
// 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 = 1.0f / (float)sqrt(dx*dx + dy*dy + dz*dz);
|
||||
len2 = 1.0f / (float)sqrt(dx*dx + dy*dy);
|
||||
|
||||
sinp = dz*len1;
|
||||
cosp = len2*len1;
|
||||
|
||||
siny = dy*len2;
|
||||
cosy = dx*len2;
|
||||
|
||||
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 Matrix3D::Multiply(const Matrix3D & A,const Matrix3D & B,Matrix3D * set_res)
|
||||
{
|
||||
assert(set_res );
|
||||
|
||||
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 != ¢er);
|
||||
assert(set_extent != &extent);
|
||||
|
||||
float tmp;
|
||||
|
||||
// now push them both out by the projections of the original intervals
|
||||
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];
|
||||
tmp = Row[i][j] * extent[j];
|
||||
if (tmp > 0.0f)
|
||||
{
|
||||
(*set_extent)[i] += tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*set_extent)[i] -= tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Matrix3D::Is_Orthogonal -- checks whether this matrix is orthogonal *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 9/16/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
int Matrix3D::Is_Orthogonal(void) const
|
||||
{
|
||||
#if 0
|
||||
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) > EPSILON) return 0;
|
||||
if (Vector3::Dot_Product(y,z) > EPSILON) return 0;
|
||||
if (Vector3::Dot_Product(z,x) > EPSILON) return 0;
|
||||
|
||||
if (Get_Float_ABS(x.Length() - 1.0f) > EPSILON) return 0;
|
||||
if (Get_Float_ABS(y.Length() - 1.0f) > EPSILON) return 0;
|
||||
if (Get_Float_ABS(z.Length() - 1.0f) > EPSILON) return 0;
|
||||
#endif
|
||||
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);
|
||||
|
||||
x*=1.0f / (float)sqrt(x.Length2());
|
||||
y*=1.0f / (float)sqrt(y.Length2());
|
||||
z*=1.0f / (float)sqrt(z.Length2());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void Matrix3D::Multiply(const Matrix3D & A,const Matrix3D & B,Matrix3D * set_res)
|
||||
{
|
||||
assert(set_res );
|
||||
|
||||
#if 0
|
||||
Matrix3D tmpa = A;
|
||||
Matrix3D tmpb = B;
|
||||
*set_res = tmpa * tmpb;
|
||||
#else
|
||||
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];
|
||||
|
||||
#if 1
|
||||
(*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);
|
||||
#else
|
||||
(*set_res)[0][0] = (float)(Aptr->Row[0].X*tmp1 + Aptr->Row[0].Y*tmp2 + Aptr->Row[0].Z*tmp3);
|
||||
(*set_res)[1][0] = (float)(Aptr->Row[1].X*tmp1 + Aptr->Row[1].Y*tmp2 + Aptr->Row[1].Z*tmp3);
|
||||
(*set_res)[2][0] = (float)(Aptr->Row[2].X*tmp1 + Aptr->Row[2].Y*tmp2 + Aptr->Row[2].Z*tmp3);
|
||||
#endif
|
||||
|
||||
// printf("tmp1 = %f\n",tmp1);
|
||||
// printf("B[0][0] = %f\n",B[0][0]);
|
||||
|
||||
// printf("Row A: %f %f %f\n",Aptr->Row[0].X,Aptr->Row[0].Y,Aptr->Row[0].Z);
|
||||
// printf("Col B: %f %f %f\n",tmp1,tmp2,tmp3);
|
||||
// printf("tmp1 = %f\n",tmp1);
|
||||
// printf("B[0][0] = %f\n",B[0][0]);
|
||||
// (*set_res)[0][0] = Aptr->Row[0].X * tmp1 + Aptr->Row[0].Y * tmp2 + Aptr->Row[0].Z * tmp3;
|
||||
|
||||
// printf("result: %f\n",(*set_res)[0][0]);
|
||||
|
||||
//print_matrix(*set_res);
|
||||
|
||||
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);
|
||||
|
||||
//print_matrix(*set_res);
|
||||
|
||||
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);
|
||||
|
||||
//print_matrix(*set_res);
|
||||
|
||||
tmp1 = B[0][3];
|
||||
tmp2 = B[1][3];
|
||||
tmp3 = B[2][3];
|
||||
|
||||
(*set_res)[0][3] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3 + (*Aptr)[0][3]);
|
||||
(*set_res)[1][3] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3 + (*Aptr)[1][3]);
|
||||
(*set_res)[2][3] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3 + (*Aptr)[2][3]);
|
||||
|
||||
//print_matrix(*set_res);
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/***********************************************************************************************
|
||||
* 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);
|
||||
}
|
||||
|
||||
288
Code/Tools/W3DShellExt/External/matrix4.cpp
vendored
Normal file
288
Code/Tools/W3DShellExt/External/matrix4.cpp
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WW3D PS2 *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/W3DShellExt/External/matrix4.cpp $*
|
||||
* *
|
||||
* Programmer : Kenny Mitchell *
|
||||
* *
|
||||
* Start Date : 11/16/99 *
|
||||
* *
|
||||
* Last Update : 11/16/99 *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Based on Greg Hjelstrom 97 *
|
||||
* Functions: *
|
||||
* Matrix4::Multiply -- Multiply two Matrix4's together *
|
||||
* Matrix4::Multiply -- Multiply a Matrix3D * Matrix4 *
|
||||
* Matrix4::Multiply -- Multiply a Matrix4 * Matrix3D *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "matrix4.h"
|
||||
|
||||
|
||||
#if 0
|
||||
/***********************************************************************************************
|
||||
* 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
|
||||
}
|
||||
|
||||
/***********************************************************************************************
|
||||
* Set_Perspective -- Sets perspective matrix *
|
||||
// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built
|
||||
// from the field-of-view (fov, in y), aspect ratio, near plane (D),
|
||||
// and far plane (F).
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/16/99 KJM: Created. *
|
||||
*=============================================================================================*/
|
||||
void Matrix4::Set_Perspective
|
||||
(
|
||||
Matrix4* m,
|
||||
float fFOV,
|
||||
float ScreenWidth,
|
||||
float ScreenHeight,
|
||||
float fNearPlane,
|
||||
float fFarPlane
|
||||
)
|
||||
{
|
||||
float w;
|
||||
float h;
|
||||
float Q,Q2;
|
||||
|
||||
Q=DEGTORAD*0.5f;
|
||||
|
||||
float c = cosf(fFOV*Q);
|
||||
float s = sinf(fFOV*Q);
|
||||
|
||||
//printf("sincos %f %f\n",c,s);
|
||||
Q=0.000244140625f; // 1/4096
|
||||
|
||||
w = (ScreenWidth*Q);
|
||||
h = (ScreenHeight*Q);
|
||||
|
||||
Q = s/(1.0f - (fNearPlane/fFarPlane));
|
||||
Q2 = -Q*fNearPlane;
|
||||
|
||||
m->Make_Identity();
|
||||
|
||||
m->Row[0][0]= c*w;
|
||||
m->Row[1][1]= -c*h;
|
||||
m->Row[2][2]= Q;
|
||||
m->Row[2][3]= s;//1.0f;
|
||||
m->Row[3][2]= Q2;
|
||||
}
|
||||
|
||||
|
||||
void Matrix4::Set_View_Matrix
|
||||
(
|
||||
Matrix4* m,
|
||||
Vector3& vFrom,
|
||||
Vector3& vAt,
|
||||
Vector3& vWorldUp
|
||||
)
|
||||
{
|
||||
Vector3 vView;
|
||||
Vector3 vUp;
|
||||
Vector3 vRight;
|
||||
float inv_length;
|
||||
float dot_product;
|
||||
|
||||
// Get the z basis vector, which points straight ahead. This is the
|
||||
// difference from the eyepoint to the lookat point.
|
||||
vView=vAt-vFrom;
|
||||
|
||||
inv_length=Inv_Sqrt(vView.Length2());
|
||||
|
||||
// Normalize the z basis vector
|
||||
vView*=inv_length;
|
||||
|
||||
// Get the dot product, and calculate the projection of the z basis
|
||||
// vector onto the up vector. The projection is the y basis vector.
|
||||
dot_product=Vector3::Dot_Product(vWorldUp,vView);
|
||||
|
||||
// vUp = vWorldUp - fDotProduct * vView
|
||||
vUp=vWorldUp-(dot_product*vView);
|
||||
|
||||
inv_length=Inv_Sqrt(vUp.Length2());
|
||||
|
||||
// Normalize the y basis vector
|
||||
vUp*=inv_length;
|
||||
|
||||
// The x basis vector is found simply with the cross product of the y
|
||||
// and z basis vectors
|
||||
Vector3::Cross_Product(vUp,vView,&vRight);
|
||||
|
||||
// Start building the matrix. The first three rows contains the basis
|
||||
// vectors used to rotate the view to point at the lookat point
|
||||
m->Row[0][0] = vRight.x; m->Row[0][1] = vUp.x; m->Row[0][2] = vView.x; m->Row[0][3] = 0.0f;
|
||||
m->Row[1][0] = vRight.y; m->Row[1][1] = vUp.y; m->Row[1][2] = vView.y; m->Row[1][3] = 0.0f;
|
||||
m->Row[2][0] = vRight.z; m->Row[2][1] = vUp.z; m->Row[2][2] = vView.z; m->Row[2][3] = 0.0f;
|
||||
|
||||
// Do the translation values (rotations are still about the eyepoint)
|
||||
m->Row[3][0] = - (vFrom * vRight);
|
||||
m->Row[3][1] = - (vFrom * vUp);
|
||||
m->Row[3][2] = - (vFrom * vView);
|
||||
m->Row[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
void Matrix4::Print_Matrix() const
|
||||
{
|
||||
printf("%f %f %f %f\n",Row[0][0],Row[0][1],Row[0][2],Row[0][3]);
|
||||
printf("%f %f %f %f\n",Row[1][0],Row[1][1],Row[1][2],Row[1][3]);
|
||||
printf("%f %f %f %f\n",Row[2][0],Row[2][1],Row[2][2],Row[2][3]);
|
||||
printf("%f %f %f %f\n",Row[3][0],Row[3][1],Row[3][2],Row[3][3]);
|
||||
}
|
||||
|
||||
#endif
|
||||
756
Code/Tools/W3DShellExt/External/quat.cpp
vendored
Normal file
756
Code/Tools/W3DShellExt/External/quat.cpp
vendored
Normal file
@@ -0,0 +1,756 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Header: /Commando/Code/Tools/W3DShellExt/External/quat.cpp 1 1/02/02 1:18p Moumine_ballo $ */
|
||||
/***********************************************************************************************
|
||||
*** 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 <stdio.h>
|
||||
//#include <iostream.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
//#include "math_util.h"
|
||||
#include "quat.h"
|
||||
#include "matrix3d.h"
|
||||
#include "matrix4.h"
|
||||
|
||||
#define SLERP_EPSILON 0.001f
|
||||
|
||||
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 = 1.0f / (float)sqrt(X * X + Y * Y + Z * Z + W * W);
|
||||
|
||||
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.0f)
|
||||
{
|
||||
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 * asinf(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.0f)
|
||||
{
|
||||
cos_t = -cos_t;
|
||||
qflip = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qflip = false;
|
||||
}
|
||||
|
||||
if (1.0f - cos_t < SLERP_EPSILON)
|
||||
{
|
||||
|
||||
// if q is very close to p, just linearly interpolate
|
||||
// between the two.
|
||||
beta = 1.0f - (float)alpha;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// normal slerp!
|
||||
theta = acosf(cos_t);
|
||||
sin_t = sinf(theta);
|
||||
oo_sin_t = 1.0f / 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);
|
||||
|
||||
// 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.0f)
|
||||
{
|
||||
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 = acosf(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.0f - alpha;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// normal slerp!
|
||||
oo_sin_t = 1.0f / slerpinfo->Theta;
|
||||
beta = sinf(slerpinfo->Theta - alpha*slerpinfo->Theta) * oo_sin_t;
|
||||
alpha = sinf(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.0f - alpha;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// normal slerp!
|
||||
oo_sin_t = 1.0f / slerpinfo->Theta;
|
||||
beta = sinf(slerpinfo->Theta - alpha*slerpinfo->Theta) * oo_sin_t;
|
||||
alpha = sinf(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 = (float)sqrt(tr + 1.0f);
|
||||
q[3] = s * 0.5f;
|
||||
s = 0.5f / 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 = (float)sqrt((mat[i][i] - (mat[j][j] + mat[k][k])) + 1.0f);
|
||||
|
||||
q[i] = s * 0.5f;
|
||||
if (s != 0.0f)
|
||||
{
|
||||
s = 0.5f / 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.0f)
|
||||
{
|
||||
|
||||
s = (float)sqrt(tr + 1.0f);
|
||||
q[3] = s * 0.5f;
|
||||
s = 0.5f / 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 = (float)sqrt( (mat[i][i] - (mat[j][j]+mat[k][k])) + 1.0f);
|
||||
|
||||
q[i] = s * 0.5f;
|
||||
|
||||
if (s != 0.0f)
|
||||
{
|
||||
s = 0.5f/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.0f)
|
||||
{
|
||||
|
||||
s = (float)sqrt(tr + 1.0f);
|
||||
q[3] = s * 0.5f;
|
||||
s = 0.5f / 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 = (float)sqrt( (mat[i][i] - (mat[j][j]+mat[k][k])) + 1.0f);
|
||||
|
||||
q[i] = s * 0.5f;
|
||||
if (s != 0.0f)
|
||||
{
|
||||
s = 0.5f/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] = (1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]));
|
||||
m[0][1] = (2.0f * (q[0] * q[1] - q[2] * q[3]));
|
||||
m[0][2] = (2.0f * (q[2] * q[0] + q[1] * q[3]));
|
||||
|
||||
m[1][0] = (2.0f * (q[0] * q[1] + q[2] * q[3]));
|
||||
m[1][1] = (1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]));
|
||||
m[1][2] = (2.0f * (q[1] * q[2] - q[0] * q[3]));
|
||||
|
||||
m[2][0] = (2.0f * (q[2] * q[0] - q[1] * q[3]));
|
||||
m[2][1] = (2.0f * (q[1] * q[2] + q[0] * q[3]));
|
||||
m[2][2] =(1.0f - 2.0f * (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] = (1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]));
|
||||
m[0][1] = (2.0f * (q[0] * q[1] - q[2] * q[3]));
|
||||
m[0][2] = (2.0f * (q[2] * q[0] + q[1] * q[3]));
|
||||
|
||||
m[1][0] = (2.0f * (q[0] * q[1] + q[2] * q[3]));
|
||||
m[1][1] = (1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]));
|
||||
m[1][2] = (2.0f * (q[1] * q[2] - q[0] * q[3]));
|
||||
|
||||
m[2][0] = (2.0f * (q[2] * q[0] - q[1] * q[3]));
|
||||
m[2][1] = (2.0f * (q[1] * q[2] + q[0] * q[3]));
|
||||
m[2][2] =(1.0f - 2.0f * (q[1] * q[1] + q[0] * q[0]));
|
||||
|
||||
// no translation
|
||||
m[0][3] = m[1][3] = m[2][3] = 0.0f;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
// JAC - Modified to create matrix already transposed
|
||||
Matrix4 Build_Matrix4(const Quaternion & q)
|
||||
{
|
||||
Matrix4 m;
|
||||
|
||||
// initialize the rotation sub-matrix
|
||||
m[0][0] = (1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]));
|
||||
m[0][1] = (2.0f * (q[0] * q[1] - q[2] * q[3]));
|
||||
m[0][2] = (2.0f * (q[2] * q[0] + q[1] * q[3]));
|
||||
|
||||
m[1][0] = (2.0f * (q[0] * q[1] + q[2] * q[3]));
|
||||
m[1][1] = (1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]));
|
||||
m[1][2] = (2.0f * (q[1] * q[2] - q[0] * q[3]));
|
||||
|
||||
m[2][0] = (2.0f * (q[2] * q[0] - q[1] * q[3]));
|
||||
m[2][1] = (2.0f * (q[1] * q[2] + q[0] * q[3]));
|
||||
m[2][2] = (1.0f - 2.0f * (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)
|
||||
{
|
||||
float t, z;
|
||||
float d = (float)sqrt(x * x + y * y);
|
||||
|
||||
// Commented out code to get it to compile. Kludge but this code shouldn't be needed here
|
||||
if (d < r * ((float)sqrt(2.0f)/(2.0f))) // inside sphere
|
||||
{
|
||||
z = (float)sqrt(r * r - d * d);
|
||||
}
|
||||
else
|
||||
{ // on hyperbola
|
||||
t = r / (float)sqrt(2.0f);
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
261
Code/Tools/W3DShellExt/External/quat.h
vendored
Normal file
261
Code/Tools/W3DShellExt/External/quat.h
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Header: /Commando/Code/Tools/W3DShellExt/External/quat.h 1 1/02/02 1:18p Moumine_ballo $ */
|
||||
/***************************************************************************
|
||||
*** Confidential - Westwood Studios ***
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : WW3D PS2 *
|
||||
* *
|
||||
* File Name : QUAT.H *
|
||||
* *
|
||||
* Programmer : Kenny Mitchell *
|
||||
* *
|
||||
* Start Date : 11/16/99 *
|
||||
* *
|
||||
* Last Update : 11/16/99 *
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* Based on Greg Hjelstrom 97 *
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef QUAT_H
|
||||
#define QUAT_H
|
||||
|
||||
#include "matrix3.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.0f, float b = 0.0f, float c = 0.0f, float d = 1.0f) { 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 (float)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
|
||||
{
|
||||
#if 1
|
||||
return (1);
|
||||
#else
|
||||
return ( Is_Valid_Float(X) &&
|
||||
Is_Valid_Float(Y) &&
|
||||
Is_Valid_Float(Z) &&
|
||||
Is_Valid_Float(W) );
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* QUAT_H */
|
||||
|
||||
|
||||
|
||||
924
Code/Tools/W3DShellExt/External/rawfilem.cpp
vendored
Normal file
924
Code/Tools/W3DShellExt/External/rawfilem.cpp
vendored
Normal file
@@ -0,0 +1,924 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : G *
|
||||
* *
|
||||
* $Archive:: /G/wdump/RAWFILEM.CPP $*
|
||||
* *
|
||||
* $Author:: Eric_c $*
|
||||
* *
|
||||
* $Modtime:: 7/28/97 3:36p $*
|
||||
* *
|
||||
* $Revision:: 3 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* RawFileMClass::Bias -- Bias a file with a specific starting position and length. *
|
||||
* RawFileMClass::Close -- Perform a closure of the file. *
|
||||
* RawFileMClass::Create -- Creates an empty file. *
|
||||
* RawFileMClass::Delete -- Deletes the file object from the disk. *
|
||||
* RawFileMClass::Error -- Handles displaying a file error message. *
|
||||
* RawFileMClass::Get_Date_Time -- Gets the date and time the file was last modified. *
|
||||
* RawFileMClass::Is_Available -- Checks to see if the specified file is available to open. *
|
||||
* RawFileMClass::Open -- Assigns name and opens file in one operation. *
|
||||
* RawFileMClass::Open -- Opens the file object with the rights specified. *
|
||||
* RawFileMClass::RawFileMClass -- Simple constructor for a file object. *
|
||||
* RawFileMClass::Raw_Seek -- Performs a seek on the unbiased file *
|
||||
* RawFileMClass::Read -- Reads the specified number of bytes into a memory buffer. *
|
||||
* RawFileMClass::Seek -- Reposition the file pointer as indicated. *
|
||||
* RawFileMClass::Set_Date_Time -- Sets the date and time the file was last modified. *
|
||||
* RawFileMClass::Set_Name -- Manually sets the name for a file object. *
|
||||
* RawFileMClass::Size -- Determines size of file (in bytes). *
|
||||
* RawFileMClass::Write -- Writes the specified data to the buffer specified. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "always.h"
|
||||
#include "rawfilem.h"
|
||||
#include <direct.h>
|
||||
#include <share.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Error -- Handles displaying a file error message. *
|
||||
* *
|
||||
* Display an error message as indicated. If it is allowed to retry, then pressing a key *
|
||||
* will return from this function. Otherwise, it will exit the program with "exit()". *
|
||||
* *
|
||||
* INPUT: error -- The error number (same as the DOSERR.H error numbers). *
|
||||
* *
|
||||
* canretry -- Can this routine exit normally so that retrying can occur? If this is *
|
||||
* false, then the program WILL exit in this routine. *
|
||||
* *
|
||||
* filename -- Optional filename to report with this error. If no filename is *
|
||||
* supplied, then no filename is listed in the error message. *
|
||||
* *
|
||||
* OUTPUT: none, but this routine might not return at all if the "canretry" parameter is *
|
||||
* false or the player pressed ESC. *
|
||||
* *
|
||||
* WARNINGS: This routine may not return at all. It handles being in text mode as well as *
|
||||
* if in a graphic mode. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/17/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void RawFileMClass::Error(int, int, char const * )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::RawFileMClass -- Simple constructor for a file object. *
|
||||
* *
|
||||
* This constructor is called when a file object is created with a supplied filename, but *
|
||||
* not opened at the same time. In this case, an assumption is made that the supplied *
|
||||
* filename is a constant string. A duplicate of the filename string is not created since *
|
||||
* it would be wasteful in that case. *
|
||||
* *
|
||||
* INPUT: filename -- The filename to assign to this file object. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/17/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
RawFileMClass::RawFileMClass(char const * filename) :
|
||||
Rights(0),
|
||||
BiasStart(0),
|
||||
BiasLength(-1),
|
||||
Handle(NULL_HANDLE),
|
||||
Filename(filename),
|
||||
Date(0),
|
||||
Time(0),
|
||||
Allocated(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Set_Name -- Manually sets the name for a file object. *
|
||||
* *
|
||||
* This routine will set the name for the file object to the name specified. This name is *
|
||||
* duplicated in free store. This allows the supplied name to be a temporarily constructed *
|
||||
* text string. Setting the name in this fashion doesn't affect the closed or opened state *
|
||||
* of the file. *
|
||||
* *
|
||||
* INPUT: filename -- The filename to assign to this file object. *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to the allocated copy of this filename. This pointer is *
|
||||
* guaranteed to remain valid for the duration of this file object or until the name *
|
||||
* is changed -- whichever is sooner. *
|
||||
* *
|
||||
* WARNINGS: Because of the allocation this routine must perform, memory could become *
|
||||
* fragmented. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/17/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
char const * RawFileMClass::Set_Name(char const * filename)
|
||||
{
|
||||
if (Filename != NULL && Allocated) {
|
||||
free((char *)Filename);
|
||||
Filename = NULL;
|
||||
Allocated = false;
|
||||
}
|
||||
|
||||
if (filename == NULL) return(NULL);
|
||||
|
||||
Bias(0);
|
||||
|
||||
Filename = strdup(filename);
|
||||
if (Filename == NULL) {
|
||||
Error(ENOMEM, false, filename);
|
||||
}
|
||||
Allocated = true;
|
||||
return(Filename);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Open -- Assigns name and opens file in one operation. *
|
||||
* *
|
||||
* This routine will assign the specified filename to the file object and open it at the *
|
||||
* same time. If the file object was already open, then it will be closed first. If the *
|
||||
* file object was previously assigned a filename, then it will be replaced with the new *
|
||||
* name. Typically, this routine is used when an anonymous file object has been crated and *
|
||||
* now it needs to be assigned a name and opened. *
|
||||
* *
|
||||
* INPUT: filename -- The filename to assign to this file object. *
|
||||
* *
|
||||
* rights -- The open file access rights to use. *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file opened? The return value of this is moot, since the open file *
|
||||
* is designed to never return unless it succeeded. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/17/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int RawFileMClass::Open(char const * filename, int rights)
|
||||
{
|
||||
Set_Name(filename);
|
||||
return(Open(rights));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Open -- Opens the file object with the rights specified. *
|
||||
* *
|
||||
* This routine is used to open the specified file object with the access rights indicated. *
|
||||
* This only works if the file has already been assigned a filename. It is guaranteed, by *
|
||||
* the error handler, that this routine will always return with success. *
|
||||
* *
|
||||
* INPUT: rights -- The file access rights to use when opening this file. This is a *
|
||||
* combination of READ and/or WRITE bit flags. *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file opened successfully? This will always return true by reason of *
|
||||
* the error handler. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/17/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int RawFileMClass::Open(int rights)
|
||||
{
|
||||
Close();
|
||||
|
||||
/*
|
||||
** Verify that there is a filename associated with this file object. If not, then this is a
|
||||
** big error condition.
|
||||
*/
|
||||
if (Filename == NULL) {
|
||||
Error(ENOENT, false);
|
||||
}
|
||||
|
||||
/*
|
||||
** Record the access rights used for this open call. These rights will be used if the
|
||||
** file object is duplicated.
|
||||
*/
|
||||
Rights = rights;
|
||||
|
||||
/*
|
||||
** Repetitively try to open the file. Abort if a fatal error condition occurs.
|
||||
*/
|
||||
for (;;) {
|
||||
|
||||
/*
|
||||
** Try to open the file according to the access rights specified.
|
||||
*/
|
||||
switch (rights) {
|
||||
|
||||
/*
|
||||
** If the access rights are not recognized, then report this as
|
||||
** an invalid access code.
|
||||
*/
|
||||
default:
|
||||
Error_Number = EINVAL;
|
||||
break;
|
||||
|
||||
case READ:
|
||||
Handle = CreateFileA(Filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
break;
|
||||
|
||||
case WRITE:
|
||||
Handle = CreateFileA(Filename, GENERIC_WRITE, 0,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
break;
|
||||
|
||||
case READ|WRITE:
|
||||
Handle = CreateFileA(Filename, GENERIC_READ | GENERIC_WRITE, 0,
|
||||
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** Biased files must be positioned past the bias start position.
|
||||
*/
|
||||
if (BiasStart != 0 || BiasLength != -1) {
|
||||
Seek(0, SEEK_SET);
|
||||
}
|
||||
|
||||
/*
|
||||
** If the handle indicates the file is not open, then this is an error condition.
|
||||
** For the case of the file cannot be found, then allow a retry. All other cases
|
||||
** are fatal.
|
||||
*/
|
||||
if (Handle == NULL_HANDLE) {
|
||||
|
||||
return(false);
|
||||
// Error(GetLastError(), false, Filename);
|
||||
// continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Is_Available -- Checks to see if the specified file is available to open. *
|
||||
* *
|
||||
* This routine will examine the disk system to see if the specified file can be opened *
|
||||
* or not. Use this routine before opening a file in order to make sure that is available *
|
||||
* or to perform other necessary actions. *
|
||||
* *
|
||||
* INPUT: force -- Should this routine keep retrying until the file becomes available? If *
|
||||
* in this case it doesn't become available, then the program will abort. *
|
||||
* *
|
||||
* OUTPUT: bool; Is the file available to be opened? *
|
||||
* *
|
||||
* WARNINGS: Depending on the parameter passed in, this routine may never return. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
bool RawFileMClass::Is_Available(int forced)
|
||||
{
|
||||
if (Filename == NULL) return(false);
|
||||
|
||||
/*
|
||||
** If the file is already open, then is must have already passed the availability check.
|
||||
** Return true in this case.
|
||||
*/
|
||||
if (Is_Open()) return(true);
|
||||
|
||||
/*
|
||||
** If this is a forced check, then go through the normal open channels, since those
|
||||
** channels ensure that the file must exist.
|
||||
*/
|
||||
if (forced) {
|
||||
RawFileMClass::Open(READ);
|
||||
RawFileMClass::Close();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform a raw open of the file. If this open fails for ANY REASON, including a missing
|
||||
** CD-ROM, this routine will return a failure condition. In all but the missing file
|
||||
** condition, go through the normal error recover channels.
|
||||
*/
|
||||
for (;;) {
|
||||
|
||||
Handle = CreateFileA(Filename, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (Handle == NULL_HANDLE) {
|
||||
return(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** Since the file could be opened, then close it and return that the file exists.
|
||||
*/
|
||||
if (!CloseHandle(Handle)) {
|
||||
Error(GetLastError(), false, Filename);
|
||||
}
|
||||
Handle = NULL_HANDLE;
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Close -- Perform a closure of the file. *
|
||||
* *
|
||||
* Close the file object. In the rare case of an error, handle it as appropriate. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: Some rare error conditions may cause this routine to abort the program. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void RawFileMClass::Close(void)
|
||||
{
|
||||
/*
|
||||
** If the file is open, then close it. If the file is already closed, then just return. This
|
||||
** isn't considered an error condition.
|
||||
*/
|
||||
if (Is_Open()) {
|
||||
|
||||
/*
|
||||
** Try to close the file. If there was an error (who knows what that could be), then
|
||||
** call the error routine.
|
||||
*/
|
||||
if (!CloseHandle(Handle)) {
|
||||
Error(GetLastError(), false, Filename);
|
||||
}
|
||||
|
||||
/*
|
||||
** At this point the file must have been closed. Mark the file as empty and return.
|
||||
*/
|
||||
Handle = NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Read -- Reads the specified number of bytes into a memory buffer. *
|
||||
* *
|
||||
* This routine will read the specified number of bytes and place the data into the buffer *
|
||||
* indicated. It is legal to call this routine with a request for more bytes than are in *
|
||||
* the file. This condition can result in fewer bytes being read than requested. Determine *
|
||||
* this by examining the return value. *
|
||||
* *
|
||||
* INPUT: buffer -- Pointer to the buffer to read data into. If NULL is passed, no read *
|
||||
* is performed. *
|
||||
* *
|
||||
* size -- The number of bytes to read. If NULL is passed, then no read is *
|
||||
* performed. *
|
||||
* *
|
||||
* OUTPUT: Returns with the number of bytes read into the buffer. If this number is less *
|
||||
* than requested, it indicates that the file has been exhausted. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int RawFileMClass::Read(void * buffer, int size)
|
||||
{
|
||||
long bytesread = 0; // Running count of the number of bytes read into the buffer.
|
||||
int opened = false; // Was the file opened by this routine?
|
||||
|
||||
/*
|
||||
** If the file isn't opened, open it. This serves as a convenience
|
||||
** for the programmer.
|
||||
*/
|
||||
if (!Is_Open()) {
|
||||
|
||||
/*
|
||||
** The error check here is moot. Open will never return unless it succeeded.
|
||||
*/
|
||||
if (!Open(READ)) {
|
||||
return(0);
|
||||
}
|
||||
opened = true;
|
||||
}
|
||||
|
||||
/*
|
||||
** A biased file has the requested read length limited to the bias length of
|
||||
** the file.
|
||||
*/
|
||||
if (BiasLength != -1) {
|
||||
int remainder = BiasLength - Seek(0);
|
||||
size = size < remainder ? size : remainder;
|
||||
}
|
||||
|
||||
long total = 0;
|
||||
while (size > 0) {
|
||||
bytesread = 0;
|
||||
if (!ReadFile(Handle, buffer, size, &(unsigned long&)bytesread, NULL)) {
|
||||
size -= bytesread;
|
||||
total += bytesread;
|
||||
Error(GetLastError(), true, Filename);
|
||||
continue;
|
||||
}
|
||||
size -= bytesread;
|
||||
total += bytesread;
|
||||
if (bytesread == 0) break;
|
||||
}
|
||||
bytesread = total;
|
||||
|
||||
/*
|
||||
** Close the file if it was opened by this routine and return
|
||||
** the actual number of bytes read into the buffer.
|
||||
*/
|
||||
if (opened) Close();
|
||||
return(bytesread);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Write -- Writes the specified data to the buffer specified. *
|
||||
* *
|
||||
* This routine will write the data specified to the file. *
|
||||
* *
|
||||
* INPUT: buffer -- The buffer that holds the data to write. *
|
||||
* *
|
||||
* size -- The number of bytes to write to the file. *
|
||||
* *
|
||||
* OUTPUT: Returns with the number of bytes written to the file. This routine catches the *
|
||||
* case of a disk full condition, so this routine will always return with the number *
|
||||
* matching the size request. *
|
||||
* *
|
||||
* WARNINGS: A fatal file condition could cause this routine to never return. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int RawFileMClass::Write(void const * buffer, int size)
|
||||
{
|
||||
long bytesread = 0;
|
||||
int opened = false; // Was the file manually opened?
|
||||
|
||||
/*
|
||||
** Check to open status of the file. If the file is open, then merely write to
|
||||
** it. Otherwise, open the file for writing and then close the file when the
|
||||
** output is finished.
|
||||
*/
|
||||
if (!Is_Open()) {
|
||||
if (!Open(WRITE)) {
|
||||
return(0);
|
||||
}
|
||||
opened = true;
|
||||
}
|
||||
|
||||
if (!WriteFile(Handle, buffer, size, &(unsigned long&)bytesread, NULL)) {
|
||||
Error(GetLastError(), false, Filename);
|
||||
}
|
||||
|
||||
/*
|
||||
** Fixup the bias length if necessary.
|
||||
*/
|
||||
if (BiasLength != -1) {
|
||||
if (Raw_Seek(0) > BiasStart+BiasLength) {
|
||||
BiasLength = Raw_Seek(0) - BiasStart;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If this routine had to open the file, then close it before returning.
|
||||
*/
|
||||
if (opened) {
|
||||
Close();
|
||||
}
|
||||
|
||||
/*
|
||||
** Return with the number of bytes written. This will always be the number of bytes
|
||||
** requested, since the case of the disk being full is caught by this routine.
|
||||
*/
|
||||
return(bytesread);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Seek -- Reposition the file pointer as indicated. *
|
||||
* *
|
||||
* Use this routine to move the filepointer to the position indicated. It can move either *
|
||||
* relative to current position or absolute from the beginning or ending of the file. This *
|
||||
* routine will only return if it successfully performed the seek. *
|
||||
* *
|
||||
* INPUT: pos -- The position to seek to. This is interpreted as relative to the position *
|
||||
* indicated by the "dir" parameter. *
|
||||
* *
|
||||
* dir -- The relative position to relate the seek to. This can be either SEEK_SET *
|
||||
* for the beginning of the file, SEEK_CUR for the current position, or *
|
||||
* SEEK_END for the end of the file. *
|
||||
* *
|
||||
* OUTPUT: This routine returns the position that the seek ended up at. *
|
||||
* *
|
||||
* WARNINGS: If there was a file error, then this routine might never return. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int RawFileMClass::Seek(int pos, int dir)
|
||||
{
|
||||
|
||||
/*
|
||||
** A file that is biased will have a seek operation modified so that the file appears to
|
||||
** exist only within the bias range. All bytes outside of this range appear to be
|
||||
** non-existant.
|
||||
*/
|
||||
if (BiasLength != -1) {
|
||||
switch (dir) {
|
||||
case SEEK_SET:
|
||||
if (pos > BiasLength) {
|
||||
pos = BiasLength;
|
||||
}
|
||||
pos += BiasStart;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
dir = SEEK_SET;
|
||||
pos += BiasStart + BiasLength;
|
||||
// pos = (pos <= BiasStart+BiasLength) ? pos : BiasStart+BiasLength;
|
||||
// pos = (pos >= BiasStart) ? pos : BiasStart;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform the modified raw seek into the file.
|
||||
*/
|
||||
long newpos = Raw_Seek(pos, dir) - BiasStart;
|
||||
|
||||
/*
|
||||
** Perform a final double check to make sure the file position fits with the bias range.
|
||||
*/
|
||||
if (newpos < 0) {
|
||||
newpos = Raw_Seek(BiasStart, SEEK_SET) - BiasStart;
|
||||
}
|
||||
if (newpos > BiasLength) {
|
||||
newpos = Raw_Seek(BiasStart+BiasLength, SEEK_SET) - BiasStart;
|
||||
}
|
||||
return(newpos);
|
||||
}
|
||||
|
||||
/*
|
||||
** If the file is not biased in any fashion, then the normal seek logic will
|
||||
** work just fine.
|
||||
*/
|
||||
return(Raw_Seek(pos, dir));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Size -- Determines size of file (in bytes). *
|
||||
* *
|
||||
* Use this routine to determine the size of the file. The file must exist or this is an *
|
||||
* error condition. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the number of bytes in the file. *
|
||||
* *
|
||||
* WARNINGS: This routine handles error conditions and will not return unless the file *
|
||||
* exists and can successfully be queried for file length. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int RawFileMClass::Size(void)
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
/*
|
||||
** A biased file already has its length determined.
|
||||
*/
|
||||
if (BiasLength != -1) {
|
||||
return(BiasLength);
|
||||
}
|
||||
|
||||
/*
|
||||
** If the file is open, then proceed normally.
|
||||
*/
|
||||
if (Is_Open()) {
|
||||
|
||||
size = GetFileSize(Handle, NULL);
|
||||
|
||||
/*
|
||||
** If there was in internal error, then call the error function.
|
||||
*/
|
||||
if (size == 0xFFFFFFFF) {
|
||||
Error(GetLastError(), false, Filename);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
** If the file wasn't open, then open the file and call this routine again. Count on
|
||||
** the fact that the open function must succeed.
|
||||
*/
|
||||
if (Open()) {
|
||||
size = Size();
|
||||
|
||||
/*
|
||||
** Since we needed to open the file we must remember to close the file when the
|
||||
** size has been determined.
|
||||
*/
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
BiasLength = size-BiasStart;
|
||||
return(BiasLength);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Create -- Creates an empty file. *
|
||||
* *
|
||||
* This routine will create an empty file from the file object. The file object's filename *
|
||||
* must already have been assigned before this routine will function. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file successfully created? This routine will always return true. *
|
||||
* *
|
||||
* WARNINGS: A fatal error condition could occur with this routine. Especially if the disk *
|
||||
* is full or a read-only media was selected. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int RawFileMClass::Create(void)
|
||||
{
|
||||
Close();
|
||||
if (Open(WRITE)) {
|
||||
|
||||
/*
|
||||
** A biased file must be at least as long as the bias offset. Seeking to the
|
||||
** appropriate start offset has the effect of lengthening the file to the
|
||||
** correct length.
|
||||
*/
|
||||
if (BiasLength != -1) {
|
||||
Seek(0, SEEK_SET);
|
||||
}
|
||||
|
||||
Close();
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Delete -- Deletes the file object from the disk. *
|
||||
* *
|
||||
* This routine will delete the file object from the disk. If the file object doesn't *
|
||||
* exist, then this routine will return as if it had succeeded (since the effect is the *
|
||||
* same). *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file deleted? If the file was already missing, the this value will *
|
||||
* be false. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int RawFileMClass::Delete(void)
|
||||
{
|
||||
/*
|
||||
** If the file was open, then it must be closed first.
|
||||
*/
|
||||
Close();
|
||||
|
||||
/*
|
||||
** If there is no filename associated with this object, then this indicates a fatal error
|
||||
** condition. Report this and abort.
|
||||
*/
|
||||
if (!Filename) {
|
||||
Error(ENOENT, false);
|
||||
}
|
||||
|
||||
/*
|
||||
** Repetitively try to delete the file if possible. Either return with success, or
|
||||
** abort the program with an error.
|
||||
*/
|
||||
for (;;) {
|
||||
|
||||
/*
|
||||
** If the file is already missing, then return with this fact. No action is necessary.
|
||||
** This can occur as this section loops if the file exists on a floppy and the floppy
|
||||
** was removed, the file deleted on another machine, and then the floppy was
|
||||
** reinserted. Admittedly, this is a rare case, but is handled here.
|
||||
*/
|
||||
if (!Is_Available()) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
if (!DeleteFile(Filename)) {
|
||||
Error(GetLastError(), false, Filename);
|
||||
return(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** DOS reports that the file was successfully deleted. Return with this fact.
|
||||
*/
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Get_Date_Time -- Gets the date and time the file was last modified. *
|
||||
* *
|
||||
* Use this routine to get the date and time of the file. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the file date and time as a long. *
|
||||
* Use the YEAR(long), MONTH(),.... *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
* 07/13/1996 JLB : Handles win32 method. *
|
||||
*=============================================================================================*/
|
||||
unsigned long RawFileMClass::Get_Date_Time(void)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
|
||||
if (GetFileInformationByHandle(Handle, &info)) {
|
||||
WORD dosdate;
|
||||
WORD dostime;
|
||||
FileTimeToDosDateTime(&info.ftLastWriteTime, &dosdate, &dostime);
|
||||
return((dosdate << 16) | dostime);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Set_Date_Time -- Sets the date and time the file was last modified. *
|
||||
* *
|
||||
* Use this routine to set the date and time of the file. *
|
||||
* *
|
||||
* INPUT: the file date and time as a long *
|
||||
* *
|
||||
* OUTPUT: successful or not if the file date and time was changed. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
* 07/13/1996 JLB : Handles win 32 method *
|
||||
*=============================================================================================*/
|
||||
bool RawFileMClass::Set_Date_Time(unsigned long datetime)
|
||||
{
|
||||
if (RawFileMClass::Is_Open()) {
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
|
||||
if (GetFileInformationByHandle(Handle, &info)) {
|
||||
FILETIME filetime;
|
||||
if (DosDateTimeToFileTime((WORD)(datetime >> 16), (WORD)(datetime & 0x0FFFF), &filetime)) {
|
||||
return(SetFileTime(Handle, &info.ftCreationTime, &filetime, &filetime) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Bias -- Bias a file with a specific starting position and length. *
|
||||
* *
|
||||
* This will bias a file by giving it an artificial starting position and length. By *
|
||||
* using this routine, it is possible to 'fool' the file into ignoring a header and *
|
||||
* trailing extra data. An example of this would be a file inside of a mixfile. *
|
||||
* *
|
||||
* INPUT: start -- The starting offset that will now be considered the start of the *
|
||||
* file. *
|
||||
* *
|
||||
* length -- The forced length of the file. For files that are opened for write, *
|
||||
* this serves as the artificial constraint on the file's length. For *
|
||||
* files opened for read, this limits the usable file size. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/02/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void RawFileMClass::Bias(int start, int length)
|
||||
{
|
||||
if (start == 0) {
|
||||
BiasStart = 0;
|
||||
BiasLength = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
BiasLength = RawFileMClass::Size();
|
||||
BiasStart += start;
|
||||
if (length != -1) {
|
||||
BiasLength = BiasLength < length ? BiasLength : length;
|
||||
}
|
||||
BiasLength = BiasLength > 0 ? BiasLength : 0;
|
||||
|
||||
/*
|
||||
** Move the current file offset to a legal position if necessary and the
|
||||
** file was open.
|
||||
*/
|
||||
if (Is_Open()) {
|
||||
RawFileMClass::Seek(0, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* RawFileMClass::Raw_Seek -- Performs a seek on the unbiased file *
|
||||
* *
|
||||
* This will perform a seek on the file as if it were unbiased. This is in spite of any *
|
||||
* bias setting the file may have. The ability to perform a raw seek in this fasion is *
|
||||
* necessary to maintain the bias ability. *
|
||||
* *
|
||||
* INPUT: pos -- The position to seek the file relative to the "dir" parameter. *
|
||||
* *
|
||||
* dir -- The origin of the seek operation. *
|
||||
* *
|
||||
* OUTPUT: Returns with the new position of the seek operation. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/04/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int RawFileMClass::Raw_Seek(int pos, int dir)
|
||||
{
|
||||
/*
|
||||
** If the file isn't opened, then this is a fatal error condition.
|
||||
*/
|
||||
if (!Is_Open()) {
|
||||
Error(EBADF, false, Filename);
|
||||
}
|
||||
|
||||
switch (dir) {
|
||||
case SEEK_SET:
|
||||
dir = FILE_BEGIN;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
dir = FILE_CURRENT;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
dir = FILE_END;
|
||||
break;
|
||||
}
|
||||
|
||||
pos = SetFilePointer(Handle, pos, NULL, dir);
|
||||
|
||||
/*
|
||||
** If there was an error in the seek, then bail with an error condition.
|
||||
*/
|
||||
if (pos == 0xFFFFFFFF) {
|
||||
Error(GetLastError(), false, Filename);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return with the new position of the file. This will range between zero and the number of
|
||||
** bytes the file contains.
|
||||
*/
|
||||
return(pos);
|
||||
}
|
||||
135
Code/Tools/W3DShellExt/External/wdumpdoc.cpp
vendored
Normal file
135
Code/Tools/W3DShellExt/External/wdumpdoc.cpp
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// wdumpDoc.cpp : implementation of the CWdumpDoc class
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "wdump.h"
|
||||
#include "wdumpDoc.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CWdumpDoc
|
||||
|
||||
IMPLEMENT_DYNCREATE(CWdumpDoc, CDocument)
|
||||
|
||||
BEGIN_MESSAGE_MAP(CWdumpDoc, CDocument)
|
||||
//{{AFX_MSG_MAP(CWdumpDoc)
|
||||
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CWdumpDoc construction/destruction
|
||||
|
||||
CWdumpDoc::CWdumpDoc()
|
||||
{
|
||||
// TODO: add one-time construction code here
|
||||
m_ChunkItem = 0;
|
||||
}
|
||||
|
||||
CWdumpDoc::~CWdumpDoc()
|
||||
{
|
||||
}
|
||||
|
||||
BOOL CWdumpDoc::OnNewDocument()
|
||||
{
|
||||
m_ChunkItem = 0;
|
||||
|
||||
if (!CDocument::OnNewDocument())
|
||||
return FALSE;
|
||||
|
||||
// TODO: add reinitialization code here
|
||||
// (SDI documents will reuse this document)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CWdumpDoc serialization
|
||||
|
||||
void CWdumpDoc::Serialize(CArchive& ar)
|
||||
{
|
||||
if (ar.IsStoring())
|
||||
{
|
||||
// TODO: add storing code here
|
||||
}
|
||||
else
|
||||
{
|
||||
Read_File(ar.m_strFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CWdumpDoc diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void CWdumpDoc::AssertValid() const
|
||||
{
|
||||
CDocument::AssertValid();
|
||||
}
|
||||
|
||||
void CWdumpDoc::Dump(CDumpContext& dc) const
|
||||
{
|
||||
CDocument::Dump(dc);
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CWdumpDoc commands
|
||||
|
||||
void CWdumpDoc::OnFileOpen()
|
||||
{
|
||||
static char szFilter[] = "W3D Files (*.w3d)|*.w3d|WLT Files (*.wlt)|*.wlt|WHT Files (*.wht)|*.wht|WHA Files (*.wha)|*.wha|WTM Files (*.wtm)|*.wtm|All Files (*.*)|*.*||";
|
||||
|
||||
CFileDialog f( true,
|
||||
NULL,
|
||||
NULL,
|
||||
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
|
||||
szFilter);
|
||||
|
||||
if(f.DoModal() != IDOK) return;
|
||||
|
||||
// Add this filename to recent file list (MRU).
|
||||
// NOTE: This call is not made by the framework.
|
||||
|
||||
//Moumine 1/2/2002 1:10:02 PM -- Project W3DShellExt needs to leave this out
|
||||
#if ! defined _W3DSHELLEXT
|
||||
theApp.AddToRecentFileList (f.m_ofn.lpstrFile);
|
||||
#endif
|
||||
m_ChunkItem = 0;
|
||||
UpdateAllViews(0);
|
||||
Read_File(f.m_ofn.lpstrFile);
|
||||
}
|
||||
|
||||
|
||||
void CWdumpDoc::Read_File(const char *filename)
|
||||
{
|
||||
m_ChunkData.Load(filename);
|
||||
m_ChunkItem = 0;
|
||||
UpdateAllViews(0);
|
||||
}
|
||||
Reference in New Issue
Block a user