source: nanovis/trunk/HeightMap.cpp @ 6295

Last change on this file since 6295 was 5715, checked in by ldelgass, 9 years ago

minor cleanup

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