00001
00008 #include <assert.h>
00009 #include <stdlib.h>
00010 #include <fstream>
00011 #include <sstream>
00012 #include <string>
00013 #include "Error.h"
00014 #include "VolumeTexture.h"
00015
00016
00017 VolumeTexture::VolumeTexture() : tex(0), boundUnit(-1)
00018 {
00019 memset((void*)histogram, 0, sizeof(unsigned int)*256);
00020 }
00021
00022
00023 VolumeTexture::~VolumeTexture()
00024 {
00025 if(tex)
00026 glDeleteTextures(1, &tex);
00027 }
00028
00029
00030 bool VolumeTexture::Load(const char *file, const char *path, VTInfo *info)
00031 {
00032 std::string fullPath = path;
00033 fullPath += file;
00034
00035 std::ifstream f(fullPath.c_str());
00036 if(!f.is_open())
00037 {
00038 std::stringstream msg;
00039 msg << "The Volume Texture Description file could not be opened: " << file;
00040 ErrorMessage(msg.str().c_str());
00041 return false;
00042 }
00043
00044
00045 std::string line;
00046 do
00047 {
00048 getline(f, line);
00049 } while(f.good() && line.length() > 0 && line[0] == '#');
00050
00051 unsigned int version, width, height, depth, components;
00052 std::string type, filename;
00053
00054 std::istringstream read1(line);
00055 if( (read1 >> version).fail() )
00056 {
00057 std::stringstream msg;
00058 msg << "Version number could not be read: " << file;
00059 ErrorMessage(msg.str().c_str());
00060 return false;
00061 }
00062
00063 if(version != 1)
00064 {
00065 std::stringstream msg;
00066 msg << "The Volume Texture Description file version '" << version << "' is not supported: " << file;
00067 ErrorMessage(msg.str().c_str());
00068 return false;
00069 }
00070
00071 if(!getline(f, line))
00072 {
00073 std::stringstream msg;
00074 msg << "Unexpected end of file: " << file;
00075 ErrorMessage(msg.str().c_str());
00076 return false;
00077 }
00078
00079 std::istringstream read2(line);
00080 if( (read2 >> width).fail() ||
00081 (read2 >> height).fail() ||
00082 (read2 >> depth).fail() ||
00083 (read2 >> components).fail() )
00084 {
00085 std::stringstream msg;
00086 msg << "Size data could not be read: " << file;
00087 ErrorMessage(msg.str().c_str());
00088 return false;
00089 }
00090
00091 if(components < 1 || components > 2)
00092 {
00093 std::stringstream msg;
00094 msg << "The number of components must be 1 or 2: " << file;
00095 ErrorMessage(msg.str().c_str());
00096 return false;
00097 }
00098
00099 if(!getline(f, line))
00100 {
00101 std::stringstream msg;
00102 msg << "Unexpected end of file: " << file;
00103 ErrorMessage(msg.str().c_str());
00104 return false;
00105 }
00106
00107 std::istringstream read3(line);
00108 if( (read3 >> type).fail() || (read3 >> filename).fail() )
00109 {
00110 std::stringstream msg;
00111 msg << "File type could not be read: " << file;
00112 ErrorMessage(msg.str().c_str());
00113 return false;
00114 }
00115
00116 if(type == "RAW")
00117 {
00118 std::string newPath = path;
00119 newPath += filename;
00120
00121 if( !LoadRAW(newPath.c_str(), width, height, depth, components) )
00122 return false;
00123
00124 loadedVTinfo.width = width;
00125 loadedVTinfo.height = height;
00126 loadedVTinfo.depth = depth;
00127 loadedVTinfo.components = components;
00128 loadedVTinfo.size = width * height * depth * components;
00129
00130 if(info)
00131 *info = loadedVTinfo;
00132
00133 return true;
00134 }
00135
00136 std::stringstream msg;
00137 msg << "Unsuported image type '" << type << "': " << file;
00138 ErrorMessage(msg.str().c_str());
00139 return false;
00140 }
00141
00142
00143 bool VolumeTexture::LoadRAW(const char *filename, int w, int h, int d, int components)
00144 {
00145 if(components != 1)
00146 return false;
00147
00148 std::ifstream f(filename, std::ios::in | std::ios::binary);
00149 if(!f.is_open())
00150 {
00151 std::string msg = "The Volume Texture could not be opened: ";
00152 msg += filename;
00153 ErrorMessage(msg.c_str());
00154 return false;
00155 }
00156
00157 int size = w*h*d*components;
00158 unsigned char *data = new unsigned char[size];
00159 f.read((char*)data, size);
00160
00161
00162 int dim = std::max(w, std::max(h, d));
00163 int paddSize = dim*dim*dim;
00164 unsigned char *image = new unsigned char[paddSize*4];
00165 memset(image, 0, sizeof(unsigned char)*paddSize*4);
00166
00167 int offset = ((dim - d) / 2) * w * h * 4;
00168
00169 Precompute(data, w, h, d, image + offset);
00170
00171 delete [] data;
00172
00173 if(tex)
00174 glDeleteTextures(1, &tex);
00175
00176 glGenTextures(1, &tex);
00177 glBindTexture(GL_TEXTURE_3D, tex);
00178 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00179 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00180 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00181 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00182 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
00183
00184 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, dim, dim, dim, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)image);
00185
00186 glBindTexture(GL_TEXTURE_3D, 0);
00187
00188 delete [] image;
00189
00190 return true;
00191 }
00192
00193
00194 void VolumeTexture::Precompute(const unsigned char *data, int w, int h, int d, unsigned char *res)
00195 {
00196 memset((void*)histogram, 0, sizeof(unsigned int)*256);
00197
00198 for(int k = 0; k < d; k++)
00199 {
00200 for(int j = 0; j < h; j++)
00201 {
00202 for(int i = 0; i < w; i++)
00203 {
00204 Vector3f n = ComputeNormal(data, i, j, k, w, h, d);
00205
00206
00207 int x = (int)((n.x + 1.0f) * 127.0f);
00208 int y = (int)((n.y + 1.0f) * 127.0f);
00209 int z = (int)((n.z + 1.0f) * 127.0f);
00210
00211 int dataValue = data[i + j*w + k*w*h];
00212 histogram[dataValue]++;
00213
00214 int index = 4*(i + w*(j + k*h));
00215 res[index] = dataValue;
00216 res[index + 1] = (unsigned char)x;
00217 res[index + 2] = (unsigned char)y;
00218 res[index + 3] = (unsigned char)z;
00219 }
00220 }
00221 }
00222 }
00223
00224
00225 Vector3f VolumeTexture::ComputeNormal(const unsigned char *data, int x, int y, int z, int w, int h, int d)
00226 {
00227 int x0 = std::min(x + 1, w - 1);
00228 int x1 = std::max(x - 1, 0);
00229
00230 float dx = (data[x0 + y*w + z*w*h] - data[x1 + y*w + z*w*h]) / 2.0f;
00231
00232 int y0 = std::min(y + 1, h - 1);
00233 int y1 = std::max(y - 1, 0);
00234
00235 float dy = (data[x + y0*w + z*w*h] - data[x + y1*w + z*w*h]) / 2.0f;
00236
00237 int z0 = std::min(z + 1, d - 1);
00238 int z1 = std::max(z - 1, 0);
00239
00240 float dz = (data[x + y*w + z0*w*h] - data[x + y*w + z1*w*h]) / 2.0f;
00241
00242 Vector3f g(dx, dy, dz);
00243 if(g.SquaredLength() == 0.0f)
00244 return g;
00245
00246 return -Normalize(g);
00247 }
00248
00249
00250 int VolumeTexture::CopyHistogram(unsigned int *data, int n)
00251 {
00252 int i;
00253
00254 for(i = 0; i < 256 && i < n; i++)
00255 {
00256 data[i] = histogram[i];
00257 }
00258
00259 return 256 - i;
00260 }
00261
00262
00263 void VolumeTexture::Bind(int unit)
00264 {
00265 if(unit < 0 || unit > GL_MAX_TEXTURE_UNITS)
00266 return;
00267
00268 if(boundUnit != -1)
00269 return;
00270
00271 glActiveTexture(GL_TEXTURE0 + unit);
00272 glBindTexture(GL_TEXTURE_3D, tex);
00273
00274 boundUnit = unit;
00275 }
00276
00277
00278 void VolumeTexture::UnBind()
00279 {
00280 if(boundUnit != -1)
00281 {
00282 glActiveTexture(GL_TEXTURE0 + boundUnit);
00283 glBindTexture(GL_TEXTURE_3D, 0);
00284
00285 boundUnit = -1;
00286 }
00287 }