summaryrefslogtreecommitdiffstats
path: root/kpovmodeler/pmrendermanager.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit47d455dd55be855e4cc691c32f687f723d9247ee (patch)
tree52e236aaa2576bdb3840ebede26619692fed6d7d /kpovmodeler/pmrendermanager.cpp
downloadtdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.tar.gz
tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kpovmodeler/pmrendermanager.cpp')
-rw-r--r--kpovmodeler/pmrendermanager.cpp1647
1 files changed, 1647 insertions, 0 deletions
diff --git a/kpovmodeler/pmrendermanager.cpp b/kpovmodeler/pmrendermanager.cpp
new file mode 100644
index 00000000..664f0fd9
--- /dev/null
+++ b/kpovmodeler/pmrendermanager.cpp
@@ -0,0 +1,1647 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+**************************************************************************
+
+**************************************************************************
+* *
+* 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. *
+* *
+**************************************************************************/
+
+// conflicting types for INT32 in qt and glx
+#ifndef QT_CLEAN_NAMESPACE
+#define QT_CLEAN_NAMESPACE
+#endif
+
+#include "pmrendermanager.h"
+#include "pmviewstructure.h"
+#include "pmobject.h"
+#include "pmdeclare.h"
+#include "pmcamera.h"
+#include "pmquickcolor.h"
+#include "pmdefaults.h"
+#include "pmgraphicalobject.h"
+#include "pmmath.h"
+
+#include <qptrstack.h>
+#include <qapplication.h>
+#include <qbitmap.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <kconfig.h>
+#include <klocale.h>
+
+#include <time.h>
+#include <stdio.h>
+#include <math.h>
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glu.h> // Only needed for gluPerspective
+
+#include "pmglview.h"
+
+const GLdouble dA = 0.75;
+const GLdouble dB = 0.15;
+
+const GLdouble viewVolumeZ = 1e5;
+
+// Size has to be controlPointSize (see pmglview.h)
+const GLubyte PointBitmap[7] = { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE };
+const GLubyte CrossBitmap[7] = { 0x10, 0x10, 0x10, 0xFE, 0x10, 0x10, 0x10 };
+
+
+const int activeTimeAfterRendering = 2;
+const int maxEventTime = 0;
+const int maxSubdivisions = 32;
+const double subdivisionDistance = 0.05;
+
+
+PMRenderManager* PMRenderManager::s_pManager = 0;
+KStaticDeleter<PMRenderManager> PMRenderManager::s_staticDeleter;
+
+bool PMRenderManager::s_hasOpenGL = true;
+bool PMRenderManager::s_hasOpenGLChecked = false;
+
+PMRenderManager* PMRenderManager::theManager( )
+{
+ if( !s_pManager )
+ s_staticDeleter.setObject( s_pManager, new PMRenderManager( ) );
+ return s_pManager;
+}
+
+PMRenderManager::PMRenderManager( )
+ : QObject( qApp )
+{
+ int i;
+
+ m_bStartTask = false;
+ m_bStopTask = false;
+ m_bTaskIsRunning = false;
+
+ m_graphicalObjectColor[0] = c_defaultGraphicalObjectColor0;
+ m_graphicalObjectColor[1] = c_defaultGraphicalObjectColor1;
+ m_textureColor[0] = c_defaultTextureColor0;
+ m_textureColor[1] = c_defaultTextureColor1;
+ m_axesColor[0] = c_defaultAxesColorX;
+ m_axesColor[1] = c_defaultAxesColorY;
+ m_axesColor[2] = c_defaultAxesColorZ;
+ m_controlPointColor[0] = c_defaultControlPointColor0;
+ m_controlPointColor[1] = c_defaultControlPointColor1;
+ m_backgroundColor = c_defaultBackgroundColor;
+ m_fieldOfViewColor = c_defaultFieldOfViewColor;
+ m_highDetailCameraView = c_defaultHighDetailCameraView;
+ m_nMaxRenderedLines = 1000;
+ m_gridDistance = c_defaultGridDistance;
+ m_gridColor = c_defaultGridColor;
+ m_axesViewStructureCreated = false;
+ m_currentVisibility = 0;
+
+ m_renderTasks.setAutoDelete( true );
+ m_matrixStack.setAutoDelete( true );
+ m_quickColors.setAutoDelete( true );
+
+ m_nViews = 0;
+
+ m_subdivisionViewStructure = PMViewStructure( maxSubdivisions + 1,
+ maxSubdivisions );
+ PMLineArray& lines = m_subdivisionViewStructure.lines( );
+ for( i = 0; i < maxSubdivisions; i++ )
+ lines[i] = PMLine( i, i+1 );
+}
+
+PMRenderManager::~PMRenderManager( )
+{
+ s_pManager = 0;
+}
+
+void PMRenderManager::addView( PMGLView* view, PMObject* active, PMObject* top,
+ PMControlPointList* controlPoints,
+ double aspectRatio, int visibilityLevel,
+ bool graphicalChange )
+{
+ PMRenderTaskListIterator it( m_renderTasks );
+ PMRenderTask* task = 0;
+ bool restart = false;
+ bool first = true;
+
+ for( ; it.current( ) && !task; ++it )
+ {
+ if( it.current( )->view( ) == view )
+ task = it.current( );
+ else
+ first = false;
+ }
+
+ if( task )
+ {
+ if( first )
+ restart = true;
+ else if( graphicalChange )
+ {
+ m_renderTasks.findRef( task );
+ m_renderTasks.take( );
+ m_renderTasks.prepend( task );
+ restart = true;
+ }
+ task->setActiveObject( active );
+ task->setTopLevelObject( top );
+ task->setControlPoints( controlPoints );
+ task->setAspectRatio( aspectRatio );
+ task->setVisibilityLevel( visibilityLevel );
+ }
+ else
+ {
+ task = new PMRenderTask( view, active, top, controlPoints, aspectRatio,
+ visibilityLevel );
+ if( graphicalChange )
+ {
+ m_renderTasks.prepend( task );
+ restart = true;
+ }
+ else
+ {
+ m_renderTasks.append( task );
+ if( m_renderTasks.count( ) == 1 )
+ restart = true;
+ }
+ }
+ if( restart )
+ restartRendering( );
+}
+
+void PMRenderManager::removeView( PMGLView* view )
+{
+ PMRenderTaskListIterator it( m_renderTasks );
+ PMRenderTask* task = 0;
+ bool restart = false;
+
+ for( ; it.current( ) && !task; ++it )
+ if( it.current( )->view( ) == view )
+ task = it.current( );
+
+ if( task )
+ {
+ if( task == m_renderTasks.first( ) )
+ {
+ restart = true;
+ if( m_bTaskIsRunning )
+ emit renderingFinished( task->view( ) );
+ }
+ m_renderTasks.removeRef( task );
+ }
+
+ if( restart )
+ restartRendering( );
+}
+
+bool PMRenderManager::containsTask( PMGLView* view ) const
+{
+ PMRenderTaskListIterator it( m_renderTasks );
+ bool contains = false;
+
+ for( ; it.current( ) && !contains; ++it )
+ if( it.current( )->view( ) == view )
+ contains = true;
+ return contains;
+}
+
+QColor PMRenderManager::controlPointColor( int i ) const
+{
+ if( ( i >= 0 ) && ( i <= 1 ) )
+ return m_controlPointColor[i];
+ return QColor( 0, 0, 0 );
+}
+
+void PMRenderManager::setControlPointColor( int i, const QColor& c )
+{
+ if( ( i >= 0 ) && ( i <= 1 ) )
+ m_controlPointColor[i] = c;
+}
+
+QColor PMRenderManager::graphicalObjectColor( int i ) const
+{
+ if( ( i >= 0 ) && ( i <= 1 ) )
+ return m_graphicalObjectColor[i];
+ return QColor( 0, 0, 0 );
+}
+
+void PMRenderManager::setGraphicalObjectColor( int i, const QColor& c )
+{
+ if( ( i >= 0 ) && ( i <= 1 ) )
+ m_graphicalObjectColor[i] = c;
+}
+
+QColor PMRenderManager::axesColor( int i ) const
+{
+ if( ( i >= 0 ) && ( i <= 2 ) )
+ return m_axesColor[i];
+ return QColor( 0, 0, 0 );
+}
+
+void PMRenderManager::setAxesColor( int i, const QColor& c )
+{
+ if( ( i >= 0 ) && ( i <= 2 ) )
+ m_axesColor[i] = c;
+}
+
+void PMRenderManager::setGridDistance( int d )
+{
+ if( d >= 20 )
+ m_gridDistance = d;
+}
+
+void PMRenderManager::restartRendering( )
+{
+ if( !m_bTaskIsRunning && !m_bStartTask )
+ startTimer( 0 );
+
+ m_bStartTask = true;
+ m_bStopTask = false;
+}
+
+void PMRenderManager::slotStopRendering( )
+{
+ m_bStopTask = true;
+ m_bStartTask = false;
+
+ if( m_bTaskIsRunning )
+ if( m_pCurrentTask )
+ emit renderingFinished( m_pCurrentTask->view( ) );
+ m_renderTasks.clear( );
+}
+
+void PMRenderManager::timerEvent( QTimerEvent* )
+{
+ killTimers( );
+ renderTask( );
+}
+
+void PMRenderManager::renderTask( )
+{
+ m_bTaskIsRunning = true;
+ emit renderingStarted( );
+
+ int r, g, b;
+ bool disableView = false;
+
+ while( m_bStartTask && !m_bStopTask )
+ {
+ m_bStartTask = false;
+
+ // render the views sequential
+ while( m_renderTasks.first( ) && !m_bStopTask && !m_bStartTask )
+ {
+ // reset the member variables for rendering
+ m_pCurrentTask = m_renderTasks.first( );
+ m_pCurrentGlView = m_pCurrentTask->view( );
+ emit renderingStarted( m_pCurrentGlView );
+
+ m_renderedLines = 0;
+ m_selected = false;
+ m_pDeselectObject = 0;
+ m_matrixStack.clear( );
+ m_quickColorObjects.clear( );
+ m_quickColors.clear( );
+ m_currentColor = m_graphicalObjectColor[0];
+ m_specialCameraMode = false;
+ m_currentVisibility = 0;
+ m_visibilityStack.clear( );
+
+ if( m_bStopTask || m_bStartTask )
+ break;
+ m_pCurrentGlView->makeCurrent( );
+
+ m_backgroundColor.rgb( &r, &g, &b );
+ glClearColor( r/255.0, g/255.0, b/255.0, 1.0 );
+ glPointSize( controlPointSize );
+ glEnable( GL_DEPTH_TEST );
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ glViewport( 0, 0, ( GLint ) m_pCurrentGlView->width( ),
+ ( GLint ) m_pCurrentGlView->height( ) );
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ disableView = false;
+ if( m_pCurrentGlView->type( ) == PMGLView::PMViewCamera )
+ {
+ if( m_pCurrentGlView->camera( ) )
+ {
+ if( m_pCurrentGlView->camera( )->cameraType( )
+ == PMCamera::Omnimax )
+ disableView = true;
+ }
+ else
+ disableView = true;
+ }
+
+ if( !disableView )
+ setProjection( );
+
+ glLoadIdentity( );
+
+ glDisable( GL_DEPTH_TEST );
+ if( m_pCurrentGlView->type( ) == PMGLView::PMViewCamera )
+ renderFieldOfView( );
+ else
+ renderGrid( );
+ renderDescription( );
+ glEnable( GL_DEPTH_TEST );
+
+ if( !disableView )
+ {
+ renderAxes( );
+
+ renderObject( m_pCurrentTask->topLevelObject( ) );
+ if( !m_bStopTask && ! m_bStartTask )
+ renderControlPoints( );
+ }
+
+ if( !m_bStopTask && ! m_bStartTask )
+ {
+ glXWaitX( );
+ emit aboutToUpdate( m_pCurrentGlView );
+ if( m_bStopTask || m_bStartTask )
+ break;
+ glXWaitX( );
+ m_pCurrentGlView->swapBuffers( );
+ glFinish( );
+ glXWaitGL( );
+ emit renderingFinished( m_pCurrentGlView );
+ if( m_bStopTask || m_bStartTask )
+ break;
+ qApp->processEvents( maxEventTime );
+ if( m_bStopTask || m_bStartTask )
+ break;
+ m_renderTasks.removeFirst( );
+ }
+ }
+ }
+
+ emit renderingFinished( );
+
+ m_bStopTask = false;
+ m_bStartTask = false;
+ m_bTaskIsRunning = false;
+}
+
+void PMRenderManager::renderObject( PMObject* objectToRender )
+{
+ bool children = false;
+ PMGraphicalObject* go = 0;
+
+ m_objectToRenderStack.append( objectToRender );
+
+ if( objectToRender->isA( "GraphicalObject" ) )
+ {
+ go = ( PMGraphicalObject* ) objectToRender;
+ m_visibilityStack.push( m_currentVisibility );
+ if( go->isVisibilityLevelRelative( ) )
+ m_currentVisibility += go->visibilityLevel( );
+ else
+ m_currentVisibility = go->visibilityLevel( );
+ }
+
+ if( !m_selected )
+ {
+ if( objectToRender->isSelected( ) )
+ {
+ m_selected = true;
+ m_pDeselectObject = objectToRender;
+ if( objectToRender->hasTransformationMatrix( ) )
+ if( objectToRender->parent( ) )
+ m_pDeselectObject = objectToRender->parent( );
+ }
+ }
+
+ if( ( m_pCurrentGlView->type( ) != PMGLView::PMViewCamera )
+ || ( objectToRender != ( PMObject* ) ( m_pCurrentGlView->camera( ) ) ) )
+ {
+ PMObject* obj = 0;
+
+ children = objectToRender->lastChild( ) || objectToRender->linkedObject( );
+ if( children )
+ {
+ bool stop;
+
+ PMMatrix* matrix;
+ if( m_specialCameraMode )
+ matrix = new PMMatrix( m_viewTransformation );
+ else
+ matrix = new PMMatrix( PMMatrix::modelviewMatrix( ) );
+ m_matrixStack.push( matrix );
+
+ // render the children and the linked object
+ obj = objectToRender->lastChild( );
+ while( obj && !m_bStopTask && !m_bStartTask )
+ {
+ if( !obj->isA( "Declare" ) )
+ renderObject( obj );
+ if( !m_bStopTask && !m_bStartTask )
+ {
+ do
+ {
+ // Do not render declares
+ obj = obj->prevSibling( );
+ if( !obj )
+ stop = true;
+ else
+ stop = !obj->isA( "Declare" );
+ }
+ while( !stop );
+ }
+ }
+ if( !m_bStopTask && !m_bStartTask )
+ {
+ obj = objectToRender->linkedObject( );
+ if( obj )
+ renderObject( obj );
+ }
+ }
+
+
+ if( !m_bStopTask && !m_bStartTask )
+ {
+ // children of the object are rendered
+ // render the object
+
+ if( objectToRender == m_pCurrentTask->activeObject( ) )
+ {
+ if( m_specialCameraMode )
+ m_controlPointTransformation = m_viewTransformation;
+ else
+ m_controlPointTransformation = PMMatrix::modelviewMatrix( );
+ }
+
+ if( objectToRender->type( ) == "QuickColor" )
+ {
+ PMQuickColor* qc = ( PMQuickColor* ) objectToRender;
+ PMObjectListIterator it( m_objectToRenderStack );
+ bool pofound = false;
+ it.toLast( );
+
+ while( it.current( ) && !pofound )
+ {
+ if( it.current( )->isA( "GraphicalObject" ) )
+ pofound = true;
+ else
+ --it;
+ }
+ if( pofound )
+ {
+ if( m_quickColorObjects.top( ) != it.current( ) )
+ {
+ m_quickColorObjects.push( it.current( ) );
+ m_quickColors.push( new QColor( m_currentColor ) );
+ m_currentColor = qc->color( ).toQColor( );
+ }
+ }
+ }
+
+ PMViewStructure* vs = objectToRender->viewStructure( );
+ if( objectToRender->hasTransformationMatrix( ) || vs )
+ {
+ // object has transformation or view structure
+ if( vs )
+ {
+ if( ( m_currentVisibility <= m_pCurrentTask->visibilityLevel( ) )
+ || ( objectToRender == m_pCurrentTask->activeObject( ) ) )
+ {
+ // render the view structure.
+ // call qApp->processEvents( ) each m_nMaxRenderedLines rendered
+ // lines
+ if( m_selected )
+ setGLColor( m_graphicalObjectColor[ 1 ] );
+ else
+ setGLColor( m_currentColor );
+
+ renderViewStructure( *vs );
+ }
+ }
+ else if( objectToRender->hasTransformationMatrix( ) )
+ {
+ if( m_specialCameraMode )
+ m_viewTransformation = m_viewTransformation * objectToRender->transformationMatrix( );
+ else
+ glMultMatrixd( objectToRender->transformationMatrix( ).data( ) );
+ }
+ }
+ // end rendering
+ }
+ }
+ if( !m_bStopTask && !m_bStartTask )
+ {
+ if( children )
+ {
+ PMMatrix* matrix = m_matrixStack.pop( );
+
+ if( matrix )
+ {
+ if( m_specialCameraMode )
+ m_viewTransformation = (*matrix);
+ else
+ glLoadMatrixd( matrix->data( ) );
+ delete matrix;
+ matrix = 0;
+ }
+ }
+ if( m_selected )
+ {
+ if( m_pDeselectObject == objectToRender )
+ {
+ m_selected = false;
+ m_pDeselectObject = 0;
+ }
+ }
+ if( m_quickColorObjects.top( ) == objectToRender )
+ {
+ m_quickColorObjects.pop( );
+ QColor* col = m_quickColors.pop( );
+ if( col )
+ {
+ m_currentColor = *col;
+ delete col;
+ col = 0;
+ }
+ }
+ }
+
+ if( go )
+ m_currentVisibility = m_visibilityStack.pop( );
+
+ m_objectToRenderStack.removeLast( );
+}
+
+void PMRenderManager::renderViewStructure( PMViewStructure& vs )
+{
+ if( m_specialCameraMode )
+ {
+ PMPointArray points = vs.points( );
+ points.detach( );
+ transformProjection( points.data( ), points.size( ),
+ m_pCurrentGlView->camera( ) );
+
+ if( m_highDetailCameraView )
+ {
+ // subdivide line
+ PMLineArray& lines = vs.lines( );
+ PMPointArray& utPoints = vs.points( );
+ int numLines = lines.size( );
+ PMPointArray& sdPoints = m_subdivisionViewStructure.points( );
+ PMLineArray& sdLines = m_subdivisionViewStructure.lines( );
+ int i, li, sd;
+ double distance;
+ PMPoint start, end, dir;
+
+ for( i = 0; ( i < numLines ) && !m_bStopTask && !m_bStartTask; i++ )
+ {
+ // calculate screen distance
+ start = points[lines[i].startPoint( )];
+ end = points[lines[i].endPoint( )];
+ dir[0] = ( end[0] - start[0] ) / m_anglex;
+ dir[1] = ( end[1] - start[1] ) / m_angley;
+ distance = sqrt( dir[0] * dir[0] + dir[1] * dir[1] );
+
+ // calculate number of subdivisions
+ sd = ( int ) ( distance / subdivisionDistance );
+ if( sd > 1 )
+ {
+ // calculate subdivision
+ if( sd > maxSubdivisions )
+ sd = maxSubdivisions;
+
+ sdPoints[0] = start;
+ sdPoints[sd] = end;
+
+ start = utPoints[lines[i].startPoint( )];
+ end = utPoints[lines[i].endPoint( )];
+ dir[0] = ( end[0] - start[0] ) / sd;
+ dir[1] = ( end[1] - start[1] ) / sd;
+ dir[2] = ( end[2] - start[2] ) / sd;
+
+ for( li = 1; li < sd; li++ )
+ {
+ sdPoints[li][0] = start[0] + li * dir[0];
+ sdPoints[li][1] = start[1] + li * dir[1];
+ sdPoints[li][2] = start[2] + li * dir[2];
+ }
+ // transform points (first and last are already transformed)
+ transformProjection( sdPoints.data( ) + 1, sd - 1,
+ m_pCurrentGlView->camera( ) );
+ renderViewStructureSimple( sdPoints, sdLines, sd );
+ }
+ else
+ {
+ sdPoints[0] = start;
+ sdPoints[1] = end;
+ renderViewStructureSimple( sdPoints, sdLines, 1 );
+ }
+ }
+ }
+ else
+ renderViewStructureSimple( points, vs.lines( ) );
+ }
+ else
+ renderViewStructureSimple( vs.points( ), vs.lines( ) );
+}
+
+void PMRenderManager::renderViewStructureSimple( PMPointArray& points,
+ PMLineArray& lines,
+ int numberOfLines )
+{
+ GLuint* linesData = ( GLuint* ) ( lines.data( ) );
+ unsigned int vsLines = 0;
+ unsigned int rl;
+
+ if( numberOfLines < 0 )
+ vsLines = lines.size( );
+ else
+ vsLines = ( unsigned ) numberOfLines;
+
+ glEnableClientState( GL_VERTEX_ARRAY );
+ glVertexPointer( 3, GL_DOUBLE, 0, points.data( ) );
+
+ while( ( vsLines > 0 ) && !m_bStopTask && !m_bStartTask )
+ {
+ rl = m_nMaxRenderedLines - m_renderedLines;
+ if( rl > vsLines )
+ rl = vsLines;
+
+ glDrawElements( GL_LINES, rl * 2,
+ GL_UNSIGNED_INT, linesData );
+
+ m_renderedLines += rl;
+ if( m_renderedLines >= m_nMaxRenderedLines )
+ {
+ m_renderedLines = 0;
+ qApp->processEvents( maxEventTime );
+ if( !m_bStopTask && !m_bStartTask )
+ m_pCurrentGlView->makeCurrent( );
+ }
+
+ vsLines -= rl;
+ linesData = linesData + ( rl * 2 );
+ }
+
+ glDisableClientState( GL_VERTEX_ARRAY );
+}
+
+void PMRenderManager::transformProjection( PMPoint* points, int size,
+ PMCamera* camera )
+{
+ int i;
+ PMPoint* data = points;
+ PMPoint p;
+ double cameraAngle = camera->angle( ) * M_PI / 180.0;
+ double rad, phi, h;
+
+ if( approxZero( cameraAngle ) )
+ cameraAngle = M_PI;
+
+ switch( camera->cameraType( ) )
+ {
+ case PMCamera::Perspective:
+ case PMCamera::Orthographic:
+ break;
+
+ case PMCamera::UltraWideAngle:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+ h = sqrt( p[0] * p[0] + p[1] * p[1] + p[2] * p[2] );
+ if( !approxZero( h ) )
+ {
+ p[0] /= h;
+ p[1] /= h;
+ }
+
+ (*data)[0] = asin( p[0] );
+ (*data)[1] = asin( p[1] );
+ if( p[2] > 0 )
+ {
+ (*data)[0] = M_PI - (*data)[0];
+ (*data)[1] = M_PI - (*data)[1];
+ }
+ (*data)[2] = -h;
+
+ data++;
+ }
+ break;
+
+ case PMCamera::FishEye:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ phi = atan2( p[1], p[0] );
+ rad = atan2( sqrt( p[0] * p[0] + p[1] * p[1] ), -p[2] );
+
+ (*data)[0] = rad * cos( phi );
+ (*data)[1] = rad * sin( phi );
+ (*data)[2] = -sqrt( p[0] * p[0] + p[1] * p[1] + p[2] * p[2] );
+
+ data++;
+ }
+ break;
+
+ case PMCamera::Panoramic:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+
+ (*data)[0] = atan2( p[0], -p[2] );
+ (*data)[1] = atan2( p[1], sqrt( p[0] * p[0] + p[2] * p[2] ) );
+ (*data)[2] = -sqrt( p[0] * p[0] + p[1] * p[1] + p[2] * p[2] );
+
+ data++;
+ }
+ break;
+
+ case PMCamera::Cylinder:
+ switch( camera->cylinderType( ) )
+ {
+ case 1:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+
+ h = sqrt( p[0] * p[0] + p[2] * p[2] );
+ if( approxZero( h ) )
+ h = 1e-5;
+
+ (*data)[0] = atan2( p[0], -p[2] ) / cameraAngle;
+ (*data)[1] = p[1] / h;
+ (*data)[2] = -h;
+
+ data++;
+ }
+ break;
+
+ case 2:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+
+ h = sqrt( p[1] * p[1] + p[2] * p[2] );
+ if( approxZero( h ) )
+ h = 1e-5;
+
+ (*data)[0] = p[0] / h;
+ (*data)[1] = atan2( p[1], -p[2] ) / cameraAngle;
+ (*data)[2] = -h;
+
+ data++;
+ }
+ break;
+
+ case 3:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+
+ h = sqrt( p[0] * p[0] + p[2] * p[2] );
+ if( approxZero( h ) )
+ h = 1e-5;
+
+ (*data)[0] = atan2( p[0], -p[2] ) / cameraAngle;
+ (*data)[1] = p[1];
+ (*data)[2] = -h;
+
+ data++;
+ }
+ break;
+
+ case 4:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+
+ h = sqrt( p[1] * p[1] + p[2] * p[2] );
+ if( approxZero( h ) )
+ h = 1e-5;
+
+ (*data)[0] = p[0];
+ (*data)[1] = atan2( p[1], -p[2] ) / cameraAngle;
+ (*data)[2] = -h;
+
+ data++;
+ }
+ break;
+ }
+ break;
+
+ case PMCamera::Omnimax:
+ break;
+
+ }
+}
+
+void PMRenderManager::renderControlPoints( )
+{
+ if( ( m_pCurrentGlView->type( ) == PMGLView::PMViewCamera )
+ && ( m_pCurrentGlView->camera( ) == m_pCurrentTask->activeObject( ) ) )
+ return;
+
+ if( m_specialCameraMode )
+ m_viewTransformation = m_controlPointTransformation;
+ else
+ glLoadMatrixd( m_controlPointTransformation.data( ) );
+
+ PMControlPointList* cplist = m_pCurrentTask->controlPoints( );
+ if( cplist->count( ) > 0 )
+ {
+ PMControlPointListIterator it( *cplist );
+ PMControlPoint* cp;
+ PMPoint v;
+ const GLubyte* bitmap = 0;
+
+ // draw extra control point lines
+ setGLColor( m_graphicalObjectColor[1] );
+ for( it.toFirst( ); it.current( ); ++it )
+ {
+ cp = it.current( );
+ if( cp->hasExtraLine( ) )
+ {
+ PMPoint s = PMPoint( cp->extraLineStart( ) );
+ PMPoint e = PMPoint( cp->extraLineEnd( ) );
+
+ if( m_specialCameraMode )
+ {
+ transformProjection( &s, 1, m_pCurrentGlView->camera( ) );
+ transformProjection( &e, 1, m_pCurrentGlView->camera( ) );
+ }
+
+ glBegin( GL_LINES );
+ glVertex3d( s[0], s[1], s[2] );
+ glVertex3d( e[0], e[1], e[2] );
+ glEnd( );
+ }
+ }
+
+ glDisable( GL_DEPTH_TEST );
+ // draw not selected control points
+ setGLColor( m_controlPointColor[0] );
+ for( it.toFirst( ); it.current( ); ++it )
+ {
+ cp = it.current( );
+
+ if( cp->display( ) )
+ {
+ v = PMPoint( cp->position( ) );
+ if( m_specialCameraMode )
+ transformProjection( &v, 1, m_pCurrentGlView->camera( ) );
+ switch( cp->displayType( ) )
+ {
+ case PMControlPoint::CPPoint:
+ if( !cp->selected( ) )
+ bitmap = PointBitmap;
+ break;
+ case PMControlPoint::CPCross:
+ bitmap = CrossBitmap;
+ break;
+ }
+
+ glRasterPos3d( v[0], v[1], v[2] );
+ if( bitmap )
+ glBitmap( controlPointSize, controlPointSize,
+ controlPointSize/2, controlPointSize/2,
+ 0, 0, bitmap );
+ }
+ }
+ // draw selected control points
+ setGLColor( m_controlPointColor[1] );
+ for( it.toFirst( ); it.current( ); ++it )
+ {
+ cp = it.current( );
+
+ if( cp->selected( ) && cp->display( ) )
+ {
+ v = PMPoint( cp->position( ) );
+ if( m_specialCameraMode )
+ transformProjection( &v, 1, m_pCurrentGlView->camera( ) );
+ if( cp->displayType( ) == PMControlPoint::CPPoint )
+ bitmap = PointBitmap;
+
+ glRasterPos3d( v[0], v[1], v[2] );
+ if( bitmap )
+ glBitmap( controlPointSize, controlPointSize,
+ controlPointSize/2, controlPointSize/2,
+ 0, 0, bitmap );
+ }
+ }
+ }
+}
+
+void PMRenderManager::renderAxes( )
+{
+ int i;
+
+ if( !m_axesViewStructureCreated )
+ {
+ m_axesViewStructure[0] = PMViewStructure( 6, 9 );
+ PMPointArray& points = m_axesViewStructure[0].points( );
+ PMLineArray& lines = m_axesViewStructure[0].lines( );
+
+ lines[0] = PMLine( 0, 1 );
+ lines[1] = PMLine( 1, 2 );
+ lines[2] = PMLine( 1, 3 );
+ lines[3] = PMLine( 1, 4 );
+ lines[4] = PMLine( 1, 5 );
+ lines[5] = PMLine( 2, 3 );
+ lines[6] = PMLine( 3, 4 );
+ lines[7] = PMLine( 4, 5 );
+ lines[8] = PMLine( 5, 2 );
+
+ points[0] = PMPoint( 0.0, 0.0, 0.0 );
+ points[1] = PMPoint( 1.0, 0.0, 0.0 );
+ points[2] = PMPoint( dA, dB, dB );
+ points[3] = PMPoint( dA, -dB, dB );
+ points[4] = PMPoint( dA, -dB, -dB );
+ points[5] = PMPoint( dA, dB, -dB );
+
+ m_axesViewStructure[1] = m_axesViewStructure[0];
+ PMPointArray& points1 = m_axesViewStructure[1].points( );
+ points1.detach( );
+
+ points1[0] = PMPoint( 0.0, 0.0, 0.0 );
+ points1[1] = PMPoint( 0.0, 1.0, 0.0 );
+ points1[2] = PMPoint( dB, dA, dB );
+ points1[3] = PMPoint( -dB, dA, dB );
+ points1[4] = PMPoint( -dB, dA, -dB );
+ points1[5] = PMPoint( dB, dA, -dB );
+
+ m_axesViewStructure[2] = m_axesViewStructure[0];
+ PMPointArray& points2 = m_axesViewStructure[2].points( );
+ points2.detach( );
+
+ points2[0] = PMPoint( 0.0, 0.0, 0.0 );
+ points2[1] = PMPoint( 0.0, 0.0, 1.0 );
+ points2[2] = PMPoint( dB, dB, dA );
+ points2[3] = PMPoint( -dB, dB, dA );
+ points2[4] = PMPoint( -dB, -dB, dA );
+ points2[5] = PMPoint( dB, -dB, dA );
+
+ m_axesViewStructureCreated = true;
+ }
+
+ glEnable( GL_DEPTH_TEST );
+ for( i = 0; i < 3; i++ )
+ {
+ setGLColor( m_axesColor[i] );
+ renderViewStructure( m_axesViewStructure[i] );
+ }
+}
+
+PMMatrix PMRenderManager::viewTransformation( PMCamera* c ) const
+{
+ PMVector location, lookAt, sky;
+ PMMatrix m;
+
+ sky = c->sky( );
+ location = c->location( );
+ lookAt = c->lookAt( );
+
+ if( approxZero( sky.abs( ) ) )
+ sky = PMVector( 0.0, 1.0, 0.0 );
+ if( approxZero( ( location - lookAt ).abs( ) ) )
+ lookAt = location + PMVector( 0.0, 0.0, 1.0 );
+
+ m = c->transformedWith( );
+ if( m.canBuildInverse( ) )
+ return PMMatrix::viewTransformation( location, lookAt, sky ) * m.inverse( );
+ return PMMatrix::viewTransformation( location, lookAt, sky );
+}
+
+void PMRenderManager::setProjection( )
+{
+ PMGLView::PMViewType type = m_pCurrentGlView->type( );
+ PMCamera* camera = m_pCurrentGlView->camera( );
+ int width = m_pCurrentGlView->width( );
+ int height = m_pCurrentGlView->height( );
+
+ if( type == PMGLView::PMViewCamera )
+ {
+ if( camera )
+ setCameraProjection( );
+ }
+ else
+ {
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity( );
+
+ double d = m_pCurrentGlView->scale( );
+
+ // TODO calculating the z clipping plane
+ glOrtho( -width/2, width/2, -height/2, height/2,
+ -viewVolumeZ, viewVolumeZ );
+ glScaled( d, d, d );
+ glTranslated( m_pCurrentGlView->translationX( ),
+ m_pCurrentGlView->translationY( ), 0 );
+
+ switch( type )
+ {
+ case PMGLView::PMViewPosZ:
+ break;
+ case PMGLView::PMViewNegZ:
+ glRotated( 180.0, 0.0, 1.0, 0.0 );
+ break;
+ case PMGLView::PMViewNegY:
+ glRotated( 90.0, 1.0, 0.0, 0.0 );
+ break;
+ case PMGLView::PMViewPosY:
+ glRotated( -90.0, 1.0, 0.0, 0.0 );
+ break;
+ case PMGLView::PMViewPosX:
+ glRotated( 90.0, 0.0, 1.0, 0.0 );
+ break;
+ case PMGLView::PMViewNegX:
+ glRotated( -90.0, 0.0, 1.0, 0.0 );
+ break;
+ default:
+ break;
+ }
+
+ glScaled( 1.0, 1.0, -1.0 );
+
+ glMatrixMode( GL_MODELVIEW );
+ m_pCurrentGlView->setProjectionUpToDate( true );
+ }
+}
+
+void PMRenderManager::setCameraProjection( )
+{
+ PMCamera* camera = m_pCurrentGlView->camera( );
+ int width = m_pCurrentGlView->width( );
+ int height = m_pCurrentGlView->height( );
+ double angle = M_PI / 2.0;
+ double modeAspect, viewAspect, cameraAspect;
+
+ m_viewTransformation = viewTransformation( camera );
+ m_upLength = camera->up( ).abs( );
+ if( approxZero( m_upLength ) )
+ m_upLength = 1.0;
+ m_rightLength = camera->right( ).abs( );
+ if( approxZero( m_rightLength ) )
+ m_rightLength = 1.0;
+ m_directionLength = camera->direction( ).abs( );
+ if( approxZero( m_directionLength ) )
+ m_directionLength = 1.0;
+
+ if( camera->isAngleEnabled( ) )
+ angle = camera->angle( ) * M_PI / 180.0;
+
+ m_anglex = 0.5;
+ m_angley = 0.5;
+ if( ( angle <= 0.0 ) || ( angle > 2 * M_PI ) )
+ angle = M_PI;
+
+ switch( camera->cameraType( ) )
+ {
+ case PMCamera::Perspective:
+ // If angle wasn't specified determine one from right and direction
+ if( !camera->isAngleEnabled( ) )
+ angle = 2 * atan2( 0.5 * m_rightLength, m_directionLength );
+ break;
+ case PMCamera::UltraWideAngle:
+ m_anglex = angle / ( 2.0 * M_PI );
+ m_angley = angle / ( 2.0 * M_PI );
+ m_specialCameraMode = true;
+ break;
+ case PMCamera::FishEye:
+ m_anglex = angle / 2.0;
+ m_angley = angle / 2.0;
+ m_specialCameraMode = true;
+ break;
+ case PMCamera::Panoramic:
+ m_anglex = M_PI / 2.0;
+ m_angley = M_PI / 2.0;
+ m_specialCameraMode = true;
+ break;
+ case PMCamera::Cylinder:
+ m_anglex = 0.5;
+ m_angley = 0.5;
+ m_specialCameraMode = true;
+ break;
+ case PMCamera::Omnimax:
+ m_specialCameraMode = true;
+ break;
+ default:
+ break;
+ }
+
+ modeAspect = m_pCurrentTask->aspectRatio( );
+ if( approxZero( modeAspect ) )
+ modeAspect = 1.0;
+ cameraAspect = camera->aspect( );
+ if( approxZero( cameraAspect ) )
+ cameraAspect = 1.0;
+ viewAspect = ( double ) width / ( double ) height;
+ if( approxZero( viewAspect ) )
+ viewAspect = 1.0;
+
+ if( viewAspect > modeAspect )
+ m_anglex *= viewAspect / modeAspect;
+ else
+ m_angley *= modeAspect / viewAspect;
+
+
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity( );
+
+
+ PMVector up, right, direction;
+ double handedness;
+ PMMatrix m;
+
+ up = camera->up( );
+ right = camera->right( );
+ direction = camera->direction( );
+
+ if( approxZero( m_upLength ) )
+ up = PMVector( 0.0, 1.0, 0.0 );
+ if( approxZero( m_rightLength ) )
+ right = PMVector( 1.0, 0.0, 0.0 );
+ if( approxZero( m_directionLength ) )
+ direction = PMVector( 0.0, 0.0, 1.0 );
+
+ handedness = PMVector::dot( PMVector::cross( up, direction ), right );
+
+ switch( camera->cameraType( ) )
+ {
+ case PMCamera::Perspective:
+ if( ( angle <= 0.0 ) || ( angle >= M_PI ) )
+ angle = M_PI / 2.0;
+
+ // opengl needs the vertical angle
+ if( viewAspect < modeAspect )
+ angle = atan( tan( angle / 2.0 ) / cameraAspect * modeAspect
+ / viewAspect ) * 360.0 / M_PI;
+ else
+ angle = atan( tan( angle / 2.0 ) / cameraAspect )
+ * 360.0 / M_PI;
+
+ gluPerspective( angle, cameraAspect * viewAspect / modeAspect,
+ 0.001, viewVolumeZ );
+
+ if( handedness > 0 )
+ glScaled( -1.0, 1.0, 1.0 );
+
+ glMultMatrixd( m_viewTransformation.data( ) );
+ break;
+
+ case PMCamera::Orthographic:
+ m_anglex = m_rightLength / 2.0;
+ m_angley = m_upLength / 2.0;
+
+ if( viewAspect > modeAspect )
+ m_anglex *= viewAspect / modeAspect;
+ else
+ m_angley *= modeAspect / viewAspect;
+
+ glOrtho( -m_anglex, m_anglex, -m_angley, m_angley,
+ 0, viewVolumeZ );
+
+ if( handedness > 0 )
+ glScaled( -1.0, 1.0, 1.0 );
+
+ glMultMatrixd( m_viewTransformation.data( ) );
+ break;
+
+ case PMCamera::UltraWideAngle:
+ case PMCamera::FishEye:
+ case PMCamera::Panoramic:
+ case PMCamera::Cylinder:
+ case PMCamera::Omnimax:
+ glOrtho( -m_anglex, m_anglex, -m_angley, m_angley,
+ -viewVolumeZ, viewVolumeZ );
+
+ if( handedness > 0 )
+ glScaled( -1.0, 1.0, 1.0 );
+ break;
+ }
+
+ glMatrixMode( GL_MODELVIEW );
+ m_pCurrentGlView->setProjectionUpToDate( true );
+}
+
+void PMRenderManager::renderFieldOfView( )
+{
+ if( m_pCurrentGlView->type( ) == PMGLView::PMViewCamera )
+ {
+ PMCamera* camera = m_pCurrentGlView->camera( );
+
+ if( camera )
+ {
+ int width = m_pCurrentGlView->width( );
+ int height = m_pCurrentGlView->height( );
+ double modeAspect, viewAspect;
+ int d, vx1, vx2, vy1, vy2;
+
+ modeAspect = m_pCurrentTask->aspectRatio( ); //camera->aspect( );
+ if( approxZero( modeAspect ) )
+ modeAspect = 1.0;
+ viewAspect = ( double ) width / ( double ) height;
+
+ if( viewAspect < modeAspect )
+ {
+ vx1 = 0;
+ vx2 = width - 1;
+
+ d = ( int ) ( height - width / modeAspect + 0.5 ) / 2;
+
+ vy1 = d;
+ vy2 = height - d - 1;
+ }
+ else
+ {
+ vy1 = 0;
+ vy2 = height - 1;
+
+ d = ( int ) ( height * modeAspect );
+
+ d = ( width - d ) / 2;
+ vx1 = d;
+ vx2 = width - d - 1;
+ }
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix( );
+ glLoadIdentity( );
+ glOrtho( 0, width, 0, height, -2, 2 );
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix( );
+ glLoadIdentity( );
+
+ setGLColor( m_fieldOfViewColor );
+ glDisable( GL_DEPTH_TEST );
+
+ if( camera->cameraType( ) == PMCamera::Omnimax )
+ renderString( i18n( "not supported" ), 5.0,
+ height - qApp->fontMetrics( ).height( ) * 2 - 2 );
+ else if( m_specialCameraMode && !m_highDetailCameraView )
+ renderString( i18n( "approximated" ), 5.0,
+ height - qApp->fontMetrics( ).height( ) * 2 - 2 );
+
+ glBegin( GL_LINE_LOOP );
+
+ glVertex2d( vx1, vy1 );
+ glVertex2d( vx2, vy1 );
+ glVertex2d( vx2, vy2 );
+ glVertex2d( vx1, vy2 );
+
+ glEnd( );
+ glEnable( GL_DEPTH_TEST );
+
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix( );
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix( );
+ }
+ }
+}
+
+void PMRenderManager::renderGrid( )
+{
+ double scale = m_pCurrentGlView->scale( );
+
+ if( scale >= 0 )
+ {
+ // calculate the views grid distance
+ double viewGridDistance = pow( 10.0, ceil( log10( ( double ) m_gridDistance / scale ) ) );
+ int sd = ( int ) ( viewGridDistance * scale + 0.5 );
+ if( ( sd * 0.2 ) > m_gridDistance )
+ viewGridDistance *= 0.2;
+ else if( ( sd * 0.5 ) > m_gridDistance )
+ viewGridDistance *= 0.5;
+
+ // draw the grid
+ double x1, x2, y1, y2, sx, sy;
+ double x, y;
+ int gi;
+ double screenx, screeny;
+ double signx = 1.0, signy = 1.0;
+
+ int height = m_pCurrentGlView->height( );
+ int width = m_pCurrentGlView->width( );
+ double transX = m_pCurrentGlView->translationX( );
+ double transY = m_pCurrentGlView->translationY( );
+ int fontHeight = qApp->fontMetrics( ).height( );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix( );
+ glLoadIdentity( );
+ glOrtho( -width/2, width/2, -height/2, height/2, -2, 2 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix( );
+ glLoadIdentity( );
+
+ setGLColor( m_gridColor );
+ glDisable( GL_DEPTH_TEST );
+
+ switch( m_pCurrentGlView->type( ) )
+ {
+ case PMGLView::PMViewPosX:
+ signx = -1.0;
+ break;
+ case PMGLView::PMViewPosY:
+ signy = -1.0;
+ break;
+ case PMGLView::PMViewNegZ:
+ signx = -1.0;
+ break;
+ default:
+ break;
+ }
+
+ sx = width / scale;
+ sy = height / scale;
+ x1 = -transX - sx / 2;
+ x2 = -transX + sx / 2;
+ y1 = -transY - sy / 2;
+ y2 = -transY + sy / 2;
+
+ sx = ceil( x1 / viewGridDistance ) * viewGridDistance;
+ gi = 0;
+ x = sx;
+ while( x < x2 )
+ {
+ screenx = ( x + transX ) * scale;
+ glBegin( GL_LINES );
+ glVertex2d( screenx, -height/2 );
+ glVertex2d( screenx, height/2 );
+ glEnd( );
+
+ QString label = QString( "%1" ).arg( x * signx, 0, 'g', 4 );
+ if( approxZero( x ) && label.find( "e-" ) )
+ label = "0";
+
+ renderString( label, screenx + 3, height / 2 - fontHeight - 2 );
+
+ gi++;
+ x = sx + viewGridDistance * gi;
+ }
+
+ sy = ceil( y1 / viewGridDistance ) * viewGridDistance;
+ gi = 0;
+ y = sy;
+ while( y < y2 )
+ {
+ screeny = ( y + transY ) * scale;
+ glBegin( GL_LINES );
+ glVertex2d( -width/2, screeny );
+ glVertex2d( width/2, screeny );
+ glEnd( );
+
+ QString label = QString( "%1" ).arg( y * signy, 0, 'g', 4 );
+ if( approxZero( y ) && label.find( "e-" ) )
+ label = "0";
+
+ renderString( label, -width / 2 + 3, screeny + 2 );
+
+ gi++;
+ y = sy + viewGridDistance * gi;
+ }
+
+
+ setGLColor( axesColor( 0 ) );
+ switch( m_pCurrentGlView->type( ) )
+ {
+ case PMGLView::PMViewPosY:
+ case PMGLView::PMViewPosZ:
+ case PMGLView::PMViewNegY:
+ renderString( "x", width / 2 - qApp->fontMetrics( ).boundingRect( "x" ).width( ) - 4, -3 );
+ break;
+ case PMGLView::PMViewNegZ:
+ renderString( "x", -width / 2 + 3, -3 );
+ break;
+ default:
+ break;
+ }
+ setGLColor( axesColor( 1 ) );
+ switch( m_pCurrentGlView->type( ) )
+ {
+ case PMGLView::PMViewPosX:
+ case PMGLView::PMViewNegX:
+ case PMGLView::PMViewPosZ:
+ case PMGLView::PMViewNegZ:
+ renderString( "y", -3, height / 2 - fontHeight );
+ break;
+ default:
+ break;
+ }
+ setGLColor( axesColor( 2 ) );
+ switch( m_pCurrentGlView->type( ) )
+ {
+ case PMGLView::PMViewPosX:
+ renderString( "z", -width / 2 + 3, -3 );
+ break;
+ case PMGLView::PMViewNegX:
+ renderString( "z", width / 2 - qApp->fontMetrics( ).boundingRect( "z" ).width( ) - 4, -3 );
+ break;
+ case PMGLView::PMViewNegY:
+ renderString( "z", -3, height / 2 - fontHeight );
+ break;
+ case PMGLView::PMViewPosY:
+ renderString( "z", -3, -height / 2 );
+ break;
+ default:
+ break;
+ }
+
+ glEnable( GL_DEPTH_TEST );
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix( );
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix( );
+ }
+}
+
+void PMRenderManager::renderDescription( )
+{
+ int height = m_pCurrentGlView->height( );
+ int width = m_pCurrentGlView->width( );
+ int fontHeight = qApp->fontMetrics( ).height( );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix( );
+ glLoadIdentity( );
+ glOrtho( 0, width, 0, height, -2, 2 );
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix( );
+ glLoadIdentity( );
+
+ setGLColor( m_fieldOfViewColor );
+
+ switch( m_pCurrentGlView->type( ) )
+ {
+ case PMGLView::PMViewPosX:
+ renderString( i18n( "left" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewNegX:
+ renderString( i18n( "right" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewPosY:
+ renderString( i18n( "bottom" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewNegY:
+ renderString( i18n( "top" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewPosZ:
+ renderString( i18n( "front" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewNegZ:
+ renderString( i18n( "back" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewCamera:
+ {
+ PMCamera* c = m_pCurrentGlView->camera( );
+ if( c )
+ {
+ QString name( "-" );
+ if( !c->name( ).isEmpty( ) )
+ name = c->name( );
+ else
+ name = i18n( "(unnamed)" );
+
+ renderString( i18n( "camera" ) + ": " + name,
+ 5.0, height - fontHeight - 2 );
+ }
+ else
+ renderString( i18n( "camera" ), 5.0, height - fontHeight - 2 );
+ break;
+ }
+ }
+
+ glEnable( GL_DEPTH_TEST );
+
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix( );
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix( );
+}
+
+void PMRenderManager::renderString( const QString& str, double x, double y )
+{
+ int width = qApp->fontMetrics( ).boundingRect( str ).width( );
+ int height = qApp->fontMetrics( ).height( );
+
+ // GL wants word aligned bitmap
+ QBitmap bm( ( ( width + 32 ) % 32 ) * 32, height, true );
+
+ QPainter p( &bm );
+ p.setFont( qApp->font( ) );
+ p.drawText( bm.rect( ), Qt::AlignLeft | Qt::AlignBottom, str );
+ p.end();
+
+ // Transform to GL bitmap
+ QImage img = bm.convertToImage( ).mirror( ).convertBitOrder( QImage::BigEndian );
+
+ glRasterPos2d( x, y );
+ glBitmap( img.width( ), img.height( ), 0, 0, 0, 0, img.bits( ) );
+}
+
+void PMRenderManager::setGLColor( const QColor& c )
+{
+ int r, g, b;
+
+ c.rgb( &r, &g, &b );
+ glColor3ub( ( GLubyte ) r, ( GLubyte ) g, ( GLubyte ) b );
+}
+
+void PMRenderManager::slotRenderingSettingsChanged( )
+{
+ emit renderingSettingsChanged( );
+}
+
+void PMRenderManager::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Rendering" );
+ cfg->writeEntry( "BackgroundColor", m_backgroundColor );
+ cfg->writeEntry( "GraphicalObjectColor0", m_graphicalObjectColor[0] );
+ cfg->writeEntry( "GraphicalObjectColor1", m_graphicalObjectColor[1] );
+ cfg->writeEntry( "ControlPointColor0", m_controlPointColor[0] );
+ cfg->writeEntry( "ControlPointColor1", m_controlPointColor[1] );
+ cfg->writeEntry( "AxesColorX", m_axesColor[0] );
+ cfg->writeEntry( "AxesColorY", m_axesColor[1] );
+ cfg->writeEntry( "AxesColorZ", m_axesColor[2] );
+ cfg->writeEntry( "GridColor", m_gridColor );
+ cfg->writeEntry( "GridDistance", m_gridDistance );
+ cfg->writeEntry( "FieldOfViewColor", m_fieldOfViewColor );
+ cfg->writeEntry( "HighDetailCameraViews", m_highDetailCameraView );
+}
+
+void PMRenderManager::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Rendering" );
+
+ m_backgroundColor = cfg->readColorEntry( "BackgroundColor", &m_backgroundColor );
+ m_graphicalObjectColor[0] = cfg->readColorEntry( "GraphicalObjectColor0", &( m_graphicalObjectColor[0] ) );
+ m_graphicalObjectColor[1] = cfg->readColorEntry( "GraphicalObjectColor1", &( m_graphicalObjectColor[1] ) );
+ m_controlPointColor[0] = cfg->readColorEntry( "ControlPointColor0", &( m_controlPointColor[0] ) );
+ m_controlPointColor[1] = cfg->readColorEntry( "ControlPointColor1", &( m_controlPointColor[1] ) );
+ m_axesColor[0] = cfg->readColorEntry( "AxesColorX", &( m_axesColor[0] ) );
+ m_axesColor[1] = cfg->readColorEntry( "AxesColorY", &( m_axesColor[1] ) );
+ m_axesColor[2] = cfg->readColorEntry( "AxesColorZ", &( m_axesColor[2] ) );
+ m_gridColor = cfg->readColorEntry( "GridColor", &m_gridColor );
+ m_gridDistance = cfg->readNumEntry( "GridDistance", m_gridDistance );
+ m_fieldOfViewColor = cfg->readColorEntry( "FieldOfViewColor", &m_fieldOfViewColor );
+ m_highDetailCameraView = cfg->readBoolEntry( "HighDetailCameraViews", m_highDetailCameraView );
+}
+
+bool PMRenderManager::hasOpenGL( )
+{
+ if( !s_hasOpenGLChecked )
+ {
+ s_hasOpenGL = ( glXQueryExtension( qt_xdisplay( ), 0, 0 ) != 0 );
+ s_hasOpenGLChecked = true;
+ }
+
+ return s_hasOpenGL;
+}
+
+void PMRenderManager::disableOpenGL( )
+{
+ s_hasOpenGLChecked = true;
+ s_hasOpenGL = false;
+}
+
+#include "pmrendermanager.moc"