Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions Core/GameEngine/Include/GameClient/View.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,9 @@ class View : public Snapshot
const Coord3D &getPosition() const { return m_pos; } ///< Returns position camera is looking at
Coord2D getPosition2D() const { Coord2D c = { m_pos.x, m_pos.y }; return c; } ///< Returns position camera is looking at

virtual const Coord3D& get3DCameraPosition() const = 0; ///< Returns the actual camera position
virtual Coord3D get3DCameraPosition() const { Coord3D c={0,0,0}; return c; } ///< Returns the actual camera position
virtual Coord3D get3DCameraDirection() const { Coord3D c={0,0,0}; return c; } ///< Returns the actual camera view direction
virtual void set3DCameraLookAt(const Coord3D &pos, const Coord3D &dir, Real roll) {} ///< Set the actual camera position and view direction

virtual Real getZoom() { return m_zoom; }
virtual void setZoom(Real z) { m_zoom = z; }
Expand Down Expand Up @@ -395,11 +397,6 @@ class ViewDummy : public View
return 0;
}
virtual void forceRedraw() override {}
virtual const Coord3D& get3DCameraPosition() const override
{
static Coord3D zero = {0,0,0};
return zero;
}
virtual WorldToScreenReturn worldToScreenTriReturn(const Coord3D *w, ICoord2D *s ) override
{
return WTS_INVALID;
Expand Down
8 changes: 6 additions & 2 deletions Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DView.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,9 @@ class W3DView : public View, public SubsystemInterface

CameraClass *get3DCamera() const { return m_3DCamera; }

virtual const Coord3D& get3DCameraPosition() const override;
virtual Coord3D get3DCameraPosition() const override; ///< Returns the actual camera position
virtual Coord3D get3DCameraDirection() const override; ///< Returns the actual camera view direction
virtual void set3DCameraLookAt(const Coord3D &pos, const Coord3D &dir, Real roll) override; ///< Set the actual camera position and view direction

virtual void setCameraLock(ObjectID id) override;
virtual void setSnapMode( CameraLockType lockType, Real lockDist ) override;
Expand Down Expand Up @@ -295,7 +297,9 @@ class W3DView : public View, public SubsystemInterface
Real getDesiredZoom(Real x, Real y) const;
Real getMaxHeight(Real x, Real y) const;
Real getMaxZoom(Real x, Real y) const;
void setCameraTransform(); ///< set the transform matrix of m_3DCamera, based on m_pos & m_angle
void updateCameraTransform(); ///< update the transform matrix of m_3DCamera, based on m_pos & m_angle
void updateCameraClipPlanes();
void setCameraTransform(const Matrix3D &transform);
void buildCameraPosition(Vector3 &sourcePos, Vector3 &targetPos);
void buildCameraTransform(Matrix3D *transform, const Vector3 &sourcePos, const Vector3 &targetPos); ///< calculate (but do not set) the transform matrix of m_3DCamera, based on m_pos & m_angle
Bool zoomCameraToDesiredHeight();
Expand Down
62 changes: 49 additions & 13 deletions Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -705,13 +705,27 @@ Real W3DView::getMaxZoom(Real x, Real y) const
//-------------------------------------------------------------------------------------------------
/** set the transform matrix of m_3DCamera, based on m_pos & m_angle */
//-------------------------------------------------------------------------------------------------
void W3DView::setCameraTransform()
void W3DView::updateCameraTransform()
{
if (TheGlobalData->m_headless)
return;

m_cameraHasMovedSinceRequest = true;
updateCameraClipPlanes();

Vector3 sourcePos;
Vector3 targetPos;
buildCameraPosition(sourcePos, targetPos);

Matrix3D cameraTransform;
buildCameraTransform(&cameraTransform, sourcePos, targetPos);

setCameraTransform(cameraTransform);
}

//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
void W3DView::updateCameraClipPlanes()
{
Real farZ = 1200.0f;

if (m_useRealZoomCam) //WST 10.19.2002
Expand All @@ -730,18 +744,19 @@ void W3DView::setCameraTransform()
}

m_3DCamera->Set_Clip_Planes(NearZ, farZ);
}

