00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "space/stellardb.hpp"
00035 #include "space/astronomy.hpp"
00036 #include "space/space_context.hpp"
00037
00038 #include "data/fstream.hpp"
00039 #include "platform/font.hpp"
00040 #include "platform/shader.hpp"
00041 #include "scenegraph/context.hpp"
00042 #include "scenegraph/camera.hpp"
00043 #include "scenegraph/utils.hpp"
00044 #include "framework/application.hpp"
00045
00046 #include "platform/lowlevel.hpp"
00047
00048 #include <cmath>
00049 #include <cfloat>
00050
00051 using namespace gsgl;
00052 using namespace gsgl::data;
00053 using namespace gsgl::io;
00054 using namespace gsgl::math;
00055 using namespace gsgl::platform;
00056 using namespace gsgl::scenegraph;
00057
00058 namespace periapsis
00059 {
00060
00061 namespace space
00062 {
00063
00064 BROKER_DEFINE_CREATOR(periapsis::space::stellar_db);
00065
00066
00067
00068 stellar_db::stellar_db(const config_record & conf)
00069 : node(conf), nearest_distance(FLT_MAX), farthest_distance(0), vertices(vbuffer::STATIC)
00070 {
00071 get_draw_flags() |= node::NODE_NO_FRUSTUM_CHECK;
00072
00073
00074 string db_fname = conf[L"data"];
00075 if (!db_fname.is_empty())
00076 {
00077 load_db(conf.get_directory().get_full_path() + db_fname);
00078 }
00079 else
00080 {
00081 throw runtime_exception(L"No data specified for stellar database node.");
00082 }
00083
00084
00085 star_shader.add_vertex_shader(gsgl::framework::application::SYS_DATA_PATH + L"Shaders" + directory::SEPARATOR + L"star_vertex_shader.glsl");
00086 }
00087
00088
00089 stellar_db::~stellar_db()
00090 {
00091 int i, len = star_names.size();
00092 for (i = 0; i < len; ++i)
00093 delete star_names[i];
00094 }
00095
00096
00097 gsgl::real_t stellar_db::get_priority(context *)
00098 {
00099 return NODE_DRAW_FIRST / 10.0f;
00100 }
00101
00102
00103
00104
00105 static const string STAR_DB_COOKIE = L"Periapsis Stellar Database 2.0";
00106
00107 void stellar_db::load_db(const string & fname)
00108 {
00109 fd_stream f(fname);
00110
00111 string cookie;
00112 f >> cookie;
00113 if (cookie != STAR_DB_COOKIE)
00114 throw io_exception(L"Invalid stellar database format in %ls.", fname.w_string());
00115
00116 f >> num_stars;
00117
00118
00119 smart_pointer<float, true> magnitudes(new float[num_stars]);
00120
00121 float max_magnitude = 0.0f;
00122 float min_magnitude = 0.0f;
00123
00124 for (int i = 0; i < num_stars; ++i)
00125 {
00126 int hyg_id;
00127 f >> hyg_id;
00128
00129
00130 float right_ascension, declination, distance, abs_magnitude;
00131
00132 f >> right_ascension;
00133 f >> declination;
00134 f >> distance;
00135 f >> abs_magnitude;
00136
00137 float theta = static_cast<float>(right_ascension * (360.0f / 24.0f) * math::DEG2RAD);
00138 float phi = static_cast<float>(declination * math::DEG2RAD);
00139
00140 float x_eq = distance * ::cos(theta) * ::cos(phi);
00141 float y_eq = distance * ::sin(theta) * ::cos(phi);
00142 float z_eq = distance * ::sin(phi);
00143
00144 vector equatorial_pos(x_eq, y_eq, z_eq);
00145 vector galactic_pos = EQUATORIAL_WRT_GALACTIC * equatorial_pos;
00146
00147 if (distance< nearest_distance)
00148 nearest_distance = distance;
00149 if (distance > farthest_distance)
00150 farthest_distance = distance;
00151
00152 magnitudes[i] = abs_magnitude;
00153 if (abs_magnitude > max_magnitude)
00154 max_magnitude = abs_magnitude;
00155 if (abs_magnitude < min_magnitude)
00156 min_magnitude = abs_magnitude;
00157
00158
00159 unsigned char r, g, b, a;
00160
00161 f >> r;
00162 f >> g;
00163 f >> b;
00164 f >> a;
00165
00166
00167 float temp_color;
00168 unsigned char *color_ptr = reinterpret_cast<unsigned char *>(&temp_color);
00169 color_ptr[0] = r;
00170 color_ptr[1] = g;
00171 color_ptr[2] = b;
00172 color_ptr[3] = 255;
00173
00174 vertices[i*4+0] = temp_color;
00175 vertices[i*4+1] = galactic_pos.get_x();
00176 vertices[i*4+2] = galactic_pos.get_y();
00177 vertices[i*4+3] = galactic_pos.get_z();
00178 }
00179
00180
00181 float magnitude_range = max_magnitude - min_magnitude;
00182 for (int i = 0; i < num_stars; ++i)
00183 {
00184 float mag_diff = math::clamp(magnitudes[i] - min_magnitude, 0.0f, 5.0f);
00185 float mag_pct = 1.0f - (mag_diff / 5.0f);
00186
00187 unsigned char *color_ptr = reinterpret_cast<unsigned char *>(&vertices[i*4+0]);
00188 color_ptr[3] = static_cast<unsigned char>(mag_pct * 255.0f);
00189
00190
00191
00192
00193
00194
00195
00196
00197 }
00198
00199
00200 int num_star_names;
00201 f >> num_star_names;
00202
00203 for (int i = 0; i < num_star_names; ++i)
00204 {
00205 int star_id;
00206 f >> star_id;
00207
00208 string star_name;
00209 f >> star_name;
00210
00211 vector pos(vertices[(star_id-1)*4+1], vertices[(star_id-1)*4+2], vertices[(star_id-1)*4+3]);
00212 add_star_name(pos, star_name);
00213 }
00214
00215
00216 gsgl::real_t axis_dist = 100.0f;
00217
00218 add_star_name(vector(axis_dist, 0, 0), L"Galactic Center (+X)");
00219 add_star_name(vector(-axis_dist, 0, 0), L"Galactic -X");
00220
00221 add_star_name(vector(0, axis_dist, 0), L"Galactic +Y");
00222 add_star_name(vector(0, -axis_dist, 0), L"Galactic -Y");
00223
00224 add_star_name(vector(0, 0, axis_dist), L"Galactic North (+Z)");
00225 add_star_name(vector(0, 0, -axis_dist), L"Galactic South (-Z)");
00226 }
00227
00228
00229 void stellar_db::add_star_name(const vector & pos, const string & name)
00230 {
00231 star_name_vertices.append(pos.get_x());
00232 star_name_vertices.append(pos.get_y());
00233 star_name_vertices.append(pos.get_z());
00234 star_names.append(new string(name));
00235 }
00236
00237
00238
00239
00240 void stellar_db::init(context *c)
00241 {
00242 star_shader.load();
00243 star_shader.bind();
00244
00245 int fd_loc = glGetUniformLocation(star_shader.get_id(), "FarthestStarDistance"); CHECK_GL_ERRORS();
00246 if (fd_loc != GL_INVALID_VALUE)
00247 glUniform1f(fd_loc, farthest_distance * get_scale());
00248
00249 star_shader.unbind();
00250 }
00251
00252
00253 void stellar_db::cleanup(gsgl::scenegraph::context *c)
00254 {
00255 star_shader.unload();
00256 }
00257
00258
00259
00260 static float scale_factor = 1.0;
00261
00262
00263 void stellar_db::draw(context *c)
00264 {
00265
00266 glPushAttrib(GL_ALL_ATTRIB_BITS); CHECK_GL_ERRORS();
00267 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); CHECK_GL_ERRORS();
00268
00269 float star_scale = get_scale();
00270 float far_plane = farthest_distance * 1.5f * star_scale;
00271 float near_plane = nearest_distance * 0.5f * star_scale;
00272 if (near_plane <= 1)
00273 near_plane = 1;
00274
00275
00276 glMatrixMode(GL_PROJECTION); CHECK_GL_ERRORS();
00277 glLoadIdentity(); CHECK_GL_ERRORS();
00278 gluPerspective(c->cam->get_field_of_view(), c->screen->get_aspect_ratio(), near_plane, far_plane); CHECK_GL_ERRORS();
00279
00280
00281 glClearDepth(1); CHECK_GL_ERRORS();
00282 glClear(GL_DEPTH_BUFFER_BIT); CHECK_GL_ERRORS();
00283 glEnable(GL_DEPTH_TEST); CHECK_GL_ERRORS();
00284
00285 glEnable(GL_BLEND); CHECK_GL_ERRORS();
00286 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CHECK_GL_ERRORS();
00287
00288
00289 glEnable(GL_POINT_SMOOTH); CHECK_GL_ERRORS();
00290 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
00291 glPointSize(2.7f);
00292
00293 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); CHECK_GL_ERRORS();
00294 star_shader.bind();
00295
00296
00297 glMatrixMode(GL_MODELVIEW);
00298 glScalef(star_scale, star_scale, star_scale); CHECK_GL_ERRORS();
00299
00300 glEnableClientState(GL_VERTEX_ARRAY); CHECK_GL_ERRORS();
00301 glEnableClientState(GL_COLOR_ARRAY); CHECK_GL_ERRORS();
00302
00303 vertices.bind();
00304 glInterleavedArrays(GL_C4UB_V3F, 0, 0); CHECK_GL_ERRORS();
00305 glDrawArrays(GL_POINTS, 0, num_stars); CHECK_GL_ERRORS();
00306
00307
00308 star_shader.unbind();
00309 glPopClientAttrib(); CHECK_GL_ERRORS();
00310 glPopAttrib(); CHECK_GL_ERRORS();
00311
00312
00313 if ((c->render_flags & context::RENDER_LABELS))
00314 {
00315 font *label_font = dynamic_cast<space_context *>(c)->DEFAULT_LABEL_FONT;
00316
00317 c->screen->record_3d_text_info();
00318 c->screen->draw_text_start();
00319
00320 int i, len = star_names.size();
00321 for (i = 0; i < len; ++i)
00322 {
00323 vector pos(star_name_vertices[i*3+0]*star_scale, star_name_vertices[i*3+1]*star_scale, star_name_vertices[i*3+2]*star_scale);
00324 c->screen->draw_3d_text(pos, label_font, *star_names[i], 4, -8);
00325 }
00326
00327 c->screen->draw_text_stop();
00328 }
00329 };
00330
00331 }
00332
00333 }