source: trunk/packages/vizservers/nanovis/dxReaderCommon.cpp @ 3464

Last change on this file since 3464 was 2877, checked in by ldelgass, 13 years ago

Some minor refactoring, also add some more fine grained config.h defines
(e.g. replace NV40 define with feature defines). Add tests for some required
OpenGL extensions (should always check for extensions or base version before
calling entry points from the extension). Also, clamp diffuse and specular
values on input and warn when they are out of range.

  • Property svn:eol-style set to native
File size: 5.1 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2#include "dxReaderCommon.h"
3#include "GradientFilter.h"
4
5#include "Vector3.h"
6#include "stdlib.h"
7
8float *
9merge(float *scalar, float *gradient, int size)
10{
11    float *data = (float *)malloc(sizeof(float) * 4 * size);
12
13    Vector3 *g = (Vector3 *)gradient;
14
15    int ngen = 0, sindex = 0;
16    for (sindex = 0; sindex < size; ++sindex) {
17        data[ngen++] = scalar[sindex];
18        data[ngen++] = 1.0 - g[sindex].x;
19        data[ngen++] = 1.0 - g[sindex].y;
20        data[ngen++] = 1.0 - g[sindex].z;
21    }
22    return data;
23}
24
25void
26normalizeScalar(float *fdata, int count, float min, float max)
27{
28    float v = max - min;
29    if (v != 0.0f) {
30        for (int i = 0; i < count; ++i) {
31            if (fdata[i] != -1.0) {
32                fdata[i] = (fdata[i] - min)/ v;
33            }
34        }
35    }
36}
37
38/**
39 * \brief Compute Sobel filtered gradients for a 3D volume
40 *
41 * This technique is fairly expensive in terms of memory and
42 * running time due to the filter extent.
43 */
44float *
45computeGradient(float *fdata,
46                int width, int height, int depth,
47                float dx, float dy, float dz,
48                float min, float max)
49{
50    float *gradients = (float *)malloc(width * height * depth * 3 *
51                                       sizeof(float));
52    float *tempGradients = (float *)malloc(width * height * depth * 3 *
53                                           sizeof(float));
54    int sizes[3] = { width, height, depth };
55    float spacing[3] = { dx, dy, dz };
56    computeGradients(tempGradients, fdata, sizes, spacing, DATRAW_FLOAT);
57    filterGradients(tempGradients, sizes);
58    quantizeGradients(tempGradients, gradients, sizes, DATRAW_FLOAT);
59    free(tempGradients);
60    normalizeScalar(fdata, width * height * depth, min, max);
61    float *data = merge(fdata, gradients, width * height * depth);
62    free(gradients);
63    return data;
64}
65
66/**
67 * \brief Compute gradients for a 3D volume with cubic cells
68 *
69 * The gradients are estimated using the central difference
70 * method.  This function assumes the data are normalized
71 * to [0,1] with missing data/NaNs represented by a negative
72 * value.
73 *
74 * \param data Data array with X the fastest running. There
75 * should be 4 floats allocated for each node, with the
76 * first float containing the scalar value.  The subsequent
77 * 3 floats will be filled with the x,y,z components of the
78 * gradient vector
79 * \param nx The number of nodes in the X direction
80 * \param ny The number of nodes in the Y direction
81 * \param nz The number of nodes in the Z direction
82 * \param dx The spacing (cell length) in the X direction
83 * \param dy The spacing (cell length) in the Y direction
84 * \param dz The spacing (cell length) in the Z direction
85 */
86void
87computeSimpleGradient(float *data, int nx, int ny, int nz,
88                      float dx, float dy, float dz)
89{
90    bool clampToEdge = true;
91    double borderVal = 0.0;
92
93#define BORDER ((clampToEdge ? data[ngen] : borderVal))
94
95    // Compute the gradient of this data.  BE CAREFUL: center
96    // calculation on each node to avoid skew in either direction.
97    int ngen = 0;
98    for (int iz = 0; iz < nz; iz++) {
99        for (int iy = 0; iy < ny; iy++) {
100            for (int ix = 0; ix < nx; ix++) {
101                // gradient in x-direction
102                double valm1 = (ix == 0) ? BORDER : data[ngen - 4];
103                double valp1 = (ix == nx-1) ? BORDER : data[ngen + 4];
104                if (valm1 < 0.0 || valp1 < 0.0) {
105                    data[ngen+1] = 0.0;
106                } else {
107                    data[ngen+1] = -(valp1-valm1)/(2. * dx);
108                 }
109
110                // gradient in y-direction
111                valm1 = (iy == 0) ? BORDER : data[ngen - 4*nx];
112                valp1 = (iy == ny-1) ? BORDER : data[ngen + 4*nx];
113                if (valm1 < 0.0 || valp1 < 0.0) {
114                    data[ngen+2] = 0.0;
115                } else {
116                    data[ngen+2] = -(valp1-valm1)/(2. * dy);
117                }
118
119                // gradient in z-direction
120                valm1 = (iz == 0) ? BORDER : data[ngen - 4*nx*ny];
121                valp1 = (iz == nz-1) ? BORDER : data[ngen + 4*nx*ny];
122                if (valm1 < 0.0 || valp1 < 0.0) {
123                    data[ngen+3] = 0.0;
124                } else {
125                    data[ngen+3] = -(valp1-valm1)/(2. * dz);
126                }
127                // Normalize and scale/bias to [0,1] range
128                // The volume shader will expand to [-1,1]
129                double len = sqrt(data[ngen+1]*data[ngen+1] +
130                                  data[ngen+2]*data[ngen+2] +
131                                  data[ngen+3]*data[ngen+3]);
132                if (len < 1.0e-6) {
133                    data[ngen+1] = 0.0;
134                    data[ngen+2] = 0.0;
135                    data[ngen+3] = 0.0;
136                } else {
137                    data[ngen+1] = (data[ngen+1]/len + 1.0) * 0.5;
138                    data[ngen+2] = (data[ngen+2]/len + 1.0) * 0.5;
139                    data[ngen+3] = (data[ngen+3]/len + 1.0) * 0.5;
140                }
141                ngen += 4;
142            }
143        }
144    }
145
146#undef BORDER
147}
Note: See TracBrowser for help on using the repository browser.