📄 celestial.cc
字号:
#include "game/fx/Celestial.h"
#include "console/consoleTypes.h"
#include "sceneGraph/sceneGraph.h"
#include "math/mathUtils.h"
// Our global object pointer so everyone can see us.
Celestials *gCelestials = NULL;
IMPLEMENT_CONOBJECT(Celestials);
Celestials::Celestials() : mConvertedToRads(0)
{
/* //This seems to be hosing things up. :P
if(gCelestials != NULL)
return; // The environment only needs one of these
*/
//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");
}
bool Celestials::onAdd()
{
if (Parent::onAdd() == false)
return false;
gCelestials = this; // make a pointer to this object accessable by all.
return true;
}
void Celestials::onRemove()
{
gCelestials = NULL;
Parent::onRemove();
}
/**
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;
}
// 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->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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -