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

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

View file

@ -0,0 +1,124 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
#include "PreRTS.h"
#include "Common/BezFwdIterator.h"
//-------------------------------------------------------------------------------------------------
BezFwdIterator::BezFwdIterator(): mStep(0), mStepsDesired(0)
{
// Added by Sadullah Nader
mCurrPoint.zero();
mDDDq.zero();
mDDq.zero();
mDq.zero();
}
//-------------------------------------------------------------------------------------------------
BezFwdIterator::BezFwdIterator(Int stepsDesired, const BezierSegment *bezSeg)
{
// Added by Sadullah Nader
mCurrPoint.zero();
mDDDq.zero();
mDDq.zero();
mDq.zero();
//
mStepsDesired = stepsDesired;
mBezSeg = (*bezSeg);
}
//-------------------------------------------------------------------------------------------------
void BezFwdIterator::start(void)
{
mStep = 0;
if (mStepsDesired <= 1)
return;
float d = 1.0f / (mStepsDesired - 1);
float d2 = d * d;
float d3 = d * d2;
D3DXVECTOR4 px(mBezSeg.m_controlPoints[0].x, mBezSeg.m_controlPoints[1].x, mBezSeg.m_controlPoints[2].x, mBezSeg.m_controlPoints[3].x);
D3DXVECTOR4 py(mBezSeg.m_controlPoints[0].y, mBezSeg.m_controlPoints[1].y, mBezSeg.m_controlPoints[2].y, mBezSeg.m_controlPoints[3].y);
D3DXVECTOR4 pz(mBezSeg.m_controlPoints[0].z, mBezSeg.m_controlPoints[1].z, mBezSeg.m_controlPoints[2].z, mBezSeg.m_controlPoints[3].z);
D3DXVECTOR4 cVec[3];
D3DXVec4Transform(&cVec[0], &px, &BezierSegment::s_bezBasisMatrix);
D3DXVec4Transform(&cVec[1], &py, &BezierSegment::s_bezBasisMatrix);
D3DXVec4Transform(&cVec[2], &pz, &BezierSegment::s_bezBasisMatrix);
mCurrPoint = mBezSeg.m_controlPoints[0];
int i = 3;
while (i--) {
float a = cVec[i].x;
float b = cVec[i].y;
float c = cVec[i].z;
float *pD, *pDD, *pDDD;
if (i == 2) {
pD = &mDq.z;
pDD = &mDDq.z;
pDDD = &mDDDq.z;
} else if (i == 1) {
pD = &mDq.y;
pDD = &mDDq.y;
pDDD = &mDDDq.y;
} else if (i == 0) {
pD = &mDq.x;
pDD = &mDDq.x;
pDDD = &mDDDq.x;
}
(*pD) = a * d3 + b * d2 + c * d;
(*pDD) = 6 * a * d3 + 2 * b * d2;
(*pDDD) = 6 * a * d3;
}
}
//-------------------------------------------------------------------------------------------------
Bool BezFwdIterator::done(void)
{
return (mStep >= mStepsDesired);
}
//-------------------------------------------------------------------------------------------------
const Coord3D& BezFwdIterator::getCurrent(void) const
{
return mCurrPoint;
}
//-------------------------------------------------------------------------------------------------
void BezFwdIterator::next(void)
{
mCurrPoint.add(&mDq);
mDq.add(&mDDq);
mDDq.add(&mDDDq);
++mStep;
}

View file

