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

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

Begin process of renaming R2 library

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