source: nanovis/branches/1.1/NvZincBlendeReconstructor.cpp @ 4883

Last change on this file since 4883 was 4830, checked in by ldelgass, 9 years ago

Preallocate full size Rappture buffer for data payloads

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