From 773c1bafe0f1d8b706e0f72e235f8466e7a9ccf5 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Tue, 11 Nov 2008 19:11:57 +0000 Subject: cleanups --- src/render/Makefile.am | 4 +- src/render/camera.cc | 21 +-- src/render/camera.h | 13 -- src/render/gl.cc | 7 +- src/render/gl.h | 4 - src/render/render.cc | 214 +++++---------------------- src/render/render.h | 12 +- src/render/screenshot.cc | 109 ++++++++++++++ src/render/screenshot.h | 27 ++++ src/render/state.cc | 91 ++++++++++++ src/render/state.h | 34 +++++ src/render/textures.cc | 3 +- src/render/tga.cc | 367 ----------------------------------------------- src/render/tga.h | 34 ----- src/render/tgafile.cc | 367 +++++++++++++++++++++++++++++++++++++++++++++++ src/render/tgafile.h | 34 +++++ 16 files changed, 714 insertions(+), 627 deletions(-) create mode 100644 src/render/screenshot.cc create mode 100644 src/render/screenshot.h create mode 100644 src/render/state.cc create mode 100644 src/render/state.h delete mode 100644 src/render/tga.cc delete mode 100644 src/render/tga.h create mode 100644 src/render/tgafile.cc create mode 100644 src/render/tgafile.h (limited to 'src/render') diff --git a/src/render/Makefile.am b/src/render/Makefile.am index 27ad8bb..7919ee2 100644 --- a/src/render/Makefile.am +++ b/src/render/Makefile.am @@ -10,6 +10,6 @@ endif librender_la_LDFLAGS = -avoid-version -no-undefined @GL_LIBS@ librender_la_LIBADD = $(top_builddir)/src/math/libmath.la librender_la_SOURCES = camera.cc draw.cc dust.cc gl.cc image.cc jpgfile.cc \ - pngfile.cc render.cc text.cc textures.cc tga.cc + pngfile.cc render.cc screenshot.cc state.cc text.cc textures.cc tgafile.cc noinst_HEADERS = camera.h draw.h dust.h gl.h image.h render.h text.h textures.h \ - tga.h pngfile.h jpgfile.h + tgafile.h pngfile.h jpgfile.h screenshot.h state.h diff --git a/src/render/camera.cc b/src/render/camera.cc index c7749c4..875b147 100644 --- a/src/render/camera.cc +++ b/src/render/camera.cc @@ -9,6 +9,7 @@ #include "math/matrix4f.h" #include "render/camera.h" #include "render/gl.h" +#include "render/state.h" #include "sys/sys.h" using math::degrees360f; @@ -22,12 +23,9 @@ const float MIN_DELTA = 10e-10; const float pitch_track = -15.0f; const float pitch_overview = -5.0f; -float Camera::camera_aspect = 1.0f; -int Camera::camera_width = 0; -int Camera::camera_height = 0; - float Camera::camera_frustum_size = 0.5f; float Camera::camera_frustum_front = 1.0f; + math::Vector3f Camera::camera_eye; math::Vector3f Camera::camera_target; math::Axis Camera::camera_axis; @@ -48,10 +46,6 @@ float Camera::distance; void Camera::init() { - camera_aspect = 1.0f; - camera_height = 0; - camera_width = 0; - camera_frustum_size = 0.5f; camera_frustum_front = 1.0f; @@ -80,13 +74,6 @@ void Camera::shutdown() { } -void Camera::resize(int width, int height) -{ - camera_width = width; - camera_height = height; - camera_aspect = (float) width / (float) height; -} - void Camera::set_mode(Mode newmode) { direction_target = 0; @@ -344,7 +331,7 @@ void Camera::frustum() gl::matrixmode(GL_PROJECTION); gl::loadidentity(); - gl::frustum(-camera_frustum_size, camera_frustum_size, -camera_frustum_size/Camera::aspect(), camera_frustum_size/Camera::aspect(), camera_frustum_front, 1023.0f); + gl::frustum(-camera_frustum_size, camera_frustum_size, -camera_frustum_size/State::aspect(), camera_frustum_size/State::aspect(), camera_frustum_front, 1023.0f); gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); @@ -365,7 +352,7 @@ void Camera::ortho() // switch to orthographic projection gl::matrixmode(GL_PROJECTION); gl::loadidentity(); - glOrtho(0, camera_width, camera_height, 0, -16.0f, 16.0f); + glOrtho(0, State::width(), State::height(), 0, -16.0f, 16.0f); gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); diff --git a/src/render/camera.h b/src/render/camera.h index 5394d1b..3f30ff6 100644 --- a/src/render/camera.h +++ b/src/render/camera.h @@ -37,9 +37,6 @@ public: /// current camera mode static inline Mode mode() { return camera_mode; } - /// current aspect ratio - static inline float aspect() { return camera_aspect; } - /// reset the current mode static void reset(); @@ -71,30 +68,20 @@ public: /// set specified camera mode static void set_mode(Mode newmode); - /// resize camera - static void resize(int width, int height); - /// current frustum front static float frustum_front(); /// current frustum size (height); static float frustum_size(); - inline static int width() { return camera_width; } - - inline static int height() { return camera_height; } - private: static math::Vector3f camera_eye; static math::Vector3f camera_target; static math::Axis camera_axis; static Mode camera_mode; static Mode camera_previous_mode; - static float camera_aspect; static float camera_frustum_size; static float camera_frustum_front; - static int camera_width; - static int camera_height; // current and target yaw angle in XZ plane, positive is looking left static float direction_current; diff --git a/src/render/gl.cc b/src/render/gl.cc index 47a0420..31c473f 100644 --- a/src/render/gl.cc +++ b/src/render/gl.cc @@ -7,14 +7,12 @@ #include "render/gl.h" #include "math/matrix4f.h" +namespace gl { + using math::Vector2f; using math::Vector3f; using math::Color; -namespace render { - -namespace gl { - std::string renderer() { return std::string ((char *)glGetString(GL_RENDERER)); @@ -185,4 +183,3 @@ void frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdou } // namespace gl -} // namespace render diff --git a/src/render/gl.h b/src/render/gl.h index 6e32e35..a858c5b 100644 --- a/src/render/gl.h +++ b/src/render/gl.h @@ -20,8 +20,6 @@ #define GL_RESCALE_NORMAL 0x803A #endif -namespace render { - /// wrapper namespace for OpenGL operations /** The gl namespace provides a wrapper to the OpenGL library functions. * All methods take floats or Vector3f and Color as parameters. @@ -184,6 +182,4 @@ namespace gl void frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble znear, GLdouble zfar); } -} - #endif // __INCLUDED_RENDER_GL_H__ diff --git a/src/render/render.cc b/src/render/render.cc index 02bd586..9afa179 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -14,93 +14,47 @@ #include "filesystem/filesystem.h" #include "model/model.h" #include "render/gl.h" +#include "render/state.h" #include "render/dust.h" -#include "render/textures.h" -#include "render/tga.h" #include "render/render.h" +#include "render/screenshot.h" +#include "render/textures.h" #include "sys/sys.h" namespace render { +model::VertexArray *vertexarray = 0; + core::Cvar *r_arraysize = 0; core::Cvar *r_bbox = 0; core::Cvar *r_grid = 0; core::Cvar *r_radius = 0; core::Cvar *r_sky = 0; core::Cvar *r_wireframe = 0; -core::Cvar *screenshotformat = 0; -core::Cvar *screenshotquality = 0; - -int screenshot_number = 0; - -using model::VertexArray; -VertexArray *vertexarray = 0; void func_list_textures(std::string const &args) { Textures::list(); } -void reset_gl() +void init(int width, int height) { - // set clear color - gl::clearcolor(0.0f, 0.0f, 0.0f, 1.0f); - - // load identity matrices - gl::matrixmode(GL_MODELVIEW); - gl::loadidentity(); - - gl::matrixmode(GL_MODELVIEW); - gl::loadidentity(); - - // shading model: Gouraud (smooth, the default) - gl::shademodel(GL_SMOOTH); - //gl::shademodel(GL_FLAT); - - // lighting settings for the default light GL_LIGHT0 - 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); - - // GL_LIGHT0 is always enabled - gl::enable(GL_LIGHT0); - - // color tracking - glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); - - // material settings - 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 + con_print << "^BInitializing renderer..." << std::endl; - // alpha blending function - gl::blendfunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + con_print << " renderer ^B" << gl::renderer() << std::endl; + con_print << " vendor ^B" << gl::vendor() << std::endl; + con_print << " version ^B" << gl::version() << std::endl; - gl::disable(GL_LIGHTING); - gl::disable(GL_COLOR_MATERIAL); + // initialize render state + State::init(width, height); - gl::cullface(GL_BACK); - gl::frontface(GL_CCW); - gl::disable(GL_CULL_FACE); - gl::disable(GL_DEPTH_TEST); - gl::disable(GL_BLEND); + Camera::init(); - gl::disable(GL_TEXTURE_2D); -} + Textures::init(); -void init() -{ - con_print << "^BInitializing renderer..." << std::endl; + Text::init(); - con_print << " renderer ^B" << gl::renderer() << std::endl; - con_print << " vendor ^B" << gl::vendor() << std::endl; - con_print << " version ^B" << gl::version() << std::endl; + Dust::init(); // size of the vertex array in megabytes r_arraysize = core::Cvar::get("r_arraysize", 0.0f , core::Cvar::Archive); @@ -112,8 +66,9 @@ void init() if (mb > 256) mb = 256; (*r_arraysize) = (float) mb; - vertexarray = new VertexArray(mb); + vertexarray = new model::VertexArray(mb); + // engine variables r_radius = core::Cvar::get("r_radius", "0", core::Cvar::Archive); r_radius->set_info("[bool] render entity radius"); @@ -129,33 +84,17 @@ void init() r_sky = core::Cvar::get("r_sky", "1", core::Cvar::Archive); r_sky->set_info("[bool] render the sky globe"); - screenshotformat = core::Cvar::get("screenshotformat", "jpg", core::Cvar::Archive); - screenshotformat->set_info("[string] screenshot format: jpg png tga"); - - screenshotquality = core::Cvar::get("screenshotquality", "85", core::Cvar::Archive); - screenshotquality->set_info("[int] screenshot jpg quality"); - - reset_gl(); - - Camera::init(); - - Textures::init(); + Screenshot::screenshotformat = core::Cvar::get("screenshotformat", "jpg", core::Cvar::Archive); + Screenshot::screenshotformat->set_info("[string] screenshot format: jpg png tga"); - Text::init(); + Screenshot::screenshotquality = core::Cvar::get("screenshotquality", "85", core::Cvar::Archive); + Screenshot::screenshotquality->set_info("[int] screenshot jpg quality"); - Dust::init(); - + // engine functions core::Func *func = core::Func::add("list_textures", func_list_textures); func->set_info("list loaded textures"); } -void resize(int width, int height) -{ - // setup our viewport. - gl::viewport(0, 0, width, height); - Camera::resize(width, height); -} - // unload game assets (zone change) void unload() { @@ -184,7 +123,8 @@ void unload() // clear all assets void clear() { - con_debug << "Clearing render data...\n"; + //con_debug << " vclearing render data...\n"; + // clear zone sky textures for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { core::Zone *zone = (*it).second; @@ -204,7 +144,7 @@ void clear() } } - // clear models + // clear model refistry model::Model::clear(); // clear vertex array @@ -212,25 +152,33 @@ void clear() vertexarray = 0; } -// reset render subsystem +// reset render subsystem (module disconnect) void reset() { clear(); + State::clear(); + Textures::shutdown(); + Textures::init(); + size_t mb = (size_t) r_arraysize->value(); if (mb < 4 * sizeof(float)) mb = 4 * sizeof(float); if (mb > 256) mb = 256; (*r_arraysize) = (float) mb; - vertexarray = new VertexArray(mb); + vertexarray = new model::VertexArray(mb); - reset_gl(); Dust::reset(); } +void resize(int width, int height) +{ + State::resize(width, height); +} + void shutdown() { con_print << "^BShutting down renderer..." << std::endl; @@ -246,92 +194,8 @@ void shutdown() Camera::shutdown(); Dust::shutdown(); -} - - -void screenshot() -{ - bool available = false; - std::string shortname; - std::string filename; - const int TYPETGA = 0; - const int TYPEPNG = 1; - const int TYPEJPG = 2; - int filetype = TYPETGA; - - // make sure the screenshots folder exists - filename.assign(filesystem::writedir()); - filename.append("screenshots/"); - sys::mkdir(filename); - - aux::lowercase(screenshotformat->str()); - - if ((screenshotformat->str().compare("jpg") == 0) || (screenshotformat->str().compare("jpeg") == 0)) { - filetype = TYPEJPG; - if (screenshotquality->value() < 10) { - (*screenshotquality) = 10; - } else if (screenshotquality->value() > 100) { - (*screenshotquality) = 100; - } - - } else if (screenshotformat->str().compare("png") == 0) { - filetype = TYPEPNG; - - } else if (screenshotformat->str().compare("tga") == 0) { - filetype = TYPETGA; - - } else { - filetype = TYPETGA; - (*screenshotformat) = "tga"; - } - - // find the first available screenshotxxxx - do { - std::stringstream nstr; - nstr << screenshot_number; - shortname.assign(nstr.str()); - - while(shortname.size() < 4) - shortname.insert(0, 1, '0'); - - shortname.insert(0, "screenshots/osirion"); - shortname.append("."); - shortname.append(screenshotformat->str()); - - filename.assign(filesystem::writedir()); - filename.append(shortname); - - FILE *handle = fopen(filename.c_str(), "r"); - if (handle) { - fclose(handle); - } else { - available = true; - } - screenshot_number++; - } while (!available); - - render::Image image(Camera::width(), Camera::height(), 3); - - glReadPixels(0, 0, (GLsizei) Camera::width(), (GLsizei) Camera::height(), - GL_RGB, GL_UNSIGNED_BYTE, (void *) image.data()); - - image.flip(); - - if (filetype == TYPEPNG) { -/* if ((Camera::width() % 8 != 0 ) || (Camera::height() % 8 != 0 )) { - image.pad(); - }*/ - render::PNG::save(filename.c_str(), image); - } else if (filetype == TYPEJPG) { -/* if ((Camera::width() % 8 != 0 ) || (Camera::height() % 8 != 0 )) { - image.pad(); - } -*/ - render::JPG::save(filename.c_str(), image, (int) screenshotquality->value()); - } else if (filetype == TYPETGA) { - render::TGA::save(filename.c_str(), image); - } -} + State::shutdown(); } +} // namespace render diff --git a/src/render/render.h b/src/render/render.h index a7aec70..4317540 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -11,20 +11,17 @@ #include "model/vertexarray.h" #include "render/camera.h" +#include "render/state.h" #include "render/draw.h" #include "render/dust.h" #include "render/gl.h" -#include "render/jpgfile.h" -#include "render/pngfile.h" -#include "render/image.h" #include "render/text.h" #include "render/textures.h" -#include "render/tga.h" namespace render { /// initialize the render subsystem - void init(); + void init(int width, int height); /// shutdown the render subsystem void shutdown(); @@ -35,11 +32,8 @@ namespace render { /// unload game render data void unload(); - /// make a screenshot - void screenshot(); - /// resize viewport - void resize(int w, int h); + void resize(int width, int height); extern core::Cvar *r_arraysize; extern core::Cvar *r_bbox; diff --git a/src/render/screenshot.cc b/src/render/screenshot.cc new file mode 100644 index 0000000..c2ee88a --- /dev/null +++ b/src/render/screenshot.cc @@ -0,0 +1,109 @@ +/* + render/screenshot.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "auxiliary/functions.h" +#include "core/core.h" +#include "filesystem/filesystem.h" +#include "render/state.h" +#include "render/screenshot.h" +#include "render/image.h" +#include "render/jpgfile.h" +#include "render/pngfile.h" +#include "render/tgafile.h" +#include "render/gl.h" + +namespace render { + +core::Cvar *Screenshot::screenshotformat = 0; +core::Cvar *Screenshot::screenshotquality = 0; + +int Screenshot::number = 0; + +void Screenshot::save() +{ + bool available = false; + std::string shortname; + std::string filename; + const int TYPETGA = 0; + const int TYPEPNG = 1; + const int TYPEJPG = 2; + int filetype = TYPETGA; + + // make sure the screenshots folder exists + filename.assign(filesystem::writedir()); + filename.append("screenshots/"); + sys::mkdir(filename); + + aux::lowercase(screenshotformat->str()); + + if ((screenshotformat->str().compare("jpg") == 0) || (screenshotformat->str().compare("jpeg") == 0)) { + filetype = TYPEJPG; + if (screenshotquality->value() < 10) { + (*screenshotquality) = 10; + } else if (screenshotquality->value() > 100) { + (*screenshotquality) = 100; + } + + } else if (screenshotformat->str().compare("png") == 0) { + filetype = TYPEPNG; + + } else if (screenshotformat->str().compare("tga") == 0) { + filetype = TYPETGA; + + } else { + filetype = TYPETGA; + (*screenshotformat) = "tga"; + } + + // find the first available screenshotxxxx + do { + std::stringstream nstr; + nstr << number; + shortname.assign(nstr.str()); + + while(shortname.size() < 4) + shortname.insert(0, 1, '0'); + + shortname.insert(0, "screenshots/osirion"); + shortname.append("."); + shortname.append(screenshotformat->str()); + + filename.assign(filesystem::writedir()); + filename.append(shortname); + + FILE *handle = fopen(filename.c_str(), "r"); + if (handle) { + fclose(handle); + } else { + available = true; + } + number++; + } while (!available); + + render::Image image(State::width(), State::height(), 3); + + glReadPixels(0, 0, (GLsizei) State::width(), (GLsizei) State::height(), + GL_RGB, GL_UNSIGNED_BYTE, (void *) image.data()); + + image.flip(); + + if (filetype == TYPEPNG) { +/* if ((Camera::width() % 8 != 0 ) || (Camera::height() % 8 != 0 )) { + image.pad(); + }*/ + render::PNG::save(filename.c_str(), image); + } else if (filetype == TYPEJPG) { +/* if ((Camera::width() % 8 != 0 ) || (Camera::height() % 8 != 0 )) { + image.pad(); + } +*/ + render::JPG::save(filename.c_str(), image, (int) screenshotquality->value()); + } else if (filetype == TYPETGA) { + render::TGA::save(filename.c_str(), image); + } +} + +} // namsepace render \ No newline at end of file diff --git a/src/render/screenshot.h b/src/render/screenshot.h new file mode 100644 index 0000000..bf61ef6 --- /dev/null +++ b/src/render/screenshot.h @@ -0,0 +1,27 @@ +/* + render/screenshot.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_RENDER_SCREENSHOT_H__ +#define __INCLUDED_RENDER_SCREENSHOT_H__ + +#include "core/cvar.h" + +namespace render { + +class Screenshot { +public: + static void save(); + + static core::Cvar *screenshotformat; + static core::Cvar *screenshotquality; + +private: + static int number; +}; + +} + +#endif // __INCLUDED_RENDER_SCREENSHOT_H__ \ No newline at end of file diff --git a/src/render/state.cc b/src/render/state.cc new file mode 100644 index 0000000..41ef158 --- /dev/null +++ b/src/render/state.cc @@ -0,0 +1,91 @@ +/* + render/state.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "render/state.h" +#include "render/gl.h" + +namespace render { + +int State::render_width; +int State::render_height; +float State::render_aspect; + +void State::init(int width, int height) +{ + resize(width, height); +} + +void State::shutdown() +{ +} + +void State::resize(int width, int height) +{ + render_width = width; + render_height = height; + + render_aspect = (float) width / (float) height; + + clear(); +} + +void State::clear() +{ + // set viewport + gl::viewport(0, 0, render_width, render_height); + + // set clear color + gl::clearcolor(0.0f, 0.0f, 0.0f, 1.0f); + + // load identity matrices + gl::matrixmode(GL_MODELVIEW); + gl::loadidentity(); + + gl::matrixmode(GL_MODELVIEW); + gl::loadidentity(); + + // shading model: Gouraud (smooth, the default) + gl::shademodel(GL_SMOOTH); + //gl::shademodel(GL_FLAT); + + // lighting settings for the default light GL_LIGHT0 + 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); + + // GL_LIGHT0 is always enabled + gl::enable(GL_LIGHT0); + + // color tracking + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); + + // material settings + 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 + + // alpha blending function + gl::blendfunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + gl::disable(GL_LIGHTING); + gl::disable(GL_COLOR_MATERIAL); + + gl::cullface(GL_BACK); + gl::frontface(GL_CCW); + gl::disable(GL_CULL_FACE); + gl::disable(GL_DEPTH_TEST); + gl::disable(GL_BLEND); + + gl::disable(GL_TEXTURE_2D); +} + +} // namespace render diff --git a/src/render/state.h b/src/render/state.h new file mode 100644 index 0000000..59626c4 --- /dev/null +++ b/src/render/state.h @@ -0,0 +1,34 @@ +/* + render/state.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_RENDER_STATE_H__ +#define __INCLUDED_RENDER_STATE_H__ + + +namespace render { + +class State { +public: + static void init(int width, int height); + static void shutdown(); + + static void resize(int width, int height); + static void clear(); + + inline static int width() { return render_width; } + inline static int height() { return render_height; } + inline static float aspect() { return render_aspect; } + +private: + static int render_width; + static int render_height; + + static float render_aspect; +}; +} // namespace render + +#endif // __INCLUDED_RENDER_STATE_H__ + diff --git a/src/render/textures.cc b/src/render/textures.cc index fd2367d..60c82c2 100644 --- a/src/render/textures.cc +++ b/src/render/textures.cc @@ -7,8 +7,9 @@ #include #include "render/gl.h" +#include "render/image.h" #include "render/textures.h" -#include "render/tga.h" +#include "render/tgafile.h" #include "render/pngfile.h" #include "render/jpgfile.h" diff --git a/src/render/tga.cc b/src/render/tga.cc deleted file mode 100644 index a7a2356..0000000 --- a/src/render/tga.cc +++ /dev/null @@ -1,367 +0,0 @@ -/* - render/tga.cc - This file is part of the Osirion project and is distributed under - the terms of the GNU General Public License version 2 -*/ - -/* - Documentation and examples on the TGA file format: - - http://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf - http://www.fileformat.info/format/tga/egff.htm - http://www.morrowland.com/apron/tut_gl.php - - Notes - - TGA image type Colormap RLE - 0 No image data included in file No No - 1 Colormapped image data Yes No - 2 Truecolor image data No No - 3 Monochrome image data No No - 9 Colormapped image data Yes Yes - 10 Truecolor image data No Yes - 11 Monochrome image data No Yes - - TGA multi-byte integer values have LSB first -*/ - -#include - -#include -#include -#include - -#include "filesystem/filesystem.h" -#include "render/tga.h" -#include "sys/sys.h" - -const unsigned char TGA_NONE = 0; -const unsigned char TGA_TRUECOLOR = 2; -const unsigned char TGA_TRUECOLOR_RLE = 10; - -namespace render -{ - -Image *TGA::load(const char *filename) -{ - Image *image = 0; - - if (!filename) - return 0; - - filesystem::File *tga_file = filesystem::open(filename); - if (!tga_file) { - //con_warn << "Could not open " << filename << std::endl; - return 0; - } - - // TGA header - unsigned char header[18]; - memset(header, 0, sizeof(header)); - - if (!tga_file->read(header, 18)) { - con_warn << "Error reading " << filename << std::endl; - filesystem::close(tga_file); - return 0; - } - - // byte 0 - image ID field length - unsigned int tga_idlength = header[0]; - - // byte 1 - color map type - unsigned int tga_colormap = header[1]; - - // byte 2 - image type - unsigned int tga_type = header[2]; - - // byte 3+4 - color map first entry index - //unsigned int tga_colormap_first = header[3] + (header[4] << 8 ); - - // byte 5+6 - color map length (in bits) - unsigned int tga_color_map_length = header[5] +(header[6] << 8 ); - - // byte 7 - color map entry length - unsigned int tga_colormap_entry = header[7]; - - // byte 8+9 - image x origin - // byte 10+11 - image y origin - // byte 12+13 - image width (LSB first) - unsigned int tga_width = header[12] + (header[13] << 8); - - // byte 14+15 - image height (LSB first) - unsigned int tga_height = header[14] + (header[15] << 8); - - // byte 16 - image color depth (in bits) - unsigned int tga_depth = header[16]; - - // byte 17 - image descriptor byte - unsigned int tga_descriptor = header[17]; - - // read the image id if there is one - if (tga_idlength) - tga_file->skip(tga_idlength); - - // read color map data (even for non-color mapped images) - if (tga_colormap) { - if (tga_colormap > 1) - con_warn << filename << ": invalid color map type!" << std::endl; - - tga_file->skip(tga_color_map_length*tga_colormap_entry); - } - - unsigned int index = 0; - unsigned int channels = tga_depth / 8; - - switch(tga_type) { - - case TGA_NONE: - con_warn << "Error reading " << filename - << ": no image data!" << std::endl; - filesystem::close(tga_file); - return 0; - break; - - case TGA_TRUECOLOR: - if ((tga_depth == 24) || (tga_depth == 32)) { - - image = new Image(tga_width, tga_height, channels); - - for (size_t i = 0; i < tga_width * tga_height; i++) { - tga_file->read((void *)(*image)[i*(size_t)channels], channels); - } - - image->swap_channels(); - - } else if (tga_depth == 16) { - - channels = 3; - image = new Image(tga_width, tga_height,channels); - - for (size_t i =0; i < tga_width * tga_height; i++) { - // unpack one pixel - unsigned char pixel_data[2]; - tga_file->read((void *)pixel_data, 2); - unsigned int unpacked = pixel_data[0] + pixel_data[1]* 0xff; - - unsigned int b = (unpacked & 0x1f) << 3; - unsigned int g = ((unpacked >> 5) & 0x1f) << 3; - unsigned int r = ((unpacked >> 10) & 0x1f) << 3; - - // store it - image->data()[i * channels] = (unsigned char) b; - image->data()[i * channels+1] = (unsigned char) g; - image->data()[i * channels+2] = (unsigned char) r; - } - } else { - con_warn << "Error reading " << filename - << ": unsupported image depth '" << tga_depth << "'!" << std::endl; - filesystem::close(tga_file); - return 0; - } - - break; - - case TGA_TRUECOLOR_RLE: - - image = new Image(tga_width, tga_height, channels); - - while (index < tga_width * tga_height) { - unsigned char rle = 0; - unsigned char pixel_data[3]; - - // read RLE packet byte - tga_file->read(&rle, 1); - - if (rle < 128) { - rle++; // rle contains the number of pixels-1 - tga_file->read((void *)(*image)[index*channels], rle*channels); - index += rle; - - } else { - rle -= 127; // rle contains 128 + the number of identical pixels-1 - tga_file->read(pixel_data, channels); - - while (rle) { - memcpy((void *)(*image)[index*channels], (void *)pixel_data, channels); - index++; - rle--; - } - } - } - - image->swap_channels(); - - break; - - default: - con_warn << "Error reading " << filename - << ": unsupported TGA type '" << (int) tga_type << "'!" << std::endl; - filesystem::close(tga_file); - return 0; - } - - filesystem::close(tga_file); - - if ((tga_descriptor & 0x20) == 0x0) { - // origin at bottom left - image->flip(); - } - - if ((tga_descriptor & 0x10) == 0x10) { - con_warn << filename << ": descriptor bit 4 (left-right) set!" << std::endl; - } - - con_debug << " " << filename << " " << image->width() << "x" << image->height() << "x" << image->bpp() << "bpp" << std::endl; - return image; -} - -void TGA::save(const char *filename, Image & image) -{ - if (!filename) - return; - - std::ofstream ofs(filename, std::ios_base::out | std::ios_base::binary ); - - if (!ofs.is_open()) { - con_warn << "Could not write " << filename << std::endl; - return; - } - - // write TGA header - unsigned char header[18]; - memset(header, 0, sizeof(header)); - - // byte 0 - image ID field length = 0 (no image ID field present) - // byte 1 - color map type = 0 (no palette present) - // byte 2 - image type = 10 (truecolor RLE encoded) - header[2] = TGA_TRUECOLOR_RLE; - // byte 3-11 - palette data (not used) - // byte 12+13 - image width - header[12] = (image.width() & 0xff); - header[13] = ((image.width() >> 8) & 0xff); - // byte 14+15 - image height - header[14] = (image.height() & 0xff); - header[15] = ((image.height() >> 8) & 0xff); - // byte 16 - image color depth = 24 (RGB) or 32 (RGBA) - header[16] = image.channels() * 8; - // byte 17 - image descriptor byte = 0x20 (origin at bottom left) - header[17] = 0x20; - - // write header - ofs.write((char *)header, sizeof(header)); - - // write image data - // TGA has the R and B channels switched - unsigned char pixel_data[image.channels()]; - unsigned char block_data[image.channels()*128]; - unsigned char rle_packet; - bool compress = false; - size_t block_length = 0; - - for (int y = image.height()-1; y >= 0; y--) { - for (size_t x = 0; x < image.width(); x++) { - size_t index = y*image.width()*image.channels() + x * image.channels(); - - pixel_data[0] = *image[index+2]; - pixel_data[1] = *image[index+1]; - pixel_data[2] = *image[index]; - if (image.channels() == 4) - pixel_data[3] = *image[index+3]; - - if (block_length == 0) { - memcpy(block_data, pixel_data, image.channels()); - block_length++; - compress = false; - } else { - if (!compress) { - - // uncompressed block and pixel_data differs from the last pixel - if (memcmp(&block_data[(block_length-1)*image.channels()], pixel_data, image.channels()) != 0) { - // append pixel - memcpy(&block_data[block_length*image.channels()], pixel_data, image.channels()); - - block_length++; - } else { - - // uncompressed block and pixel data is identical - if (block_length > 1 ) { - // write the uncompressed block - rle_packet = block_length - 2; - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, (block_length-1) * image.channels()); - block_length = 1; - } - memcpy(block_data, pixel_data, image.channels()); - block_length++; - compress = true; - } - - } else { - - // compressed block and pixel data is identical - if (memcmp(block_data, pixel_data, image.channels()) == 0) { - block_length++; - - } else { - - // compressed block and pixel data differs - if (block_length > 1) { - // write the compressed block - rle_packet = block_length + 127; - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, image.channels()); - block_length = 0; - } - memcpy(&block_data[block_length * image.channels()], pixel_data, image.channels()); - block_length++; - compress = false; - } - } - } - - if (block_length == 128) { - rle_packet = block_length - 1; - if (!compress) { - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, 128 * image.channels()); - } else { - rle_packet += 128; - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, image.channels()); - } - - block_length = 0; - compress = false; - } - } - } - - // write remaining bytes - if (block_length) { - rle_packet = block_length - 1; - if (!compress) { - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, block_length * image.channels()); - } else { - rle_packet += 128; - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, image.channels()); - } - } - - - // write footer (optional, but the specification recommends it) - char footer[26]; - memset(footer, 0, sizeof(footer)); - strncpy(&footer[8] , "TRUEVISION-XFILE", 16); - footer[24] = '.'; - footer[25] = 0; - ofs.write(footer, sizeof(footer)); - - // close file - ofs.close(); - - con_print << "Wrote " << filename << std::endl; -} - -} diff --git a/src/render/tga.h b/src/render/tga.h deleted file mode 100644 index 767a871..0000000 --- a/src/render/tga.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - render/tga.h - This file is part of the Osirion project and is distributed under - the terms of the GNU General Public License version 2 -*/ - - -#ifndef _INCLUDED_RENDER_TGA_H__ -#define _INCLUDED_RENDER_TGA_H__ - -#include "render/image.h" - -namespace render -{ - -/// a class for loading and saving .tga files -class TGA { - -public: - /// load a TGA image file from disk - /** @param filename short path to the filename to be loaded - */ - static Image *load(const char * filename); - - /// write an image to a TGA file - /** @param filename short path to the file to write the image data to - */ - static void save(const char *filename, Image & image); -}; - -} - -#endif //_INCLUDED_RENDER_TGA_H__ - diff --git a/src/render/tgafile.cc b/src/render/tgafile.cc new file mode 100644 index 0000000..5a27648 --- /dev/null +++ b/src/render/tgafile.cc @@ -0,0 +1,367 @@ +/* + render/tgafile.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +/* + Documentation and examples on the TGA file format: + + http://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf + http://www.fileformat.info/format/tga/egff.htm + http://www.morrowland.com/apron/tut_gl.php + + Notes + + TGA image type Colormap RLE + 0 No image data included in file No No + 1 Colormapped image data Yes No + 2 Truecolor image data No No + 3 Monochrome image data No No + 9 Colormapped image data Yes Yes + 10 Truecolor image data No Yes + 11 Monochrome image data No Yes + + TGA multi-byte integer values have LSB first +*/ + +#include + +#include +#include +#include + +#include "filesystem/filesystem.h" +#include "render/tgafile.h" +#include "sys/sys.h" + +const unsigned char TGA_NONE = 0; +const unsigned char TGA_TRUECOLOR = 2; +const unsigned char TGA_TRUECOLOR_RLE = 10; + +namespace render +{ + +Image *TGA::load(const char *filename) +{ + Image *image = 0; + + if (!filename) + return 0; + + filesystem::File *tga_file = filesystem::open(filename); + if (!tga_file) { + //con_warn << "Could not open " << filename << std::endl; + return 0; + } + + // TGA header + unsigned char header[18]; + memset(header, 0, sizeof(header)); + + if (!tga_file->read(header, 18)) { + con_warn << "Error reading " << filename << std::endl; + filesystem::close(tga_file); + return 0; + } + + // byte 0 - image ID field length + unsigned int tga_idlength = header[0]; + + // byte 1 - color map type + unsigned int tga_colormap = header[1]; + + // byte 2 - image type + unsigned int tga_type = header[2]; + + // byte 3+4 - color map first entry index + //unsigned int tga_colormap_first = header[3] + (header[4] << 8 ); + + // byte 5+6 - color map length (in bits) + unsigned int tga_color_map_length = header[5] +(header[6] << 8 ); + + // byte 7 - color map entry length + unsigned int tga_colormap_entry = header[7]; + + // byte 8+9 - image x origin + // byte 10+11 - image y origin + // byte 12+13 - image width (LSB first) + unsigned int tga_width = header[12] + (header[13] << 8); + + // byte 14+15 - image height (LSB first) + unsigned int tga_height = header[14] + (header[15] << 8); + + // byte 16 - image color depth (in bits) + unsigned int tga_depth = header[16]; + + // byte 17 - image descriptor byte + unsigned int tga_descriptor = header[17]; + + // read the image id if there is one + if (tga_idlength) + tga_file->skip(tga_idlength); + + // read color map data (even for non-color mapped images) + if (tga_colormap) { + if (tga_colormap > 1) + con_warn << filename << ": invalid color map type!" << std::endl; + + tga_file->skip(tga_color_map_length*tga_colormap_entry); + } + + unsigned int index = 0; + unsigned int channels = tga_depth / 8; + + switch(tga_type) { + + case TGA_NONE: + con_warn << "Error reading " << filename + << ": no image data!" << std::endl; + filesystem::close(tga_file); + return 0; + break; + + case TGA_TRUECOLOR: + if ((tga_depth == 24) || (tga_depth == 32)) { + + image = new Image(tga_width, tga_height, channels); + + for (size_t i = 0; i < tga_width * tga_height; i++) { + tga_file->read((void *)(*image)[i*(size_t)channels], channels); + } + + image->swap_channels(); + + } else if (tga_depth == 16) { + + channels = 3; + image = new Image(tga_width, tga_height,channels); + + for (size_t i =0; i < tga_width * tga_height; i++) { + // unpack one pixel + unsigned char pixel_data[2]; + tga_file->read((void *)pixel_data, 2); + unsigned int unpacked = pixel_data[0] + pixel_data[1]* 0xff; + + unsigned int b = (unpacked & 0x1f) << 3; + unsigned int g = ((unpacked >> 5) & 0x1f) << 3; + unsigned int r = ((unpacked >> 10) & 0x1f) << 3; + + // store it + image->data()[i * channels] = (unsigned char) b; + image->data()[i * channels+1] = (unsigned char) g; + image->data()[i * channels+2] = (unsigned char) r; + } + } else { + con_warn << "Error reading " << filename + << ": unsupported image depth '" << tga_depth << "'!" << std::endl; + filesystem::close(tga_file); + return 0; + } + + break; + + case TGA_TRUECOLOR_RLE: + + image = new Image(tga_width, tga_height, channels); + + while (index < tga_width * tga_height) { + unsigned char rle = 0; + unsigned char pixel_data[3]; + + // read RLE packet byte + tga_file->read(&rle, 1); + + if (rle < 128) { + rle++; // rle contains the number of pixels-1 + tga_file->read((void *)(*image)[index*channels], rle*channels); + index += rle; + + } else { + rle -= 127; // rle contains 128 + the number of identical pixels-1 + tga_file->read(pixel_data, channels); + + while (rle) { + memcpy((void *)(*image)[index*channels], (void *)pixel_data, channels); + index++; + rle--; + } + } + } + + image->swap_channels(); + + break; + + default: + con_warn << "Error reading " << filename + << ": unsupported TGA type '" << (int) tga_type << "'!" << std::endl; + filesystem::close(tga_file); + return 0; + } + + filesystem::close(tga_file); + + if ((tga_descriptor & 0x20) == 0x0) { + // origin at bottom left + image->flip(); + } + + if ((tga_descriptor & 0x10) == 0x10) { + con_warn << filename << ": descriptor bit 4 (left-right) set!" << std::endl; + } + + con_debug << " " << filename << " " << image->width() << "x" << image->height() << "x" << image->bpp() << "bpp" << std::endl; + return image; +} + +void TGA::save(const char *filename, Image & image) +{ + if (!filename) + return; + + std::ofstream ofs(filename, std::ios_base::out | std::ios_base::binary ); + + if (!ofs.is_open()) { + con_warn << "Could not write " << filename << std::endl; + return; + } + + // write TGA header + unsigned char header[18]; + memset(header, 0, sizeof(header)); + + // byte 0 - image ID field length = 0 (no image ID field present) + // byte 1 - color map type = 0 (no palette present) + // byte 2 - image type = 10 (truecolor RLE encoded) + header[2] = TGA_TRUECOLOR_RLE; + // byte 3-11 - palette data (not used) + // byte 12+13 - image width + header[12] = (image.width() & 0xff); + header[13] = ((image.width() >> 8) & 0xff); + // byte 14+15 - image height + header[14] = (image.height() & 0xff); + header[15] = ((image.height() >> 8) & 0xff); + // byte 16 - image color depth = 24 (RGB) or 32 (RGBA) + header[16] = image.channels() * 8; + // byte 17 - image descriptor byte = 0x20 (origin at bottom left) + header[17] = 0x20; + + // write header + ofs.write((char *)header, sizeof(header)); + + // write image data + // TGA has the R and B channels switched + unsigned char pixel_data[image.channels()]; + unsigned char block_data[image.channels()*128]; + unsigned char rle_packet; + bool compress = false; + size_t block_length = 0; + + for (int y = image.height()-1; y >= 0; y--) { + for (size_t x = 0; x < image.width(); x++) { + size_t index = y*image.width()*image.channels() + x * image.channels(); + + pixel_data[0] = *image[index+2]; + pixel_data[1] = *image[index+1]; + pixel_data[2] = *image[index]; + if (image.channels() == 4) + pixel_data[3] = *image[index+3]; + + if (block_length == 0) { + memcpy(block_data, pixel_data, image.channels()); + block_length++; + compress = false; + } else { + if (!compress) { + + // uncompressed block and pixel_data differs from the last pixel + if (memcmp(&block_data[(block_length-1)*image.channels()], pixel_data, image.channels()) != 0) { + // append pixel + memcpy(&block_data[block_length*image.channels()], pixel_data, image.channels()); + + block_length++; + } else { + + // uncompressed block and pixel data is identical + if (block_length > 1 ) { + // write the uncompressed block + rle_packet = block_length - 2; + ofs.write((char *)&rle_packet, 1); + ofs.write((char *)block_data, (block_length-1) * image.channels()); + block_length = 1; + } + memcpy(block_data, pixel_data, image.channels()); + block_length++; + compress = true; + } + + } else { + + // compressed block and pixel data is identical + if (memcmp(block_data, pixel_data, image.channels()) == 0) { + block_length++; + + } else { + + // compressed block and pixel data differs + if (block_length > 1) { + // write the compressed block + rle_packet = block_length + 127; + ofs.write((char *)&rle_packet, 1); + ofs.write((char *)block_data, image.channels()); + block_length = 0; + } + memcpy(&block_data[block_length * image.channels()], pixel_data, image.channels()); + block_length++; + compress = false; + } + } + } + + if (block_length == 128) { + rle_packet = block_length - 1; + if (!compress) { + ofs.write((char *)&rle_packet, 1); + ofs.write((char *)block_data, 128 * image.channels()); + } else { + rle_packet += 128; + ofs.write((char *)&rle_packet, 1); + ofs.write((char *)block_data, image.channels()); + } + + block_length = 0; + compress = false; + } + } + } + + // write remaining bytes + if (block_length) { + rle_packet = block_length - 1; + if (!compress) { + ofs.write((char *)&rle_packet, 1); + ofs.write((char *)block_data, block_length * image.channels()); + } else { + rle_packet += 128; + ofs.write((char *)&rle_packet, 1); + ofs.write((char *)block_data, image.channels()); + } + } + + + // write footer (optional, but the specification recommends it) + char footer[26]; + memset(footer, 0, sizeof(footer)); + strncpy(&footer[8] , "TRUEVISION-XFILE", 16); + footer[24] = '.'; + footer[25] = 0; + ofs.write(footer, sizeof(footer)); + + // close file + ofs.close(); + + con_print << "Wrote " << filename << std::endl; +} + +} diff --git a/src/render/tgafile.h b/src/render/tgafile.h new file mode 100644 index 0000000..767a871 --- /dev/null +++ b/src/render/tgafile.h @@ -0,0 +1,34 @@ +/* + render/tga.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + + +#ifndef _INCLUDED_RENDER_TGA_H__ +#define _INCLUDED_RENDER_TGA_H__ + +#include "render/image.h" + +namespace render +{ + +/// a class for loading and saving .tga files +class TGA { + +public: + /// load a TGA image file from disk + /** @param filename short path to the filename to be loaded + */ + static Image *load(const char * filename); + + /// write an image to a TGA file + /** @param filename short path to the file to write the image data to + */ + static void save(const char *filename, Image & image); +}; + +} + +#endif //_INCLUDED_RENDER_TGA_H__ + -- cgit v1.2.3