~ubuntu-branches/debian/sid/ember/sid

« back to all changes in this revision

Viewing changes to src/components/ogre/environment/caelum/src/PointStarfield.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Koch
  • Date: 2009-07-23 07:46:40 UTC
  • Revision ID: james.westby@ubuntu.com-20090723074640-wh0ukzis0kda36qv
Tags: upstream-0.5.6
ImportĀ upstreamĀ versionĀ 0.5.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "GeometryFactory.h"
 
24
#include "CaelumExceptions.h"
 
25
#include "Astronomy.h"
 
26
 
 
27
using namespace Ogre;
 
28
 
 
29
namespace caelum
 
30
{
 
31
        const Ogre::String PointStarfield::BILLBOARD_MATERIAL_NAME = "Caelum/StarPoint";
 
32
 
 
33
        PointStarfield::PointStarfield (
 
34
                        Ogre::SceneManager *sceneMgr,
 
35
                        Ogre::SceneNode *caelumRootNode,
 
36
                        bool initWithCatalogue)
 
37
        {
 
38
                mMag0PixelSize = 16;
 
39
                mMinPixelSize = 4;
 
40
                mMaxPixelSize = 6;
 
41
                mMagnitudeScale = Math::Pow(100, 0.2);
 
42
                mObserverLatitude = 45;
 
43
                mObserverLongitude = 0;
 
44
 
 
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");
 
48
                }
 
49
                mMaterial->load ();
 
50
                if (mMaterial->getBestTechnique () == 0) {
 
51
                        CAELUM_THROW_UNSUPPORED_EXCEPTION ("Can't load point starfield material", "PointStarfield");
 
52
                }
 
53
 
 
54
                sceneMgr->getRenderQueue()->getQueueGroup(CAELUM_RENDER_QUEUE_STARFIELD)->setShadowsEnabled (false);
 
55
 
 
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);
 
62
 
 
63
                mNode = caelumRootNode->createChildSceneNode ();
 
64
                mNode->attachObject (mManualObj);
 
65
 
 
66
                if (initWithCatalogue) {
 
67
                        addBrightStarCatalogue ();
 
68
                }
 
69
        }
 
70
 
 
71
        PointStarfield::~PointStarfield () {
 
72
                if (mNode) {
 
73
                        mNode->getCreator()->destroySceneNode(mNode->getName());
 
74
                        mNode = 0;
 
75
                }
 
76
 
 
77
                if (mManualObj) {
 
78
                        mManualObj->_getManager()->destroyMovableObject(mManualObj);
 
79
                        mManualObj = 0;
 
80
                }
 
81
                        
 
82
                Ogre::MaterialManager::getSingletonPtr()->remove(mMaterial->getHandle());
 
83
        }
 
84
 
 
85
    void PointStarfield::notifyStarVectorChanged () {
 
86
        invalidateGeometry ();
 
87
    }
 
88
 
 
89
    void PointStarfield::clearAllStars () {
 
90
        mStars.clear();
 
91
        notifyStarVectorChanged ();
 
92
    }
 
93
 
 
94
        Real randReal () {
 
95
                return rand() / static_cast<float>(RAND_MAX);
 
96
        }
 
97
 
 
98
        Real randReal (Real min, Real max) {
 
99
                Real f = randReal ();
 
100
                return min * (1 - f) + max * f;
 
101
        }
 
102
 
 
103
        void PointStarfield::addRandomStars (int count)
 
104
        {
 
105
                for (int i = 0; i < count; ++i) {
 
106
                        // Generate a vector inside a sphere
 
107
                        Ogre::Vector3 pos;
 
108
                        do {
 
109
                                pos.x = randReal(-1, 1);
 
110
                                pos.y = randReal(-1, 1);
 
111
                                pos.z = randReal(-1, 1);
 
112
                        } while (pos.squaredLength () >= 1);
 
113
 
 
114
                        // Convert to rasc/decl angles.
 
115
                        LongReal rasc, decl, dist;
 
116
                        Astronomy::convertRectangularToSpherical(
 
117
                                        pos.x, pos.y, pos.z,
 
118
                                        rasc, decl, dist);
 
119
 
 
120
                        Star s;
 
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;
 
125
                        mStars.push_back(s);
 
126
                }
 
127
                notifyStarVectorChanged ();
 
128
        }
 
