source: nanovis/branches/1.1/HeightMap.cpp @ 4804

Last change on this file since 4804 was 4612, checked in by ldelgass, 10 years ago

merge r3597 from trunk

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