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

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