/* Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc. and the "Aleph One" developers. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This license is contained in the file "COPYING", which is included with this source code; it is available online at http://www.gnu.org/licenses/gpl.html */ /* * HUDRenderer_OGL.cpp - HUD rendering using OpenGL * * Written in 2001 by Christian Bauer */ #include "HUDRenderer_OGL.h" #ifdef HAVE_OPENGL #include "FontHandler.h" #include "game_window.h" #include "screen_definitions.h" #include "images.h" #include "render.h" #include "scottish_textures.h" #include "OGL_Setup.h" #include "OGL_Textures.h" #ifdef HAVE_OPENGL # if defined (__APPLE__) && defined (__MACH__) # include # elif defined mac # include # else # include # endif #endif #include #if defined(__WIN32__) || defined(__MINGW32__) #undef DrawText #endif extern bool MotionSensorActive; // Rendering object static HUD_OGL_Class HUD_OGL; // MacOS HUD Buffer; defined in screen.cpp #if defined(mac) extern GWorldPtr HUD_Buffer; #endif /* * Draws the entire interface using OpenGL */ // We are using 6 textures to render the 640x160 pixel HUD: // // 256 256 128 // +--------+--------+----+ // | 0 | 1 | 2 | 128 // | | | | // +--------+--------+----+ // | 3 | 4 | 5 | 32 // +--------+--------+----+ const int NUM_TEX = 6; static GLuint txtr_id[NUM_TEX]; static bool hud_pict_loaded = false; // HUD backdrop picture loaded and ready static bool hud_pict_not_found = false; // HUD backdrop picture not found, don't try again to load it void OGL_DrawHUD(Rect &dest, short time_elapsed) { static const int txtr_width[NUM_TEX] = {256, 256, 128, 256, 256, 128}; static const int txtr_height[NUM_TEX] = {128, 128, 128, 32, 32, 32}; static const int txtr_x[NUM_TEX] = {0, 256, 512, 0, 256, 512}; static const int txtr_y[NUM_TEX] = {0, 0, 0, 128, 128, 128}; if(hud_pict_loaded && time_elapsed == NONE) { glDeleteTextures(NUM_TEX, txtr_id); hud_pict_loaded= false; } // Load static HUD picture if necessary if (!hud_pict_loaded && !hud_pict_not_found) { LoadedResource PictRsrc; if (get_picture_resource_from_images(INTERFACE_PANEL_BASE, PictRsrc)) hud_pict_loaded = true; else hud_pict_not_found = true; if (hud_pict_loaded) { uint8 *txtr_data[NUM_TEX]; for (int i=0; ipixels + txtr_y[i] * hud_pict_rgb->pitch) + txtr_x[i]; uint8 *q = txtr_data[i]; for (int y=0; y> 16; *q++ = v >> 8; *q++ = v; *q++ = 0xff; } p = (uint32 *)((uint8 *)p + hud_pict_rgb->pitch); } } SDL_FreeSurface(hud_pict_rgb); } SDL_FreeSurface(hud_pict); } #endif glGenTextures(NUM_TEX, txtr_id); for (int i=0; iwidth, orig_height = TMgr.Texture->height; int x = dest->left, y = dest->top; int width = dest->right - dest->left, height = dest->bottom - dest->top; GLdouble U_Scale = TMgr.U_Scale * (src->right - src->left) / orig_width; GLdouble V_Scale = TMgr.V_Scale * (src->bottom - src->top) / orig_height; GLdouble U_Offset = TMgr.U_Offset + TMgr.U_Scale * src->left / orig_width; GLdouble V_Offset = TMgr.V_Offset + TMgr.V_Scale * src->top / orig_height; // Draw shape glColor3f(1.0, 1.0, 1.0); glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); TMgr.SetupTextureMatrix(); TMgr.RenderNormal(); glBegin(GL_TRIANGLE_FAN); glTexCoord2d(U_Offset, V_Offset); glVertex2i(x, y); glTexCoord2d(U_Offset + U_Scale, V_Offset); glVertex2i(x + width, y); glTexCoord2d(U_Offset + U_Scale, V_Offset + V_Scale); glVertex2i(x + width, y + height); glTexCoord2d(U_Offset, V_Offset + V_Scale); glVertex2i(x, y + height); glEnd(); TMgr.RestoreTextureMatrix(); } void HUD_OGL_Class::DrawShapeAtXY(shape_descriptor shape, short x, short y, bool transparency) { // Set up texture TextureManager TMgr; TMgr.ShapeDesc = shape; get_shape_bitmap_and_shading_table(shape, &TMgr.Texture, &TMgr.ShadingTables, _shading_normal); TMgr.IsShadeless = true; TMgr.TransferMode = _shadeless_transfer; TMgr.TextureType = OGL_Txtr_WeaponsInHand; if (!TMgr.Setup()) return; // Get dimensions int width = TMgr.Texture->width, height = TMgr.Texture->height; GLdouble U_Scale = TMgr.U_Scale; GLdouble V_Scale = TMgr.V_Scale; GLdouble U_Offset = TMgr.U_Offset; GLdouble V_Offset = TMgr.V_Offset; // Draw shape glColor3f(1.0, 1.0, 1.0); glEnable(GL_TEXTURE_2D); if (transparency) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else glDisable(GL_BLEND); TMgr.SetupTextureMatrix(); TMgr.RenderNormal(); glBegin(GL_TRIANGLE_FAN); glTexCoord2d(U_Offset, V_Offset); glVertex2i(x, y); glTexCoord2d(U_Offset + U_Scale, V_Offset); glVertex2i(x + width, y); glTexCoord2d(U_Offset + U_Scale, V_Offset + V_Scale); glVertex2i(x + width, y + height); glTexCoord2d(U_Offset, V_Offset + V_Scale); glVertex2i(x, y + height); glEnd(); TMgr.RestoreTextureMatrix(); } /* * Draw text */ // WZ: Work around some Win32 oddness #ifdef DrawText #undef DrawText #endif void HUD_OGL_Class::DrawText(const char *text, screen_rectangle *dest, short flags, short font_id, short text_color) { // Get color const rgb_color &c = get_interface_color(text_color); glColor3f(c.red / 65535.0F, c.green / 65535.0F, c.blue / 65535.0F); // Get font information FontSpecifier &FontData = get_interface_font(font_id); // Draw text FontData.OGL_DrawText(text, *dest, flags); } /* * Fill rectangle */ void HUD_OGL_Class::FillRect(screen_rectangle *r, short color_index) { // Get color const rgb_color &c = get_interface_color(color_index); glColor3f(c.red / 65535.0F, c.green / 65535.0F, c.blue / 65535.0F); // Draw rectangle glDisable(GL_TEXTURE_2D); glRecti(r->left, r->top, r->right, r->bottom); } /* * Frame rectangle */ void HUD_OGL_Class::FrameRect(screen_rectangle *r, short color_index) { // Get color const rgb_color &c = get_interface_color(color_index); glColor3f(c.red / 65535.0F, c.green / 65535.0F, c.blue / 65535.0F); // Draw rectangle glDisable(GL_TEXTURE_2D); glLineWidth(1); glBegin(GL_LINE_LOOP); glVertex2f(r->left + 0.5, r->top + 0.5); glVertex2f(r->right - 0.5, r->top + 0.5); glVertex2f(r->right - 0.5, r->bottom - 0.5); glVertex2f(r->left + 0.5, r->bottom - 0.5); glEnd(); } /* * Set clip plane for rendering a blip at (x, y) on the motion sensor. * The plane gets attached tangential to the circle with the specified * radius and center (this circle covers the entire motion sensor area). * This should be a sufficient approximation to a circular clipping region * for small blips. */ void HUD_OGL_Class::SetClipPlane(int x, int y, int c_x, int c_y, int radius) { GLdouble blip_dist = sqrt(static_cast(x*x+y*y)); if (blip_dist <= 2.0) return; GLdouble normal_x = x / blip_dist, normal_y = y / blip_dist; GLdouble tan_pt_x = c_x + normal_x * radius + 0.5, tan_pt_y = c_y + normal_y * radius + 0.5; glEnable(GL_CLIP_PLANE0); GLdouble eqn[4] = { -normal_x, -normal_y, 0, normal_x * tan_pt_x + normal_y * tan_pt_y }; glClipPlane(GL_CLIP_PLANE0, eqn); } /* * Disable clip plane */ void HUD_OGL_Class::DisableClipPlane(void) { glDisable(GL_CLIP_PLANE0); } #define MESSAGE_AREA_X_OFFSET 291 #define MESSAGE_AREA_Y_OFFSET 321 void HUD_OGL_Class::draw_message_area(short) { { DrawShapeAtXY( BUILD_DESCRIPTOR(_collection_interface, _network_panel), MESSAGE_AREA_X_OFFSET, MESSAGE_AREA_Y_OFFSET); draw_player_name(); } } #endif // def HAVE_OPENGL