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

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

Assume baseline requirement of NV40 GPU, which translates to Cg profiles vp40
and fp40, which in turn require NV_vertex_program3 and NV_fragment_program2
assembly shader extensions. Add explicit check for these extensions.

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