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.
1648 lines
47 KiB
1648 lines
47 KiB
/*
|
|
**************************************************************************
|
|
description
|
|
--------------------
|
|
copyright : (C) 2000-2002 by Andreas Zehender
|
|
email : zehender@kde.org
|
|
**************************************************************************
|
|
|
|
**************************************************************************
|
|
* *
|
|
* 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 TQT_CLEAN_NAMESPACE
|
|
#define TQT_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 <tqptrstack.h>
|
|
#include <tqapplication.h>
|
|
#include <tqbitmap.h>
|
|
#include <tqimage.h>
|
|
#include <tqpainter.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( )
|
|
: TQObject( tqApp )
|
|
{
|
|
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;
|
|
}
|
|
|
|
TQColor PMRenderManager::controlPointColor( int i ) const
|
|
{
|
|
if( ( i >= 0 ) && ( i <= 1 ) )
|
|
return m_controlPointColor[i];
|
|
return TQColor( 0, 0, 0 );
|
|
}
|
|
|
|
void PMRenderManager::setControlPointColor( int i, const TQColor& c )
|
|
{
|
|
if( ( i >= 0 ) && ( i <= 1 ) )
|
|
m_controlPointColor[i] = c;
|
|
}
|
|
|
|
TQColor PMRenderManager::graphicalObjectColor( int i ) const
|
|
{
|
|
if( ( i >= 0 ) && ( i <= 1 ) )
|
|
return m_graphicalObjectColor[i];
|
|
return TQColor( 0, 0, 0 );
|
|
}
|
|
|
|
void PMRenderManager::setGraphicalObjectColor( int i, const TQColor& c )
|
|
{
|
|
if( ( i >= 0 ) && ( i <= 1 ) )
|
|
m_graphicalObjectColor[i] = c;
|
|
}
|
|
|
|
TQColor PMRenderManager::axesColor( int i ) const
|
|
{
|
|
if( ( i >= 0 ) && ( i <= 2 ) )
|
|
return m_axesColor[i];
|
|
return TQColor( 0, 0, 0 );
|
|
}
|
|
|
|
void PMRenderManager::setAxesColor( int i, const TQColor& 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( TQTimerEvent* )
|
|
{
|
|
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;
|
|
tqApp->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 TQColor( m_currentColor ) );
|
|
m_currentColor = qc->color( ).toTQColor( );
|
|
}
|
|
}
|
|
}
|
|
|
|
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 tqApp->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( );
|
|
TQColor* 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;
|
|
tqApp->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 - tqApp->fontMetrics( ).height( ) * 2 - 2 );
|
|
else if( m_specialCameraMode && !m_highDetailCameraView )
|
|
renderString( i18n( "approximated" ), 5.0,
|
|
height - tqApp->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 = tqApp->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( );
|
|
|
|
TQString label = TQString( "%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( );
|
|
|
|
TQString label = TQString( "%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 - tqApp->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 - tqApp->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 = tqApp->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 )
|
|
{
|
|
TQString 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 TQString& str, double x, double y )
|
|
{
|
|
int width = tqApp->fontMetrics( ).boundingRect( str ).width( );
|
|
int height = tqApp->fontMetrics( ).height( );
|
|
|
|
// GL wants word aligned bitmap
|
|
TQBitmap bm( ( ( width + 32 ) % 32 ) * 32, height, true );
|
|
|
|
TQPainter p( &bm );
|
|
p.setFont( tqApp->font( ) );
|
|
p.drawText( bm.rect( ), TQt::AlignLeft | TQt::AlignBottom, str );
|
|
p.end();
|
|
|
|
// Transform to GL bitmap
|
|
TQImage img = TQImage(bm.convertToImage( )).mirror( ).convertBitOrder( TQImage::BigEndian );
|
|
|
|
glRasterPos2d( x, y );
|
|
glBitmap( img.width( ), img.height( ), 0, 0, 0, 0, img.bits( ) );
|
|
}
|
|
|
|
void PMRenderManager::setGLColor( const TQColor& 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"
|