⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 celestial.cc

📁 五行MMORPG引擎系统V1.0
💻 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 + -