/* view.cc This file is part of the Osirion project and is distributed under the terms and conditions of the GNU General Public License version 2 */ #include #include #include #include #include #include "client/client.h" #include "client/camera.h" #include "client/chat.h" #include "client/console.h" #include "client/input.h" #include "client/radar.h" #include "client/video.h" #include "render/draw.h" #include "render/render.h" #include "render/textures.h" #include "core/core.h" #include "core/stats.h" #include "math/mathlib.h" #include "sys/sys.h" namespace client { core::Cvar *draw_ui = 0; core::Cvar *draw_stats = 0; core::Cvar *cl_crosshaircolor = 0; core::Cvar *draw_radar = 0; namespace view { float fps = 0; void init() { camera::init(); draw_stats = core::Cvar::get("draw_stats", "0", core::Cvar::Archive); draw_stats->set_info("[bool] draw network and render statistics"); draw_ui = core::Cvar::get("draw_ui", "1", core::Cvar::Archive); draw_ui->set_info("[bool] draw the user interface"); draw_radar = core::Cvar::get("draw_radar", "1", core::Cvar::Archive); draw_radar->set_info("[bool] draw the radar view"); cl_crosshaircolor = core::Cvar::get("cl_crosshaircolor", "1 1 1", core::Cvar::Archive); cl_crosshaircolor->set_info("[r g b] crosshairs color"); } void shutdown() { camera::shutdown(); } void reset() { using namespace render; // set clear color gl::clearcolor(0.0f, 0.0f, 0.0f, 1.0f); // shading model: Gouraud (smooth, the default) gl::shademodel(GL_SMOOTH); //gl::shademodel(GL_FLAT); // load identity matrices gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); // lighting GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat ambient_light[] = { 0.01f, 0.01f, 0.01f, 1.0f }; GLfloat diffuse_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; GLfloat specular_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_light); glLightfv(GL_LIGHT0, GL_SPECULAR, specular_light); // color tracking glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); GLfloat specular_reflectance[] = { 0.2f, 0.2f, 0.2f, 1.0f }; glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflectance); glMateriali(GL_FRONT, GL_SHININESS, 128); // shininess 1-128 gl::disable(GL_LIGHTING); gl::enable(GL_LIGHT0); gl::disable(GL_COLOR_MATERIAL); // culling gl::cullface(GL_BACK); gl::frontface(GL_CCW); gl::disable(GL_CULL_FACE); // depth gl::depthmask(GL_TRUE); gl::disable(GL_DEPTH_TEST); // alpha-blending gl::blendfunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl::enable(GL_BLEND); // client state } void draw_loader() { using namespace render; render::Textures::bind("bitmaps/loader"); gl::color(1.0f, 1.0f, 1.0f, 1.0f); gl::begin(gl::Quads); glTexCoord2f(0.0f, 0.0f); gl::vertex(0,0, 0); glTexCoord2f(1.0f, 0.0f); gl::vertex(video::width,0,0); glTexCoord2f(1.0f, 1.0f); gl::vertex(video::width,video::height,0); glTexCoord2f(0.0f, 1.0f); gl::vertex(0,video::height,0); gl::end(); } void draw_status() { using namespace render; if (console()->visible()) return; // print the status in the upper left corner std::stringstream status; if (core::game()) { int minutes = (int) floorf(core::game()->clientframetime() / 60.0f); int seconds = (int) floorf( core::game()->clientframetime() - (float) minutes* 60.0f); status << "^Ntime ^B" << std::setfill('0') << std::setw(2) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; Text::draw(video::width-Text::fontwidth()*11-4, 4+Text::fontheight(), status); } // print stats if desired if (draw_stats && draw_stats->value()) { std::stringstream stats; stats << "^Nfps ^B" << std::setw(6) << fps << "\n"; if (core::application()->connected()) { stats << "^Ntris ^B" << std::setw(5) << render::Stats::tris << "\n"; stats << "^Nquads ^B" << std::setw(5) << render::Stats::quads << "\n"; } stats << "^Ntx ^B"<< std::setw(5) << (core::Stats::network_bytes_sent >> 10) << "\n"; stats << "^Nrx ^B"<< std::setw(5) << (core::Stats::network_bytes_received >> 10) << "\n"; Text::draw(video::width-Text::fontwidth()*11-4, 4 + Text::fontheight()*3, stats); } // draw a basic HUD if (core::localcontrol()) { status.str(""); status << "^Nthrust ^B" << std::setfill(' ') << std::setw(5) << std::fixed << std::setprecision(2) << core::localcontrol()->thrust() << " "; status << "^Nspeed ^B" << std::setfill(' ') << std::setw(5) << std::fixed << std::setprecision(2) << core::localcontrol()->speed(); Text::draw(4, video::height - Text::fontheight() -4, status); } } void draw_cursor() { if (!core::localcontrol() || console()->visible()) return; float crosshair_size = 48.0f; float x = input::mouse_x - (crosshair_size /2); float y = input::mouse_y - (crosshair_size /2); using namespace render; render::Textures::bind("bitmaps/crosshair"); math::Color color; if (cl_crosshaircolor && cl_crosshaircolor->value()) { std::stringstream colorstr(cl_crosshaircolor->str()); colorstr >> color; } if (cl_mousecontrol->value() && input::mouse_deadzone) color.a = 0.3f; else color.a = 0.5f; gl::color(color); gl::begin(gl::Quads); glTexCoord2f(0,0 ); gl::vertex(x,y,0.0f); glTexCoord2f(1, 0); gl::vertex(x+crosshair_size, y, 0.0f); glTexCoord2f(1, 1); gl::vertex(x+crosshair_size, y+crosshair_size, 0.0f); glTexCoord2f(0, 1); gl::vertex(x, y+crosshair_size, 0.0f); gl::end(); } void frame(float seconds) { using namespace render; // calculate frames per second if (seconds > 0.0f) fps = floorf(1.0f / seconds); else fps = 9999; // flush console messages console()->flush(); // Clear the color and depth buffers. gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (core::application()->connected() && core::game()->serverframetime()) { // Change to the projection matrix and set our viewing volume. gl::matrixmode(GL_PROJECTION); gl::loadidentity(); // FIXME width must always be one const float frustumsize = .5f; gl::frustum(-frustumsize*video::aspect, frustumsize*video::aspect, -frustumsize, frustumsize, 1.0f, 1024.0f); gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); camera::draw(seconds); // draw the current camera transformation render::draw(camera::axis, camera::eye, camera::target, seconds); // draw the world } // switch to ortographic projection to draw the GUI gl::matrixmode(GL_PROJECTION); gl::loadidentity(); glOrtho(0, video::width, video::height, 0, -1000.0f, 1000.0f); gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); gl::enable(GL_TEXTURE_2D); if (!core::application()->connected()) { // draw the loader bitmap draw_loader(); } // draw text elements Text::setfont("bitmaps/fonts/console", 12, 18); console()->draw(); chat::draw(); if (draw_radar->value()) { Radar::draw(); } if (draw_ui->value()) { Text::setfont("bitmaps/fonts/gui", 16, 24); draw_status(); // draw the mouse cursor draw_cursor(); } gl::disable(GL_TEXTURE_2D); } } //namespace view } // namespace client