2
This file is part of Caelum.
3
See http://www.ogre3d.org/wiki/index.php/Caelum
5
Copyright (c) 2008 Caelum team. See Contributors.txt for details.
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.
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.
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/>.
21
#include "CaelumPrecompiled.h"
22
#include "PointStarfield.h"
23
#include "GeometryFactory.h"
24
#include "CaelumExceptions.h"
25
#include "Astronomy.h"
31
const Ogre::String PointStarfield::BILLBOARD_MATERIAL_NAME = "Caelum/StarPoint";
33
PointStarfield::PointStarfield (
34
Ogre::SceneManager *sceneMgr,
35
Ogre::SceneNode *caelumRootNode,
36
bool initWithCatalogue)
41
mMagnitudeScale = Math::Pow(100, 0.2);
42
mObserverLatitude = 45;
43
mObserverLongitude = 0;
45
mMaterial = Ogre::MaterialManager::getSingleton ().getByName (BILLBOARD_MATERIAL_NAME);
46
if (mMaterial.isNull ()) {
47
CAELUM_THROW_UNSUPPORED_EXCEPTION ("Can't load point starfield material", "PointStarfield");
50
if (mMaterial->getBestTechnique () == 0) {
51
CAELUM_THROW_UNSUPPORED_EXCEPTION ("Can't load point starfield material", "PointStarfield");
54
sceneMgr->getRenderQueue()->getQueueGroup(CAELUM_RENDER_QUEUE_STARFIELD)->setShadowsEnabled (false);
56
// We use a separate data source.
57
Ogre::String objName = "Caelum/PointStarfield/" + Ogre::StringConverter::toString ((size_t)this);
58
mManualObj = sceneMgr->createManualObject (objName);
59
mManualObj->setDynamic(false);
60
mManualObj->setRenderQueueGroup (CAELUM_RENDER_QUEUE_STARFIELD);
61
mManualObj->setCastShadows(false);
63
mNode = caelumRootNode->createChildSceneNode ();
64
mNode->attachObject (mManualObj);
66
if (initWithCatalogue) {
67
addBrightStarCatalogue ();
71
PointStarfield::~PointStarfield () {
73
mNode->getCreator()->destroySceneNode(mNode->getName());
78
mManualObj->_getManager()->destroyMovableObject(mManualObj);
82
Ogre::MaterialManager::getSingletonPtr()->remove(mMaterial->getHandle());
85
void PointStarfield::notifyStarVectorChanged () {
86
invalidateGeometry ();
89
void PointStarfield::clearAllStars () {
91
notifyStarVectorChanged ();
95
return rand() / static_cast<float>(RAND_MAX);
98
Real randReal (Real min, Real max) {
100
return min * (1 - f) + max * f;
103
void PointStarfield::addRandomStars (int count)
105
for (int i = 0; i < count; ++i) {
106
// Generate a vector inside a sphere
109
pos.x = randReal(-1, 1);
110
pos.y = randReal(-1, 1);
111
pos.z = randReal(-1, 1);
112
} while (pos.squaredLength () >= 1);
114
// Convert to rasc/decl angles.
115
LongReal rasc, decl, dist;
116
Astronomy::convertRectangularToSpherical(
121
s.RightAscension = Ogre::Degree (rasc);
122
s.Declination = Ogre::Degree (decl);
123
// This distribution is wrong.
124
s.Magnitude = 6 * pos.squaredLength () + 1.5;
127
notifyStarVectorChanged ();
130
void PointStarfield::addStar (const BrightStarCatalogueEntry &entry) {
132
s.RightAscension = Ogre::Degree(360 / 24.0f * (
133
Math::Abs(entry.rasc_hour) +
134
entry.rasc_min / 60.0f +
135
entry.rasc_sec / 3600.0f));
136
s.Declination = Ogre::Degree(Math::Sign(entry.decl_deg) * (
137
Math::Abs(entry.decl_deg) +
138
entry.decl_min / 60.0f +
139
entry.decl_sec / 3600.0f));
140
s.Magnitude = entry.magn;
143
notifyStarVectorChanged ();
146
void PointStarfield::addBrightStarCatalogue (int count) {
148
if (count < BrightStarCatalogueSize) {
149
// Only sort if we don't add everything.
150
// It would be lovely if the catalogue was already sorted.
151
std::vector<std::pair<Real, int> > vec;
152
vec.reserve(BrightStarCatalogueSize);
153
for (int i = 0; i < BrightStarCatalogueSize; ++i) {
154
vec.push_back(std::make_pair(BrightStarCatalogue[i].magn, i));
156
sort(vec.begin(), vec.end());
157
for (int i = 0; i < count; ++i) {
158
addStar(BrightStarCatalogue[vec[i].second]);
161
assert(count == BrightStarCatalogueSize);
162
for (int i = 0; i < BrightStarCatalogueSize; ++i) {
163
addStar(BrightStarCatalogue[i]);
166
notifyStarVectorChanged ();
169
void PointStarfield::invalidateGeometry () {
170
mValidGeometry = false;
173
void PointStarfield::ensureGeometry ()
175
if (mValidGeometry) {
179
Ogre::LogManager::getSingleton ().logMessage ("Caelum: Recomputing starfield geometry.");
182
mManualObj->estimateVertexCount(6 * mStars.size());
183
mManualObj->begin(mMaterial->getName (), Ogre::RenderOperation::OT_TRIANGLE_LIST);
184
for (uint i = 0; i < mStars.size(); ++i) {
185
// Determine position at J2000
187
Astronomy::convertEquatorialToHorizontal(
189
mObserverLatitude.valueDegrees(),
190
mObserverLongitude.valueDegrees(),
191
mStars[i].RightAscension.valueDegrees(), mStars[i].Declination.valueDegrees(),
195
pos.z = -Math::Cos (Ogre::Degree(azm)) * Math::Cos (Ogre::Degree(alt));
196
pos.x = Math::Sin (Ogre::Degree(azm)) * Math::Cos (Ogre::Degree(alt));
197
pos.y = -Math::Sin (Ogre::Degree(alt));
199
mManualObj->colour (Ogre::ColourValue::White);
200
mManualObj->position (pos);
201
mManualObj->textureCoord (+1, -1, mStars[i].Magnitude);
202
mManualObj->position (pos);
203
mManualObj->textureCoord (+1, +1, mStars[i].Magnitude);
204
mManualObj->position (pos);
205
mManualObj->textureCoord (-1, -1, mStars[i].Magnitude);
207
mManualObj->position (pos);
208
mManualObj->textureCoord (-1, -1, mStars[i].Magnitude);
209
mManualObj->position (pos);
210
mManualObj->textureCoord (+1, +1, mStars[i].Magnitude);
211
mManualObj->position (pos);
212
mManualObj->textureCoord (-1, +1, mStars[i].Magnitude);
216
// Set infinite bounds on the starfield.
219
mManualObj->setBoundingBox (box);
221
mValidGeometry = true;
224
void PointStarfield::notifyCameraChanged (Ogre::Camera *cam) {
225
CameraBoundElement::notifyCameraChanged (cam);
227
// Shader params are changed for every camera.
228
Pass* pass = mMaterial->getBestTechnique ()->getPass (0);
229
GpuProgramParametersSharedPtr fpParams = pass->getFragmentProgramParameters ();
230
GpuProgramParametersSharedPtr vpParams = pass->getVertexProgramParameters ();
232
int height = cam->getViewport ()-> getActualHeight ();
233
int width = cam->getViewport ()-> getActualWidth ();
234
Real pixFactor = 1.0f / width;
235
Real magScale = -Math::Log (mMagnitudeScale) / 2;
236
Real mag0Size = mMag0PixelSize * pixFactor;
237
Real minSize = mMinPixelSize * pixFactor;
238
Real maxSize = mMaxPixelSize * pixFactor;
239
Real aspectRatio = static_cast<Real>(width) / height;
241
// These params are relative to the size of the screen.
242
vpParams->setIgnoreMissingParams (true);
243
vpParams->setNamedConstant ("mag_scale", magScale);
244
vpParams->setNamedConstant ("mag0_size", mag0Size);
245
vpParams->setNamedConstant ("min_size", minSize);
246
vpParams->setNamedConstant ("max_size", maxSize);
247
vpParams->setNamedConstant ("aspect_ratio", aspectRatio);
250
void PointStarfield::setFarRadius (Ogre::Real radius) {
251
CameraBoundElement::setFarRadius(radius);
252
mNode->setScale (Ogre::Vector3::UNIT_SCALE * radius);
255
void PointStarfield::_update (const float time) {
256
// This is probably wrong.
257
Ogre::Quaternion orientation = Ogre::Quaternion::IDENTITY;
258
orientation = orientation * Ogre::Quaternion (Ogre::Radian (-mObserverLatitude + Ogre::Degree (90)), Ogre::Vector3::UNIT_X);
259
orientation = orientation * Ogre::Quaternion (Ogre::Radian (-time * 2 * Ogre::Math::PI), Ogre::Vector3::UNIT_Y);
260
mNode->setOrientation (orientation);
264
void PointStarfield::setObserverLatitude (Ogre::Degree value) {
265
if (!Math::RealEqual (mObserverLatitude.valueDegrees (), value.valueDegrees (), 0.001)) {
266
mObserverLatitude = value;
267
invalidateGeometry ();
271
void PointStarfield::setObserverLongitude (Ogre::Degree value) {
272
if (!Math::RealEqual (mObserverLongitude.valueDegrees (), value.valueDegrees (), 0.001)) {
273
mObserverLongitude = value;
274
invalidateGeometry ();