/* 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/video.h" #include "render/draw.h" #include "render/render.h" #include "core/core.h" #include "math/mathlib.h" #include "sys/sys.h" namespace client { namespace view { float fps = 0; void init() { camera::init(); } 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); // lighting GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat ambient_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; GLfloat diffuse_light[] = { 0.4f, 0.4f, 0.4f, 1.0f }; GLfloat specular_light[] = { 0.4f, 0.4f, 0.4f, 1.0f }; GLfloat specular_reflectance[] = { 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); 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; gl::enable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, render::textures[0]); // bitmaps/loader.tga 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(); gl::disable(GL_TEXTURE_2D); } void draw_status() { using namespace render; if (console::visible()) return; glBindTexture(GL_TEXTURE_2D, render::textures[1]); // bitmaps/conchars.tga gl::enable(GL_TEXTURE_2D); // print the status in the upper left corner gl::color(1.0f, 1.0f, 1.0f, 1.0f); std::stringstream status; int hours = (int) sys::time() / 3600; int minutes = (int)(sys::time() - 3600*hours) / 60; int seconds = (int)(sys::time() - 3600*hours - 60 *minutes); status << "clock " << std::setfill('0') << std::setw(2) << hours << ":" << std::setfill('0') << std::setw(2) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; minutes = (int) floorf(core::application()->time() / 60.0f); seconds = (int) floorf(core::application()->time() - (float) minutes* 60.0f); status << " time " << std::setfill('0') << std::setw(2) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; draw_text(CHARWIDTH, 4, status); // print stats if desired if (render::r_drawstats && render::r_drawstats->value()) { std::stringstream stats; stats << "fps " << std::setw(6) << fps << "\n"; stats << "tris " << std::setw(6) << render::Stats::tris << "\n"; stats << "spheres " << std::setw(4) << render::Stats::spheres << "\n"; draw_text(video::width-CHARWIDTH*13, CHARHEIGHT*3, stats); } // print the version number in the upper right corner gl::color(0.0f, 1.0f, 0.0f, 1.0f); std::string version("ver. "); version.append(core::version()); draw_text(video::width-(version.size()+1)*CHARWIDTH, 4, version); // draw notifications gl::color(1.0f, 1.0f, 1.0f, 1.0f); size_t n = console::notify_pos % MAXNOTIFYLINES; float now = sys::time(); int h = 4 + CHARHEIGHT; for (size_t l = 0; l < MAXNOTIFYLINES; l++) { if (console::notify_text[n].size() > 2 && console::notify_time[n] + 4 > now) { if (console::notify_text[n][0] == '?') gl::color(0.7f,0.7f,0.7f, 1.0f); else if (console::notify_text[n][0] == '*') gl::color(1.0f,1.0f,0.0f, 1.0f); else if (console::notify_text[n][0] == '!') gl::color(1.0f,0.0f,0.0f, 1.0f); else gl::color(1.0f,1.0f,1.0f, 1.0f); draw_text(CHARWIDTH, h, console::notify_text[n].substr(2)); h += CHARHEIGHT; } n = (n+1) % MAXNOTIFYLINES; } // draw a basic HUD if (core::localcontrol()) { status.str(""); status << " dir " << std::setfill('0') << std::setw(3) << roundf(core::localcontrol()->direction()) << " speed " << std::setfill(' ') << std::setw(5) << std::fixed << std::setprecision(2) << core::localcontrol()->speed(); draw_text(CHARWIDTH, video::height - CHARHEIGHT -4, status); } gl::disable(GL_TEXTURE_2D); } 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()) { // 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 = 0.5f; gl::frustum(-frustumsize*video::aspect, frustumsize*video::aspect, -frustumsize, frustumsize, 1.0f, 1024.0f); gl::matrixmode(GL_MODELVIEW); // map world to screen coordinates gl::loadidentity(); camera::draw(seconds); // draw the current camera transformation render::draw(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(); if (!core::application()->connected()) { // draw the loader bitmap draw_loader(); } // draw the console console::draw(); chat::draw(); // draw the status line draw_status(); } } //namespace view } // namespace client