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/celestial_body.hpp"
00035 #include "space/space_context.hpp"
00036
00037 #include "math/units.hpp"
00038 #include "scenegraph/camera.hpp"
00039 #include "platform/lowlevel.hpp"
00040
00041 using namespace gsgl;
00042 using namespace gsgl::data;
00043 using namespace gsgl::math;
00044 using namespace gsgl::scenegraph;
00045 using namespace gsgl::platform;
00046
00047 namespace periapsis
00048 {
00049
00050 namespace space
00051 {
00052
00053 config_variable<gsgl::real_t> celestial_body::MIN_PIXEL_WIDTH(L"space/celestial_body/min_pixel_width", 1.7f);
00054
00055
00056 celestial_body::celestial_body(const config_record & obj_config)
00057 : orbital_frame(obj_config),
00058 mass(1), polar_radius(1), equatorial_radius(1),
00059 rotating_frame(0), atmo_child(0), litho_child(0),
00060 simple_colormap(0), simple_color_x_offset(0), simple_color_y_offset(0),
00061 simple_heightmap(0), simple_height_x_offset(0), simple_height_y_offset(0), simple_height_max(0),
00062 sphere(0)
00063 {
00064 mass = units::parse(obj_config[L"mass"]); assert(mass > 0);
00065 polar_radius = units::parse(obj_config[L"polar_radius"]); assert(polar_radius > 0);
00066 equatorial_radius = units::parse(obj_config[L"equatorial_radius"]); assert(equatorial_radius > 0);
00067
00068 if (!obj_config[L"simple_map"].is_empty())
00069 simple_colormap = new gsgl::platform::texture(obj_config.get_directory().get_full_path() + obj_config[L"simple_map"], TEXTURE_ENV_MODULATE);
00070
00071 if (simple_colormap)
00072 {
00073 simple_color_x_offset = static_cast<gsgl::real_t>(obj_config[L"simple_map_x_offset"].to_double());
00074 simple_color_y_offset = static_cast<gsgl::real_t>(obj_config[L"simple_map_y_offset"].to_double());
00075
00076 sphere = new utils::simple_sphere(this, 32, equatorial_radius, polar_radius, simple_colormap, simple_color_x_offset, simple_color_y_offset);
00077 }
00078
00079 if (!obj_config[L"simple_height"].is_empty())
00080 simple_heightmap = new gsgl::platform::texture(obj_config.get_directory().get_full_path() + obj_config[L"simple_height"], TEXTURE_ENV_MODULATE, TEXTURE_HEIGHTMAP, 1);
00081
00082 if (simple_heightmap)
00083 {
00084 simple_height_x_offset = static_cast<gsgl::real_t>(obj_config[L"simple_height_x_offset"].to_double());
00085 simple_height_y_offset = static_cast<gsgl::real_t>(obj_config[L"simple_height_y_offset"].to_double());
00086 simple_height_max = static_cast<gsgl::real_t>(obj_config[L"simple_height_max"].to_double());
00087 }
00088 }
00089
00090
00091 celestial_body::~celestial_body()
00092 {
00093 delete sphere;
00094 delete simple_colormap;
00095 delete simple_heightmap;
00096 }
00097
00098
00099 gsgl::real_t celestial_body::max_extent() const
00100 {
00101 return gsgl::max_val(polar_radius, equatorial_radius);
00102 }
00103
00104
00105 gsgl::real_t celestial_body::default_view_distance() const
00106 {
00107 return max_extent() * 3;
00108 }
00109
00110
00111 gsgl::real_t celestial_body::minimum_view_distance() const
00112 {
00113 return max_extent();
00114 }
00115
00116
00117 gsgl::real_t celestial_body::get_priority(gsgl::scenegraph::context *)
00118 {
00119 return utils::pos_in_eye_space(this).mag2();
00120 }
00121
00122
00123 void celestial_body::init(context *c)
00124 {
00125 if (sphere)
00126 sphere->init(c);
00127
00128
00129 }
00130
00131
00132 void celestial_body::draw(context *c)
00133 {
00134 glPushAttrib(GL_ALL_ATTRIB_BITS); CHECK_GL_ERRORS();
00135 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); CHECK_GL_ERRORS();
00136
00137
00138 vector ep = utils::pos_in_eye_space(this);
00139
00140 gsgl::real_t radius = gsgl::max_val(get_polar_radius(), get_equatorial_radius());
00141 gsgl::real_t dist = ep.mag();
00142 gsgl::real_t zdist = -ep.get_z();
00143 gsgl::real_t far_plane = zdist + (radius * 1.1f);
00144 gsgl::real_t near_plane = zdist - (radius * 1.1f);
00145 if (near_plane <= 0)
00146 near_plane = 1;
00147
00148 glMatrixMode(GL_PROJECTION); CHECK_GL_ERRORS();
00149 glLoadIdentity(); CHECK_GL_ERRORS();
00150 gluPerspective(c->cam->get_field_of_view(), c->screen->get_aspect_ratio(), near_plane, far_plane); CHECK_GL_ERRORS();
00151
00152
00153 gsgl::real_t screen_width = utils::pixel_size(dist, radius, c->cam->get_field_of_view(), c->screen->get_height());
00154
00155 color::WHITE.set();
00156
00157 if (screen_width < MIN_PIXEL_WIDTH)
00158 {
00159 get_draw_results() |= node::NODE_DREW_POINT;
00160 draw_point(MIN_PIXEL_WIDTH);
00161 }
00162 else
00163 {
00164 utils::simple_sphere *sph = get_simple_sphere();
00165
00166 if (sph)
00167 {
00168
00169 rotating_body *rb = get_rotating_frame();
00170
00171 if (rb)
00172 {
00173 glMatrixMode(GL_MODELVIEW);
00174 glPushMatrix();
00175 glLoadMatrixf(rb->get_modelview().ptr());
00176 }
00177
00178 glClearDepth(1); CHECK_GL_ERRORS();
00179 glClear(GL_DEPTH_BUFFER_BIT); CHECK_GL_ERRORS();
00180 glEnable(GL_DEPTH_TEST); CHECK_GL_ERRORS();
00181
00182 glEnable(GL_CULL_FACE); CHECK_GL_ERRORS();
00183 glPolygonMode(GL_FRONT_AND_BACK, (c->render_flags & context::RENDER_WIREFRAME) ? GL_LINE : GL_FILL); CHECK_GL_ERRORS();
00184
00185
00186 if (!(c->render_flags & context::RENDER_UNLIT) && !(get_draw_flags() & NODE_DRAW_UNLIT))
00187 {
00188 glEnable(GL_LIGHTING); CHECK_GL_ERRORS();
00189
00190 glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); CHECK_GL_ERRORS();
00191 glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); CHECK_GL_ERRORS();
00192
00193
00194 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color::WHITE.get_val()); CHECK_GL_ERRORS();
00195 glMaterialfv(GL_FRONT, GL_SPECULAR, color::BLACK.get_val()); CHECK_GL_ERRORS();
00196 glMaterialfv(GL_FRONT, GL_EMISSION, color::BLACK.get_val()); CHECK_GL_ERRORS();
00197 glMaterialf(GL_FRONT, GL_SHININESS, 8); CHECK_GL_ERRORS();
00198 }
00199
00200 sph->draw(c);
00201
00202 if (rb)
00203 {
00204 glMatrixMode(GL_MODELVIEW);
00205 glPopMatrix();
00206 }
00207 }
00208 }
00209
00210
00211 glPopClientAttrib(); CHECK_GL_ERRORS();
00212 glPopAttrib(); CHECK_GL_ERRORS();
00213
00214
00215 draw_name(c, 1, far_plane);
00216 }
00217
00218
00219 void celestial_body::draw_point(float width)
00220 {
00221 glPushAttrib(GL_ALL_ATTRIB_BITS); CHECK_GL_ERRORS();
00222 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); CHECK_GL_ERRORS();
00223
00224 glEnable(GL_BLEND); CHECK_GL_ERRORS();
00225 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CHECK_GL_ERRORS();
00226
00227 glEnable(GL_POINT_SMOOTH); CHECK_GL_ERRORS();
00228 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); CHECK_GL_ERRORS();
00229 glPointSize(width); CHECK_GL_ERRORS();
00230
00231 glBegin(GL_POINTS);
00232 glVertex3f(0, 0, 0);
00233 glEnd(); CHECK_GL_ERRORS();
00234
00235 glPopClientAttrib(); CHECK_GL_ERRORS();
00236 glPopAttrib(); CHECK_GL_ERRORS();
00237 }
00238
00239
00240 void celestial_body::draw_name(context *c, gsgl::real_t near_plane, gsgl::real_t far_plane)
00241 {
00242 if ((c->render_flags & context::RENDER_LABELS) && !get_name().is_empty())
00243 {
00244 glPushAttrib(GL_ALL_ATTRIB_BITS); CHECK_GL_ERRORS();
00245 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); CHECK_GL_ERRORS();
00246
00247 gsgl::platform::font *label_font = dynamic_cast<space_context *>(c)->DEFAULT_LABEL_FONT;
00248
00249 glMatrixMode(GL_PROJECTION); CHECK_GL_ERRORS();
00250 glLoadIdentity(); CHECK_GL_ERRORS();
00251 gluPerspective(c->cam->get_field_of_view(), c->screen->get_aspect_ratio(), near_plane, far_plane); CHECK_GL_ERRORS();
00252
00253 c->screen->record_3d_text_info();
00254 c->screen->draw_text_start();
00255 c->screen->draw_3d_text(vector::ZERO, label_font, get_name(), 4, -8);
00256 c->screen->draw_text_stop();
00257
00258 glPopClientAttrib(); CHECK_GL_ERRORS();
00259 glPopAttrib(); CHECK_GL_ERRORS();
00260 }
00261 }
00262
00263
00264 }
00265
00266 }