156 lines
5.9 KiB
C++

/*
** 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. //
// //
////////////////////////////////////////////////////////////////////////////////
// Snow.cpp ////////////////////////////////////////////////////////////////////////////////
// Snow Rendering implementation
// Author: Mark Wilczynski, July 2003
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "PreRTS.h" // This must go first in EVERY cpp file int the Game
#include "GameClient/Snow.h"
#include "GameClient/view.h"
#ifdef _INTERNAL
// for occasional debugging...
//#pragma optimize("", off)
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
#endif
SnowManager *TheSnowManager=NULL;
SnowManager::SnowManager()
{
m_time = 0;
m_velocity = 1;
m_isVisible = TRUE; //default to showing if it's enabled via INI.
}
void SnowManager::init( void )
{
//starting heights of each particle
//TODO: replace this lookup table with some kind of procedural method that takes x,y as input.
m_startingHeights=NEW Real [ SNOW_NOISE_X * SNOW_NOISE_Y];
m_time = 0;
updateIniSettings();
}
void SnowManager::updateIniSettings(void)
{
Real *dst=m_startingHeights;
//initialize a table of random starting positions for each particle.
Int boxDimensions = (Int)TheWeatherSetting->m_snowBoxDimensions;
for (Int y=0; y<SNOW_NOISE_Y; y++)
{
for (Int x=0; x<SNOW_NOISE_X; x++)
{
*dst=(Real)(rand()%(boxDimensions));
dst++;
}
}
m_velocity = TheWeatherSetting->m_snowVelocity;
m_frequencyScaleX = TheWeatherSetting->m_snowFrequencyScaleX;
m_frequencyScaleY = TheWeatherSetting->m_snowFrequencyScaleY;
m_amplitude = TheWeatherSetting->m_snowAmplitude;
m_pointSize = TheWeatherSetting->m_snowPointSize;
m_quadSize = TheWeatherSetting->m_snowQuadSize;
m_boxDimensions = TheWeatherSetting->m_snowBoxDimensions;
m_emitterSpacing = 1.0f/TheWeatherSetting->m_snowBoxDensity;
m_maxPointSize = TheWeatherSetting->m_snowMaxPointSize;
m_minPointSize = TheWeatherSetting->m_snowMinPointSize;
//Time for snow flake to make it from top to bottom of rendered cube around camera.
m_fullTimePeriod = m_boxDimensions/m_velocity;
}
void SnowManager::setVisible(Bool showWeather)
{
m_isVisible = showWeather;
}
void SnowManager::reset(void)
{
m_isVisible = TRUE; //default to showing if it's enabled via INI.
}
SnowManager::~SnowManager()
{
delete [] m_startingHeights;
m_startingHeights=NULL;
}
OVERRIDE<WeatherSetting> TheWeatherSetting = NULL;
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
const FieldParse WeatherSetting::m_weatherSettingFieldParseTable[] =
{
{ "SnowTexture", INI::parseAsciiString,NULL, offsetof( WeatherSetting, m_snowTexture ) },
{ "SnowFrequencyScaleX", INI::parseReal,NULL, offsetof( WeatherSetting, m_snowFrequencyScaleX ) },
{ "SnowFrequencyScaleY", INI::parseReal,NULL, offsetof( WeatherSetting, m_snowFrequencyScaleY ) },
{ "SnowAmplitude", INI::parseReal,NULL, offsetof( WeatherSetting, m_snowAmplitude ) },
{ "SnowPointSize", INI::parseReal,NULL, offsetof( WeatherSetting, m_snowPointSize ) },
{ "SnowMaxPointSize", INI::parseReal,NULL, offsetof( WeatherSetting, m_snowMaxPointSize ) },
{ "SnowMinPointSize", INI::parseReal,NULL, offsetof( WeatherSetting, m_snowMinPointSize ) },
{ "SnowQuadSize", INI::parseReal,NULL, offsetof( WeatherSetting, m_snowQuadSize ) },
{ "SnowBoxDimensions", INI::parseReal,NULL, offsetof( WeatherSetting, m_snowBoxDimensions ) },
{ "SnowBoxDensity", INI::parseReal,NULL, offsetof( WeatherSetting, m_snowBoxDensity ) },
{ "SnowVelocity", INI::parseReal,NULL, offsetof( WeatherSetting, m_snowVelocity ) },
{ "SnowPointSprites", INI::parseBool,NULL, offsetof( WeatherSetting, m_usePointSprites ) },
{ "SnowEnabled", INI::parseBool,NULL, offsetof( WeatherSetting, m_snowEnabled ) },
{ 0, 0, 0, 0 },
};
//-------------------------------------------------------------------------------------------------
void INI::parseWeatherDefinition( INI *ini )
{
if (TheWeatherSetting == NULL) {
TheWeatherSetting = newInstance(WeatherSetting);
} else if (ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES) {
WeatherSetting* ws = (WeatherSetting*) (TheWeatherSetting.getNonOverloadedPointer());
WeatherSetting* wsOverride = newInstance(WeatherSetting);
*wsOverride = *ws;
// Mark that it is an override.
wsOverride->markAsOverride();
ws->friend_getFinalOverride()->setNextOverride(wsOverride);
} else {
throw INI_INVALID_DATA;
}
WeatherSetting* weatherSet = (WeatherSetting*) (TheWeatherSetting.getNonOverloadedPointer());
weatherSet = (WeatherSetting*) (weatherSet->friend_getFinalOverride());
// parse the data
ini->initFromINI( weatherSet, TheWeatherSetting->getFieldParse() );
if (TheSnowManager)
TheSnowManager->updateIniSettings();
if (ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES) {
// Check to see if we overrode any textures.
// If we did, then we need to replace them in the model.
}
}