129
 
 
130
        void PointStarfield::addStar (const BrightStarCatalogueEntry &entry) {
 
131
                Star s;
 
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;
 
141
                mStars.push_back(s);
 
142
 
 
143
        notifyStarVectorChanged ();
 
144
        }
 
145
 
 
146
        void PointStarfield::addBrightStarCatalogue (int count) {
 
147
                assert(count >= 0);
 
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));
 
155
                        }
 
156
                        sort(vec.begin(), vec.end());
 
157
                        for (int i = 0; i < count; ++i) {
 
158
                                addStar(BrightStarCatalogue[vec[i].second]);
 
159
                        }
 
160
                } else {
 
161
                        assert(count == BrightStarCatalogueSize);
 
162
                        for (int i = 0; i < BrightStarCatalogueSize; ++i) {
 
163
                                addStar(BrightStarCatalogue[i]);
 
164
                        }
 
165
                }
 
166
        notifyStarVectorChanged ();
 
167
        }
 
168
 
 
169
        void PointStarfield::invalidateGeometry () {
 
170
                mValidGeometry = false;
 
171
        }
 
172
 
 
173
        void PointStarfield::ensureGeometry ()
 
174
        {
 
175
                if (mValidGeometry) {
 
176
                        return;
 
177
                }
 
178
 
 
179
                Ogre::LogManager::getSingleton ().logMessage ("Caelum: Recomputing starfield geometry.");
 
180
 
 
181
        mManualObj->clear();
 
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
 
186
                        LongReal azm, alt;
 
187
                        Astronomy::convertEquatorialToHorizontal(
 
188
                                        Astronomy::J2000,
 
189
                                        mObserverLatitude.valueDegrees(),
 
190
                                        mObserverLongitude.valueDegrees(),
 
191
                                        mStars[i].RightAscension.valueDegrees(), mStars[i].Declination.valueDegrees(),
 
192
                                        azm, alt);
 
193
 
 
194
                Ogre::Vector3 pos;
 
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));
 
198
 
 
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);
 
206
 
 
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);
 
213
        }
 
214
        mManualObj->end();
 
215
 
 
216
        // Set infinite bounds on the starfield.
 
217
        AxisAlignedBox box;
 
218
        box.setInfinite ();
 
219
        mManualObj->setBoundingBox (box);
 
220
 
 
221
                mValidGeometry = true;
 
222
        }
 
223
 
 
224
        void PointStarfield::notifyCameraChanged (Ogre::Camera *cam) {
 
225
                CameraBoundElement::notifyCameraChanged (cam);
 
226
 
 
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 ();
 
231
 
 
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;
 
240
 
 
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);
 
248
        }
 
249
 
 
250
        void PointStarfield::setFarRadius (Ogre::Real radius) {
 
251
        CameraBoundElement::setFarRadius(radius);
 
252
            mNode->setScale (Ogre::Vector3::UNIT_SCALE * radius);
 
253
        }
 
254
 
 
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);
 
261
        ensureGeometry ();
 
262
        }
 
263
 
 
264
        void PointStarfield::setObserverLatitude (Ogre::Degree value) {
 
265
                if (!Math::RealEqual (mObserverLatitude.valueDegrees (), value.valueDegrees (), 0.001)) {
 
266
                        mObserverLatitude = value;
 
267
                        invalidateGeometry ();
 
268
                }
 
269
        }
 
270
 
 
271
        void PointStarfield::setObserverLongitude (Ogre::Degree value) {
 
272
                if (!Math::RealEqual (mObserverLongitude.valueDegrees (), value.valueDegrees (), 0.001)) {
 
273
                        mObserverLongitude = value;
 
274
                        invalidateGeometry ();
 
275
                }
 
276
        }
 
277
}