4075 lines
No EOL
198 KiB
C++
4075 lines
No EOL
198 KiB
C++
/*
|
|
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
|
***********************************************************************************************
|
|
* *
|
|
* Project Name : Commando *
|
|
* *
|
|
* $Archive:: /Commando/Code/Combat/backgroundmgr.cpp $*
|
|
* *
|
|
* Author:: Patrick Smith *
|
|
* *
|
|
* $Modtime:: 1/19/02 3:45p $*
|
|
* *
|
|
* $Revision:: 43 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
// Includes.
|
|
#include "backgroundmgr.h"
|
|
#include "apppackettypes.h"
|
|
#include "assetmgr.h"
|
|
#include "audiblesound.h"
|
|
#include "camera.h"
|
|
#include "dazzle.h"
|
|
#include "dx8wrapper.h"
|
|
#include "gameobjmanager.h"
|
|
#include "gametype.h"
|
|
#include "matrix3d.h"
|
|
#include "phys.h"
|
|
#include "pscene.h"
|
|
#include "random.h"
|
|
#include "rinfo.h"
|
|
#include "scene.h"
|
|
#include "soundenvironment.h"
|
|
#include "texture.h"
|
|
#include "wwaudio.h"
|
|
#include "wwmemlog.h"
|
|
#include "seglinerenderer.h"
|
|
#include "textureloader.h"
|
|
|
|
|
|
// Singletons.
|
|
BackgroundMgrClass _TheBackgroundMgr;
|
|
|
|
|
|
// Static data.
|
|
unsigned BackgroundMgrClass::_Hours;
|
|
unsigned BackgroundMgrClass::_Minutes;
|
|
BackgroundMgrClass::LightSourceTypeEnum BackgroundMgrClass::_LightSourceType;
|
|
SkyClass::MoonTypeEnum BackgroundMgrClass::_MoonType;
|
|
BackgroundParameterClass BackgroundMgrClass::_Parameters [PARAMETER_COUNT];
|
|
Vector3 BackgroundMgrClass::_LightVector;
|
|
Vector3 BackgroundMgrClass::_UnitLightVector;
|
|
unsigned BackgroundMgrClass::_CloudOverrideCount;
|
|
unsigned BackgroundMgrClass::_LightningOverrideCount;
|
|
unsigned BackgroundMgrClass::_SkyTintOverrideCount;
|
|
bool BackgroundMgrClass::_Dirty;
|
|
|
|
SkyClass *BackgroundMgrClass::_Sky = NULL;
|
|
DazzleRenderObjClass *BackgroundMgrClass::_Dazzle = NULL;
|
|
|
|
static Random2Class _RandomNumber (0x1f855092);
|
|
|
|
|
|
/***********************************************************************************************
|
|
* HazeClass::HazeClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
HazeClass::HazeClass (float radius)
|
|
: RowCount (ROW_COUNT)
|
|
{
|
|
const Vector3 white (1.0f, 1.0f, 1.0f);
|
|
const float longitude [ROW_COUNT + 1] = {1.22f, 1.55f, 1.57f, 1.92f};
|
|
const unsigned segmentcount = 16;
|
|
const float twopioosegmentcount = (1.0f / segmentcount) * 2.0f * WWMATH_PI;
|
|
|
|
unsigned row, segment;
|
|
unsigned v;
|
|
float latitude;
|
|
float x, y, z;
|
|
unsigned short i;
|
|
|
|
VertexCount = (RowCount + 1) * segmentcount;
|
|
TriangleCount = segmentcount * (RowCount * 2);
|
|
|
|
// Define vertices.
|
|
VertexArray = new Vector3 [VertexCount];
|
|
WWASSERT (VertexArray != NULL);
|
|
v = 0;
|
|
for (segment = 0; segment < segmentcount; segment++) {
|
|
latitude = segment * twopioosegmentcount;
|
|
for (row = 0; row < RowCount + 1; row++) {
|
|
x = radius * sinf (longitude [row]) * cosf (latitude);
|
|
y = radius * sinf (longitude [row]) * sinf (latitude);
|
|
z = radius * cosf (longitude [row]);
|
|
VertexArray [v].Set (x, y, z);
|
|
v++;
|
|
}
|
|
}
|
|
|
|
// Define triangles.
|
|
IndexBuffer = NEW_REF (DX8IndexBufferClass, (TriangleCount * VERTICES_PER_TRIANGLE));
|
|
{
|
|
DX8IndexBufferClass::WriteLockClass lock (IndexBuffer);
|
|
unsigned short *indices = lock.Get_Index_Array();
|
|
|
|
i = 0;
|
|
for (row = 0; row < RowCount; row++) {
|
|
v = row;
|
|
for (segment = 0; segment < segmentcount; segment++) {
|
|
|
|
// Is this not the last segment?
|
|
if (segment < segmentcount - 1) {
|
|
indices [i + 0] = v;
|
|
indices [i + 1] = v + RowCount + 1;
|
|
indices [i + 2] = v + RowCount + 2;
|
|
indices [i + 3] = v + RowCount + 2;
|
|
indices [i + 4] = v + 1;
|
|
indices [i + 5] = v;
|
|
} else {
|
|
indices [i + 0] = v;
|
|
indices [i + 1] = row;
|
|
indices [i + 2] = row + 1;
|
|
indices [i + 3] = row + 1;
|
|
indices [i + 4] = v + 1;
|
|
indices [i + 5] = v;
|
|
}
|
|
v += RowCount + 1;
|
|
i += 6;
|
|
}
|
|
}
|
|
}
|
|
|
|
Material = VertexMaterialClass::Get_Preset (VertexMaterialClass::PRELIT_NODIFFUSE);
|
|
|
|
Shader = ShaderClass::_PresetOpaque2DShader;
|
|
Shader.Set_Primary_Gradient (ShaderClass::GRADIENT_MODULATE);
|
|
Shader.Set_Texturing (ShaderClass::TEXTURING_DISABLE);
|
|
Shader.Set_Cull_Mode (ShaderClass::CULL_MODE_DISABLE);
|
|
|
|
DiffuseArray = new unsigned [VertexCount];
|
|
WWASSERT (DiffuseArray != NULL);
|
|
|
|
Configure (white, white, 1.0f);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* HazeClass::~HazeClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
HazeClass::~HazeClass()
|
|
{
|
|
// Clean-up.
|
|
delete [] DiffuseArray;
|
|
REF_PTR_RELEASE (Material);
|
|
REF_PTR_RELEASE (IndexBuffer);
|
|
delete [] VertexArray;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* HazeClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void HazeClass::Configure (const Vector3 &blendcolor, const Vector3 &horizoncolor, float intensity)
|
|
{
|
|
BlendColor = blendcolor;
|
|
HorizonColor = horizoncolor;
|
|
Intensity = intensity;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* HazeClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void HazeClass::Configure (const Vector3 &blendcolor, const Vector3 &horizoncolor)
|
|
{
|
|
BlendColor = blendcolor;
|
|
HorizonColor = horizoncolor;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* HazeClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void HazeClass::Configure (const Vector3 &blendcolor, float intensity)
|
|
{
|
|
BlendColor = blendcolor;
|
|
Intensity = intensity;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* HazeClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void HazeClass::Configure (const Vector3 &blendcolor)
|
|
{
|
|
BlendColor = blendcolor;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* HazeClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void HazeClass::Configure()
|
|
{
|
|
const unsigned d3dblendcolor = DX8Wrapper::Convert_Color (BlendColor, 1.0f);
|
|
const unsigned d3dhorizoncolor = DX8Wrapper::Convert_Color (HorizonColor * Intensity, 1.0f);
|
|
|
|
for (unsigned v = 0; v < VertexCount; v++) {
|
|
|
|
switch (v % (RowCount + 1)) {
|
|
|
|
case 0:
|
|
DiffuseArray [v] = d3dblendcolor;
|
|
break;
|
|
|
|
default:
|
|
DiffuseArray [v] = d3dhorizoncolor;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Haze is always visible.
|
|
Set_Visibility (true);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* HazeClass::Render -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void HazeClass::Render()
|
|
{
|
|
if (Is_Visible()) {
|
|
|
|
// Copy the vertices into a dynamic vertex buffer.
|
|
// NOTE: Vertex normals and UV's are uninitialized.
|
|
DynamicVBAccessClass dynamicvb (BUFFER_TYPE_DYNAMIC_DX8, dynamic_fvf_type, VertexCount);
|
|
{
|
|
DynamicVBAccessClass::WriteLockClass lock (&dynamicvb);
|
|
VertexFormatXYZNDUV2 *vertex = lock.Get_Formatted_Vertex_Array();
|
|
|
|
for (unsigned v = 0; v < VertexCount; v++) {
|
|
vertex->x = VertexArray [v].X;
|
|
vertex->y = VertexArray [v].Y;
|
|
vertex->z = VertexArray [v].Z;
|
|
vertex->diffuse = DiffuseArray [v];
|
|
vertex++;
|
|
}
|
|
}
|
|
|
|
DX8Wrapper::Set_Material (Material);
|
|
DX8Wrapper::Set_Shader (Shader);
|
|
DX8Wrapper::Set_Index_Buffer (IndexBuffer, 0);
|
|
DX8Wrapper::Set_Vertex_Buffer (dynamicvb);
|
|
DX8Wrapper::Draw_Triangles (0, TriangleCount, 0, VertexCount);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* StarfieldClass::StarfieldClass -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/18/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
StarfieldClass::StarfieldClass (float extent, unsigned starcount)
|
|
{
|
|
const Vector3 white (1.0f, 1.0f, 1.0f);
|
|
|
|
VertexCount = VERTICES_PER_TRIANGLE * starcount;
|
|
TriangleCount = starcount;
|
|
|
|
VertexArray = new Vector3 [VertexCount];
|
|
WWASSERT (VertexArray != NULL);
|
|
|
|
// Define triangles.
|
|
IndexBuffer = NEW_REF (DX8IndexBufferClass, (VertexCount));
|
|
{
|
|
DX8IndexBufferClass::WriteLockClass lock (IndexBuffer);
|
|
unsigned short *indices = lock.Get_Index_Array();
|
|
|
|
for (unsigned short i = 0; i < VertexCount; i++) {
|
|
indices [i] = i;
|
|
}
|
|
}
|
|
|
|
Material = VertexMaterialClass::Get_Preset (VertexMaterialClass::PRELIT_NODIFFUSE);
|
|
|
|
Shader = ShaderClass::_PresetAlpha2DShader;
|
|
Shader.Set_Primary_Gradient (ShaderClass::GRADIENT_MODULATE);
|
|
Shader.Set_Cull_Mode (ShaderClass::CULL_MODE_DISABLE);
|
|
|
|
Texture = WW3DAssetManager::Get_Instance()->Get_Texture ("Star.tga");
|
|
Texture->Set_U_Addr_Mode (TextureClass::TEXTURE_ADDRESS_CLAMP);
|
|
Texture->Set_V_Addr_Mode (TextureClass::TEXTURE_ADDRESS_CLAMP);
|
|
|
|
#ifdef WW3D_DX8
|
|
Set_Texture_Hint (Texture, srTextureIFace::HINT_ALPHA_ONLY);
|
|
#endif
|
|
|
|
DiffuseArray = new unsigned [VertexCount];
|
|
WWASSERT (DiffuseArray != NULL);
|
|
|
|
Configure (Vector3 (1.0f, 0.0f, 0.0f), 1.0f, 1.0f, white, white, 0.0f);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* StarfieldClass::~StarfieldClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/18/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
StarfieldClass::~StarfieldClass()
|
|
{
|
|
// Clean-up.
|
|
delete [] DiffuseArray;
|
|
REF_PTR_RELEASE (Texture);
|
|
REF_PTR_RELEASE (Material);
|
|
REF_PTR_RELEASE (IndexBuffer);
|
|
delete [] VertexArray;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* StarfieldClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/18/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void StarfieldClass::Configure (const Vector3 &orientation, float length, float radius, const Vector3 &color0, const Vector3 &color1, float alpha)
|
|
{
|
|
Orientation = orientation;
|
|
Length = length;
|
|
Radius = radius;
|
|
Color0 = color0;
|
|
Color1 = color1;
|
|
Alpha = alpha;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* StarfieldClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/18/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void StarfieldClass::Configure (const Vector3 &orientation, float length, float radius)
|
|
{
|
|
Orientation = orientation;
|
|
Length = length;
|
|
Radius = radius;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* StarfieldClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/18/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void StarfieldClass::Configure (const Vector3 &color0, const Vector3 &color1, float alpha)
|
|
{
|
|
Color0 = color0;
|
|
Color1 = color1;
|
|
Alpha = alpha;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* StarfieldClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/18/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void StarfieldClass::Configure()
|
|
{
|
|
const unsigned positionrandomness = 8192;
|
|
const float oopositionrandomnesstwo = 2.0f / positionrandomness;
|
|
const unsigned radiusrandomness = 16;
|
|
const float ooradiusrandomness = 1.0f / radiusrandomness;
|
|
const float minradius = 0.65f;
|
|
const float maxradius = 0.90f;
|
|
const unsigned intensityrandomness = 16;
|
|
const float oointensityrandomness = 1.0f / intensityrandomness;
|
|
const float theta = sinf (WWMATH_PI / 36);
|
|
|
|
Matrix3D m0;
|
|
unsigned t;
|
|
Vector3 colordifference;
|
|
float maxdp;
|
|
|
|
colordifference = Color1 - Color0;
|
|
m0.Look_At (Vector3 (0.0f, 0.0f, 0.0f), Orientation, 0.0f);
|
|
maxdp = Length / sqrtf ((Length * Length) + (Radius * Radius));
|
|
|
|
ActiveVertexCount = 0;
|
|
ActiveTriangleCount = 0;
|
|
for (t = 0; t < TriangleCount; t++) {
|
|
|
|
float x, y, z;
|
|
Vector3 d;
|
|
float r, intensity;
|
|
|
|
// NOTE: Generate all random numbers regardless of orientation to ensure a consistent starfield.
|
|
x = (_RandomNumber (0, positionrandomness) * oopositionrandomnesstwo) - 1.0f;
|
|
y = (_RandomNumber (0, positionrandomness) * oopositionrandomnesstwo) - 1.0f;
|
|
z = (_RandomNumber (0, positionrandomness) * oopositionrandomnesstwo) - 1.0f;
|
|
r = _RandomNumber (1, radiusrandomness) * ooradiusrandomness;
|
|
intensity = _RandomNumber (1, intensityrandomness) * oointensityrandomness;
|
|
d.Set (x, y, z);
|
|
d.Normalize();
|
|
d = m0 * d;
|
|
|
|
// Optimization: If the star is located an arbitrary angle above the horizon deem it visible.
|
|
if (d.Z >= theta) {
|
|
|
|
// Ensure that the star does not lie within the radius of the orientation vector
|
|
// (this area is reserved for another object).
|
|
if (Vector3::Dot_Product (d, Orientation) < maxdp) {
|
|
|
|
Matrix3D m1;
|
|
Vector3 color;
|
|
unsigned d3dcolor;
|
|
|
|
m1.Look_At (d * Length, d * Length * 2.0f, 0.0f);
|
|
|
|
r = pow (r, 10) * maxradius;
|
|
r = MAX (r, minradius);
|
|
VertexArray [ActiveVertexCount] = m1 * Vector3 (-r, -r, 0.0f);
|
|
VertexArray [ActiveVertexCount + 1] = m1 * Vector3 (-r, +r, 0.0f);
|
|
VertexArray [ActiveVertexCount + 2] = m1 * Vector3 (+r, -r, 0.0f);
|
|
|
|
color = Color0 + (colordifference * intensity);
|
|
d3dcolor = DX8Wrapper::Convert_Color (color, Alpha);
|
|
|
|
DiffuseArray [ActiveVertexCount + 0] = d3dcolor;
|
|
DiffuseArray [ActiveVertexCount + 1] = d3dcolor;
|
|
DiffuseArray [ActiveVertexCount + 2] = d3dcolor;
|
|
|
|
ActiveTriangleCount++;
|
|
ActiveVertexCount += VERTICES_PER_TRIANGLE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Optimization: If alpha is zero then stars are invisible.
|
|
Set_Visibility (Alpha > 0.0f);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* StarfieldClass::Render -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/18/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void StarfieldClass::Render()
|
|
{
|
|
if (Is_Visible()) {
|
|
|
|
const unsigned flickercount = 5;
|
|
const float flickeralpha = 0.6f;
|
|
|
|
unsigned activeflickercount;
|
|
float alpha, f, frac;
|
|
unsigned triangleindices [flickercount];
|
|
unsigned i, v;
|
|
|
|
// If time has gone by this frame...
|
|
if (WW3D::Get_Frame_Time() > 0) {
|
|
|
|
// Emulate flickering stars by attenuating some randomly selected diffuse alphas.
|
|
alpha = Alpha * flickeralpha;
|
|
f = flickercount * (((float) ActiveTriangleCount) / TriangleCount);
|
|
frac = f - floorf (f);
|
|
activeflickercount = (frac < 0.5f) ? floorf (f) : floorf (f) + 1;
|
|
for (i = 0; i < activeflickercount; i++) {
|
|
triangleindices [i] = _RandomNumber (0, ActiveTriangleCount - 1);
|
|
v = triangleindices [i] * VERTICES_PER_TRIANGLE;
|
|
DX8Wrapper::Set_Alpha (alpha, DiffuseArray [v + 0]);
|
|
DX8Wrapper::Set_Alpha (alpha, DiffuseArray [v + 1]);
|
|
DX8Wrapper::Set_Alpha (alpha, DiffuseArray [v + 2]);
|
|
}
|
|
|
|
} else {
|
|
activeflickercount = 0;
|
|
}
|
|
|
|
// Copy the vertices into a dynamic vertex buffer.
|
|
// NOTE: Vertex normals and stage 1 UV's are uninitialized.
|
|
DynamicVBAccessClass dynamicvb (BUFFER_TYPE_DYNAMIC_DX8, dynamic_fvf_type, ActiveVertexCount);
|
|
{
|
|
const float texcoordarray [VERTICES_PER_TRIANGLE][2] = {{0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}};
|
|
|
|
DynamicVBAccessClass::WriteLockClass lock (&dynamicvb);
|
|
VertexFormatXYZNDUV2 *vertex = lock.Get_Formatted_Vertex_Array();
|
|
|
|
for (unsigned v = 0; v < ActiveVertexCount; v += VERTICES_PER_TRIANGLE) {
|
|
for (unsigned t = 0; t < VERTICES_PER_TRIANGLE; t++) {
|
|
|
|
unsigned i = v + t;
|
|
|
|
vertex->x = VertexArray [i].X;
|
|
vertex->y = VertexArray [i].Y;
|
|
vertex->z = VertexArray [i].Z;
|
|
vertex->diffuse = DiffuseArray [i];
|
|
vertex->u1 = texcoordarray [t][0];
|
|
vertex->v1 = texcoordarray [t][1];
|
|
vertex++;
|
|
}
|
|
}
|
|
}
|
|
|
|
DX8Wrapper::Set_Texture (0, Texture);
|
|
DX8Wrapper::Set_Material (Material);
|
|
DX8Wrapper::Set_Shader (Shader);
|
|
DX8Wrapper::Set_Index_Buffer (IndexBuffer, 0);
|
|
DX8Wrapper::Set_Vertex_Buffer (dynamicvb);
|
|
DX8Wrapper::Draw_Triangles (0, ActiveTriangleCount, 0, ActiveVertexCount);
|
|
|
|
// Restore alphas for those stars that were modified prior to rendering.
|
|
for (i = 0; i < activeflickercount; i++) {
|
|
v = triangleindices [i] * VERTICES_PER_TRIANGLE;
|
|
DX8Wrapper::Set_Alpha (Alpha, DiffuseArray [v + 0]);
|
|
DX8Wrapper::Set_Alpha (Alpha, DiffuseArray [v + 1]);
|
|
DX8Wrapper::Set_Alpha (Alpha, DiffuseArray [v + 2]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyObjectClass::SkyObjectClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
SkyObjectClass::SkyObjectClass (ShaderClass shader)
|
|
: VertexCount (8),
|
|
TriangleCount (6)
|
|
{
|
|
const Vector3 white (1.0f, 1.0f, 1.0f);
|
|
|
|
VertexArray = new Vector3 [VertexCount];
|
|
WWASSERT (VertexArray != NULL);
|
|
|
|
// Define triangles.
|
|
// NOTE: For simplicity, assume that there are exactly 8 vertices and 6 triangles.
|
|
IndexBuffer = NEW_REF (DX8IndexBufferClass, (TriangleCount * VERTICES_PER_TRIANGLE));
|
|
{
|
|
static const unsigned short _indices [] = {0, 4, 5, 5, 1, 0, 1, 5, 6, 6, 2, 1, 2, 6, 7, 7, 3, 2};
|
|
|
|
DX8IndexBufferClass::WriteLockClass lock (IndexBuffer);
|
|
unsigned short *indices = lock.Get_Index_Array();
|
|
|
|
for (unsigned short i = 0; i < TriangleCount * VERTICES_PER_TRIANGLE; i++) {
|
|
indices [i] = _indices [i];
|
|
}
|
|
}
|
|
|
|
Material = VertexMaterialClass::Get_Preset (VertexMaterialClass::PRELIT_NODIFFUSE);
|
|
|
|
Shader = shader;
|
|
Shader.Set_Primary_Gradient (ShaderClass::GRADIENT_MODULATE);
|
|
Shader.Set_Src_Blend_Func (ShaderClass::SRCBLEND_SRC_ALPHA);
|
|
Shader.Set_Cull_Mode (ShaderClass::CULL_MODE_DISABLE);
|
|
|
|
Texture = NULL;
|
|
|
|
// Define texture coordinates.
|
|
// NOTE: Must be in clockwise order.
|
|
TexCoordArray = new Vector2 [VertexCount];
|
|
WWASSERT (TexCoordArray != NULL);
|
|
|
|
DiffuseArray = new unsigned [VertexCount];
|
|
WWASSERT (DiffuseArray != NULL);
|
|
|
|
Configure (Vector3 (1.0f, 0.0f, 0.0f), 1.0f, 1.0f, white);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyObjectClass::~SkyObjectClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
SkyObjectClass::~SkyObjectClass()
|
|
{
|
|
// Clean-up.
|
|
delete [] DiffuseArray;
|
|
delete [] TexCoordArray;
|
|
REF_PTR_RELEASE (Texture);
|
|
REF_PTR_RELEASE (Material);
|
|
REF_PTR_RELEASE (IndexBuffer);
|
|
delete [] VertexArray;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyObjectClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyObjectClass::Configure (const Vector3 &direction, float length, float radius, const Vector3 &color)
|
|
{
|
|
Direction = direction;
|
|
Length = length;
|
|
Width = radius;
|
|
Height = radius;
|
|
Color = color;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyObjectClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyObjectClass::Configure (const Vector3 &direction, float length, float width, float height)
|
|
{
|
|
Direction = direction;
|
|
Length = length;
|
|
Width = width;
|
|
Height = height;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyObjectClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyObjectClass::Configure (const Vector3 &direction, float length, float radius)
|
|
{
|
|
Direction = direction;
|
|
Length = length;
|
|
Width = radius;
|
|
Height = radius;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyObjectClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyObjectClass::Configure (const Vector3 &color)
|
|
{
|
|
Color = color;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyObjectClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyObjectClass::Configure()
|
|
{
|
|
const Vector3 black = Vector3 (0.0f, 0.0f, 0.0f);
|
|
const float defaultlambda [2] = {0.0f, 1.0f};
|
|
const float zblend [2] = {0.0f, 20.0f};
|
|
|
|
Matrix3D m;
|
|
float z0, z1;
|
|
bool visible;
|
|
float lambda [2];
|
|
|
|
m.Look_At (Direction * Length, Direction * (Length * 2.0f), 0.0f);
|
|
|
|
// Set the corner vertices.
|
|
// NOTE: For simplicity, assume that there are exactly 8 vertices.
|
|
VertexArray [0] = m * Vector3 (-Width, -Height, 0.0f);
|
|
TexCoordArray [0].Set (0.0f, 0.0f);
|
|
VertexArray [4] = m * Vector3 (+Width, -Height, 0.0f);
|
|
TexCoordArray [4].Set (1.0f, 0.0f);
|
|
VertexArray [7] = m * Vector3 (+Width, +Height, 0.0f);
|
|
TexCoordArray [7].Set (1.0f, 1.0f);
|
|
VertexArray [3] = m * Vector3 (-Width, +Height, 0.0f);
|
|
TexCoordArray [3].Set (0.0f, 1.0f);
|
|
|
|
z0 = VertexArray [0].Z;
|
|
z1 = VertexArray [3].Z;
|
|
|
|
for (unsigned r = 0; r < 2; r++) {
|
|
|
|
if (((z0 >= zblend [r]) && (z1 >= zblend [r])) || ((z0 <= zblend [r]) && (z1 <= zblend [r]))) {
|
|
lambda [r] = defaultlambda [r];
|
|
} else {
|
|
lambda [r] = (zblend [r] - z0) / (z1 - z0);
|
|
}
|
|
|
|
VertexArray [1 + r] = VertexArray [0] + lambda [r] * (VertexArray [3] - VertexArray [0]);
|
|
TexCoordArray [1 + r] = TexCoordArray [0] + lambda [r] * (TexCoordArray [3] - TexCoordArray [0]);
|
|
VertexArray [5 + r] = VertexArray [4] + lambda [r] * (VertexArray [7] - VertexArray [4]);
|
|
TexCoordArray [5 + r] = TexCoordArray [4] + lambda [r] * (TexCoordArray [7] - TexCoordArray [4]);
|
|
}
|
|
|
|
visible = false;
|
|
for (unsigned v = 0; v < VertexCount; v++) {
|
|
|
|
float alpha;
|
|
|
|
if (VertexArray [v].Z <= zblend [0]) {
|
|
alpha = 0.0f;
|
|
} else {
|
|
if (VertexArray [v].Z >= zblend [1]) {
|
|
alpha = 1.0f;
|
|
} else {
|
|
alpha = (VertexArray [v].Z - zblend [0]) / (zblend [1] - zblend [0]);
|
|
}
|
|
}
|
|
visible |= (alpha > 0.0f);
|
|
DiffuseArray [v] = DX8Wrapper::Convert_Color (Color, alpha);
|
|
}
|
|
|
|
// Optimization: If all vertex alphas are zero then the object is invisible.
|
|
Set_Visibility (visible);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyObjectClass::Set_Texture -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyObjectClass::Set_Texture (const char *texturename)
|
|
{
|
|
REF_PTR_RELEASE (Texture);
|
|
Texture = WW3DAssetManager::Get_Instance()->Get_Texture (texturename);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyObjectClass::Render -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyObjectClass::Render()
|
|
{
|
|
if (Is_Visible()) {
|
|
|
|
// Copy the vertices into the dynamic vertex buffer.
|
|
// NOTE: Vertex normals and stage 1 UV's are uninitialized.
|
|
DynamicVBAccessClass dynamicvb (BUFFER_TYPE_DYNAMIC_DX8, dynamic_fvf_type, VertexCount);
|
|
{
|
|
DynamicVBAccessClass::WriteLockClass lock (&dynamicvb);
|
|
VertexFormatXYZNDUV2 *vertex = lock.Get_Formatted_Vertex_Array();
|
|
|
|
for (unsigned v = 0; v < VertexCount; v++) {
|
|
vertex->x = VertexArray [v].X;
|
|
vertex->y = VertexArray [v].Y;
|
|
vertex->z = VertexArray [v].Z;
|
|
vertex->diffuse = DiffuseArray [v];
|
|
vertex->u1 = TexCoordArray [v].X;
|
|
vertex->v1 = TexCoordArray [v].Y;
|
|
vertex++;
|
|
}
|
|
}
|
|
|
|
DX8Wrapper::Set_Texture (0, Texture);
|
|
DX8Wrapper::Set_Material (Material);
|
|
DX8Wrapper::Set_Shader (Shader);
|
|
DX8Wrapper::Set_Index_Buffer (IndexBuffer, 0);
|
|
DX8Wrapper::Set_Vertex_Buffer (dynamicvb);
|
|
DX8Wrapper::Draw_Triangles (0, TriangleCount, 0, VertexCount);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CloudLayerClass::CloudLayerClass -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
CloudLayerClass::CloudLayerClass (float maxdistance, const char *texturename, const Vector2 &velocity, float tilefactor, bool rotate)
|
|
: RowCount (4)
|
|
{
|
|
const Vector3 white (1.0f, 1.0f, 1.0f);
|
|
const Vector3 black (0.0f, 0.0f, 0.0f);
|
|
|
|
const float radius = maxdistance;
|
|
const float maxlongitude = WWMATH_PI / 15;
|
|
const float oosinmaxlongitude = 1.0f / sinf (maxlongitude);
|
|
const float oorowcount = 1.0f / RowCount;
|
|
const unsigned segmentcount = 16;
|
|
const float twopioosegmentcount = (1.0f / segmentcount) * 2.0f * WWMATH_PI;
|
|
|
|
unsigned row, segment;
|
|
unsigned v;
|
|
unsigned short i;
|
|
float longitude, latitude;
|
|
float x, y, z;
|
|
float scale;
|
|
|
|
VertexCount = (RowCount + 1) * segmentcount;
|
|
TriangleCount = segmentcount * (RowCount * 2);
|
|
|
|
// Define vertices.
|
|
VertexArray = new Vector3 [VertexCount];
|
|
WWASSERT (VertexArray != NULL);
|
|
v = 0;
|
|
for (segment = 0; segment < segmentcount; segment++) {
|
|
latitude = segment * twopioosegmentcount;
|
|
for (row = 0; row < RowCount + 1; row++) {
|
|
longitude = (sinf (row * oorowcount * maxlongitude) * oosinmaxlongitude) * row * oorowcount * maxlongitude;
|
|
x = radius * sinf (longitude) * cosf (latitude);
|
|
y = radius * sinf (longitude) * sinf (latitude);
|
|
z = radius * (cosf (longitude) - cosf (maxlongitude));
|
|
VertexArray [v].Set (x, y, z);
|
|
v++;
|
|
}
|
|
}
|
|
|
|
// Define triangles.
|
|
IndexBuffer = NEW_REF (DX8IndexBufferClass, (TriangleCount * VERTICES_PER_TRIANGLE));
|
|
{
|
|
DX8IndexBufferClass::WriteLockClass lock (IndexBuffer);
|
|
unsigned short *indices = lock.Get_Index_Array();
|
|
|
|
i = 0;
|
|
for (row = 0; row < RowCount; row++) {
|
|
v = row;
|
|
for (segment = 0; segment < segmentcount; segment++) {
|
|
|
|
// Is this not the last segment?
|
|
if (segment < segmentcount - 1) {
|
|
indices [i + 0] = v;
|
|
indices [i + 1] = v + RowCount + 1;
|
|
indices [i + 2] = v + RowCount + 2;
|
|
indices [i + 3] = v + RowCount + 2;
|
|
indices [i + 4] = v + 1;
|
|
indices [i + 5] = v;
|
|
} else {
|
|
indices [i + 0] = v;
|
|
indices [i + 1] = row;
|
|
indices [i + 2] = row + 1;
|
|
indices [i + 3] = row + 1;
|
|
indices [i + 4] = v + 1;
|
|
indices [i + 5] = v;
|
|
}
|
|
v += RowCount + 1;
|
|
i += 6;
|
|
}
|
|
}
|
|
}
|
|
|
|
Material = VertexMaterialClass::Get_Preset (VertexMaterialClass::PRELIT_NODIFFUSE);
|
|
|
|
Shader = ShaderClass::_PresetAlpha2DShader;
|
|
Shader.Set_Primary_Gradient (ShaderClass::GRADIENT_MODULATE);
|
|
Shader.Set_Cull_Mode (ShaderClass::CULL_MODE_DISABLE);
|
|
|
|
Texture = WW3DAssetManager::Get_Instance()->Get_Texture (texturename, TextureClass::MIP_LEVELS_ALL, WW3D_FORMAT_UNKNOWN);
|
|
Texture->Set_U_Addr_Mode (TextureClass::TEXTURE_ADDRESS_REPEAT);
|
|
Texture->Set_V_Addr_Mode (TextureClass::TEXTURE_ADDRESS_REPEAT);
|
|
|
|
#if WW3D_DX8
|
|
Set_Texture_Hint (Texture, srTextureIFace::HINT_ALPHA_ONLY);
|
|
#endif
|
|
|
|
// Define texture UV's.
|
|
TexCoordArray = new Vector2 [VertexCount];
|
|
WWASSERT (TexCoordArray != NULL);
|
|
|
|
scale = tilefactor / (radius * sinf (maxlongitude));
|
|
for (v = 0; v < VertexCount; v++) {
|
|
if (rotate) {
|
|
TexCoordArray [v] = Vector2 (VertexArray [v].Y, VertexArray [v].X) * scale;
|
|
} else {
|
|
TexCoordArray [v] = Vector2 (VertexArray [v].X, VertexArray [v].Y) * scale;
|
|
}
|
|
}
|
|
|
|
if (rotate) {
|
|
Velocity.X = velocity.Y;
|
|
Velocity.Y = velocity.X;
|
|
} else {
|
|
Velocity = velocity;
|
|
}
|
|
Velocity *= tilefactor;
|
|
|
|
DiffuseArray = new unsigned [VertexCount];
|
|
WWASSERT (DiffuseArray != NULL);
|
|
|
|
WarmColor = white;
|
|
ColdColor = white;
|
|
WarmDirection = Vector3 (1.0f, 0.0f, 0.0f);
|
|
Alpha = 1.0f;
|
|
CloudIntensity = 1.0f;
|
|
HorizonIntensity = 1.0f;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CloudLayerClass::~CloudLayerClass -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
CloudLayerClass::~CloudLayerClass()
|
|
{
|
|
delete [] DiffuseArray;
|
|
delete [] TexCoordArray;
|
|
REF_PTR_RELEASE (Texture);
|
|
REF_PTR_RELEASE (Material);
|
|
REF_PTR_RELEASE (IndexBuffer);
|
|
delete [] VertexArray;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CloudLayerClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void CloudLayerClass::Configure (const Vector3 &warmcolor, const Vector3 &coldcolor)
|
|
{
|
|
WarmColor = warmcolor;
|
|
ColdColor = coldcolor;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CloudLayerClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void CloudLayerClass::Configure (const Vector3 &warmdirection)
|
|
{
|
|
WarmDirection = warmdirection;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CloudLayerClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void CloudLayerClass::Configure (const Vector3 &warmcolor, const Vector3 &coldcolor, const Vector3 &warmdirection)
|
|
{
|
|
WarmColor = warmcolor;
|
|
ColdColor = coldcolor;
|
|
WarmDirection = warmdirection;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CloudLayerClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void CloudLayerClass::Configure (float alpha, float cloudintensity, float horizonintensity)
|
|
{
|
|
Alpha = alpha;
|
|
CloudIntensity = cloudintensity;
|
|
HorizonIntensity = horizonintensity;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CloudLayerClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void CloudLayerClass::Configure()
|
|
{
|
|
const Vector3 cap (1.0f, 1.0f, 1.0f);
|
|
|
|
Vector3 warmcloudcolor, coldcloudcolor, warmhorizoncolor, coldhorizoncolor;
|
|
|
|
warmcloudcolor = WarmColor * CloudIntensity;
|
|
coldcloudcolor = ColdColor * CloudIntensity;
|
|
warmhorizoncolor = WarmColor * HorizonIntensity;
|
|
coldhorizoncolor = ColdColor * HorizonIntensity;
|
|
|
|
for (unsigned v = 0; v < VertexCount; v++) {
|
|
|
|
float interpolant, alpha;
|
|
Vector3 n, color;
|
|
|
|
n = Normalize (VertexArray [v]);
|
|
interpolant = Vector3::Dot_Product (WarmDirection, n);
|
|
if (interpolant < 0.0f) interpolant = 0.0f;
|
|
if (v % (RowCount + 1) < RowCount) {
|
|
Vector3::Lerp (coldcloudcolor, warmcloudcolor, interpolant, &color);
|
|
alpha = Alpha;
|
|
} else {
|
|
Vector3::Lerp (coldhorizoncolor, warmhorizoncolor, interpolant, &color);
|
|
alpha = 0.0f;
|
|
}
|
|
DiffuseArray [v] = DX8Wrapper::Convert_Color (color, alpha);
|
|
}
|
|
|
|
// Optimization: If alpha is zero then cloud layer is invisible.
|
|
Set_Visibility (Alpha > 0.0f);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CloudLayerClass::Render -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void CloudLayerClass::Render()
|
|
{
|
|
const float wraplimit = 8.0f;
|
|
|
|
Vector2 offset;
|
|
|
|
offset = (WW3D::Get_Frame_Time() * 0.001f) * Velocity;
|
|
|
|
// Keep the texture coordinates within certain bounds to avoid floating point overflow
|
|
// and to avoid potential hardware problems associated with large +ve/-ve coordinates.
|
|
// NOTE: Wrap limit has been chosen arbitrarily to allow for enough texture wrapping.
|
|
if (TexCoordArray [0].X < -wraplimit) {
|
|
offset.X += wraplimit;
|
|
} else {
|
|
if (TexCoordArray [0].X > wraplimit) {
|
|
offset.X -= wraplimit;
|
|
}
|
|
}
|
|
if (TexCoordArray [0].Y < -wraplimit) {
|
|
offset.Y += wraplimit;
|
|
} else {
|
|
if (TexCoordArray [0].Y > wraplimit) {
|
|
offset.Y -= wraplimit;
|
|
}
|
|
}
|
|
|
|
for (unsigned v = 0; v < VertexCount; v++) {
|
|
TexCoordArray [v] += offset;
|
|
}
|
|
|
|
if (Is_Visible()) {
|
|
|
|
// Copy the vertices into the dynamic vertex buffer.
|
|
// NOTE: Vertex normals and stage 1 UV's are uninitialized.
|
|
DynamicVBAccessClass dynamicvb (BUFFER_TYPE_DYNAMIC_DX8, dynamic_fvf_type, VertexCount);
|
|
{
|
|
DynamicVBAccessClass::WriteLockClass lock (&dynamicvb);
|
|
VertexFormatXYZNDUV2 *vertex = lock.Get_Formatted_Vertex_Array();
|
|
|
|
for (unsigned v = 0; v < VertexCount; v++) {
|
|
vertex->x = VertexArray [v].X;
|
|
vertex->y = VertexArray [v].Y;
|
|
vertex->z = VertexArray [v].Z;
|
|
vertex->diffuse = DiffuseArray [v];
|
|
vertex->u1 = TexCoordArray [v].X;
|
|
vertex->v1 = TexCoordArray [v].Y;
|
|
vertex++;
|
|
}
|
|
}
|
|
|
|
DX8Wrapper::Set_Texture (0, Texture);
|
|
DX8Wrapper::Set_Material (Material);
|
|
DX8Wrapper::Set_Shader (Shader);
|
|
DX8Wrapper::Set_Index_Buffer (IndexBuffer, 0);
|
|
DX8Wrapper::Set_Vertex_Buffer (dynamicvb);
|
|
DX8Wrapper::Draw_Triangles (0, TriangleCount, 0, VertexCount);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyGlowClass::SkyGlowClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
SkyGlowClass::SkyGlowClass (float radius)
|
|
: RowCount (ROW_COUNT),
|
|
Radius (radius)
|
|
{
|
|
const Vector3 white (1.0f, 1.0f, 1.0f);
|
|
const float longitude [ROW_COUNT + 1] = {1.37f, 1.42f, 1.47f, 1.52f, 1.57f, 1.92f};
|
|
const unsigned segmentcount = 32;
|
|
const float twopioosegmentcount = (1.0f / segmentcount) * 2.0f * WWMATH_PI;
|
|
|
|
unsigned row, segment;
|
|
unsigned v;
|
|
float latitude;
|
|
float x, y, z;
|
|
unsigned short i;
|
|
|
|
VertexCount = (RowCount + 1) * segmentcount;
|
|
TriangleCount = segmentcount * (RowCount * 2);
|
|
|
|
MinZ = 0.0f;
|
|
MaxZ = radius * cosf (longitude [0]);
|
|
|
|
// Define vertices.
|
|
VertexArray = new Vector3 [VertexCount];
|
|
WWASSERT (VertexArray != NULL);
|
|
v = 0;
|
|
for (segment = 0; segment < segmentcount; segment++) {
|
|
latitude = segment * twopioosegmentcount;
|
|
for (row = 0; row < RowCount + 1; row++) {
|
|
x = radius * sinf (longitude [row]) * cosf (latitude);
|
|
y = radius * sinf (longitude [row]) * sinf (latitude);
|
|
z = radius * cosf (longitude [row]);
|
|
VertexArray [v].Set (x, y, z);
|
|
v++;
|
|
}
|
|
}
|
|
|
|
// Define triangles.
|
|
IndexBuffer = NEW_REF (DX8IndexBufferClass, (TriangleCount * VERTICES_PER_TRIANGLE));
|
|
{
|
|
DX8IndexBufferClass::WriteLockClass lock (IndexBuffer);
|
|
unsigned short *indices = lock.Get_Index_Array();
|
|
|
|
i = 0;
|
|
for (row = 0; row < RowCount; row++) {
|
|
v = row;
|
|
for (segment = 0; segment < segmentcount; segment++) {
|
|
|
|
// Is this not the last segment?
|
|
if (segment < segmentcount - 1) {
|
|
indices [i + 0] = v;
|
|
indices [i + 1] = v + RowCount + 1;
|
|
indices [i + 2] = v + RowCount + 2;
|
|
indices [i + 3] = v + RowCount + 2;
|
|
indices [i + 4] = v + 1;
|
|
indices [i + 5] = v;
|
|
} else {
|
|
indices [i + 0] = v;
|
|
indices [i + 1] = row;
|
|
indices [i + 2] = row + 1;
|
|
indices [i + 3] = row + 1;
|
|
indices [i + 4] = v + 1;
|
|
indices [i + 5] = v;
|
|
}
|
|
v += RowCount + 1;
|
|
i += 6;
|
|
}
|
|
}
|
|
}
|
|
|
|
Material = VertexMaterialClass::Get_Preset (VertexMaterialClass::PRELIT_NODIFFUSE);
|
|
|
|
Shader = ShaderClass::_PresetAdditive2DShader;
|
|
Shader.Set_Primary_Gradient (ShaderClass::GRADIENT_MODULATE);
|
|
Shader.Set_Texturing (ShaderClass::TEXTURING_DISABLE);
|
|
Shader.Set_Cull_Mode (ShaderClass::CULL_MODE_DISABLE);
|
|
|
|
DiffuseArray = new unsigned [VertexCount];
|
|
WWASSERT (DiffuseArray != NULL);
|
|
|
|
Configure (Vector2 (1.0f, 0.0f), white, 1.0f);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyGlowClass::~SkyGlowClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
SkyGlowClass::~SkyGlowClass()
|
|
{
|
|
// Clean-up.
|
|
delete [] DiffuseArray;
|
|
REF_PTR_RELEASE (Material);
|
|
REF_PTR_RELEASE (IndexBuffer);
|
|
delete [] VertexArray;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyGlowClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyGlowClass::Configure (const Vector2 &hotdirection, const Vector3 &horizoncolor, float coldintensity)
|
|
{
|
|
HotDirection = Normalize (hotdirection);
|
|
HorizonColor = horizoncolor;
|
|
ColdIntensity = coldintensity;
|
|
Configure();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyGlowClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyGlowClass::Configure()
|
|
{
|
|
const float ooradius = 1.0f / Radius;
|
|
const float exponent = 7.0f;
|
|
const float oomaxz = 1.0f / MaxZ;
|
|
const Vector3 hotdirection (HotDirection.X, HotDirection.Y, 0.0f);
|
|
|
|
for (unsigned v = 0; v < VertexCount; v++) {
|
|
|
|
float dotproduct, gradient, z;
|
|
|
|
dotproduct = Vector3::Dot_Product (hotdirection, VertexArray [v] * ooradius);
|
|
dotproduct = pow (dotproduct, exponent);
|
|
if (dotproduct < ColdIntensity) dotproduct = ColdIntensity;
|
|
|
|
z = VertexArray [v].Z;
|
|
if (z < MinZ) {
|
|
gradient = 1.0f;
|
|
} else {
|
|
gradient = 1.0f - (z * oomaxz);
|
|
}
|
|
|
|
DiffuseArray [v] = DX8Wrapper::Convert_Color (HorizonColor * (dotproduct * gradient), 1.0f);
|
|
}
|
|
|
|
// Sky glow is always visible.
|
|
Set_Visibility (true);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyGlowClass::Render -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyGlowClass::Render()
|
|
{
|
|
if (Is_Visible()) {
|
|
|
|
// Copy the vertices into a dynamic vertex buffer.
|
|
// NOTE: Vertex normals and UV's are uninitialized.
|
|
DynamicVBAccessClass dynamicvb (BUFFER_TYPE_DYNAMIC_DX8, dynamic_fvf_type, VertexCount);
|
|
{
|
|
DynamicVBAccessClass::WriteLockClass lock (&dynamicvb);
|
|
VertexFormatXYZNDUV2 *vertex = lock.Get_Formatted_Vertex_Array();
|
|
|
|
for (unsigned v = 0; v < VertexCount; v++) {
|
|
vertex->x = VertexArray [v].X;
|
|
vertex->y = VertexArray [v].Y;
|
|
vertex->z = VertexArray [v].Z;
|
|
vertex->diffuse = DiffuseArray [v];
|
|
vertex++;
|
|
}
|
|
}
|
|
|
|
DX8Wrapper::Set_Material (Material);
|
|
DX8Wrapper::Set_Shader (Shader);
|
|
DX8Wrapper::Set_Index_Buffer (IndexBuffer, 0);
|
|
DX8Wrapper::Set_Vertex_Buffer (dynamicvb);
|
|
DX8Wrapper::Draw_Triangles (0, TriangleCount, 0, VertexCount);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* LightningBoltClass::LightningBoltClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
LightningBoltClass::LightningBoltClass (int branchcount, Matrix3D &m, float length, float childlength, float width, float amplitude)
|
|
: Branches (NULL)
|
|
{
|
|
const int randomness = 100;
|
|
const float oorandomness = 1.0f / randomness;
|
|
const unsigned maxvertexcount = MAX (2, length * 0.5f);
|
|
const float oomaxvertexcountminusone = 1.0f / (maxvertexcount - 1);
|
|
const char *texturename = "LightningBolt.tga";
|
|
|
|
Vector3 white (1.0f, 1.0f, 1.0f);
|
|
unsigned vertexcount;
|
|
float x;
|
|
Vector3 *localvertex, *worldvertex;
|
|
int branchrandomness;
|
|
TextureClass *texture;
|
|
|
|
localvertex = new Vector3 [maxvertexcount];
|
|
worldvertex = new Vector3 [maxvertexcount];
|
|
|
|
vertexcount = 0;
|
|
x = 0;
|
|
for (unsigned v = 0; v < maxvertexcount; v++) {
|
|
vertexcount++;
|
|
localvertex [v] = Vector3 (x, -oomaxvertexcountminusone * v * length, 0.0f);
|
|
worldvertex [v] = m * localvertex [v];
|
|
x = x + _RandomNumber (-randomness, +randomness) * 0.5f * oorandomness * amplitude;
|
|
}
|
|
|
|
Set_Points (vertexcount, worldvertex);
|
|
texture = WW3DAssetManager::Get_Instance()->Get_Texture (texturename, TextureClass::MIP_LEVELS_3);
|
|
Set_Texture (texture);
|
|
REF_PTR_RELEASE (texture);
|
|
|
|
Set_Shader (ShaderClass::_PresetAdditive2DShader);
|
|
Set_Width (width);
|
|
Set_Texture_Mapping_Mode (SegLineRendererClass::UNIFORM_WIDTH_TEXTURE_MAP);
|
|
|
|
// Optimization: Merging intersections yields no visual improvement.
|
|
Set_Merge_Intersections (false);
|
|
|
|
// Optimization: Sorting is not required because all of the line segments are coplanar.
|
|
Set_Disable_Sorting (true);
|
|
|
|
BranchCount = (vertexcount == maxvertexcount) ? branchcount : 0;
|
|
|
|
// Create the child lightning bolts.
|
|
if (BranchCount > 0) {
|
|
|
|
const float minbranchangle = WWMATH_PI * 0.167f;
|
|
const float maxbranchangle = WWMATH_PI * 0.223f;
|
|
const float branchfactor = 0.50f;
|
|
const float minlengthfactor = 0.20f;
|
|
const float maxlengthfactor = 0.45f;
|
|
const float widthfactor = 0.30f;
|
|
const float minwidth = 0.13f;
|
|
const float amplitudefactor = 0.85f;
|
|
|
|
float oobranchcount;
|
|
int branchcount;
|
|
float minlength, maxlength, w, a;
|
|
|
|
Branches = new BranchStruct [BranchCount];
|
|
WWASSERT (Branches != NULL);
|
|
oobranchcount = 1.0f / BranchCount;
|
|
branchrandomness = vertexcount / (BranchCount * 2);
|
|
branchcount = BranchCount * branchfactor;
|
|
minlength = childlength * minlengthfactor;
|
|
maxlength = childlength * maxlengthfactor;
|
|
w = MAX (minwidth, width * widthfactor);
|
|
a = amplitude * amplitudefactor;
|
|
for (int b = 0; b < BranchCount; b++) {
|
|
|
|
float angle, l;
|
|
unsigned v;
|
|
Matrix3D m0 (m);
|
|
|
|
angle = WWMath::Lerp (minbranchangle, maxbranchangle, _RandomNumber (0, randomness) * oorandomness);
|
|
if ((b & 0x1) == 0) angle = -angle;
|
|
l = WWMath::Lerp (minlength, maxlength, _RandomNumber (0, randomness) * oorandomness);
|
|
v = MIN (((int) vertexcount) - 1, b * oobranchcount * (((int) vertexcount) - 1) + _RandomNumber (0, +branchrandomness));
|
|
m0.Translate (localvertex [v] - localvertex [0]);
|
|
m0.Rotate_Z (angle);
|
|
|
|
// If the lightning bolt originates below the horizon don't bother generating it.
|
|
if (m0.Get_Translation().Z > 0.0f) {
|
|
Branches [b].LightningBolt = NEW_REF (LightningBoltClass, (branchcount, m0, l, l, w, a));
|
|
} else {
|
|
Branches [b].LightningBolt = NULL;
|
|
}
|
|
|
|
WWASSERT (Branches != NULL);
|
|
}
|
|
}
|
|
|
|
Configure (white);
|
|
|
|
// Clean-up.
|
|
delete [] localvertex;
|
|
delete [] worldvertex;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* LightningBoltClass::~LightningBoltClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
LightningBoltClass::~LightningBoltClass()
|
|
{
|
|
for (int b = 0; b < BranchCount; b++) {
|
|
REF_PTR_RELEASE (Branches [b].LightningBolt);
|
|
}
|
|
|
|
if (Branches != NULL) {
|
|
delete Branches;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* LightningBoltClass::Set_Visibility -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void LightningBoltClass::Set_Visibility (bool visible, bool recurse)
|
|
{
|
|
VisibilityClass::Set_Visibility (visible);
|
|
if (recurse) {
|
|
for (int b = 0; b < BranchCount; b++) {
|
|
if (Branches [b].LightningBolt != NULL) {
|
|
Branches [b].LightningBolt->Set_Visibility (visible, recurse);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* LightningBoltClass::Configure -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void LightningBoltClass::Configure (Vector3 &color)
|
|
{
|
|
Set_Color (color);
|
|
for (int b = 0; b < BranchCount; b++) {
|
|
if (Branches [b].LightningBolt != NULL) {
|
|
Branches [b].LightningBolt->Configure (color);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* LightningBoltClass::Set_Transform -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void LightningBoltClass::Set_Transform (Matrix3D &t)
|
|
{
|
|
((SegmentedLineClass*) this)->Set_Transform (t);
|
|
for (int b = 0; b < BranchCount; b++) {
|
|
if (Branches [b].LightningBolt != NULL) {
|
|
Branches [b].LightningBolt->Set_Transform (t);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* LightningBoltClass::Render -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void LightningBoltClass::Render (RenderInfoClass &rinfo)
|
|
{
|
|
if (VisibilityClass::Is_Visible()) {
|
|
if (!rinfo.Camera.Cull_Sphere (Get_Bounding_Sphere())) {
|
|
|
|
Matrix4 t;
|
|
|
|
// NOTE: Copy and restore the object to world space transform because Render_Seg_Line()
|
|
// will modify it (because it is a render-object function).
|
|
DX8Wrapper::Get_Transform (D3DTS_WORLD, t);
|
|
SegmentedLineClass::Render_Seg_Line (rinfo);
|
|
DX8Wrapper::Set_Transform (D3DTS_WORLD, t);
|
|
}
|
|
for (int b = 0; b < BranchCount; b++) {
|
|
if (Branches [b].LightningBolt != NULL) {
|
|
Branches [b].LightningBolt->Render (rinfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* LightningClass::LightningClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
LightningClass::LightningClass (float extent, float startdistance, float enddistance, float heading, float distribution)
|
|
: Time (0),
|
|
PlayedThunder (false)
|
|
{
|
|
const Vector3 white (1.0f, 1.0f, 1.0f);
|
|
|
|
const unsigned randomness = 100;
|
|
const float oorandomness = 1.0f / randomness;
|
|
const unsigned minthunderdelaytime = 0;
|
|
const unsigned maxthunderdelaytime = 1000;
|
|
const float minlongitude = WWMATH_PI * 0.340f;
|
|
const float maxlongitude = WWMATH_PI * 0.472f;
|
|
const float bufferangle = 0.35f;
|
|
const int minbranchcount = 5;
|
|
const int maxbranchcount = 8;
|
|
const float minwidth = 0.5f;
|
|
const float maxwidth = 1.1f;
|
|
const float amplitude = 1.5f;
|
|
const char *lightningsourcetexturename = "LightningSource.tga";
|
|
const float minlightningsourcewidth = 1.00f;
|
|
const float maxlightningsourcewidth = 3.00f;
|
|
const float minlightningsourceheight = 0.35f;
|
|
const float maxlightningsourceheight = 1.05f;
|
|
const unsigned majorsamplecount = 2;
|
|
const unsigned minorsamplecount = 3;
|
|
|
|
static const char *_thundersamplename [majorsamplecount][minorsamplecount] = {
|
|
{"Thunder01", "Thunder02", "Thunder03"},
|
|
{"Thunder04", "Thunder05", "Thunder06"}
|
|
};
|
|
|
|
unsigned branchcount;
|
|
float latitude, longitude, theta, x, y, z, length, childlength, width;
|
|
Vector3 d, o;
|
|
Matrix3D m;
|
|
float lightningsourcewidth, lightningsourceheight;
|
|
unsigned majorsampleindex, minorsampleindex;
|
|
|
|
Distance = WWMath::Lerp (startdistance, enddistance, _RandomNumber (0, randomness) * oorandomness);
|
|
ThunderDelayTime = WWMath::Lerp ((float) minthunderdelaytime, (float) maxthunderdelaytime, Distance);
|
|
|
|
LightningGlow = new SkyGlowClass (extent);
|
|
WWASSERT (LightningGlow != NULL);
|
|
|
|
branchcount = WWMath::Lerp ((float) maxbranchcount, (float) minbranchcount, Distance);
|
|
latitude = heading + (0.5f * WWMATH_PI) + (_RandomNumber (- ((int) randomness), ((int) randomness)) * oorandomness * WWMATH_PI * distribution);
|
|
x = cosf (latitude);
|
|
y = sinf (latitude);
|
|
Direction.Set (x, y);
|
|
d.Set (x, y, 0.0f);
|
|
longitude = WWMath::Lerp (minlongitude, maxlongitude, Distance);
|
|
x = sinf (longitude) * cosf (latitude);
|
|
y = sinf (longitude) * sinf (latitude);
|
|
z = cosf (longitude);
|
|
o.Set (x, y, z);
|
|
m.Look_At (o * extent, (o + d) * extent, 0.0f);
|
|
theta = (WWMATH_PI * 0.5f) - longitude;
|
|
childlength = extent * sinf (theta);
|
|
length = childlength + extent * cosf (theta) * tanf (bufferangle);
|
|
width = WWMath::Lerp (maxwidth, minwidth, Distance);
|
|
LightningBolt = NEW_REF (LightningBoltClass, (branchcount, m, length, childlength, width, amplitude));
|
|
WWASSERT (LightningBolt != NULL);
|
|
|
|
LightningSource = new SkyObjectClass (ShaderClass::_PresetAdditive2DShader);
|
|
WWASSERT (LightningSource != NULL);
|
|
lightningsourcewidth = WWMath::Lerp (maxlightningsourcewidth, minlightningsourcewidth, Distance);
|
|
lightningsourceheight = WWMath::Lerp (maxlightningsourceheight, minlightningsourceheight, Distance);
|
|
LightningSource->Configure (o, extent, lightningsourcewidth, lightningsourceheight);
|
|
LightningSource->Set_Texture (lightningsourcetexturename);
|
|
|
|
ThunderPosition = o * (extent * Distance);
|
|
majorsampleindex = MIN ((unsigned) (Distance * majorsamplecount), majorsamplecount - 1);
|
|
minorsampleindex = _RandomNumber (0, minorsamplecount - 1);
|
|
ThunderSampleName = _thundersamplename [majorsampleindex][minorsampleindex];
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* LightningClass::~LightningClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
LightningClass::~LightningClass()
|
|
{
|
|
delete LightningSource;
|
|
REF_PTR_RELEASE (LightningBolt);
|
|
delete LightningGlow;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* LightningClass::Update -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool LightningClass::Update (Matrix3D &t, Vector3 &additivecolor, SoundEnvironmentClass *soundenvironment)
|
|
{
|
|
const Vector3 black (0.000f, 0.000f, 0.000f);
|
|
const Vector3 blue (0.663f, 0.750f, 0.969f);
|
|
const Vector3 gray (0.350f, 0.350f, 0.350f);
|
|
const Vector3 white (1.000f, 1.000f, 1.000f);
|
|
const unsigned lightningtime = 550;
|
|
const float minglowintensity = 0.10f;
|
|
const float coldintensity = 0.25f;
|
|
|
|
bool notfinished = true;
|
|
|
|
// Set the lightning bolt transform so that render-object culling will work correctly.
|
|
LightningBolt->Set_Transform (t);
|
|
|
|
Time += WW3D::Get_Frame_Time();
|
|
if (Time < lightningtime) {
|
|
|
|
const unsigned phasecount = 7;
|
|
|
|
const static float _intensities [phasecount] = {1.00f, 0.75f, 0.50f, 0.50f, 1.00f, 0.50f, 0.10f};
|
|
const static bool _renderbranches [phasecount] = {true, true, true, true, false, false, false};
|
|
|
|
unsigned phase;
|
|
Vector3 color;
|
|
|
|
phase = (((float) Time) / lightningtime) * (phasecount + 1);
|
|
phase = MIN (phase, phasecount);
|
|
|
|
additivecolor = blue * _intensities [phase] * MAX (1.0f - Distance, minglowintensity);
|
|
LightningGlow->Configure (Direction, additivecolor, coldintensity);
|
|
additivecolor *= coldintensity;
|
|
|
|
color = gray * _intensities [phase];
|
|
LightningBolt->Configure (color);
|
|
if (_renderbranches [phase]) {
|
|
LightningBolt->Set_Visibility (true, true);
|
|
} else {
|
|
LightningBolt->Set_Visibility (false, true);
|
|
LightningBolt->Set_Visibility (true, false);
|
|
}
|
|
|
|
color = white * _intensities [phase];
|
|
LightningSource->Configure (color);
|
|
LightningSource->Set_Visibility (true);
|
|
|
|
} else {
|
|
|
|
additivecolor = black;
|
|
if (Time < lightningtime + ThunderDelayTime) {
|
|
|
|
LightningGlow->Set_Visibility (false);
|
|
LightningBolt->Set_Visibility (false, false);
|
|
LightningSource->Set_Visibility (false);
|
|
|
|
} else {
|
|
|
|
LightningGlow->Set_Visibility (false);
|
|
LightningBolt->Set_Visibility (false, false);
|
|
LightningSource->Set_Visibility (false);
|
|
if (!PlayedThunder) {
|
|
|
|
AudibleSoundClass *sound;
|
|
|
|
sound = WWAudioClass::Get_Instance()->Create_Sound (ThunderSampleName, NULL, 0, CLASSID_PSEUDO3D);
|
|
if (sound != NULL) {
|
|
|
|
Matrix3D m (t);
|
|
|
|
m.Adjust_Translation (ThunderPosition);
|
|
|
|
sound->Set_Transform (m);
|
|
sound->Add_To_Scene();
|
|
sound->Set_Volume (soundenvironment->Get_Amplitude() * 0.5f);
|
|
sound->Play();
|
|
sound->Release_Ref();
|
|
}
|
|
PlayedThunder = true;
|
|
}
|
|
notfinished = false;
|
|
}
|
|
}
|
|
|
|
return (notfinished);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* LightningClass::Render -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void LightningClass::Render (RenderInfoClass &rinfo)
|
|
{
|
|
LightningGlow->Render();
|
|
LightningBolt->Render (rinfo);
|
|
LightningSource->Render();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WarBlitzClass::WarBlitzClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/26/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
WarBlitzClass::WarBlitzClass (float extent, float startdistance, float enddistance, float heading, float distribution)
|
|
: Time (0),
|
|
PlayedSample (false)
|
|
{
|
|
const unsigned randomness = 100;
|
|
const float oorandomness = 1.0f / randomness;
|
|
const unsigned minsampledelaytime = 25;
|
|
const unsigned maxsampledelaytime = 400;
|
|
|
|
float latitude, x, y;
|
|
Vector2 position;
|
|
|
|
Distance = WWMath::Lerp (startdistance, enddistance, _RandomNumber (0, randomness) * oorandomness);
|
|
SampleDelayTime = WWMath::Lerp ((float) minsampledelaytime, (float) maxsampledelaytime, Distance);
|
|
|
|
latitude = heading + (0.5f * WWMATH_PI) + (_RandomNumber (- ((int) randomness), ((int) randomness)) * oorandomness * WWMATH_PI * distribution);
|
|
x = cosf (latitude);
|
|
y = sinf (latitude);
|
|
Direction.Set (x, y);
|
|
|
|
position = Direction * (extent * Distance);
|
|
SamplePosition.Set (position.X, position.Y, 0.0f);
|
|
|
|
WarBlitzGlow = new SkyGlowClass (extent);
|
|
WWASSERT (WarBlitzGlow != NULL);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WarBlitzClass::~WarBlitzClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/26/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
WarBlitzClass::~WarBlitzClass()
|
|
{
|
|
delete WarBlitzGlow;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WarBlitzClass::Update -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/26/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool WarBlitzClass::Update (Matrix3D &t, Vector3 &additivecolor)
|
|
{
|
|
const Vector3 red (0.950f, 0.250f, 0.250f);
|
|
const Vector3 black (0.000f, 0.000f, 0.000f);
|
|
const unsigned warblitztime = 550;
|
|
const float minglowintensity = 0.10f;
|
|
const float coldintensity = 0.25f;
|
|
|
|
bool notfinished = true;
|
|
|
|
Time += WW3D::Get_Frame_Time();
|
|
if (Time < warblitztime) {
|
|
|
|
const unsigned phasecount = 7;
|
|
const static float _intensities [phasecount] = {0.50f, 1.00f, 0.80f, 0.60f, 0.40f, 0.20f, 0.10f};
|
|
|
|
unsigned phase;
|
|
|
|
phase = (((float) Time) / warblitztime) * (phasecount + 1);
|
|
phase = MIN (phase, phasecount);
|
|
additivecolor = red * _intensities [phase] * MAX (1.0f - Distance, minglowintensity);
|
|
WarBlitzGlow->Configure (Direction, additivecolor, coldintensity);
|
|
|
|
} else {
|
|
|
|
additivecolor = black;
|
|
WarBlitzGlow->Set_Visibility (false);
|
|
if (Time >= warblitztime + SampleDelayTime) {
|
|
if (!PlayedSample) {
|
|
|
|
const char *samplename = "SFX.Ambient_Explosion_01";
|
|
|
|
AudibleSoundClass *sound;
|
|
|
|
sound = WWAudioClass::Get_Instance()->Create_Sound (samplename, NULL, 0, CLASSID_PSEUDO3D);
|
|
if (sound != NULL) {
|
|
|
|
Matrix3D m (t);
|
|
|
|
m.Adjust_Translation (SamplePosition);
|
|
sound->Set_Transform (m);
|
|
sound->Add_To_Scene();
|
|
sound->Play();
|
|
sound->Release_Ref();
|
|
}
|
|
PlayedSample = true;
|
|
}
|
|
notfinished = false;
|
|
}
|
|
}
|
|
|
|
additivecolor *= coldintensity;
|
|
return (notfinished);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* WarBlitzClass::Render -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/26/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
void WarBlitzClass::Render (RenderInfoClass &rinfo)
|
|
{
|
|
WarBlitzGlow->Render();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::SkyClass -- Constructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
SkyClass::SkyClass (SoundEnvironmentClass *soundenvironment)
|
|
: Extent (100.0f),
|
|
Color (0.0f, 0.0f, 0.0f),
|
|
Hours (0),
|
|
Minutes (0),
|
|
Gloominess (0.0f),
|
|
TintFactor (0.0f),
|
|
LightningIntensity (0.0f),
|
|
LightningStartDistance (0.0f),
|
|
LightningEndDistance (1.0f),
|
|
LightningHeading (0.0f),
|
|
LightningDistribution (0.5f),
|
|
SoundEnvironment (NULL),
|
|
WarBlitzIntensity (0.0f),
|
|
WarBlitzStartDistance (0.0f),
|
|
WarBlitzEndDistance (1.0f),
|
|
WarBlitzHeading (0.0f),
|
|
WarBlitzDistribution (0.5f)
|
|
{
|
|
const unsigned starcount = 200;
|
|
|
|
WWASSERT (soundenvironment != NULL);
|
|
REF_PTR_SET (SoundEnvironment, soundenvironment);
|
|
SoundEnvironment->Add_User();
|
|
|
|
Haze = new HazeClass (Extent);
|
|
WWASSERT (Haze != NULL);
|
|
|
|
Starfield = new StarfieldClass (Extent, starcount);
|
|
WWASSERT (Starfield != NULL);
|
|
|
|
Sun = new SkyObjectClass (ShaderClass::_PresetAdditive2DShader);
|
|
WWASSERT (Sun != NULL);
|
|
Sun->Set_Texture ("Sun.tga");
|
|
|
|
SunHalo = new SkyObjectClass (ShaderClass::_PresetAdditive2DShader);
|
|
WWASSERT (SunHalo != NULL);
|
|
SunHalo->Set_Texture ("SunHalo.tga");
|
|
|
|
Moon = new SkyObjectClass (ShaderClass::_PresetAlpha2DShader);
|
|
WWASSERT (Moon != NULL);
|
|
Set_Moon_Type (MOON_TYPE_FULL);
|
|
|
|
MoonHalo = new SkyObjectClass (ShaderClass::_PresetAdditive2DShader);
|
|
WWASSERT (MoonHalo != NULL);
|
|
MoonHalo->Set_Texture ("MoonHalo.tga");
|
|
|
|
CloudLayer0 = new CloudLayerClass (Extent, "CloudLayer.tga", Vector2 (0.0030f, 0.0006f), 1.2f, false);
|
|
WWASSERT (CloudLayer0 != NULL);
|
|
|
|
CloudLayer1 = new CloudLayerClass (Extent, "CloudLayer.tga", Vector2 (0.0050f, 0.0010f), 0.8f, true);
|
|
WWASSERT (CloudLayer1 != NULL);
|
|
|
|
for (unsigned l = 0; l < LIGHTNING_COUNT; l++) {
|
|
Lightning [l] = NULL;
|
|
LightningCountdown [l] = Lightning_Delay();
|
|
}
|
|
|
|
WarBlitz = NULL;
|
|
WarBlitzCountdown = War_Blitz_Delay();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::~SkyClass -- Destructor *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
SkyClass::~SkyClass()
|
|
{
|
|
// Clean-up.
|
|
if (WarBlitz != NULL) delete WarBlitz;
|
|
for (unsigned l = 0; l < LIGHTNING_COUNT; l++) {
|
|
if (Lightning [l] != NULL) delete Lightning [l];
|
|
}
|
|
delete CloudLayer1;
|
|
delete CloudLayer0;
|
|
delete MoonHalo;
|
|
delete Moon;
|
|
delete SunHalo;
|
|
delete Sun;
|
|
delete Starfield;
|
|
delete Haze;
|
|
|
|
SoundEnvironment->Remove_User();
|
|
REF_PTR_RELEASE (SoundEnvironment);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Set_Light_Direction -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyClass::Set_Light_Direction (const Vector3 &sundirection, const Vector3 &moondirection)
|
|
{
|
|
const float sunradius = 30.00f;
|
|
const float sunhaloradius = 85.00f;
|
|
const float moonradius = 5.00f;
|
|
const float moonhaloradius = 20.00f;
|
|
|
|
Starfield->Configure (moondirection, Extent, moonradius);
|
|
Sun->Configure (sundirection, Extent, sunradius);
|
|
SunHalo->Configure (sundirection, Extent, sunhaloradius);
|
|
Moon->Configure (moondirection, Extent, moonradius);
|
|
MoonHalo->Configure (moondirection, Extent, moonhaloradius);
|
|
CloudLayer0->Configure (sundirection);
|
|
CloudLayer1->Configure (sundirection);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Set_Time_Of_Day -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyClass::Set_Time_Of_Day (unsigned hours, unsigned minutes)
|
|
{
|
|
const Vector3 white (1.00f, 1.00f, 1.00f);
|
|
const Vector3 starfieldcolor (0.27f, 0.31f, 0.37f);
|
|
|
|
const unsigned colorcount = 24;
|
|
const unsigned alphacount = 24;
|
|
|
|
static const unsigned char _warmskycolors [colorcount][3] = {
|
|
|
|
{ 36, 36, 40}, // 0000 hrs
|
|
{ 36, 36, 40}, // 0100 hrs
|
|
{ 36, 36, 40}, // 0200 hrs
|
|
{ 36, 36, 40}, // 0300 hrs
|
|
{ 51, 83, 100}, // 0400 hrs
|
|
{168, 160, 216}, // 0500 hrs
|
|
{240, 212, 216}, // 0600 hrs
|
|
{255, 255, 192}, // 0700 hrs
|
|
{255, 255, 248}, // 0800 hrs
|
|
{255, 255, 248}, // 0900 hrs
|
|
{255, 255, 248}, // 1000 hrs
|
|
{255, 255, 248}, // 1100 hrs
|
|
{255, 255, 248}, // 1200 hrs
|
|
{255, 255, 248}, // 1300 hrs
|
|
{255, 255, 248}, // 1400 hrs
|
|
{255, 255, 248}, // 1500 hrs
|
|
{245, 243, 200}, // 1600 hrs
|
|
{245, 209, 121}, // 1700 hrs
|
|
{229, 188, 88}, // 1800 hrs
|
|
{201, 103, 60}, // 1900 hrs
|
|
{ 72, 72, 80}, // 2000 hrs
|
|
{ 36, 36, 40}, // 2100 hrs
|
|
{ 36, 36, 40}, // 2200 hrs
|
|
{ 36, 36, 40}}; // 2300 hrs
|
|
|
|
static const unsigned char _coldskycolors [colorcount][3] = {
|
|
|
|
{ 36, 36, 40}, // 0000 hrs
|
|
{ 36, 36, 40}, // 0100 hrs
|
|
{ 36, 36, 40}, // 0200 hrs
|
|
{ 36, 36, 40}, // 0300 hrs
|
|
{ 51, 83, 100}, // 0400 hrs
|
|
{170, 164, 205}, // 0500 hrs
|
|
{200, 179, 182}, // 0600 hrs
|
|
{215, 215, 181}, // 0700 hrs
|
|
{215, 215, 209}, // 0800 hrs
|
|
{215, 215, 209}, // 0900 hrs
|
|
{215, 215, 209}, // 1000 hrs
|
|
{215, 215, 209}, // 1100 hrs
|
|
{215, 215, 209}, // 1200 hrs
|
|
{215, 215, 209}, // 1300 hrs
|
|
{215, 215, 209}, // 1400 hrs
|
|
{215, 215, 209}, // 1500 hrs
|
|
{210, 209, 176}, // 1600 hrs
|
|
{213, 190, 135}, // 1700 hrs
|
|
{214, 187, 123}, // 1800 hrs
|
|
{179, 123, 98}, // 1900 hrs
|
|
{ 72, 72, 80}, // 2000 hrs
|
|
{ 36, 36, 40}, // 2100 hrs
|
|
{ 36, 36, 40}, // 2200 hrs
|
|
{ 36, 36, 40}}; // 2300 hrs
|
|
|
|
static const unsigned char _suncolors [colorcount][3] = {
|
|
|
|
{ 0, 0, 0}, // 0000 hrs
|
|
{ 0, 0, 0}, // 0100 hrs
|
|
{ 0, 0, 0}, // 0200 hrs
|
|
{ 0, 0, 0}, // 0300 hrs
|
|
{ 0, 0, 0}, // 0400 hrs
|
|
{127, 127, 0}, // 0500 hrs
|
|
{127, 127, 0}, // 0600 hrs
|
|
{110, 110, 0}, // 0700 hrs
|
|
{ 96, 96, 32}, // 0800 hrs
|
|
{ 76, 76, 76}, // 0900 hrs
|
|
{ 76, 76, 76}, // 1000 hrs
|
|
{ 76, 76, 76}, // 1100 hrs
|
|
{ 76, 76, 76}, // 1200 hrs
|
|
{ 76, 76, 76}, // 1300 hrs
|
|
{ 76, 76, 76}, // 1400 hrs
|
|
{ 76, 76, 76}, // 1500 hrs
|
|
{ 96, 81, 48}, // 1600 hrs
|
|
{123, 81, 21}, // 1700 hrs
|
|
{127, 32, 32}, // 1800 hrs
|
|
{127, 32, 32}, // 1900 hrs
|
|
{ 0, 0, 0}, // 2000 hrs
|
|
{ 0, 0, 0}, // 2100 hrs
|
|
{ 0, 0, 0}, // 2200 hrs
|
|
{ 0, 0, 0}}; // 2300 hrs
|
|
|
|
static const unsigned char _sunhalocolors [colorcount][3] = {
|
|
|
|
{ 0, 0, 0}, // 0000 hrs
|
|
{ 0, 0, 0}, // 0100 hrs
|
|
{ 0, 0, 0}, // 0200 hrs
|
|
{ 0, 0, 0}, // 0300 hrs
|
|
{ 0, 0, 0}, // 0400 hrs
|
|
{192, 192, 144}, // 0500 hrs
|
|
{192, 192, 144}, // 0600 hrs
|
|
{192, 192, 144}, // 0700 hrs
|
|
{ 96, 96, 96}, // 0800 hrs
|
|
{ 96, 96, 96}, // 0900 hrs
|
|
{ 96, 96, 96}, // 1000 hrs
|
|
{ 96, 96, 96}, // 1100 hrs
|
|
{ 96, 96, 96}, // 1200 hrs
|
|
{ 96, 96, 96}, // 1300 hrs
|
|
{ 96, 96, 96}, // 1400 hrs
|
|
{ 96, 96, 96}, // 1500 hrs
|
|
{ 96, 96, 96}, // 1600 hrs
|
|
{245, 223, 185}, // 1700 hrs
|
|
{239, 179, 107}, // 1800 hrs
|
|
{239, 179, 107}, // 1900 hrs
|
|
{ 0, 0, 0}, // 2000 hrs
|
|
{ 0, 0, 0}, // 2100 hrs
|
|
{ 0, 0, 0}, // 2200 hrs
|
|
{ 0, 0, 0}}; // 2300 hrs
|
|
|
|
static const unsigned char _moonhalocolors [colorcount][3] = {
|
|
|
|
{192, 192, 192}, // 0000 hrs
|
|
{192, 192, 192}, // 0100 hrs
|
|
{192, 192, 192}, // 0200 hrs
|
|
{192, 192, 192}, // 0300 hrs
|
|
{160, 160, 160}, // 0400 hrs
|
|
{128, 128, 128}, // 0500 hrs
|
|
{ 64, 64, 64}, // 0600 hrs
|
|
{ 0, 0, 0}, // 0700 hrs
|
|
{ 0, 0, 0}, // 0800 hrs
|
|
{ 0, 0, 0}, // 0900 hrs
|
|
{ 0, 0, 0}, // 1000 hrs
|
|
{ 0, 0, 0}, // 1100 hrs
|
|
{ 0, 0, 0}, // 1200 hrs
|
|
{ 0, 0, 0}, // 1300 hrs
|
|
{ 0, 0, 0}, // 1400 hrs
|
|
{ 0, 0, 0}, // 1500 hrs
|
|
{ 0, 0, 0}, // 1600 hrs
|
|
{ 0, 0, 0}, // 1700 hrs
|
|
{ 64, 64, 64}, // 1800 hrs
|
|
{128, 128, 128}, // 1900 hrs
|
|
{160, 160, 160}, // 2000 hrs
|
|
{192, 192, 192}, // 2100 hrs
|
|
{192, 192, 192}, // 2200 hrs
|
|
{192, 192, 192}}; // 2300 hrs
|
|
|
|
static const unsigned char _starfieldalphas [alphacount] = {
|
|
|
|
255, // 0000 hrs
|
|
255, // 0100 hrs
|
|
255, // 0200 hrs
|
|
255, // 0300 hrs
|
|
255, // 0400 hrs
|
|
0, // 0500 hrs
|
|
0, // 0600 hrs
|
|
0, // 0700 hrs
|
|
0, // 0800 hrs
|
|
0, // 0900 hrs
|
|
0, // 1000 hrs
|
|
0, // 1100 hrs
|
|
0, // 1200 hrs
|
|
0, // 1300 hrs
|
|
0, // 1400 hrs
|
|
0, // 1500 hrs
|
|
0, // 1600 hrs
|
|
0, // 1700 hrs
|
|
0, // 1800 hrs
|
|
0, // 1900 hrs
|
|
255, // 2000 hrs
|
|
255, // 2100 hrs
|
|
255, // 2200 hrs
|
|
255}; // 2300 hrs
|
|
|
|
float timeofday;
|
|
Vector3 warmskycolor, coldskycolor, sunhalocolor, moonhalocolor, cloudcolor, suncolor;
|
|
float starfieldalpha;
|
|
|
|
Hours = hours;
|
|
Minutes = minutes;
|
|
Set_Color();
|
|
|
|
// Calculate haze, sun, moon & cloud colors for time of day.
|
|
timeofday = hours + (minutes / 60.0f);
|
|
starfieldalpha = Interpolate_Scalar (_starfieldalphas, alphacount, timeofday);
|
|
warmskycolor = Interpolate_Color (_warmskycolors, colorcount, timeofday);
|
|
coldskycolor = Interpolate_Color (_coldskycolors, colorcount, timeofday);
|
|
sunhalocolor = Interpolate_Color (_sunhalocolors, colorcount, timeofday);
|
|
moonhalocolor = Interpolate_Color (_moonhalocolors, colorcount, timeofday);
|
|
suncolor = Interpolate_Color (_suncolors, colorcount, timeofday);
|
|
|
|
Haze->Configure (Get_Color(), coldskycolor);
|
|
Starfield->Configure (starfieldcolor, white, starfieldalpha);
|
|
Sun->Configure (suncolor);
|
|
SunHalo->Configure (sunhalocolor);
|
|
Moon->Configure (white);
|
|
MoonHalo->Configure (moonhalocolor);
|
|
CloudLayer0->Configure (warmskycolor, coldskycolor);
|
|
CloudLayer1->Configure (warmskycolor, coldskycolor);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Set_Clouds -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyClass::Set_Clouds (float cloudcover, float gloominess)
|
|
{
|
|
const float layer0minintensity = 0.60f;
|
|
const float layer0maxintensity = 0.95f;
|
|
const float layer1minintensity = 0.20f;
|
|
const float layer1maxintensity = 0.90f;
|
|
|
|
float layer0alpha, layer1alpha, layer0intensity, layer1intensity;
|
|
|
|
WWASSERT ((cloudcover >= 0.0f) && (cloudcover <= 1.0f));
|
|
WWASSERT ((gloominess >= 0.0f) && (gloominess <= 1.0f));
|
|
|
|
Gloominess = gloominess;
|
|
Set_Color();
|
|
|
|
if (cloudcover <= 0.5f) {
|
|
layer0alpha = cloudcover * 2.0f;
|
|
layer1alpha = 0.0f;
|
|
} else {
|
|
layer0alpha = 1.0f;
|
|
layer1alpha = (cloudcover - 0.5f) * 2.0f;
|
|
}
|
|
|
|
layer0alpha = log10 (cloudcover * 9.0f + 1.0f);
|
|
layer1alpha = cloudcover * cloudcover * cloudcover;
|
|
layer0intensity = layer0maxintensity - gloominess * (layer0maxintensity - layer0minintensity);
|
|
layer1intensity = layer1maxintensity - gloominess * (layer1maxintensity - layer1minintensity);
|
|
|
|
Haze->Configure (Get_Color(), layer0intensity);
|
|
CloudLayer0->Configure (layer0alpha, layer0intensity, layer0intensity);
|
|
CloudLayer1->Configure (layer1alpha, layer1intensity, layer0intensity);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Set_Tint_Factor -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyClass::Set_Tint_Factor (float tintfactor)
|
|
{
|
|
TintFactor = tintfactor;
|
|
Set_Color();
|
|
Haze->Configure (Get_Color());
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Set_Color -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyClass::Set_Color()
|
|
{
|
|
const Vector3 tintcolor (1.0f, 0.0f, 0.0f);
|
|
const unsigned colorcount = 24;
|
|
|
|
static const unsigned char _skycolors [colorcount][3] = {
|
|
|
|
{ 4, 12, 18}, // 0000 hrs
|
|
{ 4, 12, 18}, // 0100 hrs
|
|
{ 4, 12, 18}, // 0200 hrs
|
|
{ 4, 12, 18}, // 0300 hrs
|
|
{ 8, 24, 40}, // 0400 hrs
|
|
{ 72, 92, 136}, // 0500 hrs
|
|
{120, 120, 128}, // 0600 hrs
|
|
{128, 152, 168}, // 0700 hrs
|
|
{112, 148, 168}, // 0800 hrs
|
|
{112, 148, 176}, // 0900 hrs
|
|
{112, 148, 176}, // 1000 hrs
|
|
{112, 148, 176}, // 1100 hrs
|
|
{112, 148, 176}, // 1200 hrs
|
|
{112, 148, 176}, // 1300 hrs
|
|
{112, 148, 176}, // 1400 hrs
|
|
{112, 146, 176}, // 1500 hrs
|
|
{128, 160, 176}, // 1600 hrs
|
|
{120, 148, 152}, // 1700 hrs
|
|
{160, 132, 112}, // 1800 hrs
|
|
{ 72, 88, 88}, // 1900 hrs
|
|
{ 8, 24, 36}, // 2000 hrs
|
|
{ 4, 12, 18}, // 2100 hrs
|
|
{ 4, 12, 18}, // 2200 hrs
|
|
{ 4, 12, 18}}; // 2300 hrs
|
|
|
|
static const unsigned char _gloominesscolors [colorcount][3] = {
|
|
|
|
{ 4, 12, 18}, // 0000 hrs
|
|
{ 4, 12, 18}, // 0100 hrs
|
|
{ 4, 12, 18}, // 0200 hrs
|
|
{ 4, 12, 18}, // 0300 hrs
|
|
{ 8, 24, 40}, // 0400 hrs
|
|
{ 72, 92, 136}, // 0500 hrs
|
|
{192, 192, 192}, // 0600 hrs
|
|
{192, 192, 192}, // 0700 hrs
|
|
{192, 192, 192}, // 0800 hrs
|
|
{192, 192, 192}, // 0900 hrs
|
|
{192, 192, 192}, // 1000 hrs
|
|
{192, 192, 192}, // 1100 hrs
|
|
{192, 192, 192}, // 1200 hrs
|
|
{192, 192, 192}, // 1300 hrs
|
|
{192, 192, 192}, // 1400 hrs
|
|
{192, 192, 192}, // 1500 hrs
|
|
{192, 192, 192}, // 1600 hrs
|
|
{192, 192, 192}, // 1700 hrs
|
|
{192, 192, 192}, // 1800 hrs
|
|
{ 72, 88, 88}, // 1900 hrs
|
|
{ 8, 24, 36}, // 2000 hrs
|
|
{ 4, 12, 18}, // 2100 hrs
|
|
{ 4, 12, 18}, // 2200 hrs
|
|
{ 4, 12, 18}}; // 2300 hrs
|
|
|
|
float timeofday, interpolant;
|
|
Vector3 color;
|
|
|
|
timeofday = Hours + (Minutes / 60.0f);
|
|
interpolant = log10 (Gloominess * 9.0f + 1.0f);
|
|
Vector3::Lerp (Interpolate_Color (_skycolors, colorcount, timeofday), Interpolate_Color (_gloominesscolors, colorcount, timeofday), interpolant, &color);
|
|
Vector3::Lerp (color, tintcolor, TintFactor, &Color);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Set_Moon_Type -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyClass::Set_Moon_Type (MoonTypeEnum moontype)
|
|
{
|
|
const char *moontextures [MOON_TYPE_COUNT] = {"FullMoon.tga",
|
|
"PartMoon.tga"};
|
|
|
|
Moon->Set_Texture (moontextures [moontype]);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Interpolate_Color -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
Vector3 SkyClass::Interpolate_Color (const unsigned char colortable [][3], unsigned colorcount, float interpolant)
|
|
{
|
|
const float ooucharmax = 1.0f / UCHAR_MAX;
|
|
|
|
unsigned lowerindex, upperindex;
|
|
Vector3 lowercolor, uppercolor;
|
|
float alpha;
|
|
Vector3 color;
|
|
|
|
// Clamp the interpolant to the index range of the color table.
|
|
interpolant = MIN (MAX (0.0f, interpolant), colorcount);
|
|
if (interpolant == colorcount) interpolant = 0.0f;
|
|
|
|
lowerindex = floorf (interpolant);
|
|
upperindex = (lowerindex + 1) % colorcount;
|
|
|
|
lowercolor = Vector3 (colortable [lowerindex][0] * ooucharmax, colortable [lowerindex][1] * ooucharmax, colortable [lowerindex][2] * ooucharmax);
|
|
uppercolor = Vector3 (colortable [upperindex][0] * ooucharmax, colortable [upperindex][1] * ooucharmax, colortable [upperindex][2] * ooucharmax);
|
|
alpha = interpolant - lowerindex;
|
|
|
|
Vector3::Lerp (lowercolor, uppercolor, alpha, &color);
|
|
return (color);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Interpolate_Scalar -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
float SkyClass::Interpolate_Scalar (const unsigned char scalartable [], unsigned scalarcount, float interpolant)
|
|
{
|
|
const float ooucharmax = 1.0f / UCHAR_MAX;
|
|
|
|
unsigned lowerindex, upperindex;
|
|
float lowervalue, uppervalue, alpha;
|
|
|
|
// Clamp the interpolant to the index range of the color table.
|
|
interpolant = MIN (MAX (0.0f, interpolant), scalarcount);
|
|
if (interpolant == scalarcount) interpolant = 0.0f;
|
|
|
|
lowerindex = floorf (interpolant);
|
|
upperindex = (lowerindex + 1) % scalarcount;
|
|
|
|
lowervalue = scalartable [lowerindex] * ooucharmax;
|
|
uppervalue = scalartable [upperindex] * ooucharmax;
|
|
alpha = interpolant - lowerindex;
|
|
|
|
return (lowervalue + ((uppervalue - lowervalue) * alpha));
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Lightning_Delay -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
unsigned SkyClass::Lightning_Delay()
|
|
{
|
|
const unsigned maxdelay = 240000; // Maximum delay for lightning (in milliseconds).
|
|
|
|
return (_RandomNumber (1, maxdelay));
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::War_Blitz_Delay -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 06/26/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
unsigned SkyClass::War_Blitz_Delay()
|
|
{
|
|
const unsigned maxdelay = 240000; // Maximum delay for war blitz (in milliseconds).
|
|
|
|
return (_RandomNumber (1, maxdelay));
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Update -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyClass::Update (SceneClass *mainscene, const Vector3 &cameraposition)
|
|
{
|
|
const unsigned timescale = 40;
|
|
const Vector3 white (1.0f, 1.0f, 1.0f);
|
|
|
|
unsigned time;
|
|
Vector3 colorsum, fogcolor;
|
|
int ticks;
|
|
|
|
Matrix3D t = Matrix3D (cameraposition);
|
|
Set_Transform (t);
|
|
|
|
// Iterate over lightning and create, update or destroy them as necessary.
|
|
time = WW3D::Get_Frame_Time();
|
|
colorsum.Set (0.0f, 0.0f, 0.0f);
|
|
for (unsigned l = 0; l < LIGHTNING_COUNT; l++) {
|
|
|
|
// Is it time to create some more lightning?
|
|
// NOTE: If lightning intensity is zero then no more lightning will be created.
|
|
ticks = ((int) (LightningIntensity * timescale)) * time;
|
|
LightningCountdown [l] -= ticks;
|
|
if (LightningCountdown [l] <= 0) {
|
|
|
|
LightningCountdown [l] = Lightning_Delay();
|
|
if (Lightning [l] == NULL) {
|
|
|
|
// Is lightning enabled?
|
|
if (LightningIntensity > 0.0f) {
|
|
Lightning [l] = new LightningClass (Extent, LightningStartDistance, LightningEndDistance, LightningHeading, LightningDistribution);
|
|
WWASSERT (Lightning [l] != NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Lightning [l] != NULL) {
|
|
|
|
Vector3 lightningcolor;
|
|
|
|
if (!Lightning [l]->Update (t, lightningcolor, SoundEnvironment)) {
|
|
|
|
// Lightning has played out - so remove it.
|
|
delete Lightning [l];
|
|
Lightning [l] = NULL;
|
|
|
|
} else {
|
|
colorsum += lightningcolor;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Is it time to create a war blitz?
|
|
// NOTE: If war blitz intensity is zero then no more will be created.
|
|
ticks = ((int) (WarBlitzIntensity * timescale)) * time;
|
|
WarBlitzCountdown -= ticks;
|
|
if (WarBlitzCountdown <= 0) {
|
|
|
|
WarBlitzCountdown = War_Blitz_Delay();
|
|
if (WarBlitz == NULL) {
|
|
|
|
// Is war blitz enabled?
|
|
if (WarBlitzIntensity > 0.0f) {
|
|
WarBlitz = new WarBlitzClass (Extent, WarBlitzStartDistance, WarBlitzEndDistance, WarBlitzHeading, WarBlitzDistribution);
|
|
WWASSERT (WarBlitz != NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (WarBlitz != NULL) {
|
|
|
|
Vector3 warblitzcolor;
|
|
|
|
if (!WarBlitz->Update (t, warblitzcolor)) {
|
|
|
|
// War blitz has played out - so remove it.
|
|
delete WarBlitz;
|
|
WarBlitz = NULL;
|
|
|
|
} else {
|
|
colorsum += warblitzcolor;
|
|
}
|
|
}
|
|
|
|
// Set the main scene fog color to color at horizon plus any lightning/war blitz color.
|
|
fogcolor = Haze->Get_Horizon_Color() + colorsum;
|
|
fogcolor.Update_Min (white);
|
|
mainscene->Set_Fog_Color (fogcolor);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Render -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyClass::Render (RenderInfoClass &rinfo)
|
|
{
|
|
DX8Wrapper::Set_Transform (D3DTS_WORLD, Transform);
|
|
|
|
// Render in predetermined order.
|
|
Haze->Render();
|
|
Starfield->Render();
|
|
CloudLayer0->Render();
|
|
MoonHalo->Render();
|
|
Moon->Render();
|
|
SunHalo->Render();
|
|
CloudLayer1->Render();
|
|
Sun->Render();
|
|
for (unsigned l = 0; l < LIGHTNING_COUNT; l++) {
|
|
if (Lightning [l] != NULL) Lightning [l]->Render (rinfo);
|
|
}
|
|
if (WarBlitz != NULL) WarBlitz->Render (rinfo);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Get_Obj_Space_Bounding_Sphere -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyClass::Get_Obj_Space_Bounding_Sphere (SphereClass &sphere) const
|
|
{
|
|
const Vector3 position (0.0f, 0.0f, 0.0f);
|
|
const Vector3 extent (Extent, Extent, Extent);
|
|
|
|
sphere.Init (position, extent.Length());
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SkyClass::Get_Obj_Space_Bounding_Box -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void SkyClass::Get_Obj_Space_Bounding_Box (AABoxClass &box) const
|
|
{
|
|
const Vector3 position (0.0f, 0.0f, 0.0f);
|
|
const Vector3 extent (Extent, Extent, Extent);
|
|
|
|
box.Init (position, extent);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundParameterClass::Initialize -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 04/24/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundParameterClass::Initialize()
|
|
{
|
|
CurrentValue = 0.0f;
|
|
NormalTarget = 0.0f;
|
|
NormalDuration = 0.0f;
|
|
OverrideTarget = 0.0f;
|
|
OverrideDuration = 0.0f;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundParameterClass::Set -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 04/24/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundParameterClass::Set (float target, float ramptime, bool override)
|
|
{
|
|
if (!override) {
|
|
NormalTarget = target;
|
|
NormalDuration = ramptime;
|
|
} else {
|
|
OverrideTarget = target;
|
|
OverrideDuration = ramptime;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundParameterClass::Update -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 04/24/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundParameterClass::Update (float time, bool override)
|
|
{
|
|
const float previouscurrentvalue = CurrentValue;
|
|
|
|
// Update the normal parameters.
|
|
Update (NormalValue, NormalTarget, NormalDuration, time);
|
|
|
|
// Update the override parameters?
|
|
if (override) {
|
|
Update (CurrentValue, OverrideTarget, OverrideDuration, time);
|
|
} else {
|
|
if (OverrideDuration > 0.0f) {
|
|
Update (CurrentValue, NormalValue, OverrideDuration, time);
|
|
} else {
|
|
CurrentValue = NormalValue;
|
|
}
|
|
}
|
|
|
|
return (CurrentValue != previouscurrentvalue);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundParameterClass::Update -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 04/24/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundParameterClass::Update (float &value, float &target, float &duration, float time)
|
|
{
|
|
if (value == target) {
|
|
duration = 0.0f;
|
|
} else {
|
|
duration -= time;
|
|
if (duration > 0.0f) {
|
|
|
|
bool sign0, sign1;
|
|
|
|
sign0 = value < target;
|
|
value += ((target - value) * (time / duration));
|
|
if (value == target) {
|
|
duration = 0.0f;
|
|
} else {
|
|
sign1 = value < target;
|
|
|
|
// If the value has 'blown past' the target value...
|
|
if (sign0 ^ sign1) {
|
|
duration = 0.0f;
|
|
value = target;
|
|
}
|
|
}
|
|
} else {
|
|
duration = 0.0f;
|
|
value = target;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::BackgroundMgrClass -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 03/06/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
BackgroundMgrClass::BackgroundMgrClass()
|
|
{
|
|
Set_Network_ID (NETID_SERVER_BACKGROUND);
|
|
Set_App_Packet_Type (APPPACKETTYPE_NETBACKGROUND);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Init -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundMgrClass::Init (SimpleSceneClass *renderscene, SoundEnvironmentClass *soundenvironment, bool render_available)
|
|
{
|
|
WWASSERT (renderscene != NULL);
|
|
WWASSERT (_Sky == NULL);
|
|
WWASSERT (_Dazzle == NULL);
|
|
|
|
if (render_available) {
|
|
_Sky = NEW_REF (SkyClass, (soundenvironment));
|
|
renderscene->Add_Render_Object (_Sky);
|
|
|
|
_Dazzle = NEW_REF (DazzleRenderObjClass, ("SUN"));
|
|
renderscene->Add_Render_Object (_Dazzle);
|
|
}
|
|
Reset();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Reset -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundMgrClass::Reset()
|
|
{
|
|
// Iterate and initialize the parameters.
|
|
for (unsigned p = 0; p < PARAMETER_COUNT; p++) {
|
|
_Parameters [p].Initialize();
|
|
}
|
|
|
|
// Set the background components to sensible defaults.
|
|
Set_Time_Of_Day (15, 0);
|
|
_LightSourceType = LIGHT_SOURCE_TYPE_SUN;
|
|
Set_Moon_Type (SkyClass::MOON_TYPE_FULL);
|
|
Set_Clouds (0.0f, 0.0f, 0.0f, false);
|
|
Set_Sky_Tint (0.0f, 0.0f, false);
|
|
Set_Lightning (0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.0f, false);
|
|
Set_War_Blitz (0.0f, 0.0f, 1.0f, 0.0f, 0.5f);
|
|
|
|
_LightVector.Set (1.0f, 0.0f, 0.0f);
|
|
_UnitLightVector.Set (1.0f, 0.0f, 0.0f);
|
|
_CloudOverrideCount = 0;
|
|
_LightningOverrideCount = 0;
|
|
_SkyTintOverrideCount = 0;
|
|
|
|
Set_Dirty();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Shutdown -- Deallocate resources. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundMgrClass::Shutdown()
|
|
{
|
|
//WWASSERT (_Dazzle != NULL);
|
|
//WWASSERT (_Sky != NULL);
|
|
if (_Dazzle) {
|
|
_Dazzle->Remove();
|
|
REF_PTR_RELEASE (_Dazzle);
|
|
}
|
|
if (_Sky) {
|
|
_Sky->Remove();
|
|
REF_PTR_RELEASE (_Sky);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Set_Clouds -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Set_Clouds (float cloudcover, float cloudgloominess, float ramptime)
|
|
{
|
|
if (CombatManager::I_Am_Server()) {
|
|
if (Set_Clouds (cloudcover, cloudgloominess, ramptime, false)) {
|
|
_TheBackgroundMgr.Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
|
|
return (true);
|
|
}
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Override_Clouds -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Override_Clouds (float cloudcover, float cloudgloominess, float ramptime)
|
|
{
|
|
if (CombatManager::I_Am_Server()) {
|
|
_CloudOverrideCount++;
|
|
if (Set_Clouds (cloudcover, cloudgloominess, ramptime, true)) {
|
|
_TheBackgroundMgr.Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
|
|
return (true);
|
|
}
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Get_Clouds -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundMgrClass::Get_Clouds (float &cloudcover, float &gloominess)
|
|
{
|
|
cloudcover = _Parameters [PARAMETER_CLOUD_COVER].Value();
|
|
gloominess = _Parameters [PARAMETER_CLOUD_GLOOMINESS].Value();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Set_Clouds -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Set_Clouds (float cloudcover, float cloudgloominess, float ramptime, bool override)
|
|
{
|
|
if ((cloudcover >= 0.0f) && (cloudcover <= 1.0f) && (cloudgloominess >= 0.0f) && (cloudgloominess <= 1.0f) && (ramptime >= 0.0f)) {
|
|
|
|
const bool o = override && (_CloudOverrideCount > 0);
|
|
|
|
_Parameters [PARAMETER_CLOUD_COVER].Set (cloudcover, ramptime, o);
|
|
_Parameters [PARAMETER_CLOUD_GLOOMINESS].Set (cloudgloominess, ramptime, o);
|
|
return (true);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Restore_Clouds -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundMgrClass::Restore_Clouds (float ramptime)
|
|
{
|
|
if (CombatManager::I_Am_Server()) {
|
|
|
|
WWASSERT (_CloudOverrideCount > 0);
|
|
|
|
_Parameters [PARAMETER_CLOUD_COVER].Set (ramptime);
|
|
_Parameters [PARAMETER_CLOUD_GLOOMINESS].Set (ramptime);
|
|
_CloudOverrideCount--;
|
|
_TheBackgroundMgr.Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Set_Sky_Tint -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Set_Sky_Tint (float skytintfactor, float ramptime)
|
|
{
|
|
if (CombatManager::I_Am_Server()) {
|
|
if (Set_Sky_Tint (skytintfactor, ramptime, false)) {
|
|
_TheBackgroundMgr.Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
|
|
return (true);
|
|
}
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Override_Sky_Tint -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Override_Sky_Tint (float skytintfactor, float ramptime)
|
|
{
|
|
if (CombatManager::I_Am_Server()) {
|
|
_SkyTintOverrideCount++;
|
|
if (Set_Sky_Tint (skytintfactor, ramptime, true)) {
|
|
_TheBackgroundMgr.Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
|
|
return (true);
|
|
}
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Restore_Sky_Tint -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundMgrClass::Restore_Sky_Tint (float ramptime)
|
|
{
|
|
if (CombatManager::I_Am_Server()) {
|
|
|
|
WWASSERT (_SkyTintOverrideCount > 0);
|
|
|
|
_Parameters [PARAMETER_SKY_TINT_FACTOR].Set (ramptime);
|
|
_SkyTintOverrideCount--;
|
|
_TheBackgroundMgr.Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Set_Sky_Tint -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Set_Sky_Tint (float skytintfactor, float ramptime, bool override)
|
|
{
|
|
if ((skytintfactor >= 0.0f) && (skytintfactor <= 1.0f) && (ramptime >= 0.0f)) {
|
|
|
|
const bool o = override && (_SkyTintOverrideCount > 0);
|
|
|
|
_Parameters [PARAMETER_SKY_TINT_FACTOR].Set (skytintfactor, ramptime, o);
|
|
return (true);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Set_Lightning_Intensity -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Set_Lightning_Intensity (float intensity, float ramptime)
|
|
{
|
|
if (CombatManager::I_Am_Server()) {
|
|
if (Set_Lightning_Intensity (intensity, ramptime, false)) {
|
|
_TheBackgroundMgr.Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
|
|
return (true);
|
|
}
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Set_Lightning -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Set_Lightning (float intensity, float startdistance, float enddistance, float heading, float distribution, float ramptime)
|
|
{
|
|
if (CombatManager::I_Am_Server()) {
|
|
if (Set_Lightning (intensity, startdistance, enddistance, heading, distribution, ramptime, false)) {
|
|
_TheBackgroundMgr.Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
|
|
return (true);
|
|
}
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Override_Lightning -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Override_Lightning (float intensity, float startdistance, float enddistance, float heading, float distribution, float ramptime)
|
|
{
|
|
if (CombatManager::I_Am_Server()) {
|
|
_LightningOverrideCount++;
|
|
if (Set_Lightning (intensity, startdistance, enddistance, heading, distribution, ramptime, true)) {
|
|
_TheBackgroundMgr.Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
|
|
return (true);
|
|
}
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Set_Lightning_Intensity -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Set_Lightning_Intensity (float intensity, float ramptime, bool override)
|
|
{
|
|
if ((intensity >= 0.0f) && (intensity <= 1.0f) && (ramptime >= 0.0f)) {
|
|
|
|
const bool o = (_LightningOverrideCount > 0) && override;
|
|
|
|
_Parameters [PARAMETER_LIGHTNING_INTENSITY].Set (intensity, ramptime, o);
|
|
return (true);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Set_Lightning -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Set_Lightning (float intensity, float startdistance, float enddistance, float heading, float distribution, float ramptime, bool override)
|
|
{
|
|
if ((intensity >= 0.0f) && (intensity <= 1.0f) && (startdistance >= 0.0f) && (startdistance <= 1.0f) &&
|
|
(enddistance >= 0.0f) && (enddistance <= 1.0f) && (heading >= 0.0f) && (heading <= 360.0f) &&
|
|
(distribution >= 0.0f) && (distribution <= 1.0f) && (ramptime >= 0.0f)) {
|
|
|
|
const bool o = (_LightningOverrideCount > 0) && override;
|
|
|
|
_Parameters [PARAMETER_LIGHTNING_INTENSITY].Set (intensity, ramptime, o);
|
|
_Parameters [PARAMETER_LIGHTNING_START_DISTANCE].Set (startdistance, ramptime, o);
|
|
_Parameters [PARAMETER_LIGHTNING_END_DISTANCE].Set (enddistance, ramptime, o);
|
|
_Parameters [PARAMETER_LIGHTNING_HEADING].Set (heading, ramptime, o);
|
|
_Parameters [PARAMETER_LIGHTNING_DISTRIBUTION].Set (distribution, ramptime, o);
|
|
return (true);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Get_Lightning -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundMgrClass::Get_Lightning (float &intensity, float &startdistance, float &enddistance, float &heading, float &distribution)
|
|
{
|
|
intensity = _Parameters [PARAMETER_LIGHTNING_INTENSITY].Value();
|
|
startdistance = _Parameters [PARAMETER_LIGHTNING_START_DISTANCE].Value();
|
|
enddistance = _Parameters [PARAMETER_LIGHTNING_END_DISTANCE].Value();
|
|
heading = _Parameters [PARAMETER_LIGHTNING_HEADING].Value();
|
|
distribution = _Parameters [PARAMETER_LIGHTNING_DISTRIBUTION].Value();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Restore_Lightning -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundMgrClass::Restore_Lightning (float ramptime)
|
|
{
|
|
if (CombatManager::I_Am_Server()) {
|
|
_Parameters [PARAMETER_LIGHTNING_INTENSITY].Set (ramptime);
|
|
_Parameters [PARAMETER_LIGHTNING_START_DISTANCE].Set (ramptime);
|
|
_Parameters [PARAMETER_LIGHTNING_END_DISTANCE].Set (ramptime);
|
|
_Parameters [PARAMETER_LIGHTNING_HEADING].Set (ramptime);
|
|
_Parameters [PARAMETER_LIGHTNING_DISTRIBUTION].Set (ramptime);
|
|
_LightningOverrideCount--;
|
|
_TheBackgroundMgr.Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Set_War_Blitz -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Set_War_Blitz (float intensity, float ramptime)
|
|
{
|
|
if ((intensity >= 0.0f) && (intensity <= 1.0f) && (ramptime >= 0.0f)) {
|
|
_Parameters [PARAMETER_WAR_BLITZ_INTENSITY].Set (intensity, ramptime, false);
|
|
return (true);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Set_War_Blitz -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Set_War_Blitz (float intensity, float startdistance, float enddistance, float heading, float distribution, float ramptime, bool override)
|
|
{
|
|
if ((intensity >= 0.0f) && (intensity <= 1.0f) && (startdistance >= 0.0f) && (startdistance <= 1.0f) &&
|
|
(enddistance >= 0.0f) && (enddistance <= 1.0f) && (heading >= 0.0f) && (heading <= 360.0f) &&
|
|
(distribution >= 0.0f) && (distribution <= 1.0f) && (ramptime >= 0.0f)) {
|
|
|
|
_Parameters [PARAMETER_WAR_BLITZ_INTENSITY].Set (intensity, ramptime, false);
|
|
_Parameters [PARAMETER_WAR_BLITZ_START_DISTANCE].Set (startdistance, ramptime, false);
|
|
_Parameters [PARAMETER_WAR_BLITZ_END_DISTANCE].Set (enddistance, ramptime, false);
|
|
_Parameters [PARAMETER_WAR_BLITZ_HEADING].Set (heading, ramptime, false);
|
|
_Parameters [PARAMETER_WAR_BLITZ_DISTRIBUTION].Set (distribution, ramptime, false);
|
|
return (true);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Get_War_Blitz -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundMgrClass::Get_War_Blitz (float &intensity, float &startdistance, float &enddistance, float &heading, float &distribution)
|
|
{
|
|
intensity = _Parameters [PARAMETER_WAR_BLITZ_INTENSITY].Value();
|
|
startdistance = _Parameters [PARAMETER_WAR_BLITZ_START_DISTANCE].Value();
|
|
enddistance = _Parameters [PARAMETER_WAR_BLITZ_END_DISTANCE].Value();
|
|
heading = _Parameters [PARAMETER_WAR_BLITZ_HEADING].Value();
|
|
distribution = _Parameters [PARAMETER_WAR_BLITZ_DISTRIBUTION].Value();
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Update -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
void BackgroundMgrClass::Update (PhysicsSceneClass *mainscene, CameraClass *camera)
|
|
{
|
|
const float minlensflareintensity = 0.10f;
|
|
const float maxlensflareintensity = 0.50f;
|
|
|
|
float time;
|
|
bool cloudsmodified, skytintmodified, lightningmodified, warblitzmodified;
|
|
Vector3 lightvector;
|
|
float znear, zfar;
|
|
Vector3 dazzlecolor;
|
|
float cloudcover, gloominess;
|
|
float intensity, dazzleintensity, lensflareintensity;
|
|
|
|
if (_Sky == NULL) return;
|
|
|
|
WWASSERT (mainscene != NULL);
|
|
WWASSERT (camera != NULL);
|
|
WWASSERT (_Sky != NULL);
|
|
WWASSERT (_Dazzle != NULL);
|
|
|
|
if (Is_Dirty()) {
|
|
_Sky->Set_Time_Of_Day (_Hours, _Minutes);
|
|
_Sky->Set_Moon_Type (_MoonType);
|
|
}
|
|
|
|
// Process parameters.
|
|
time = WW3D::Get_Frame_Time() * 0.001f;
|
|
|
|
cloudsmodified = _Parameters [PARAMETER_CLOUD_COVER].Update (time, _CloudOverrideCount > 0);
|
|
cloudsmodified |= _Parameters [PARAMETER_CLOUD_GLOOMINESS].Update (time, _CloudOverrideCount > 0);
|
|
if (Is_Dirty() || cloudsmodified) {
|
|
_Sky->Set_Clouds (_Parameters [PARAMETER_CLOUD_COVER].Value(), _Parameters [PARAMETER_CLOUD_GLOOMINESS].Value());
|
|
}
|
|
|
|
skytintmodified = _Parameters [PARAMETER_SKY_TINT_FACTOR].Update (time, _SkyTintOverrideCount > 0);
|
|
if (Is_Dirty() || skytintmodified) {
|
|
_Sky->Set_Tint_Factor (_Parameters [PARAMETER_SKY_TINT_FACTOR].Value());
|
|
}
|
|
|
|
lightningmodified = _Parameters [PARAMETER_LIGHTNING_INTENSITY].Update (time, _LightningOverrideCount > 0);
|
|
lightningmodified |= _Parameters [PARAMETER_LIGHTNING_START_DISTANCE].Update (time, _LightningOverrideCount > 0);
|
|
lightningmodified |= _Parameters [PARAMETER_LIGHTNING_END_DISTANCE].Update (time, _LightningOverrideCount > 0);
|
|
lightningmodified |= _Parameters [PARAMETER_LIGHTNING_HEADING].Update (time, _LightningOverrideCount > 0);
|
|
lightningmodified |= _Parameters [PARAMETER_LIGHTNING_DISTRIBUTION].Update (time, _LightningOverrideCount > 0);
|
|
if (Is_Dirty() || lightningmodified) {
|
|
_Sky->Set_Lightning (_Parameters [PARAMETER_LIGHTNING_INTENSITY].Value(), _Parameters [PARAMETER_LIGHTNING_START_DISTANCE].Value(), _Parameters [PARAMETER_LIGHTNING_END_DISTANCE].Value(), _Parameters [PARAMETER_LIGHTNING_HEADING].Value(), _Parameters [PARAMETER_LIGHTNING_DISTRIBUTION].Value());
|
|
}
|
|
|
|
warblitzmodified = _Parameters [PARAMETER_WAR_BLITZ_INTENSITY].Update (time, false);
|
|
warblitzmodified |= _Parameters [PARAMETER_WAR_BLITZ_START_DISTANCE].Update (time, false);
|
|
warblitzmodified |= _Parameters [PARAMETER_WAR_BLITZ_END_DISTANCE].Update (time, false);
|
|
warblitzmodified |= _Parameters [PARAMETER_WAR_BLITZ_HEADING].Update (time, false);
|
|
warblitzmodified |= _Parameters [PARAMETER_WAR_BLITZ_DISTRIBUTION].Update (time, false);
|
|
if (Is_Dirty() || warblitzmodified) {
|
|
_Sky->Set_War_Blitz (_Parameters [PARAMETER_WAR_BLITZ_INTENSITY].Value(), _Parameters [PARAMETER_WAR_BLITZ_START_DISTANCE].Value(), _Parameters [PARAMETER_WAR_BLITZ_END_DISTANCE].Value(), _Parameters [PARAMETER_WAR_BLITZ_HEADING].Value(), _Parameters [PARAMETER_WAR_BLITZ_DISTRIBUTION].Value());
|
|
}
|
|
|
|
// Has the sunlight direction changed this frame?
|
|
mainscene->Get_Sun_Light_Vector (&lightvector);
|
|
if (Is_Dirty() || (_LightVector != lightvector)) {
|
|
|
|
// NOTE 0: Direction must be normalized.
|
|
// NOTE 1: For simplicity, the moon is always directly opposite the sun.
|
|
_LightVector = lightvector;
|
|
_UnitLightVector = Normalize (-lightvector);
|
|
|
|
// Invert the direction if the light source is the moon (rather than the sun).
|
|
if (_LightSourceType == LIGHT_SOURCE_TYPE_MOON) {
|
|
_UnitLightVector = -_UnitLightVector;
|
|
}
|
|
|
|
_Sky->Set_Light_Direction (_UnitLightVector, -_UnitLightVector);
|
|
}
|
|
|
|
_Sky->Update (mainscene, camera->Get_Position());
|
|
|
|
// Locate the sun dazzle just inside the far clip plane.
|
|
camera->Get_Clip_Planes (znear, zfar);
|
|
_Dazzle->Set_Transform (Matrix3D (camera->Get_Position() + _UnitLightVector * (zfar - 1.0f)));
|
|
|
|
// Set the dazzle color to that of sun.
|
|
// Attenuate dazzle and lensflare as function of cloud cover and gloominess.
|
|
Get_Clouds (cloudcover, gloominess);
|
|
intensity = 1.0f - (0.5f * (cloudcover + gloominess));
|
|
dazzleintensity = (0.75f * intensity) + 0.25f;
|
|
dazzlecolor = _Sky->Get_Sun()->Get_Color() * dazzleintensity;
|
|
if (intensity < minlensflareintensity) {
|
|
lensflareintensity = 0.0f;
|
|
} else {
|
|
lensflareintensity = MIN (maxlensflareintensity, intensity);
|
|
}
|
|
_Dazzle->Set_Dazzle_Color (dazzlecolor);
|
|
_Dazzle->Set_Lensflare_Intensity (lensflareintensity);
|
|
|
|
// Everything necessary has been updated. Clear the dirty flag.
|
|
Set_Dirty (false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Save -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
#define WRITE_PARAMETER(varname) \
|
|
WRITE_MICRO_CHUNK (csave, VARID_ ## varname ## _CURRENT_VALUE, _Parameters [PARAMETER_ ## varname ##].CurrentValue); \
|
|
WRITE_MICRO_CHUNK (csave, VARID_ ## varname ## _NORMAL_VALUE, _Parameters [PARAMETER_ ## varname ##].NormalValue); \
|
|
WRITE_MICRO_CHUNK (csave, VARID_ ## varname ## _NORMAL_TARGET, _Parameters [PARAMETER_ ## varname ##].NormalTarget); \
|
|
WRITE_MICRO_CHUNK (csave, VARID_ ## varname ## _NORMAL_DURATION, _Parameters [PARAMETER_ ## varname ##].NormalDuration); \
|
|
WRITE_MICRO_CHUNK (csave, VARID_ ## varname ## _OVERRIDE_TARGET, _Parameters [PARAMETER_ ## varname ##].OverrideTarget); \
|
|
WRITE_MICRO_CHUNK (csave, VARID_ ## varname ## _OVERRIDE_DURATION, _Parameters [PARAMETER_ ## varname ##].OverrideDuration)
|
|
|
|
bool BackgroundMgrClass::Save (ChunkSaveClass &csave)
|
|
{
|
|
csave.Begin_Chunk (CHUNKID_MICRO_CHUNKS);
|
|
WRITE_MICRO_CHUNK (csave, VARID_TIME_HOURS, _Hours);
|
|
WRITE_MICRO_CHUNK (csave, VARID_TIME_MINUTES, _Minutes);
|
|
WRITE_MICRO_CHUNK (csave, VARID_LIGHT_SOURCE_TYPE, _LightSourceType);
|
|
WRITE_MICRO_CHUNK (csave, VARID_MOON_TYPE, _MoonType);
|
|
csave.End_Chunk ();
|
|
|
|
Save_Dynamic (csave);
|
|
return (true);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Save Dynamic -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Save_Dynamic (ChunkSaveClass &csave)
|
|
{
|
|
csave.Begin_Chunk (CHUNKID_DYNAMIC_MICRO_CHUNKS);
|
|
WRITE_PARAMETER (SKY_TINT_FACTOR);
|
|
WRITE_PARAMETER (CLOUD_COVER);
|
|
WRITE_PARAMETER (CLOUD_GLOOMINESS);
|
|
WRITE_PARAMETER (LIGHTNING_INTENSITY);
|
|
WRITE_PARAMETER (LIGHTNING_START_DISTANCE);
|
|
WRITE_PARAMETER (LIGHTNING_END_DISTANCE);
|
|
WRITE_PARAMETER (LIGHTNING_HEADING);
|
|
WRITE_PARAMETER (LIGHTNING_DISTRIBUTION);
|
|
WRITE_MICRO_CHUNK (csave, VARID_CLOUD_OVERRIDE_COUNT, _CloudOverrideCount);
|
|
WRITE_MICRO_CHUNK (csave, VARID_LIGHTNING_OVERRIDE_COUNT, _LightningOverrideCount);
|
|
WRITE_PARAMETER (WAR_BLITZ_INTENSITY);
|
|
WRITE_PARAMETER (WAR_BLITZ_START_DISTANCE);
|
|
WRITE_PARAMETER (WAR_BLITZ_END_DISTANCE);
|
|
WRITE_PARAMETER (WAR_BLITZ_HEADING);
|
|
WRITE_PARAMETER (WAR_BLITZ_DISTRIBUTION);
|
|
WRITE_MICRO_CHUNK (csave, VARID_SKY_TINT_OVERRIDE_COUNT, _SkyTintOverrideCount);
|
|
csave.End_Chunk ();
|
|
return (true);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Load -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Load (ChunkLoadClass &cload)
|
|
{
|
|
WWMEMLOG (MEM_GAMEDATA);
|
|
|
|
bool retval = true;
|
|
|
|
while (cload.Open_Chunk ()) {
|
|
switch (cload.Cur_Chunk_ID ()) {
|
|
|
|
case CHUNKID_MICRO_CHUNKS:
|
|
retval &= Load_Micro_Chunks (cload);
|
|
break;
|
|
|
|
case CHUNKID_DYNAMIC_MICRO_CHUNKS:
|
|
retval &= Load_Dynamic_Micro_Chunks (cload);
|
|
break;
|
|
|
|
}
|
|
cload.Close_Chunk ();
|
|
}
|
|
|
|
return (retval);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Load_Micro_Chunks -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
#define READ_PARAMETER(varname) \
|
|
READ_MICRO_CHUNK (cload, VARID_ ## varname ## _CURRENT_VALUE, _Parameters [PARAMETER_ ## varname ##].CurrentValue); \
|
|
READ_MICRO_CHUNK (cload, VARID_ ## varname ## _NORMAL_VALUE, _Parameters [PARAMETER_ ## varname ##].NormalValue); \
|
|
READ_MICRO_CHUNK (cload, VARID_ ## varname ## _NORMAL_TARGET, _Parameters [PARAMETER_ ## varname ##].NormalTarget); \
|
|
READ_MICRO_CHUNK (cload, VARID_ ## varname ## _NORMAL_DURATION, _Parameters [PARAMETER_ ## varname ##].NormalDuration); \
|
|
READ_MICRO_CHUNK (cload, VARID_ ## varname ## _OVERRIDE_TARGET, _Parameters [PARAMETER_ ## varname ##].OverrideTarget); \
|
|
READ_MICRO_CHUNK (cload, VARID_ ## varname ## _OVERRIDE_DURATION, _Parameters [PARAMETER_ ## varname ##].OverrideDuration)
|
|
|
|
bool BackgroundMgrClass::Load_Micro_Chunks (ChunkLoadClass &cload)
|
|
{
|
|
// Read background micro chunk.
|
|
while (cload.Open_Micro_Chunk ()) {
|
|
switch (cload.Cur_Micro_Chunk_ID ()) {
|
|
READ_MICRO_CHUNK (cload, VARID_TIME_HOURS, _Hours);
|
|
READ_MICRO_CHUNK (cload, VARID_TIME_MINUTES, _Minutes);
|
|
READ_MICRO_CHUNK (cload, VARID_LIGHT_SOURCE_TYPE, _LightSourceType);
|
|
READ_MICRO_CHUNK (cload, VARID_MOON_TYPE, _MoonType);
|
|
}
|
|
cload.Close_Micro_Chunk ();
|
|
}
|
|
|
|
return (true);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Load Dynamic -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Load_Dynamic (ChunkLoadClass &cload)
|
|
{
|
|
WWMEMLOG (MEM_GAMEDATA);
|
|
|
|
bool retval = true;
|
|
|
|
while (cload.Open_Chunk ()) {
|
|
switch (cload.Cur_Chunk_ID ()) {
|
|
|
|
case CHUNKID_DYNAMIC_MICRO_CHUNKS:
|
|
retval &= Load_Dynamic_Micro_Chunks (cload);
|
|
break;
|
|
}
|
|
cload.Close_Chunk ();
|
|
}
|
|
return (retval);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Load_Dynamic_Micro_Chunks -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 09/15/00 IML : Created. *
|
|
*=============================================================================================*/
|
|
bool BackgroundMgrClass::Load_Dynamic_Micro_Chunks (ChunkLoadClass &cload)
|
|
{
|
|
// Read background micro chunk.
|
|
while (cload.Open_Micro_Chunk ()) {
|
|
switch (cload.Cur_Micro_Chunk_ID ()) {
|
|
READ_PARAMETER (SKY_TINT_FACTOR);
|
|
READ_PARAMETER (CLOUD_COVER);
|
|
READ_PARAMETER (CLOUD_GLOOMINESS);
|
|
READ_PARAMETER (LIGHTNING_INTENSITY);
|
|
READ_PARAMETER (LIGHTNING_START_DISTANCE);
|
|
READ_PARAMETER (LIGHTNING_END_DISTANCE);
|
|
READ_PARAMETER (LIGHTNING_HEADING);
|
|
READ_PARAMETER (LIGHTNING_DISTRIBUTION);
|
|
READ_MICRO_CHUNK (cload, VARID_CLOUD_OVERRIDE_COUNT, _CloudOverrideCount);
|
|
READ_MICRO_CHUNK (cload, VARID_LIGHTNING_OVERRIDE_COUNT, _LightningOverrideCount);
|
|
READ_PARAMETER (WAR_BLITZ_INTENSITY);
|
|
READ_PARAMETER (WAR_BLITZ_START_DISTANCE);
|
|
READ_PARAMETER (WAR_BLITZ_END_DISTANCE);
|
|
READ_PARAMETER (WAR_BLITZ_HEADING);
|
|
READ_PARAMETER (WAR_BLITZ_DISTRIBUTION);
|
|
READ_MICRO_CHUNK (cload, VARID_SKY_TINT_OVERRIDE_COUNT, _SkyTintOverrideCount);
|
|
}
|
|
cload.Close_Micro_Chunk ();
|
|
}
|
|
|
|
return (true);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Export_Rare -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 03/02/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
#define EXPORT_PARAMETER(object, varname) \
|
|
object.Add (_Parameters [PARAMETER_ ## varname ##].NormalTarget); \
|
|
object.Add (_Parameters [PARAMETER_ ## varname ##].NormalDuration); \
|
|
object.Add (_Parameters [PARAMETER_ ## varname ##].OverrideTarget); \
|
|
object.Add (_Parameters [PARAMETER_ ## varname ##].OverrideDuration)
|
|
|
|
void BackgroundMgrClass::Export_Rare (BitStreamClass &packet)
|
|
{
|
|
WWASSERT (CombatManager::I_Am_Server());
|
|
|
|
EXPORT_PARAMETER (packet, SKY_TINT_FACTOR);
|
|
EXPORT_PARAMETER (packet, CLOUD_COVER);
|
|
EXPORT_PARAMETER (packet, CLOUD_GLOOMINESS);
|
|
EXPORT_PARAMETER (packet, LIGHTNING_INTENSITY);
|
|
EXPORT_PARAMETER (packet, LIGHTNING_START_DISTANCE);
|
|
EXPORT_PARAMETER (packet, LIGHTNING_END_DISTANCE);
|
|
EXPORT_PARAMETER (packet, LIGHTNING_HEADING);
|
|
EXPORT_PARAMETER (packet, LIGHTNING_DISTRIBUTION);
|
|
packet.Add (_CloudOverrideCount);
|
|
packet.Add (_LightningOverrideCount);
|
|
packet.Add (_SkyTintOverrideCount);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* BackgroundMgrClass::Import_Rare -- *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 03/02/01 IML : Created. *
|
|
*=============================================================================================*/
|
|
#define IMPORT_PARAMETER(object, varname) \
|
|
object.Get (_Parameters [PARAMETER_ ## varname ##].NormalTarget); \
|
|
object.Get (_Parameters [PARAMETER_ ## varname ##].NormalDuration); \
|
|
object.Get (_Parameters [PARAMETER_ ## varname ##].OverrideTarget); \
|
|
object.Get (_Parameters [PARAMETER_ ## varname ##].OverrideDuration)
|
|
|
|
void BackgroundMgrClass::Import_Rare (BitStreamClass &packet)
|
|
{
|
|
WWASSERT (CombatManager::I_Am_Client());
|
|
|
|
IMPORT_PARAMETER (packet, SKY_TINT_FACTOR);
|
|
IMPORT_PARAMETER (packet, CLOUD_COVER);
|
|
IMPORT_PARAMETER (packet, CLOUD_GLOOMINESS);
|
|
IMPORT_PARAMETER (packet, LIGHTNING_INTENSITY);
|
|
IMPORT_PARAMETER (packet, LIGHTNING_START_DISTANCE);
|
|
IMPORT_PARAMETER (packet, LIGHTNING_END_DISTANCE);
|
|
IMPORT_PARAMETER (packet, LIGHTNING_HEADING);
|
|
IMPORT_PARAMETER (packet, LIGHTNING_DISTRIBUTION);
|
|
packet.Get (_CloudOverrideCount);
|
|
packet.Get (_LightningOverrideCount);
|
|
packet.Get (_SkyTintOverrideCount);
|
|
}
|
|
|
|
|
|
#undef EXPORT_PARAMETER
|
|
#undef IMPORT_PARAMETER
|
|
#undef READ_PARAMETER
|
|
#undef WRITE_PARAMETER |