/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: W3DTerrainVisual.cpp /////////////////////////////////////////////////////////////////////
// W3D implementation details for visual aspects of terrain
// Author: Colin Day, April 2001
///////////////////////////////////////////////////////////////////////////////////////////////////
#include
#include
#include
#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 "GameClient/Drawable.h"
#include "GameLogic/Object.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 "WW3D2/Light.h"
#include "WW3D2/RendObj.h"
#include "WW3D2/ColType.h"
#include "WW3D2/ColTest.h"
#include "WW3D2/assetmgr.h"
#include "Common/UnitTimings.h" //Contains the DO_UNIT_TIMINGS define jba.
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
W3DTerrainVisual::W3DTerrainVisual()
{
m_terrainRenderObject = NULL;
m_terrainHeightMap = NULL;
m_waterRenderObject = NULL;
TheWaterRenderObj = NULL;
} // 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;
}
REF_PTR_RELEASE( m_waterRenderObject );
TheWaterRenderObj=NULL;
REF_PTR_RELEASE( m_terrainRenderObject );
REF_PTR_RELEASE( m_terrainHeightMap );
} // 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
#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;
} // end init
//-------------------------------------------------------------------------------------------------
/** reset */
//-------------------------------------------------------------------------------------------------
void W3DTerrainVisual::reset( void )
{
// extend
TerrainVisual::reset();
m_terrainRenderObject->reset();
if (TheW3DShadowManager)
TheW3DShadowManager->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();
}
} // end reset
//-------------------------------------------------------------------------------------------------
/** update */
//-------------------------------------------------------------------------------------------------
void W3DTerrainVisual::update( void )
{
// extend
TerrainVisual::update();
// if we have a water render object, it has an update method
if( m_waterRenderObject )
m_waterRenderObject->update();
} // end update
//-------------------------------------------------------------------------------------------------
/** load method for W3D visual terrain */
//-------------------------------------------------------------------------------------------------
Bool W3DTerrainVisual::load( AsciiString filename )
{
#if 0
// (gth) Testing exclusion list asset releasing
DynamicVectorClass 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;
REF_PTR_RELEASE( m_terrainHeightMap );
ChunkInputStream *pStrm = &fileStrm;
// allocate new height map data to read from file
m_terrainHeightMap = NEW WorldHeightMap(pStrm);
// 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
m_terrainRenderObject->initHeightData( m_terrainHeightMap->getDrawWidth(),
m_terrainHeightMap->getDrawHeight(),
m_terrainHeightMap,
it);
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);
}
#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 )
{
if( m_terrainHeightMap )
m_terrainHeightMap->getTerrainColorAt( x, y, pColor );
} // end getTerrainColorAt
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
TerrainType *W3DTerrainVisual::getTerrainTile( Real x, Real y )
{
TerrainType *tile = NULL;
if( m_terrainHeightMap )
{
AsciiString tileName = m_terrainHeightMap->getTerrainNameAt( x, y );
tile = TheTerrainTypes->findTerrain( tileName );
} // end if
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)
{
if (m_terrainHeightMap) {
Int x = gridPos->x+m_terrainHeightMap->getBorderSize();
Int y = gridPos->y+m_terrainHeightMap->getBorderSize();
//if (m_terrainHeightMap->getHeight(x,y) != height) //ML changed to prevent scissoring with roads
if (m_terrainHeightMap->getHeight(x,y) > height)
{
m_terrainHeightMap->setRawHeight(x, y, height);
m_terrainRenderObject->staticLightingChanged();
}
}
}
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
void W3DTerrainVisual::addFactionBibDrawable(Drawable *factionBuilding, Bool highlight, Real extra)
{
if (m_terrainHeightMap) {
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)
{
if (m_terrainHeightMap) {
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_terrainHeightMap) {
m_terrainRenderObject->removeTerrainBibDrawable(factionBuilding->getID());
}
}
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
void W3DTerrainVisual::removeFactionBib(Object *factionBuilding)
{
if (m_terrainHeightMap) {
m_terrainRenderObject->removeTerrainBib(factionBuilding->getID());
}
}
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
void W3DTerrainVisual::removeAllBibs(void)
{
if (m_terrainHeightMap) {
m_terrainRenderObject->removeAllTerrainBibs();
}
}
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
void W3DTerrainVisual::removeBibHighlighting(void)
{
if (m_terrainHeightMap) {
m_terrainRenderObject->removeTerrainBibHighlighting();
}
}
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
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 */
// ------------------------------------------------------------------------------------------------
void W3DTerrainVisual::xfer( Xfer *xfer )
{
// version
XferVersion currentVersion = 2;
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_terrainHeightMap->getDataPtr();
Int len = m_terrainHeightMap->getXExtent()*m_terrainHeightMap->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();
}
}
} // end xfer
// ------------------------------------------------------------------------------------------------
/** Load post process */
// ------------------------------------------------------------------------------------------------
void W3DTerrainVisual::loadPostProcess( void )
{
// extend base class
TerrainVisual::loadPostProcess();
} // end loadPostProcess