| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685 |
- /*
- ** 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 <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: W3DTruckDraw.cpp
- // Draw Trucks. Actually, this draws rocket buggies.
- // Author: John Ahlquist, March 2002
- #include <stdlib.h>
- #include <math.h>
- #include "Common/Thing.h"
- #include "Common/ThingFactory.h"
- #include "Common/GameAudio.h"
- #include "Common/GlobalData.h"
- #include "Common/ThingTemplate.h"
- #include "Common/Xfer.h"
- #include "GameClient/Drawable.h"
- #include "GameClient/ParticleSys.h"
- #include "GameLogic/AIPathfind.h"
- #include "GameLogic/Weapon.h"
- #include "GameLogic/GameLogic.h" // for logic frame count
- #include "GameLogic/PartitionManager.h"
- #include "GameLogic/Locomotor.h"
- #include "GameLogic/Module/PhysicsUpdate.h"
- #include "GameLogic/Module/BodyModule.h"
- #include "GameLogic/Module/AIUpdate.h"
- #include "GameLogic/ScriptEngine.h"
- #include "W3DDevice/GameClient/W3DGameClient.h"
- #include "W3DDevice/GameClient/Module/W3DTruckDraw.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- //-------------------------------------------------------------------------------------------------
- W3DTruckDrawModuleData::W3DTruckDrawModuleData()
- {
- }
- //-------------------------------------------------------------------------------------------------
- W3DTruckDrawModuleData::~W3DTruckDrawModuleData()
- {
- }
- //-------------------------------------------------------------------------------------------------
- void W3DTruckDrawModuleData::buildFieldParse(MultiIniFieldParse& p)
- {
- W3DModelDrawModuleData::buildFieldParse(p);
- static const FieldParse dataFieldParse[] =
- {
- { "Dust", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_dustEffectName) },
- { "DirtSpray", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_dirtEffectName) },
- { "PowerslideSpray", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_powerslideEffectName) },
- { "LeftFrontTireBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_frontLeftTireBoneName) },
- { "RightFrontTireBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_frontRightTireBoneName) },
- { "LeftRearTireBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_rearLeftTireBoneName) },
- { "RightRearTireBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_rearRightTireBoneName) },
- { "MidLeftFrontTireBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_midFrontLeftTireBoneName) },
- { "MidRightFrontTireBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_midFrontRightTireBoneName) },
- { "MidLeftRearTireBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_midRearLeftTireBoneName) },
- { "MidRightRearTireBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_midRearRightTireBoneName) },
- { "MidLeftMidTireBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_midMidLeftTireBoneName) },
- { "MidRightMidTireBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_midMidRightTireBoneName) },
- { "TireRotationMultiplier", INI::parseReal, NULL, offsetof(W3DTruckDrawModuleData, m_rotationSpeedMultiplier) },
- { "PowerslideRotationAddition", INI::parseReal, NULL, offsetof(W3DTruckDrawModuleData, m_powerslideRotationAddition) },
- { "CabBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_cabBoneName) },
- { "TrailerBone", INI::parseAsciiString, NULL, offsetof(W3DTruckDrawModuleData, m_trailerBoneName) },
- { "CabRotationMultiplier", INI::parseReal, NULL, offsetof(W3DTruckDrawModuleData, m_cabRotationFactor) },
- { "TrailerRotationMultiplier", INI::parseReal, NULL, offsetof(W3DTruckDrawModuleData, m_trailerRotationFactor) },
- { "RotationDamping", INI::parseReal, NULL, offsetof(W3DTruckDrawModuleData, m_rotationDampingFactor) },
- { 0, 0, 0, 0 }
- };
- p.add(dataFieldParse);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- W3DTruckDraw::W3DTruckDraw( Thing *thing, const ModuleData* moduleData ) : W3DModelDraw( thing, moduleData ),
- m_dirtEffect(NULL), m_dustEffect(NULL), m_powerslideEffect(NULL), m_effectsInitialized(false),
- m_wasAirborne(false), m_isPowersliding(false),
- m_frontWheelRotation(0), m_rearWheelRotation(0), m_midFrontWheelRotation(0), m_midRearWheelRotation(0),
- m_frontRightTireBone(0), m_frontLeftTireBone(0), m_rearLeftTireBone(0),m_rearRightTireBone(0),
- m_midFrontRightTireBone(0), m_midFrontLeftTireBone(0), m_midRearLeftTireBone(0),m_midRearRightTireBone(0),
- m_midMidRightTireBone(0), m_midMidLeftTireBone(0), m_prevRenderObj(NULL)
- {
- const AudioEventRTS * event;
- event = thing->getTemplate()->getPerUnitSound("TruckLandingSound");
- if (event) {
- m_landingSound = *event;
- }
- event = thing->getTemplate()->getPerUnitSound("TruckPowerslideSound");
- if (event) {
- m_powerslideSound = *event;
- }
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- W3DTruckDraw::~W3DTruckDraw()
- {
- tossEmitters();
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void W3DTruckDraw::tossEmitters()
- {
- if (m_dustEffect)
- {
- m_dustEffect->attachToObject(NULL);
- m_dustEffect->destroy();
- m_dustEffect = NULL;
- }
- if (m_dirtEffect)
- {
- m_dirtEffect->attachToObject(NULL);
- m_dirtEffect->destroy();
- m_dirtEffect = NULL;
- }
- if (m_powerslideEffect)
- {
- m_powerslideEffect->attachToObject(NULL);
- m_powerslideEffect->destroy();
- m_powerslideEffect = NULL;
- }
- }
- //-------------------------------------------------------------------------------------------------
- void W3DTruckDraw::setFullyObscuredByShroud(Bool fullyObscured)
- {
- if (fullyObscured != getFullyObscuredByShroud())
- {
- if (fullyObscured)
- tossEmitters();
- else
- createEmitters();
- }
- W3DModelDraw::setFullyObscuredByShroud(fullyObscured);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- /**
- * Start creating debris from the tank treads
- */
- void W3DTruckDraw::createEmitters( void )
- {
- if (getDrawable()->isDrawableEffectivelyHidden())
- return;
- if (getW3DTruckDrawModuleData())
- {
- const ParticleSystemTemplate *sysTemplate;
- if (!m_dustEffect) {
- sysTemplate = TheParticleSystemManager->findTemplate(getW3DTruckDrawModuleData()->m_dustEffectName);
- if (sysTemplate)
- {
- m_dustEffect = TheParticleSystemManager->createParticleSystem( sysTemplate );
- m_dustEffect->attachToObject(getDrawable()->getObject());
- // important: mark it as do-not-save, since we'll just re-create it when we reload.
- m_dustEffect->setSaveable(FALSE);
- } else {
- if (!getW3DTruckDrawModuleData()->m_dustEffectName.isEmpty()) {
- DEBUG_LOG(("*** ERROR - Missing particle system '%s' in thing '%s'\n",
- getW3DTruckDrawModuleData()->m_dustEffectName.str(), getDrawable()->getObject()->getTemplate()->getName().str()));
- }
- }
- }
- if (!m_dirtEffect) {
- sysTemplate = TheParticleSystemManager->findTemplate(getW3DTruckDrawModuleData()->m_dirtEffectName);
- if (sysTemplate)
- {
- m_dirtEffect = TheParticleSystemManager->createParticleSystem( sysTemplate );
- m_dirtEffect->attachToObject(getDrawable()->getObject());
- // important: mark it as do-not-save, since we'll just re-create it when we reload.
- m_dirtEffect->setSaveable(FALSE);
- } else {
- if (!getW3DTruckDrawModuleData()->m_dirtEffectName.isEmpty()) {
- DEBUG_LOG(("*** ERROR - Missing particle system '%s' in thing '%s'\n",
- getW3DTruckDrawModuleData()->m_dirtEffectName.str(), getDrawable()->getObject()->getTemplate()->getName().str()));
- }
- }
- }
- if (!m_powerslideEffect) {
- sysTemplate = TheParticleSystemManager->findTemplate(getW3DTruckDrawModuleData()->m_powerslideEffectName);
- if (sysTemplate)
- {
- m_powerslideEffect = TheParticleSystemManager->createParticleSystem( sysTemplate );
- m_powerslideEffect->attachToObject(getDrawable()->getObject());
- // important: mark it as do-not-save, since we'll just re-create it when we reload.
- m_powerslideEffect->setSaveable(FALSE);
- } else {
- if (!getW3DTruckDrawModuleData()->m_powerslideEffectName.isEmpty()) {
- DEBUG_LOG(("*** ERROR - Missing particle system '%s' in thing '%s'\n",
- getW3DTruckDrawModuleData()->m_powerslideEffectName.str(), getDrawable()->getObject()->getTemplate()->getName().str()));
- }
- }
- }
- }
-
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- /**
- * Stop creating debris from the tank treads
- */
- void W3DTruckDraw::enableEmitters( Bool enable )
- {
- // don't check... if we are hidden the first time thru, then we'll never create the emitters.
- // eg, if we are loading a game and the unit is in a tunnel, he'll never get emitteres even when he exits.
- //if (!m_effectsInitialized)
- {
- createEmitters();
- m_effectsInitialized=true;
- }
- if (m_dustEffect)
- {
- if (enable)
- m_dustEffect->start();
- else
- m_dustEffect->stop();
- }
- if (m_dirtEffect)
- {
- if (enable)
- m_dirtEffect->start();
- else
- m_dirtEffect->stop();
- }
- if (m_powerslideEffect)
- {
- if (!enable)
- m_powerslideEffect->stop();
- }
- }
- //-------------------------------------------------------------------------------------------------
- void W3DTruckDraw::updateBones( void )
- {
- if( getW3DTruckDrawModuleData() )
- {
- //Front tires
- if( !getW3DTruckDrawModuleData()->m_frontLeftTireBoneName.isEmpty() )
- {
- m_frontLeftTireBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_frontLeftTireBoneName.str());
- DEBUG_ASSERTCRASH(m_frontLeftTireBone, ("Missing front-left tire bone %s in model %s\n", getW3DTruckDrawModuleData()->m_frontLeftTireBoneName.str(), getRenderObject()->Get_Name()));
- }
- if( !getW3DTruckDrawModuleData()->m_frontRightTireBoneName.isEmpty() )
- {
- m_frontRightTireBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_frontRightTireBoneName.str());
- DEBUG_ASSERTCRASH(m_frontRightTireBone, ("Missing front-right tire bone %s in model %s\n", getW3DTruckDrawModuleData()->m_frontRightTireBoneName.str(), getRenderObject()->Get_Name()));
- }
- //Rear tires
- if( !getW3DTruckDrawModuleData()->m_rearLeftTireBoneName.isEmpty() )
- {
- m_rearLeftTireBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_rearLeftTireBoneName.str());
- DEBUG_ASSERTCRASH(m_rearLeftTireBone, ("Missing rear-left tire bone %s in model %s\n", getW3DTruckDrawModuleData()->m_rearLeftTireBoneName.str(), getRenderObject()->Get_Name()));
- }
- if( !getW3DTruckDrawModuleData()->m_rearRightTireBoneName.isEmpty() )
- {
- m_rearRightTireBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_rearRightTireBoneName.str());
- DEBUG_ASSERTCRASH(m_rearRightTireBone, ("Missing rear-left tire bone %s in model %s\n", getW3DTruckDrawModuleData()->m_rearRightTireBoneName.str(), getRenderObject()->Get_Name()));
- }
- //midFront tires
- if( !getW3DTruckDrawModuleData()->m_midFrontLeftTireBoneName.isEmpty() )
- {
- m_midFrontLeftTireBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_midFrontLeftTireBoneName.str());
- DEBUG_ASSERTCRASH(m_midFrontLeftTireBone, ("Missing mid-front-left tire bone %s in model %s\n", getW3DTruckDrawModuleData()->m_midFrontLeftTireBoneName.str(), getRenderObject()->Get_Name()));
-
- m_midFrontRightTireBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_midFrontRightTireBoneName.str());
- DEBUG_ASSERTCRASH(m_midFrontRightTireBone, ("Missing mid-front-right tire bone %s in model %s\n", getW3DTruckDrawModuleData()->m_midFrontRightTireBoneName.str(), getRenderObject()->Get_Name()));
-
- if (!m_midFrontRightTireBone )
- {
- m_midFrontLeftTireBone = 0;
- }
- }
- //midRear tires
- if( !getW3DTruckDrawModuleData()->m_midRearLeftTireBoneName.isEmpty() )
- {
- m_midRearLeftTireBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_midRearLeftTireBoneName.str());
- DEBUG_ASSERTCRASH(m_midRearLeftTireBone, ("Missing mid-rear-left tire bone %s in model %s\n", getW3DTruckDrawModuleData()->m_midRearLeftTireBoneName.str(), getRenderObject()->Get_Name()));
- m_midRearRightTireBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_midRearRightTireBoneName.str());
- DEBUG_ASSERTCRASH(m_midRearRightTireBone, ("Missing mid-rear-right tire bone %s in model %s\n", getW3DTruckDrawModuleData()->m_midRearRightTireBoneName.str(), getRenderObject()->Get_Name()));
- if (!m_midRearRightTireBone)
- {
- m_midRearLeftTireBone = 0;
- }
- }
- //midMid tires
- if( !getW3DTruckDrawModuleData()->m_midMidLeftTireBoneName.isEmpty() )
- {
- m_midMidLeftTireBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_midMidLeftTireBoneName.str());
- DEBUG_ASSERTCRASH(m_midMidLeftTireBone, ("Missing mid-mid-left tire bone %s in model %s\n", getW3DTruckDrawModuleData()->m_midMidLeftTireBoneName.str(), getRenderObject()->Get_Name()));
- m_midMidRightTireBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_midMidRightTireBoneName.str());
- DEBUG_ASSERTCRASH(m_midMidRightTireBone, ("Missing mid-mid-right tire bone %s in model %s\n", getW3DTruckDrawModuleData()->m_midMidRightTireBoneName.str(), getRenderObject()->Get_Name()));
- if (!m_midMidRightTireBone)
- {
- m_midMidLeftTireBone = 0;
- }
- }
- //Cab
- if( !getW3DTruckDrawModuleData()->m_cabBoneName.isEmpty() )
- {
- m_cabBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_cabBoneName.str());
- DEBUG_ASSERTCRASH(m_cabBone, ("Missing cab bone %s in model %s\n", getW3DTruckDrawModuleData()->m_cabBoneName.str(), getRenderObject()->Get_Name()));
- m_trailerBone = getRenderObject()->Get_Bone_Index(getW3DTruckDrawModuleData()->m_trailerBoneName.str());
- }
- }
- m_prevRenderObj = getRenderObject();
- m_prevNumBones = m_prevRenderObj->Get_Num_Bones();
- }
- //-------------------------------------------------------------------------------------------------
- void W3DTruckDraw::setHidden(Bool h)
- {
- W3DModelDraw::setHidden(h);
- if (h)
- {
- enableEmitters(false);
- }
- }
- //-------------------------------------------------------------------------------------------------
- void W3DTruckDraw::onRenderObjRecreated(void)
- {
- //DEBUG_LOG(("Old obj %x, newObj %x, new bones %d, old bones %d\n",
- // m_prevRenderObj, getRenderObject(), getRenderObject()->Get_Num_Bones(),
- // m_prevNumBones));
- m_prevRenderObj = NULL;
- m_frontLeftTireBone = 0;
- m_frontRightTireBone = 0;
- m_rearLeftTireBone = 0;
- m_rearRightTireBone = 0;
- m_midFrontLeftTireBone = 0;
- m_midFrontRightTireBone = 0;
- m_midRearLeftTireBone = 0;
- m_midRearRightTireBone = 0;
- m_midMidLeftTireBone = 0;
- m_midMidRightTireBone = 0;
- updateBones();
- }
- //-------------------------------------------------------------------------------------------------
- /** Rotate and position wheels and other truck parts. */
- //-------------------------------------------------------------------------------------------------
- void W3DTruckDraw::doDrawModule(const Matrix3D* transformMtx)
- {
- W3DModelDraw::doDrawModule(transformMtx);
- if (!TheGlobalData->m_showClientPhysics)
- return;
- const W3DTruckDrawModuleData *moduleData = getW3DTruckDrawModuleData();
- if (moduleData==NULL) return; // shouldn't ever happen.
- Bool frozen = TheTacticalView->isTimeFrozen() && !TheTacticalView->isCameraMovementFinished();
- frozen = frozen || TheScriptEngine->isTimeFrozenDebug() || TheScriptEngine->isTimeFrozenScript();
- if (frozen)
- return;
- const Real ACCEL_THRESHOLD = 0.01f;
- const Real SIZE_CAP = 2.0f;
- // get object from logic
- Object *obj = getDrawable()->getObject();
- if (obj == NULL)
- return;
- if (getRenderObject()==NULL) return;
- if (getRenderObject() != m_prevRenderObj) {
- DEBUG_LOG(("W3DTruckDraw::doDrawModule - shouldn't update bones. jba\n"));
- updateBones();
- }
-
- // get object physics state
- PhysicsBehavior *physics = obj->getPhysics();
- if (physics == NULL)
- return;
- const Coord3D *vel = physics->getVelocity();
- Real speed = physics->getVelocityMagnitude();
- const TWheelInfo *wheelInfo = getDrawable()->getWheelInfo(); // note, can return null!
- AIUpdateInterface *ai = obj->getAI();
- if (m_cabBone && wheelInfo) {
- Matrix3D cabXfrm(1);
- cabXfrm.Make_Identity();
- Real desiredAngle = wheelInfo->m_wheelAngle*moduleData->m_cabRotationFactor;
- // Check goal angle.
- if (ai && ai->getPath())
- {
- Coord3D pointOnPath;
- ai->getPath()->peekCachedPointOnPath(pointOnPath);
- Real angleToGoal = ThePartitionManager->getRelativeAngle2D( obj, &pointOnPath );
- //DEBUG_LOG(("To goal %f, desired %f ", 180*angleToGoal/PI, 180*desiredAngle/PI));
- if (angleToGoal<0) {
- if (desiredAngle<angleToGoal) desiredAngle=angleToGoal;
- if (desiredAngle>0) desiredAngle = 0;
- } else {
- if (desiredAngle>angleToGoal) desiredAngle = angleToGoal;
- if (desiredAngle<0) desiredAngle = 0;
- }
- //DEBUG_LOG(("final desired %f ", 180*desiredAngle/PI));
- }
- Real deltaAngle = desiredAngle - m_curCabRotation;
- deltaAngle *= moduleData->m_rotationDampingFactor;
- m_curCabRotation += deltaAngle;
- cabXfrm.Rotate_Z(m_curCabRotation);
- getRenderObject()->Capture_Bone( m_cabBone );
- getRenderObject()->Control_Bone( m_cabBone, cabXfrm );
- if (m_trailerBone && wheelInfo) {
- desiredAngle = -wheelInfo->m_wheelAngle*moduleData->m_trailerRotationFactor;
- Real deltaAngle = desiredAngle - m_curTrailerRotation;
- deltaAngle *= moduleData->m_rotationDampingFactor;
- m_curTrailerRotation += deltaAngle;
- cabXfrm.Make_Identity();
- cabXfrm.Rotate_Z(m_curTrailerRotation);
- getRenderObject()->Capture_Bone( m_trailerBone );
- getRenderObject()->Control_Bone( m_trailerBone, cabXfrm );
- }
- }
- if (m_frontLeftTireBone || m_rearLeftTireBone)
- {
- Real powerslideRotationAddition = moduleData->m_powerslideRotationAddition;
- if (ai) {
- Locomotor *loco = ai->getCurLocomotor();
- if (loco) {
- if (loco->isMovingBackwards()) {
- speed = -speed; // rotate wheels backwards. jba.
- powerslideRotationAddition = -powerslideRotationAddition;
- }
- }
- }
- const Real rotationFactor = moduleData->m_rotationSpeedMultiplier;
- m_frontWheelRotation += rotationFactor*speed;
- if (m_isPowersliding)
- {
- m_rearWheelRotation += rotationFactor*(speed + powerslideRotationAddition);
- }
- else
- {
- m_rearWheelRotation += rotationFactor*speed;
- }
- // For now, just use the same values for mid wheels -- may want to do independent calcs later...
- m_midFrontWheelRotation = m_frontWheelRotation;
- m_midRearWheelRotation = m_rearWheelRotation;
- Matrix3D wheelXfrm(1);
- if (m_frontLeftTireBone && wheelInfo)
- {
- wheelXfrm.Make_Identity();
- wheelXfrm.Adjust_Z_Translation(wheelInfo->m_frontLeftHeightOffset);
- wheelXfrm.Rotate_Z(wheelInfo->m_wheelAngle);
- wheelXfrm.Rotate_Y(m_frontWheelRotation);
- getRenderObject()->Capture_Bone( m_frontLeftTireBone );
- getRenderObject()->Control_Bone( m_frontLeftTireBone, wheelXfrm );
- wheelXfrm.Make_Identity();
- wheelXfrm.Adjust_Z_Translation(wheelInfo->m_frontRightHeightOffset);
- wheelXfrm.Rotate_Z(wheelInfo->m_wheelAngle);
- wheelXfrm.Rotate_Y(m_frontWheelRotation);
- getRenderObject()->Capture_Bone( m_frontRightTireBone );
- getRenderObject()->Control_Bone( m_frontRightTireBone, wheelXfrm );
- }
- if (m_rearLeftTireBone && wheelInfo)
- {
- wheelXfrm.Make_Identity();
- wheelXfrm.Rotate_Y(m_rearWheelRotation);
- wheelXfrm.Adjust_Z_Translation(wheelInfo->m_rearLeftHeightOffset);
- getRenderObject()->Capture_Bone( m_rearLeftTireBone );
- getRenderObject()->Control_Bone( m_rearLeftTireBone, wheelXfrm );
- wheelXfrm.Make_Identity();
- wheelXfrm.Rotate_Y(m_rearWheelRotation);
- wheelXfrm.Adjust_Z_Translation(wheelInfo->m_rearRightHeightOffset);
- //@todo TROUBLE HERE, THE BONE INDICES DO NOT MATCH THE RENDEROBJECTS BONES, SOMETIMES
- getRenderObject()->Capture_Bone( m_rearRightTireBone );
- getRenderObject()->Control_Bone( m_rearRightTireBone, wheelXfrm );
- }
- if (m_midFrontLeftTireBone && wheelInfo)
- {
- wheelXfrm.Make_Identity();
- wheelXfrm.Adjust_Z_Translation(wheelInfo->m_frontLeftHeightOffset);
- wheelXfrm.Rotate_Z(wheelInfo->m_wheelAngle);
- wheelXfrm.Rotate_Y(m_midFrontWheelRotation);
- getRenderObject()->Capture_Bone( m_midFrontLeftTireBone );
- getRenderObject()->Control_Bone( m_midFrontLeftTireBone, wheelXfrm );
- wheelXfrm.Make_Identity();
- wheelXfrm.Adjust_Z_Translation(wheelInfo->m_frontRightHeightOffset);
- wheelXfrm.Rotate_Z(wheelInfo->m_wheelAngle);
- wheelXfrm.Rotate_Y(m_midFrontWheelRotation);
- getRenderObject()->Capture_Bone( m_midFrontRightTireBone );
- getRenderObject()->Control_Bone( m_midFrontRightTireBone, wheelXfrm );
- }
- if (m_midRearLeftTireBone && wheelInfo)
- {
- wheelXfrm.Make_Identity();
- wheelXfrm.Rotate_Y(m_midRearWheelRotation);
- wheelXfrm.Adjust_Z_Translation(wheelInfo->m_rearLeftHeightOffset);
- getRenderObject()->Capture_Bone( m_midRearLeftTireBone );
- getRenderObject()->Control_Bone( m_midRearLeftTireBone, wheelXfrm );
- wheelXfrm.Make_Identity();
- wheelXfrm.Rotate_Y(m_midRearWheelRotation);
- wheelXfrm.Adjust_Z_Translation(wheelInfo->m_rearRightHeightOffset);
- getRenderObject()->Capture_Bone( m_midRearRightTireBone );
- getRenderObject()->Control_Bone( m_midRearRightTireBone, wheelXfrm );
- }
- if (m_midMidLeftTireBone && wheelInfo)
- {
- wheelXfrm.Make_Identity();
- wheelXfrm.Rotate_Y(m_midRearWheelRotation);
- wheelXfrm.Adjust_Z_Translation(wheelInfo->m_rearLeftHeightOffset);
- getRenderObject()->Capture_Bone( m_midMidLeftTireBone );
- getRenderObject()->Control_Bone( m_midMidLeftTireBone, wheelXfrm );
- wheelXfrm.Make_Identity();
- wheelXfrm.Rotate_Y(m_midRearWheelRotation);
- wheelXfrm.Adjust_Z_Translation(wheelInfo->m_rearRightHeightOffset);
- getRenderObject()->Capture_Bone( m_midMidRightTireBone );
- getRenderObject()->Control_Bone( m_midMidRightTireBone, wheelXfrm );
- }
- }
- Bool wasPowersliding = m_isPowersliding;
- m_isPowersliding = false;
- if (physics->isMotive() && !obj->isSignificantlyAboveTerrain()) {
- enableEmitters(true);
- Coord3D accel = *physics->getAcceleration();
- accel.z = 0; // ignore gravitational force.
- Bool accelerating = accel.length()>ACCEL_THRESHOLD;
- //DEBUG_LOG(("Accel %f, speed %f\n", accel.length(), speed));
- if (accelerating) {
- Real dot = accel.x*vel->x + accel.y*vel->y;
- if (dot<0) {
- accelerating = false; // decelerating, actually.
- }
- }
- if (m_dustEffect) {
- // Need more dust the faster we go.
- if (speed>SIZE_CAP) {
- speed = SIZE_CAP;
- }
- m_dustEffect->setSizeMultiplier(speed);
- }
- if (m_dirtEffect) {
- if (wheelInfo && wheelInfo->m_framesAirborne>3) {
- Real factor = 1 + wheelInfo->m_framesAirborne/16;
- if (factor>2.0) factor = 2.0;
- m_dustEffect->setSizeMultiplier(factor*SIZE_CAP);
- m_dustEffect->trigger();
- m_landingSound.setObjectID(obj->getID());
- TheAudio->addAudioEvent(&m_landingSound);
- } else {
- if (!accelerating || speed>2.0f) {
- m_dirtEffect->stop();
- }
- }
- }
- if (m_powerslideEffect) {
- if (physics->getTurning() == TURN_NONE) {
- m_powerslideEffect->stop();
- } else {
- m_isPowersliding = true;
- m_powerslideEffect->start();
- }
- }
- if (m_dirtEffect) {
- if (!accelerating || speed>2.0f) {
- m_dirtEffect->stop();
- }
- }
- }
- else
- enableEmitters(false);
- m_wasAirborne = obj->isSignificantlyAboveTerrain();
- if(!wasPowersliding && m_isPowersliding) {
- // start sound
- m_powerslideSound.setObjectID(obj->getID());
- m_powerslideSound.setPlayingHandle(TheAudio->addAudioEvent(&m_powerslideSound));
- } else if (wasPowersliding && !m_isPowersliding) {
- TheAudio->removeAudioEvent(m_powerslideSound.getPlayingHandle());
- }
- }
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void W3DTruckDraw::crc( Xfer *xfer )
- {
- // extend base class
- W3DModelDraw::crc( xfer );
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer method
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void W3DTruckDraw::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // extend base class
- W3DModelDraw::xfer( xfer );
- // John A and Mark W say there is no data to save here
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void W3DTruckDraw::loadPostProcess( void )
- {
- // extend base class
- W3DModelDraw::loadPostProcess();
- // toss any existing ones (no need to re-create; we'll do that on demand)
- tossEmitters();
- } // end loadPostProcess
|