//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
void W3DView::setCameraTransform(const Matrix3D &transform)
{
m_cameraHasMovedSinceRequest = true;

#if defined(RTS_DEBUG)
m_3DCamera->Set_View_Plane( m_FOV, -1 );
#endif

// rebuild it (even if we just did it due to camera constraints)
Vector3 sourcePos;
Vector3 targetPos;
buildCameraPosition(sourcePos, targetPos);
Matrix3D cameraTransform;
buildCameraTransform(&cameraTransform, sourcePos, targetPos);
m_3DCamera->Set_Transform( cameraTransform );
m_3DCamera->Set_Transform(transform);

if (TheTerrainRenderObject)
{
Expand Down Expand Up @@ -790,14 +805,35 @@ void W3DView::init()
}

//-------------------------------------------------------------------------------------------------
const Coord3D& W3DView::get3DCameraPosition() const
Coord3D W3DView::get3DCameraPosition() const
{
Vector3 camera = m_3DCamera->Get_Position();
static Coord3D pos;
pos.set( camera.X, camera.Y, camera.Z );
Coord3D pos = { camera.X, camera.Y, camera.Z };
return pos;
}

//-------------------------------------------------------------------------------------------------
Coord3D W3DView::get3DCameraDirection() const
{
Vector3 forward = m_3DCamera->Get_Forward_Dir();
Coord3D dir = { forward.X, forward.Y, forward.Z };
return dir;
}

//-------------------------------------------------------------------------------------------------
void W3DView::set3DCameraLookAt(const Coord3D &pos, const Coord3D &dir, Real roll)
{
Vector3 camPos(pos.x, pos.y, pos.z);
Vector3 camDir(dir.x, dir.y, dir.z);
Matrix3D transform;
transform.Look_At_Dir(camPos, camDir, roll);

updateCameraClipPlanes();
setCameraTransform(transform);

m_recalcCamera = false;
}

//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
void W3DView::reset()
Expand Down Expand Up @@ -1560,7 +1596,7 @@ void W3DView::update()
// (gth) C&C3 if m_isCameraSlaved then force the camera to update each frame
if (m_recalcCamera || m_isCameraSlaved)
{
setCameraTransform();
updateCameraTransform();
m_recalcCamera = false;
}

Expand Down
45 changes: 45 additions & 0 deletions Core/Libraries/Include/Lib/BaseType.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ struct RealRange
hi = 0.0f;
}

bool is(Real value) const
{
return lo == value && hi == value;
}

// combine the given range with us such that we now encompass
// both ranges
void combine( RealRange &other )
Expand All @@ -222,6 +227,11 @@ struct Coord2D
y = 0.0f;
}

bool is(Real value) const
{
return x == value && y == value;
}

Real length() const { return (Real)sqrt( x*x + y*y ); }
Real lengthSqr() const { return x*x + y*y; }

Expand Down Expand Up @@ -309,6 +319,11 @@ struct ICoord2D
y = 0;
}

bool is(Int value) const
{
return x == value && y == value;
}

Int length() const { return (Int)sqrt( (double)(x*x + y*y) ); }
};

Expand All @@ -322,6 +337,11 @@ struct Region2D
hi.zero();
}

bool is(Real value) const
{
return lo.is(value) && hi.is(value);
}

Real width() const { return hi.x - lo.x; }
Real height() const { return hi.y - lo.y; }
Bool isInRegion( Real x, Real y ) const { return (lo.x < x) && (x < hi.x) && (lo.y < y) && (y < hi.y); }
Expand All @@ -337,6 +357,11 @@ struct IRegion2D
hi.zero();
}

bool is(Int value) const
{
return lo.is(value) && hi.is(value);
}

Int width() const { return hi.x - lo.x; }
Int height() const { return hi.y - lo.y; }
Bool isInRegion( Int x, Int y ) const { return (lo.x < x) && (x < hi.x) && (lo.y < y) && (y < hi.y); }
Expand Down Expand Up @@ -376,6 +401,11 @@ struct Coord3D
z = 0.0f;
}

bool is(Real value) const
{
return x == value && y == value && z == value;
}

void add( const Coord3D *a )
{
x += a->x;
Expand Down Expand Up @@ -438,6 +468,11 @@ struct ICoord3D
y = 0;
z = 0;
}

bool is(Int value) const
{
return x == value && y == value && z == value;
}
};

// For alternative see AABoxClass
Expand All @@ -451,6 +486,11 @@ struct Region3D

void zero() { lo.zero(); hi.zero(); }

bool is(Real value) const
{
return lo.is(value) && hi.is(value);
}

void setFromPointsNoZ(const Coord3D* points, Int count)
{
lo.x = points[0].x;
Expand Down Expand Up @@ -515,6 +555,11 @@ struct IRegion3D
hi.zero();
}

bool is(Int value) const
{
return lo.is(value) && hi.is(value);
}

Int width() const { return hi.x - lo.x; }
Int height() const { return hi.y - lo.y; }
Int depth() const { return hi.z - lo.z; }
Expand Down
42 changes: 23 additions & 19 deletions Core/Libraries/Source/WWVegas/WWMath/matrix3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,26 +355,30 @@ Vector3 Matrix3D::Inverse_Rotate_Vector(const Vector3 &vect) const
*=============================================================================================*/
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)
Vector3 dir(t - p);
dir.Normalize();

dx = (t[0] - p[0]);
dy = (t[1] - p[1]);
dz = (t[2] - p[2]);
Look_At_Dir(p, dir, roll);
}

len1 = (float)WWMath::Sqrt(dx*dx + dy*dy + dz*dz);
len2 = (float)WWMath::Sqrt(dx*dx + dy*dy);

