You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
739 lines
22 KiB
739 lines
22 KiB
/***************************************************************************
|
|
qsdrvopengl.cpp
|
|
-------------------
|
|
begin : 01-January-2000
|
|
copyright : (C) 2000 by Kamil Dobkowski
|
|
email : kamildobk@poczta.onet.pl
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
#include "qsdrvopengl.h"
|
|
|
|
#ifdef HAVE_GL
|
|
#include "qsconsole.h"
|
|
#include "qsaxes3d.h"
|
|
#include <qapplication.h>
|
|
#include <qpainter.h>
|
|
#include <qpixmap.h>
|
|
#include <qbitmap.h>
|
|
#include <qpicture.h>
|
|
#include <qpen.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
|
|
/**
|
|
* What a mess !
|
|
*/
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSDrvOpenGL::QSDrvOpenGL()
|
|
:QSDrvQt()
|
|
{
|
|
m_alpha = false;
|
|
dpaint = false;
|
|
m_shade_walls = true;
|
|
m_auto_stroke = true;
|
|
m_global_transparency = 0;
|
|
m_stroke_lightness = -45;
|
|
pasize = 0;
|
|
pix = NULL;
|
|
pic = NULL;
|
|
pgl = NULL;
|
|
ppic = NULL;
|
|
points = NULL;
|
|
m_opaint = NULL;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSDrvOpenGL::~QSDrvOpenGL()
|
|
{
|
|
//cout << " open gl destructor " << endl;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSDrvOpenGL *QSDrvOpenGL::copy()
|
|
{
|
|
QSDrvOpenGL *result = new QSDrvOpenGL();
|
|
result->copySettingsFrom( this );
|
|
return result;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::copySettingsFrom( const QSDrvOpenGL *drv )
|
|
{
|
|
QSDrvQt::copySettingsFrom( drv );
|
|
setAlpha( drv->alpha() );
|
|
setShadeWalls( drv->shadeWalls() );
|
|
setGlobalTransparency( drv->globalTransparency() );
|
|
setMeshAutoStroke( drv->meshAutoStroke() );
|
|
setAutoStrokeLightness( drv->meshAutoStrokeLightness() );
|
|
init( drv->parentAxes() );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSDrvOpenGL::CNormals QSDrvOpenGL::cNormals() const
|
|
{
|
|
return VertexNormals;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSDrvOpenGL::CColors QSDrvOpenGL::cColors() const
|
|
{
|
|
return VertexColors;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSDrvOpenGL::COrdering QSDrvOpenGL::cOrdering() const
|
|
// Nearer first not working good with light enabled because
|
|
// further polygons overwrites closer ones ( depth function is LEQUAL )
|
|
{
|
|
return m_alpha || m_axes3->light() ? FurtherFirst : NearerFirst;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::setAlpha( bool enabled )
|
|
{
|
|
m_alpha = enabled;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::setShadeWalls( bool enabled )
|
|
{
|
|
m_shade_walls = enabled;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::setGlobalTransparency( unsigned char value )
|
|
{
|
|
m_global_transparency = value;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::setMeshAutoStroke( bool enabled )
|
|
{
|
|
m_auto_stroke = enabled;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::setAutoStrokeLightness( int value )
|
|
{
|
|
m_stroke_lightness = value;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::glError()
|
|
{
|
|
int error;
|
|
while ( (error=glGetError()) ) {
|
|
switch( error ) {
|
|
case GL_INVALID_ENUM: QSConsole::write("Open GL Error: GL_INVALID_ENUM"); break;
|
|
case GL_INVALID_VALUE: QSConsole::write("Open GL Error: GL_INVALID_VALUE"); break;
|
|
case GL_INVALID_OPERATION: QSConsole::write("Open GL Error: GL_INVALID_OPERATION"); break;
|
|
case GL_STACK_OVERFLOW: QSConsole::write("Open GL Error: GL_STACK_OVERFLOW"); break;
|
|
case GL_STACK_UNDERFLOW: QSConsole::write("Open GL Error: GL_STACK_UNDERFLOW"); break;
|
|
case GL_OUT_OF_MEMORY: QSConsole::write("Open GL Error: GL_OUT_OF_MEMORY"); break;
|
|
default: QSConsole::write("Open GL Error: UNKNOWN"); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::loadMatrix( const double m[4][4] )
|
|
{
|
|
GLdouble M[16];
|
|
for ( int i=0; i<16; i++ ) M[i] = GLdouble( m[i%4][i/4] );
|
|
glLoadMatrixd( M );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::setDC( QPainter *p, double init_dpi, bool delete_painter )
|
|
{
|
|
QSDrvQt::setDC(p,init_dpi,delete_painter);
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
#define MARG 5
|
|
|
|
void QSDrvOpenGL::init( QSAxes3D *parent )
|
|
{
|
|
m_axes3 = parent;
|
|
t = m_axes3->p3D();
|
|
|
|
//
|
|
// Create context
|
|
//
|
|
// pdev - is a paint device on which we draw all stuff
|
|
// OpenGL doesn't support printing so when the external
|
|
// paint device is used pdev is a pixmap, which is next
|
|
// flushed to the external device.
|
|
// paint - is an additional painter for drawing text etc.
|
|
//
|
|
QPaintDevice *gl_dev;
|
|
|
|
m_opaint = m_paint;
|
|
if ( m_opaint->device()->isExtDev() ) {
|
|
//cout << "KMatplot: Creating oixmap, picture and painter " << endl;
|
|
pix = new QPixmap( toInt(m_axes3->canvasRect().size.x),
|
|
toInt(m_axes3->canvasRect().size.y) );
|
|
gl_dev = pix;
|
|
pic = new QPicture();
|
|
ppic = new QPainter( pic );
|
|
m_paint = ppic;
|
|
} else {
|
|
m_paint = m_opaint;
|
|
gl_dev = m_opaint->device();
|
|
}
|
|
|
|
//
|
|
// Context's format.
|
|
//
|
|
QGLFormat f;
|
|
f.setDoubleBuffer( false );
|
|
|
|
//
|
|
//
|
|
// Only if device is an external device ?????????????????????????????????????????????????????????????
|
|
//
|
|
//f.setDirectRendering( FALSE );
|
|
|
|
pgl = new QGLContext( f, gl_dev );
|
|
pgl->create();
|
|
pgl->makeCurrent();
|
|
|
|
//cout << "KMatplot: Checking viewport size. " << endl;
|
|
GLint maxSize[2]; glGetIntegerv( GL_MAX_VIEWPORT_DIMS, maxSize );
|
|
if ( m_axes3->canvasRect().size.x > maxSize[0] ||
|
|
m_axes3->canvasRect().size.y > maxSize[1] ) {
|
|
//cout << "KMatplot: Resizing pixmap. " << endl;
|
|
QSConsole::write( QObject::tr(
|
|
"OpenGL: Trying to set %1, %2 viewport ( probably during printing ). <br>"
|
|
"OpenGL: This OpenGL implementation supports only %3, %4 viewports !<br>")
|
|
.arg(toInt(m_axes3->canvasRect().size.x))
|
|
.arg(toInt(m_axes3->canvasRect().size.y))
|
|
.arg(maxSize[0])
|
|
.arg(maxSize[1])
|
|
);
|
|
if ( pix ) {
|
|
delete pgl;
|
|
pix->resize( maxSize[0], maxSize[1] );
|
|
pgl = new QGLContext( f, pix );
|
|
pgl->create();
|
|
pgl->makeCurrent();
|
|
}
|
|
//cout << "KMatplot: Resizing done. " << endl;
|
|
}
|
|
|
|
if ( pix ) {
|
|
//cout << "KMatplot: Clear pixmap. " << endl;
|
|
QPainter p( pix );
|
|
p.fillRect( pix->rect(), white );
|
|
}
|
|
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::stopDrawing()
|
|
{
|
|
//cout << "KMatplot: Finishing. " << endl;
|
|
|
|
// finish with GL
|
|
if ( pgl ) {
|
|
pgl->makeCurrent();
|
|
glFlush();
|
|
glDeleteLists( plist, 1 );
|
|
}
|
|
|
|
//cout << "KMatplot: Deleted gl lists. " << endl;
|
|
|
|
// finish with QPicture
|
|
if ( ppic ) ppic->end();
|
|
|
|
//cout << "KMatplot: QPicture ended. " << endl;
|
|
|
|
// draw pixmap on painter
|
|
if ( pix ) {
|
|
if ( pix->width() != m_axes3->canvasRect().size.x ||
|
|
pix->height() != m_axes3->canvasRect().size.y ) {
|
|
//cout << "KMatplot: Drawing pixmap.init " << endl;
|
|
double scalex = m_axes3->canvasRect().size.x/pix->width();
|
|
double scaley = m_axes3->canvasRect().size.y/pix->height();
|
|
bool xform = m_opaint->hasWorldXForm();
|
|
m_opaint->setWorldXForm( TRUE );
|
|
m_opaint->saveWorldMatrix();
|
|
m_opaint->scale( scalex, scaley );
|
|
|
|
// Not working when printing
|
|
//pix->setMask( pix->createHeuristicMask() );
|
|
//cout << "KMatplot: Drawing scaled pixmap. " << endl;
|
|
m_opaint->drawPixmap( (int )floor( 0.5 + 1.0/scalex * m_axes3->canvasRect().pos.x ),
|
|
(int )floor( 0.5 + 1.0/scaley * m_axes3->canvasRect().pos.y ),
|
|
*pix );
|
|
m_opaint->restoreWorldMatrix();
|
|
m_opaint->setWorldXForm( xform );
|
|
//cout << "KMatplot: Drawing scaled pixmap.done." << endl;
|
|
} else {
|
|
//cout << "KMatplot: Drawing pixmap. " << endl;
|
|
m_opaint->drawPixmap( toInt(m_axes3->canvasRect().pos.x),
|
|
toInt(m_axes3->canvasRect().pos.y),
|
|
*pix );
|
|
}
|
|
}
|
|
|
|
//cout << "KMatplot: Flushing QPicture!. " << endl;
|
|
|
|
// draw QPicture on painter
|
|
if ( pic ) m_opaint->drawPicture( *pic );
|
|
|
|
//restore oryginal painter
|
|
m_paint = m_opaint;
|
|
|
|
//cout << "KMatplot: Deleting objects !. " << endl;
|
|
|
|
m_opaint = NULL;
|
|
delete ppic; ppic = NULL;
|
|
delete pgl; pgl = NULL;
|
|
delete pix; pix = NULL;
|
|
delete pic; pic = NULL;
|
|
delete points; points = NULL;
|
|
pasize = 0;
|
|
|
|
|
|
QSDrvQt::stopDrawing();
|
|
//cout << "KMatplot: Drawing Finished !. \n\n\n" << endl;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::setCurrentElement( int category, int element )
|
|
{
|
|
if ( category == QSAxes::DatasetCategory && element == 0 ) {
|
|
// Clear the buffer after axis box is drawn, but before the first
|
|
// dataset is drawn.Depth test with the axis box is not needed because
|
|
// all datasets are clipped already to the axis box
|
|
glClear( GL_DEPTH_BUFFER_BIT );
|
|
glDisable( GL_CULL_FACE );
|
|
//cout << " clearing a depth buffer bit " << endl;
|
|
}
|
|
QSDrvQt::setCurrentElement( category, element );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::startDrawing()
|
|
{
|
|
//cout << "KMatplot: Start drawing " << endl;
|
|
QSDrvQt::startDrawing();
|
|
|
|
//
|
|
// Activate context
|
|
//
|
|
pgl->makeCurrent();
|
|
axis_mode = m_axes3->axesOnly();
|
|
//if ( stage > 0 ) trv = m_global_transparency; else trv = 0;
|
|
trv = m_global_transparency;
|
|
|
|
//
|
|
// Dont mess the plot with the axis box.
|
|
//
|
|
glClear( GL_DEPTH_BUFFER_BIT );
|
|
|
|
//
|
|
// Apply modelview matrix.
|
|
//
|
|
double MS[4][4];
|
|
glMatrixMode( GL_MODELVIEW );
|
|
t->copy( MS, t->M );
|
|
loadMatrix( MS );
|
|
glError();
|
|
|
|
//
|
|
// Apply projection matrix.
|
|
//
|
|
double PS[4][4];
|
|
glMatrixMode( GL_PROJECTION );
|
|
t->copy( PS, t->P );
|
|
loadMatrix( PS );
|
|
glError();
|
|
|
|
//
|
|
// now our plot is drawn in ( -1.0, -1.0, 0.0 ) ( 1.0, 1.0, 1.0 ) box
|
|
// an we must rescale its x,y sizes to the viewport, but unfortunately
|
|
// the viewpor is given so, that (0,0) is at the top-left corner, and
|
|
// OpenGL accepts coordinates starting at the bottom-left corner.
|
|
//
|
|
|
|
|
|
//
|
|
// Apply viewport matrix.
|
|
//
|
|
double x;
|
|
double y;
|
|
double w;
|
|
double h;
|
|
|
|
// the same as canvas size and pos.
|
|
t->getViewport( &x,
|
|
&y,
|
|
&w,
|
|
&h,
|
|
NULL,
|
|
NULL );
|
|
|
|
glError();
|
|
// -1 because of pixmap printing
|
|
if ( pix )
|
|
glViewport( GLint(0),
|
|
GLint(0),
|
|
GLsizei(pix->width()-1),
|
|
GLsizei(pix->height()-1) );
|
|
else
|
|
glViewport( GLint(x),
|
|
GLint(m_paint->viewport().height()-h-y),
|
|
GLsizei(w-1),
|
|
GLsizei(h-1) );
|
|
|
|
glError();
|
|
|
|
//
|
|
//
|
|
//
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
glPolygonOffset(1.0, 1.0);
|
|
glEnable( GL_DEPTH_TEST );
|
|
glDepthFunc( GL_LESS );
|
|
glShadeModel(GL_SMOOTH);
|
|
|
|
if ( t->light() ) {
|
|
GLfloat params[4];
|
|
QSGColor color;
|
|
|
|
if ( !m_shade_walls ) {
|
|
glDisable( GL_LIGHTING );
|
|
glDisable( GL_COLOR_MATERIAL );
|
|
} else {
|
|
glEnable(GL_LIGHTING);
|
|
glError();
|
|
glEnable( GL_COLOR_MATERIAL );
|
|
glError();
|
|
}
|
|
|
|
//
|
|
// light settings
|
|
//
|
|
//glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
|
|
glFrontFace( GL_CW );
|
|
glEnable( GL_CULL_FACE );
|
|
//glEnable( GL_NORMALIZE );
|
|
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, 1 );
|
|
|
|
//
|
|
// lightness ( ambient light )
|
|
//
|
|
glEnable(GL_LIGHT0);
|
|
// This simply looks good, no special theory.
|
|
params[0] = params[1] = params[2] = 0.35 +
|
|
(t->ambientLight()+50.0)/64.0 -
|
|
(t->directedLight()+50.0)/64.0;
|
|
params[3] = 1.0;
|
|
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, params );
|
|
glError();
|
|
|
|
//
|
|
// light intensity ( directional light )
|
|
//
|
|
GLfloat ldir[4];
|
|
ldir[0] = (GLfloat )t->lvector.x;
|
|
ldir[1] = (GLfloat )t->lvector.y;
|
|
ldir[2] = (GLfloat )t->lvector.z;
|
|
ldir[3] = (GLfloat )0.0;
|
|
glLightfv(GL_LIGHT0, GL_POSITION, ldir );
|
|
//cout <<" LIGHT VECTOR " << t->lvector.x << "," << t->lvector.y << ","<<t->lvector.z<<endl;
|
|
glError();
|
|
|
|
GLfloat lint[4];
|
|
lint[0] = lint[1] = lint[2] = (t->directedLight()+50.0)/48.0;
|
|
lint[3] = 1.0;
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, lint );
|
|
glError();
|
|
glLightfv(GL_LIGHT0, GL_SPECULAR, lint );
|
|
glError();
|
|
|
|
//glLightfv(GL_LIGHT0, GL_AMBIENT, lint );
|
|
//glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 80.0 );
|
|
|
|
//
|
|
// top
|
|
//
|
|
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
|
|
|
|
//
|
|
// bottom
|
|
//
|
|
color = m_bottom_fill.color;
|
|
params[0] = color.r/255.0;
|
|
params[1] = color.g/255.0;
|
|
params[2] = color.b/255.0;
|
|
params[3] = (color.a-trv)/255.0;
|
|
glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, params );
|
|
glError();
|
|
|
|
} else {
|
|
|
|
glDisable( GL_LIGHTING );
|
|
glDisable( GL_COLOR_MATERIAL );
|
|
|
|
}
|
|
|
|
if ( m_alpha ) {
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
|
|
|
|
// only one time
|
|
//if ( stage == 0 )
|
|
plist = glGenLists(1);
|
|
|
|
glError();
|
|
//cout << "KMatplot: start drawing done. " << endl;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::setClipping( bool enabled )
|
|
{
|
|
QSDrvQt::setClipping( enabled );
|
|
if ( enabled ) {
|
|
// x y z w >= 0
|
|
double cp1[4] = { 0.0, 0.0, 1.0, 0.0 }; // z >= 0
|
|
double cp2[4] = { 0.0, 0.0, -1.0, 1.0 }; // z <= 1
|
|
double cp3[4] = { 1.0, 0.0, 0.0, 0.0 }; // x >= 0
|
|
double cp4[4] = { -1.0, 0.0, 0.0, 1.0 }; // x <= 1
|
|
double cp5[4] = { 0.0, 1.0, 0.0, 0.0 }; // y >= 0
|
|
double cp6[4] = { 0.0, -1.0, 0.0, 1.0 }; // y <= 1
|
|
glClipPlane( GL_CLIP_PLANE0, cp1 );
|
|
glClipPlane( GL_CLIP_PLANE1, cp2 );
|
|
glClipPlane( GL_CLIP_PLANE2, cp3 );
|
|
glClipPlane( GL_CLIP_PLANE3, cp4 );
|
|
glClipPlane( GL_CLIP_PLANE4, cp5 );
|
|
glClipPlane( GL_CLIP_PLANE5, cp6 );
|
|
glEnable( GL_CLIP_PLANE0 );
|
|
glEnable( GL_CLIP_PLANE1 );
|
|
glEnable( GL_CLIP_PLANE2 );
|
|
glEnable( GL_CLIP_PLANE3 );
|
|
glEnable( GL_CLIP_PLANE4 );
|
|
glEnable( GL_CLIP_PLANE5 );
|
|
} else {
|
|
glDisable( GL_CLIP_PLANE0 );
|
|
glDisable( GL_CLIP_PLANE1 );
|
|
glDisable( GL_CLIP_PLANE2 );
|
|
glDisable( GL_CLIP_PLANE3 );
|
|
glDisable( GL_CLIP_PLANE4 );
|
|
glDisable( GL_CLIP_PLANE5 );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::clearCanvas( const QSGFill& f, const QSPt2&, const QSPt2& )
|
|
{
|
|
pgl->makeCurrent();
|
|
glClear( GL_DEPTH_BUFFER_BIT );
|
|
if ( f.style != QSGFill::Transparent ) {
|
|
glClearColor( f.color.r / 255.0,
|
|
f.color.g / 255.0,
|
|
f.color.b / 255.0,
|
|
f.color.a / 255.0 );
|
|
|
|
glClear( GL_COLOR_BUFFER_BIT );
|
|
}
|
|
|
|
lcolor[0] = GLubyte(0);
|
|
lcolor[1] = GLubyte(0);
|
|
lcolor[2] = GLubyte(0);
|
|
lcolor[3] = GLubyte(0);
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
#define EPS 1e-15
|
|
|
|
void QSDrvOpenGL::drawPoly3( const QSPt3f pts[], int npoints,
|
|
const QSPt3f *normals, const QSGFill *colors, const bool *edges, int edgeAutoColor )
|
|
{
|
|
int i;
|
|
pgl->makeCurrent();
|
|
|
|
if ( !axis_mode && colors[0].style != QSGFill::Transparent ) {
|
|
|
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
|
glBegin( GL_POLYGON );
|
|
|
|
for ( i=0; i<npoints; i++ ) {
|
|
|
|
glColor4ub( colors[i].color.r,
|
|
colors[i].color.g,
|
|
colors[i].color.b,
|
|
(GLubyte )max(int(colors[i].color.a)-trv,0));
|
|
|
|
glNormal3d( normals[i+1].x,
|
|
normals[i+1].y,
|
|
normals[i+1].z );
|
|
|
|
if ( i == 0 ||
|
|
fabs(pts[i].x-pts[i-1].x) > EPS ||
|
|
fabs(pts[i].y-pts[i-1].y) > EPS ||
|
|
fabs(pts[i].z-pts[i-1].z) > EPS )
|
|
glVertex3d( pts[i].x, pts[i].y, pts[i].z );
|
|
}
|
|
|
|
glEnd();
|
|
}
|
|
|
|
if ( lcolor[3] ) {
|
|
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
|
glBegin( GL_POLYGON );
|
|
if ( !m_auto_stroke ) glColor4ubv( lcolor );
|
|
for ( i=0; i<npoints; i++ ) {
|
|
|
|
|
|
if ( m_auto_stroke ) {
|
|
int r = colors[i].color.r+m_stroke_lightness;
|
|
int g = colors[i].color.g+m_stroke_lightness;
|
|
int b = colors[i].color.b+m_stroke_lightness;
|
|
|
|
if ( m_stroke_lightness > 0 ) {
|
|
r = min(r,255);
|
|
g = min(g,255);
|
|
b = min(b,255);
|
|
}
|
|
else
|
|
if ( m_stroke_lightness < 0 ) {
|
|
r = max(r,0);
|
|
g = max(g,0);
|
|
b = max(b,0);
|
|
}
|
|
|
|
glColor4ub( (GLubyte )r, (GLubyte )g, (GLubyte )b, colors[i].color.a );
|
|
}
|
|
|
|
glNormal3d( normals[i+1].x,
|
|
normals[i+1].y,
|
|
normals[i+1].z );
|
|
if ( i == 0 ||
|
|
fabs(pts[i].x-pts[i-1].x) > EPS ||
|
|
fabs(pts[i].y-pts[i-1].y) > EPS ||
|
|
fabs(pts[i].z-pts[i-1].z) > EPS )
|
|
glVertex3d( pts[i].x, pts[i].y, pts[i].z );
|
|
}
|
|
|
|
glEnd();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::drawLine3( const QSPt3f& begin, const QSPt3f& end, const QSPt3f norm[2] )
|
|
{
|
|
if ( lcolor[3] ) {
|
|
pgl->makeCurrent();
|
|
glBegin( GL_LINES );
|
|
glColor4ubv( lcolor );
|
|
|
|
// first
|
|
if ( norm )
|
|
glNormal3d( norm[0].x,
|
|
norm[0].y,
|
|
norm[0].z );
|
|
glVertex3d( begin.x, begin.y, begin.z );
|
|
|
|
// end
|
|
if ( norm )
|
|
glNormal3d( norm[1].x,
|
|
norm[1].y,
|
|
norm[1].z );
|
|
|
|
glVertex3d( end.x, end.y, end.z );
|
|
//cout << " GL line from "<<begin.x<<","<<begin.y<<","<<begin.z<<" - "<<end.x<<","<<end.y<<","<<end.z<<endl;
|
|
glEnd();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::setFill( const QSGFill &f )
|
|
// Obsolete. All fill setting is done in drawPoly3()
|
|
{
|
|
glColor4ub( f.color.r,
|
|
f.color.g,
|
|
f.color.b,
|
|
f.color.a );
|
|
|
|
// if stage = 2
|
|
QSDrvQt::setFill( f );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSDrvOpenGL::setLine( const QSGLine &l )
|
|
{
|
|
glLineWidth( l.width?toPixels(l.width):0.1 );
|
|
lcolor[0] = GLubyte(l.color.r);
|
|
lcolor[1] = GLubyte(l.color.g);
|
|
lcolor[2] = GLubyte(l.color.b);
|
|
lcolor[3] = ( l.style == QSGLine::Invisible ? 0 : GLubyte(l.color.a) );
|
|
// if stage == 2
|
|
QSDrvQt::setLine( l );
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
#endif // HAVE_GL
|
|
|
|
//glEnable( GL_LINE_SMOOTH );
|
|
//glShadeModel( GL_FLAT );
|
|
//glEnable( GL_LINE_SMOOTH );
|
|
//glEnable( GL_LINE_SMOOTH );
|
|
//glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
//glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
|
|
|
|
//glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
|
//glLineWidth( 0.5 ) ;
|
|
/*
|
|
if ( stage == 0 && !m_shade_walls ) {
|
|
glDisable( GL_LIGHTING );
|
|
glDisable( GL_COLOR_MATERIAL );
|
|
} else {
|
|
glEnable(GL_LIGHTING);
|
|
glEnable( GL_COLOR_MATERIAL );
|
|
}
|
|
*/ |