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/large_lithosphere.hpp"
00035 #include "space/celestial_body.hpp"
00036
00037 #include "data/pointer.hpp"
00038 #include "math/units.hpp"
00039 #include "platform/texture.hpp"
00040 #include "scenegraph/camera.hpp"
00041 #include "framework/application.hpp"
00042
00043 using namespace gsgl;
00044 using namespace gsgl::data;
00045 using namespace gsgl::math;
00046 using namespace gsgl::scenegraph;
00047 using namespace gsgl::platform;
00048
00049 namespace periapsis
00050 {
00051
00052 namespace space
00053 {
00054
00055
00056 class lithosphere_quadtree
00057 : public spherical_quadtree
00058 {
00059
00060
00061 gsgl::data::shared_pointer<gsgl::platform::shader_program> shader;
00062
00063 public:
00064 lithosphere_quadtree(large_lithosphere *parent_sg_node, const gsgl::real_t & polar_radius, const gsgl::real_t & equatorial_radius);
00065 virtual ~lithosphere_quadtree();
00066
00067 shader_program *get_shader() { return shader; }
00068
00069 virtual void init(gsgl::scenegraph::context *c);
00070 virtual void draw(gsgl::scenegraph::context *c);
00071 virtual void cleanup();
00072
00073 virtual sph_qt_node *create_node(sph_qt_node *parent);
00074 };
00075
00076
00077
00078 class lithosphere_qt_node
00079 : public sph_qt_node
00080 {
00081 gsgl::platform::texture *own_texture;
00082 gsgl::platform::texture *current_texture;
00083
00084
00085
00086 gsgl::real_t texture_bounds[4];
00087
00088 gsgl::platform::texture *own_heightmap;
00089 gsgl::platform::texture *current_heightmap;
00090
00091 gsgl::real_t heightmap_bounds[4];
00092
00093 friend class lithosphere_quadtree;
00094
00095 public:
00096 lithosphere_qt_node(lithosphere_quadtree *parent_quadtree, sph_qt_node *parent);
00097 virtual ~lithosphere_qt_node();
00098
00099 virtual void draw(gsgl::scenegraph::context *c);
00100 };
00101
00102
00103 lithosphere_qt_node::lithosphere_qt_node(lithosphere_quadtree *parent_quadtree, sph_qt_node *parent)
00104 : sph_qt_node(parent_quadtree, parent),
00105 own_texture(0), current_texture(0),
00106 own_heightmap(0), current_heightmap(0)
00107 {
00108 lithosphere_qt_node *pqn = dynamic_cast<lithosphere_qt_node *>(parent);
00109
00110 if (pqn)
00111 {
00112
00113 current_texture = pqn->current_texture;
00114
00115 for (int i = 0; i < 4; ++i)
00116 texture_bounds[i] = pqn->texture_bounds[i];
00117 }
00118 }
00119
00120
00121 lithosphere_qt_node::~lithosphere_qt_node()
00122 {
00123 }
00124
00125
00126 void lithosphere_qt_node::draw(gsgl::scenegraph::context *c)
00127 {
00128 lithosphere_quadtree *lqt = dynamic_cast<lithosphere_quadtree *>(parent_quadtree);
00129 assert(lqt->get_shader());
00130
00131 if (current_texture)
00132 {
00133 current_texture->bind();
00134 lqt->get_shader()->set_uniform("TextureBounds", texture_bounds);
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 sph_qt_node::draw(c);
00156 }
00157
00158
00159
00160
00161 static shared_pointer<shader_program> *first_shader_instance = 0;
00162
00163
00164 lithosphere_quadtree::lithosphere_quadtree(periapsis::space::large_lithosphere *parent_sg_node, const gsgl::real_t & polar_radius, const gsgl::real_t & equatorial_radius)
00165 : spherical_quadtree(parent_sg_node, polar_radius, equatorial_radius), shader(first_shader_instance ? *first_shader_instance : 0)
00166 {
00167 if (!first_shader_instance)
00168 {
00169 shader = new shader_program();
00170 shader->add_vertex_shader(gsgl::framework::application::SYS_DATA_PATH + L"Shaders" + io::directory::SEPARATOR + L"lithosphere_vertex_shader.glsl");
00171 first_shader_instance = &shader;
00172 }
00173 }
00174
00175
00176 lithosphere_quadtree::~lithosphere_quadtree()
00177 {
00178 }
00179
00180
00181 void lithosphere_quadtree::init(gsgl::scenegraph::context *c)
00182 {
00183 shader->load();
00184
00185 spherical_quadtree::init(c);
00186
00187
00188 lithosphere *ls = dynamic_cast<lithosphere *>(parent_sg_node);
00189 if (ls)
00190 {
00191 const celestial_body *cb = ls->get_parent_body();
00192 assert(cb);
00193
00194 for (int i = 0; i < 6; ++i)
00195 {
00196 lithosphere_qt_node *q = dynamic_cast<lithosphere_qt_node *>(root_nodes[i]);
00197 if (q)
00198 {
00199
00200 q->current_texture = const_cast<texture *>(cb->get_simple_colormap());
00201
00202 gsgl::real_t lon_offset = cb->get_simple_color_x_offset();
00203 q->texture_bounds[0] = 0 + lon_offset;
00204 q->texture_bounds[2] = 1 + lon_offset;
00205
00206 gsgl::real_t lat_offset = cb->get_simple_color_y_offset();
00207 q->texture_bounds[1] = 0 + lat_offset;
00208 q->texture_bounds[3] = 1 + lat_offset;
00209
00210
00211 q->current_heightmap = const_cast<texture *>(cb->get_simple_heightmap());
00212
00213 lon_offset = cb->get_simple_height_x_offset();
00214 q->heightmap_bounds[0] = 0 + lon_offset;
00215 q->heightmap_bounds[2] = 1 + lon_offset;
00216
00217 lat_offset = cb->get_simple_height_y_offset();
00218 q->heightmap_bounds[1] = 0 + lat_offset;
00219 q->heightmap_bounds[3] = 1 + lat_offset;
00220 }
00221 }
00222 }
00223 }
00224
00225
00226 void lithosphere_quadtree::draw(gsgl::scenegraph::context *c)
00227 {
00228 shader->bind();
00229 shader->set_uniform("NumLights", c->num_lights);
00230 spherical_quadtree::draw(c);
00231 shader->unbind();
00232 }
00233
00234
00235 void lithosphere_quadtree::cleanup()
00236 {
00237 shader->unload();
00238 }
00239
00240
00241 sph_qt_node *lithosphere_quadtree::create_node(sph_qt_node *parent)
00242 {
00243 return new lithosphere_qt_node(this, parent);
00244 }
00245
00246
00247
00248
00249 large_lithosphere::large_lithosphere(const string & name, node *parent, body_rotator *rotator)
00250 : lithosphere(name, parent, rotator), quadtree(0)
00251 {
00252 assert(get_parent_body());
00253 quadtree = new lithosphere_quadtree(this, get_parent_body()->get_polar_radius(), get_parent_body()->get_equatorial_radius());
00254 }
00255
00256
00257 large_lithosphere::~large_lithosphere()
00258 {
00259 delete quadtree;
00260 }
00261
00262
00263 gsgl::real_t large_lithosphere::get_priority(context *c)
00264 {
00265
00266 return node::NODE_DRAW_IGNORE;
00267 }
00268
00269
00270 gsgl::real_t large_lithosphere::max_extent() const
00271 {
00272 assert(get_parent());
00273 return get_parent()->max_extent();
00274 }
00275
00276
00277 gsgl::real_t large_lithosphere::default_view_distance() const
00278 {
00279 assert(get_parent());
00280 return get_parent()->default_view_distance();
00281 }
00282
00283
00284 gsgl::real_t large_lithosphere::minimum_view_distance() const
00285 {
00286 assert(get_parent());
00287 return get_parent()->minimum_view_distance();
00288 }
00289
00290
00291 void large_lithosphere::init(context *c)
00292 {
00293 quadtree->init(c);
00294 }
00295
00296
00297 void large_lithosphere::draw(context *c)
00298 {
00299
00300 quadtree->draw(c);
00301 }
00302
00303
00304 void large_lithosphere::update(context *c)
00305 {
00306
00307 lithosphere::update(c);
00308
00309
00310 if (utils::is_on_screen(this, c->cam->get_field_of_view(), c->screen->get_aspect_ratio(), vector::ZERO, max_extent())
00311 && utils::pixel_size((get_modelview() * vector::ZERO).mag(), max_extent(), c->cam->get_field_of_view(), c->screen->get_height()) > celestial_body::MIN_PIXEL_WIDTH)
00312 {
00313 assert(get_parent_body());
00314 quadtree->update(c, (get_parent_body()->get_draw_results() & (node::NODE_DREW_POINT & node::NODE_OFF_SCREEN)) != 0);
00315 }
00316 }
00317
00318
00319 void large_lithosphere::cleanup(context *c)
00320 {
00321 quadtree->cleanup();
00322 }
00323
00324
00325 }
00326
00327
00328 }