if (len1 != 0.0f) {
sinp = dz/len1;
cosp = len2/len1;
} else {
sinp = 0.0f;
cosp = 1.0f;
}
void Matrix3D::Look_At_Dir(const Vector3 &pos, const Vector3 &dir, float roll)
{
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)

float dx = dir.X;
float dy = dir.Y;
float dz = dir.Z;

// length of projection onto XY plane
float len2 = (float)WWMath::Sqrt(dx*dx + dy*dy);

// pitch
sinp = dz;
cosp = len2;
Comment thread
Skyaero42 marked this conversation as resolved.

// yaw
if (len2 != 0.0f) {
siny = dy/len2;
cosy = dx/len2;
Expand All @@ -388,9 +392,9 @@ void Matrix3D::Look_At(const Vector3 &p,const Vector3 &t,float roll)
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;
Row[0].W = pos.X;
Row[1].W = pos.Y;
Row[2].W = pos.Z;

// Yaw rotation to make the matrix look at the projection of the target
// into the x-y plane
Expand Down
4 changes: 4 additions & 0 deletions Core/Libraries/Source/WWVegas/WWMath/matrix3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ class Matrix3D
// Used for pointing cameras at targets.
void Look_At(const Vector3 &p,const Vector3 &t,float roll);

// Points the negative Z axis at dir.
// Used for looking with cameras into directions.
void Look_At_Dir(const Vector3 &pos, const Vector3 &dir, float roll);

// Previous look_at function follows the camera coordinate convention.
// This one follows the object convention used in Commando and G. I
// special cased this convention since it is used so much by us rather
Expand Down
5 changes: 2 additions & 3 deletions Generals/Code/GameEngine/Source/Common/MessageStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,14 @@ GameMessage::~GameMessage()
*/
const GameMessageArgumentType *GameMessage::getArgument( Int argIndex ) const
{
static const GameMessageArgumentType junk = { 0 };

int i=0;
for( GameMessageArgument *a = m_argList; a; a=a->m_next, i++ )
if (i == argIndex)
return &a->m_data;

DEBUG_CRASH(("argument not found"));
return &junk;
static const GameMessageArgumentType zero = { 0 };
return &zero;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,9 @@ GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage
msg->appendRealArgument( currentView.getZoom() );
msg->appendIntegerArgument( (Int)TheMouse->getMouseCursor() );
msg->appendPixelArgument( m_currentPos );
// TheSuperHackers @tweak Save 3D camera position and direction to recover optimal playback precision
msg->appendLocationArgument( TheTacticalView->get3DCameraPosition() );
msg->appendLocationArgument( TheTacticalView->get3DCameraDirection() );
}
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1929,6 +1929,8 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData )
const Real angle = msg->getArgument( 1 )->real;
const Real pitch = msg->getArgument( 2 )->real;
const Real zoom = msg->getArgument( 3 )->real;
const Mouse::MouseCursor mouseCursor = static_cast<Mouse::MouseCursor>(msg->getArgument( 4 )->integer);
const ICoord2D mousePos = msg->getArgument( 5 )->pixel;

// TheSuperHackers @info Definitely call in user mode to ensure the camera operates with auto-zoom
// over terrain elevations, because the Replay Camera does not store the absolute camera location,
Expand All @@ -1942,13 +1944,26 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData )
const Coord2D scroll = {0, 0};
TheTacticalView->userScrollBy(&scroll);

// TheSuperHackers @fix xezon 18/09/2025 Lock the new location to avoid user input from changing the camera in this frame.
if (msg->getArgumentCount() >= 8)
{
// TheSuperHackers @feature Override all the settings above with real camera position and view direction.
// This ensures that the camera looks EXACTLY like it was at the time of recording, no matter how the
// View is configured or tweaked. Note that the above settings are still required to set regardless, because
// when the replay camera is exited, then the pivot position and angles will be needed to build the camera
// where it was left off.
const Coord3D camPos = msg->getArgument( 6 )->location;
const Coord3D camDir = msg->getArgument( 7 )->location;

TheTacticalView->setUserControlled(false);
TheTacticalView->set3DCameraLookAt(camPos, camDir, 0.0f);
}

// TheSuperHackers @fix Lock the new location to avoid user input from changing the camera in this frame.
TheTacticalView->lockUserControlUntilFrame( getFrame() + 1 );

if (!TheLookAtTranslator->hasMouseMovedRecently())
{
TheMouse->setCursor( (Mouse::MouseCursor)(msg->getArgument( 4 )->integer) );
ICoord2D mousePos = msg->getArgument( 5 )->pixel;
TheMouse->setCursor( mouseCursor );
TheMouse->setPosition( mousePos.x, mousePos.y );
TheLookAtTranslator->setCurrentPos( mousePos );
}
Expand Down
Loading
Loading