Caelum
PointStarfield.cpp
1 /*
2 This file is part of Caelum.
3 See http://www.ogre3d.org/wiki/index.php/Caelum
4 
5 Copyright (c) 2008 Caelum team. See Contributors.txt for details.
6 
7 Caelum is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Caelum is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License
18 along with Caelum. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "CaelumPrecompiled.h"
22 #include "PointStarfield.h"
23 #include "CaelumExceptions.h"
24 #include "Astronomy.h"
25 #include "InternalUtilities.h"
26 
27 using namespace Ogre;
28 
29 namespace Caelum
30 {
31  const Ogre::String PointStarfield::STARFIELD_MATERIAL_NAME = "Caelum/StarPoint";
32  const Ogre::Degree PointStarfield::DEFAULT_OBSERVER_POSITION_REBUILD_DELTA = Ogre::Degree(0.1);
33 
34  PointStarfield::PointStarfield (
35  Ogre::SceneManager *sceneMgr,
36  Ogre::SceneNode *caelumRootNode,
37  bool initWithCatalogue)
38  {
39  mMag0PixelSize = 16;
40  mMinPixelSize = 4;
41  mMaxPixelSize = 6;
42  mMagnitudeScale = Math::Pow(100, 0.2);
43  mObserverLatitude = 45;
44  mObserverLongitude = 0;
45  mObserverPositionRebuildDelta = DEFAULT_OBSERVER_POSITION_REBUILD_DELTA;
46 
47  String uniqueSuffix = "/" + InternalUtilities::pointerToString(this);
48 
49  // Load material.
50  mMaterial.reset(InternalUtilities::checkLoadMaterialClone(
51  STARFIELD_MATERIAL_NAME,
52  STARFIELD_MATERIAL_NAME + uniqueSuffix));
53 
54  mParams.setup(mMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters());
55 
56  // We use a separate data source.
57  Ogre::String objName = "Caelum/PointStarfield" + uniqueSuffix;
58  mManualObj.reset (sceneMgr->createManualObject (objName));
59  mManualObj->setDynamic(false);
60  mManualObj->setRenderQueueGroup (CAELUM_RENDER_QUEUE_STARFIELD);
61  sceneMgr->getRenderQueue()->getQueueGroup(CAELUM_RENDER_QUEUE_STARFIELD)->setShadowsEnabled (false);
62  mManualObj->setCastShadows(false);
63 
64  mNode.reset (caelumRootNode->createChildSceneNode ());
65  mNode->attachObject (mManualObj.getPointer ());
66 
67  if (initWithCatalogue) {
68  addBrightStarCatalogue ();
69  }
70  }
71 
72  PointStarfield::~PointStarfield ()
73  {
74  }
75 
76  void PointStarfield::notifyStarVectorChanged () {
77  invalidateGeometry ();
78  }
79 
80  void PointStarfield::clearAllStars () {
81  mStars.clear();
82  notifyStarVectorChanged ();
83  }
84 
85  Real randReal () {
86  return rand() / static_cast<float>(RAND_MAX);
87  }
88 
89  Real randReal (Real min, Real max) {
90  Real f = randReal ();
91  return min * (1 - f) + max * f;
92  }
93 
94  void PointStarfield::addRandomStars (int count)
95  {
96  for (int i = 0; i < count; ++i) {
97  // Generate a vector inside a sphere
98  Ogre::Vector3 pos;
99  do {
100  pos.x = randReal(-1, 1);
101  pos.y = randReal(-1, 1);
102  pos.z = randReal(-1, 1);
103  } while (pos.squaredLength () >= 1);
104 
105  // Convert to rasc/decl angles.
106  LongReal rasc, decl, dist;
107  Astronomy::convertRectangularToSpherical(
108  pos.x, pos.y, pos.z,
109  rasc, decl, dist);
110 
111  Star s;
112  s.RightAscension = Ogre::Degree (rasc);
113  s.Declination = Ogre::Degree (decl);
114  // This distribution is wrong.
115  s.Magnitude = 6 * pos.squaredLength () + 1.5;
116  mStars.push_back(s);
117  }
118  notifyStarVectorChanged ();
119  }
120 
121  void PointStarfield::addStar (const BrightStarCatalogueEntry &entry) {
122  Star s;
123  s.RightAscension = Ogre::Degree(360 / 24.0f * (
124  Math::Abs(entry.rasc_hour) +
125  entry.rasc_min / 60.0f +
126  entry.rasc_sec / 3600.0f));
127  s.Declination = Ogre::Degree(Math::Sign(entry.decl_deg) * (
128  Math::Abs(entry.decl_deg) +
129  entry.decl_min / 60.0f +
130  entry.decl_sec / 3600.0f));
131  s.Magnitude = entry.magn;
132  mStars.push_back(s);
133 
134  notifyStarVectorChanged ();
135  }
136 
137  void PointStarfield::addBrightStarCatalogue (int count) {
138  assert(count >= 0);
139  if (count < BrightStarCatalogueSize) {
140  // Only sort if we don't add everything.
141  // It would be lovely if the catalogue was already sorted.
142  std::vector<std::pair<Real, int> > vec;
143  vec.reserve(BrightStarCatalogueSize);
144  for (int i = 0; i < BrightStarCatalogueSize; ++i) {
145  vec.push_back(std::make_pair(BrightStarCatalogue[i].magn, i));
146  }
147  sort(vec.begin(), vec.end());
148  for (int i = 0; i < count; ++i) {
149  addStar(BrightStarCatalogue[vec[i].second]);
150  }
151  } else {
152  assert(count == BrightStarCatalogueSize);
153  for (int i = 0; i < BrightStarCatalogueSize; ++i) {
154  addStar(BrightStarCatalogue[i]);
155  }
156  }
157  notifyStarVectorChanged ();
158  }
159 
160  void PointStarfield::invalidateGeometry () {
161  mValidGeometry = false;
162  }
163 
164  void PointStarfield::ensureGeometry ()
165  {
166  if (mValidGeometry) {
167  return;
168  }
169 
170  //Ogre::LogManager::getSingleton ().logMessage ("Caelum: Recomputing starfield geometry.");
171 
172  size_t starCount = mStars.size();
173 
174  mManualObj->clear();
175  mManualObj->estimateVertexCount(6 * starCount);
176  mManualObj->begin(mMaterial->getName (), Ogre::RenderOperation::OT_TRIANGLE_LIST);
177  for (uint i = 0; i < starCount; ++i)
178  {
179  const Star& star = mStars[i];
180 
181  // Determine position at J2000
182  LongReal azm, alt;
183  Astronomy::convertEquatorialToHorizontal(
184  Astronomy::J2000,
185  mObserverLatitude.valueDegrees(),
186  mObserverLongitude.valueDegrees(),
187  star.RightAscension.valueDegrees(), star.Declination.valueDegrees(),
188  azm, alt);
189 
190  Ogre::Vector3 pos;
191  pos.z = -Math::Cos (Ogre::Degree(azm)) * Math::Cos (Ogre::Degree(alt));
192  pos.x = Math::Sin (Ogre::Degree(azm)) * Math::Cos (Ogre::Degree(alt));
193  pos.y = -Math::Sin (Ogre::Degree(alt));
194 
195  //mManualObj->colour (Ogre::ColourValue::White);
196  mManualObj->position (pos);
197  mManualObj->textureCoord (+1, -1, star.Magnitude);
198  mManualObj->position (pos);
199  mManualObj->textureCoord (+1, +1, star.Magnitude);
200  mManualObj->position (pos);
201  mManualObj->textureCoord (-1, -1, star.Magnitude);
202 
203  mManualObj->position (pos);
204  mManualObj->textureCoord (-1, -1, star.Magnitude);
205  mManualObj->position (pos);
206  mManualObj->textureCoord (+1, +1, star.Magnitude);
207  mManualObj->position (pos);
208  mManualObj->textureCoord (-1, +1, star.Magnitude);
209  }
210  mManualObj->end();
211 
212  // Set finite bounds on the starfield to avoid parent AABB infection
213  AxisAlignedBox box(Ogre::AxisAlignedBox::EXTENT_FINITE);
214  mManualObj->setBoundingBox (box);
215 
216  mValidGeometry = true;
217  }
218 
219  void PointStarfield::Params::setup(Ogre::GpuProgramParametersSharedPtr vpParams)
220  {
221  this->vpParams = vpParams;
222  this->mag_scale.bind(vpParams, "mag_scale");
223  this->mag0_size.bind(vpParams, "mag0_size");
224  this->min_size.bind(vpParams, "min_size");
225  this->max_size.bind(vpParams, "max_size");
226  this->aspect_ratio.bind(vpParams, "aspect_ratio");
227  }
228 
229  void PointStarfield::notifyCameraChanged (Ogre::Camera *cam) {
230  CameraBoundElement::notifyCameraChanged (cam);
231 
232  // Shader params are changed for every camera.
233  Pass* pass = mMaterial->getBestTechnique ()->getPass (0);
234  GpuProgramParametersSharedPtr fpParams = pass->getFragmentProgramParameters ();
235  GpuProgramParametersSharedPtr vpParams = pass->getVertexProgramParameters ();
236 
237  int height = cam->getViewport ()-> getActualHeight ();
238  int width = cam->getViewport ()-> getActualWidth ();
239  Real pixFactor = 1.0f / width;
240  Real magScale = -Math::Log (mMagnitudeScale) / 2;
241  Real mag0Size = mMag0PixelSize * pixFactor;
242  Real minSize = mMinPixelSize * pixFactor;
243  Real maxSize = mMaxPixelSize * pixFactor;
244  Real aspectRatio = static_cast<Real>(width) / height;
245 
246  // These params are relative to the size of the screen.
247  mParams.mag_scale.set(mParams.vpParams, magScale);
248  mParams.mag0_size.set(mParams.vpParams, mag0Size);
249  mParams.min_size.set(mParams.vpParams, minSize);
250  mParams.max_size.set(mParams.vpParams, maxSize);
251  mParams.aspect_ratio.set(mParams.vpParams, aspectRatio);
252  }
253 
254  void PointStarfield::setFarRadius (Ogre::Real radius) {
255  CameraBoundElement::setFarRadius(radius);
256  mNode->setScale (Ogre::Vector3::UNIT_SCALE * radius);
257  }
258 
259  void PointStarfield::_update (const float time) {
260  // This is probably wrong.
261  Ogre::Quaternion orientation = Ogre::Quaternion::IDENTITY;
262  orientation = orientation * Ogre::Quaternion (Ogre::Radian (-mObserverLatitude + Ogre::Degree (90)), Ogre::Vector3::UNIT_X);
263  orientation = orientation * Ogre::Quaternion (Ogre::Radian (-time * 2 * Ogre::Math::PI), Ogre::Vector3::UNIT_Y);
264  mNode->setOrientation (orientation);
265  ensureGeometry ();
266  }
267 
268  void PointStarfield::setObserverLatitude (Ogre::Degree value)
269  {
270  if (!Math::RealEqual (
271  mObserverLatitude.valueDegrees (),
272  value.valueDegrees (),
273  this->getObserverPositionRebuildDelta ().valueDegrees ()))
274  {
275  mObserverLatitude = value;
276  invalidateGeometry ();
277  }
278  }
279 
280  void PointStarfield::setObserverLongitude (Ogre::Degree value)
281  {
282  if (!Math::RealEqual (
283  mObserverLongitude.valueDegrees (),
284  value.valueDegrees (),
285  this->getObserverPositionRebuildDelta ().valueDegrees ()))
286  {
287  mObserverLongitude = value;
288  invalidateGeometry ();
289  }
290  }
291 }
const int BrightStarCatalogueSize
There are exactly 9110 stars in our version of the BSC.
const BrightStarCatalogueEntry BrightStarCatalogue[BrightStarCatalogueSize]
Hardcoded bright star catalogue (BrightStarCatalogue.cpp)
Struct representing one star inside PointStarfield.
POD for bright star catalogue entries.
Caelum namespace.
Definition: Astronomy.cpp:24