00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "VolumeTexture.h"
00023 #include "VolumetricData.h"
00024 #include "AtomColor.h"
00025 #include "Scene.h"
00026 #include "VMDApp.h"
00027 #include "Inform.h"
00028
00029 #include <math.h>
00030 #include <stdio.h>
00031
00032 VolumeTexture::VolumeTexture()
00033 : v(NULL), texmap(NULL), texid(0) {
00034
00035 size[0] = size[1] = size[2] = 0;
00036 }
00037
00038 VolumeTexture::~VolumeTexture() {
00039 if (texmap) vmd_dealloc(texmap);
00040 }
00041
00042 void VolumeTexture::setGridData(const VolumetricData *voldata) {
00043 if (v == voldata) return;
00044 v = voldata;
00045 if (texmap) {
00046 vmd_dealloc(texmap);
00047 texmap = NULL;
00048 }
00049 size[0] = size[1] = size[2] = 0;
00050 texid = 0;
00051 }
00052
00053 int VolumeTexture::allocateTextureMap(int npixels) {
00054 texid = 0;
00055 if (texmap) {
00056 vmd_dealloc(texmap);
00057 texmap = NULL;
00058 }
00059 texmap = (unsigned char *) vmd_alloc(npixels*3*sizeof(unsigned char));
00060 if (texmap == NULL) {
00061 msgErr << "Texture map allocation failed, out of memory?" << sendmsg;
00062 return FALSE;
00063 }
00064 memset(texmap, 0, npixels*3*sizeof(unsigned char));
00065 texid = VMDApp::get_texserialnum();
00066 return TRUE;
00067 }
00068
00069 void VolumeTexture::generatePosTexture() {
00070
00071 size[0] = size[1] = size[2] = 32;
00072 int x, y, z;
00073 int addr, addr2;
00074 int num = size[0]*size[1]*size[2];
00075
00076 if (!allocateTextureMap(num)) return;
00077
00078 for (z=0; z<size[2]; z++) {
00079 for (y=0; y<size[1]; y++) {
00080 addr = z * size[0] * size[1] + y * size[0];
00081 for (x=0; x<size[0]; x++) {
00082 addr2 = (addr + x) * 3;
00083 texmap[addr2 ] = (unsigned char) (((float) x / (float) size[0]) * 255.0f);
00084 texmap[addr2 + 1] = (unsigned char) (((float) y / (float) size[1]) * 255.0f);
00085 texmap[addr2 + 2] = (unsigned char) (((float) z / (float) size[2]) * 255.0f);
00086 }
00087 }
00088 }
00089 }
00090
00091
00092 static void HSItoRGB(float h, float s, float i,
00093 unsigned char *r, unsigned char *g, unsigned char *b) {
00094 float rv, gv, bv, t;
00095
00096 t=float(VMD_TWOPI)*h;
00097 rv=(float) (1 + s*sinf(t - VMD_TWOPI/3));
00098 gv=(float) (1 + s*sinf(t));
00099 bv=(float) (1 + s*sinf(t + VMD_TWOPI/3));
00100
00101 t=(float) (254.9999 * i / 2);
00102
00103 *r=(unsigned char)(rv*t);
00104 *g=(unsigned char)(gv*t);
00105 *b=(unsigned char)(bv*t);
00106 }
00107
00108
00109 static int nextpower2(int size) {
00110 int i;
00111 int power;
00112
00113 if (size == 1)
00114 return 1;
00115
00116 power=1;
00117 for (i=0; i<16; i++) {
00118 power <<= 1;
00119 if (power >= size)
00120 return power;
00121 }
00122
00123 return power;
00124 }
00125
00126 void VolumeTexture::generateIndexTexture() {
00127
00128 size[0] = size[1] = size[2] = 32;
00129 int x, y, z;
00130 int addr, addr2, addr3, index;
00131 int num = size[0]*size[1]*size[2];
00132 unsigned char coltable[3 * 4096];
00133
00134 if (!allocateTextureMap(num)) return;
00135
00136
00137 for (index=0; index<4096; index++) {
00138 addr = index * 3;
00139 HSItoRGB(8.0f * index / 4096.0f, 0.75, 1.0,
00140 coltable+addr, coltable+addr+1, coltable+addr+2);
00141 }
00142
00143 for (z=0; z<size[2]; z++) {
00144 for (y=0; y<size[1]; y++) {
00145 addr = z * size[0] * size[1] + y * size[0];
00146 for (x=0; x<size[0]; x++) {
00147 index = addr + x;
00148 addr2 = index * 3;
00149 addr3 = ((int) ((index / (float) num) * 4095)) * 3;
00150 texmap[addr2 ] = coltable[addr3 ];
00151 texmap[addr2 + 1] = coltable[addr3 + 1];
00152 texmap[addr2 + 2] = coltable[addr3 + 2];
00153 }
00154 }
00155 }
00156 }
00157
00158 void VolumeTexture::generateChargeTexture(float vmin, float vmax) {
00159
00160 if (!v) return;
00161
00162 int x, y, z;
00163 int addr, addr2;
00164 int daddr;
00165 float vscale, vrange;
00166
00167 size[0] = v->xsize;
00168 size[1] = v->ysize;
00169 size[2] = v->zsize;
00170 for (int i=0; i<3; i++) {
00171 size[i] = nextpower2(size[i]);
00172 }
00173 int num = size[0]*size[1]*size[2];
00174 if (!allocateTextureMap(num)) return;
00175
00176 vrange = vmax - vmin;
00177 if (fabs(vrange) < 0.00001)
00178 vscale = 0.0f;
00179 else
00180 vscale = 1.00001f / vrange;
00181
00182
00183 for (z=0; z<v->zsize; z++) {
00184 for (y=0; y<v->ysize; y++) {
00185 addr = z * size[0] * size[1] + y * size[0];
00186 daddr = z * v->xsize * v->ysize + y * v->xsize;
00187 for (x=0; x<v->xsize; x++) {
00188 addr2 = (addr + x) * 3;
00189 float level, r, g, b;
00190
00191
00192 level = (v->data[daddr + x] - vmin) * vscale;
00193 level = level < 0 ? 0 :
00194 level > 1 ? 1 : level;
00195
00196
00197 r = (1.0f - level) * 255.0f;
00198 b = level * 255.0f;
00199 if (level < 0.5f) {
00200 g = level * 2.0f * 128.0f;
00201 } else {
00202 g = (0.5f - (level - 0.5f)) * 2.0f * 128.0f;
00203 }
00204
00205 texmap[addr2 ] = (unsigned char) r;
00206 texmap[addr2 + 1] = (unsigned char) g;
00207 texmap[addr2 + 2] = (unsigned char) b;
00208 }
00209 }
00210 }
00211 }
00212
00213 void VolumeTexture::generateHSVTexture(float vmin, float vmax) {
00214 int x, y, z;
00215 int index, addr, addr2, addr3;
00216 int daddr;
00217 float vscale, vrange;
00218 unsigned char coltable[3 * 4096];
00219
00220 size[0] = v->xsize;
00221 size[1] = v->ysize;
00222 size[2] = v->zsize;
00223 for (int i=0; i<3; i++) {
00224 size[i] = nextpower2(size[i]);
00225 }
00226 int num = size[0]*size[1]*size[2];
00227 if (!allocateTextureMap(num)) return;
00228
00229
00230 for (index=0; index<4096; index++) {
00231 addr = index * 3;
00232 HSItoRGB(4.0f * index / 4096.0f, 0.75, 1.0,
00233 coltable+addr, coltable+addr+1, coltable+addr+2);
00234 }
00235
00236
00237 vrange = vmax - vmin;
00238 if (fabs(vrange) < 0.00001)
00239 vscale = 0.0f;
00240 else
00241 vscale = 1.00001f / vrange;
00242
00243
00244 for (z=0; z<v->zsize; z++) {
00245 for (y=0; y<v->ysize; y++) {
00246 addr = z * size[0] * size[1] + y * size[0];
00247 daddr = z * v->xsize * v->ysize + y * v->xsize;
00248 for (x=0; x<v->xsize; x++) {
00249 addr2 = (addr + x) * 3;
00250 float level;
00251
00252
00253 level = (v->data[daddr + x] - vmin) * vscale;
00254 level = level < 0 ? 0 :
00255 level > 1 ? 1 : level;
00256
00257
00258 addr3 = ((int) (level * 4095)) * 3;
00259 texmap[addr2 ] = coltable[addr3 ];
00260 texmap[addr2 + 1] = coltable[addr3 + 1];
00261 texmap[addr2 + 2] = coltable[addr3 + 2];
00262 }
00263 }
00264 }
00265 }
00266
00267 void VolumeTexture::generateColorScaleTexture(float vmin, float vmax, const Scene *scene) {
00268
00269 int x, y, z;
00270 int addr, addr2;
00271 int daddr;
00272 float vscale, vrange;
00273
00274 size[0] = v->xsize;
00275 size[1] = v->ysize;
00276 size[2] = v->zsize;
00277 for (int i=0; i<3; i++) {
00278 size[i] = nextpower2(size[i]);
00279 }
00280 int num = size[0]*size[1]*size[2];
00281 if (!allocateTextureMap(num)) return;
00282
00283 vrange = vmax - vmin;
00284 if (fabs(vrange) < 0.00001)
00285 vscale = 0.0f;
00286 else
00287 vscale = 1.00001f / vrange;
00288
00289
00290 for (z=0; z<v->zsize; z++) {
00291 for (y=0; y<v->ysize; y++) {
00292 addr = z * size[0] * size[1] + y * size[0];
00293 daddr = z * v->xsize * v->ysize + y * v->xsize;
00294 for (x=0; x<v->xsize; x++) {
00295 addr2 = (addr + x) * 3;
00296 float level;
00297
00298
00299
00300
00301 level = (v->data[daddr + x] - vmin) * vscale;
00302
00303 int colindex = (int)(level * MAPCLRS-1);
00304
00305 if (colindex < 0)
00306 colindex = 0;
00307 else if (colindex >= MAPCLRS)
00308 colindex = MAPCLRS-1;
00309
00310 const float *rgb = scene->color_value(MAPCOLOR(colindex));
00311 texmap[addr2 ] = (unsigned char)(rgb[0]*255.0f);
00312 texmap[addr2 + 1] = (unsigned char)(rgb[1]*255.0f);
00313 texmap[addr2 + 2] = (unsigned char)(rgb[2]*255.0f);
00314 }
00315 }
00316 }
00317 }
00318
00319 void VolumeTexture::generateContourLineTexture(float densityperline, float linewidth) {
00320 int x, y, z;
00321 int addr, addr2;
00322 float xp, yp, zp;
00323
00324 printf("Contour lines...\n");
00325 printf("range / densityperline: %f\n", log(v->datamax - v->datamin) / densityperline);
00326
00327 size[0] = nextpower2(v->xsize*2);
00328 size[1] = nextpower2(v->ysize*2);
00329 size[2] = nextpower2(v->zsize*2);
00330 int num = size[0]*size[1]*size[2];
00331 if (!allocateTextureMap(num)) return;
00332
00333
00334 for (z=0; z<size[2]; z++) {
00335 zp = ((float) z / size[2]) * v->zsize;
00336 for (y=0; y<size[1]; y++) {
00337 addr = z * size[0] * size[1] + y * size[0];
00338 yp = ((float) y / size[1]) * v->ysize;
00339 for (x=0; x<size[0]; x++) {
00340 addr2 = (addr + x) * 3;
00341 xp = ((float) x / size[0]) * v->xsize;
00342 float level;
00343
00344 level = float(fmod(log(v->voxel_value_interpolate(xp,yp,zp)), densityperline) / densityperline);
00345
00346 if (level < linewidth) {
00347 texmap[addr2 ] = 0;
00348 texmap[addr2 + 1] = 0;
00349 texmap[addr2 + 2] = 0;
00350 } else {
00351 texmap[addr2 ] = 255;
00352 texmap[addr2 + 1] = 255;
00353 texmap[addr2 + 2] = 255;
00354 }
00355 }
00356 }
00357 }
00358 }
00359
00360
00361 void VolumeTexture::calculateTexgenPlanes(float v0[3], float v1[3], float v2[3], float v3[3]) const {
00362
00363 int i;
00364 if (!texmap || !v) {
00365
00366 vec_zero(v0);
00367 vec_zero(v1);
00368 vec_zero(v2);
00369 vec_zero(v3);
00370 v1[0] = v2[1] = v3[2] = 1;
00371 return;
00372 }
00373
00374
00375
00376
00377
00378
00379 float tscale[3];
00380 tscale[0] = (v->xsize / (float)size[0]) * 0.99999f;
00381 tscale[1] = (v->ysize / (float)size[1]) * 0.99999f;
00382 tscale[2] = (v->zsize / (float)size[2]) * 0.99999f;
00383
00384
00385 float lensq[3];
00386 vec_zero(lensq);
00387 for (i=0; i<3; i++) {
00388 lensq[0] += float(v->xaxis[i] * v->xaxis[i]);
00389 lensq[1] += float(v->yaxis[i] * v->yaxis[i]);
00390 lensq[2] += float(v->zaxis[i] * v->zaxis[i]);
00391 }
00392
00393
00394
00395
00396
00397
00398
00399 float xaxdir[3], yaxdir[3], zaxdir[3];
00400 float nxaxdir[3], nyaxdir[3], nzaxdir[3];
00401 float bxc[3], cxa[3], axb[3];
00402 float tmp;
00403
00404
00405 for (i=0; i<3; i++) {
00406 xaxdir[i] = float(v->xaxis[i]);
00407 yaxdir[i] = float(v->yaxis[i]);
00408 zaxdir[i] = float(v->zaxis[i]);
00409 }
00410
00411
00412 cross_prod(bxc, yaxdir, zaxdir);
00413 tmp = dot_prod(xaxdir, bxc);
00414 for (i=0; i<3; i++) {
00415 nxaxdir[i] = bxc[i] / tmp;
00416 }
00417
00418
00419 cross_prod(cxa, zaxdir, xaxdir);
00420 tmp = dot_prod(yaxdir, cxa);
00421 for (i=0; i<3; i++) {
00422 nyaxdir[i] = cxa[i] / tmp;
00423 }
00424
00425
00426 cross_prod(axb, xaxdir, yaxdir);
00427 tmp = dot_prod(zaxdir, axb);
00428 for (i=0; i<3; i++) {
00429 nzaxdir[i] = axb[i] / tmp;
00430 }
00431
00432
00433
00434 float norigin[3];
00435 for (i=0; i<3; i++)
00436 norigin[i] = float(v->origin[i]);
00437
00438 v0[0] = -dot_prod(norigin, nxaxdir) * tscale[0];
00439 v0[1] = -dot_prod(norigin, nyaxdir) * tscale[1];
00440 v0[2] = -dot_prod(norigin, nzaxdir) * tscale[2];
00441
00442
00443 for (i=0; i<3; i++) {
00444 v1[i] = nxaxdir[i] * tscale[0];
00445 v2[i] = nyaxdir[i] * tscale[1];
00446 v3[i] = nzaxdir[i] * tscale[2];
00447 }
00448 }
00449