source: nanovis/branches/1.2/HeightMap.cpp @ 5590

Last change on this file since 5590 was 5551, checked in by ldelgass, 9 years ago

merge r5549:5550 from nanovis trunk

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