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

Last change on this file since 2953 was 2953, checked in by ldelgass, 12 years ago

Remove unused global origin, make default transfer function a bit more
sensible (used to have full opacity at 0). Fix HeightMap? dtor to use delete[]
instead of free() on array allocated with new[]. Document data response in
protocol.

  • Property svn:eol-style set to native
File size: 18.3 KB
Line 
1 /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
3#include <GL/glew.h>
4#include <Cg/cgGL.h>
5
6#include "Grid.h"
7#include "HeightMap.h"
8#include "ContourLineFilter.h"
9#include "Texture1D.h"
10#include "RenderContext.h"
11
12bool HeightMap::updatePending = false;
13double HeightMap::valueMin = 0.0;
14double HeightMap::valueMax = 1.0;
15
16#define TOPCONTOUR      0
17//#define TOPCONTOUR    1
18HeightMap::HeightMap() :
19    _vertexBufferObjectID(0),
20    _textureBufferObjectID(0),
21    _vertexCount(0),
22    _contour(0),
23    _topContour(0),
24    _tfPtr(0),
25    _opacity(0.5f),
26    _indexBuffer(0),
27    _indexCount(0),
28    _contourColor(1.0f, 0.0f, 0.0f),
29    _contourVisible(false),
30    _topContourVisible(true),
31    _visible(false),
32    _scale(1.0f, 1.0f, 1.0f),
33    _centerPoint(0.0f, 0.0f, 0.0f),
34    _heights(NULL)
35{
36    _shader = new NvShader();
37    _shader->loadFragmentProgram("heightcolor.cg", "main");
38    _tfParam      = _shader->getNamedParameterFromFP("tf");
39    _opacityParam = _shader->getNamedParameterFromFP("opacity");
40}
41
42HeightMap::~HeightMap()
43{
44    reset();
45
46    if (_shader) {
47        delete _shader;
48    }
49    if (_heights != NULL) {
50        delete [] _heights;
51    }
52}
53
54void
55HeightMap::render(graphics::RenderContext *renderContext)
56{
57    glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT | GL_LIGHTING_BIT);
58
59    if (renderContext->getCullMode() == graphics::RenderContext::NO_CULL) {
60        glDisable(GL_CULL_FACE);
61    } else {
62        glEnable(GL_CULL_FACE);
63        glCullFace((GLuint)renderContext->getCullMode());
64    }
65    glPolygonMode(GL_FRONT_AND_BACK, (GLuint)renderContext->getPolygonMode());
66    glShadeModel((GLuint)renderContext->getShadingModel());
67
68    glMatrixMode(GL_MODELVIEW);
69    glPushMatrix();
70
71#ifndef notdef
72    if (_scale.x != 0.0) {
73        glScalef(1 / _scale.x, 1 / _scale.y , 1 / _scale.z);
74    }
75#endif
76    glTranslatef(-_centerPoint.x, -_centerPoint.y, -_centerPoint.z);
77
78    if (_contour != NULL) {
79        glDepthRange(0.001, 1.0);
80    }
81       
82    glEnable(GL_DEPTH_TEST);
83
84    if (_vertexBufferObjectID) {
85        glColor3f(1.0f, 1.0f, 1.0f);
86        glShadeModel(GL_SMOOTH);
87        glEnable(GL_BLEND);
88        glEnableClientState(GL_VERTEX_ARRAY);
89        glDisableClientState(GL_COLOR_ARRAY);
90        glDisableClientState(GL_INDEX_ARRAY);
91        glDisableClientState(GL_NORMAL_ARRAY);
92
93        if (_tfPtr) {
94            // PUT vertex program here
95            //
96            //
97            _shader->bind();
98 
99            cgGLSetTextureParameter(_tfParam, _tfPtr->id());
100            cgGLEnableTextureParameter(_tfParam);
101            cgGLSetParameter1f(_opacityParam, _opacity);
102
103            glEnable(GL_TEXTURE_1D);
104            _tfPtr->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, _textureBufferObjectID);
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 (_tfPtr != NULL) {
128            _tfPtr->getTexture()->deactivate();
129            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
130
131            _shader->unbind();
132        }
133    }
134    glShadeModel(GL_FLAT);
135    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
136
137    if (_contour != NULL) {
138        if (_contourVisible) {
139            glDisable(GL_BLEND);
140            glDisable(GL_TEXTURE_2D);
141            glColor4f(_contourColor.x, _contourColor.y, _contourColor.z,
142                      _opacity /*1.0f*/);
143            glDepthRange (0.0, 0.999);
144            _contour->render();
145        }
146
147#if TOPCONTOUR
148        if (_topContourVisible) {
149            glDisable(GL_BLEND);
150            glDisable(GL_TEXTURE_2D);
151            glColor4f(_contourColor.x, _contourColor.y, _contourColor.z,
152                      _opacity /*1.0f*/);
153            //glDepthRange (0.0, 0.999);
154            _topContour->render();
155        }
156#endif
157        glDepthRange (0.0, 1.0);
158    }
159
160    glPopMatrix();
161    glPopAttrib();
162}
163
164void
165HeightMap::createIndexBuffer(int xCount, int zCount, float* heights)
166{
167    if (_indexBuffer != NULL) {
168        delete [] _indexBuffer;
169        _indexBuffer = NULL;
170    }
171    _indexCount = (xCount - 1) * (zCount - 1) * 6;
172    _indexBuffer = new int[_indexCount];
173   
174    int i, j;
175    int boundaryWidth = xCount - 1;
176    int boundaryHeight = zCount - 1;
177    int* ptr = _indexBuffer;
178    int index1, index2, index3, index4;
179    bool index1Valid, index2Valid, index3Valid, index4Valid;
180    index1Valid = index2Valid = index3Valid = index4Valid = true;
181
182    if (heights) {
183        int ic = 0;
184        for (i = 0; i < boundaryHeight; ++i) {
185            for (j = 0; j < boundaryWidth; ++j) {
186                index1 = i * xCount +j;
187                if (isnan(heights[index1])) index1Valid = false;
188                index2 = (i + 1) * xCount + j;
189                if (isnan(heights[index2])) index2Valid = false;
190                index3 = (i + 1) * xCount + j + 1;
191                if (isnan(heights[index3])) index3Valid = false;
192                index4 = i * xCount + j + 1;
193                if (isnan(heights[index4])) index4Valid = false;
194           
195#ifdef _TRIANGLES_
196                if (index1Valid && index2Valid && index3Valid) {
197                    *ptr = index1; ++ptr;
198                    *ptr = index2; ++ptr;
199                    *ptr = index3; ++ptr;
200                    ++ic;
201                }
202                if (index1Valid && index3Valid && index4Valid) {
203                    *ptr = index1; ++ptr;
204                    *ptr = index3; ++ptr;
205                    *ptr = index4; ++ptr;
206                    ++ic;
207                }
208#else
209                if (index1Valid && index2Valid && index3Valid && index4Valid) {
210                    *ptr = index1; ++ptr;
211                    *ptr = index2; ++ptr;
212                    *ptr = index3; ++ptr;
213                    *ptr = index4; ++ptr;
214                    ++ic;
215                }
216#endif
217            }
218        }
219    } else {
220        for (i = 0; i < boundaryHeight; ++i) {
221            for (j = 0; j < boundaryWidth; ++j) {
222                *ptr = i * xCount + j; ++ptr;
223                *ptr = (i + 1) * xCount + j; ++ptr;
224                *ptr = (i + 1) * xCount + j + 1; ++ptr;
225                *ptr = i * xCount + j; ++ptr;
226                *ptr = (i + 1) * xCount + j + 1; ++ptr;
227                *ptr = i * xCount + j + 1; ++ptr;
228            }
229        }
230    }
231}
232
233void
234HeightMap::reset()
235{
236    if (_vertexBufferObjectID) {
237        glDeleteBuffers(1, &_vertexBufferObjectID);
238        _vertexBufferObjectID = 0;
239    }
240    if (_textureBufferObjectID) {
241        glDeleteBuffers(1, &_textureBufferObjectID);
242        _textureBufferObjectID = 0;
243    }
244    if (_contour != NULL) {
245        delete _contour;
246        _contour = NULL;
247    }
248    if (_indexBuffer != NULL) {
249        delete [] _indexBuffer;
250        _indexBuffer = NULL;
251    }
252}
253
254void
255HeightMap::setHeight(int xCount, int yCount, Vector3 *heights)
256{
257    _vertexCount = xCount * yCount;
258    reset();
259
260    _heights = (float *)heights;
261    float min, max;
262    min = heights[0].y, max = heights[0].y;
263
264    int count = xCount * yCount;
265    for (int i = 0; i < count; ++i) {
266        if (min > heights[i].y) {
267            min = heights[i].y;
268        }
269        if (max < heights[i].y) {
270            max = heights[i].y;
271        }
272    }
273
274    _scale.x = 1.0f;
275    _scale.z = max - min;
276    _scale.y = 1.0f;
277
278    xAxis.setRange(0.0, 1.0);
279    yAxis.setRange(0.0, 1.0);
280    zAxis.setRange(0.0, 1.0);
281    wAxis.setRange(min, max);
282    updatePending = true;
283
284    _centerPoint.set(_scale.x * 0.5, _scale.z * 0.5 + min, _scale.y * 0.5);
285
286    Vector3* texcoord = new Vector3[count];
287    for (int i = 0; i < count; ++i) {
288        texcoord[i].set(0, 0, heights[i].y);
289    }
290   
291    glGenBuffers(1, &_vertexBufferObjectID);
292    glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
293    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof( Vector3 ), heights,
294        GL_STATIC_DRAW);
295    glGenBuffers(1, &_textureBufferObjectID);
296    glBindBuffer(GL_ARRAY_BUFFER, _textureBufferObjectID);
297    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(float) * 3, texcoord,
298        GL_STATIC_DRAW);
299    glBindBuffer(GL_ARRAY_BUFFER, 0);
300   
301    delete [] texcoord;
302   
303    if (_contour != NULL) {
304        delete _contour;
305        _contour = NULL;
306    }
307    ContourLineFilter lineFilter;
308    _contour = lineFilter.create(0.0f, 1.0f, 10, heights, xCount, yCount);
309
310#if TOPCONTOUR
311    ContourLineFilter topLineFilter;
312    topLineFilter.setHeightTop(true);
313    _topContour = topLineFilter.create(0.0f, 1.0f, 10, heights, xCount, yCount);
314#endif
315
316    //if (heightMap)
317    //{
318    //  VertexBuffer* vertexBuffer = new VertexBuffer(VertexBuffer::POSITION3, xCount * yCount, sizeof(Vector3) * xCount * yCount, heightMap, false);
319    this->createIndexBuffer(xCount, yCount, 0);
320    //}
321    //else
322    //{
323    //ERROR("HeightMap::setHeight\n");
324    //}
325}
326
327void
328HeightMap::setHeight(float xMin, float yMin, float xMax, float yMax,
329                     int xNum, int yNum, float *heights)
330{
331    _vertexCount = xNum * yNum;
332    _xNum = xNum, _yNum = yNum;
333    _heights = heights;
334    reset();
335   
336    // Get the min/max of the heights. */
337    float min, max;
338    min = max = heights[0];
339    for (int i = 0; i < _vertexCount; ++i) {
340        if (min > heights[i]) {
341            min = heights[i];
342        } else if (max < heights[i]) {
343            max = heights[i];
344        }
345    }
346#ifdef notdef
347    if (retainScale_) {
348        // Check the units of each axis.  If they are the same, we want to
349        // retain the surface's aspect ratio when transforming coordinates to
350        // the grid. Use the range of the longest axis when the units are the
351        // same. 
352        if (xAxis.units() != NULL) && (xAxis.units() == yAxis.units()) {
353        }
354        if (yAxis.units() != NULL) && (yAxis.units() == zAxis.units()) {
355        }
356    }
357#endif
358
359    wAxis.setRange(min, max);
360    yAxis.setRange(min, max);
361    xAxis.setRange(xMin, xMax);
362    zAxis.setRange(yMin, yMax);
363
364    min = 0.0, max = 1.0;
365    xMin = yMin = min = 0.0;
366    xMax = yMax = max = 1.0;
367    // Save the scales.
368    _scale.x = _scale.y = _scale.z = 1.0;
369
370    updatePending = true;
371
372    _centerPoint.set(0.5, 0.5, 0.5);
373   
374#ifndef notdef
375    Vector3* texcoord = new Vector3[_vertexCount];
376    for (int i = 0; i < _vertexCount; ++i) {
377        texcoord[i].set(0, 0, heights[i]);
378    }
379   
380    Vector3* map = createHeightVertices(xMin, yMin, xMax, yMax, xNum, yNum,
381                                        heights);
382   
383    glGenBuffers(1, &_vertexBufferObjectID);
384    glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
385    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(Vector3), map,
386        GL_STATIC_DRAW);
387    glGenBuffers(1, &_textureBufferObjectID);
388    glBindBuffer(GL_ARRAY_BUFFER, _textureBufferObjectID);
389    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(float) * 3, texcoord,
390        GL_STATIC_DRAW);
391    glBindBuffer(GL_ARRAY_BUFFER, 0);
392   
393    delete [] texcoord;
394   
395   
396    if (_contour != NULL) {
397        delete _contour;
398        _contour = NULL;
399    }
400    ContourLineFilter lineFilter;
401    //lineFilter.transferFunction(_tfPtr);
402    _contour = lineFilter.create(0.0f, 1.0f, 10, map, xNum, yNum);
403   
404#if TOPCONTOUR
405    ContourLineFilter topLineFilter;
406    topLineFilter.setHeightTop(true);
407    _topContour = topLineFilter.create(0.0f, 1.0f, 10, map, xNum, yNum);
408#endif
409    this->createIndexBuffer(xNum, yNum, heights);
410    delete [] map;
411#endif
412}
413
414Vector3 *
415HeightMap::createHeightVertices(float xMin, float yMin, float xMax,
416                                float yMax, int xNum, int yNum, float *height)
417{
418    Vector3* vertices = new Vector3[xNum * yNum];
419
420    Vector3* dstDataPtr = vertices;
421    float* srcDataPtr = height;
422   
423    for (int y = 0; y < yNum; ++y) {
424        float yCoord;
425
426        yCoord = yMin + ((yMax - yMin) * y) / (yNum - 1);
427        for (int x = 0; x < xNum; ++x) {
428            float xCoord;
429
430            xCoord = xMin + ((xMax - xMin) * x) / (xNum - 1);
431            dstDataPtr->set(xCoord, *srcDataPtr, yCoord);
432
433            ++dstDataPtr;
434            ++srcDataPtr;
435        }
436    }
437    return vertices;
438}
439
440/**
441 * \brief Maps the data coordinates of the surface into the grid's axes.
442 */
443void
444HeightMap::mapToGrid(Grid *gridPtr)
445{
446    int count = _xNum * _yNum;
447
448    reset();
449
450    // The range of the grid's y-axis 0..1 represents the distance between the
451    // smallest and largest major ticks for all surfaces plotted.  Translate
452    // this surface's y-values (heights) into the grid's axis coordinates.
453
454    float yScale = 1.0 / (gridPtr->yAxis.max() - gridPtr->yAxis.min());
455    float *p, *q, *pend;
456    float *normHeights = new float[count];
457    for (p = _heights, pend = p + count, q = normHeights; p < pend; p++, q++) {
458        *q = (*p - gridPtr->yAxis.min()) * yScale;
459    }
460    Vector3 *t, *texcoord;
461    texcoord = new Vector3[count];
462    for (t = texcoord, p = normHeights, pend = p + count; p < pend; p++, t++) {
463        t->set(0, 0, *p);
464    }
465
466    // Normalize the mesh coordinates (x and z min/max) the range of the major
467    // ticks for the x and z grid axes as well.
468
469    float xScale, zScale;
470    float xMin, xMax, zMin, zMax;
471
472    xScale = 1.0 / (gridPtr->xAxis.max() - gridPtr->xAxis.min());
473    xMin = (xAxis.min() - gridPtr->xAxis.min()) * xScale;
474    xMax = (xAxis.max() - gridPtr->xAxis.min()) * xScale;
475    zScale = 1.0 / (gridPtr->zAxis.max() - gridPtr->zAxis.min());
476    zMin = (zAxis.min() - gridPtr->zAxis.min()) * zScale;
477    zMax = (zAxis.max() - gridPtr->zAxis.min()) * zScale;
478
479    Vector3* vertices;
480    vertices = createHeightVertices(xMin, zMin, xMax, zMax, _xNum, _yNum,
481        normHeights);
482   
483    glGenBuffers(1, &_vertexBufferObjectID);
484    glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
485    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(Vector3), vertices,
486        GL_STATIC_DRAW);
487    glGenBuffers(1, &_textureBufferObjectID);
488    glBindBuffer(GL_ARRAY_BUFFER, _textureBufferObjectID);
489    glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(float) * 3, texcoord,
490        GL_STATIC_DRAW);
491    glBindBuffer(GL_ARRAY_BUFFER, 0);
492    delete [] texcoord;
493
494    if (_contour != NULL) {
495        delete _contour;
496        _contour = NULL;
497    }
498    ContourLineFilter lineFilter;
499    //lineFilter.transferFunction(_tfPtr);
500    _contour = lineFilter.create(0.0f, 1.0f, 10, vertices, _xNum, _yNum);
501   
502#if TOPCONTOUR
503    ContourLineFilter topLineFilter;
504    topLineFilter.setHeightTop(true);
505    _topContour = topLineFilter.create(0.0f, 1.0f, 10, vertices, _xNum, _yNum);
506#endif
507    this->createIndexBuffer(_xNum, _yNum, normHeights);
508    delete [] normHeights;
509    delete [] vertices;
510}
511
512void
513HeightMap::renderTopview(graphics::RenderContext* renderContext,
514                         int render_width, int render_height)
515{
516    glClear(GL_COLOR_BUFFER_BIT);
517    glPushAttrib(GL_VIEWPORT_BIT);
518    glViewport(0, 0, render_width, render_height);
519    glMatrixMode(GL_PROJECTION);
520    glPushMatrix();
521    glLoadIdentity();
522    //gluOrtho2D(0, render_width, 0, render_height);
523    glOrtho(-.5, .5, -.5, .5, -50, 50);
524    glMatrixMode(GL_MODELVIEW);
525    glPushMatrix();
526    glLoadIdentity();
527
528    glTranslatef(0.0, 0.0, -10.0);
529
530    // put camera rotation and translation
531    //glScalef(1 / _scale.x, 1 / _scale.y , 1 / _scale.z);
532
533    if (renderContext->getCullMode() == graphics::RenderContext::NO_CULL) {
534        glDisable(GL_CULL_FACE);
535    } else {
536        glEnable(GL_CULL_FACE);
537        glCullFace((GLuint) renderContext->getCullMode());
538    }
539
540    glPolygonMode(GL_FRONT_AND_BACK, (GLuint) renderContext->getPolygonMode());
541    glShadeModel((GLuint) renderContext->getShadingModel());
542
543    glPushMatrix();
544
545    //glTranslatef(-_centerPoint.x, -_centerPoint.y, -_centerPoint.z);
546
547    //glScalef(0.01, 0.01, 0.01f);
548    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
549    glTranslatef(-_centerPoint.x, -_centerPoint.y, -_centerPoint.z);
550    if (_contour != NULL) {
551        glDepthRange (0.001, 1.0);
552    }
553       
554    glEnable(GL_DEPTH_TEST);
555
556    glEnable(GL_BLEND);
557    glEnable(GL_TEXTURE_2D);
558    if (_vertexBufferObjectID)
559    {
560        TRACE("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\n");
561        glColor3f(1.0f, 1.0f, 1.0f);
562        glShadeModel(GL_SMOOTH);
563        glEnable(GL_BLEND);
564        glEnableClientState(GL_VERTEX_ARRAY);
565        glDisableClientState(GL_COLOR_ARRAY);
566        glDisableClientState(GL_INDEX_ARRAY);
567        glDisableClientState(GL_NORMAL_ARRAY);
568       
569        if (_tfPtr != NULL) {
570            _shader->bind();
571           
572            cgGLSetTextureParameter(_tfParam, _tfPtr->id());
573            cgGLEnableTextureParameter(_tfParam);
574
575            glEnable(GL_TEXTURE_1D);
576            _tfPtr->getTexture()->activate();
577
578            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
579        } else {
580            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
581        }
582
583        glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferObjectID);
584        glVertexPointer(3, GL_FLOAT, 12, 0);
585
586        glBindBuffer(GL_ARRAY_BUFFER, _textureBufferObjectID);
587        glTexCoordPointer(3, GL_FLOAT, 12, 0);
588
589#define _TRIANGLES_
590#ifdef _TRIANGLES_
591        glDrawElements(GL_TRIANGLES, _indexCount, GL_UNSIGNED_INT,
592                       _indexBuffer);
593#else
594        glDrawElements(GL_QUADS, _indexCount, GL_UNSIGNED_INT,
595                       _indexBuffer);
596#endif
597
598        glBindBuffer(GL_ARRAY_BUFFER, 0);
599
600        glDisableClientState(GL_VERTEX_ARRAY);
601        if (_tfPtr != NULL) {
602            _tfPtr->getTexture()->deactivate();
603            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
604
605            _shader->unbind();
606        }
607    }
608
609    glShadeModel(GL_FLAT);
610    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
611
612    if (_contour != NULL) {
613        if (_contourVisible) {
614            glDisable(GL_BLEND);
615            glDisable(GL_TEXTURE_2D);
616            glColor4f(_contourColor.x, _contourColor.y, _contourColor.z, 1.0f);
617            glDepthRange (0.0, 0.999);
618            _contour->render();
619            glDepthRange (0.0, 1.0);
620        }
621
622#if TOPCONTOUR
623        if (_topContourVisible) {
624            glDisable(GL_BLEND);
625            glDisable(GL_TEXTURE_2D);
626            glColor4f(_contourColor.x, _contourColor.y, _contourColor.z, 1.0f);
627            //glDepthRange (0.0, 0.999);
628            _topContour->render();
629            //glDepthRange (0.0, 1.0);
630        }
631#endif
632    }
633   
634    glPopMatrix();
635    glPopMatrix();
636
637    glMatrixMode(GL_PROJECTION);
638    glPushMatrix();
639    glMatrixMode(GL_MODELVIEW);
640
641    glPopAttrib();
642}
Note: See TracBrowser for help on using the repository browser.