source: nanovis/tags/1.2.0/HeightMap.cpp @ 6307

Last change on this file since 6307 was 4904, checked in by ldelgass, 9 years ago

Merge serveral changes from trunk. Does not include threading, world space
changes, etc.

  • 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::getWorldSpaceBounds(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.