/* ** 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. } }