00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "CaelumPrecompiled.h"
00022 #include "PointStarfield.h"
00023 #include "CaelumExceptions.h"
00024 #include "Astronomy.h"
00025 #include "InternalUtilities.h"
00026
00027 using namespace Ogre;
00028
00029 namespace Caelum
00030 {
00031 const Ogre::String PointStarfield::STARFIELD_MATERIAL_NAME = "Caelum/StarPoint";
00032 const Ogre::Degree PointStarfield::DEFAULT_OBSERVER_POSITION_REBUILD_DELTA = Ogre::Degree(0.1);
00033
00034 PointStarfield::PointStarfield (
00035 Ogre::SceneManager *sceneMgr,
00036 Ogre::SceneNode *caelumRootNode,
00037 bool initWithCatalogue)
00038 {
00039 mMag0PixelSize = 16;
00040 mMinPixelSize = 4;
00041 mMaxPixelSize = 6;
00042 mMagnitudeScale = Math::Pow(100, 0.2);
00043 mObserverLatitude = 45;
00044 mObserverLongitude = 0;
00045 mObserverPositionRebuildDelta = DEFAULT_OBSERVER_POSITION_REBUILD_DELTA;
00046
00047 String uniqueSuffix = "/" + InternalUtilities::pointerToString(this);
00048
00049
00050 mMaterial.reset(InternalUtilities::checkLoadMaterialClone(
00051 STARFIELD_MATERIAL_NAME,
00052 STARFIELD_MATERIAL_NAME + uniqueSuffix));
00053
00054 mParams.setup(mMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters());
00055
00056
00057 Ogre::String objName = "Caelum/PointStarfield" + uniqueSuffix;
00058 mManualObj.reset (sceneMgr->createManualObject (objName));
00059 mManualObj->setDynamic(false);
00060 mManualObj->setRenderQueueGroup (CAELUM_RENDER_QUEUE_STARFIELD);
00061 sceneMgr->getRenderQueue()->getQueueGroup(CAELUM_RENDER_QUEUE_STARFIELD)->setShadowsEnabled (false);
00062 mManualObj->setCastShadows(false);
00063
00064 mNode.reset (caelumRootNode->createChildSceneNode ());
00065 mNode->attachObject (mManualObj.getPointer ());
00066
00067 if (initWithCatalogue) {
00068 addBrightStarCatalogue ();
00069 }
00070 }
00071
00072 PointStarfield::~PointStarfield ()
00073 {
00074 }
00075
00076 void PointStarfield::notifyStarVectorChanged () {
00077 invalidateGeometry ();
00078 }
00079
00080 void PointStarfield::clearAllStars () {
00081 mStars.clear();
00082 notifyStarVectorChanged ();
00083 }
00084
00085 Real randReal () {
00086 return rand() / static_cast<float>(RAND_MAX);
00087 }
00088
00089 Real randReal (Real min, Real max) {
00090 Real f = randReal ();
00091 return min * (1 - f) + max * f;
00092 }
00093
00094 void PointStarfield::addRandomStars (int count)
00095 {
00096 for (int i = 0; i < count; ++i) {
00097
00098 Ogre::Vector3 pos;
00099 do {
00100 pos.x = randReal(-1, 1);
00101 pos.y = randReal(-1, 1);
00102 pos.z = randReal(-1, 1);
00103 } while (pos.squaredLength () >= 1);
00104
00105
00106 LongReal rasc, decl, dist;
00107 Astronomy::convertRectangularToSpherical(
00108 pos.x, pos.y, pos.z,
00109 rasc, decl, dist);
00110
00111 Star s;
00112 s.RightAscension = Ogre::Degree (rasc);
00113 s.Declination = Ogre::Degree (decl);
00114
00115 s.Magnitude = 6 * pos.squaredLength () + 1.5;
00116 mStars.push_back(s);
00117 }
00118 notifyStarVectorChanged ();
00119 }
00120
00121 void PointStarfield::addStar (const BrightStarCatalogueEntry &entry) {
00122 Star s;
00123 s.RightAscension = Ogre::Degree(360 / 24.0f * (
00124 Math::Abs(entry.rasc_hour) +
00125 entry.rasc_min / 60.0f +
00126 entry.rasc_sec / 3600.0f));
00127 s.Declination = Ogre::Degree(Math::Sign(entry.decl_deg) * (
00128 Math::Abs(entry.decl_deg) +
00129 entry.decl_min / 60.0f +
00130 entry.decl_sec / 3600.0f));
00131 s.Magnitude = entry.magn;
00132 mStars.push_back(s);
00133
00134 notifyStarVectorChanged ();
00135 }
00136
00137 void PointStarfield::addBrightStarCatalogue (int count) {
00138 assert(count >= 0);
00139 if (count < BrightStarCatalogueSize) {
00140
00141
00142 std::vector<std::pair<Real, int> > vec;
00143 vec.reserve(BrightStarCatalogueSize);
00144 for (int i = 0; i < BrightStarCatalogueSize; ++i) {
00145 vec.push_back(std::make_pair(BrightStarCatalogue[i].magn, i));
00146 }
00147 sort(vec.begin(), vec.end());
00148 for (int i = 0; i < count; ++i) {
00149 addStar(BrightStarCatalogue[vec[i].second]);
00150 }
00151 } else {
00152 assert(count == BrightStarCatalogueSize);
00153 for (int i = 0; i < BrightStarCatalogueSize; ++i) {
00154 addStar(BrightStarCatalogue[i]);
00155 }
00156 }
00157 notifyStarVectorChanged ();
00158 }
00159
00160 void PointStarfield::invalidateGeometry () {
00161 mValidGeometry = false;
00162 }
00163
00164 void PointStarfield::ensureGeometry ()
00165 {
00166 if (mValidGeometry) {
00167 return;
00168 }
00169
00170
00171
00172 size_t starCount = mStars.size();
00173
00174 mManualObj->clear();
00175 mManualObj->estimateVertexCount(6 * starCount);
00176 mManualObj->begin(mMaterial->getName (), Ogre::RenderOperation::OT_TRIANGLE_LIST);
00177 for (uint i = 0; i < starCount; ++i)
00178 {
00179 const Star& star = mStars[i];
00180
00181
00182 LongReal azm, alt;
00183 Astronomy::convertEquatorialToHorizontal(
00184 Astronomy::J2000,
00185 mObserverLatitude.valueDegrees(),
00186 mObserverLongitude.valueDegrees(),
00187 star.RightAscension.valueDegrees(), star.Declination.valueDegrees(),
00188 azm, alt);
00189
00190 Ogre::Vector3 pos;
00191 pos.z = -Math::Cos (Ogre::Degree(azm)) * Math::Cos (Ogre::Degree(alt));
00192 pos.x = Math::Sin (Ogre::Degree(azm)) * Math::Cos (Ogre::Degree(alt));
00193 pos.y = -Math::Sin (Ogre::Degree(alt));
00194
00195
00196 mManualObj->position (pos);
00197 mManualObj->textureCoord (+1, -1, star.Magnitude);
00198 mManualObj->position (pos);
00199 mManualObj->textureCoord (+1, +1, star.Magnitude);
00200 mManualObj->position (pos);
00201 mManualObj->textureCoord (-1, -1, star.Magnitude);
00202
00203 mManualObj->position (pos);
00204 mManualObj->textureCoord (-1, -1, star.Magnitude);
00205 mManualObj->position (pos);
00206 mManualObj->textureCoord (+1, +1, star.Magnitude);
00207 mManualObj->position (pos);
00208 mManualObj->textureCoord (-1, +1, star.Magnitude);
00209 }
00210 mManualObj->end();
00211
00212
00213 AxisAlignedBox box;
00214 box.setInfinite ();
00215 mManualObj->setBoundingBox (box);
00216
00217 mValidGeometry = true;
00218 }
00219
00220 void PointStarfield::Params::setup(Ogre::GpuProgramParametersSharedPtr vpParams)
00221 {
00222 this->vpParams = vpParams;
00223 this->mag_scale.bind(vpParams, "mag_scale");
00224 this->mag0_size.bind(vpParams, "mag0_size");
00225 this->min_size.bind(vpParams, "min_size");
00226 this->max_size.bind(vpParams, "max_size");
00227 this->aspect_ratio.bind(vpParams, "aspect_ratio");
00228 }
00229
00230 void PointStarfield::notifyCameraChanged (Ogre::Camera *cam) {
00231 CameraBoundElement::notifyCameraChanged (cam);
00232
00233
00234 Pass* pass = mMaterial->getBestTechnique ()->getPass (0);
00235 GpuProgramParametersSharedPtr fpParams = pass->getFragmentProgramParameters ();
00236 GpuProgramParametersSharedPtr vpParams = pass->getVertexProgramParameters ();
00237
00238 int height = cam->getViewport ()-> getActualHeight ();
00239 int width = cam->getViewport ()-> getActualWidth ();
00240 Real pixFactor = 1.0f / width;
00241 Real magScale = -Math::Log (mMagnitudeScale) / 2;
00242 Real mag0Size = mMag0PixelSize * pixFactor;
00243 Real minSize = mMinPixelSize * pixFactor;
00244 Real maxSize = mMaxPixelSize * pixFactor;
00245 Real aspectRatio = static_cast<Real>(width) / height;
00246
00247
00248 mParams.mag_scale.set(mParams.vpParams, magScale);
00249 mParams.mag0_size.set(mParams.vpParams, mag0Size);
00250 mParams.min_size.set(mParams.vpParams, minSize);
00251 mParams.max_size.set(mParams.vpParams, maxSize);
00252 mParams.aspect_ratio.set(mParams.vpParams, aspectRatio);
00253 }
00254
00255 void PointStarfield::setFarRadius (Ogre::Real radius) {
00256 CameraBoundElement::setFarRadius(radius);
00257 mNode->setScale (Ogre::Vector3::UNIT_SCALE * radius);
00258 }
00259
00260 void PointStarfield::_update (const float time) {
00261
00262 Ogre::Quaternion orientation = Ogre::Quaternion::IDENTITY;
00263 orientation = orientation * Ogre::Quaternion (Ogre::Radian (-mObserverLatitude + Ogre::Degree (90)), Ogre::Vector3::UNIT_X);
00264 orientation = orientation * Ogre::Quaternion (Ogre::Radian (-time * 2 * Ogre::Math::PI), Ogre::Vector3::UNIT_Y);
00265 mNode->setOrientation (orientation);
00266 ensureGeometry ();
00267 }
00268
00269 void PointStarfield::setObserverLatitude (Ogre::Degree value)
00270 {
00271 if (!Math::RealEqual (
00272 mObserverLatitude.valueDegrees (),
00273 value.valueDegrees (),
00274 this->getObserverPositionRebuildDelta ().valueDegrees ()))
00275 {
00276 mObserverLatitude = value;
00277 invalidateGeometry ();
00278 }
00279 }
00280
00281 void PointStarfield::setObserverLongitude (Ogre::Degree value)
00282 {
00283 if (!Math::RealEqual (
00284 mObserverLongitude.valueDegrees (),
00285 value.valueDegrees (),
00286 this->getObserverPositionRebuildDelta ().valueDegrees ()))
00287 {
00288 mObserverLongitude = value;
00289 invalidateGeometry ();
00290 }
00291 }
00292 }