/*
** Command & Conquer Generals Zero Hour(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 .
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: W3DRopeDraw.cpp ////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, Aug 2002
// Desc: Rope drawing
///////////////////////////////////////////////////////////////////////////////////////////////////
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include
#include
#include "Common/Thing.h"
#include "Common/ThingTemplate.h"
#include "Common/Xfer.h"
#include "GameClient/ClientRandomValue.h"
#include "GameClient/Color.h"
#include "GameClient/Drawable.h"
#include "GameClient/GameClient.h"
#include "GameLogic/GameLogic.h"
#include "W3DDevice/GameClient/W3DDisplay.h"
#include "W3DDevice/GameClient/Module/W3DRopeDraw.h"
#include "WW3D2/Line3D.h"
#include "W3DDevice/GameClient/W3DScene.h"
#include "Common/GameState.h"
#ifdef _INTERNAL
// for occasional debugging...
//#pragma optimize("", off)
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
W3DRopeDraw::W3DRopeDraw( Thing *thing, const ModuleData* moduleData ) : DrawModule( thing, moduleData )
{
m_curLen = 0.0f;
m_maxLen = 1.0f;
m_width = 0.5f;
m_color.red = 0.0f;
m_color.green = 0.0f;
m_color.blue = 0.0f;
m_curSpeed = 0.0f;
m_maxSpeed = 0.0f;
m_accel = 0.0f;
m_wobbleLen = m_maxLen; // huge
m_wobbleAmp = 0.0f;
m_segments.clear();
m_curWobblePhase = 0.0f;
m_curZOffset = 0.0f;
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
void W3DRopeDraw::buildSegments()
{
DEBUG_ASSERTCRASH(m_segments.empty(), ("Hmmn, not empty"));
m_segments.clear();
Int numSegs = ceil(m_maxLen / m_wobbleLen);
Real eachLen = m_maxLen / (Real)numSegs;
Coord3D pos = *getDrawable()->getPosition();
for (int i = 0; i < numSegs; ++i, pos.z += eachLen)
{
SegInfo info;
Real axis = GameClientRandomValueReal(0, 2*PI);
info.wobbleAxisX = Cos(axis);
info.wobbleAxisY = Sin(axis);
info.line = NEW Line3DClass( Vector3(pos.x,pos.y,pos.z),
Vector3(pos.x,pos.y,pos.z+eachLen),
m_width * 0.5f, // width
m_color.red, // red
m_color.green, // green
m_color.blue, // blue
1.0f ); // transparency
info.softLine = NEW Line3DClass( Vector3(pos.x,pos.y,pos.z),
Vector3(pos.x,pos.y,pos.z+eachLen),
m_width, // width
m_color.red, // red
m_color.green, // green
m_color.blue, // blue
0.5f ); // transparency
W3DDisplay::m_3DScene->Add_Render_Object( info.line );
W3DDisplay::m_3DScene->Add_Render_Object( info.softLine );
m_segments.push_back(info);
}
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
void W3DRopeDraw::tossSegments()
{
// remove tracer from the scene and delete
for (std::vector::iterator it = m_segments.begin(); it != m_segments.end(); ++it)
{
if (it->line)
{
W3DDisplay::m_3DScene->Remove_Render_Object(it->line);
REF_PTR_RELEASE((it->line));
}
if (it->softLine)
{
W3DDisplay::m_3DScene->Remove_Render_Object(it->softLine);
REF_PTR_RELEASE((it->softLine));
}
}
m_segments.clear();
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
void W3DRopeDraw::initRopeParms(Real length, Real width, const RGBColor& color, Real wobbleLen, Real wobbleAmp, Real wobbleRate)
{
m_maxLen = max(1.0f, length);
m_curLen = 0.0f;
m_width = width;
m_color = color;
m_wobbleLen = min(m_maxLen, wobbleLen);
m_wobbleAmp = wobbleAmp;
m_wobbleRate = wobbleRate;
m_curZOffset = 0.0f;
tossSegments();
buildSegments();
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
void W3DRopeDraw::setRopeCurLen(Real length)
{
m_curLen = length;
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
void W3DRopeDraw::setRopeSpeed(Real curSpeed, Real maxSpeed, Real accel)
{
m_curSpeed = curSpeed;
m_maxSpeed = maxSpeed;
m_accel = accel;
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
W3DRopeDraw::~W3DRopeDraw()
{
tossSegments();
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
void W3DRopeDraw::doDrawModule(const Matrix3D* transformMtx)
{
if (m_segments.empty())
{
buildSegments();
}
if (!m_segments.empty())
{
Real deflection = Sin(m_curWobblePhase) * m_wobbleAmp;
const Coord3D* pos = getDrawable()->getPosition();
Vector3 start(pos->x, pos->y, pos->z + m_curZOffset);
Real eachLen = m_curLen / m_segments.size();
for (std::vector::iterator it = m_segments.begin(); it != m_segments.end(); ++it)
{
Vector3 end(pos->x + deflection*it->wobbleAxisX, pos->y + deflection*it->wobbleAxisY, start.Z - eachLen);
if (it->line)
(it->line)->Reset(start, end);
if (it->softLine)
(it->softLine)->Reset(start, end);
start = end;
}
}
m_curWobblePhase += m_wobbleRate;
if (m_curWobblePhase > 2*PI)
m_curWobblePhase -= 2*PI;
m_curZOffset += m_curSpeed;
m_curSpeed += m_accel;
if (m_curSpeed > m_maxSpeed)
m_curSpeed = m_maxSpeed;
else if (m_curSpeed < -m_maxSpeed)
m_curSpeed = -m_maxSpeed;
}
// ------------------------------------------------------------------------------------------------
/** CRC */
// ------------------------------------------------------------------------------------------------
void W3DRopeDraw::crc( Xfer *xfer )
{
// extend base class
DrawModule::crc( xfer );
} // end crc
// ------------------------------------------------------------------------------------------------
/** Xfer method
* Version Info:
* 1: Initial version */
// ------------------------------------------------------------------------------------------------
void W3DRopeDraw::xfer( Xfer *xfer )
{
// version
const XferVersion currentVersion = 1;
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
// extend base class
DrawModule::xfer( xfer );
// m_segments is not saved
// cur len
xfer->xferReal( &m_curLen );
// max len
xfer->xferReal( &m_maxLen );
// width
xfer->xferReal( &m_width );
// color
xfer->xferRGBColor( &m_color );
// cur speed
xfer->xferReal( &m_curSpeed );
// max speed
xfer->xferReal( &m_maxSpeed );
// acceleration
xfer->xferReal( &m_accel );
// wobble len
xfer->xferReal( &m_wobbleLen );
// wobble amp
xfer->xferReal( &m_wobbleAmp );
// wobble rate
xfer->xferReal( &m_wobbleRate );
// current wobble phase
xfer->xferReal( &m_curWobblePhase );
// cur Z offset
xfer->xferReal( &m_curZOffset );
if (xfer->getXferMode() == XFER_LOAD)
tossSegments();
} // end xfer
// ------------------------------------------------------------------------------------------------
/** Load post process */
// ------------------------------------------------------------------------------------------------
void W3DRopeDraw::loadPostProcess( void )
{
// extend base class
DrawModule::loadPostProcess();
} // end loadPostProcess