| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310 |
- /*
- ** 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: W3DTerrainVisual.cpp /////////////////////////////////////////////////////////////////////
- // W3D implementation details for visual aspects of terrain
- // Author: Colin Day, April 2001
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- #include <stdio.h>
- #include <stdlib.h>
- #include <windows.h>
- #include "Common/GameState.h"
- #include "Common/GlobalData.h"
- #include "Common/PerfTimer.h"
- #include "Common/MapReaderWriterInfo.h"
- #include "Common/ThingTemplate.h"
- #include "Common/WellKnownKeys.h"
- #include "Common/TerrainTypes.h"
- #include "Common/Xfer.h"
- #include "Common/UnitTimings.h" //Contains the DO_UNIT_TIMINGS define jba.
- #include "Common/QuickTrig.h"
- #include "GameClient/Drawable.h"
- #include "GameClient/ClientRandomValue.h"
- #include "GameLogic/Object.h"
- #include "GameLogic/GameLogic.h"
- #include "W3DDevice/GameClient/W3DScene.h"
- #include "W3DDevice/GameClient/W3DTerrainVisual.h"
- #include "W3DDevice/GameClient/WorldHeightMap.h"
- #include "W3DDevice/GameClient/W3DWater.h"
- #include "W3DDevice/GameClient/W3DDisplay.h"
- #include "W3DDevice/GameClient/W3DDebugIcons.h"
- #include "W3DDevice/GameClient/W3DTerrainTracks.h"
- #include "W3DDevice/GameClient/W3DGranny.h"
- #include "W3DDevice/GameClient/W3DShadow.h"
- #include "W3DDevice/GameClient/heightmap.h"
- #include "W3DDevice/GameClient/FlatHeightmap.h"
- #include "W3DDevice/GameClient/W3DSmudge.h"
- #include "W3DDevice/GameClient/Module/W3DModelDraw.h"
- #include "WW3D2/Light.h"
- #include "WW3D2/RendObj.h"
- #include "WW3D2/ColType.h"
- #include "WW3D2/ColTest.h"
- #include "WW3D2/assetmgr.h"
- class TestSeismicFilter : public SeismicSimulationFilterBase
- {
- virtual SeismicSimStatusCode filterCallback( WorldHeightMapInterfaceClass *heightMap, const SeismicSimulationNode *node )
- {
- Int life = node->m_life;
- if ( heightMap == NULL )
- return SEISMIC_STATUS_INVALID;
- if ( life == 0 )
- return SEISMIC_STATUS_ACTIVE;
- if ( life < 15 )
- {
- // ADD HEIGHT BECAUSE THE EXPLOSION IS PUSHING DIRT UP
- Real magnitude = node->m_magnitude;
- Real offsScalar = magnitude / (Real)life; // real-life, get it?
- Int radius = node->m_radius;
- Int border = heightMap->getBorderSize();
- Int centerX = node->m_center.x + border ;
- Int centerY = node->m_center.y + border ;
-
- UnsignedInt workspaceWidth = radius*2;
- Real *workspace = NEW( Real[ sqr(workspaceWidth) ] );
- Real *workspaceEnd = workspace + sqr(workspaceWidth);
- for ( Real *t = workspace; t < workspaceEnd; ++t ) *t = 0.0f;// clear the workspace
- for (Int x = 0; x < radius; ++x)
- {
- for (Int y = 0; y < radius; ++y)
- {
- Real distance = sqrt( sqr(x) + sqr(y) );//Pythagoras
-
- if ( distance < radius )
- {
- Real distScalar = cos( ( distance / radius * (PI/2) ) );
- Real height = (offsScalar * distScalar);
- workspace[ (radius + x) + workspaceWidth * (radius + y) ] = height + heightMap->getBilinearSampleSeismicZVelocity( centerX + x, centerY + y ) ;//kaleidoscope
-
- if ( x != 0 ) // non-zero test prevents cross-shaped double stamp
- {
- workspace[ (radius - x) + workspaceWidth * (radius + y) ] = height + heightMap->getBilinearSampleSeismicZVelocity( centerX - x, centerY + y ) ;
- if ( y != 0 )
- workspace[ (radius - x) + workspaceWidth * (radius - y) ] = height + heightMap->getBilinearSampleSeismicZVelocity( centerX - x, centerY - y ) ;
- }
- if ( y != 0 )
- workspace[ (radius + x) + workspaceWidth * (radius - y) ] = height + heightMap->getBilinearSampleSeismicZVelocity( centerX + x, centerY - y ) ;
- }
- }
- }
- // stuff the values from the workspace into the heightmap's velocities
- for (x = 0; x < workspaceWidth; ++x)
- for (Int y = 0; y < workspaceWidth; ++y)
- heightMap->setSeismicZVelocity( centerX - radius + x, centerY - radius + y, workspace[ x + workspaceWidth * y ] );
- delete [] workspace;
- return SEISMIC_STATUS_ACTIVE;
- }
- else
- return SEISMIC_STATUS_ZERO_ENERGY;
- }
- virtual Real applyGravityCallback( Real velocityIn )
- {
- Real velocityOut = velocityIn;
- velocityOut -= 1.5f;
- return velocityOut;
- }
- };
- static TestSeismicFilter testSeismicFilter;
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- W3DTerrainVisual::W3DTerrainVisual()
- {
- m_terrainRenderObject = NULL;
- m_waterRenderObject = NULL;
- TheWaterRenderObj = NULL;
-
- m_logicHeightMap = NULL;
-
- #ifdef DO_SEISMIC_SIMULATIONS
- m_clientHeightMap = NULL;
- #endif
- } // end W3DTerrainVisual
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- W3DTerrainVisual::~W3DTerrainVisual()
- {
- // release our render object
- if (TheTerrainRenderObject == m_terrainRenderObject) {
- TheTerrainRenderObject = NULL;
- }
- if (TheTerrainTracksRenderObjClassSystem)
- {
- delete TheTerrainTracksRenderObjClassSystem;
- TheTerrainTracksRenderObjClassSystem=NULL;
- }
- #ifdef INCLUDE_GRANNY_IN_BUILD
- if (TheGrannyRenderObjSystem)
- {
- delete TheGrannyRenderObjSystem;
- TheGrannyRenderObjSystem=NULL;
- }
- #endif
- if (TheW3DShadowManager)
- {
- delete TheW3DShadowManager;
- TheW3DShadowManager=NULL;
- }
- if (TheSmudgeManager)
- {
- delete TheSmudgeManager;
- TheSmudgeManager=NULL;
- }
- REF_PTR_RELEASE( m_waterRenderObject );
- TheWaterRenderObj=NULL;
- REF_PTR_RELEASE( m_terrainRenderObject );
- REF_PTR_RELEASE( m_logicHeightMap );
- #ifdef DO_SEISMIC_SIMULATIONS
- REF_PTR_RELEASE( m_clientHeightMap );
- #endif
- } // end ~W3DTerrainVisual
- //-------------------------------------------------------------------------------------------------
- /** init */
- //-------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::init( void )
- {
- // extend
- TerrainVisual::init();
- // create a new render object for W3D
- m_terrainRenderObject = NEW_REF( HeightMapRenderObjClass, () );
- m_terrainRenderObject->Set_Collision_Type( PICK_TYPE_TERRAIN );
- TheTerrainRenderObject = m_terrainRenderObject;
- // initialize track drawing system
- TheTerrainTracksRenderObjClassSystem = NEW TerrainTracksRenderObjClassSystem;
- TheTerrainTracksRenderObjClassSystem->init(W3DDisplay::m_3DScene);
- #ifdef INCLUDE_GRANNY_IN_BUILD
- // initialize Granny model drawing system
- TheGrannyRenderObjSystem = NEW GrannyRenderObjSystem;
- #endif
- // initialize object shadow drawing system
- TheW3DShadowManager = NEW W3DShadowManager;
- TheW3DShadowManager->init();
-
- // create a water plane render object
- TheWaterRenderObj=m_waterRenderObject = NEW_REF( WaterRenderObjClass, () );
- m_waterRenderObject->init(TheGlobalData->m_waterPositionZ, TheGlobalData->m_waterExtentX, TheGlobalData->m_waterExtentY, W3DDisplay::m_3DScene, (WaterRenderObjClass::WaterType)TheGlobalData->m_waterType); //create a water plane that's 128x128 units
- m_waterRenderObject->Set_Position(Vector3(TheGlobalData->m_waterPositionX,TheGlobalData->m_waterPositionY,TheGlobalData->m_waterPositionZ)); //place water in world
- // create smudge rendering system.
- TheSmudgeManager = NEW(W3DSmudgeManager);
- TheSmudgeManager->init();
- #ifdef DO_UNIT_TIMINGS
- #pragma MESSAGE("********************* WARNING- Doing UNIT TIMINGS. ")
- #else
- if (TheGlobalData->m_waterType == WaterRenderObjClass::WATER_TYPE_1_FB_REFLECTION)
- { // add water render object to the pre-pass scene (to be rendered before main scene)
- //W3DDisplay::m_prePass3DScene->Add_Render_Object( m_waterRenderObject);
- }
- else
- { // add water render object to the post-pass scene (to be rendered after main scene)
- W3DDisplay::m_3DScene->Add_Render_Object( m_waterRenderObject);
- }
- #endif
- if (TheGlobalData->m_useCloudPlane)
- m_waterRenderObject->toggleCloudLayer(true);
- else
- m_waterRenderObject->toggleCloudLayer(false);
- // set the vertex animated water properties
- Int waterSettingIndex = 0; // use index 0 settings by default
- TheTerrainVisual->setWaterGridHeightClamps( NULL,
- TheGlobalData->m_vertexWaterHeightClampLow[ waterSettingIndex ],
- TheGlobalData->m_vertexWaterHeightClampHi[ waterSettingIndex ] );
- TheTerrainVisual->setWaterTransform( NULL,
- TheGlobalData->m_vertexWaterAngle[ waterSettingIndex ],
- TheGlobalData->m_vertexWaterXPosition[ waterSettingIndex ],
- TheGlobalData->m_vertexWaterYPosition[ waterSettingIndex ],
- TheGlobalData->m_vertexWaterZPosition[ waterSettingIndex ] );
- TheTerrainVisual->setWaterGridResolution( NULL,
- TheGlobalData->m_vertexWaterXGridCells[ waterSettingIndex ],
- TheGlobalData->m_vertexWaterYGridCells[ waterSettingIndex ],
- TheGlobalData->m_vertexWaterGridSize[ waterSettingIndex ] );
- TheTerrainVisual->setWaterAttenuationFactors( NULL,
- TheGlobalData->m_vertexWaterAttenuationA[ waterSettingIndex ],
- TheGlobalData->m_vertexWaterAttenuationB[ waterSettingIndex ],
- TheGlobalData->m_vertexWaterAttenuationC[ waterSettingIndex ],
- TheGlobalData->m_vertexWaterAttenuationRange[ waterSettingIndex ] );
- m_isWaterGridRenderingEnabled = FALSE;
- #ifdef DO_SEISMIC_SIMULATIONS
- m_seismicSimulationList.clear();
- #endif
- } // end init
- //-------------------------------------------------------------------------------------------------
- /** reset */
- //-------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::reset( void )
- {
- // extend
- TerrainVisual::reset();
- m_terrainRenderObject->reset();
- if (TheW3DShadowManager)
- TheW3DShadowManager->Reset();
- if (TheSmudgeManager)
- TheSmudgeManager->reset();
- if (TheTerrainTracksRenderObjClassSystem)
- TheTerrainTracksRenderObjClassSystem->Reset();
- // reset water render object if present
- if( m_waterRenderObject )
- {
- for (Int i=0; i<5; i++)
- {
- //check if this texture was ever changed from default
- if (m_currentSkyboxTexNames[i] != m_initialSkyboxTexNames[i])
- {
- m_waterRenderObject->replaceSkyboxTexture(m_currentSkyboxTexNames[i], m_initialSkyboxTexNames[i]);
- m_currentSkyboxTexNames[i]=m_initialSkyboxTexNames[i]; //update current state to new texture
- }
- }
- m_waterRenderObject->reset();
- }
- #ifdef DO_SEISMIC_SIMULATIONS
- m_seismicSimulationList.clear();
- #endif
-
- } // end reset
- //-------------------------------------------------------------------------------------------------
- /** update */
- //-------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::update( void )
- {
- // extend
- TerrainVisual::update();
- #ifdef DO_SEISMIC_SIMULATIONS
- handleSeismicSimulations();
- #endif
- // if we have a water render object, it has an update method
- if( m_waterRenderObject )
- m_waterRenderObject->update();
- } // end update
- #ifdef DO_SEISMIC_SIMULATIONS
- void W3DTerrainVisual::addSeismicSimulation( const SeismicSimulationNode& sim )
- {
- // HERE WOULD BE A GREAT PLACE FOR AN IDIOT TEST:
- // REJECT SIMULATION NODES THAT ARE OFF SCREEN!!!!!!!!!!
- // HERE WOULD BE A GREAT PLACE FOR AN IDIOT TEST:
- // REJECT SIMULATION NODES THAT ARE OFF SCREEN!!!!!!!!!!
- m_seismicSimulationList.push_back( sim );
- }
- void W3DTerrainVisual::handleSeismicSimulations( void )
- {
- if ( ! m_clientHeightMap || ! m_logicHeightMap || ! m_terrainRenderObject )
- return;
- if ( ! m_seismicSimulationList.empty() )
- {
- SeismicSimulationListIt it = m_seismicSimulationList.begin();
-
-
- m_clientHeightMap->clearSeismicUpdateFlags();
- while ( it != m_seismicSimulationList.end() )
- {
- SeismicSimulationNode *ssn = &*it;
- if ( ssn )
- {
- SeismicSimulationFilterBase::SeismicSimStatusCode code = ssn->handleFilterCallback( m_clientHeightMap );
- DEBUG_ASSERTCRASH( code != SeismicSimulationFilterBase::SEISMIC_STATUS_INVALID, ("Trouble in the Seismic simulator.") );
-
- switch ( code )
- {
- case SeismicSimulationFilterBase::SEISMIC_STATUS_ACTIVE:
- {
- break;
- }
- case SeismicSimulationFilterBase::SEISMIC_STATUS_ZERO_ENERGY:
- {
- break;
- }
- }
- Int border = m_clientHeightMap->getBorderSizeInline();
- // Now we apply some gravity to the dirt, so it falls back to its "original" height
- UnsignedInt fallCount = 0;
- for (Int x = border+ssn->m_region.lo.x; x < border+ssn->m_region.hi.x; ++x)
- {
- for (Int y = border+ssn->m_region.lo.y; y < border+ssn->m_region.hi.y; ++y)
- {
- if ( ! m_clientHeightMap->getSeismicUpdateFlag( x, y ) )
- {
- UnsignedByte heightOfOriginal = m_logicHeightMap->getHeight( x, y ); // LOGIC, YES DEFINITELY THE LOGIC
- Real oldSpeed = m_clientHeightMap->getSeismicZVelocity( x, y );
- Real newSpeed = ssn->applyGravity( oldSpeed );// - 0.5f;
-
- m_clientHeightMap->setSeismicZVelocity( x, y, newSpeed );
- Int heightToUse = m_clientHeightMap->getHeight( x, y ) + newSpeed ;
- if (heightToUse <= heightOfOriginal)
- {
- heightToUse = heightOfOriginal;
- m_clientHeightMap->setSeismicZVelocity( x, y, 0.0f ); //poof! the dirt hit ground level so stop "falling"
- }
- else
- {
- ++fallCount;
-
- if ( heightToUse > 255 )
- heightToUse = 255;
- }
- m_clientHeightMap->setRawHeight( x, y, heightToUse );
- m_clientHeightMap->setSeismicUpdateFlag( x, y, TRUE );
- }
-
- }
- }
- if ( fallCount == 0 )
- ssn->m_clean = TRUE;
- }
- ++it;
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- void W3DTerrainVisual::updateSeismicSimulations( void )
- {
- if (m_logicHeightMap==NULL)
- return;
- if (m_clientHeightMap==NULL)
- return;
- if (m_terrainRenderObject==NULL)
- return;
- if ( ! m_seismicSimulationList.empty() )
- {
- SeismicSimulationListIt it = m_seismicSimulationList.begin();
- // First we run through the list and do our business for each region
- while ( it != m_seismicSimulationList.end() )
- {
- SeismicSimulationNode *hur = &*it;
- if ( hur )
- {
- Int border = m_clientHeightMap->getBorderSizeInline();
- TheTerrainRenderObject->updateBlock(
- hur->m_region.lo.x + border,
- hur->m_region.lo.y + border,
- hur->m_region.hi.x + border,
- hur->m_region.hi.y + border,
- m_clientHeightMap,
- 0);
- }
- ++it;
- }
- // Then we check to see if these need to get erased from the list
- it = m_seismicSimulationList.begin();
- while ( it != m_seismicSimulationList.end() )
- {
- SeismicSimulationNode *hur = &*it;
- if ( hur->m_clean )
- {
- it = m_seismicSimulationList.erase( it );
- }
- else
- ++it;
- }
- }
- }
- #endif //#defined DO_SEISMIC_SIMULATIONS
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //-------------------------------------------------------------------------------------------------
- /** load method for W3D visual terrain */
- //-------------------------------------------------------------------------------------------------
- Bool W3DTerrainVisual::load( AsciiString filename )
- {
-
- #if 0
- // (gth) Testing exclusion list asset releasing
- DynamicVectorClass<StringClass> exclusion_list(8000);
-
- WW3DAssetManager::Get_Instance()->Create_Asset_List(exclusion_list);
- exclusion_list.Add(StringClass("avcomanche"));
- exclusion_list.Add(StringClass("avcomanche_d"));
- exclusion_list.Add(StringClass("ptdogwood08"));
- exclusion_list.Add(StringClass("ptdogwood01_b"));
- exclusion_list.Add(StringClass("ptpalm01"));
- exclusion_list.Add(StringClass("ptpalm01_b"));
- exclusion_list.Add(StringClass("avhummer"));
- exclusion_list.Add(StringClass("avhummer_d"));
- exclusion_list.Add(StringClass("avleopard"));
- exclusion_list.Add(StringClass("avleopard_d"));
- WW3DAssetManager::Get_Instance()->Free_Assets_With_Exclusion_List(exclusion_list);
- #endif
- // enhancing functionality specific for W3D terrain
- if( TerrainVisual::load( filename ) == FALSE )
- return FALSE; // failed
- // open the terrain file
- CachedFileInputStream fileStrm;
- if( !fileStrm.open(filename) )
- {
- REF_PTR_RELEASE( m_terrainRenderObject );
- return FALSE;
- } // end if
- if( m_terrainRenderObject == NULL )
- return FALSE;
- ChunkInputStream *pStrm = &fileStrm;
- // allocate new height map data to read from file
- REF_PTR_RELEASE( m_logicHeightMap );
- m_logicHeightMap = NEW WorldHeightMap(pStrm);
- #ifdef DO_SEISMIC_SIMULATIONS
- fileStrm.close();
- fileStrm.open(filename);
- pStrm = &fileStrm;
- REF_PTR_RELEASE( m_clientHeightMap );
- m_clientHeightMap = NEW WorldHeightMap( pStrm );
- #endif
- // Add any lights loaded by map.
- MapObject *pMapObj = MapObject::getFirstMapObject();
- while (pMapObj)
- {
- Dict *d = pMapObj->getProperties();
- if (pMapObj->isLight())
- {
- Coord3D loc = *pMapObj->getLocation();
- if (loc.z < 0) {
- Vector3 vec;
- loc.z = m_terrainRenderObject->getHeightMapHeight(loc.x, loc.y, NULL);
- loc.z += d->getReal(TheKey_lightHeightAboveTerrain);
- }
- // It is a light, and handled at the device level. jba.
- LightClass* lightP = NEW_REF(LightClass, (LightClass::POINT));
- RGBColor c;
- c.setFromInt(d->getInt(TheKey_lightAmbientColor));
- lightP->Set_Ambient( Vector3( c.red, c.green, c.blue ) );
- c.setFromInt(d->getInt(TheKey_lightDiffuseColor));
- lightP->Set_Diffuse( Vector3( c.red, c.green, c.blue) );
- lightP->Set_Position(Vector3(loc.x, loc.y, loc.z));
- lightP->Set_Far_Attenuation_Range(d->getReal(TheKey_lightInnerRadius), d->getReal(TheKey_lightOuterRadius));
- W3DDisplay::m_3DScene->Add_Render_Object(lightP);
- REF_PTR_RELEASE( lightP );
- }
- pMapObj = pMapObj->getNext();
- }
- RefRenderObjListIterator *it = W3DDisplay::m_3DScene->createLightsIterator();
- // apply the heightmap to the terrain render object
- #ifdef DO_SEISMIC_SIMULATIONS
- m_terrainRenderObject->initHeightData( m_clientHeightMap->getDrawWidth(),
- m_clientHeightMap->getDrawHeight(),
- m_clientHeightMap,
- it);
- #else
- m_terrainRenderObject->initHeightData( m_logicHeightMap->getDrawWidth(),
- m_logicHeightMap->getDrawHeight(),
- m_logicHeightMap,
- it);
- #endif
- if (it) {
- W3DDisplay::m_3DScene->destroyLightsIterator(it);
- it = NULL;
- }
- // add our terrain render object to the scene
- W3DDisplay::m_3DScene->Add_Render_Object( m_terrainRenderObject );
- #if defined _DEBUG || defined _INTERNAL
- // Icon drawing utility object for pathfinding.
- W3DDebugIcons *icons = NEW W3DDebugIcons;
- W3DDisplay::m_3DScene->Add_Render_Object( icons );
- icons->Release_Ref(); // belongs to scene.
- #endif
- #ifdef DO_UNIT_TIMINGS
- #pragma MESSAGE("********************* WARNING- Doing UNIT TIMINGS. ")
- #else
- if (m_waterRenderObject)
- {
- W3DDisplay::m_3DScene->Add_Render_Object( m_waterRenderObject);
- m_waterRenderObject->enableWaterGrid(false);
- m_waterRenderObject->updateMapOverrides();
- }
- #endif
- pMapObj = MapObject::getFirstMapObject();
- while (pMapObj)
- {
- Dict *d = pMapObj->getProperties();
- if (pMapObj->isScorch()) {
- const Coord3D *pos = pMapObj->getLocation();
- Vector3 loc(pos->x, pos->y, pos->z);
- Real radius = d->getReal(TheKey_objectRadius);
- Scorches type = (Scorches)d->getInt(TheKey_scorchType);
- m_terrainRenderObject->addScorch(loc, radius, type);
- }
- pMapObj = pMapObj->getNext();
- }
- // reset water render object if present
- if( m_waterRenderObject )
- {
- m_waterRenderObject->load();
- }
- return TRUE; // success
- } // end load
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::enableWaterGrid( Bool enable )
- {
- //Get default water type
- m_isWaterGridRenderingEnabled = enable;
- // make the changes in the water render object
- if( m_waterRenderObject )
- m_waterRenderObject->enableWaterGrid( enable );
- } // end enableWaterGrid
- //-------------------------------------------------------------------------------------------------
- /** intersect the ray with the terrain, if a hit occurs TRUE is returned
- * and the result point on the terrain is returned in "result" */
- //-------------------------------------------------------------------------------------------------
- Bool W3DTerrainVisual::intersectTerrain( Coord3D *rayStart,
- Coord3D *rayEnd,
- Coord3D *result )
- {
- Bool hit = FALSE;
- // sanity
- if( rayStart == NULL || rayEnd == NULL )
- return hit;
- if( m_terrainRenderObject )
- {
- CastResultStruct res;
- LineSegClass lineSeg( Vector3( rayStart->x, rayStart->y, rayStart->z ),
- Vector3( rayEnd->x, rayEnd->y, rayEnd->z ) );
- RayCollisionTestClass rayTest( lineSeg, &res );
- hit = m_terrainRenderObject->Cast_Ray( rayTest );
- if( hit && result )
- {
- Vector3 point = rayTest.Result->ContactPoint;
- result->x = point.X;
- result->y = point.Y;
- result->z = point.Z;
- } // end if
-
- } // end if
- // return hit result
- return hit;
- } // end intersectTerrain
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::getTerrainColorAt( Real x, Real y, RGBColor *pColor )
- {
- #ifdef DO_SEISMIC_SIMULATIONS
- if( m_clientHeightMap )
- m_clientHeightMap->getTerrainColorAt( x, y, pColor );
- #else
- if( m_logicHeightMap )
- m_logicHeightMap->getTerrainColorAt( x, y, pColor );
- #endif
- } // end getTerrainColorAt
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- TerrainType *W3DTerrainVisual::getTerrainTile( Real x, Real y )
- {
- TerrainType *tile = NULL;
- #ifdef DO_SEISMIC_SIMULATIONS
- if( m_clientHeightMap )
- {
- AsciiString tileName = m_clientHeightMap->getTerrainNameAt( x, y );
- tile = TheTerrainTypes->findTerrain( tileName );
- } // end if
- #else
- if( m_logicHeightMap )
- {
- AsciiString tileName = m_logicHeightMap->getTerrainNameAt( x, y );
- tile = TheTerrainTypes->findTerrain( tileName );
- } // end if
- #endif
- return tile;
- } // end getTerrainTile
- // ------------------------------------------------------------------------------------------------
- /** set min/max height values allowed in water grid pointed to by waterTable */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::setWaterGridHeightClamps( const WaterHandle *waterTable,
- Real minZ, Real maxZ )
- {
- if( m_waterRenderObject )
- m_waterRenderObject->setGridHeightClamps( minZ, maxZ );
- } // end setWaterGridHeightClamps
- // ------------------------------------------------------------------------------------------------
- /** adjust fallof parameters for grid change method */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::setWaterAttenuationFactors( const WaterHandle *waterTable,
- Real a, Real b, Real c, Real range )
- {
- if( m_waterRenderObject )
- m_waterRenderObject->setGridChangeAttenuationFactors( a, b, c, range );
- } // end setWaterAttenuationFactors
- // ------------------------------------------------------------------------------------------------
- /** set the water table position and orientation in world space */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::setWaterTransform( const WaterHandle *waterTable,
- Real angle, Real x, Real y, Real z )
- {
- if( m_waterRenderObject )
- m_waterRenderObject->setGridTransform( angle, x, y, z );
- } // end setWaterTransform
- // ------------------------------------------------------------------------------------------------
- /** set water table transform by matrix */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::setWaterTransform( const Matrix3D *transform )
- {
- if( m_waterRenderObject )
- m_waterRenderObject->setGridTransform( transform );
-
- } // end setWaterTransform
- // ------------------------------------------------------------------------------------------------
- /** get the water transform matrix */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::getWaterTransform( const WaterHandle *waterTable, Matrix3D *transform )
- {
- if( m_waterRenderObject )
- m_waterRenderObject->getGridTransform( transform );
- } // end getWaterTransform
- // ------------------------------------------------------------------------------------------------
- /** water grid resolution spacing */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::setWaterGridResolution( const WaterHandle *waterTable,
- Real gridCellsX, Real gridCellsY, Real cellSize )
- {
- if( m_waterRenderObject )
- m_waterRenderObject->setGridResolution( gridCellsX, gridCellsY, cellSize );
- } // end setWaterGridResolution
- // ------------------------------------------------------------------------------------------------
- /** get water grid resolution spacing */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::getWaterGridResolution( const WaterHandle *waterTable,
- Real *gridCellsX, Real *gridCellsY, Real *cellSize )
- {
- if( m_waterRenderObject )
- m_waterRenderObject->getGridResolution( gridCellsX, gridCellsY, cellSize );
- } // end getWaterGridResolution
- // ------------------------------------------------------------------------------------------------
- /** adjust the water grid in world coords by the delta */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::changeWaterHeight( Real x, Real y, Real delta )
- {
- if( m_waterRenderObject )
- m_waterRenderObject->changeGridHeight( x, y, delta );
- } // end changeWaterHeight
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::addWaterVelocity( Real worldX, Real worldY,
- Real velocity, Real preferredHeight )
- {
- if( m_waterRenderObject )
- m_waterRenderObject->addVelocity( worldX, worldY, velocity, preferredHeight );
- } // end addWaterVelocity
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- Bool W3DTerrainVisual::getWaterGridHeight( Real worldX, Real worldY, Real *height)
- {
- Real gridX, gridY;
- if (m_isWaterGridRenderingEnabled && m_waterRenderObject &&
- m_waterRenderObject->worldToGridSpace(worldX, worldY, gridX, gridY))
- { //point falls within grid, return correct height
- m_waterRenderObject->getGridVertexHeight(REAL_TO_INT(gridX),REAL_TO_INT(gridY),height);
- return TRUE;
- }
- return FALSE;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::setRawMapHeight(const ICoord2D *gridPos, Int height)
- {
- // This method writes to the m_logicHeightMap member,
- // since m_logicHeightMap is the true, golden standard to which m_clientHeightMap
- // interpolates during or after its Seismic simulation displaces it..
- // THIS IS TRUE ONLY WHEN DO_SEISMIC_SIMULATIONS is defined M Lorenzen, 8/23/03
- if (m_logicHeightMap)
- {
- Int x = gridPos->x+m_logicHeightMap->getBorderSizeInline();
- Int y = gridPos->y+m_logicHeightMap->getBorderSizeInline();
- //if (m_logicHeightMap->getHeight(x,y) != height) //ML changed to prevent scissoring with roads
- if (m_logicHeightMap->getHeight(x,y) > height)
- {
- m_logicHeightMap->setRawHeight(x, y, height);
- m_terrainRenderObject->staticLightingChanged(); // OOH! this could benefit from the new Seismic update code
- #ifdef DO_SEISMIC_SIMULATIONS
- if ( m_clientHeightMap )
- {
- if ( height < m_clientHeightMap->getHeight( x,y ) )
- m_clientHeightMap->setRawHeight( x, y, height ); // if the client map is heigher than this height, it will fall down to it anyway!
- }
- #endif
- }
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- Int W3DTerrainVisual::getRawMapHeight(const ICoord2D *gridPos)
- {
- if (m_logicHeightMap)
- {
- Int x = gridPos->x+m_logicHeightMap->getBorderSizeInline();
- Int y = gridPos->y+m_logicHeightMap->getBorderSizeInline();
- //if (m_logicHeightMap->getHeight(x,y) != height) //ML changed to prevent scissoring with roads
- return m_logicHeightMap->getHeight(x,y) ;
- }
- return 0;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::addFactionBibDrawable(Drawable *factionBuilding, Bool highlight, Real extra)
- {
- #ifdef DO_SEISMIC_SIMULATIONS
- if (m_clientHeightMap)
- #else
- if (m_logicHeightMap)
- #endif
- {
- const Matrix3D * mtx = factionBuilding->getTransformMatrix();
- Vector3 corners[4];
- Coord3D pos;
- pos.set(0,0,0);
- Real exitWidth = factionBuilding->getTemplate()->getFactoryExitWidth();
- Real extraWidth = factionBuilding->getTemplate()->getFactoryExtraBibWidth() + extra;
- const GeometryInfo info = factionBuilding->getTemplate()->getTemplateGeometryInfo();
- Real sizeX = info.getMajorRadius();
- Real sizeY = info.getMinorRadius();
- if (info.getGeomType() != GEOMETRY_BOX) {
- sizeY = sizeX;
- }
- corners[0].Set(pos.x, pos.y, pos.z);
- corners[0].X -= sizeX+extraWidth;
- corners[0].Y -= sizeY+extraWidth;
- corners[1].Set(pos.x, pos.y, pos.z);
- corners[1].X += sizeX+exitWidth+extraWidth;
- corners[1].Y -= sizeY+extraWidth;
- corners[2].Set(pos.x, pos.y, pos.z);
- corners[2].X += sizeX+exitWidth+extraWidth;
- corners[2].Y += sizeY+extraWidth;
- corners[3].Set(pos.x, pos.y, pos.z);
- corners[3].X -= sizeX+extraWidth;
- corners[3].Y += sizeY+extraWidth;
- mtx->Transform_Vector(*mtx, corners[0], &corners[0]);
- mtx->Transform_Vector(*mtx, corners[1], &corners[1]);
- mtx->Transform_Vector(*mtx, corners[2], &corners[2]);
- mtx->Transform_Vector(*mtx, corners[3], &corners[3]);
- m_terrainRenderObject->addTerrainBibDrawable(corners, factionBuilding->getID(), highlight);
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::addFactionBib(Object *factionBuilding, Bool highlight, Real extra)
- {
- #ifdef DO_SEISMIC_SIMULATIONS
- if (m_clientHeightMap)
- #else
- if (m_logicHeightMap)
- #endif
- {
- const Matrix3D * mtx = factionBuilding->getTransformMatrix();
- Vector3 corners[4];
- Coord3D pos;
- pos.set(0,0,0);
- Real exitWidth = factionBuilding->getTemplate()->getFactoryExitWidth();
- Real extraWidth = factionBuilding->getTemplate()->getFactoryExtraBibWidth() + extra;
- const GeometryInfo info = factionBuilding->getGeometryInfo();
- Real sizeX = info.getMajorRadius();
- Real sizeY = info.getMinorRadius();
- if (info.getGeomType() != GEOMETRY_BOX) {
- sizeY = sizeX;
- }
- corners[0].Set(pos.x, pos.y, pos.z);
- corners[0].X -= sizeX+extraWidth;
- corners[0].Y -= sizeY+extraWidth;
- corners[1].Set(pos.x, pos.y, pos.z);
- corners[1].X += sizeX+exitWidth+extraWidth;
- corners[1].Y -= sizeY+extraWidth;
- corners[2].Set(pos.x, pos.y, pos.z);
- corners[2].X += sizeX+exitWidth+extraWidth;
- corners[2].Y += sizeY+extraWidth;
- corners[3].Set(pos.x, pos.y, pos.z);
- corners[3].X -= sizeX+extraWidth;
- corners[3].Y += sizeY+extraWidth;
- mtx->Transform_Vector(*mtx, corners[0], &corners[0]);
- mtx->Transform_Vector(*mtx, corners[1], &corners[1]);
- mtx->Transform_Vector(*mtx, corners[2], &corners[2]);
- mtx->Transform_Vector(*mtx, corners[3], &corners[3]);
- m_terrainRenderObject->addTerrainBib(corners, factionBuilding->getID(), highlight);
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::removeFactionBibDrawable(Drawable *factionBuilding)
- {
- if (m_terrainRenderObject) {
- m_terrainRenderObject->removeTerrainBibDrawable(factionBuilding->getID());
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::removeFactionBib(Object *factionBuilding)
- {
- if (m_terrainRenderObject) {
- m_terrainRenderObject->removeTerrainBib(factionBuilding->getID());
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::removeAllBibs(void)
- {
- if (m_terrainRenderObject) {
- m_terrainRenderObject->removeAllTerrainBibs();
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::removeBibHighlighting(void)
- {
- if (m_terrainRenderObject) {
- m_terrainRenderObject->removeTerrainBibHighlighting();
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::removeTreesAndPropsForConstruction(const Coord3D* pos,
- const GeometryInfo& geom,
- Real angle)
- {
- if (m_terrainRenderObject) {
- m_terrainRenderObject->removeTreesAndPropsForConstruction(pos, geom, angle);
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::addProp(const ThingTemplate *tTemplate, const Coord3D *pos, Real angle)
- {
- ModelConditionFlags state;
- state.clear();
- if (TheGlobalData->m_weather == WEATHER_SNOWY)
- {
- state.set(MODELCONDITION_SNOW);
- }
- if (TheGlobalData->m_timeOfDay == TIME_OF_DAY_NIGHT)
- {
- state.set(MODELCONDITION_NIGHT);
- }
- AsciiString modelName;
- Real scale = tTemplate->getAssetScale();
- const ModuleInfo& mi = tTemplate->getDrawModuleInfo();
- if (mi.getCount() > 0)
- {
- const ModuleData* mdd = mi.getNthData(0);
- const W3DModelDrawModuleData* md = mdd ? mdd->getAsW3DModelDrawModuleData() : NULL;
- if (md)
- {
- modelName = md->getBestModelNameForWB(state);
- }
- }
- if (m_terrainRenderObject && modelName.isNotEmpty()) {
- m_terrainRenderObject->addProp(1, *pos, angle, scale, modelName);
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::setTerrainTracksDetail(void)
- {
- if (TheTerrainTracksRenderObjClassSystem)
- TheTerrainTracksRenderObjClassSystem->setDetail();
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::setShoreLineDetail(void)
- {
- if (m_terrainRenderObject)
- m_terrainRenderObject->setShoreLineDetail();
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- /// Replace the skybox texture
- void W3DTerrainVisual::replaceSkyboxTextures(const AsciiString *oldTexName[5], const AsciiString *newTexName[5])
- {
- if (m_waterRenderObject)
- {
- for (Int i=0; i<5; i++)
- {
- //check if this texture was never changed before and is still using the default art.
- if (m_initialSkyboxTexNames[i].isEmpty())
- { m_initialSkyboxTexNames[i]=*oldTexName[i];
- m_currentSkyboxTexNames[i]=*oldTexName[i];
- }
- if (m_currentSkyboxTexNames[i] != *newTexName[i])
- { m_waterRenderObject->replaceSkyboxTexture(m_currentSkyboxTexNames[i], *newTexName[i]);
- m_currentSkyboxTexNames[i]=*newTexName[i]; //update current state to new texture
- }
- }
- }
- }
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::crc( Xfer *xfer )
- {
- // extend base class
- TerrainVisual::crc( xfer );
- } // end CRC
- // ------------------------------------------------------------------------------------------------
- /** Xfer
- * Version Info:
- * 1: Initial version
- * 2: Add height map heights.
- * 3: Add client side trees & props. jba.
- */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 3;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // extend base class
- TerrainVisual::xfer( xfer );
- // flag for whether or not the water grid is enabled
- Bool gridEnabled = m_isWaterGridRenderingEnabled;
- xfer->xferBool( &gridEnabled );
- if( gridEnabled != m_isWaterGridRenderingEnabled )
- {
- DEBUG_CRASH(( "W3DTerrainVisual::xfer - m_isWaterGridRenderingEnabled mismatch\n" ));
- throw SC_INVALID_DATA;
- } // end if
- // xfer grid data if enabled
- if( gridEnabled )
- xfer->xferSnapshot( m_waterRenderObject );
- /*
- {
- // grid width and height
- Int width = getGridWidth();
- Int height = getGridheight();
- xfer->xferInt( &width );
- xfer->xferInt( &height );
- if( width != getGridWidth() )
- {
- DEBUG_CRASH(( "W3DTerainVisual::xfer - grid width mismatch '%d' should be '%d'\n",
- width, getGridWidth() ));
- throw SC_INVALID_DATA;
- } // end if
- if( height != getGridHeight() )
- {
- DEBUG_CRASH(( "W3DTerainVisual::xfer - grid height mismatch '%d' should be '%d'\n",
- height, getGridHeight() ));
- throw SC_INVALID_DATA;
- } // end if
- // write data for each grid
- } // end if
- */
- // Write out the terrain height data.
- if (version >= 2) {
- UnsignedByte *data = m_logicHeightMap->getDataPtr();
- Int len = m_logicHeightMap->getXExtent()*m_logicHeightMap->getYExtent();
- Int xferLen = len;
- xfer->xferInt(&xferLen);
- if (len!=xferLen) {
- DEBUG_CRASH(("Bad height map length."));
- if (len>xferLen) {
- len = xferLen;
- }
- }
- xfer->xferUser(data, len);
- if (xfer->getXferMode() == XFER_LOAD)
- {
- // Update the display height map.
- m_terrainRenderObject->staticLightingChanged();
- }
- }
- if (version >= 3) {
- xfer->xferSnapshot(m_terrainRenderObject);
- }
- // XFER //
- // X R //
- // X R //
- // XFER //
- ///// /USE CLIENT HEIGHT MAPCLIENT HEIGHT MAP
- // // /USE CLIENT HEIGHT MAPCLIENT HEIGHT MAP
- // ////USE CLIENT HEIGHT MAPCLIENT HEIGHT MAP----------------------------
- // // /USE CLIENT HEIGHT MAPCLIENT HEIGHT MAP ^
- ///// /USE CLIENT HEIGHT MAPCLIENT HEIGHT MAP 0
- // XFER //
- // X R //
- // X R //
- // XFER //
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void W3DTerrainVisual::loadPostProcess( void )
- {
- // extend base class
- TerrainVisual::loadPostProcess();
- } // end loadPostProcess
|