source: trunk/packages/vizservers/nanovis/ZincBlendeReconstructor.cpp @ 3884

Last change on this file since 3884 was 3630, checked in by ldelgass, 11 years ago

Nanovis refactoring to fix problems with scaling and multiple results.
Do rendering in world space to properly place and scale multiple data sets.
Also fix flows to reduce resets of animations. More work toward removing
Cg dependency. Fix panning to convert viewport coords to world coords.

  • Property svn:eol-style set to native
File size: 16.0 KB
RevLine 
[2798]1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
[3502]2/*
3 * Copyright (c) 2004-2013  HUBzero Foundation, LLC
[3611]4 *
5 * Authors:
6 *   Insoo Woo <iwoo@purdue.edu>
[3502]7 */
[800]8#include <stdio.h>
9#include <string.h>
[1053]10#include <stdlib.h>
[2844]11
[3492]12#include <vrmath/Vector3f.h>
13
[3611]14#include "ZincBlendeReconstructor.h"
[601]15#include "ZincBlendeVolume.h"
[3492]16#include "Trace.h"
[601]17
[3611]18using namespace nv;
[3492]19using namespace vrmath;
20
[3611]21ZincBlendeReconstructor *ZincBlendeReconstructor::_instance = NULL;
[806]22
[3611]23ZincBlendeReconstructor::ZincBlendeReconstructor()
[601]24{
25}
26
[3611]27ZincBlendeReconstructor::~ZincBlendeReconstructor()
[601]28{
29}
30
[3611]31ZincBlendeReconstructor *ZincBlendeReconstructor::getInstance()
[601]32{
[2822]33    if (_instance == NULL) {
[3611]34        return (_instance = new ZincBlendeReconstructor());
[601]35    }
36
37    return _instance;
38}
39
[3611]40ZincBlendeVolume *ZincBlendeReconstructor::loadFromFile(const char *fileName)
[601]41{
[800]42    std::ifstream stream;
43    stream.open(fileName, std::ios::binary);
[617]44
[2822]45    ZincBlendeVolume *volume = loadFromStream(stream);
[617]46
47    stream.close();
48
49    return volume;
50}
51
[3611]52ZincBlendeVolume *ZincBlendeReconstructor::loadFromStream(std::istream& stream)
[617]53{
[2822]54    ZincBlendeVolume *volume = NULL;
[3492]55    Vector3f origin, delta;
[617]56    int width = 0, height = 0, depth = 0;
[2822]57    void *data = NULL;
[800]58    int version = 1;
[617]59
60    char str[5][20];
61    do {
62        getLine(stream);
[2822]63        if (buff[0] == '#') {
[800]64            continue;
[2822]65        } else if (strstr((const char*) buff, "object") != 0) {
[3452]66            TRACE("VERSION 1");
[2822]67            version = 1;
68            break;
69        } else if (strstr(buff, "record format") != 0) {
[3452]70            TRACE("VERSION 2");
[2822]71            version = 2;
72            break;
[800]73        }
[2822]74    } while (1);
[617]75
[953]76    if (version == 1) {
77        float dummy;
78
[2822]79        sscanf(buff, "%s%s%s%s%s%d%d%d", str[0], str[1], str[2], str[3], str[4], &width, &height, &depth);
[800]80        getLine(stream);
81        sscanf(buff, "%s%f%f%f", str[0], &(origin.x), &(origin.y), &(origin.z));
82        getLine(stream);
[953]83        sscanf(buff, "%s%f%f%f", str[0], &(delta.x), &dummy, &dummy);
[800]84        getLine(stream);
[953]85        sscanf(buff, "%s%f%f%f", str[0], &dummy, &(delta.y), &dummy);
[800]86        getLine(stream);
[953]87        sscanf(buff, "%s%f%f%f", str[0], &dummy, &dummy, &(delta.z));
[800]88        do {
89            getLine(stream);
[2822]90        } while (strcmp(buff, "<\\HDR>") != 0);
[617]91
[800]92        width = width / 4;
93        height = height / 4;
94        depth = depth / 4;
95        //data = new double[width * height * depth * 8 * 4];
96        data = malloc(width * height * depth * 8 * 4 * sizeof(double));
[2822]97        // 8 atom per cell, 4 double (x, y, z, and probability) per atom
[800]98        try {
[2822]99            stream.read((char *)data, width * height * depth * 8 * 4 * sizeof(double));
100        } catch (...) {
[3452]101            ERROR("Caught exception trying to read stream");
[800]102        }
[617]103
[800]104        volume = buildUp(origin, delta, width, height, depth, data);
[617]105
[800]106        free(data);
[2822]107    } else if (version == 2) {
108        const char *pt;
[800]109        int datacount;
110        double emptyvalue;
111        do {
112            getLine(stream);
[2822]113            if ((pt = strstr(buff, "delta")) != 0) {
[800]114                sscanf(pt, "%s%f%f%f", str[0], &(delta.x), &(delta.y), &(delta.z));
[806]115#ifdef _LOADER_DEBUG_
[3452]116                TRACE("delta : %f %f %f", delta.x, delta.y, delta.z);
[806]117#endif
[2822]118            } else if ((pt = strstr(buff, "datacount")) != 0) {
[800]119                sscanf(pt, "%s%d", str[0], &datacount);
[806]120#ifdef _LOADER_DEBUG_
[3452]121                TRACE("datacount = %d", datacount);
[806]122#endif
[2822]123            } else if ((pt = strstr(buff, "datatype")) != 0) {
[800]124                sscanf(pt, "%s%s", str[0], str[1]);
[2822]125                if (strcmp(str[1], "double64")) {
[800]126                }
[2822]127            } else if ((pt = strstr(buff, "count")) != 0) {
[800]128                sscanf(pt, "%s%d%d%d", str[0], &width, &height, &depth);
[806]129#ifdef _LOADER_DEBUG_
[3452]130                TRACE("width height depth %d %d %d", width, height, depth);
[806]131#endif
[2822]132            } else if ((pt = strstr(buff, "emptymark")) != 0) {
[800]133                sscanf(pt, "%s%lf", str[0], &emptyvalue);
[806]134#ifdef _LOADER_DEBUG_
[3452]135                TRACE("emptyvalue %lf", emptyvalue);
[806]136#endif
[2822]137            } else if ((pt = strstr(buff, "emprymark")) != 0) {
[800]138                sscanf(pt, "%s%lf", str[0], &emptyvalue);
[806]139#ifdef _LOADER_DEBUG_
[3452]140                TRACE("emptyvalue %lf", emptyvalue);
[806]141#endif
[800]142            }
[2822]143        } while (strcmp(buff, "<\\HDR>") != 0 && strcmp(buff, "</HDR>") != 0);
[800]144
145        data = malloc(width * height * depth * 8 * 4 * sizeof(double));
[804]146        memset(data, 0, width * height * depth * 8 * 4 * sizeof(double));
[2822]147        stream.read((char *) data, width * height * depth * 8 * 4 * sizeof(double));
[800]148
149        volume =  buildUp(origin, delta, width, height, depth, datacount, emptyvalue, data);
150        free(data);
[617]151    }
[800]152    return volume;
[601]153}
154
[617]155struct _NvAtomInfo {
156    double indexX, indexY, indexZ;
157    double atom;
[601]158
159    int getIndex(int width, int height) const
160    {
161        // NOTE
[2844]162        // Zinc blende data has different axes from OpenGL
[601]163        // + z -> +x (OpenGL)
164        // + x -> +y (OpenGL)
165        // + y -> +z (OpenGL), But in 3D texture coordinate is the opposite direction of z
[2844]166        // The reason why index is multiplied by 4 is that one unit cell has half of eight atoms,
167        // i.e. four atoms are mapped into RGBA component of one texel
[777]168        //return ((int) (indexZ - 1)+ (int) (indexX - 1) * width + (int) (indexY - 1) * width * height) * 4;
[2822]169        return ((int)(indexX - 1) + (int)(indexY - 1) * width + (int)(indexZ - 1) * width * height) * 4;
[601]170    }
171};
172
173template<class T>
[2822]174inline T _NvMax2(T a, T b)
175{ return ((a >= b)? a : b); }
[601]176
177template<class T>
[2822]178inline T _NvMin2(T a, T b)
179{ return ((a >= b)? a : b); }
[601]180
181template<class T>
[2822]182inline T _NvMax3(T a, T b, T c)
183{ return ((a >= b)? ((a >= c) ? a : c) : ((b >= c)? b : c)); }
[601]184
185template<class T>
[2822]186inline T _NvMin3(T a, T b, T c)
187{ return ((a <= b)? ((a <= c) ? a : c) : ((b <= c)? b : c)); }
[601]188
189template<class T>
[2822]190inline T _NvMax9(T* a, T curMax)
191{ return _NvMax3(_NvMax3(a[0], a[1], a[2]), _NvMax3(a[3], a[4], a[5]), _NvMax3(a[6], a[7], curMax)); }
[601]192
193template<class T>
[2822]194inline T _NvMin9(T* a, T curMax)
195{ return _NvMin3(_NvMax3(a[0], a[1], a[2]), _NvMin3(a[3], a[4], a[5]), _NvMin3(a[6], a[7], curMax)); }
[601]196
[617]197template<class T>
[2822]198inline T _NvMax4(T* a)
199{ return _NvMax2(_NvMax2(a[0], a[1]), _NvMax2(a[2], a[3])); }
[617]200
201template<class T>
[2822]202inline T _NvMin4(T* a)
203{ return _NvMin2(_NvMin2(a[0], a[1]), _NvMin2(a[2], a[3])); }
[617]204
[2822]205ZincBlendeVolume *
[3611]206ZincBlendeReconstructor::buildUp(const Vector3f& origin, const Vector3f& delta,
[2844]207                                   int width, int height, int depth, void *data)
[601]208{
[2822]209    ZincBlendeVolume *zincBlendeVolume = NULL;
[601]210
[617]211    float *fourAnionVolume, *fourCationVolume;
[601]212    int cellCount = width * height * depth;
[617]213    fourAnionVolume = new float[cellCount * sizeof(float) * 4];
214    fourCationVolume = new float[cellCount * sizeof(float) * 4];
[601]215
[2822]216    _NvAtomInfo *srcPtr = (_NvAtomInfo *)data;
[601]217
[777]218    float vmin, vmax, nzero_min;
[2822]219    float *component4A, *component4B;
[601]220    int index;
221
[953]222    nzero_min = 0.0f;           /* Suppress compiler warning. */
[617]223    vmin = vmax = srcPtr->atom;
224
[2822]225    for (int i = 0; i < cellCount; ++i) {
[601]226        index = srcPtr->getIndex(width, height);
[804]227
[806]228#ifdef _LOADER_DEBUG_
[3452]229        TRACE("index %d", index);
[806]230#endif
[804]231
[617]232        component4A = fourAnionVolume + index;
233        component4B = fourCationVolume + index;
[601]234
[2822]235        component4A[0] = (float)srcPtr->atom; srcPtr++;
236        component4A[1] = (float)srcPtr->atom; srcPtr++;
237        component4A[2] = (float)srcPtr->atom; srcPtr++;
238        component4A[3] = (float)srcPtr->atom; srcPtr++;
[617]239     
[2822]240        component4B[0] = (float)srcPtr->atom; srcPtr++;
241        component4B[1] = (float)srcPtr->atom; srcPtr++;
242        component4B[2] = (float)srcPtr->atom; srcPtr++;
243        component4B[3] = (float)srcPtr->atom; srcPtr++;
[601]244
[617]245        vmax = _NvMax3(_NvMax4(component4A), _NvMax4(component4B), vmax);
246        vmin = _NvMin3(_NvMin4(component4A), _NvMin4(component4B), vmin);
[777]247
[2822]248        if (vmin != 0.0 && vmin < nzero_min) {
249            nzero_min = vmin;
[777]250        }
[617]251    }
[601]252
[617]253    double dv = vmax - vmin;
[2822]254    if (vmax != 0.0f) {
255        for (int i = 0; i < cellCount; ++i) {
[617]256            fourAnionVolume[i] = (fourAnionVolume[i] - vmin)/ dv;
257            fourCationVolume[i] = (fourCationVolume[i] - vmin) / dv;
258        }
259    }
[601]260
[3492]261    Vector3f cellSize;
[617]262    cellSize.x = 0.25 / width;
263    cellSize.y = 0.25 / height;
264    cellSize.z = 0.25 / depth;
[601]265
[3630]266    zincBlendeVolume = new ZincBlendeVolume(width, height, depth, 4,
[617]267                                            fourAnionVolume, fourCationVolume,
[777]268                                            vmin, vmax, nzero_min, cellSize);
[601]269
[3630]270    zincBlendeVolume->xAxis.setRange(origin.x, origin.x + delta.x * (width-1));
271    zincBlendeVolume->yAxis.setRange(origin.y, origin.y + delta.y * (height-1));
272    zincBlendeVolume->zAxis.setRange(origin.z, origin.z + delta.z * (depth-1));
273
[601]274    return zincBlendeVolume;
275}
276
[2822]277ZincBlendeVolume *
[3611]278ZincBlendeReconstructor::buildUp(const Vector3f& origin, const Vector3f& delta,
[2822]279                                   int width, int height, int depth,
280                                   int datacount, double emptyvalue, void* data)
[800]281{
[2822]282    ZincBlendeVolume *zincBlendeVolume = NULL;
[800]283    float *fourAnionVolume, *fourCationVolume;
284    int size = width * height * depth * 4;
285    fourAnionVolume = new float[size];
286    fourCationVolume = new float[size];
287
288    memset(fourAnionVolume, 0, size * sizeof(float));
289    memset(fourCationVolume, 0, size * sizeof(float));
290
[2822]291    _NvAtomInfo *srcPtr = (_NvAtomInfo *) data;
[800]292
[2822]293    float *component4A, *component4B;
[800]294    float vmin, vmax, nzero_min;
295    int index;
296    nzero_min = 1e23f;
297    vmin = vmax = srcPtr->atom;
[2822]298    for (int i = 0; i < datacount; ++i) {
[800]299        index = srcPtr->getIndex(width, height);
[806]300
301#ifdef _LOADER_DEBUG_
[3452]302        TRACE("[%d] index %d (width:%lf height:%lf depth:%lf)", i, index, srcPtr->indexX, srcPtr->indexY, srcPtr->indexZ);
[806]303#endif
[804]304
305        if (index < 0) {
[806]306#ifdef _LOADER_DEBUG_
[3452]307            TRACE("There is an invalid data");
[806]308#endif
[804]309            srcPtr +=8;
310            continue;
311        }
312
[800]313        component4A = fourAnionVolume + index;
314        component4B = fourCationVolume + index;
315
316        component4A[0] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
317        component4A[1] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
318        component4A[2] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
319        component4A[3] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
320     
321        component4B[0] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
322        component4B[1] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
323        component4B[2] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
324        component4B[3] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
325
326        vmax = _NvMax3(_NvMax4(component4A), _NvMax4(component4B), vmax);
327        vmin = _NvMin3(_NvMin4(component4A), _NvMin4(component4B), vmin);
328
[2822]329        if (vmin != 0.0 && vmin < nzero_min) {
[800]330            nzero_min = vmin;   
331        }
332    }
333
334    double dv = vmax - vmin;
[2822]335    if (vmax != 0.0f) {
336        for (int i = 0; i < datacount; ++i) {
[800]337            fourAnionVolume[i] = (fourAnionVolume[i] - vmin)/ dv;
338            fourCationVolume[i] = (fourCationVolume[i] - vmin) / dv;
339        }
340    }
341
[3492]342    Vector3f cellSize;
[800]343    cellSize.x = 0.25 / width;
344    cellSize.y = 0.25 / height;
345    cellSize.z = 0.25 / depth;
346
[3630]347    zincBlendeVolume = new ZincBlendeVolume(width, height, depth, 4,
[800]348                                            fourAnionVolume, fourCationVolume,
349                                            vmin, vmax, nzero_min, cellSize);
350
[3630]351    zincBlendeVolume->xAxis.setRange(origin.x, origin.x + delta.x * (width-1));
352    zincBlendeVolume->yAxis.setRange(origin.y, origin.y + delta.y * (height-1));
353    zincBlendeVolume->zAxis.setRange(origin.z, origin.z + delta.z * (depth-1));
354
[800]355    return zincBlendeVolume;
356}
357
[3611]358void ZincBlendeReconstructor::getLine(std::istream& sin)
[617]359{
360    char ch;
361    int index = 0;
362    do {
363        sin.get(ch);
364        if (ch == '\n') break;
365        buff[index++] = ch;
[2822]366        if (ch == '>') {
[617]367            if (buff[1] == '\\')
368                break;
369        }
370    } while (!sin.eof());
371
372    buff[index] = '\0';
[804]373
[806]374#ifdef _LOADER_DEBUG_
[2376]375    TRACE("%s", buff);
[806]376#endif
[617]377}
378
[2822]379ZincBlendeVolume *
[3611]380ZincBlendeReconstructor::loadFromMemory(void *dataBlock)
[804]381{
[2822]382    ZincBlendeVolume *volume = NULL;
[3492]383    Vector3f origin, delta;
[804]384    int width = 0, height = 0, depth = 0;
[2822]385    void *data = NULL;
[804]386    int version = 1;
387
[2822]388    unsigned char *stream = (unsigned char *)dataBlock;
[804]389    char str[5][20];
390    do {
391        getLine(stream);
[2822]392        if (buff[0] == '#') {
[804]393            continue;
[2822]394        } else if (strstr((const char *)buff, "object") != 0) {
[3452]395            TRACE("VERSION 1");
[2822]396            version = 1;
397            break;
398        } else if (strstr(buff, "record format") != 0) {
[3452]399            TRACE("VERSION 2");
[2822]400            version = 2;
401            break;
[804]402        }
[2822]403    } while (1);
[804]404
[2822]405    if (version == 1) {
[953]406        float dummy;
407
[804]408        sscanf(buff, "%s%s%s%s%s%d%d%d", str[0], str[1], str[2], str[3], str[4],&width, &height, &depth);
409        getLine(stream);
410        sscanf(buff, "%s%f%f%f", str[0], &(origin.x), &(origin.y), &(origin.z));
411        getLine(stream);
[953]412        sscanf(buff, "%s%f%f%f", str[0], &(delta.x), &dummy, &dummy);
[804]413        getLine(stream);
[953]414        sscanf(buff, "%s%f%f%f", str[0], &dummy, &(delta.y), &dummy);
[804]415        getLine(stream);
[953]416        sscanf(buff, "%s%f%f%f", str[0], &dummy, &dummy, &(delta.z));
[804]417        do {
418            getLine(stream);
[2822]419        } while (strcmp(buff, "<\\HDR>") != 0);
[804]420
421        width = width / 4;
422        height = height / 4;
423        depth = depth / 4;
424        data = malloc(width * height * depth * 8 * 4 * sizeof(double));
[2822]425        // 8 atom per cell, 4 double (x, y, z, and probability) per atom
426        memcpy(data, stream, width * height * depth * 8 * 4 * sizeof(double));
[804]427
428        volume = buildUp(origin, delta, width, height, depth, data);
429
430        free(data);
[2822]431    } else if (version == 2) {
432        const char *pt;
[804]433        int datacount = -1;
434        double emptyvalue;
435        do {
436            getLine(stream);
[2822]437            if ((pt = strstr(buff, "delta")) != 0) {   
[804]438                sscanf(pt, "%s%f%f%f", str[0], &(delta.x), &(delta.y), &(delta.z));
[806]439#ifdef _LOADER_DEBUG_
[3452]440                TRACE("delta : %f %f %f", delta.x, delta.y, delta.z);
[806]441#endif
[2822]442            } else if ((pt = strstr(buff, "datacount")) != 0) {
[804]443                sscanf(pt, "%s%d", str[0], &datacount);
[3452]444                TRACE("datacount = %d", datacount);
[2822]445            } else if ((pt = strstr(buff, "datatype")) != 0) {
[804]446                sscanf(pt, "%s%s", str[0], str[1]);
[2822]447                if (strcmp(str[1], "double64")) {
[804]448                }
[2822]449            } else if ((pt = strstr(buff, "count")) != 0) {
[804]450                sscanf(pt, "%s%d%d%d", str[0], &width, &height, &depth);
[806]451#ifdef _LOADER_DEBUG_
[3452]452                TRACE("width height depth %d %d %d", width, height, depth);
[806]453#endif
[2822]454            } else if ((pt = strstr(buff, "emptymark")) != 0) {
[804]455                sscanf(pt, "%s%lf", str[0], &emptyvalue);
[806]456#ifdef _LOADER_DEBUG_
[3452]457                TRACE("emptyvalue %lf", emptyvalue);
[806]458#endif
[2822]459            } else if ((pt = strstr(buff, "emprymark")) != 0) {
[804]460                sscanf(pt, "%s%lf", str[0], &emptyvalue);
[806]461#ifdef _LOADER_DEBUG_
[3452]462                TRACE("emptyvalue %lf", emptyvalue);
[806]463#endif
[804]464            }
[2822]465        } while (strcmp(buff, "<\\HDR>") != 0 && strcmp(buff, "</HDR>") != 0);
[804]466
467        if (datacount == -1) datacount = width * height * depth;
468
469        data = malloc(datacount * 8 * 4 * sizeof(double));
470        memset(data, 0, datacount * 8 * 4 * sizeof(double));
471        memcpy(data, stream, datacount * 8 * 4 * sizeof(double));
472
473        volume =  buildUp(origin, delta, width, height, depth, datacount, emptyvalue, data);
474
475        free(data);
476    }
477    return volume;
478}
479
[3611]480void ZincBlendeReconstructor::getLine(unsigned char*& stream)
[804]481{
482    char ch;
483    int index = 0;
484    do {
485        ch = stream[0];
486        ++stream;
487        if (ch == '\n') break;
488        buff[index++] = ch;
[2822]489        if (ch == '>') {
[804]490            if (buff[1] == '\\')
491                break;
492        }
493    } while (1);
494
495    buff[index] = '\0';
496
[806]497#ifdef _LOADER_DEBUG_
[2376]498    TRACE("%s", buff);
[806]499#endif
[804]500}
Note: See TracBrowser for help on using the repository browser.