source: nanovis/trunk/HeightMap.cpp @ 5106

Last change on this file since 5106 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: 13.9 KB
Line 
1 /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (c) 2004-2013  HUBzero Foundation, LLC
4 *
5 */
6#include <float.h>
7
8#include <GL/glew.h>
9
10#include <graphics/RenderContext.h>
11
12#include "Grid.h"
13#include "HeightMap.h"
14#include "ContourLineFilter.h"
15#include "Texture1D.h"
16
17using namespace nv;
18using namespace nv::graphics;
19using namespace vrmath;
20
21bool HeightMap::updatePending = false;
22double HeightMap::valueMin = 0.0;
23double HeightMap::valueMax = 1.0;
24
25HeightMap::HeightMap() :
26    _vertexBufferObjectID(0),
27    _texcoordBufferObjectID(0),
28    _vertexCount(0),
29    _contour(NULL),
30    _transferFunc(NULL),
31    _opacity(0.5f),
32    _indexBuffer(NULL),
33    _indexCount(0),
34    _contourColor(1.0f, 0.0f, 0.0f),
35    _contourVisible(false),
36    _visible(false),
37    _scale(1.0f, 1.0f, 1.0f),
38    _centerPoint(0.0f, 0.0f, 0.0f),
39    _heights(NULL)
40{
41    _shader = new Shader();
42    _shader->loadFragmentProgram("heightcolor.cg");
43}
44
45HeightMap::~HeightMap()
46{
47    reset();
48
49    if (_shader != NULL) {
50        delete _shader;
51    }
52    if (_heights != NULL) {
53        delete [] _heights;
54    }
55}
56
57void
58HeightMap::render(RenderContext *renderContext)
59{
60    if (!isVisible())
61        return;
62
63    glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT | GL_LIGHTING_BIT);
64
65    if (renderContext->getCullMode() == RenderContext::NO_CULL) {
66        glDisable(GL_CULL_FACE);
67    } else {
68        glEnable(GL_CULL_FACE);
69        glCullFace((GLuint)renderContext->getCullMode());
70    }
71    glPolygonMode(GL_FRONT_AND_BACK, (GLuint)renderContext->getPolygonMode());
72    glShadeModel((GLuint)renderContext->getShadingModel());
73
74    glMatrixMode(GL_MODELVIEW);
75    glPushMatrix();
76
77#ifndef notdef
78    if (_scale.x != 0.0) {
79        glScalef(1 / _scale.x, 1 / _scale.y , 1 / _scale.z);
80    }
81#endif
82    glTranslatef(-_centerPoint.x, -_centerPoint.y, -_centerPoint.z);
83
84    if (_contour != NULL) {
85        glDepthRange(0.001, 1.0);
86    }
87       
88    glEnable(GL_DEPTH_TEST);
89
90    if (_vertexBufferObjectID) {
91        glColor3f(1.0f, 1.0f, 1.0f);
92        glShadeModel(GL_SMOOTH);
93        glEnable(GL_BLEND);
94        glEnableClientState(GL_VERTEX_ARRAY);
95        glDisableClientState(GL_COLOR_ARRAY);
96        glDisableClientState(GL_INDEX_ARRAY);
97        glDisableClientState(GL_NORMAL_ARRAY);
98
99        if (_transferFunc) {
100            // PUT vertex program here
101            //
102            //
103            _shader->bind();
104            _shader->setFPTextureParameter("tf", _transferFunc->id());
105            _shader->setFPParameter1f("opacity", _opacity);
106
107            glEnable(GL_TEXTURE_1D);
108            _transferFunc->getTexture()->activate();
109 
110            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
111        }
112
113        glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
114        glVertexPointer(3, GL_FLOAT, 12, 0);
115
116        glBindBuffer(GL_ARRAY_BUFFER, _texcoordBufferObjectID);
117        glTexCoordPointer(3, GL_FLOAT, 12, 0);
118
119#define _TRIANGLES_
120#ifdef _TRIANGLES_
121        glDrawElements(GL_TRIANGLES, _indexCount, GL_UNSIGNED_INT,
122                       _indexBuffer);
123#else
124        glDrawElements(GL_QUADS, _indexCount, GL_UNSIGNED_INT,
125                       _indexBuffer);
126#endif
127
128        glBindBuffer(GL_ARRAY_BUFFER, 0);
129
130        glDisableClientState(GL_VERTEX_ARRAY);
131        if (_transferFunc != NULL) {
132            _transferFunc->getTexture()->deactivate();
133            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
134
135            _shader->disableFPTextureParameter("tf");
136            _shader->unbind();
137        }
138    }
139    glShadeModel(GL_FLAT);
140    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
141
142    if (_contour != NULL) {
143        if (_contourVisible) {
144            glDisable(GL_BLEND);
145            glDisable(GL_TEXTURE_2D);
146            glColor4f(_contourColor.x, _contourColor.y, _contourColor.z,
147                      _opacity /*1.0f*/);
148            glDepthRange (0.0, 0.999);
149            _contour->render();
150        }
151
152        glDepthRange (0.0, 1.0);
153    }
154
155    glPopMatrix();
156    glPopAttrib();
157}
158
159void
160HeightMap::createIndexBuffer(int xCount, int zCount, float* heights)
161{
162    if (_indexBuffer != NULL) {
163        delete [] _indexBuffer;
164        _indexBuffer = NULL;
165    }
166    _indexCount = (xCount - 1) * (zCount - 1) * 6;
167    _indexBuffer = new int[_indexCount];
168   
169    int i, j;
170    int boundaryWidth = xCount - 1;
171    int boundaryHeight = zCount - 1;
172    int* ptr = _indexBuffer;
173    int index1, index2, index3, index4;
174    bool index1Valid, index2Valid, index3Valid, index4Valid;
175    index1Valid = index2Valid = index3Valid = index4Valid = true;
176
177    if (heights) {
178        int ic = 0;
179        for (i = 0; i < boundaryHeight; ++i) {
180            for (j = 0; j < boundaryWidth; ++j) {
181                index1 = i * xCount +j;
182                if (isnan(heights[index1])) index1Valid = false;
183                index2 = (i + 1) * xCount + j;
184                if (isnan(heights[index2])) index2Valid = false;
185                index3 = (i + 1) * xCount + j + 1;
186                if (isnan(heights[index3])) index3Valid = false;
187                index4 = i * xCount + j + 1;
188                if (isnan(heights[index4])) index4Valid = false;
189           
190#ifdef _TRIANGLES_
191                if (index1Valid && index2Valid && index3Valid) {
192                    *ptr = index1; ++ptr;
193                    *ptr = index2; ++ptr;
194                    *ptr = index3; ++ptr;
195                    ++ic;
196                }
197                if (index1Valid && index3Valid && index4Valid) {
198                    *ptr = index1; ++ptr;
199                    *ptr = index3; ++ptr;
200                    *ptr = index4; ++ptr;
201                    ++ic;
202                }
203#else
204                if (index1Valid && index2Valid && index3Valid && index4Valid) {
205                    *ptr = index1; ++ptr;
206                    *ptr = index2; ++ptr;
207                    *ptr = index3; ++ptr;
208                    *ptr = index4; ++ptr;
209                    ++ic;
210                }
211#endif
212            }
213        }
214    } else {
215        for (i = 0; i < boundaryHeight; ++i) {
216            for (j = 0; j < boundaryWidth; ++j) {
217                *ptr = i * xCount + j; ++ptr;
218                *ptr = (i + 1) * xCount + j; ++ptr;
219                *ptr = (i + 1) * xCount + j + 1; ++ptr;
220                *ptr = i * xCount + j; ++ptr;
221                *ptr = (i + 1) * xCount + j + 1; ++ptr;
222                *ptr = i * xCount + j + 1; ++ptr;
223            }
224        }
225    }
226}
227
228void
229HeightMap::reset()
230{
231    if (_vertexBufferObjectID) {
232        glDeleteBuffers(1, &_vertexBufferObjectID);
233        _vertexBufferObjectID = 0;
234    }
235    if (_texcoordBufferObjectID) {
236        glDeleteBuffers(1, &_texcoordBufferObjectID);
237        _texcoordBufferObjectID = 0;
238    }
239    if (_contour != NULL) {
240        delete _contour;
241        _contour = NULL;
242    }
243    if (_indexBuffer != NULL) {
244        delete [] _indexBuffer;
245        _indexBuffer = NULL;
246    }
247}
248#if 0
249void
250HeightMap::setHeight(int xCount, int yCount, Vector3f *heights)
251{
252    _vertexCount = xCount * yCount;
253    reset();
254
255    _heights = (float *)heights;
256    float min, max;
257    min = heights[0].y, max = heights[0].y;
258
259    int count = xCount * yCount;
260    for (int i = 0; i < count; ++i) {
261        if (min > heights[i].y) {
262            min = heights[i].y;
263        }
264        if (max < heights[i].y) {
265            max = heights[i].y;
266        }
267    }
268
269    _scale.x = 1.0f;
270    _scale.z = max - min;
271    _scale.y = 1.0f;
272
273    xAxis.setRange(0.0, 1.0);
274    yAxis.setRange(0.0, 1.0);
275    zAxis.setRange(0.0, 1.0);
276    wAxis.setRange(min, max);
277    updatePending = true;
278
279    _centerPoint.set(_scale.x * 0.5, _scale.z * 0.5 + min, _scale.y * 0.5);
280
281    Vector3f* texcoord = new Vector3f[count];
282    for (int i = 0; i < count; ++i) {
283        texcoord[i].set(0, 0, heights[i].y);
284    }
285   
286    glGenBuffers(1, &_vertexBufferObjectID);
287    glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
288    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof( Vector3f ), heights,
289        GL_STATIC_DRAW);
290    glGenBuffers(1, &_texcoordBufferObjectID);
291    glBindBuffer(GL_ARRAY_BUFFER, _texcoordBufferObjectID);
292    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(float) * 3, texcoord,
293        GL_STATIC_DRAW);
294    glBindBuffer(GL_ARRAY_BUFFER, 0);
295   
296    delete [] texcoord;
297   
298    if (_contour != NULL) {
299        delete _contour;
300        _contour = NULL;
301    }
302    ContourLineFilter lineFilter;
303    _contour = lineFilter.create(0.0f, 1.0f, 10, heights, xCount, yCount);
304
305    //if (heightMap)
306    //{
307    //  VertexBuffer* vertexBuffer = new VertexBuffer(VertexBuffer::POSITION3, xCount * yCount, sizeof(Vector3f) * xCount * yCount, heightMap, false);
308    this->createIndexBuffer(xCount, yCount, 0);
309    //}
310    //else
311    //{
312    //ERROR("HeightMap::setHeight");
313    //}
314}
315#endif
316void
317HeightMap::setHeight(float xMin, float yMin, float xMax, float yMax,
318                     int xNum, int yNum, float *heights)
319{
320    _vertexCount = xNum * yNum;
321    _xNum = xNum, _yNum = yNum;
322    _heights = heights;
323    reset();
324   
325    // Get the min/max of the heights. */
326    float min, max;
327    min = max = heights[0];
328    for (int i = 0; i < _vertexCount; ++i) {
329        if (min > heights[i]) {
330            min = heights[i];
331        } else if (max < heights[i]) {
332            max = heights[i];
333        }
334    }
335#ifdef notdef
336    if (retainScale_) {
337        // Check the units of each axis.  If they are the same, we want to
338        // retain the surface's aspect ratio when transforming coordinates to
339        // the grid. Use the range of the longest axis when the units are the
340        // same. 
341        if (xAxis.units() != NULL) && (xAxis.units() == yAxis.units()) {
342        }
343        if (yAxis.units() != NULL) && (yAxis.units() == zAxis.units()) {
344        }
345    }
346#endif
347
348    wAxis.setRange(min, max);
349    yAxis.setRange(min, max);
350    xAxis.setRange(xMin, xMax);
351    zAxis.setRange(yMin, yMax);
352
353    min = 0.0, max = 1.0;
354    xMin = yMin = min = 0.0;
355    xMax = yMax = max = 1.0;
356    // Save the scales.
357    _scale.x = _scale.y = _scale.z = 1.0;
358
359    updatePending = true;
360
361    _centerPoint.set(0.5, 0.5, 0.5);
362   
363#ifndef notdef
364    Vector3f* texcoord = new Vector3f[_vertexCount];
365    for (int i = 0; i < _vertexCount; ++i) {
366        texcoord[i].set(0, 0, heights[i]);
367    }
368   
369    Vector3f* map = createHeightVertices(xMin, yMin, xMax, yMax, xNum, yNum,
370                                        heights);
371   
372    glGenBuffers(1, &_vertexBufferObjectID);
373    glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
374    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(Vector3f), map,
375        GL_STATIC_DRAW);
376    glGenBuffers(1, &_texcoordBufferObjectID);
377    glBindBuffer(GL_ARRAY_BUFFER, _texcoordBufferObjectID);
378    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(float) * 3, texcoord,
379        GL_STATIC_DRAW);
380    glBindBuffer(GL_ARRAY_BUFFER, 0);
381   
382    delete [] texcoord;
383   
384   
385    if (_contour != NULL) {
386        delete _contour;
387        _contour = NULL;
388    }
389    ContourLineFilter lineFilter;
390    //lineFilter.transferFunction(_transferFunc);
391    _contour = lineFilter.create(0.0f, 1.0f, 10, map, xNum, yNum);
392
393    this->createIndexBuffer(xNum, yNum, heights);
394    delete [] map;
395#endif
396}
397
398Vector3f *
399HeightMap::createHeightVertices(float xMin, float yMin, float xMax,
400                                float yMax, int xNum, int yNum, float *height)
401{
402    Vector3f* vertices = new Vector3f[xNum * yNum];
403
404    Vector3f* dstData = vertices;
405    float* srcData = height;
406   
407    for (int y = 0; y < yNum; ++y) {
408        float yCoord;
409
410        yCoord = yMin + ((yMax - yMin) * y) / (yNum - 1);
411        for (int x = 0; x < xNum; ++x) {
412            float xCoord;
413
414            xCoord = xMin + ((xMax - xMin) * x) / (xNum - 1);
415            dstData->set(xCoord, *srcData, yCoord);
416
417            ++dstData;
418            ++srcData;
419        }
420    }
421    return vertices;
422}
423
424/**
425 * \brief Maps the data coordinates of the surface into the grid's axes.
426 */
427void
428HeightMap::mapToGrid(Grid *grid)
429{
430    int count = _xNum * _yNum;
431
432    reset();
433
434    // The range of the grid's y-axis 0..1 represents the distance between the
435    // smallest and largest major ticks for all surfaces plotted.  Translate
436    // this surface's y-values (heights) into the grid's axis coordinates.
437
438    float yScale = 1.0 / (grid->yAxis.max() - grid->yAxis.min());
439    float *p, *q, *pend;
440    float *normHeights = new float[count];
441    for (p = _heights, pend = p + count, q = normHeights; p < pend; p++, q++) {
442        *q = (*p - grid->yAxis.min()) * yScale;
443    }
444    Vector3f *t, *texcoord;
445    texcoord = new Vector3f[count];
446    for (t = texcoord, p = normHeights, pend = p + count; p < pend; p++, t++) {
447        t->set(0, 0, *p);
448    }
449
450    // Normalize the mesh coordinates (x and z min/max) the range of the major
451    // ticks for the x and z grid axes as well.
452
453    float xScale, zScale;
454    float xMin, xMax, zMin, zMax;
455
456    xScale = 1.0 / (grid->xAxis.max() - grid->xAxis.min());
457    xMin = (xAxis.min() - grid->xAxis.min()) * xScale;
458    xMax = (xAxis.max() - grid->xAxis.min()) * xScale;
459    zScale = 1.0 / (grid->zAxis.max() - grid->zAxis.min());
460    zMin = (zAxis.min() - grid->zAxis.min()) * zScale;
461    zMax = (zAxis.max() - grid->zAxis.min()) * zScale;
462
463    Vector3f* vertices;
464    vertices = createHeightVertices(xMin, zMin, xMax, zMax, _xNum, _yNum,
465        normHeights);
466   
467    glGenBuffers(1, &_vertexBufferObjectID);
468    glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
469    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(Vector3f), vertices,
470        GL_STATIC_DRAW);
471    glGenBuffers(1, &_texcoordBufferObjectID);
472    glBindBuffer(GL_ARRAY_BUFFER, _texcoordBufferObjectID);
473    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(float) * 3, texcoord,
474        GL_STATIC_DRAW);
475    glBindBuffer(GL_ARRAY_BUFFER, 0);
476    delete [] texcoord;
477
478    if (_contour != NULL) {
479        delete _contour;
480        _contour = NULL;
481    }
482    ContourLineFilter lineFilter;
483    //lineFilter.transferFunction(_transferFunc);
484    _contour = lineFilter.create(0.0f, 1.0f, 10, vertices, _xNum, _yNum);
485   
486    this->createIndexBuffer(_xNum, _yNum, normHeights);
487    delete [] normHeights;
488    delete [] vertices;
489}
490
491void
492HeightMap::getBounds(Vector3f& bboxMin,
493                     Vector3f& bboxMax) const
494{
495    bboxMin.set(xAxis.min(), yAxis.min(), zAxis.min());
496    bboxMax.set(xAxis.max(), yAxis.max(), zAxis.max());
497}
Note: See TracBrowser for help on using the repository browser.