@ -0,0 +1,246 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
#include "PreRTS.h"
#include "Common/BezierSegment.h"
#include "Common/BezFwdIterator.h"
#include <D3DX8Math.h>
//-------------------------------------------------------------------------------------------------
BezierSegment::BezierSegment()
{
for(int i=0; i < 4; i++)
m_controlPoints[i].zero();
}
//-------------------------------------------------------------------------------------------------
BezierSegment::BezierSegment(Real x0, Real y0, Real z0,
Real x1, Real y1, Real z1,
Real x2, Real y2, Real z2,
Real x3, Real y3, Real z3)
{
m_controlPoints[0].x = x0;
m_controlPoints[0].y = y0;
m_controlPoints[0].z = z0;
m_controlPoints[1].x = x1;
m_controlPoints[1].y = y1;
m_controlPoints[1].z = z1;
m_controlPoints[2].x = x2;
m_controlPoints[2].y = y2;
m_controlPoints[2].z = z2;
m_controlPoints[3].x = x3;
m_controlPoints[3].y = y3;
m_controlPoints[3].z = z3;
}
BezierSegment::BezierSegment(Real cp[12])
{
m_controlPoints[0].x = cp[0];
m_controlPoints[0].y = cp[1];
m_controlPoints[0].z = cp[2];
m_controlPoints[1].x = cp[3];
m_controlPoints[1].y = cp[4];
m_controlPoints[1].z = cp[5];
m_controlPoints[2].x = cp[6];
m_controlPoints[2].y = cp[7];
m_controlPoints[2].z = cp[8];
m_controlPoints[3].x = cp[9];
m_controlPoints[3].y = cp[10];
m_controlPoints[3].z = cp[11];
}
BezierSegment::BezierSegment(const Coord3D& cp0, const Coord3D& cp1, const Coord3D& cp2, const Coord3D& cp3)
{
m_controlPoints[0] = cp0;
m_controlPoints[1] = cp1;
m_controlPoints[2] = cp2;
m_controlPoints[3] = cp3;
}
BezierSegment::BezierSegment(Coord3D cp[4])
{
m_controlPoints[0] = cp[0];
m_controlPoints[1] = cp[1];
m_controlPoints[2] = cp[2];
m_controlPoints[3] = cp[3];
}
//-------------------------------------------------------------------------------------------------
void BezierSegment::evaluateBezSegmentAtT(Real tValue, Coord3D *outResult) const
{
if (!outResult)
return;
D3DXVECTOR4 tVec(tValue * tValue * tValue, tValue * tValue, tValue, 1);
D3DXVECTOR4 xCoords(m_controlPoints[0].x, m_controlPoints[1].x, m_controlPoints[2].x, m_controlPoints[3].x);
D3DXVECTOR4 yCoords(m_controlPoints[0].y, m_controlPoints[1].y, m_controlPoints[2].y, m_controlPoints[3].y);
D3DXVECTOR4 zCoords(m_controlPoints[0].z, m_controlPoints[1].z, m_controlPoints[2].z, m_controlPoints[3].z);
D3DXVECTOR4 tResult;
D3DXVec4Transform(&tResult, &tVec, &BezierSegment::s_bezBasisMatrix);
outResult->x = D3DXVec4Dot(&xCoords, &tResult);
outResult->y = D3DXVec4Dot(&yCoords, &tResult);
outResult->z = D3DXVec4Dot(&zCoords, &tResult);
}
//-------------------------------------------------------------------------------------------------
void BezierSegment::getSegmentPoints(Int numSegments, VecCoord3D *outResult) const
{
if (!outResult) {
return;
}
outResult->clear();
outResult->resize(numSegments);
BezFwdIterator iter(numSegments, this);
iter.start();
Int i = 0;
while (!iter.done()) {
(*outResult)[i] = iter.getCurrent();
++i;
iter.next();
}
}
//-------------------------------------------------------------------------------------------------
// This function isn't terribly fast. There are alternatives, and if this is too slow, we can
// take a look at the other approximations.
// There is no known close-form solution to this problem.
Real BezierSegment::getApproximateLength(Real withinTolerance) const
{
/*
How this works:
We can determine the approximate length of a bezier segment by
L0 = |(P0,P1)| + |(P1,P2)| + |(P2,P3)|
L1 = |(P0,P3)|
The length of the segment is approximately 1/2 L0 + 1/2 L1
P1__P2
/ \
P0----P3
The error in this is L1 - L0. If the error is too much, then we subdivide the curve and
try again.
*/
Coord3D p0p1 = { m_controlPoints[1].x - m_controlPoints[0].x,
m_controlPoints[1].y - m_controlPoints[0].y,
m_controlPoints[1].z - m_controlPoints[0].z, };
Coord3D p1p2 = { m_controlPoints[2].x - m_controlPoints[1].x,
m_controlPoints[2].y - m_controlPoints[1].y,
m_controlPoints[2].z - m_controlPoints[1].z, };
Coord3D p2p3 = { m_controlPoints[3].x - m_controlPoints[2].x,
m_controlPoints[3].y - m_controlPoints[2].y,
m_controlPoints[3].z - m_controlPoints[2].z, };
Coord3D p0p3 = { m_controlPoints[3].x - m_controlPoints[0].x,
m_controlPoints[3].y - m_controlPoints[0].y,
m_controlPoints[3].z - m_controlPoints[0].z, };
Real length0 = p0p3.length();
Real length1 = p0p1.length() + p1p2.length() + p2p3.length();
if ((length1 - length0) > withinTolerance) {
BezierSegment seg1, seg2;
splitSegmentAtT(0.5f, seg1, seg2);
return (seg1.getApproximateLength(withinTolerance) + seg2.getApproximateLength(withinTolerance));
}
return (INT_TO_REAL(length0 + length1) / 2.0f);
}
//-------------------------------------------------------------------------------------------------
void BezierSegment::splitSegmentAtT(Real tValue, BezierSegment &outSeg1, BezierSegment &outSeg2) const
{
// I think there are faster ways to do this. Could someone clue me in?
Coord3D p0p1 = { m_controlPoints[1].x - m_controlPoints[0].x,
m_controlPoints[1].y - m_controlPoints[0].y,
m_controlPoints[1].z - m_controlPoints[0].z, };
Coord3D p1p2 = { m_controlPoints[2].x - m_controlPoints[1].x,
m_controlPoints[2].y - m_controlPoints[1].y,
m_controlPoints[2].z - m_controlPoints[1].z, };
Coord3D p2p3 = { m_controlPoints[3].x - m_controlPoints[2].x,
m_controlPoints[3].y - m_controlPoints[2].y,
m_controlPoints[3].z - m_controlPoints[2].z, };
p0p1.scale(tValue);
p1p2.scale(tValue);
p2p3.scale(tValue);
p0p1.add(&m_controlPoints[0]);
p1p2.add(&m_controlPoints[1]);
p2p3.add(&m_controlPoints[2]);
Coord3D triLeft = { p1p2.x - p0p1.x,
p1p2.y - p0p1.y,
p1p2.z - p0p1.z, };
Coord3D triRight = { p2p3.x - p1p2.x,
p2p3.y - p1p2.y,
p2p3.z - p1p2.z, };
triLeft.scale(tValue);
triRight.scale(tValue);
triLeft.add(&p0p1);
triRight.add(&p1p2);
outSeg1.m_controlPoints[0] = m_controlPoints[0];
outSeg1.m_controlPoints[1] = p0p1;
outSeg1.m_controlPoints[2] = triLeft;
evaluateBezSegmentAtT(tValue, &outSeg1.m_controlPoints[3]);
outSeg2.m_controlPoints[0] = outSeg1.m_controlPoints[3];
outSeg2.m_controlPoints[1] = triRight;
outSeg2.m_controlPoints[2] = p2p3;
outSeg2.m_controlPoints[3] = m_controlPoints[3];
}
//-------------------------------------------------------------------------------------------------
// The Basis Matrix for a bezier segment
const D3DXMATRIX BezierSegment::s_bezBasisMatrix(
-1.0f, 3.0f, -3.0f, 1.0f,
3.0f, -6.0f, 3.0f, 0.0f,
-3.0f, 3.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 0.0f
);