00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "scenegraph/heightmap.hpp"
00035
00036 #include "data/string.hpp"
00037 #include "data/pointer.hpp"
00038 #include "data/file.hpp"
00039 #include "math/math.hpp"
00040 #include "platform/hardware.hpp"
00041
00042 #include <cstdlib>
00043
00044 namespace gsgl
00045 {
00046
00047 using namespace data;
00048 using namespace platform;
00049
00050
00051 namespace scenegraph
00052 {
00053
00054 heightmap::heightmap(const string & fname, double altitude)
00055 : scenegraph_object(), width(0), height(0), altitude(altitude), surface(0)
00056 {
00057 init(fname);
00058 }
00059
00060
00061 heightmap::~heightmap()
00062 {
00063 if (surface)
00064 SDL_FreeSurface(surface);
00065 }
00066
00067
00068 static void flip_texture(SDL_Surface *s)
00069 {
00070 SDL_LockSurface(s);
00071
00072 int a = 0, b = s->h - 1;
00073 smart_pointer<unsigned char, true> temp(new unsigned char[s->pitch]);
00074 unsigned char *ptr_a, *ptr_b, *ptr_t = temp.ptr();
00075
00076 while (b > a)
00077 {
00078 ptr_a = static_cast<unsigned char *>(s->pixels) + a++*s->pitch;
00079 ptr_b = static_cast<unsigned char *>(s->pixels) + b--*s->pitch;
00080
00081 ::memcpy(ptr_t, ptr_a, s->pitch);
00082 ::memcpy(ptr_a, ptr_b, s->pitch);
00083 ::memcpy(ptr_b, ptr_t, s->pitch);
00084 }
00085
00086 SDL_UnlockSurface(s);
00087 }
00088
00089
00090 void heightmap::init(const string & fname)
00091 {
00092 if (!io::file::exists(fname))
00093 throw io_exception(L"%ls does not exist!", fname.w_string());
00094
00095 surface = IMG_Load(fname.c_string());
00096
00097 if (!surface)
00098 throw io_exception(L"Unable to load %ls!", fname.w_string());
00099
00100 flip_texture(surface);
00101
00102 width = surface->w;
00103 height = surface->h;
00104 }
00105
00106
00107 void heightmap::get_data(const double s, const double t, double & hval, double & alpha)
00108 {
00109 unsigned char rgba[4];
00110
00111 SDL_LockSurface(surface);
00112 unsigned char *buf = static_cast<unsigned char *>(surface->pixels);
00113 math::interpolate_bilinear<unsigned char>(buf, width, height, surface->format->BytesPerPixel, s, t, rgba, math::INTERPOLATE_NO_FLAGS);
00114 SDL_UnlockSurface(surface);
00115
00116 double r = static_cast<double>(rgba[0]) / 255.0;
00117 double g = static_cast<double>(rgba[1]) / 255.0;
00118 double b = static_cast<double>(rgba[2]) / 255.0;
00119 double a = static_cast<double>(rgba[3]) / 255.0;
00120
00121 hval = (r + g + b) / 3.0;
00122 alpha = a;
00123 }
00124
00125
00126 }
00127
00128 }