mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 07:31:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
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);
|
||||
}
|
||||
55
Code/Tools/W3DShellExt/StdAfx.h
Normal file
55
Code/Tools/W3DShellExt/StdAfx.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#if !defined(AFX_STDAFX_H__E3D529E9_7881_4733_91CE_310F49A15696__INCLUDED_)
|
||||
#define AFX_STDAFX_H__E3D529E9_7881_4733_91CE_310F49A15696__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#include <afxwin.h> // MFC core and standard components
|
||||
#include <afxext.h> // MFC extensions
|
||||
#include <afxdisp.h> // MFC Automation classes
|
||||
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
|
||||
#ifndef _AFX_NO_AFXCMN_SUPPORT
|
||||
#include <afxcmn.h> // MFC support for Windows Common Controls
|
||||
#include <afxcview.h> // treeview class
|
||||
#include <afxtempl.h> // CList class
|
||||
#include <afxdlgs.h> // FileDialog class
|
||||
#include <CdErr.h>
|
||||
//#include <AfxRes.h>
|
||||
#endif // _AFX_NO_AFXCMN_SUPPORT
|
||||
|
||||
#include "chunkio.h"
|
||||
#include "BitType.h"
|
||||
#include "vector3i.h"
|
||||
#include "w3d_file.h"
|
||||
#include "IOStruct.h"
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__E3D529E9_7881_4733_91CE_310F49A15696__INCLUDED_)
|
||||
9
Code/Tools/W3DShellExt/W3DShellExt.def
Normal file
9
Code/Tools/W3DShellExt/W3DShellExt.def
Normal file
@@ -0,0 +1,9 @@
|
||||
; W3DShellExt.def : Declares the module parameters for the DLL.
|
||||
|
||||
LIBRARY "W3DShellExt"
|
||||
DESCRIPTION 'W3DShell Windows Dynamic Link Library'
|
||||
|
||||
EXPORTS
|
||||
DllCanUnloadNow PRIVATE
|
||||
DllGetClassObject PRIVATE
|
||||
; DllRegisterServer PRIVATE
|
||||
202
Code/Tools/W3DShellExt/W3DShellExt.dsp
Normal file
202
Code/Tools/W3DShellExt/W3DShellExt.dsp
Normal file
@@ -0,0 +1,202 @@
|
||||
# Microsoft Developer Studio Project File - Name="W3DShellExt" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||
|
||||
CFG=W3DShellExt - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "W3DShellExt.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "W3DShellExt.mak" CFG="W3DShellExt - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "W3DShellExt - Win32 Release" (based on "Win32 (x86) Application")
|
||||
!MESSAGE "W3DShellExt - Win32 Debug" (based on "Win32 (x86) Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/BAY/Tools/W3DShellExt", SIKEAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=snCl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "W3DShellExt - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 1
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\wwdebug" /I "..\..\WWLib" /I "..\..\WW3D2" /I "..\..\WWMath" /I "..\WDump" /I "..\W3d2P3D" /I "external" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=snLink.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||
# ADD LINK32 comctl32.lib wwlib.lib wwdebug.lib Winmm.lib /nologo /subsystem:windows /dll /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"LIBCMTD.LIB" /libpath:"..\..\libs\Release"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "W3DShellExt - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 2
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\wwdebug" /I "..\..\WWLib" /I "..\..\WW3D2" /I "..\..\WWMath" /I "..\WDump" /I "..\W3d2P3D" /I "external" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_W3DSHELLEXT" /FR /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=snLink.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
# ADD LINK32 comctl32.lib wwlib.lib wwdebug.lib Winmm.lib /nologo /subsystem:windows /dll /debug /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"LIBCMTD.LIB" /libpath:"..\..\libs\debug"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to system dir
|
||||
PostBuild_Cmds=Dll_Copy W3DSellExt.dll
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "W3DShellExt - Win32 Release"
|
||||
# Name "W3DShellExt - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\copyhook.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ctxmenu.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\iconhdlr.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\propshet.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\shellext.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\shexinit.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\W3DShellExt.def
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\shellext.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gak.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gak2.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gak3.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\shellext.RC
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\W3DView.ico
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "External"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\External\chunk_d.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\External\FindDialog.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\external\matrix3.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\external\matrix3d.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\external\matrix4.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\External\quat.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\external\rawfilem.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\external\wdumpdoc.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
BIN
Code/Tools/W3DShellExt/W3DView.ico
Normal file
BIN
Code/Tools/W3DShellExt/W3DView.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
81
Code/Tools/W3DShellExt/copyhook.cpp
Normal file
81
Code/Tools/W3DShellExt/copyhook.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (C) 1993-1997 Microsoft Corporation. All Rights Reserved.
|
||||
//
|
||||
// MODULE: copyhook.cpp
|
||||
//
|
||||
// PURPOSE: Implements the ICopyHook member functions necessary to support
|
||||
// the copy hook portioins of this shell extension.
|
||||
// Copy hook handlers are called each time a folder is copied, moved,
|
||||
// renamed, etc. in the system. Note that the CopyCallback is NOT
|
||||
// called for each file, but only for entire folders.
|
||||
//
|
||||
#include "StdAfx.h"
|
||||
#include "priv.h"
|
||||
#include "shellext.h"
|
||||
|
||||
|
||||
//
|
||||
// FUNCTION: CShellExt::CopyCallback(HWND,
|
||||
// UINT,
|
||||
// UINT,
|
||||
// LPCSTR,
|
||||
// DWORD,
|
||||
// LPCSTR,
|
||||
// DWORD)
|
||||
//
|
||||
// PURPOSE: Called by the shell when a folder is being manipulated.
|
||||
//
|
||||
// PARAMETERS:
|
||||
// hwnd - Window handle to use for any UI stuff
|
||||
// wFunc - what operation is being done
|
||||
// wFlags - and flags (FOF_*) set in the initial call
|
||||
// to the file operation
|
||||
// pszSrcFile - name of the source file
|
||||
// dwSrcAttribs - file attributes of the source file
|
||||
// pszDestFile - name of the destiation file (for move and renames)
|
||||
// dwDestAttribs - file attributes of the destination file
|
||||
//
|
||||
// RETURN VALUE:
|
||||
//
|
||||
// IDYES - allow the operation
|
||||
// IDNO - disallow the operation on this file, but continue with
|
||||
// any other operations (eg. batch copy)
|
||||
// IDCANCEL - disallow the current operation and cancel any pending
|
||||
// operations
|
||||
//
|
||||
// COMMENTS:
|
||||
//
|
||||
|
||||
STDMETHODIMP_(UINT) CShellExt::CopyCallback(HWND hwnd,
|
||||
UINT wFunc,
|
||||
UINT wFlags,
|
||||
LPCSTR pszSrcFile,
|
||||
DWORD dwSrcAttribs,
|
||||
LPCSTR pszDestFile,
|
||||
DWORD dwDestAttribs)
|
||||
{
|
||||
ODS("CShellExt::CopyCallback\r\n");
|
||||
return IDYES;
|
||||
}
|
||||
136
Code/Tools/W3DShellExt/ctxmenu.cpp
Normal file
136
Code/Tools/W3DShellExt/ctxmenu.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (C) 1993-1997 Microsoft Corporation. All Rights Reserved.
|
||||
//
|
||||
// MODULE: ctxmenu.cpp
|
||||
//
|
||||
// PURPOSE: Implements the IContextMenu member functions necessary to support
|
||||
// the context menu portioins of this shell extension. Context menu
|
||||
// shell extensions are called when the user right clicks on a file
|
||||
// (of the type registered for the shell extension--see SHELLEXT.REG
|
||||
// for details on the registry entries. In this sample, the relevant
|
||||
// files are of type .W3D) in the Explorer, or selects the File menu
|
||||
// item.
|
||||
//
|
||||
|
||||
#include "Stdafx.h"
|
||||
#include "priv.h"
|
||||
#include "shellext.h"
|
||||
|
||||
|
||||
//
|
||||
// FUNCTION: CShellExt::QueryContextMenu(HMENU, UINT, UINT, UINT, UINT)
|
||||
//
|
||||
// PURPOSE: Called by the shell just before the context menu is displayed.
|
||||
// This is where you add your specific menu items.
|
||||
//
|
||||
// PARAMETERS:
|
||||
// hMenu - Handle to the context menu
|
||||
// indexMenu - Index of where to begin inserting menu items
|
||||
// idCmdFirst - Lowest value for new menu ID's
|
||||
// idCmtLast - Highest value for new menu ID's
|
||||
// uFlags - Specifies the context of the menu event
|
||||
//
|
||||
// RETURN VALUE:
|
||||
//
|
||||
//
|
||||
// COMMENTS:
|
||||
//
|
||||
|
||||
STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu,
|
||||
UINT indexMenu,
|
||||
UINT idCmdFirst,
|
||||
UINT idCmdLast,
|
||||
UINT uFlags){
|
||||
UINT idCmd = idCmdFirst;
|
||||
char szMenuText[64];
|
||||
BOOL bAppendItems=TRUE;
|
||||
if ((uFlags & 0x000F) == CMF_NORMAL){ //Check == here, since CMF_NORMAL=0
|
||||
lstrcpy(szMenuText, "&Convert to P3D");
|
||||
} else{
|
||||
if (uFlags & CMF_VERBSONLY){
|
||||
lstrcpy(szMenuText, "&Convert to P3D");
|
||||
}else{
|
||||
if (uFlags & CMF_EXPLORE){
|
||||
lstrcpy(szMenuText, "&Convert to P3D");
|
||||
}else{
|
||||
if (uFlags & CMF_DEFAULTONLY){
|
||||
bAppendItems = FALSE;
|
||||
}else{
|
||||
char szTemp[32];
|
||||
wsprintf(szTemp, "uFlags==>%d\r\n", uFlags);
|
||||
bAppendItems = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bAppendItems){
|
||||
InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL);
|
||||
InsertMenu(hMenu, indexMenu,MF_STRING|MF_BYPOSITION,idCmd++, szMenuText);
|
||||
return ResultFromShort(idCmd-idCmdFirst); //Must return number of menu items we added.
|
||||
}
|
||||
return NOERROR;
|
||||
}
|
||||
STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
|
||||
{
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
|
||||
//If HIWORD(lpcmi->lpVerb) then we have been called programmatically
|
||||
//and lpVerb is a command that should be invoked. Otherwise, the shell
|
||||
//has called us, and LOWORD(lpcmi->lpVerb) is the menu ID the user has
|
||||
//selected. Actually, it's (menu ID - idCmdFirst) from QueryContextMenu().
|
||||
if (!HIWORD(lpcmi->lpVerb)){
|
||||
UINT idCmd = LOWORD(lpcmi->lpVerb);
|
||||
switch (idCmd){
|
||||
case 0:{
|
||||
hr = DoW3DMenu1(lpcmi->hwnd,lpcmi->lpDirectory,lpcmi->lpVerb,lpcmi->lpParameters, lpcmi->nShow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
STDMETHODIMP CShellExt::GetCommandString(UINT idCmd,
|
||||
UINT uFlags,
|
||||
UINT FAR *reserved,
|
||||
LPSTR pszName,
|
||||
UINT cchMax){
|
||||
switch (idCmd){
|
||||
case 0:
|
||||
lstrcpy(pszName, "New menu item number 1");
|
||||
break;
|
||||
|
||||
}
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
STDMETHODIMP CShellExt::DoW3DMenu1(HWND hParent,
|
||||
LPCSTR pszWorkingDir,
|
||||
LPCSTR pszCmd,
|
||||
LPCSTR pszParam,
|
||||
int iShowCmd){
|
||||
MessageBox(hParent, "Not Implemented !", "Sorry !", MB_OK);
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
93
Code/Tools/W3DShellExt/iconhdlr.cpp
Normal file
93
Code/Tools/W3DShellExt/iconhdlr.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (C) 1993-1997 Microsoft Corporation. All Rights Reserved.
|
||||
//
|
||||
// Modudule: ICONHDLR.CPP
|
||||
//
|
||||
// Purpose: Implements the IExtractIcon and IPersistFile member
|
||||
// functions necessary to support the icon handler portion
|
||||
// of this shell extension.
|
||||
//
|
||||
|
||||
#include "Stdafx.h"
|
||||
#include "priv.h"
|
||||
#include "shellext.h"
|
||||
|
||||
extern HINSTANCE g_DllInstance; // Handle to this DLL itself.
|
||||
|
||||
// *********************** IExtractIcon Implementation *************************
|
||||
|
||||
STDMETHODIMP CShellExt::GetIconLocation(UINT uFlags,
|
||||
LPSTR szIconFile,
|
||||
UINT cchMax,
|
||||
int *piIndex,
|
||||
UINT *pwFlags)
|
||||
{
|
||||
GetModuleFileName(g_DllInstance, szIconFile, cchMax);
|
||||
*piIndex = (int)GetPrivateProfileInt("IconImage", "Index", 0, m_szFileUserClickedOn);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CShellExt::Extract(LPCSTR pszFile,UINT nIconIndex,HICON *phiconLarge,HICON *phiconSmall,UINT nIconSize)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
|
||||
// *********************** IPersistFile Implementation ******************
|
||||
|
||||
STDMETHODIMP CShellExt::GetClassID(LPCLSID lpClassID)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CShellExt::IsDirty()
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP CShellExt::Load(LPCOLESTR lpszFileName, DWORD grfMode)
|
||||
{
|
||||
WideCharToMultiByte(CP_ACP,0,lpszFileName,-1,m_szFileUserClickedOn, sizeof(m_szFileUserClickedOn), NULL,NULL);
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
STDMETHODIMP CShellExt::Save(LPCOLESTR lpszFileName, BOOL fRemember)
|
||||
{
|
||||
ODS("CShellExt::Save()\r\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CShellExt::SaveCompleted(LPCOLESTR lpszFileName)
|
||||
{
|
||||
ODS("CShellExt::SaveCompleted()\r\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CShellExt::GetCurFile(LPOLESTR FAR* lplpszFileName)
|
||||
{
|
||||
ODS("CShellExt::GetCurFile()\r\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
36
Code/Tools/W3DShellExt/priv.h
Normal file
36
Code/Tools/W3DShellExt/priv.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// common user interface routines
|
||||
//
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
|
||||
#ifndef STRICT
|
||||
#define STRICT
|
||||
#endif
|
||||
|
||||
#define INC_OLE2 // WIN32, get ole2 from windows.h
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#define ResultFromShort(i) ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, 0, (USHORT)(i)))
|
||||
|
||||
430
Code/Tools/W3DShellExt/propshet.cpp
Normal file
430
Code/Tools/W3DShellExt/propshet.cpp
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "priv.h"
|
||||
#include "shellext.h"
|
||||
#include "resource.h"
|
||||
#include <stdio.h>
|
||||
#include "wdump.h"
|
||||
#include "WdumpDoc.h"
|
||||
#include "W3D_File.h"
|
||||
#include <commctrl.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============================================================
|
||||
// *********** G L O B A L S ************************
|
||||
extern UINT g_DllRefCount; // Reference count of this DLL.
|
||||
extern HINSTANCE g_DllInstance; // Handle to this DLL itself.
|
||||
//===============================================================
|
||||
// *********** F U N C T I O N S *********************
|
||||
|
||||
///////////////////////////////////////
|
||||
UINT CALLBACK W3DPageCallback(HWND hWnd,
|
||||
UINT uMessage,
|
||||
LPPROPSHEETPAGE ppsp){
|
||||
switch(uMessage){
|
||||
case PSPCB_CREATE:
|
||||
return TRUE;
|
||||
|
||||
case PSPCB_RELEASE:{
|
||||
if (ppsp->lParam){
|
||||
((LPCSHELLEXT)(ppsp->lParam))->Release();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ShowHideControls(HWND hDlg, bool show){
|
||||
HWND hControl = GetWindow(hDlg, GW_CHILD);
|
||||
while(hControl != NULL){
|
||||
ShowWindow(hControl,show?SW_SHOW:SW_HIDE);
|
||||
hControl = GetWindow(hControl, GW_HWNDNEXT);
|
||||
}
|
||||
ShowWindow(GetDlgItem(hDlg, IDC_NODATA),show?SW_HIDE:SW_SHOW );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void GetItemName(ChunkItem *pItem, int id_of_interest, void* pInfo, int sizeof_struct, int& found ){
|
||||
if(pItem->ID == id_of_interest){
|
||||
BYTE *byte_ptr = (BYTE*) pInfo;
|
||||
byte_ptr += sizeof_struct* found;
|
||||
memcpy(byte_ptr,pItem->Data,pItem->Length);
|
||||
found ++;
|
||||
}
|
||||
//Get all Sibitems for this item
|
||||
POSITION p = pItem->Chunks.GetHeadPosition();
|
||||
while(p != 0) {
|
||||
ChunkItem *subitem = pItem->Chunks.GetNext(p);
|
||||
GetItemName(subitem, id_of_interest, pInfo, sizeof_struct,found);
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
BOOL CALLBACK AnimPageDlgProc(HWND hDlg,UINT uMessage, WPARAM wParam, LPARAM lParam){
|
||||
LPPROPSHEETPAGE psp=(LPPROPSHEETPAGE)GetWindowLong(hDlg, DWL_USER);
|
||||
UINT iIndex=0;
|
||||
LPCSHELLEXT lpcs;
|
||||
char buf[MAX_PATH];
|
||||
switch (uMessage){
|
||||
case WM_INITDIALOG:{
|
||||
SetWindowLong(hDlg, DWL_USER, lParam);
|
||||
psp = (LPPROPSHEETPAGE)lParam;
|
||||
lpcs = (LPCSHELLEXT)psp->lParam;
|
||||
if(!lpcs->m_FileInMemory){
|
||||
lpcs->Read_SelectedFile();
|
||||
}
|
||||
ChunkData* pData = &(lpcs->m_WdumpDocument.m_ChunkData);
|
||||
assert(pData);
|
||||
POSITION ptr = pData->Chunks.GetHeadPosition();;
|
||||
ASSERT(ptr);
|
||||
W3dAnimHeaderStruct* pAnim = lpcs->m_AnimInfos;
|
||||
int id_of_interest = W3D_CHUNK_ANIMATION_HEADER;
|
||||
int sizeof_struct = sizeof W3dAnimHeaderStruct;
|
||||
|
||||
int found_animations(0);
|
||||
while(ptr){
|
||||
ChunkItem *pItem = pData->Chunks.GetNext(ptr);
|
||||
GetItemName(pItem, id_of_interest, (void*)lpcs->m_AnimInfos, sizeof_struct, found_animations );
|
||||
}
|
||||
if(found_animations){
|
||||
//So far assuming only one animation per file
|
||||
SetDlgItemText(hDlg, IDC_ANIMNAME, pAnim->Name);
|
||||
SetDlgItemText(hDlg, IDC_HNAME, pAnim->HierarchyName);
|
||||
SetDlgItemInt(hDlg, IDC_NUMFRAMES, pAnim->NumFrames,FALSE);
|
||||
//FrameRate
|
||||
sprintf(buf,"%i fps",pAnim->FrameRate,FALSE);
|
||||
SetDlgItemText(hDlg, IDC_FRAMERATE, buf);
|
||||
//SetDlgItemInt(hDlg, IDC_FRAMERATE, pAnim->FrameRate,FALSE);
|
||||
//version
|
||||
sprintf(buf,"%d.%d",W3D_GET_MAJOR_VERSION(pAnim->Version),W3D_GET_MINOR_VERSION(pAnim->Version));
|
||||
SetDlgItemText(hDlg, IDC_ANIMVERSION, buf);
|
||||
}
|
||||
//Hierarchies
|
||||
ptr = pData->Chunks.GetHeadPosition();;
|
||||
ASSERT(ptr);
|
||||
id_of_interest = W3D_CHUNK_HIERARCHY_HEADER;
|
||||
//So far assuming only one hierarchy per file
|
||||
W3dHierarchyStruct* pHInfo = lpcs->m_Hierarchies;
|
||||
ASSERT(pHInfo);
|
||||
sizeof_struct = sizeof W3dHierarchyStruct;
|
||||
int found_hierarchies(0);
|
||||
while(ptr){
|
||||
ChunkItem *pItem = pData->Chunks.GetNext(ptr);
|
||||
GetItemName(pItem, id_of_interest, (void*)pHInfo, sizeof_struct, found_hierarchies );
|
||||
}
|
||||
if(found_hierarchies){
|
||||
SetDlgItemText(hDlg, IDC_HIERARCHYNAME, pHInfo->Name);
|
||||
SetDlgItemInt(hDlg, IDC_NUMPIVOTS, pHInfo->NumPivots,FALSE);
|
||||
sprintf(buf,"%d.%d",W3D_GET_MAJOR_VERSION(pHInfo->Version),W3D_GET_MINOR_VERSION(pHInfo->Version));
|
||||
SetDlgItemText(hDlg, IDC_HIERARCHYVERSION, buf);
|
||||
sprintf(buf, "(%.3f, %.3f, %.3f)", pHInfo->Center.X, pHInfo->Center.Y, pHInfo->Center.Z);
|
||||
SetDlgItemText(hDlg, IDC_HCENTER, buf);
|
||||
}
|
||||
ShowHideControls(hDlg, (found_animations + found_hierarchies)!= 0);
|
||||
break;
|
||||
}
|
||||
case WM_DESTROY:{
|
||||
RemoveProp(hDlg, "ID");
|
||||
break;
|
||||
}
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)){
|
||||
case IDC_TOP3D:
|
||||
//SetProp(hDlg, "ID", (HANDLE)lParam);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
switch (((NMHDR FAR *)lParam)->code){
|
||||
case PSN_SETACTIVE:
|
||||
break;
|
||||
case PSN_APPLY:
|
||||
//User has clicked the OK or Apply button so we'll
|
||||
//update the icon information in the .W3D file
|
||||
lpcs = (LPCSHELLEXT)psp->lParam;
|
||||
//Ask the shell to refresh the icon list...
|
||||
//SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, 0, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
//=====================================================================================================
|
||||
void SetDlgMeshParams(HWND hDlg, W3dMeshHeader3Struct*pInfo){
|
||||
SetDlgItemText(hDlg,IDC_MESHNAME,pInfo->MeshName);
|
||||
SetDlgItemText(hDlg,IDC_CONTAINER,pInfo->ContainerName);
|
||||
SetDlgItemInt(hDlg,IDC_NUM_MATERIALS, pInfo->NumMaterials,FALSE);
|
||||
|
||||
SetDlgItemInt(hDlg,IDC_NUM_POLYS, pInfo->NumTris,FALSE);
|
||||
SetDlgItemInt(hDlg,IDC_NUM_VERTICES, pInfo->NumVertices, FALSE);
|
||||
SetDlgItemInt(hDlg,IDC_NUM_MATERIALS, pInfo->NumMaterials,FALSE);
|
||||
char msg[MAX_PATH];
|
||||
sprintf(msg, "%.3f", pInfo->SphRadius);
|
||||
SetDlgItemText(hDlg,IDC_SPHERERADIUS,msg);
|
||||
//3D Coords
|
||||
//Center
|
||||
sprintf(msg, "(%.3f, %.3f, %.3f)", pInfo->SphCenter.X, pInfo->SphCenter.Y, pInfo->SphCenter.Z);
|
||||
SetDlgItemText(hDlg, IDC_SPHERECENTER, msg);
|
||||
//Min
|
||||
sprintf(msg, "(%.3f, %.3f, %.3f)", pInfo->Min.X, pInfo->Min.Y, pInfo->Min.Z);
|
||||
SetDlgItemText(hDlg, IDC_MINDIM, msg);
|
||||
//Max
|
||||
sprintf(msg, "(%.3f, %.3f, %.3f)", pInfo->Max.X, pInfo->Max.Y, pInfo->Max.Z);
|
||||
SetDlgItemText(hDlg, IDC_MAXDIM, msg);
|
||||
|
||||
sprintf(msg,"%d.%d",W3D_GET_MAJOR_VERSION(pInfo->Version),W3D_GET_MINOR_VERSION(pInfo->Version));
|
||||
SetDlgItemText(hDlg, IDC_VERSION, msg);
|
||||
}
|
||||
//==========================================================================================================
|
||||
BOOL CALLBACK MeshPageDlgProc(HWND hDlg,UINT uMessage, WPARAM wParam, LPARAM lParam){
|
||||
LPPROPSHEETPAGE psp=(LPPROPSHEETPAGE)GetWindowLong(hDlg, DWL_USER);
|
||||
UINT iIndex=0;
|
||||
LPCSHELLEXT lpcs;
|
||||
|
||||
switch (uMessage){
|
||||
case WM_INITDIALOG:{
|
||||
SetWindowLong(hDlg, DWL_USER, lParam);
|
||||
psp = (LPPROPSHEETPAGE)lParam;
|
||||
lpcs = (LPCSHELLEXT)psp->lParam;
|
||||
if(!lpcs->m_FileInMemory){
|
||||
lpcs->Read_SelectedFile();
|
||||
}
|
||||
ChunkData* pData = &(lpcs->m_WdumpDocument.m_ChunkData);
|
||||
assert(pData);
|
||||
POSITION ptr = pData->Chunks.GetHeadPosition();
|
||||
ASSERT(ptr);
|
||||
//Look for mesh headers
|
||||
W3dMeshHeader3Struct* pInfo = lpcs->m_Meshes;
|
||||
int id_of_interest = W3D_CHUNK_MESH_HEADER3;
|
||||
int sizeof_struct = sizeof W3dMeshHeader3Struct;
|
||||
while(ptr){
|
||||
ChunkItem *pItem = pData->Chunks.GetNext(ptr);
|
||||
ASSERT(lpcs->m_FoundMeshes < MAX_MESH);
|
||||
GetItemName(pItem, id_of_interest, (void*)(pInfo),sizeof_struct, lpcs->m_FoundMeshes );
|
||||
}
|
||||
if(lpcs->m_FoundMeshes){
|
||||
SetDlgItemInt(hDlg,IDC_MESHNUMBER, 0,FALSE);
|
||||
//Look for Textures
|
||||
char pTextureInfo[MAX_TEXUTRE_NAME_LEN * MAX_MESH];
|
||||
id_of_interest = W3D_CHUNK_TEXTURE_NAME;
|
||||
int found_textures(0);
|
||||
int sizeof_struct = MAX_TEXUTRE_NAME_LEN;
|
||||
ptr = pData->Chunks.GetHeadPosition();
|
||||
while(ptr){
|
||||
ChunkItem *pItem = pData->Chunks.GetNext(ptr);
|
||||
GetItemName(pItem, id_of_interest, (void*)pTextureInfo, sizeof_struct, found_textures );
|
||||
}
|
||||
for(int t_count(0); t_count < found_textures; t_count ++){
|
||||
if(lpcs->NotAdded(&(pTextureInfo[t_count*MAX_TEXUTRE_NAME_LEN]))){
|
||||
char* text = lpcs->m_Textures[lpcs->m_NumAdded-1].LockBuffer();
|
||||
SendDlgItemMessage(hDlg, IDC_TEXTURELIST, LB_ADDSTRING,(WPARAM) 0L, (LPARAM)text);//(pTextureInfo[t_count].name)) ;
|
||||
lpcs->m_Textures[lpcs->m_NumAdded-1].ReleaseBuffer();
|
||||
}
|
||||
}
|
||||
SetDlgItemInt(hDlg,IDC_NUM_MESHES, lpcs->m_FoundMeshes,FALSE);
|
||||
SetDlgMeshParams(hDlg, pInfo);
|
||||
//Set Spin range
|
||||
SendDlgItemMessage(hDlg, IDC_MESHSPIN, UDM_SETRANGE, (WPARAM)0L, (LPARAM)MAKELONG(lpcs->m_FoundMeshes-1,0));
|
||||
}
|
||||
ShowHideControls(hDlg, lpcs->m_FoundMeshes != 0);
|
||||
break;
|
||||
}
|
||||
case WM_DESTROY:
|
||||
RemoveProp(hDlg, "ID");
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
|
||||
switch (LOWORD(wParam)){
|
||||
case IDC_TOP3D:
|
||||
//SetProp(hDlg, "ID", (HANDLE)lParam);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
lpcs = (LPCSHELLEXT)psp->lParam;
|
||||
switch (((NMHDR FAR *)lParam)->code){
|
||||
case PSN_SETACTIVE:
|
||||
break;
|
||||
case PSN_APPLY:
|
||||
//Ask the shell to refresh the icon list...
|
||||
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, 0, 0);
|
||||
break;
|
||||
case UDN_DELTAPOS:{
|
||||
lpcs = (LPCSHELLEXT)psp->lParam;
|
||||
W3dMeshHeader3Struct* pInfo = lpcs->m_Meshes;
|
||||
LPNMUPDOWN lpUD = (LPNMUPDOWN) lParam;
|
||||
int mesh_num = lpUD->iDelta + lpUD->iPos;
|
||||
if(mesh_num >= 0 && mesh_num < lpcs->m_FoundMeshes){
|
||||
SetDlgMeshParams(hDlg, pInfo+mesh_num);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
BOOL CALLBACK PreviewPageDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam){
|
||||
|
||||
LPPROPSHEETPAGE psp=(LPPROPSHEETPAGE)GetWindowLong(hDlg, DWL_USER);
|
||||
UINT iIndex(0);
|
||||
LPCSHELLEXT lpcs;
|
||||
switch (uMessage){
|
||||
case WM_INITDIALOG:{
|
||||
SetWindowLong(hDlg, DWL_USER, lParam);
|
||||
psp = (LPPROPSHEETPAGE)lParam;
|
||||
lpcs = (LPCSHELLEXT)psp->lParam;
|
||||
if(!lpcs->m_FileInMemory){
|
||||
lpcs->Read_SelectedFile();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_DESTROY:{
|
||||
RemoveProp(hDlg, "ID");
|
||||
break;
|
||||
}
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)){
|
||||
case IDC_TOP3D:
|
||||
//SetProp(hDlg, "ID", (HANDLE)lParam);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
switch (((NMHDR FAR *)lParam)->code){
|
||||
case PSN_SETACTIVE:
|
||||
break;
|
||||
case PSN_APPLY:
|
||||
//User has clicked the OK or Apply button so we'll
|
||||
//update the icon information in the .W3D file
|
||||
lpcs = (LPCSHELLEXT)psp->lParam;
|
||||
//Ask the shell to refresh the icon list...
|
||||
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, 0, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// PURPOSE: Called by the shell just before the property sheet is displayed.
|
||||
STDMETHODIMP CShellExt::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, //Pointer to the Shell's AddPage function
|
||||
LPARAM lParam){ //Passed as second parameter to lpfnAddPage
|
||||
m_FileInMemory = false;
|
||||
PROPSHEETPAGE psp;
|
||||
HPROPSHEETPAGE hpage;
|
||||
FORMATETC fmte = {CF_HDROP,(DVTARGETDEVICE FAR *)NULL,DVASPECT_CONTENT,-1, TYMED_HGLOBAL };
|
||||
STGMEDIUM medium;
|
||||
HRESULT hres = 0;
|
||||
// char buf[MAX_PATH];
|
||||
if (m_pDataObj){ //Paranoid check, m_pDataObj should have something by now...
|
||||
hres = m_pDataObj->GetData(&fmte, &medium);
|
||||
}
|
||||
if (SUCCEEDED(hres)){
|
||||
//Find out how many files the user has selected...
|
||||
UINT cbFiles = 0;
|
||||
LPCSHELLEXT lpcsext = this;
|
||||
|
||||
if (medium.hGlobal){
|
||||
cbFiles = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, 0, 0);
|
||||
}
|
||||
if (cbFiles < 2){
|
||||
if (cbFiles){
|
||||
DragQueryFile((HDROP)medium.hGlobal,0, m_SelectedFile, sizeof(m_SelectedFile));
|
||||
}
|
||||
psp.dwSize = sizeof(psp); // no extra data.
|
||||
psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE | PSP_USECALLBACK;
|
||||
psp.hInstance = g_DllInstance;
|
||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_MESH);
|
||||
psp.hIcon = 0;
|
||||
psp.pszTitle = " Meshes ";
|
||||
psp.pfnDlgProc = MeshPageDlgProc;
|
||||
psp.pcRefParent = &g_DllRefCount;
|
||||
psp.pfnCallback = W3DPageCallback;
|
||||
psp.lParam = (LPARAM)lpcsext;
|
||||
AddRef();
|
||||
hpage = CreatePropertySheetPage(&psp);
|
||||
if(hpage){
|
||||
if (!lpfnAddPage(hpage, lParam)){
|
||||
DestroyPropertySheetPage(hpage);
|
||||
Release();
|
||||
}
|
||||
}
|
||||
//Animation Page
|
||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_ANIMPAGE);
|
||||
psp.pszTitle = "Animations";
|
||||
psp.pfnDlgProc = AnimPageDlgProc;
|
||||
AddRef();
|
||||
hpage = CreatePropertySheetPage(&psp);
|
||||
if(hpage){
|
||||
if (!lpfnAddPage(hpage, lParam)){
|
||||
DestroyPropertySheetPage(hpage);
|
||||
Release();
|
||||
}
|
||||
}
|
||||
//Preview Page
|
||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_PREVIEW);
|
||||
psp.pszTitle = " Preview ";
|
||||
psp.pfnDlgProc = PreviewPageDlgProc;
|
||||
AddRef();
|
||||
hpage = CreatePropertySheetPage(&psp);
|
||||
if(hpage){
|
||||
if (!lpfnAddPage(hpage, lParam)){
|
||||
DestroyPropertySheetPage(hpage);
|
||||
Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NOERROR;
|
||||
}
|
||||
// PURPOSE: Called by the shell only for Control Panel property sheet
|
||||
STDMETHODIMP CShellExt::ReplacePage(UINT uPageID, //ID of page to be replaced
|
||||
LPFNADDPROPSHEETPAGE lpfnReplaceWith, //Pointer to the Shell's Replace function
|
||||
LPARAM lParam){ //Passed as second parameter to lpfnReplaceWith
|
||||
return E_FAIL;//we don't support this function. It should never be
|
||||
}
|
||||
73
Code/Tools/W3DShellExt/resource.h
Normal file
73
Code/Tools/W3DShellExt/resource.h
Normal file
@@ -0,0 +1,73 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by shellext.RC
|
||||
//
|
||||
#define IDD_TOOLS_FIND 130
|
||||
#define IDD_MESHPAGE 132
|
||||
#define IDD_PREVIEW 132
|
||||
#define IDI_W3D 136
|
||||
#define IDD_ANIMPAGE 138
|
||||
#define IDD_MESH 139
|
||||
#define IDD_ANIMPAGE1 140
|
||||
#define IDC_NUM_POLYS 1000
|
||||
#define IDC_FIND_STRING 1000
|
||||
#define IDC_NUM_VERTICES 1001
|
||||
#define IDC_NUM_MESHES 1002
|
||||
#define IDC_NUM_MATERIALS 1003
|
||||
#define IDC_PREVIEW 1004
|
||||
#define IDC_CONTAINER 1004
|
||||
#define IDC_TOP3D 1005
|
||||
#define IDC_MESHNAME 1006
|
||||
#define IDC_MESHNUMBER 1007
|
||||
#define IDC_MINDIM 1009
|
||||
#define IDC_MAXDIM 1010
|
||||
#define IDC_SPHERECENTER 1011
|
||||
#define IDC_SPHERERADIUS 1012
|
||||
#define IDC_NUMFRAMES 1013
|
||||
#define IDC_VERSION 1013
|
||||
#define IDC_FRAMERATE 1014
|
||||
#define IDC_NUMANIMCHANNELS 1015
|
||||
#define IDC_ANIMVERSION 1015
|
||||
#define IDC_NUMBITCHANNELS 1016
|
||||
#define IDC_NUMPIVOTS 1016
|
||||
#define IDC_ZMOTION 1017
|
||||
#define IDC_HCENTER 1017
|
||||
#define IDC_HNAME 1018
|
||||
#define IDC_ANIMNAME 1019
|
||||
#define IDC_ANIMNAME_STATIC 1020
|
||||
#define IDC_HNAME_STATIC 1021
|
||||
#define IDC_NUMFRAMES_STATIC 1022
|
||||
#define IDC_FRAMERATE_STATIC 1023
|
||||
#define IDC_NUM_MESHES_STATIC 1024
|
||||
#define IDC_FRAMERATE_STATIC2 1024
|
||||
#define IDC_ANIMATIONCHANNELS 1025
|
||||
#define IDC_NUMPIVOTRS_STATIC 1025
|
||||
#define IDC_ANIMATIONCHANNELS_STATIC 1026
|
||||
#define IDC_CENTER_STATIC 1026
|
||||
#define IDC_NUMBITCHANNELS_STATIC 1027
|
||||
#define IDC_HNAME_STATIC2 1027
|
||||
#define IDC_ZMOTION_STATIC 1028
|
||||
#define IDC_HIERARCHYNAME 1028
|
||||
#define IDC_NUM_POLYS_STATIC 1029
|
||||
#define IDC_NUM_VERTICES_STATIC 1030
|
||||
#define IDC_NUM_MATERIALS_STATIC 1031
|
||||
#define IDC_HVERSION_STATIC 1031
|
||||
#define IDC_SPHERERADIUS_STATIC 1032
|
||||
#define IDC_HIERARCHYVERSION 1032
|
||||
#define IDC_SPHERECENTER_STATIC 1033
|
||||
#define IDC_MINDIM_STATIC 1034
|
||||
#define IDC_MAXDIM_STATIC 1035
|
||||
#define IDC_NODATA 1036
|
||||
#define IDC_MESHSPIN 1040
|
||||
#define IDC_TEXTURELIST 1042
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 139
|
||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
||||
#define _APS_NEXT_CONTROL_VALUE 1044
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
230
Code/Tools/W3DShellExt/shellext.RC
Normal file
230
Code/Tools/W3DShellExt/shellext.RC
Normal file
@@ -0,0 +1,230 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifndef _MAC
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Programmer: Moumine Ballo\0"
|
||||
VALUE "CompanyName", "Westwood Studios\0"
|
||||
VALUE "FileDescription", "Shell Extension DLL\0"
|
||||
VALUE "FileVersion", "1, 0, 0, 1\0"
|
||||
VALUE "InternalName", "W3DShellExt\0"
|
||||
VALUE "LegalCopyright", "Copyright <20> Westwwod Studios 1985-2001\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "W3DShellExt\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "ProductName", "W3DShellExt Dynamic Link Library\0"
|
||||
VALUE "ProductVersion", "1, 0, 0, 1\0"
|
||||
VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // !_MAC
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_PREVIEW DIALOG DISCARDABLE 0, 0, 238, 218
|
||||
STYLE WS_CHILD | WS_VISIBLE | WS_BORDER
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
ICON IDI_W3D,IDC_STATIC,6,7,20,20
|
||||
PUSHBUTTON "Convert to P3D",IDC_TOP3D,175,13,59,14
|
||||
PUSHBUTTON "Coming soon",IDC_PREVIEW,5,32,229,175,BS_FLAT
|
||||
END
|
||||
|
||||
IDD_ANIMPAGE DIALOG DISCARDABLE 0, 0, 238, 218
|
||||
STYLE WS_CHILD | WS_VISIBLE | WS_BORDER
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
RTEXT "Number of Frames : ",IDC_NUMFRAMES_STATIC,51,66,59,8
|
||||
LTEXT "",IDC_NUMFRAMES,117,66,35,9
|
||||
RTEXT "Frame Rate : ",IDC_FRAMERATE_STATIC,51,78,59,8
|
||||
LTEXT "",IDC_FRAMERATE,117,78,35,9
|
||||
RTEXT "Hierarchy Name : ",IDC_HNAME_STATIC,51,54,59,8
|
||||
LTEXT "",IDC_HNAME,117,54,70,9
|
||||
ICON IDI_W3D,IDC_STATIC,6,7,20,20
|
||||
PUSHBUTTON "Convert to P3D",IDC_TOP3D,174,201,59,14
|
||||
RTEXT "Animationn Name : ",IDC_ANIMNAME_STATIC,51,42,59,8
|
||||
LTEXT "",IDC_ANIMNAME,117,42,70,9
|
||||
LTEXT "NO DATA TO DISPLAY",IDC_NODATA,88,99,84,9
|
||||
GROUPBOX "Animation :",IDC_STATIC,33,29,173,78
|
||||
RTEXT "Version :",IDC_FRAMERATE_STATIC2,52,90,59,8
|
||||
LTEXT "",IDC_ANIMVERSION,118,90,35,9
|
||||
RTEXT "Number of Pivots : ",IDC_NUMPIVOTRS_STATIC,50,141,59,8
|
||||
LTEXT "",IDC_NUMPIVOTS,116,141,35,9
|
||||
RTEXT "Center : ",IDC_CENTER_STATIC,50,154,59,8
|
||||
LTEXT "",IDC_HCENTER,116,154,86,9
|
||||
RTEXT "Hierarchy Name :",IDC_HNAME_STATIC2,50,128,59,8
|
||||
LTEXT "",IDC_HIERARCHYNAME,116,128,70,9
|
||||
GROUPBOX "Hierarchy",IDC_STATIC,33,111,173,78
|
||||
RTEXT "Version :",IDC_HVERSION_STATIC,51,167,59,8
|
||||
LTEXT "",IDC_HIERARCHYVERSION,117,167,35,9
|
||||
END
|
||||
|
||||
IDD_MESH DIALOGEX 0, 0, 238, 218
|
||||
STYLE WS_CHILD | WS_VISIBLE | WS_BORDER
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
RTEXT "Mesh Number :",IDC_STATIC,13,55,62,8
|
||||
CTEXT "",IDC_MESHNUMBER,84,55,9,9
|
||||
CONTROL "Spin1",IDC_MESHSPIN,"msctls_updown32",UDS_SETBUDDYINT |
|
||||
UDS_AUTOBUDDY | UDS_ARROWKEYS,96,54,11,10
|
||||
RTEXT "Number of Polygons :",IDC_STATIC,10,94,65,8
|
||||
LTEXT "",IDC_NUM_POLYS,98,94,125,9
|
||||
RTEXT "Number of Vertices :",IDC_STATIC,13,106,62,8
|
||||
RTEXT "Number of Meshes",IDC_STATIC,32,24,60,8
|
||||
RTEXT "Number of Materials :",IDC_STATIC,13,118,75,8
|
||||
LTEXT "",IDC_NUM_VERTICES,98,106,125,9
|
||||
LTEXT "",IDC_NUM_MESHES,99,23,11,9
|
||||
LTEXT "",IDC_NUM_MATERIALS,98,118,125,9
|
||||
RTEXT "Dimensions Min.:",IDC_STATIC,13,166,62,8
|
||||
RTEXT "Dimensions Max :",IDC_STATIC,13,154,62,8
|
||||
LTEXT "",IDC_MINDIM,98,166,125,9
|
||||
LTEXT "",IDC_MAXDIM,98,154,125,9
|
||||
RTEXT "Sphere Center :",IDC_STATIC,13,142,62,8
|
||||
RTEXT "Sphere Radius :",IDC_STATIC,13,130,62,8
|
||||
LTEXT "",IDC_SPHERECENTER,98,142,125,9
|
||||
LTEXT "",IDC_SPHERERADIUS,98,130,125,9
|
||||
ICON IDI_W3D,IDC_STATIC,5,7,20,20
|
||||
PUSHBUTTON "Convert to P3D",IDC_TOP3D,174,201,59,14
|
||||
RTEXT "Container Name",IDC_STATIC,13,82,62,8
|
||||
LTEXT "",IDC_CONTAINER,98,82,125,9
|
||||
RTEXT "Mesh Name :",IDC_STATIC,13,70,62,8
|
||||
LTEXT "",IDC_MESHNAME,98,70,125,9
|
||||
RTEXT "Version Number :",IDC_STATIC,13,178,62,8
|
||||
LTEXT "",IDC_VERSION,98,178,125,9
|
||||
GROUPBOX "Mesh Description",IDC_STATIC,9,39,225,159
|
||||
RTEXT "Textures :",IDC_STATIC,132,8,30,8
|
||||
LISTBOX IDC_TEXTURELIST,132,16,89,25,NOT LBS_NOTIFY | LBS_SORT |
|
||||
LBS_NOINTEGRALHEIGHT | NOT WS_BORDER | WS_VSCROLL |
|
||||
WS_TABSTOP,WS_EX_STATICEDGE
|
||||
LTEXT "NO DATA TO DISPLAY",IDC_NODATA,77,105,84,9
|
||||
END
|
||||
|
||||
IDD_ANIMPAGE1 DIALOG DISCARDABLE 0, 0, 238, 211
|
||||
STYLE WS_CHILD | WS_VISIBLE | WS_BORDER
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
RTEXT "Number of Frames",IDC_NUMFRAMES_STATIC,5,58,94,8
|
||||
LTEXT "",IDC_NUMFRAMES,106,58,35,9
|
||||
RTEXT "Frame Rate",IDC_FRAMERATE_STATIC,5,71,94,8
|
||||
RTEXT "Animation Channels",IDC_NUM_MESHES_STATIC,5,84,94,8
|
||||
LTEXT "",IDC_FRAMERATE,106,71,35,9
|
||||
LTEXT "",IDC_ANIMATIONCHANNELS,106,84,35,9
|
||||
LTEXT "",IDC_NUM_MATERIALS,108,97,35,9
|
||||
RTEXT "Number of Bit Channels",IDC_NUMBITCHANNELS_STATIC,5,123,
|
||||
94,8
|
||||
RTEXT "ZMotion",IDC_ZMOTION_STATIC,5,136,94,8
|
||||
LTEXT "",IDC_NUMBITCHANNELS,106,123,70,9
|
||||
LTEXT "",IDC_ZMOTION,106,136,70,9
|
||||
RTEXT "Hierarchy Name",IDC_HNAME_STATIC,5,43,94,8
|
||||
RTEXT "Number of Animation Channels",
|
||||
IDC_ANIMATIONCHANNELS_STATIC,5,110,94,8
|
||||
LTEXT "",IDC_HNAME,106,43,70,9
|
||||
LTEXT "",IDC_NUMANIMCHANNELS,106,110,35,9
|
||||
ICON IDI_W3D,IDC_STATIC,6,7,20,20
|
||||
PUSHBUTTON "Convert to P3D",IDC_TOP3D,174,190,50,14
|
||||
RTEXT "Animationn Name",IDC_ANIMNAME_STATIC,5,31,94,8
|
||||
LTEXT "",IDC_ANIMNAME,106,31,70,9
|
||||
LTEXT "NO DATA TO DISPLAY",IDC_NODATA,77,101,84,9
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_W3D ICON DISCARDABLE "W3DView.ico"
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
209
Code/Tools/W3DShellExt/shellext.cpp
Normal file
209
Code/Tools/W3DShellExt/shellext.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
#include "stdAfx.h"
|
||||
#include "priv.h"
|
||||
#include "Chunkio.h"
|
||||
#include "io.h"
|
||||
#include "wdump.h"
|
||||
#include "WdumpDoc.h"
|
||||
//#include "w3d2dat.h" /// LFeenanEA: Header file missing, perhaps this tool is outdated?
|
||||
//
|
||||
// Initialize GUIDs (should be done only and at-least once per DLL/EXE)
|
||||
//
|
||||
#pragma data_seg(".text")
|
||||
#define INITGUID
|
||||
#include <initguid.h>
|
||||
#include <shlguid.h>
|
||||
#include "shellext.h"
|
||||
|
||||
|
||||
#pragma data_seg()
|
||||
// Global variables
|
||||
//
|
||||
UINT g_DllRefCount = 0; // Reference count of this DLL.
|
||||
HINSTANCE g_DllInstance = NULL; // Handle to this DLL itself.
|
||||
|
||||
//===============================================================
|
||||
extern "C" int APIENTRY
|
||||
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved){
|
||||
if (dwReason == DLL_PROCESS_ATTACH){
|
||||
g_DllInstance = hInstance;
|
||||
}else
|
||||
if (dwReason == DLL_PROCESS_DETACH){
|
||||
ODS3("Detaching Process");
|
||||
}
|
||||
return 1; // ok
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// DllCanUnloadNow
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
STDAPI DllCanUnloadNow(void)
|
||||
{
|
||||
return (g_DllRefCount == 0 ? S_OK : S_FALSE);
|
||||
}
|
||||
|
||||
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut)
|
||||
{
|
||||
*ppvOut = NULL;
|
||||
if (IsEqualIID(rclsid, CLSID_ShellExtension)) {
|
||||
CShellExtClassFactory* pcf = new CShellExtClassFactory;
|
||||
return pcf->QueryInterface(riid, ppvOut);
|
||||
}
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
||||
//======================================================================================
|
||||
CShellExtClassFactory::CShellExtClassFactory()
|
||||
{
|
||||
m_cRef = 0L;
|
||||
g_DllRefCount++;
|
||||
}
|
||||
|
||||
//======================================================================================
|
||||
CShellExtClassFactory::~CShellExtClassFactory(){
|
||||
g_DllRefCount--;
|
||||
}
|
||||
|
||||
//======================================================================================
|
||||
STDMETHODIMP CShellExtClassFactory::QueryInterface(REFIID riid, LPVOID FAR *ppv){
|
||||
*ppv = NULL;
|
||||
// Any interface on this object is the object pointer
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)){
|
||||
*ppv = (LPCLASSFACTORY)this;
|
||||
AddRef();
|
||||
return NOERROR;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
//======================================================================================
|
||||
STDMETHODIMP_(ULONG) CShellExtClassFactory::AddRef()
|
||||
{
|
||||
return ++m_cRef;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CShellExtClassFactory::Release()
|
||||
{
|
||||
if (--m_cRef)
|
||||
return m_cRef;
|
||||
delete this;
|
||||
return 0L;
|
||||
}
|
||||
|
||||
STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,REFIID riid,LPVOID *ppvObj){
|
||||
*ppvObj = NULL;
|
||||
// Shell extensions typically don't support aggregation (inheritance)
|
||||
if (pUnkOuter)
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
// Create the main shell extension object. The shell will then call
|
||||
// QueryInterface with IID_IShellExtInit--this is how shell extensions are
|
||||
// initialized.
|
||||
|
||||
LPCSHELLEXT pShellExt = new CShellExt(); //Create the CShellExt object
|
||||
if (NULL == pShellExt)
|
||||
return E_OUTOFMEMORY;
|
||||
return pShellExt->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CShellExtClassFactory::LockServer(BOOL fLock)
|
||||
{
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
// *********************** CShellExt *************************
|
||||
CShellExt::CShellExt(): m_FileInMemory(false),
|
||||
m_NumAdded(0),
|
||||
m_FoundMeshes(0){
|
||||
m_cRef = 0L;
|
||||
m_pDataObj = NULL;
|
||||
g_DllRefCount++;
|
||||
}
|
||||
|
||||
CShellExt::~CShellExt()
|
||||
{
|
||||
if (m_pDataObj)
|
||||
m_pDataObj->Release();
|
||||
|
||||
g_DllRefCount--;
|
||||
}
|
||||
|
||||
STDMETHODIMP CShellExt::QueryInterface(REFIID riid, LPVOID FAR *ppv)
|
||||
{
|
||||
*ppv = NULL;
|
||||
if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown)) {
|
||||
*ppv = (LPSHELLEXTINIT)this;
|
||||
}else {
|
||||
if (IsEqualIID(riid, IID_IContextMenu)) {
|
||||
*ppv = (LPCONTEXTMENU)this;
|
||||
}else{
|
||||
if (IsEqualIID(riid, IID_IExtractIcon)){
|
||||
*ppv = (LPEXTRACTICON)this;
|
||||
}else {
|
||||
if (IsEqualIID(riid, IID_IPersistFile)){
|
||||
*ppv = (LPPERSISTFILE)this;
|
||||
}else {
|
||||
if (IsEqualIID(riid, IID_IShellPropSheetExt)){
|
||||
*ppv = (LPSHELLPROPSHEETEXT)this;
|
||||
}else {
|
||||
if (IsEqualIID(riid, IID_IShellCopyHook)){
|
||||
*ppv = (LPCOPYHOOK)this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*ppv){
|
||||
AddRef();
|
||||
return NOERROR;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CShellExt::AddRef()
|
||||
{
|
||||
return ++m_cRef;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CShellExt::Release()
|
||||
{
|
||||
if (--m_cRef){
|
||||
return m_cRef;
|
||||
}
|
||||
delete this;
|
||||
return 0L;
|
||||
}
|
||||
void CShellExt::Read_SelectedFile(){
|
||||
m_WdumpDocument.Read_File(m_SelectedFile);
|
||||
m_FileInMemory = true;
|
||||
}
|
||||
bool CShellExt::NotAdded(char* name){
|
||||
CString str = name;
|
||||
for(int pos(0); pos < m_NumAdded; pos ++){
|
||||
if(str == m_Textures[pos]){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_Textures[m_NumAdded ++ ] = str;
|
||||
return true;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
138
Code/Tools/W3DShellExt/shellext.h
Normal file
138
Code/Tools/W3DShellExt/shellext.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _SHELLEXT_H
|
||||
#define _SHELLEXT_H
|
||||
|
||||
#define MAX_TEXTURES_INFILE 32
|
||||
#define MAX_TEXUTRE_NAME_LEN 32
|
||||
#define MAX_MESH 128
|
||||
#define MAX_ANIMS_INFILE 16
|
||||
|
||||
//#define ODS(sz) OutputDebugString(sz)
|
||||
//#define ENABLE_MSG2
|
||||
//#define ENABLE_MSG
|
||||
//#define ENABLE_MSG3
|
||||
#if defined ENABLE_MSG
|
||||
#define ODS(sz) MessageBox(NULL, sz, "Debug Message", MB_OK)
|
||||
#else
|
||||
#define ODS(sz)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined ENABLE_MSG2
|
||||
#define ODS2(sz) MessageBox(NULL, sz, "Debug Message", MB_OK)
|
||||
#else
|
||||
#define ODS2(sz)
|
||||
#endif
|
||||
|
||||
#if defined ENABLE_MSG3
|
||||
#define ODS3(sz) MessageBox(NULL, sz, "Debug Message", MB_OK)
|
||||
#else
|
||||
#define ODS3(sz)
|
||||
#endif
|
||||
|
||||
#include "W3D_File.h"
|
||||
#include "wdump.h"
|
||||
#include "WdumpDoc.h"
|
||||
//#include "w3d2dat.h" /// LFeenanEA: Header file missing, perhaps this tool is outdated?
|
||||
|
||||
|
||||
class CWdumpDoc;
|
||||
// {556F8779-49C4-4e88-9CEF-0AC2CFD6B763}
|
||||
DEFINE_GUID(CLSID_ShellExtension, 0x556f8779L, 0x49c4, 0x4e88, 0x9c, 0xef, 0x0a, 0xc2, 0xcf, 0xd6, 0xb7, 0x63 );
|
||||
class CShellExtClassFactory : public IClassFactory
|
||||
{
|
||||
protected:
|
||||
ULONG m_cRef;
|
||||
|
||||
public:
|
||||
CShellExtClassFactory();
|
||||
~CShellExtClassFactory();
|
||||
|
||||
//IUnknown members
|
||||
STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *);
|
||||
STDMETHODIMP_(ULONG) AddRef();
|
||||
STDMETHODIMP_(ULONG) Release();
|
||||
|
||||
//IClassFactory members
|
||||
STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR *);
|
||||
STDMETHODIMP LockServer(BOOL);
|
||||
|
||||
};
|
||||
typedef CShellExtClassFactory *LPCSHELLEXTCLASSFACTORY;
|
||||
class CShellExt : public IContextMenu,
|
||||
IShellExtInit,
|
||||
IExtractIcon,
|
||||
IPersistFile,
|
||||
IShellPropSheetExt,
|
||||
ICopyHook{
|
||||
public:
|
||||
char m_SelectedFile[MAX_PATH];
|
||||
void Read_SelectedFile();
|
||||
protected:
|
||||
// ITEMIDLIST m_idFolder;
|
||||
ULONG m_cRef;
|
||||
LPDATAOBJECT m_pDataObj;
|
||||
char m_szFileUserClickedOn[MAX_PATH];
|
||||
STDMETHODIMP DoW3DMenu1(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,LPCSTR pszParam, int iShowCmd);
|
||||
public:
|
||||
bool NotAdded(char* name);
|
||||
void Read_Selection(W3dMeshHeader3Struct&, W3D_HTree&, W3D_HAnim** );
|
||||
CShellExt();
|
||||
~CShellExt();
|
||||
|
||||
//IUnknown members
|
||||
STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *);
|
||||
STDMETHODIMP_(ULONG) AddRef();
|
||||
STDMETHODIMP_(ULONG) Release();
|
||||
|
||||
//IShell members
|
||||
STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
|
||||
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);
|
||||
STDMETHODIMP GetCommandString(UINT idCmd, UINT uFlags, UINT FAR *reserved, LPSTR pszName, UINT cchMax);
|
||||
//IShellExtInit methods
|
||||
STDMETHODIMP Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hKeyID);
|
||||
//IExtractIcon methods
|
||||
STDMETHODIMP GetIconLocation(UINT uFlags,LPSTR szIconFile,UINT cchMax,int *piIndex,UINT *pwFlags);
|
||||
STDMETHODIMP Extract(LPCSTR pszFile,UINT nIconIndex,HICON *phiconLarge,HICON *phiconSmall,UINT nIconSize);
|
||||
//IPersistFile methods
|
||||
STDMETHODIMP GetClassID(LPCLSID lpClassID);
|
||||
STDMETHODIMP IsDirty();
|
||||
STDMETHODIMP Load(LPCOLESTR lpszFileName, DWORD grfMode);
|
||||
STDMETHODIMP Save(LPCOLESTR lpszFileName, BOOL fRemember);
|
||||
STDMETHODIMP SaveCompleted(LPCOLESTR lpszFileName);
|
||||
STDMETHODIMP GetCurFile(LPOLESTR FAR* lplpszFileName);
|
||||
//IShellPropSheetExt methods
|
||||
STDMETHODIMP AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam);
|
||||
STDMETHODIMP ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam);
|
||||
//ICopyHook method
|
||||
STDMETHODIMP_(UINT) CopyCallback(HWND hwnd, UINT wFunc, UINT wFlags, LPCSTR pszSrcFile, DWORD dwSrcAttribs,LPCSTR pszDestFile, DWORD dwDestAttribs);
|
||||
public:
|
||||
W3dAnimHeaderStruct m_AnimInfos[MAX_ANIMS_INFILE];
|
||||
W3dHierarchyStruct m_Hierarchies[MAX_ANIMS_INFILE];
|
||||
CString m_Textures[MAX_TEXTURES_INFILE];
|
||||
int m_NumAdded;
|
||||
bool m_FileInMemory;
|
||||
CWdumpDoc m_WdumpDocument;
|
||||
int m_FoundMeshes;
|
||||
W3dMeshHeader3Struct m_Meshes[MAX_MESH];
|
||||
};
|
||||
|
||||
typedef CShellExt *LPCSHELLEXT;
|
||||
#endif // _SHELLEXT_H
|
||||
37
Code/Tools/W3DShellExt/shexinit.cpp
Normal file
37
Code/Tools/W3DShellExt/shexinit.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "priv.h"
|
||||
#include "shellext.h"
|
||||
STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
|
||||
LPDATAOBJECT pDataObj,
|
||||
HKEY hRegKey){
|
||||
// Initialize can be called more than once
|
||||
if(m_pDataObj){
|
||||
m_pDataObj->Release();
|
||||
}
|
||||
// duplicate the object pointer and registry handle
|
||||
if (pDataObj){
|
||||
m_pDataObj = pDataObj;
|
||||
pDataObj->AddRef();
|
||||
}
|
||||
// m_idFolder = *pIDFolder;
|
||||
ODS("Initialized");
|
||||
return NOERROR;
|
||||
}
|
||||
Reference in New Issue
Block a user