Enviro-Torque
by Steven Peterson · 10/16/2005 (12:33 am) · 89 comments
---------------------------------------------------------------------------------------------------------
Authors Notes:
---------------------------------------------------------------------------------------------------------
This is my first patch. I did not have a lot of time to detour from my project to work
on it but I wanted to make a contribution. I hope you find this useful, and that
as you find improvements - you will submit them in return. It is good, but not perfect.
If you e-mail me (email in profile)
new patch files I will galdly add them to the resource. I hope to do another
maintenance release based on the comments below in a couple months,
but probably not till Q1-2006. (unless it's something HUGE ;-)
Enjoy!
(edit: June 28th, 2008 - Things got moved around on my website recently. This resource link has now been updated, to point to the correct location.)
-----------------------------------------------------------------------------------------------------------
Current Resource File:
----------------------------
envTorque-1.zip
Original Sources:
------------------------
GameManager Resource
Celestials Day/Night Cycles Resource
Dynamic Skies Forum Thread
Works With:
------------
This should patch to:
- TGE 1.3
- TGE+Lighting Pack (1.3.5)
Justification:
--------------
I'm new to Torque and found the above three resources incredibly
usefull. I also found them severely out of date. The mod was easy to
get working but the patches were a bear to merge by hand, bug-fix, and then
integrate into each other.
I figured that the three of these resources went together logically and
there was no reason for someone to go through the work I did all over again.
I was also afraid that if no one put out a maintenance release to any of them,
they would be lost to the sands of time when TGE 1.4 rolled around.
So here it is -
Included
------------
- Stand-alone "GameManager" mod - updated
- Enviro-Torque patch/mod
What Is Enviro-Torque
--------------------------------
Good Question.
Enviro-Torque has 3 components:
- Celestial day/night cycles with seasons
- Fractal Skies for dynamically generated sky patterns
- GameManager Date/Time and Weather system
I did not write any of them. I simply updated them to patch with the
current version of Torque, added in all the known bug-fixes and combined
them into one larger system. Some minor new features made it in too. :-)
You can read about the gameManager in detail in the (included)gameManager.txt file.
It's most important purpose is to bring dynamic weather into the mix.
The Celestial portion of the patch implements a sun that rises and sets
and moves with the seasons, as does the real sun. It also colors the sky,
terrain, and objects based on the time of day, and makes it get lighter/darker out.
The Fractal skies is a feature that creates a random sky pattern
using a fractal calculations. It is good for very light clouds. It can be turned
on/off with the:
FractalSky = true/false
at the top of sky.cc
Work In Progress
-----------------
One of this resources goals have yet to be accomplished: The GameManager
turns clouds on/off based on the weather. Unfortunately a "clear-blue" sky looks
fairly freakish in torque.
The FractalSkies is excellent for giving just a wisp of clouds.
With a little more tweaking, it should be perfect for texturing the sky on a
"clear" day without making it look overcast.
Then on a cloudy day we want to turn "on" or switch to our normal
.bmp storm clouds. This switch is what I'm currently stuck on.
For now you can select whether you want to use FractalSkies or
.bmp skies on a 'cloudy' day using the true/fals value listed above.
Last note, this is a living resource. If you submit fixes I will try to
update it from time to time. thx.
Current Status of Resource:
---------------------------
CRITICAL BUGS REMAINING:
- Need to finish dynamic weather integration with fractal-skies
- - Very Light clouds for "clear skies"
- - Big storm clouds for "story skies"
- - - (w/ or w/out fractal)
- If the weather is "clear" at game initialization, it mistakenly shows a
cloudy sky. It will abruptly fix itself when the sky changes to "cloudy".
NON-CRITICLE BUGS:
- Player and objects remain 'glowing' at night
- - Only a partial fix is available for this, and it's BAD.
- Terrain Shadows don't move - Apparently this has NEVER been an included feature...
OTHER-ISSUES:
- (?)
FIXED:
NOTES:
- Chances look good for a 1.4 if I release soon.
- - Any Takers?
- I don't believe this version has network support. sorry.
Authors Notes:
---------------------------------------------------------------------------------------------------------
This is my first patch. I did not have a lot of time to detour from my project to work
on it but I wanted to make a contribution. I hope you find this useful, and that
as you find improvements - you will submit them in return. It is good, but not perfect.
If you e-mail me (email in profile)
new patch files I will galdly add them to the resource. I hope to do another
maintenance release based on the comments below in a couple months,
but probably not till Q1-2006. (unless it's something HUGE ;-)
Enjoy!
(edit: June 28th, 2008 - Things got moved around on my website recently. This resource link has now been updated, to point to the correct location.)
-----------------------------------------------------------------------------------------------------------
Current Resource File:
----------------------------
envTorque-1.zip
Original Sources:
------------------------
GameManager Resource
Celestials Day/Night Cycles Resource
Dynamic Skies Forum Thread
Works With:
------------
This should patch to:
- TGE 1.3
- TGE+Lighting Pack (1.3.5)
Justification:
--------------
I'm new to Torque and found the above three resources incredibly
usefull. I also found them severely out of date. The mod was easy to
get working but the patches were a bear to merge by hand, bug-fix, and then
integrate into each other.
I figured that the three of these resources went together logically and
there was no reason for someone to go through the work I did all over again.
I was also afraid that if no one put out a maintenance release to any of them,
they would be lost to the sands of time when TGE 1.4 rolled around.
So here it is -
Included
------------
- Stand-alone "GameManager" mod - updated
- Enviro-Torque patch/mod
What Is Enviro-Torque
--------------------------------
Good Question.
Enviro-Torque has 3 components:
- Celestial day/night cycles with seasons
- Fractal Skies for dynamically generated sky patterns
- GameManager Date/Time and Weather system
I did not write any of them. I simply updated them to patch with the
current version of Torque, added in all the known bug-fixes and combined
them into one larger system. Some minor new features made it in too. :-)
You can read about the gameManager in detail in the (included)gameManager.txt file.
It's most important purpose is to bring dynamic weather into the mix.
The Celestial portion of the patch implements a sun that rises and sets
and moves with the seasons, as does the real sun. It also colors the sky,
terrain, and objects based on the time of day, and makes it get lighter/darker out.
The Fractal skies is a feature that creates a random sky pattern
using a fractal calculations. It is good for very light clouds. It can be turned
on/off with the:
FractalSky = true/false
at the top of sky.cc
Work In Progress
-----------------
One of this resources goals have yet to be accomplished: The GameManager
turns clouds on/off based on the weather. Unfortunately a "clear-blue" sky looks
fairly freakish in torque.
The FractalSkies is excellent for giving just a wisp of clouds.
With a little more tweaking, it should be perfect for texturing the sky on a
"clear" day without making it look overcast.
Then on a cloudy day we want to turn "on" or switch to our normal
.bmp storm clouds. This switch is what I'm currently stuck on.
For now you can select whether you want to use FractalSkies or
.bmp skies on a 'cloudy' day using the true/fals value listed above.
Last note, this is a living resource. If you submit fixes I will try to
update it from time to time. thx.
Current Status of Resource:
---------------------------
CRITICAL BUGS REMAINING:
- Need to finish dynamic weather integration with fractal-skies
- - Very Light clouds for "clear skies"
- - Big storm clouds for "story skies"
- - - (w/ or w/out fractal)
- If the weather is "clear" at game initialization, it mistakenly shows a
cloudy sky. It will abruptly fix itself when the sky changes to "cloudy".
NON-CRITICLE BUGS:
- Player and objects remain 'glowing' at night
- - Only a partial fix is available for this, and it's BAD.
- Terrain Shadows don't move - Apparently this has NEVER been an included feature...
OTHER-ISSUES:
- (?)
FIXED:
NOTES:
- Chances look good for a 1.4 if I release soon.
- - Any Takers?
- I don't believe this version has network support. sorry.
#42
My team is very happy to use your resource ! But we have a problem !
We have TGE 1.4 and when we use D3D the terrain remain BLACK !!!
Why ???
Can you help us ??
Thanks to all !!
Bye
01/14/2006 (2:46 am)
Hi !!My team is very happy to use your resource ! But we have a problem !
We have TGE 1.4 and when we use D3D the terrain remain BLACK !!!
Why ???
Can you help us ??
Thanks to all !!
Bye
#43
01/21/2006 (12:11 pm)
Cant wait for the 1.4 update RavenSlay3r :)
#45
01/26/2006 (5:23 pm)
Has anyone implemented so that we could have a time gui component so that players can see what time it is without having to press a button and see it in the chathud? For my use I wouldn't need it anymore than just having the text on the screen that would just say January 1, 2006, etc..
#46
ok, this is the mod'd cel I came up with it seems to work w/ multi player now,
#include "game/fx/Celestial.h"
#include "console/consoleTypes.h"
#include "sceneGraph/sceneGraph.h"
#include "math/mathUtils.h"
#include "core/bitStream.h"
// Our global object pointer so everyone can see us.
Celestials *gCelestials = NULL;
//IMPLEMENT_CONOBJECT(Celestials);
IMPLEMENT_CO_NETOBJECT_V1(Celestials);
Celestials::Celestials() : mConvertedToRads(0)
{
/* //This seems to be hosing things up. :P
if(gCelestials != NULL)
return; // The environment only needs one of these
*/
mTypeMask |= EnvironmentObjectType;
mNetFlags.set(Ghostable | ScopeAlways);
gCelestials = this; // make a pointer to this object accessable by all.
mStartTime = Sim::getCurrentTime();
// Create the static discription
mAxisTilt = 35; // 35 degree tilt
mYearLen = 360; // 360 days in a year
mDayLen = 60000; // 1 minute
mTimeOfDay = 30000; // High noon
mTimeOfYear = 120; // 1/3 of the way through the year
mLongitude = 180;
mLatitude = 35;
// Sets the sun vector directly overhead for lightmap generation
// The value of mSunVector is grabbed by the terrain lighting stuff.
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
/**
Manage the scriptable assets of this class.
*/
void Celestials::initPersistFields()
{
Parent::initPersistFields();
addGroup("SunCycle");
addField("axistilt", TypeF32, Offset(mAxisTilt, Celestials));
addField("yearlength", TypeS32, Offset(mYearLen, Celestials));
addField("daylength", TypeS32, Offset(mDayLen, Celestials));
addField("date", TypeS32, Offset(mTimeOfYear, Celestials));
addField("time", TypeS32, Offset(mTimeOfDay, Celestials));
addField("longitude", TypeF32, Offset(mLongitude, Celestials));
addField("latitude", TypeF32, Offset(mLatitude, Celestials));
endGroup("SunCycle");
}
/**
Heavens::UpdateSunPosition() does just that. It updates the position of the sun.
The fxSunLight class must be updated to grab elevation and azimuth data from
this class object.
*/
void Celestials::UpdateSunPosition()
{
// get decline and meridian angle
F32 sunDecline = 0, meridianAngle;
VectorF sunvec;
if(!mConvertedToRads)
{
// convert our stuff from degrees to radians
mLongitude = mDegToRad(mLongitude);
mLatitude = mDegToRad(mLatitude);
mAxisTilt = mDegToRad(mAxisTilt);
mConvertedToRads = 1;
}
// do time updates
U32 prevTime = mTimeOfDay;
mTimeOfDay = (Sim::getCurrentTime() - mStartTime) % mDayLen;
if(prevTime > mTimeOfDay)
{
mTimeOfYear = (++mTimeOfYear) % mYearLen; //The mYearLen is 0.
}
// calculate sun decline and meridian angle (in radians)
sunDecline = sin((2*PI) * mTimeOfYear/mYearLen) * mAxisTilt;
meridianAngle = ((F32)mTimeOfDay/(F32)mDayLen) * 2*PI - mLongitude;
// calculate the elevation and azimuth (in radians)
mElevation = Elevation(mLatitude, sunDecline, meridianAngle);
mAzimuth = Azimuth(mLatitude, sunDecline, meridianAngle);
// Get the sun vector and put it into our mSunLight object.
MathUtils::getVectorFromAngles(mSunVector, mAzimuth, mElevation);
//***************************
// Now do the lighting stuff
//***************************
GetColor(mCurrentColor);
LightManager *lm = gClientSceneGraph->getLightManager();
lm->getSunLight()->mColor = mCurrentColor; // EWR
lm->getSunLight()->mDirection = -mSunVector; // EWR
lm->setVectorLightsEnabled(false);
lm->setAmbientColor(mCurrentColor);
}
/*
void Celestials::UpdateSunPosition(fxSunLight *sunLight)
{
UpdateSunPosition();
// Update the colors for the fxSunLight object
}
*/
/**
*/
Sun* Celestials::GetSunObject()
{
return (Sun*) &(gClientSceneGraph->getLightManager()->getLight(0));
}
/**
*/
F32 Celestials::Elevation(F32 lat, F32 dec, F32 mer)
{
F32 ele;
ele = asin(sin(lat) * sin(dec) + cos(lat) * cos(dec) * cos(mer));
return ele;
}
/**
*/
F32 Celestials::Azimuth(F32 lat, F32 dec, F32 mer)
{
F32 azi;
azi = atan2(sin(mer), cos(mer) * sin(lat) - tan(dec) * cos(lat));
return azi;
}
/******************************************************************
Lighting stuff (Adapted from Joshua Ritter's Day/Night cycle code)
*******************************************************************/
/**
I'm not sure, but I think this adjusts light levels and colors the sky.
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::EnableLighting(F32 emissiveScale)
{
GLfloat matProp[] = {1.0f,1.0f,1.0f,1.0};
GLfloat zeroColor[] = {0,0,0,1.0};
GLfloat color[4];
color[0]=mClampF(mCurrentColor.red * emissiveScale, 0.0f, 1.0f);
color[1]=mClampF(mCurrentColor.green * emissiveScale, 0.0f, 1.0f);
color[2]=mClampF(mCurrentColor.blue * emissiveScale, 0.0f, 1.0f);
color[3]=1.0f;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zeroColor);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matProp);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matProp);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zeroColor);
glEnable(GL_LIGHTING);
glNormal3f(0.0,0.0,1.0);
}
/**
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::DisableLighting()
{
GLfloat zeroColor[] = {0,0,0,0};
glDisable(GL_LIGHTING);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, zeroColor);
}
/**
Grab our sun and sky colors based upon sun elevation.
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::GetColor(ColorF& color)
{
LPCOLOR_TARGET ct = NULL;
float ele = mClampF((PI/2) - mElevation, 0, PI);
float phase = -1.0f;
float div;
if (!mColorTargets.size())
{
color.set(1.0f,1.0f,1.0f);
return;
}
if (mColorTargets.size() == 1)
{
ct = &mColorTargets[0];
color.set(ct->color.red, ct->color.green, ct->color.blue);
return;
}
//simple check
if (mColorTargets[0].elevation != 0.0f)
{
AssertFatal(0, "Celestials::GetColor() - First elevation must be 0.0 radians")
color.set(1.0f, 1.0f, 1.0f);
mBandMod = 1.0f;
mCurrentBandColor = color;
return;
}
if (mColorTargets[mColorTargets.size()-1].elevation != (PI))
{
AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI")
color.set(1.0f, 1.0f, 1.0f);
mBandMod = 1.0f;
mCurrentBandColor = color;
return;
}
//we need to find the phase and interp... also loop back around
U32 count=0;
for (;count < mColorTargets.size() - 1; count++)
{
LPCOLOR_TARGET one = &mColorTargets[count];
LPCOLOR_TARGET two = &mColorTargets[count+1];
if (ele >= one->elevation && ele <= two->elevation)
{
div = two->elevation - one->elevation;
//catch bad input divide by zero
if (fabs(div)<.01)
div=.01;
phase = (ele - one->elevation) / div;
color.interpolate(one->color, two->color, phase);
mCurrentBandColor.interpolate(one->bandColor, two->bandColor, phase);
mBandMod = one->bandMod * (1.0f - phase) + two->bandMod * phase;
//we need to scale up band calc for sky... they are set for a visible
//distance of 500... hopefully linear works
Sky* s=(Sky*)Sim::findObject("Sky");
float bscale = 1.0;
if(s)
{
bscale = s->getVisibleDistance() / 500.0f;
}
mBandMod *= bscale;
return;
}
}
AssertFatal(0,"This isn't supposed to happen");
}
/**
Adds all of our target colors to our COLOR_TARGETS. ;-)
(Adapted from Joshua Ritter's Day/Night cycle code)
The elevation targets represent distances from PI/2 radians (strait up).
*/
void Celestials::InitColors()
{
ColorF c;
ColorF bc;
// e is for elevation
F32 e = PI / 13; // (semicircle in radians)/(number of color target entries);
// Day
c.set(1.0,1.0,1.0);
AddColorTarget(0, c, 1.0f, c); // High noon at equanox
c.set(.9,.9,.9);
AddColorTarget(e * 1, c, 1.0f, c);
c.set(.9,.9,.9);
AddColorTarget(e * 2, c, 1.0f, c);
c.set(.8,.75,.75);
AddColorTarget(e * 3, c, 1.0f, c);
c.set(.7,.65,.65);
AddColorTarget(e * 4, c, 1.0f, c);
//Dawn and Dusk (3 entries)
c.set(.7,.65,.65);
bc.set(.8,.6,.3);
AddColorTarget(e * 5, c, 3.0f, bc);
c.set(.65,.54,.4);
bc.set(.75,.5,.4);
AddColorTarget(e * 6, c, 2.75f, bc);
c.set(.55,.45,.25);
bc.set(.65,.3,.3);
AddColorTarget(e * 7, c, 2.5f, bc);
//NIGHT
c.set(.3,.3,.3);
bc.set(.7,.4,.2);
AddColorTarget(e * 8, c, 1.25f, bc);
c.set(.25,.25,.3);
bc.set(.8,.3,.2);
AddColorTarget(e * 9, c, 1.00f, bc);
c.set(.25,.25,.4);
AddColorTarget(e * 10, c, 1.0f, c);
c.set(.2,.2,.35);
AddColorTarget(e * 11, c, 1.0f, c);
c.set(.15,.15,.2);
AddColorTarget(PI, c, 1.0f, c); // Midnight at equanox.
}
/**
Adds a color target to our set of targets
(Adapted from Joshua Ritter's Day/Night cycle code)
@param ele [in] target sun elevation.
@param color [in] target color.
@param bandMod [in]
@param bandColor [in]
*/
void Celestials::AddColorTarget(F32 ele, ColorF& color, F32 bandMod, ColorF& bandColor)
{
COLOR_TARGET newTarget;
// float time = hour*60+minute; // We'll be working with sun elevation instead
newTarget.elevation = ele;
newTarget.color = color;
newTarget.bandMod = bandMod;
newTarget.bandColor = bandColor;
mColorTargets.push_back(newTarget);
}
bool Celestials::onAdd()
{
//Did the parent call this or did this object call this.... exit if parent did.
if(!Parent::onAdd())
return false;
if(isClientObject()) { } else
{
assignName("SunCycles");
}
addToScene();
return true;
}
void Celestials::onRemove()
{
removeFromScene();
Parent::onRemove();
}
void Celestials::inspectPostApply()
{
}
//---------------------------------------------------------------------------
void Celestials::unpackUpdate(NetConnection *, BitStream *stream)
{
stream->read(&mAxisTilt);
stream->read(&mYearLen);
stream->read(&mDayLen);
stream->read(&mTimeOfDay);
stream->read(&mTimeOfYear);
stream->read(&mLongitude);
stream->read(&mLatitude);
stream->read(&mStartTime);
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
//---------------------------------------------------------------------------
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream)
{
stream->write(mAxisTilt);
stream->write(mYearLen);
stream->write(mDayLen);
stream->write(mTimeOfDay);
stream->write(mTimeOfYear);
stream->write(mLongitude);
stream->write(mLatitude);
stream->write(mStartTime);
return 0;
}
//Basically, you want to have TimeOfDay, StartTime and all the datablock variables sent via pack and unpack. In onAdd() and onRemove(), the only important thing is doing a call to addToScene() and removeFromScene().
Vince Gee (Mar 21, 2005 at 20:49) Resource Rating: 5
Don't know if anyone is following this, but I finally got it working. The following is the fix to pack and unpack
void Celestials::unpackUpdate(NetConnection *, BitStream *stream)
{
SimTime temp;
stream->read(&mAxisTilt);
stream->read(&mYearLen);
stream->read(&mDayLen);
stream->read(&mTimeOfDay);
stream->read(&mTimeOfYear);
stream->read(&mLongitude);
stream->read(&mLatitude);
stream->read(&mStartTime);
stream->read(&temp);
//Read the servers time and advance the clock to it. This can throw an error if the clients connect while the server is booting up.
Sim::advanceToTime(temp);
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
//---------------------------------------------------------------------------
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream)
{
stream->write(mAxisTilt);
stream->write(mYearLen);
stream->write(mDayLen);
stream->write(mTimeOfDay);
stream->write(mTimeOfYear);
stream->write(mLongitude);
stream->write(mLatitude);
stream->write(mStartTime);
//Pass the current simtime of the server to the client
stream->write(Sim::getCurrentTime());
return 0;
}
01/27/2006 (6:11 pm)
I implemented the day/night routine a year ago in torque, I posted the code. Here is the repost:ok, this is the mod'd cel I came up with it seems to work w/ multi player now,
#include "game/fx/Celestial.h"
#include "console/consoleTypes.h"
#include "sceneGraph/sceneGraph.h"
#include "math/mathUtils.h"
#include "core/bitStream.h"
// Our global object pointer so everyone can see us.
Celestials *gCelestials = NULL;
//IMPLEMENT_CONOBJECT(Celestials);
IMPLEMENT_CO_NETOBJECT_V1(Celestials);
Celestials::Celestials() : mConvertedToRads(0)
{
/* //This seems to be hosing things up. :P
if(gCelestials != NULL)
return; // The environment only needs one of these
*/
mTypeMask |= EnvironmentObjectType;
mNetFlags.set(Ghostable | ScopeAlways);
gCelestials = this; // make a pointer to this object accessable by all.
mStartTime = Sim::getCurrentTime();
// Create the static discription
mAxisTilt = 35; // 35 degree tilt
mYearLen = 360; // 360 days in a year
mDayLen = 60000; // 1 minute
mTimeOfDay = 30000; // High noon
mTimeOfYear = 120; // 1/3 of the way through the year
mLongitude = 180;
mLatitude = 35;
// Sets the sun vector directly overhead for lightmap generation
// The value of mSunVector is grabbed by the terrain lighting stuff.
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
/**
Manage the scriptable assets of this class.
*/
void Celestials::initPersistFields()
{
Parent::initPersistFields();
addGroup("SunCycle");
addField("axistilt", TypeF32, Offset(mAxisTilt, Celestials));
addField("yearlength", TypeS32, Offset(mYearLen, Celestials));
addField("daylength", TypeS32, Offset(mDayLen, Celestials));
addField("date", TypeS32, Offset(mTimeOfYear, Celestials));
addField("time", TypeS32, Offset(mTimeOfDay, Celestials));
addField("longitude", TypeF32, Offset(mLongitude, Celestials));
addField("latitude", TypeF32, Offset(mLatitude, Celestials));
endGroup("SunCycle");
}
/**
Heavens::UpdateSunPosition() does just that. It updates the position of the sun.
The fxSunLight class must be updated to grab elevation and azimuth data from
this class object.
*/
void Celestials::UpdateSunPosition()
{
// get decline and meridian angle
F32 sunDecline = 0, meridianAngle;
VectorF sunvec;
if(!mConvertedToRads)
{
// convert our stuff from degrees to radians
mLongitude = mDegToRad(mLongitude);
mLatitude = mDegToRad(mLatitude);
mAxisTilt = mDegToRad(mAxisTilt);
mConvertedToRads = 1;
}
// do time updates
U32 prevTime = mTimeOfDay;
mTimeOfDay = (Sim::getCurrentTime() - mStartTime) % mDayLen;
if(prevTime > mTimeOfDay)
{
mTimeOfYear = (++mTimeOfYear) % mYearLen; //The mYearLen is 0.
}
// calculate sun decline and meridian angle (in radians)
sunDecline = sin((2*PI) * mTimeOfYear/mYearLen) * mAxisTilt;
meridianAngle = ((F32)mTimeOfDay/(F32)mDayLen) * 2*PI - mLongitude;
// calculate the elevation and azimuth (in radians)
mElevation = Elevation(mLatitude, sunDecline, meridianAngle);
mAzimuth = Azimuth(mLatitude, sunDecline, meridianAngle);
// Get the sun vector and put it into our mSunLight object.
MathUtils::getVectorFromAngles(mSunVector, mAzimuth, mElevation);
//***************************
// Now do the lighting stuff
//***************************
GetColor(mCurrentColor);
LightManager *lm = gClientSceneGraph->getLightManager();
lm->getSunLight()->mColor = mCurrentColor; // EWR
lm->getSunLight()->mDirection = -mSunVector; // EWR
lm->setVectorLightsEnabled(false);
lm->setAmbientColor(mCurrentColor);
}
/*
void Celestials::UpdateSunPosition(fxSunLight *sunLight)
{
UpdateSunPosition();
// Update the colors for the fxSunLight object
}
*/
/**
*/
Sun* Celestials::GetSunObject()
{
return (Sun*) &(gClientSceneGraph->getLightManager()->getLight(0));
}
/**
*/
F32 Celestials::Elevation(F32 lat, F32 dec, F32 mer)
{
F32 ele;
ele = asin(sin(lat) * sin(dec) + cos(lat) * cos(dec) * cos(mer));
return ele;
}
/**
*/
F32 Celestials::Azimuth(F32 lat, F32 dec, F32 mer)
{
F32 azi;
azi = atan2(sin(mer), cos(mer) * sin(lat) - tan(dec) * cos(lat));
return azi;
}
/******************************************************************
Lighting stuff (Adapted from Joshua Ritter's Day/Night cycle code)
*******************************************************************/
/**
I'm not sure, but I think this adjusts light levels and colors the sky.
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::EnableLighting(F32 emissiveScale)
{
GLfloat matProp[] = {1.0f,1.0f,1.0f,1.0};
GLfloat zeroColor[] = {0,0,0,1.0};
GLfloat color[4];
color[0]=mClampF(mCurrentColor.red * emissiveScale, 0.0f, 1.0f);
color[1]=mClampF(mCurrentColor.green * emissiveScale, 0.0f, 1.0f);
color[2]=mClampF(mCurrentColor.blue * emissiveScale, 0.0f, 1.0f);
color[3]=1.0f;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zeroColor);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matProp);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matProp);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zeroColor);
glEnable(GL_LIGHTING);
glNormal3f(0.0,0.0,1.0);
}
/**
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::DisableLighting()
{
GLfloat zeroColor[] = {0,0,0,0};
glDisable(GL_LIGHTING);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, zeroColor);
}
/**
Grab our sun and sky colors based upon sun elevation.
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::GetColor(ColorF& color)
{
LPCOLOR_TARGET ct = NULL;
float ele = mClampF((PI/2) - mElevation, 0, PI);
float phase = -1.0f;
float div;
if (!mColorTargets.size())
{
color.set(1.0f,1.0f,1.0f);
return;
}
if (mColorTargets.size() == 1)
{
ct = &mColorTargets[0];
color.set(ct->color.red, ct->color.green, ct->color.blue);
return;
}
//simple check
if (mColorTargets[0].elevation != 0.0f)
{
AssertFatal(0, "Celestials::GetColor() - First elevation must be 0.0 radians")
color.set(1.0f, 1.0f, 1.0f);
mBandMod = 1.0f;
mCurrentBandColor = color;
return;
}
if (mColorTargets[mColorTargets.size()-1].elevation != (PI))
{
AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI")
color.set(1.0f, 1.0f, 1.0f);
mBandMod = 1.0f;
mCurrentBandColor = color;
return;
}
//we need to find the phase and interp... also loop back around
U32 count=0;
for (;count < mColorTargets.size() - 1; count++)
{
LPCOLOR_TARGET one = &mColorTargets[count];
LPCOLOR_TARGET two = &mColorTargets[count+1];
if (ele >= one->elevation && ele <= two->elevation)
{
div = two->elevation - one->elevation;
//catch bad input divide by zero
if (fabs(div)<.01)
div=.01;
phase = (ele - one->elevation) / div;
color.interpolate(one->color, two->color, phase);
mCurrentBandColor.interpolate(one->bandColor, two->bandColor, phase);
mBandMod = one->bandMod * (1.0f - phase) + two->bandMod * phase;
//we need to scale up band calc for sky... they are set for a visible
//distance of 500... hopefully linear works
Sky* s=(Sky*)Sim::findObject("Sky");
float bscale = 1.0;
if(s)
{
bscale = s->getVisibleDistance() / 500.0f;
}
mBandMod *= bscale;
return;
}
}
AssertFatal(0,"This isn't supposed to happen");
}
/**
Adds all of our target colors to our COLOR_TARGETS. ;-)
(Adapted from Joshua Ritter's Day/Night cycle code)
The elevation targets represent distances from PI/2 radians (strait up).
*/
void Celestials::InitColors()
{
ColorF c;
ColorF bc;
// e is for elevation
F32 e = PI / 13; // (semicircle in radians)/(number of color target entries);
// Day
c.set(1.0,1.0,1.0);
AddColorTarget(0, c, 1.0f, c); // High noon at equanox
c.set(.9,.9,.9);
AddColorTarget(e * 1, c, 1.0f, c);
c.set(.9,.9,.9);
AddColorTarget(e * 2, c, 1.0f, c);
c.set(.8,.75,.75);
AddColorTarget(e * 3, c, 1.0f, c);
c.set(.7,.65,.65);
AddColorTarget(e * 4, c, 1.0f, c);
//Dawn and Dusk (3 entries)
c.set(.7,.65,.65);
bc.set(.8,.6,.3);
AddColorTarget(e * 5, c, 3.0f, bc);
c.set(.65,.54,.4);
bc.set(.75,.5,.4);
AddColorTarget(e * 6, c, 2.75f, bc);
c.set(.55,.45,.25);
bc.set(.65,.3,.3);
AddColorTarget(e * 7, c, 2.5f, bc);
//NIGHT
c.set(.3,.3,.3);
bc.set(.7,.4,.2);
AddColorTarget(e * 8, c, 1.25f, bc);
c.set(.25,.25,.3);
bc.set(.8,.3,.2);
AddColorTarget(e * 9, c, 1.00f, bc);
c.set(.25,.25,.4);
AddColorTarget(e * 10, c, 1.0f, c);
c.set(.2,.2,.35);
AddColorTarget(e * 11, c, 1.0f, c);
c.set(.15,.15,.2);
AddColorTarget(PI, c, 1.0f, c); // Midnight at equanox.
}
/**
Adds a color target to our set of targets
(Adapted from Joshua Ritter's Day/Night cycle code)
@param ele [in] target sun elevation.
@param color [in] target color.
@param bandMod [in]
@param bandColor [in]
*/
void Celestials::AddColorTarget(F32 ele, ColorF& color, F32 bandMod, ColorF& bandColor)
{
COLOR_TARGET newTarget;
// float time = hour*60+minute; // We'll be working with sun elevation instead
newTarget.elevation = ele;
newTarget.color = color;
newTarget.bandMod = bandMod;
newTarget.bandColor = bandColor;
mColorTargets.push_back(newTarget);
}
bool Celestials::onAdd()
{
//Did the parent call this or did this object call this.... exit if parent did.
if(!Parent::onAdd())
return false;
if(isClientObject()) { } else
{
assignName("SunCycles");
}
addToScene();
return true;
}
void Celestials::onRemove()
{
removeFromScene();
Parent::onRemove();
}
void Celestials::inspectPostApply()
{
}
//---------------------------------------------------------------------------
void Celestials::unpackUpdate(NetConnection *, BitStream *stream)
{
stream->read(&mAxisTilt);
stream->read(&mYearLen);
stream->read(&mDayLen);
stream->read(&mTimeOfDay);
stream->read(&mTimeOfYear);
stream->read(&mLongitude);
stream->read(&mLatitude);
stream->read(&mStartTime);
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
//---------------------------------------------------------------------------
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream)
{
stream->write(mAxisTilt);
stream->write(mYearLen);
stream->write(mDayLen);
stream->write(mTimeOfDay);
stream->write(mTimeOfYear);
stream->write(mLongitude);
stream->write(mLatitude);
stream->write(mStartTime);
return 0;
}
//Basically, you want to have TimeOfDay, StartTime and all the datablock variables sent via pack and unpack. In onAdd() and onRemove(), the only important thing is doing a call to addToScene() and removeFromScene().
Vince Gee (Mar 21, 2005 at 20:49) Resource Rating: 5
Don't know if anyone is following this, but I finally got it working. The following is the fix to pack and unpack
void Celestials::unpackUpdate(NetConnection *, BitStream *stream)
{
SimTime temp;
stream->read(&mAxisTilt);
stream->read(&mYearLen);
stream->read(&mDayLen);
stream->read(&mTimeOfDay);
stream->read(&mTimeOfYear);
stream->read(&mLongitude);
stream->read(&mLatitude);
stream->read(&mStartTime);
stream->read(&temp);
//Read the servers time and advance the clock to it. This can throw an error if the clients connect while the server is booting up.
Sim::advanceToTime(temp);
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
//---------------------------------------------------------------------------
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream)
{
stream->write(mAxisTilt);
stream->write(mYearLen);
stream->write(mDayLen);
stream->write(mTimeOfDay);
stream->write(mTimeOfYear);
stream->write(mLongitude);
stream->write(mLatitude);
stream->write(mStartTime);
//Pass the current simtime of the server to the client
stream->write(Sim::getCurrentTime());
return 0;
}
#47
I then added in my old code changes and I'm having trouble atm as soon as I have the stuff fixed I'll post it.
Vince
01/27/2006 (7:57 pm)
Little update, I followed this guys patching directions, had to look a around in some spots due to code changes and everything worked in 1.4I then added in my old code changes and I'm having trouble atm as soon as I have the stuff fixed I'll post it.
Vince
#48
replace the old code
bool Celestials::onAdd()
{
setYearLen();
setDayLen();
setTimeOfYear();
setTimeOfDay();
return true;
}
with
bool Celestials::onAdd()
{
if(!Parent::onAdd()) return(false);
setYearLen();
setDayLen();
setTimeOfYear();
setTimeOfDay();
return true;
}
it appears I forgot to call the parent onadd().
I just watch the sun rise and set on both terminals at the same time :)
So to sum it up.
Add to Celestial.cc
void Celestials::unpackUpdate(NetConnection *, BitStream *stream)
{
SimTime temp;
stream->read(&mAxisTilt);
stream->read(&mYearLen);
stream->read(&mDayLen);
stream->read(&mTimeOfDay);
stream->read(&mTimeOfYear);
stream->read(&mLongitude);
stream->read(&mLatitude);
stream->read(&mStartTime);
stream->read(&temp);
//Read the servers time and advance the clock to it. This can throw an error if the clients connect while the server is booting up.
Sim::advanceToTime(temp);
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
//---------------------------------------------------------------------------
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream)
{
stream->write(mAxisTilt);
stream->write(mYearLen);
stream->write(mDayLen);
stream->write(mTimeOfDay);
stream->write(mTimeOfYear);
stream->write(mLongitude);
stream->write(mLatitude);
stream->write(mStartTime);
//Pass the current simtime of the server to the client
stream->write(Sim::getCurrentTime());
return 0;
}
Add to Celestial.h
public:
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream);
void Celestials::unpackUpdate(NetConnection *, BitStream *stream);
and change in the declaration:
//IMPLEMENT_CONOBJECT(Celestials);
IMPLEMENT_CO_NETOBJECT_V1(Celestials);
If you follow the patching directions (You can't apply the patch) and then make these changes the sun etc will replicate to clients.
Actually what it does is sinc's the sim time, and sets all the parameters identical w/ the host. Thus both suns in both simulators move at the same pace etc.
Hope this helps you guys.
Vince
01/27/2006 (8:48 pm)
Ok, figured out what I did wrong...replace the old code
bool Celestials::onAdd()
{
setYearLen();
setDayLen();
setTimeOfYear();
setTimeOfDay();
return true;
}
with
bool Celestials::onAdd()
{
if(!Parent::onAdd()) return(false);
setYearLen();
setDayLen();
setTimeOfYear();
setTimeOfDay();
return true;
}
it appears I forgot to call the parent onadd().
I just watch the sun rise and set on both terminals at the same time :)
So to sum it up.
Add to Celestial.cc
void Celestials::unpackUpdate(NetConnection *, BitStream *stream)
{
SimTime temp;
stream->read(&mAxisTilt);
stream->read(&mYearLen);
stream->read(&mDayLen);
stream->read(&mTimeOfDay);
stream->read(&mTimeOfYear);
stream->read(&mLongitude);
stream->read(&mLatitude);
stream->read(&mStartTime);
stream->read(&temp);
//Read the servers time and advance the clock to it. This can throw an error if the clients connect while the server is booting up.
Sim::advanceToTime(temp);
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
//---------------------------------------------------------------------------
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream)
{
stream->write(mAxisTilt);
stream->write(mYearLen);
stream->write(mDayLen);
stream->write(mTimeOfDay);
stream->write(mTimeOfYear);
stream->write(mLongitude);
stream->write(mLatitude);
stream->write(mStartTime);
//Pass the current simtime of the server to the client
stream->write(Sim::getCurrentTime());
return 0;
}
Add to Celestial.h
public:
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream);
void Celestials::unpackUpdate(NetConnection *, BitStream *stream);
and change in the declaration:
//IMPLEMENT_CONOBJECT(Celestials);
IMPLEMENT_CO_NETOBJECT_V1(Celestials);
If you follow the patching directions (You can't apply the patch) and then make these changes the sun etc will replicate to clients.
Actually what it does is sinc's the sim time, and sets all the parameters identical w/ the host. Thus both suns in both simulators move at the same pace etc.
Hope this helps you guys.
Vince
#49
ConsoleMethod( Celestials, getTime, const char*, 2, 2, "Return the current time.")
{
char* buff = Con::getReturnBuffer(100000);
F32 AMPM = 0; //AM=1//PM=2
dStrcpy(buff,"");
dStrcat(buff,inItoa((Sim::getCurrentTime() - gCelestials->mStartTime) % gCelestials->mDayLen));
dStrcat(buff," ");
//1000 * mSecsPerHour * mHoursInDay //Is the day length
//So if we divide it by 24 thats the hour
S32 SecondsPassedSoFar = (Sim::getCurrentTime() - gCelestials->mStartTime) % gCelestials->mDayLen ;
S32 thour = SecondsPassedSoFar / ((1000 * gCelestials->mSecsPerHour * gCelestials->mHoursInDay)/24);
//hour / (1 * gCelestials->mSecsPerHour * gCelestials->mHoursInDay);
//Little note to self... at 0 hour the sun is directly overhead.
S32 hour = thour + 12; //Make it so that when the sun is directly overhead it's noon
//Military = Civilian Military = Civilian
//0001 = 12:01 AM 1200 = 12 Noon
//0100 = 1:00 AM 1300 = 1:00 PM
//0200 = 2:00 AM 1400 = 2:00 PM
//0300 = 3:00 AM 1500 = 3:00 PM
//0400 = 4:00 AM 1600 = 4:00 PM
//0500 = 5:00 AM 1700 = 5:00 PM
//0600 = 6:00 AM 1800 = 6:00 PM
//0700 = 7:00 AM 1900 = 7:00 PM
//0800 = 8:00 AM 2000 = 8:00 PM
//0900 = 9:00 AM 2100 = 9:00 PM
//1000 = 10:00 AM 2200 = 10:00 PM
//1100 = 11:00 AM 2300 = 11:00 PM
//1200 = 12 Noon 0000 = 12 Midnight
if (hour >= 24){hour = hour - 24;}
if (hour >= 13)
{
dStrcat(buff,inItoa(hour-12));
AMPM =2;
}
else
{
if (hour ==0)
{
dStrcat(buff,"12"); //Ok, the zero'th hour is actually 12am... no wonder I can never set my alarm clock right...
}
else
{
dStrcat(buff,inItoa(hour));
}
dStrcat(buff," ");
AMPM = 1;
}
dStrcat(buff,":");
S32 Minutes = SecondsPassedSoFar - (thour * ((1000 * gCelestials->mSecsPerHour * gCelestials->mHoursInDay)/24));
S32 MinutesInHour = ((1000 * gCelestials->mSecsPerHour * gCelestials->mHoursInDay)/24)/60;
dStrcat(buff,inItoa(Minutes/MinutesInHour));
if (AMPM == 1)
dStrcat(buff,"AM");
else
dStrcat(buff,"PM");
return buff;
}
01/30/2006 (7:14 am)
Dunno if this would be useful to anyone, but have you ever wanted the current time out of the Celestial class?ConsoleMethod( Celestials, getTime, const char*, 2, 2, "Return the current time.")
{
char* buff = Con::getReturnBuffer(100000);
F32 AMPM = 0; //AM=1//PM=2
dStrcpy(buff,"");
dStrcat(buff,inItoa((Sim::getCurrentTime() - gCelestials->mStartTime) % gCelestials->mDayLen));
dStrcat(buff," ");
//1000 * mSecsPerHour * mHoursInDay //Is the day length
//So if we divide it by 24 thats the hour
S32 SecondsPassedSoFar = (Sim::getCurrentTime() - gCelestials->mStartTime) % gCelestials->mDayLen ;
S32 thour = SecondsPassedSoFar / ((1000 * gCelestials->mSecsPerHour * gCelestials->mHoursInDay)/24);
//hour / (1 * gCelestials->mSecsPerHour * gCelestials->mHoursInDay);
//Little note to self... at 0 hour the sun is directly overhead.
S32 hour = thour + 12; //Make it so that when the sun is directly overhead it's noon
//Military = Civilian Military = Civilian
//0001 = 12:01 AM 1200 = 12 Noon
//0100 = 1:00 AM 1300 = 1:00 PM
//0200 = 2:00 AM 1400 = 2:00 PM
//0300 = 3:00 AM 1500 = 3:00 PM
//0400 = 4:00 AM 1600 = 4:00 PM
//0500 = 5:00 AM 1700 = 5:00 PM
//0600 = 6:00 AM 1800 = 6:00 PM
//0700 = 7:00 AM 1900 = 7:00 PM
//0800 = 8:00 AM 2000 = 8:00 PM
//0900 = 9:00 AM 2100 = 9:00 PM
//1000 = 10:00 AM 2200 = 10:00 PM
//1100 = 11:00 AM 2300 = 11:00 PM
//1200 = 12 Noon 0000 = 12 Midnight
if (hour >= 24){hour = hour - 24;}
if (hour >= 13)
{
dStrcat(buff,inItoa(hour-12));
AMPM =2;
}
else
{
if (hour ==0)
{
dStrcat(buff,"12"); //Ok, the zero'th hour is actually 12am... no wonder I can never set my alarm clock right...
}
else
{
dStrcat(buff,inItoa(hour));
}
dStrcat(buff," ");
AMPM = 1;
}
dStrcat(buff,":");
S32 Minutes = SecondsPassedSoFar - (thour * ((1000 * gCelestials->mSecsPerHour * gCelestials->mHoursInDay)/24));
S32 MinutesInHour = ((1000 * gCelestials->mSecsPerHour * gCelestials->mHoursInDay)/24)/60;
dStrcat(buff,inItoa(Minutes/MinutesInHour));
if (AMPM == 1)
dStrcat(buff,"AM");
else
dStrcat(buff,"PM");
return buff;
}
#50
Below Celestial.cc:
#include "game/fx/Celestial.h"
#include "console/consoleTypes.h"
#include "sceneGraph/sceneGraph.h"
#include "math/mathUtils.h"
#include "core/bitStream.h"
// Our global object pointer so everyone can see us.
Celestials *gCelestials = NULL;
//IMPLEMENT_CONOBJECT(Celestials);
IMPLEMENT_CO_NETOBJECT_V1(Celestials);
Celestials::Celestials() : mConvertedToRads(0)
{
/* //This seems to be hosing things up. :P
if(gCelestials != NULL)
return; // The environment only needs one of these
*/
mTypeMask |= EnvironmentObjectType;
mNetFlags.set(Ghostable | ScopeAlways);
gCelestials = this; // make a pointer to this object accessable by all.
mStartTime = Sim::getCurrentTime();
// Create the static discription
mAxisTilt = 35; // 35 degree tilt
mYearLen = 360; // 360 days in a year
mDayLen = 60000; // 1 minute
mTimeOfDay = 30000; // High noon
mTimeOfYear = 120; // 1/3 of the way through the year
mLongitude = 180;
mLatitude = 35;
// Sets the sun vector directly overhead for lightmap generation
// The value of mSunVector is grabbed by the terrain lighting stuff.
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
/**
Manage the scriptable assets of this class.
*/
void Celestials::initPersistFields()
{
Parent::initPersistFields();
addGroup("SunCycle");
addField("axistilt", TypeF32, Offset(mAxisTilt, Celestials));
addField("yearlength", TypeS32, Offset(mYearLen, Celestials));
addField("daylength", TypeS32, Offset(mDayLen, Celestials));
addField("date", TypeS32, Offset(mTimeOfYear, Celestials));
addField("time", TypeS32, Offset(mTimeOfDay, Celestials));
addField("longitude", TypeF32, Offset(mLongitude, Celestials));
addField("latitude", TypeF32, Offset(mLatitude, Celestials));
endGroup("SunCycle");
}
/**
Heavens::UpdateSunPosition() does just that. It updates the position of the sun.
The fxSunLight class must be updated to grab elevation and azimuth data from
this class object.
*/
void Celestials::UpdateSunPosition()
{
// get decline and meridian angle
F32 sunDecline = 0, meridianAngle;
VectorF sunvec;
if(!mConvertedToRads)
{
// convert our stuff from degrees to radians
mLongitude = mDegToRad(mLongitude);
mLatitude = mDegToRad(mLatitude);
mAxisTilt = mDegToRad(mAxisTilt);
mConvertedToRads = 1;
}
// do time updates
U32 prevTime = mTimeOfDay;
mTimeOfDay = (Sim::getCurrentTime() - mStartTime) % mDayLen;
if(prevTime > mTimeOfDay)
{
mTimeOfYear = (++mTimeOfYear) % mYearLen; //The mYearLen is 0.
}
// calculate sun decline and meridian angle (in radians)
sunDecline = sin((2*PI) * mTimeOfYear/mYearLen) * mAxisTilt;
meridianAngle = ((F32)mTimeOfDay/(F32)mDayLen) * 2*PI - mLongitude;
// calculate the elevation and azimuth (in radians)
mElevation = Elevation(mLatitude, sunDecline, meridianAngle);
mAzimuth = Azimuth(mLatitude, sunDecline, meridianAngle);
// Get the sun vector and put it into our mSunLight object.
MathUtils::getVectorFromAngles(mSunVector, mAzimuth, mElevation);
//***************************
// Now do the lighting stuff
//***************************
GetColor(mCurrentColor);
LightManager *lm = gClientSceneGraph->getLightManager();
lm->getSunLight()->mColor = mCurrentColor; // EWR
lm->getSunLight()->mDirection = -mSunVector; // EWR
lm->setVectorLightsEnabled(false);
lm->setAmbientColor(mCurrentColor);
}
/*
void Celestials::UpdateSunPosition(fxSunLight *sunLight)
{
UpdateSunPosition();
// Update the colors for the fxSunLight object
}
*/
/**
*/
Sun* Celestials::GetSunObject()
{
return (Sun*) &(gClientSceneGraph->getLightManager()->getLight(0));
}
/**
*/
F32 Celestials::Elevation(F32 lat, F32 dec, F32 mer)
{
F32 ele;
ele = asin(sin(lat) * sin(dec) + cos(lat) * cos(dec) * cos(mer));
return ele;
}
/**
*/
F32 Celestials::Azimuth(F32 lat, F32 dec, F32 mer)
{
F32 azi;
azi = atan2(sin(mer), cos(mer) * sin(lat) - tan(dec) * cos(lat));
return azi;
}
/******************************************************************
Lighting stuff (Adapted from Joshua Ritter's Day/Night cycle code)
*******************************************************************/
/**
I'm not sure, but I think this adjusts light levels and colors the sky.
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::EnableLighting(F32 emissiveScale)
{
GLfloat matProp[] = {1.0f,1.0f,1.0f,1.0};
GLfloat zeroColor[] = {0,0,0,1.0};
GLfloat color[4];
color[0]=mClampF(mCurrentColor.red * emissiveScale, 0.0f, 1.0f);
color[1]=mClampF(mCurrentColor.green * emissiveScale, 0.0f, 1.0f);
color[2]=mClampF(mCurrentColor.blue * emissiveScale, 0.0f, 1.0f);
color[3]=1.0f;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zeroColor);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matProp);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matProp);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zeroColor);
glEnable(GL_LIGHTING);
glNormal3f(0.0,0.0,1.0);
}
/**
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::DisableLighting()
{
GLfloat zeroColor[] = {0,0,0,0};
glDisable(GL_LIGHTING);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, zeroColor);
}
/**
Grab our sun and sky colors based upon sun elevation.
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::GetColor(ColorF& color)
{
LPCOLOR_TARGET ct = NULL;
float ele = mClampF((PI/2) - mElevation, 0, PI);
float phase = -1.0f;
float div;
if (!mColorTargets.size())
{
color.set(1.0f,1.0f,1.0f);
return;
}
if (mColorTargets.size() == 1)
{
ct = &mColorTargets[0];
color.set(ct->color.red, ct->color.green, ct->color.blue);
return;
}
//simple check
if (mColorTargets[0].elevation != 0.0f)
{
AssertFatal(0, "Celestials::GetColor() - First elevation must be 0.0 radians")
color.set(1.0f, 1.0f, 1.0f);
mBandMod = 1.0f;
mCurrentBandColor = color;
return;
}
if (mColorTargets[mColorTargets.size()-1].elevation != (PI))
{
AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI")
color.set(1.0f, 1.0f, 1.0f);
mBandMod = 1.0f;
mCurrentBandColor = color;
return;
}
//we need to find the phase and interp... also loop back around
U32 count=0;
for (;count < mColorTargets.size() - 1; count++)
{
LPCOLOR_TARGET one = &mColorTargets[count];
LPCOLOR_TARGET two = &mColorTargets[count+1];
if (ele >= one->elevation && ele <= two->elevation)
{
div = two->elevation - one->elevation;
//catch bad input divide by zero
if (fabs(div)<.01)
div=.01;
phase = (ele - one->elevation) / div;
color.interpolate(one->color, two->color, phase);
mCurrentBandColor.interpolate(one->bandColor, two->bandColor, phase);
mBandMod = one->bandMod * (1.0f - phase) + two->bandMod * phase;
//we need to scale up band calc for sky... they are set for a visible
//distance of 500... hopefully linear works
Sky* s=(Sky*)Sim::findObject("Sky");
float bscale = 1.0;
if(s)
{
bscale = s->getVisibleDistance() / 500.0f;
}
mBandMod *= bscale;
return;
}
}
AssertFatal(0,"This isn't supposed to happen");
}
/**
Adds all of our target colors to our COLOR_TARGETS. ;-)
(Adapted from Joshua Ritter's Day/Night cycle code)
The elevation targets represent distances from PI/2 radians (strait up).
*/
void Celestials::InitColors()
{
ColorF c;
ColorF bc;
// e is for elevation
F32 e = PI / 13; // (semicircle in radians)/(number of color target entries);
// Day
c.set(1.0,1.0,1.0);
AddColorTarget(0, c, 1.0f, c); // High noon at equanox
c.set(.9,.9,.9);
AddColorTarget(e * 1, c, 1.0f, c);
c.set(.9,.9,.9);
AddColorTarget(e * 2, c, 1.0f, c);
c.set(.8,.75,.75);
AddColorTarget(e * 3, c, 1.0f, c);
c.set(.7,.65,.65);
AddColorTarget(e * 4, c, 1.0f, c);
//Dawn and Dusk (3 entries)
c.set(.7,.65,.65);
bc.set(.8,.6,.3);
AddColorTarget(e * 5, c, 3.0f, bc);
c.set(.65,.54,.4);
bc.set(.75,.5,.4);
AddColorTarget(e * 6, c, 2.75f, bc);
c.set(.55,.45,.25);
bc.set(.65,.3,.3);
AddColorTarget(e * 7, c, 2.5f, bc);
//NIGHT
c.set(.3,.3,.3);
bc.set(.7,.4,.2);
AddColorTarget(e * 8, c, 1.25f, bc);
c.set(.25,.25,.3);
bc.set(.8,.3,.2);
AddColorTarget(e * 9, c, 1.00f, bc);
c.set(.25,.25,.4);
AddColorTarget(e * 10, c, 1.0f, c);
c.set(.2,.2,.35);
AddColorTarget(e * 11, c, 1.0f, c);
c.set(.15,.15,.2);
AddColorTarget(PI, c, 1.0f, c); // Midnight at equanox.
}
/**
Adds a color target to our set of targets
(Adapted from Joshua Ritter's Day/Night cycle code)
@param ele [in] target sun elevation.
@param color [in] target color.
@param bandMod [in]
@param bandColor [in]
*/
void Celestials::AddColorTarget(F32 ele, ColorF& color, F32 bandMod, ColorF& bandColor)
{
COLOR_TARGET newTarget;
// float time = hour*60+minute; // We'll be working with sun elevation instead
newTarget.elevation = ele;
newTarget.color = color;
newTarget.bandMod = bandMod;
newTarget.bandColor = bandColor;
mColorTargets.push_back(newTarget);
}
bool Celestials::onAdd()
{
//Did the parent call this or did this object call this.... exit if parent did.
if(!Parent::onAdd())
return false;
if(isClientObject()) { } else
{
assignName("SunCycles");
}
addToScene();
return true;
}
void Celestials::onRemove()
{
removeFromScene();
Parent::onRemove();
}
void Celestials::inspectPostApply()
{
Parent::inspectPostApply();
}
//---------------------------------------------------------------------------
void Celestials::unpackUpdate(NetConnection *, BitStream *stream)
{
stream->read(&mAxisTilt);
stream->read(&mYearLen);
stream->read(&mDayLen);
stream->read(&mTimeOfDay);
stream->read(&mTimeOfYear);
stream->read(&mLongitude);
stream->read(&mLatitude);
stream->read(&mStartTime);
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
//---------------------------------------------------------------------------
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream)
{
stream->write(mAxisTilt);
stream->write(mYearLen);
stream->write(mDayLen);
stream->write(mTimeOfDay);
stream->write(mTimeOfYear);
stream->write(mLongitude);
stream->write(mLatitude);
stream->write(mStartTime);
return 0;
}
Below Celestial.h:
#ifndef _DAYCYCLE_H_
#define _DAYCYCLE_H_
#ifndef _NETOBJECT_H_
#include "sim/netObject.h"
#endif
#ifndef _LIGHTMANAGER_H_
#include "sceneGraph/lightManager.h"
#endif
#ifndef _SUN_H_
#include "terrain/sun.h"
#endif
#ifndef _SKY_H_
#include "terrain/sky.h"
#endif
// defines for working with radians and degrees
#ifndef PI
#define PI (3.141592653589793238462643f)
#endif
#define RADIAN (180/PI)
#define TORADIANS(x) (((x)/360) * (2*PI))
#define TODEGREES(x) (((x)/(2*PI)) * 360)
typedef struct _color_target{
F32 elevation; // maximum target elevation
ColorF color; //normalized 0 = 1.0 ...
F32 bandMod; //6 is max
ColorF bandColor;
} COLOR_TARGET, *LPCOLOR_TARGET;
typedef Vector COLOR_TARGETS;
/**
The Celestials class manages the heavens: major lights, minor lights, scene
lighting effects, celestial object positioning, seasons, and star fields.
*/
class Celestials : public SceneObject
{
public:
Celestials();
typedef SceneObject Parent;
// Sun position stuff
void UpdateSunPosition(void);
// void UpdateSunPosition(fxSunLight *sunLight);
F32 getAzimuthRads() {return mAzimuth;}
F32 getElevationRads() {return mElevation;}
F32 getAzimuthDegrees() {return TODEGREES(mAzimuth);}
F32 getElevationDegrees() {return TODEGREES(mElevation);}
// Scene lighting (Adapted from Joshua Ritter's Day/Night cycle code)
// I changed references to pointers on the basis of principle. ;-)
void EnableLighting(F32 emissiveScale = 1.0);
void DisableLighting();
void GetColor(ColorF& color);
void InitColors();
void AddColorTarget(F32 ele, ColorF& color, F32 bandMod, ColorF& bandColor);
F32 GetIntensity()
{ return (mCurrentColor.blue + mCurrentColor.green + mCurrentColor.red) / 3; }
// Manages scriptable initializations
static void initPersistFields();
protected:
bool onAdd();
private:
// Get a pointer to the sun's light object
Sun* GetSunObject();
// return Azimuth in radians
F32 Azimuth(F32 viewerLatitude, F32 objectDecline, F32 medianAngle);
F32 Elevation(F32 viewerLatitude, F32 objectDecline, F32 medianAngle);
// return number between 0 and 1 representing color variance
F32 getColorVariance();
public:
F32 mAzimuth; // Angle from true north of celestial object in radians
F32 mElevation; // Angle from horizon of celestial object in radians
VectorF mSunVector; // the sun vector
//Accessor Functions for Date and Time variables (SP)
void setSecsPerHour(F32 SecsPerHour); // In Real-Time Seconds
void setHoursInDay(U32 HoursInDay); // In Game-Hours
void setDaysInWeek(U32 DaysInWeek); // In Game-Days
void setDaysInMonth(U32 DaysInMonth); // In Game-Days
void setMonthsInYear(U32 MonthsInYear); // In Game-Months
void setInitialHour(U32 InitialHour); // In Game-Hours
void setInitialDay(U32 InitialDay); // In Game-Days
void setInitialMonth(U32 InitialMonth); // In Game-Months
void setInitialYear(U32 InitialYear); // In Game-Year
// Conversion Functions
void setDayLen(); // Conversion based on existing variablese
void setYearLen(); // Conversion based on existing variablese
void setTimeOfDay(); // Conversion based on existing variablese
void setTimeOfYear(); // Conversion based on existing variablese
void onRemove(); // Added public member functions BM
void inspectPostApply();// Added public member functions BM
//--
F32 getSecsPerHour(); // Out Real-Time Seconds
U32 getHoursInDay(); // Out Game-Hours
U32 getDaysInWeek(); // Out Game-Days
U32 getDaysInMonth(); // Out Game-Days
U32 getMonthsInYear(); // Out Game-Months
U32 getInitialHour(); // Out Game-Hours
U32 getInitialDay(); // Out Game-Days
U32 getInitialMonth(); // Out Game-Months
U32 getInitialYear(); // Out Game-Year
// No 'Get' for the Conversion Functions
// If you want it - write it :-P
private:
// Vars for GameManager Integration (SP)
// *** REAL TIME CONVERSTION FACTOR ***
F32 mSecsPerHour; // Real-Time Seconds per Game-Hour
U32 mHoursInDay; // Number of Game-Hours per Game-day
U32 mDaysInWeek; // Number of Game-Days per Game-Week
U32 mDaysInMonth; // Number of Game-Days per Game-Month
U32 mMonthsInYear; // Number of Game-Months per Game-Year
U32 mInitialHour; // Hour of Game-Day at initilization
U32 mInitialDay; // Day of Game-Month at initilization
U32 mInitialMonth; // Month of Game-Year at initilization
U32 mInitialYear; // arbatrairy Game-Year at initilization
// Date tracking stuff
SimTime mStartTime; // The time this object was created.
SimTime mDayLen; // length of day in real world milliseconds
SimTime mTimeOfDay; // in game milliseconds standard time (one_game_minute = (mDayLen / 24) / 60)
U32 mYearLen; // Length of year in virtual days
U32 mTimeOfYear; // Number of days since the last winter equinox
// Global positioning stuff
F32 mLongitude; // longitudinal position of this mission
F32 mLatitude; // latitudinal position of this missiion
F32 mAxisTilt; // angle between global equator and tropic
// color management
COLOR_TARGETS mColorTargets;
public:
ColorF mCurrentColor;
F32 mBandMod;
ColorF mCurrentBandColor;
private:
// PersistFields preparation
bool mConvertedToRads; // initPersist takes arguments in degtrees. Have we converted?
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream);
void Celestials::unpackUpdate(NetConnection *, BitStream *stream);
public:
DECLARE_CONOBJECT(Celestials);
};
extern Celestials *gCelestials;
#endif
--------------------Celestial.cc-------------------------------------
Suggested method:
void Celestials::inspectPostApply()
{
}
Changed To:
void Celestials::inspectPostApply()
{
Parent::inspectPostApply();
}
--------------------Celestial.h-------------------------------------
Added (below Public: // Conversion Functions ):
void onRemove();
void inspectPostApply();
I am not sure if this helps anyone, but it compiles and seems to work. :) Thanks for the Resource. I did test this and it works with multiplayer under build 1.4 .
02/06/2006 (1:12 am)
I followed all the patches through this post, and I noticed some final things missing when I compiled the script with 1.4, but here is the celestial.cc and celestial.h that I have and they seem work:Below Celestial.cc:
#include "game/fx/Celestial.h"
#include "console/consoleTypes.h"
#include "sceneGraph/sceneGraph.h"
#include "math/mathUtils.h"
#include "core/bitStream.h"
// Our global object pointer so everyone can see us.
Celestials *gCelestials = NULL;
//IMPLEMENT_CONOBJECT(Celestials);
IMPLEMENT_CO_NETOBJECT_V1(Celestials);
Celestials::Celestials() : mConvertedToRads(0)
{
/* //This seems to be hosing things up. :P
if(gCelestials != NULL)
return; // The environment only needs one of these
*/
mTypeMask |= EnvironmentObjectType;
mNetFlags.set(Ghostable | ScopeAlways);
gCelestials = this; // make a pointer to this object accessable by all.
mStartTime = Sim::getCurrentTime();
// Create the static discription
mAxisTilt = 35; // 35 degree tilt
mYearLen = 360; // 360 days in a year
mDayLen = 60000; // 1 minute
mTimeOfDay = 30000; // High noon
mTimeOfYear = 120; // 1/3 of the way through the year
mLongitude = 180;
mLatitude = 35;
// Sets the sun vector directly overhead for lightmap generation
// The value of mSunVector is grabbed by the terrain lighting stuff.
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
/**
Manage the scriptable assets of this class.
*/
void Celestials::initPersistFields()
{
Parent::initPersistFields();
addGroup("SunCycle");
addField("axistilt", TypeF32, Offset(mAxisTilt, Celestials));
addField("yearlength", TypeS32, Offset(mYearLen, Celestials));
addField("daylength", TypeS32, Offset(mDayLen, Celestials));
addField("date", TypeS32, Offset(mTimeOfYear, Celestials));
addField("time", TypeS32, Offset(mTimeOfDay, Celestials));
addField("longitude", TypeF32, Offset(mLongitude, Celestials));
addField("latitude", TypeF32, Offset(mLatitude, Celestials));
endGroup("SunCycle");
}
/**
Heavens::UpdateSunPosition() does just that. It updates the position of the sun.
The fxSunLight class must be updated to grab elevation and azimuth data from
this class object.
*/
void Celestials::UpdateSunPosition()
{
// get decline and meridian angle
F32 sunDecline = 0, meridianAngle;
VectorF sunvec;
if(!mConvertedToRads)
{
// convert our stuff from degrees to radians
mLongitude = mDegToRad(mLongitude);
mLatitude = mDegToRad(mLatitude);
mAxisTilt = mDegToRad(mAxisTilt);
mConvertedToRads = 1;
}
// do time updates
U32 prevTime = mTimeOfDay;
mTimeOfDay = (Sim::getCurrentTime() - mStartTime) % mDayLen;
if(prevTime > mTimeOfDay)
{
mTimeOfYear = (++mTimeOfYear) % mYearLen; //The mYearLen is 0.
}
// calculate sun decline and meridian angle (in radians)
sunDecline = sin((2*PI) * mTimeOfYear/mYearLen) * mAxisTilt;
meridianAngle = ((F32)mTimeOfDay/(F32)mDayLen) * 2*PI - mLongitude;
// calculate the elevation and azimuth (in radians)
mElevation = Elevation(mLatitude, sunDecline, meridianAngle);
mAzimuth = Azimuth(mLatitude, sunDecline, meridianAngle);
// Get the sun vector and put it into our mSunLight object.
MathUtils::getVectorFromAngles(mSunVector, mAzimuth, mElevation);
//***************************
// Now do the lighting stuff
//***************************
GetColor(mCurrentColor);
LightManager *lm = gClientSceneGraph->getLightManager();
lm->getSunLight()->mColor = mCurrentColor; // EWR
lm->getSunLight()->mDirection = -mSunVector; // EWR
lm->setVectorLightsEnabled(false);
lm->setAmbientColor(mCurrentColor);
}
/*
void Celestials::UpdateSunPosition(fxSunLight *sunLight)
{
UpdateSunPosition();
// Update the colors for the fxSunLight object
}
*/
/**
*/
Sun* Celestials::GetSunObject()
{
return (Sun*) &(gClientSceneGraph->getLightManager()->getLight(0));
}
/**
*/
F32 Celestials::Elevation(F32 lat, F32 dec, F32 mer)
{
F32 ele;
ele = asin(sin(lat) * sin(dec) + cos(lat) * cos(dec) * cos(mer));
return ele;
}
/**
*/
F32 Celestials::Azimuth(F32 lat, F32 dec, F32 mer)
{
F32 azi;
azi = atan2(sin(mer), cos(mer) * sin(lat) - tan(dec) * cos(lat));
return azi;
}
/******************************************************************
Lighting stuff (Adapted from Joshua Ritter's Day/Night cycle code)
*******************************************************************/
/**
I'm not sure, but I think this adjusts light levels and colors the sky.
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::EnableLighting(F32 emissiveScale)
{
GLfloat matProp[] = {1.0f,1.0f,1.0f,1.0};
GLfloat zeroColor[] = {0,0,0,1.0};
GLfloat color[4];
color[0]=mClampF(mCurrentColor.red * emissiveScale, 0.0f, 1.0f);
color[1]=mClampF(mCurrentColor.green * emissiveScale, 0.0f, 1.0f);
color[2]=mClampF(mCurrentColor.blue * emissiveScale, 0.0f, 1.0f);
color[3]=1.0f;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zeroColor);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matProp);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matProp);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zeroColor);
glEnable(GL_LIGHTING);
glNormal3f(0.0,0.0,1.0);
}
/**
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::DisableLighting()
{
GLfloat zeroColor[] = {0,0,0,0};
glDisable(GL_LIGHTING);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, zeroColor);
}
/**
Grab our sun and sky colors based upon sun elevation.
(Adapted from Joshua Ritter's Day/Night cycle code)
*/
void Celestials::GetColor(ColorF& color)
{
LPCOLOR_TARGET ct = NULL;
float ele = mClampF((PI/2) - mElevation, 0, PI);
float phase = -1.0f;
float div;
if (!mColorTargets.size())
{
color.set(1.0f,1.0f,1.0f);
return;
}
if (mColorTargets.size() == 1)
{
ct = &mColorTargets[0];
color.set(ct->color.red, ct->color.green, ct->color.blue);
return;
}
//simple check
if (mColorTargets[0].elevation != 0.0f)
{
AssertFatal(0, "Celestials::GetColor() - First elevation must be 0.0 radians")
color.set(1.0f, 1.0f, 1.0f);
mBandMod = 1.0f;
mCurrentBandColor = color;
return;
}
if (mColorTargets[mColorTargets.size()-1].elevation != (PI))
{
AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI")
color.set(1.0f, 1.0f, 1.0f);
mBandMod = 1.0f;
mCurrentBandColor = color;
return;
}
//we need to find the phase and interp... also loop back around
U32 count=0;
for (;count < mColorTargets.size() - 1; count++)
{
LPCOLOR_TARGET one = &mColorTargets[count];
LPCOLOR_TARGET two = &mColorTargets[count+1];
if (ele >= one->elevation && ele <= two->elevation)
{
div = two->elevation - one->elevation;
//catch bad input divide by zero
if (fabs(div)<.01)
div=.01;
phase = (ele - one->elevation) / div;
color.interpolate(one->color, two->color, phase);
mCurrentBandColor.interpolate(one->bandColor, two->bandColor, phase);
mBandMod = one->bandMod * (1.0f - phase) + two->bandMod * phase;
//we need to scale up band calc for sky... they are set for a visible
//distance of 500... hopefully linear works
Sky* s=(Sky*)Sim::findObject("Sky");
float bscale = 1.0;
if(s)
{
bscale = s->getVisibleDistance() / 500.0f;
}
mBandMod *= bscale;
return;
}
}
AssertFatal(0,"This isn't supposed to happen");
}
/**
Adds all of our target colors to our COLOR_TARGETS. ;-)
(Adapted from Joshua Ritter's Day/Night cycle code)
The elevation targets represent distances from PI/2 radians (strait up).
*/
void Celestials::InitColors()
{
ColorF c;
ColorF bc;
// e is for elevation
F32 e = PI / 13; // (semicircle in radians)/(number of color target entries);
// Day
c.set(1.0,1.0,1.0);
AddColorTarget(0, c, 1.0f, c); // High noon at equanox
c.set(.9,.9,.9);
AddColorTarget(e * 1, c, 1.0f, c);
c.set(.9,.9,.9);
AddColorTarget(e * 2, c, 1.0f, c);
c.set(.8,.75,.75);
AddColorTarget(e * 3, c, 1.0f, c);
c.set(.7,.65,.65);
AddColorTarget(e * 4, c, 1.0f, c);
//Dawn and Dusk (3 entries)
c.set(.7,.65,.65);
bc.set(.8,.6,.3);
AddColorTarget(e * 5, c, 3.0f, bc);
c.set(.65,.54,.4);
bc.set(.75,.5,.4);
AddColorTarget(e * 6, c, 2.75f, bc);
c.set(.55,.45,.25);
bc.set(.65,.3,.3);
AddColorTarget(e * 7, c, 2.5f, bc);
//NIGHT
c.set(.3,.3,.3);
bc.set(.7,.4,.2);
AddColorTarget(e * 8, c, 1.25f, bc);
c.set(.25,.25,.3);
bc.set(.8,.3,.2);
AddColorTarget(e * 9, c, 1.00f, bc);
c.set(.25,.25,.4);
AddColorTarget(e * 10, c, 1.0f, c);
c.set(.2,.2,.35);
AddColorTarget(e * 11, c, 1.0f, c);
c.set(.15,.15,.2);
AddColorTarget(PI, c, 1.0f, c); // Midnight at equanox.
}
/**
Adds a color target to our set of targets
(Adapted from Joshua Ritter's Day/Night cycle code)
@param ele [in] target sun elevation.
@param color [in] target color.
@param bandMod [in]
@param bandColor [in]
*/
void Celestials::AddColorTarget(F32 ele, ColorF& color, F32 bandMod, ColorF& bandColor)
{
COLOR_TARGET newTarget;
// float time = hour*60+minute; // We'll be working with sun elevation instead
newTarget.elevation = ele;
newTarget.color = color;
newTarget.bandMod = bandMod;
newTarget.bandColor = bandColor;
mColorTargets.push_back(newTarget);
}
bool Celestials::onAdd()
{
//Did the parent call this or did this object call this.... exit if parent did.
if(!Parent::onAdd())
return false;
if(isClientObject()) { } else
{
assignName("SunCycles");
}
addToScene();
return true;
}
void Celestials::onRemove()
{
removeFromScene();
Parent::onRemove();
}
void Celestials::inspectPostApply()
{
Parent::inspectPostApply();
}
//---------------------------------------------------------------------------
void Celestials::unpackUpdate(NetConnection *, BitStream *stream)
{
stream->read(&mAxisTilt);
stream->read(&mYearLen);
stream->read(&mDayLen);
stream->read(&mTimeOfDay);
stream->read(&mTimeOfYear);
stream->read(&mLongitude);
stream->read(&mLatitude);
stream->read(&mStartTime);
F32 ele, azi;
ele = azi = TORADIANS(90);
MathUtils::getVectorFromAngles(mSunVector, azi, ele);
InitColors();
}
//---------------------------------------------------------------------------
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream)
{
stream->write(mAxisTilt);
stream->write(mYearLen);
stream->write(mDayLen);
stream->write(mTimeOfDay);
stream->write(mTimeOfYear);
stream->write(mLongitude);
stream->write(mLatitude);
stream->write(mStartTime);
return 0;
}
Below Celestial.h:
#ifndef _DAYCYCLE_H_
#define _DAYCYCLE_H_
#ifndef _NETOBJECT_H_
#include "sim/netObject.h"
#endif
#ifndef _LIGHTMANAGER_H_
#include "sceneGraph/lightManager.h"
#endif
#ifndef _SUN_H_
#include "terrain/sun.h"
#endif
#ifndef _SKY_H_
#include "terrain/sky.h"
#endif
// defines for working with radians and degrees
#ifndef PI
#define PI (3.141592653589793238462643f)
#endif
#define RADIAN (180/PI)
#define TORADIANS(x) (((x)/360) * (2*PI))
#define TODEGREES(x) (((x)/(2*PI)) * 360)
typedef struct _color_target{
F32 elevation; // maximum target elevation
ColorF color; //normalized 0 = 1.0 ...
F32 bandMod; //6 is max
ColorF bandColor;
} COLOR_TARGET, *LPCOLOR_TARGET;
typedef Vector
/**
The Celestials class manages the heavens: major lights, minor lights, scene
lighting effects, celestial object positioning, seasons, and star fields.
*/
class Celestials : public SceneObject
{
public:
Celestials();
typedef SceneObject Parent;
// Sun position stuff
void UpdateSunPosition(void);
// void UpdateSunPosition(fxSunLight *sunLight);
F32 getAzimuthRads() {return mAzimuth;}
F32 getElevationRads() {return mElevation;}
F32 getAzimuthDegrees() {return TODEGREES(mAzimuth);}
F32 getElevationDegrees() {return TODEGREES(mElevation);}
// Scene lighting (Adapted from Joshua Ritter's Day/Night cycle code)
// I changed references to pointers on the basis of principle. ;-)
void EnableLighting(F32 emissiveScale = 1.0);
void DisableLighting();
void GetColor(ColorF& color);
void InitColors();
void AddColorTarget(F32 ele, ColorF& color, F32 bandMod, ColorF& bandColor);
F32 GetIntensity()
{ return (mCurrentColor.blue + mCurrentColor.green + mCurrentColor.red) / 3; }
// Manages scriptable initializations
static void initPersistFields();
protected:
bool onAdd();
private:
// Get a pointer to the sun's light object
Sun* GetSunObject();
// return Azimuth in radians
F32 Azimuth(F32 viewerLatitude, F32 objectDecline, F32 medianAngle);
F32 Elevation(F32 viewerLatitude, F32 objectDecline, F32 medianAngle);
// return number between 0 and 1 representing color variance
F32 getColorVariance();
public:
F32 mAzimuth; // Angle from true north of celestial object in radians
F32 mElevation; // Angle from horizon of celestial object in radians
VectorF mSunVector; // the sun vector
//Accessor Functions for Date and Time variables (SP)
void setSecsPerHour(F32 SecsPerHour); // In Real-Time Seconds
void setHoursInDay(U32 HoursInDay); // In Game-Hours
void setDaysInWeek(U32 DaysInWeek); // In Game-Days
void setDaysInMonth(U32 DaysInMonth); // In Game-Days
void setMonthsInYear(U32 MonthsInYear); // In Game-Months
void setInitialHour(U32 InitialHour); // In Game-Hours
void setInitialDay(U32 InitialDay); // In Game-Days
void setInitialMonth(U32 InitialMonth); // In Game-Months
void setInitialYear(U32 InitialYear); // In Game-Year
// Conversion Functions
void setDayLen(); // Conversion based on existing variablese
void setYearLen(); // Conversion based on existing variablese
void setTimeOfDay(); // Conversion based on existing variablese
void setTimeOfYear(); // Conversion based on existing variablese
void onRemove(); // Added public member functions BM
void inspectPostApply();// Added public member functions BM
//--
F32 getSecsPerHour(); // Out Real-Time Seconds
U32 getHoursInDay(); // Out Game-Hours
U32 getDaysInWeek(); // Out Game-Days
U32 getDaysInMonth(); // Out Game-Days
U32 getMonthsInYear(); // Out Game-Months
U32 getInitialHour(); // Out Game-Hours
U32 getInitialDay(); // Out Game-Days
U32 getInitialMonth(); // Out Game-Months
U32 getInitialYear(); // Out Game-Year
// No 'Get' for the Conversion Functions
// If you want it - write it :-P
private:
// Vars for GameManager Integration (SP)
// *** REAL TIME CONVERSTION FACTOR ***
F32 mSecsPerHour; // Real-Time Seconds per Game-Hour
U32 mHoursInDay; // Number of Game-Hours per Game-day
U32 mDaysInWeek; // Number of Game-Days per Game-Week
U32 mDaysInMonth; // Number of Game-Days per Game-Month
U32 mMonthsInYear; // Number of Game-Months per Game-Year
U32 mInitialHour; // Hour of Game-Day at initilization
U32 mInitialDay; // Day of Game-Month at initilization
U32 mInitialMonth; // Month of Game-Year at initilization
U32 mInitialYear; // arbatrairy Game-Year at initilization
// Date tracking stuff
SimTime mStartTime; // The time this object was created.
SimTime mDayLen; // length of day in real world milliseconds
SimTime mTimeOfDay; // in game milliseconds standard time (one_game_minute = (mDayLen / 24) / 60)
U32 mYearLen; // Length of year in virtual days
U32 mTimeOfYear; // Number of days since the last winter equinox
// Global positioning stuff
F32 mLongitude; // longitudinal position of this mission
F32 mLatitude; // latitudinal position of this missiion
F32 mAxisTilt; // angle between global equator and tropic
// color management
COLOR_TARGETS mColorTargets;
public:
ColorF mCurrentColor;
F32 mBandMod;
ColorF mCurrentBandColor;
private:
// PersistFields preparation
bool mConvertedToRads; // initPersist takes arguments in degtrees. Have we converted?
U32 Celestials::packUpdate(NetConnection *, U32 mask, BitStream *stream);
void Celestials::unpackUpdate(NetConnection *, BitStream *stream);
public:
DECLARE_CONOBJECT(Celestials);
};
extern Celestials *gCelestials;
#endif
--------------------Celestial.cc-------------------------------------
Suggested method:
void Celestials::inspectPostApply()
{
}
Changed To:
void Celestials::inspectPostApply()
{
Parent::inspectPostApply();
}
--------------------Celestial.h-------------------------------------
Added (below Public: // Conversion Functions ):
void onRemove();
void inspectPostApply();
I am not sure if this helps anyone, but it compiles and seems to work. :) Thanks for the Resource. I did test this and it works with multiplayer under build 1.4 .
#51
02/26/2006 (2:00 pm)
Anyone having sucess in incorperating this into Torque 1.4? I changed my celestial.cc and celestial.h to match what Barry posted. But I am still getting errors with the sky.cc file when I try and compile.
#52
Anyways this resource has been made fully network aware and is going into the MMORPG Enhancement Kit.
03/01/2006 (3:33 am)
I'm having no errors from compilation, but I did have to change the size of my bitstream to get it function without an out of range write error. Also when rain stops, the client crashes saying "Wrong Object Deleted!" or something like that in a debug build. Error does not seem to occur in a release build...Anyways this resource has been made fully network aware and is going into the MMORPG Enhancement Kit.
#53
Hey all - I didn't realize this thread was still active. I'm slowly working on an entirely NEW version of this, but i'm glad the old one has helped out some people. It's pretty cool when it works!
@Dreamer: where can I read more on this "MMORPG enhancment kit"?
03/07/2006 (9:54 pm)
Quote:and is going into the MMORPG Enhancement Kit.
Hey all - I didn't realize this thread was still active. I'm slowly working on an entirely NEW version of this, but i'm glad the old one has helped out some people. It's pretty cool when it works!
@Dreamer: where can I read more on this "MMORPG enhancment kit"?
#54
The reason I ask is that this looks awesome, but if a new one is on the horizon I will hold off on implementing....
Either way, thanks for a great resource!
03/08/2006 (8:58 am)
RavenSlay3r, do you have an expected time frame on the new version?The reason I ask is that this looks awesome, but if a new one is on the horizon I will hold off on implementing....
Either way, thanks for a great resource!
#55
03/13/2006 (3:35 am)
Have an update for TGE 1.4 + TLK 1.4?
#56
I'm very hesitant to say anything so as not to disapoint. Right now I'd tentativly say late april or early may. As of now, it will initially support TGE-1.4 and TLK-1.4.
Hope that helps a little!
03/13/2006 (10:37 am)
Juan,I'm very hesitant to say anything so as not to disapoint. Right now I'd tentativly say late april or early may. As of now, it will initially support TGE-1.4 and TLK-1.4.
Hope that helps a little!
#57
03/26/2006 (11:38 pm)
Definitely keeping my eye on this, it would be extremely useful.
#58
Any update on the release of the new Enviro-Torque for TGE 1.4? Also how will support for the new DRL: http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=10232 work. Would this be easy to incorporate in?
Thanks for you work on this,
-- Chris S.
04/23/2006 (10:42 am)
Hey Steve,Any update on the release of the new Enviro-Torque for TGE 1.4? Also how will support for the new DRL: http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=10232 work. Would this be easy to incorporate in?
Thanks for you work on this,
-- Chris S.
#59
04/24/2006 (12:31 am)
#60
Maybe the server could send the time and weather every now and then just to check that client isnt badly in offset.
04/30/2006 (12:03 pm)
Would it be possible that server sends the time and weather to client and client would adjust the time&world to match the time on the server? And then the client could do the math by its own so the server would need to send the time only at connection.Maybe the server could send the time and weather every now and then just to check that client isnt badly in offset.

Torque Owner Corin