source: trunk/packages/vizservers/nanovis/HeightMap.cpp @ 3597

Last change on this file since 3597 was 3597, checked in by ldelgass, 11 years ago

More refactoring in nanovis flows: Rename FlowCmd? to Flow and move to separate
implementation module. Move statis NanoVis? methods to nanovis.cpp from
FlowCmd?.cpp, remove more unused classes and code.

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