// // Handle rendering of sky // // Copyright (C) J. Belson 2001.12.08 // // $Author: jon $ : $Date: 2003/10/11 18:11:00 $ // #include #include #include #include "handler_sky.h" #include "hf_skydome.h" #include "perlin.h" #include "point2d.h" #include "procedural.h" #include "skylight.h" #include "texture_cloud.h" #include "texture_skydome.h" #include "texture_skylight.h" #include "triangle3d.h" using namespace std; /** * Constructor */ handler_sky::handler_sky(int w, int h, const render_info& info) : handler_base(w, h, info), first(true) { skydome = new hf_skydome(); my_settings->get_colour(SKY_HORIZON_COLOUR, &horizon_colour); my_settings->get_colour(SKY_ZENITH_COLOUR, &zenith_colour); my_settings->get_bool(SKY_REALISTIC, &realistic_sky); sun_pos = calc_sun_pos(); if (realistic_sky) { textset_skylight ts; ts.sun_direction = -light; ts.sun_direction.normalise(); sky = new texture_skylight(ts); } else { textset ts; ts.bg = zenith_colour; ts.fg = horizon_colour; sky = new texture_skydome(ts); } textset_cloud ts; textset_cloud::load_settings(ts); cloud = new texture_cloud(ts); } /** * Destructor */ handler_sky::~handler_sky() { rinfo.prog->update_status(); delete skydome; delete tex; delete sky; delete cloud; } /** * Calculate height for specified point */ float handler_sky::get_height(float x, float y) { return skydome->get_height(x, y); } /** * Pass quad patch through render pipeline */ void handler_sky::process_patch(const point3d& p1, const point3d& p2, const point3d& p3, const point3d& p4) { point3d points[4]; points[0] = p1; points[1] = p2; points[2] = p3; points[3] = p4; for (int i=0; i<4; i++) { float x = points[i].x; float z = points[i].z; points[i].y = skydome->get_height(x, z); } // Our triangle patch... triangle3d triangle[2] = { triangle3d(0, 1, 2), triangle3d(0, 2, 3)}; for (int tri=0; tri<2; tri++) { triangle[tri].calculate_normal(points); fcolour col; point3d p = triangle[tri].find_centre(points); // Get skydome colour for specified point col = get_colour(p); triangle[tri].set_colour(col); triangle[tri].normal = vector3d(0, -1, 0); } static int num_tri = 0; // Translate/rotate transform(points, 4); // Do perspective transform... point2d pnt2d[4]; perspective(points, pnt2d, 4); transform_normals(triangle, 2); vector3d dummy[4]; // Render the strip... rinfo.rend->setup( triangle, pnt2d, dummy, 2, rinfo.fbuffer, rinfo.bytes_per_row, scene_width, scene_height, rinfo.zb); rinfo.rend->do_render(); num_tri+=2; // Aaarrggghhhh!!!!!! if (num_tri%100 == 0) { rinfo.prog->update_status(); if (rinfo.prog->cancelled()) { set_cancelled(); } } } /** * Calculate skydome colour at specified point */ fcolour handler_sky::get_colour(const point3d& p) { // Get colour for this point fcolour colour; colour = sky->colour(p.x, p.z, p.y); if (!realistic_sky) { #if 0 ////////////////////////// // Quick hack - try and add a glow from the sun static const float corona = 200; static const float disk = 20.0; static const float gain = 12.0; vector3d v = sun_pos - p; float dist = v.magnitude(); float glow = 0.0; if (dist < disk) { glow = 1.0; } else { glow = expf(-dist/(corona/12)); } glow *= 8; colour = colour + fcolour(glow, glow, glow); ////////////////////////// #endif } colour.alpha = 1.0; // Now add clouds. fcolour col2 = cloud->colour(p.x, p.z, p.y); colour = colour.blend(col2); //colour = col2; return colour; } /** * Calculate sun position from light vector */ point3d handler_sky::calc_sun_pos(void) { point3d p = viewpoint; vector3d vec = -light; bool found; found = skydome->trace_path(p, vec); if (!found) { cout << "sun not found on skydome!" << endl; } return p; } /** * Render skydome */ void handler_sky::render(void) { int terrain_width = skydome->get_width(); subdivide(-terrain_width/2, -terrain_width/2, terrain_width, 0, 0, 0, 0); }