summaryrefslogtreecommitdiffstats
path: root/kpovmodeler/pmpovrayparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kpovmodeler/pmpovrayparser.cpp')
-rw-r--r--kpovmodeler/pmpovrayparser.cpp7213
1 files changed, 7213 insertions, 0 deletions
diff --git a/kpovmodeler/pmpovrayparser.cpp b/kpovmodeler/pmpovrayparser.cpp
new file mode 100644
index 00000000..88bd8393
--- /dev/null
+++ b/kpovmodeler/pmpovrayparser.cpp
@@ -0,0 +1,7213 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 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. *
+* *
+**************************************************************************/
+
+
+#include "pmpovrayparser.h"
+
+#include <klocale.h>
+#include <qvaluelist.h>
+
+#include "pmpart.h"
+#include "pmscanner.h"
+#include "pmtokens.h"
+
+#include "pmcolor.h"
+#include "pmallobjects.h"
+#include "pmprototypemanager.h"
+#include "pmxmlhelper.h"
+
+
+PMPovrayParser::PMPovrayParser( PMPart* part, QIODevice* dev )
+ : PMParser( part, dev )
+{
+ init( );
+}
+
+PMPovrayParser::PMPovrayParser( PMPart* part, const QByteArray& array )
+ : PMParser( part, array )
+{
+ init( );
+}
+
+PMPovrayParser::~PMPovrayParser( )
+{
+ if( m_pScanner )
+ delete m_pScanner;
+}
+
+void PMPovrayParser::init( )
+{
+ m_pScanner = new PMScanner( m_pDevice );
+ m_consumedTokens = 0;
+ m_skippedComments.setAutoDelete( true );
+ m_bLastPMCommentEmpty = true;
+}
+
+
+void PMPovrayParser::nextToken( )
+{
+ m_token = m_pScanner->nextToken( );
+ m_consumedTokens++;
+ setCurrentLine( m_pScanner->currentLine( ) );
+
+ if( ( m_token == SCANNER_ERROR_TOK ) || ( m_token == COMMENT_TOK )
+ || ( m_token == LINE_COMMENT_TOK ) || ( m_token == PMNAME_TOK ) )
+ {
+ // create the objects (string) only if necessary
+ PMComment* c;
+ int lastCommentLine = -2;
+ QString commentText;
+
+ while( ( m_token == SCANNER_ERROR_TOK ) || ( m_token == COMMENT_TOK )
+ || ( m_token == LINE_COMMENT_TOK ) || ( m_token == PMNAME_TOK ) )
+ {
+ switch( m_token )
+ {
+ case SCANNER_ERROR_TOK:
+ printError( m_pScanner->error( ) );
+ lastCommentLine = -2;
+ break;
+ case LINE_COMMENT_TOK:
+ commentText = m_pScanner->sValue( );
+ if( lastCommentLine == ( m_pScanner->currentLine( ) - 1 ) )
+ {
+ c = m_skippedComments.last( );
+ if( c )
+ c->setText( c->text( ) + '\n' + commentText );
+ else
+ {
+ c = new PMComment( m_pPart, commentText );
+ m_skippedComments.append( c );
+ }
+ }
+ else
+ {
+ c = new PMComment( m_pPart, m_pScanner->sValue( ) );
+ m_skippedComments.append( c );
+ }
+ lastCommentLine = m_pScanner->currentLine( );
+ break;
+ case COMMENT_TOK:
+ c = new PMComment( m_pPart, m_pScanner->sValue( ) );
+ m_skippedComments.append( c );
+ lastCommentLine = -2;
+ break;
+ case PMNAME_TOK:
+ // Special comment
+ m_lastPMComment = m_pScanner->sValue( );
+ m_bLastPMCommentEmpty = false;
+ lastCommentLine = -2;
+ break;
+ default:
+ lastCommentLine = -2;
+ break;
+ }
+
+ m_token = m_pScanner->nextToken( );
+ m_consumedTokens++;
+ }
+ }
+}
+
+bool PMPovrayParser::isTrue( ) const
+{
+ if( ( m_token == ON_TOK ) || ( m_token == TRUE_TOK ) || ( m_token == YES_TOK ) )
+ return true;
+ return false;
+}
+
+bool PMPovrayParser::isFalse( ) const
+{
+ if( ( m_token == OFF_TOK ) || ( m_token == FALSE_TOK ) || ( m_token == NO_TOK ) )
+ return true;
+ return false;
+}
+
+void PMPovrayParser::topParse( )
+{
+ nextToken( );
+
+ do
+ {
+ if( !parseChildObjects( 0 ) )
+ m_token = EOF_TOK;
+ if( m_token != EOF_TOK )
+ {
+ printUnexpected( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+ }
+ while( m_token != EOF_TOK );
+
+ if( errors( ) || warnings( ) )
+ printMessage( PMMSpecialRawComment );
+}
+
+bool PMPovrayParser::parseBool( )
+{
+ if( isFalse( ) )
+ {
+ nextToken( );
+ return false;
+ }
+ if( isTrue( ) )
+ {
+ nextToken( );
+ return true;
+ }
+
+ PMValue v;
+
+ if( parseNumericExpression( v, true ) )
+ {
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ return v.floatValue( ) > 0.0;
+ break;
+ case PMVVector:
+ return ( v.vector( ) )[0] > 0.0;
+ break;
+ default:
+ printError( i18n( "Boolean expression expected" ) );
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool PMPovrayParser::parseChildObjects( PMCompositeObject* parent,
+ int max /* = -1 */ )
+{
+ PMObject* child = 0;
+ bool finished = false;
+ bool error = false;
+ bool noChild = false;
+ int numParsed = 0;
+
+ do
+ {
+ if( !m_bLastPMCommentEmpty && parent )
+ {
+ if( parent->isA( "NamedObject" ) )
+ ( ( PMNamedObject* ) parent )->setName( m_lastPMComment );
+ m_bLastPMCommentEmpty = true;
+ }
+ if( m_skippedComments.count( ) > 0 )
+ child = m_skippedComments.take( 0 );
+ else
+ {
+ child = 0;
+ noChild = false;
+
+ // some objects
+ switch( m_token )
+ {
+ case UNION_TOK:
+ case DIFFERENCE_TOK:
+ case INTERSECTION_TOK:
+ case MERGE_TOK:
+ child = new PMCSG( m_pPart );
+ error = !parseCSG( ( PMCSG* ) child );
+ break;
+ case BOX_TOK:
+ child = new PMBox( m_pPart );
+ error = !parseBox( ( PMBox* ) child );
+ break;
+ case SPHERE_TOK:
+ if( ( parent && ( parent->type( ) == "Blob" ) )
+ || ( !parent && m_pTopParent
+ && ( m_pTopParent->type( ) == "Blob" ) ) )
+ {
+ child = new PMBlobSphere( m_pPart );
+ error = !parseBlobSphere( ( PMBlobSphere* ) child );
+ }
+ else
+ {
+ child = new PMSphere( m_pPart );
+ error = !parseSphere( ( PMSphere* ) child );
+ }
+ break;
+ case CYLINDER_TOK:
+ if( ( parent && ( parent->type( ) == "Blob" ) )
+ || ( !parent && m_pTopParent
+ && ( m_pTopParent->type( ) == "Blob" ) ) )
+ {
+ child = new PMBlobCylinder( m_pPart );
+ error = !parseBlobCylinder( ( PMBlobCylinder* ) child );
+ }
+ else
+ {
+ child = new PMCylinder( m_pPart );
+ error = !parseCylinder( ( PMCylinder* ) child );
+ }
+ break;
+ case CONE_TOK:
+ child = new PMCone( m_pPart );
+ error = !parseCone( ( PMCone* ) child );
+ break;
+ case TORUS_TOK:
+ child = new PMTorus( m_pPart );
+ error = !parseTorus( ( PMTorus* ) child );
+ break;
+ case BLOB_TOK:
+ child = new PMBlob( m_pPart );
+ error = !parseBlob( ( PMBlob* ) child );
+ break;
+ case COMPONENT_TOK:
+ child = new PMBlobSphere( m_pPart );
+ error = !parseBlobComponent( ( PMBlobSphere* ) child );
+ break;
+ case HEIGHT_FIELD_TOK:
+ child = new PMHeightField( m_pPart );
+ error = !parseHeightField( ( PMHeightField* ) child );
+ break;
+ case TEXT_TOK:
+ child = new PMText( m_pPart );
+ error = !parseText( ( PMText* ) child );
+ break;
+ case JULIA_FRACTAL_TOK:
+ child = new PMJuliaFractal( m_pPart );
+ error = !parseJuliaFractal( ( PMJuliaFractal* ) child );
+ break;
+ case PLANE_TOK:
+ child = new PMPlane( m_pPart );
+ error = !parsePlane( ( PMPlane* ) child );
+ break;
+ case QUADRIC_TOK:
+ case CUBIC_TOK:
+ case QUARTIC_TOK:
+ case POLY_TOK:
+ child = new PMPolynom( m_pPart );
+ error = !parsePolynom( ( PMPolynom* ) child );
+ break;
+ case BICUBIC_PATCH_TOK:
+ child = new PMBicubicPatch( m_pPart );
+ error = !parseBicubicPatch( ( PMBicubicPatch* ) child );
+ break;
+ case DISC_TOK:
+ child = new PMDisc( m_pPart );
+ error = !parseDisc( ( PMDisc* ) child );
+ break;
+ case TRIANGLE_TOK:
+ case SMOOTH_TRIANGLE_TOK:
+ child = new PMTriangle( m_pPart );
+ error = !parseTriangle( ( PMTriangle* ) child );
+ break;
+ case LATHE_TOK:
+ child = new PMLathe( m_pPart );
+ error = !parseLathe( ( PMLathe* ) child );
+ break;
+ case PRISM_TOK:
+ child = new PMPrism( m_pPart );
+ error = !parsePrism( ( PMPrism* ) child );
+ break;
+ case SOR_TOK:
+ child = new PMSurfaceOfRevolution( m_pPart );
+ error = !parseSor( ( PMSurfaceOfRevolution* ) child );
+ break;
+ case SUPERELLIPSOID_TOK:
+ child = new PMSuperquadricEllipsoid( m_pPart );
+ error = !parseSqe( ( PMSuperquadricEllipsoid* ) child );
+ break;
+ case CAMERA_TOK:
+ child = new PMCamera( m_pPart );
+ error = !parseCamera( ( PMCamera* ) child );
+ break;
+ case LIGHT_SOURCE_TOK:
+ child = new PMLight( m_pPart );
+ error = !parseLight( ( PMLight* ) child );
+ break;
+ case LOOKS_LIKE_TOK:
+ child = new PMLooksLike( m_pPart );
+ error = !parseLooksLike( ( PMLooksLike* ) child );
+ break;
+ case PROJECTED_THROUGH_TOK:
+ child = new PMProjectedThrough( m_pPart );
+ error = !parseProjectedThrough( ( PMProjectedThrough* ) child );
+ break;
+ case TEXTURE_TOK:
+ child = new PMTexture( m_pPart );
+ error = !parseTexture( ( PMTexture* ) child );
+ break;
+ case AGATE_TOK:
+ case AVERAGE_TOK:
+ case BOXED_TOK:
+ case BOZO_TOK:
+ case BUMPS_TOK:
+ case CELLS_TOK:
+ case CRACKLE_TOK:
+ case CYLINDRICAL_TOK:
+ case DENTS_TOK:
+ case DENSITY_FILE_TOK:
+ case GRADIENT_TOK:
+ case GRANITE_TOK:
+ case JULIA_TOK:
+ case LEOPARD_TOK:
+ case MAGNET_TOK:
+ case MANDEL_TOK:
+ case MARBLE_TOK:
+ case ONION_TOK:
+ case PLANAR_TOK:
+ case QUILTED_TOK:
+ case RADIAL_TOK:
+ case RIPPLES_TOK:
+ case SLOPE_TOK:
+ case SPHERICAL_TOK:
+ case SPIRAL1_TOK:
+ case SPIRAL2_TOK:
+ case SPOTTED_TOK:
+ case WOOD_TOK:
+ case WAVES_TOK:
+ case WRINKLES_TOK:
+ child = new PMPattern( m_pPart );
+ {
+ bool normal = true;
+ if( parent && ( parent->type( ) != "Normal" ) )
+ normal = false;
+ error = !parsePattern( ( PMPattern* ) child, normal );
+ }
+ break;
+ case TURBULENCE_TOK:
+ // Search for a PMPattern in the object's children
+ child = parent->firstChild( );
+ while( child && !child->isA( "Pattern" ) )
+ child = child->nextSibling( );
+ if( child )
+ {
+ error = !parsePattern( ( PMPattern* ) child );
+ child = 0;
+ noChild = true;
+ }
+ else
+ {
+ printError( i18n( "Found turbulence without a pattern." ) );
+ error = true;
+ }
+ break;
+ case FREQUENCY_TOK:
+ case PHASE_TOK:
+ case RAMP_WAVE_TOK:
+ case TRIANGLE_WAVE_TOK:
+ case SINE_WAVE_TOK:
+ case SCALLOP_WAVE_TOK:
+ case CUBIC_WAVE_TOK:
+ case POLY_WAVE_TOK:
+ // Search for a PMBlendMapModifiers in the object's children
+ child = parent->firstChild( );
+ while( child && !child->isA( "BlendMapModifiers" ) )
+ child = child->nextSibling( );
+ if( child )
+ {
+ error = !parseBlendMapModifiers( ( PMBlendMapModifiers* ) child );
+ child = 0;
+ noChild = 0;
+ }
+ else
+ {
+ child = new PMBlendMapModifiers( m_pPart );
+ error = !parseBlendMapModifiers( ( PMBlendMapModifiers* ) child );
+ }
+ break;
+ case WARP_TOK:
+ child = new PMWarp( m_pPart );
+ error = !parseWarp( ( PMWarp* ) child );
+ break;
+ case PIGMENT_TOK:
+ child = new PMPigment( m_pPart );
+ error = !parsePigment( ( PMPigment* ) child );
+ break;
+ case NORMAL_TOK:
+ child = new PMNormal( m_pPart );
+ error = !parseNormal( ( PMNormal* ) child );
+ break;
+ case NORMAL_MAP_TOK:
+ child = new PMNormalMap( m_pPart );
+ error = !parseNormalMap( ( PMNormalMap* ) child );
+ break;
+ case BUMP_MAP_TOK:
+ child = new PMBumpMap( m_pPart );
+ error = !parseBumpMap( ( PMBumpMap* ) child );
+ break;
+ case SLOPE_MAP_TOK:
+ child = new PMSlopeMap( m_pPart );
+ error = !parseSlopeMap( ( PMSlopeMap* ) child );
+ break;
+ case DENSITY_MAP_TOK:
+ child = new PMDensityMap( m_pPart );
+ error = !parseDensityMap( ( PMDensityMap* ) child );
+ break;
+ case TEXTURE_MAP_TOK:
+ child = new PMTextureMap( m_pPart );
+ error = !parseTextureMap( ( PMTextureMap* ) child );
+ break;
+ case MATERIAL_MAP_TOK:
+ child = new PMMaterialMap( m_pPart );
+ error = !parseMaterialMap( ( PMMaterialMap* ) child );
+ break;
+ case PIGMENT_MAP_TOK:
+ child = new PMPigmentMap( m_pPart );
+ error = !parsePigmentMap( ( PMPigmentMap* ) child );
+ break;
+ case COLOR_MAP_TOK:
+ case COLOUR_MAP_TOK:
+ child = new PMColorMap( m_pPart );
+ error = !parseColorMap( ( PMColorMap* ) child );
+ break;
+ case CHECKER_TOK:
+ case HEXAGON_TOK:
+ case BRICK_TOK:
+ {
+ bool normal = false;
+ double depth = 0.0;
+ int expect = 0;
+ PMListPattern::PMListType type = PMListPattern::ListPatternChecker;
+
+ if( parent && parent->type( ) == "Normal" )
+ normal = true;
+ else if( m_pTopParent && m_pTopParent->type( ) == "Normal" )
+ normal = true;
+
+ switch( m_token )
+ {
+ case CHECKER_TOK:
+ type = PMListPattern::ListPatternChecker;
+ expect = 2;
+ break;
+ case HEXAGON_TOK:
+ type = PMListPattern::ListPatternHexagon;
+ expect = 3;
+ break;
+ case BRICK_TOK:
+ type = PMListPattern::ListPatternBrick;
+ expect = 2;
+ break;
+ }
+ nextToken( );
+
+ if( normal )
+ {
+ child = new PMNormalList( m_pPart );
+ if( parseFloat( depth, true ) )
+ ( ( PMNormalList* ) child )->setDepth( depth );
+
+ if( m_token == NORMAL_TOK )
+ error = !parseNormalList( ( PMNormalList* ) child, expect );
+ }
+ else
+ {
+ switch( m_token )
+ {
+ case COLOR_TOK:
+ case COLOUR_TOK:
+ case RGB_TOK:
+ case RGBT_TOK:
+ case RGBF_TOK:
+ case RGBFT_TOK:
+ case RED_TOK:
+ case GREEN_TOK:
+ case BLUE_TOK:
+ case TRANSMIT_TOK:
+ case FILTER_TOK:
+ case ID_TOK:
+ child = new PMColorList( m_pPart );
+ error = !parseColorList( ( PMColorList* ) child, expect );
+ break;
+ case PIGMENT_TOK:
+ child = new PMPigmentList( m_pPart );
+ error = !parsePigmentList( ( PMPigmentList* ) child, expect );
+ break;
+ case TEXTURE_TOK:
+ child = new PMTextureList( m_pPart );
+ error = !parseTextureList( ( PMTextureList* ) child, expect );
+ break;
+ case NORMAL_TOK:
+ child = new PMNormalList( m_pPart );
+ error = !parseNormalList( ( PMNormalList* ) child, expect );
+ break;
+ case DENSITY_TOK:
+ child = new PMDensityList( m_pPart );
+ error = !parseDensityList( ( PMDensityList* ) child, expect );
+ break;
+ default:
+ printError( i18n( "Invalid list member." ) );
+ error = true;
+ }
+ }
+
+ if( child )
+ {
+ ( ( PMListPattern* ) child )->setListType( type );
+
+ int oldConsumed;
+ double num = 0;
+ PMVector vector;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case MORTAR_TOK:
+ nextToken( );
+ if( !parseFloat( num ) )
+ return false;
+ ( ( PMListPattern* ) child )->setMortar( num );
+ break;
+ case BRICK_SIZE_TOK:
+ nextToken( );
+ if( !parseVector( vector ) )
+ return false;
+ ( ( PMListPattern* ) child )->setBrickSize( vector );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+ }
+ break;
+ }
+ case IMAGE_MAP_TOK:
+ child = new PMImageMap( m_pPart );
+ error = !parseImageMap( ( PMImageMap* ) child );
+ break;
+ case FINISH_TOK:
+ child = new PMFinish( m_pPart );
+ error = !parseFinish( ( PMFinish* ) child );
+ break;
+ case INTERIOR_TOK:
+ child = new PMInterior( m_pPart );
+ error = !parseInterior( ( PMInterior* ) child );
+ break;
+ case MEDIA_TOK:
+ child = new PMMedia( m_pPart );
+ error = !parseMedia( ( PMMedia* ) child );
+ break;
+ case DENSITY_TOK:
+ child = new PMDensity( m_pPart );
+ error = !parseDensity( ( PMDensity* ) child );
+ break;
+ case MATERIAL_TOK:
+ child = new PMMaterial( m_pPart );
+ error = !parseMaterial( ( PMMaterial* ) child );
+ break;
+ case SKY_SPHERE_TOK:
+ child = new PMSkySphere( m_pPart );
+ error = !parseSkySphere( ( PMSkySphere* ) child );
+ break;
+ case RAINBOW_TOK:
+ child = new PMRainbow( m_pPart );
+ error = !parseRainbow( ( PMRainbow* ) child );
+ break;
+ case FOG_TOK:
+ child = new PMFog( m_pPart );
+ error = !parseFog( ( PMFog* ) child );
+ break;
+ case GLOBAL_SETTINGS_TOK:
+ child = new PMGlobalSettings( m_pPart );
+ error = !parseGlobalSettings( ( PMGlobalSettings* ) child );
+ break;
+ case SCALE_TOK:
+ child = new PMScale( m_pPart );
+ error = !parseScale( ( PMScale* ) child );
+ break;
+ case ROTATE_TOK:
+ child = new PMRotate( m_pPart );
+ error = !parseRotate( ( PMRotate* ) child );
+ break;
+ case TRANSLATE_TOK:
+ child = new PMTranslate( m_pPart );
+ error = !parseTranslate( ( PMTranslate* ) child );
+ break;
+ case MATRIX_TOK:
+ child = new PMPovrayMatrix( m_pPart );
+ error = !parseMatrix( ( PMPovrayMatrix* ) child );
+ break;
+ case BOUNDED_BY_TOK:
+ if( parent && ( parent->type( ) == "ClippedBy" ) )
+ finished = true;
+ else
+ {
+ child = new PMBoundedBy( m_pPart );
+ error = !parseBoundedBy( ( PMBoundedBy* ) child );
+ }
+ break;
+ case CLIPPED_BY_TOK:
+ if( parent && ( parent->type( ) == "BoundedBy" ) )
+ finished = true;
+ else
+ {
+ child = new PMClippedBy( m_pPart );
+ error = !parseClippedBy( ( PMClippedBy* ) child );
+ }
+ break;
+ case ISOSURFACE_TOK:
+ child = new PMIsoSurface( m_pPart );
+ error = !parseIsoSurface( ( PMIsoSurface* ) child );
+ break;
+ case RADIOSITY_TOK:
+ child = new PMRadiosity( m_pPart );
+ error = !parseRadiosity( ( PMRadiosity* ) child );
+ break;
+ case PHOTONS_TOK:
+ if ( parent && ( parent->type( ) == "GlobalSettings" ) )
+ {
+ child = new PMGlobalPhotons( m_pPart );
+ error = !parseGlobalPhotons( ( PMGlobalPhotons* ) child );
+ }
+ else
+ {
+ child = new PMPhotons( m_pPart );
+ error =!parsePhotons( ( PMPhotons* ) child );
+ }
+ break;
+ case LIGHT_GROUP_TOK:
+ child = new PMLightGroup( m_pPart );
+ error = !parseLightGroup( ( PMLightGroup* ) child );
+ break;
+ case INTERIOR_TEXTURE_TOK:
+ child = new PMInteriorTexture( m_pPart );
+ error = !parseInteriorTexture( ( PMInteriorTexture* ) child );
+ break;
+ case SPHERE_SWEEP_TOK:
+ child = new PMSphereSweep( m_pPart );
+ error = !parseSphereSweep( ( PMSphereSweep* ) child );
+ break;
+ case MESH_TOK:
+ child = new PMMesh( m_pPart );
+ error = !parseMesh( ( PMMesh* ) child );
+ break;
+ case DECLARE_TOK:
+ nextToken( );
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ nextToken( );
+
+ if( !parseToken( '=' ) )
+ error = true;
+ else
+ {
+ PMValue v;
+ switch( m_token )
+ {
+ case OBJECT_TOK:
+ // finite solid
+ case BLOB_TOK:
+ case BOX_TOK:
+ case CONE_TOK:
+ case CYLINDER_TOK:
+ case HEIGHT_FIELD_TOK:
+ case JULIA_FRACTAL_TOK:
+ case LATHE_TOK:
+ case PRISM_TOK:
+ case SPHERE_TOK:
+ case SUPERELLIPSOID_TOK:
+ case SOR_TOK:
+ case TEXT_TOK:
+ case TORUS_TOK:
+ case ISOSURFACE_TOK:
+ case SPHERE_SWEEP_TOK:
+ // finite patch
+ case BICUBIC_PATCH_TOK:
+ case DISC_TOK:
+ case MESH_TOK:
+ case POLYGON_TOK:
+ case TRIANGLE_TOK:
+ case SMOOTH_TRIANGLE_TOK:
+ // infinite solid
+ case PLANE_TOK:
+ case QUADRIC_TOK:
+ case CUBIC_TOK:
+ case QUARTIC_TOK:
+ case POLY_TOK:
+ // csg
+ case UNION_TOK:
+ case INTERSECTION_TOK:
+ case DIFFERENCE_TOK:
+ case MERGE_TOK:
+ // textures
+ case TEXTURE_TOK:
+ case INTERIOR_TEXTURE_TOK:
+ case PIGMENT_TOK:
+ case NORMAL_TOK:
+ case FINISH_TOK:
+ case TEXTURE_MAP_TOK:
+ case PIGMENT_MAP_TOK:
+ case COLOR_MAP_TOK:
+ case COLOUR_MAP_TOK:
+ case NORMAL_MAP_TOK:
+ case SLOPE_MAP_TOK:
+ case DENSITY_MAP_TOK:
+ case INTERIOR_TOK:
+ case MEDIA_TOK:
+ case DENSITY_TOK:
+ case MATERIAL_TOK:
+ case SKY_SPHERE_TOK:
+ case RAINBOW_TOK:
+ case FOG_TOK:
+ // misc
+ case LIGHT_SOURCE_TOK:
+ case LIGHT_GROUP_TOK:
+ child = new PMDeclare( m_pPart );
+ error = !parseDeclare( ( PMDeclare* ) child );
+ break;
+ default:
+ // constant, vector or color declare?
+ if( parseNumericExpression( v ) )
+ {
+ checkID( id, v );
+ noChild = true;
+ }
+ else
+ error = true;
+ break;
+ }
+ }
+
+ if( child )
+ if( child->isA( "Declare" ) )
+ ( ( PMDeclare* ) child )->setID( id );
+ if( m_token == ';' )
+ nextToken( );
+ }
+ else
+ printExpected( i18n( "identifier" ), m_pScanner->sValue( ) );
+ break;
+ case OBJECT_TOK:
+ error = !parseObject( parent );
+ noChild = true;
+ break;
+ case RAW_POVRAY_TOK:
+ child = new PMRaw( m_pPart, m_pScanner->sValue( ) );
+ error = false;
+ nextToken( );
+ break;
+ default:
+ finished = true;
+ break;
+ }
+ }
+ if( !finished && !child && !noChild )
+ error = true;
+ if( child )
+ {
+ if( !insertChild( child, parent ) )
+ {
+ delete child;
+ child = 0;
+ }
+ else if( child->isA( "Declare" ) )
+ checkID( ( PMDeclare* ) child );
+ numParsed ++;
+ if( ( max > 0 ) && ( numParsed >= max ) )
+ finished = true;
+ }
+ }
+ while( !finished && !error );
+
+ return finished;
+}
+
+bool PMPovrayParser::parseToken( int t, const QString& tokenName )
+{
+ if( t == ',' )
+ {
+ // do not require commas any more.
+ if( m_token == ',' )
+ nextToken( );
+ return true;
+ }
+ else if( m_token == t )
+ {
+ nextToken( );
+ return true;
+ }
+
+ if( tokenName.isNull() )
+ printExpected( ( char ) t, m_pScanner->sValue( ) );
+ else
+ printExpected( tokenName, m_pScanner->sValue( ) );
+ return false;
+}
+
+bool PMPovrayParser::parseNumericItem( PMValue& v, bool checkForBool /*=false*/ )
+{
+ bool finishColor = false;
+ PMVector cv( 0 );
+ PMVector vec( 0 );
+ PMValue hv;
+ PMSymbol* s;
+ int i;
+
+ switch( m_token )
+ {
+ case X_TOK:
+ v.setVector( PMVector( 1.0, 0.0, 0.0 ) );
+ nextToken( );
+ break;
+ case Y_TOK:
+ v.setVector( PMVector( 0.0, 1.0, 0.0 ) );
+ nextToken( );
+ break;
+ case Z_TOK:
+ v.setVector( PMVector( 0.0, 0.0, 1.0 ) );
+ nextToken( );
+ break;
+ case T_TOK:
+ v.setVector( PMVector( 0.0, 0.0, 0.0, 1.0 ) );
+ nextToken( );
+ break;
+ case U_TOK:
+ v.setVector( PMVector( 1.0, 0.0 ) );
+ nextToken( );
+ break;
+ case V_TOK:
+ v.setVector( PMVector( 0.0, 1.0 ) );
+ nextToken( );
+ break;
+ case PI_TOK:
+ v.setFloat( 3.1415926535897932384626 );
+ nextToken( );
+ break;
+ case CLOCK_TOK:
+ printMessage( PMMClockDefault );
+ v.setFloat( 0.0 );
+ break;
+ case CLOCK_DELTA_TOK:
+ printMessage( PMMClockDeltaDefault );
+ v.setFloat( 1.0 );
+ break;
+ case FLOAT_TOK:
+ v.setFloat( m_pScanner->fValue( ) );
+ nextToken( );
+ break;
+ case INTEGER_TOK:
+ v.setFloat( ( double ) m_pScanner->iValue( ) );
+ nextToken( );
+ break;
+ case ON_TOK:
+ case TRUE_TOK:
+ case YES_TOK:
+ v.setFloat( 1.0 );
+ nextToken( );
+ break;
+ case OFF_TOK:
+ case FALSE_TOK:
+ case NO_TOK:
+ v.setFloat( 0.0 );
+ nextToken( );
+ break;
+ case '(':
+ nextToken( );
+ if( !parseNumericExpression( v ) )
+ return false;
+ if( !parseToken( ')' ) )
+ return false;
+ break;
+ case '-':
+ nextToken( );
+ if( !parseNumericItem( v ) )
+ return false;
+ if( v.type( ) == PMVFloat )
+ v.setFloat( -v.floatValue( ) );
+ else
+ v.setVector( -v.vector( ) );
+ break;
+ case '+':
+ nextToken( );
+ if( !parseNumericItem( v ) )
+ return false;
+ break;
+ case '<':
+ if( !parseVectorLiteral( vec ) )
+ return false;
+ v.setVector( vec );
+ break;
+ case COLOR_TOK:
+ case COLOUR_TOK:
+ nextToken( );
+ case RGB_TOK:
+ case RGBT_TOK:
+ case RGBF_TOK:
+ case RGBFT_TOK:
+ case RED_TOK:
+ case GREEN_TOK:
+ case BLUE_TOK:
+ case TRANSMIT_TOK:
+ case FILTER_TOK:
+ cv.resize( 5 );
+ cv = 0.0;
+ finishColor = true;
+ break;
+ case ID_TOK:
+ s = getSymbol( m_pScanner->sValue( ) );
+ if( s )
+ {
+ nextToken( );
+ if( s->type( ) == PMSymbol::Value )
+ v = s->value( );
+ else
+ {
+ printError( i18n( "Float, color or vector identifier expected." ) );
+ return false;
+ }
+ }
+ else
+ {
+ printError( i18n( "Undefined identifier \"%1\"." )
+ .arg( m_pScanner->sValue( ) ) );
+ nextToken( );
+ }
+ break;
+ default:
+ if( !checkForBool )
+ printUnexpected( m_pScanner->sValue( ) );
+ return false;
+ break;
+ }
+
+ if( !finishColor )
+ {
+ if( m_token == '.' )
+ {
+ int index = -1;
+ nextToken( );
+
+ switch( m_token )
+ {
+ case X_TOK:
+ case RED_TOK:
+ case U_TOK:
+ index = 0;
+ break;
+ case Y_TOK:
+ case GREEN_TOK:
+ case V_TOK:
+ index = 1;
+ break;
+ case Z_TOK:
+ case BLUE_TOK:
+ index = 2;
+ break;
+ case T_TOK:
+ case FILTER_TOK:
+ index = 3;
+ break;
+ case TRANSMIT_TOK:
+ index = 4;
+ break;
+ default:
+ break;
+ }
+ if( index >= 0 )
+ {
+ nextToken( );
+ if( v.type( ) == PMVFloat )
+ {
+ if( index != 0 )
+ index = -1;
+ }
+ else
+ {
+ PMVector vec;
+ if( v.type( ) == PMVVector )
+ vec = v.vector( );
+ else
+ vec = v.color( );
+
+ if( ( ( unsigned ) index ) < vec.size( ) )
+ v.setFloat( vec[index] );
+ else
+ index = -1;
+ }
+ }
+ if( index == -1 )
+ {
+ printError( i18n( "Bad operands for period operator." ) );
+ return false;
+ }
+ }
+ }
+
+ while( finishColor )
+ {
+ switch( m_token )
+ {
+ case RGB_TOK:
+ nextToken( );
+ if( !parseNumericExpression( hv ) )
+ return false;
+ switch( hv.type( ) )
+ {
+ case PMVFloat:
+ cv[0] = hv.floatValue( );
+ cv[1] = hv.floatValue( );
+ cv[2] = hv.floatValue( );
+ break;
+ case PMVVector:
+ vec = hv.vector( );
+ vec.resize( 3 );
+ cv[0] = vec[0];
+ cv[1] = vec[1];
+ cv[2] = vec[2];
+ break;
+ default:
+ printError( i18n( "Float or vector expression expected" ) );
+ break;
+ }
+ break;
+ case RGBT_TOK:
+ nextToken( );
+ if( !parseNumericExpression( hv ) )
+ return false;
+ switch( hv.type( ) )
+ {
+ case PMVFloat:
+ cv[0] = hv.floatValue( );
+ cv[1] = hv.floatValue( );
+ cv[2] = hv.floatValue( );
+ cv[4] = hv.floatValue( );
+ break;
+ case PMVVector:
+ vec = hv.vector( );
+ vec.resize( 4 );
+ cv[0] = vec[0];
+ cv[1] = vec[1];
+ cv[2] = vec[2];
+ cv[4] = vec[3];
+ break;
+ default:
+ printError( i18n( "Float or vector expression expected" ) );
+ break;
+ }
+ break;
+ case RGBF_TOK:
+ nextToken( );
+ if( !parseNumericExpression( hv ) )
+ return false;
+ switch( hv.type( ) )
+ {
+ case PMVFloat:
+ cv[0] = hv.floatValue( );
+ cv[1] = hv.floatValue( );
+ cv[2] = hv.floatValue( );
+ cv[3] = hv.floatValue( );
+ break;
+ case PMVVector:
+ vec = hv.vector( );
+ vec.resize( 4 );
+ cv[0] = vec[0];
+ cv[1] = vec[1];
+ cv[2] = vec[2];
+ cv[3] = vec[3];
+ break;
+ default:
+ printError( i18n( "Float or vector expression expected" ) );
+ break;
+ }
+ break;
+ case RGBFT_TOK:
+ nextToken( );
+ if( !parseNumericExpression( hv ) )
+ return false;
+ switch( hv.type( ) )
+ {
+ case PMVFloat:
+ cv = hv.floatValue( );
+ break;
+ case PMVVector:
+ vec = hv.vector( );
+ vec.resize( 5 );
+ cv = vec;
+ break;
+ default:
+ printError( i18n( "Float or vector expression expected" ) );
+ break;
+ }
+ break;
+ case RED_TOK:
+ nextToken( );
+ parseNumericExpression( hv );
+ if( hv.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ break;
+ }
+ cv[0] = hv.floatValue( );
+ break;
+ case GREEN_TOK:
+ nextToken( );
+ parseNumericExpression( hv );
+ if( hv.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ break;
+ }
+ cv[1] = hv.floatValue( );
+ break;
+ case BLUE_TOK:
+ nextToken( );
+ parseNumericExpression( hv );
+ if( hv.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ break;
+ }
+ cv[2] = hv.floatValue( );
+ break;
+ case FILTER_TOK:
+ case ALPHA_TOK:
+ nextToken( );
+ parseNumericExpression( hv );
+ if( hv.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ break;
+ }
+ cv[3] = hv.floatValue( );
+ break;
+ case TRANSMIT_TOK:
+ nextToken( );
+ parseNumericExpression( hv );
+ if( hv.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ break;
+ }
+ cv[4] = hv.floatValue( );
+ break;
+ case ID_TOK:
+ if( parseNumericItem( hv ) )
+ {
+ if( hv.type( ) == PMVFloat )
+ {
+ for( i = 0; i < 5; i++ )
+ cv[i] = hv.floatValue( );
+ }
+ else if( hv.type( ) == PMVVector )
+ {
+ cv = hv.vector( );
+ cv.resize( 5 );
+ }
+ else
+ cv = hv.color( );
+ }
+ break;
+ default:
+ finishColor = false;
+ v.setColor( cv );
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool PMPovrayParser::parseVectorLiteral( PMVector& p )
+{
+ PMValue v;
+
+ if( !parseToken( '<' ) )
+ return false;
+ if( !parseNumericExpression( v ) )
+ return false;
+
+ if( v.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ return false;
+ }
+
+ p.resize( 1 );
+ p[0] = v.floatValue( );
+
+ while( m_token != '>' )
+ {
+ // many old scenes do not use a comma between values
+ if( m_token == ',' )
+ nextToken( );
+ // parseToken( ',' );
+ if( !parseNumericExpression( v ) )
+ return false;
+
+ if( v.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ return false;
+ }
+
+ p.resize( p.size( ) + 1 );
+ p[p.size( ) - 1] = v.floatValue( );
+ }
+
+ /** old code
+ while( m_token == ',' )
+ {
+ nextToken( );
+ if( !parseNumericExpression( v ) )
+ return false;
+
+ if( v.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ return false;
+ }
+
+ p.resize( p.size( ) + 1 );
+ p[p.size( ) - 1] = v.floatValue( );
+ }
+ */
+
+ if( !parseToken( '>' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseNumericExpression( PMValue& v, bool checkForBool /*=false*/ )
+{
+ bool end = false;
+ PMValue v2;
+ PMVector hv( 0 );
+
+ if( !parseNumericItem( v, checkForBool ) )
+ return false;
+
+ do
+ {
+ switch( m_token )
+ {
+ case '*':
+ nextToken( );
+ if( !parseNumericItem( v2 ) )
+ break;
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setFloat( v.floatValue( ) * v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v2.vector( ) * v.floatValue( ) );
+ break;
+ case PMVColor:
+ v.setColor( v2.color( ) * v.floatValue( ) );
+ break;
+ }
+ break;
+ case PMVVector:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setVector( v.vector( ) * v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v.vector( ) * v2.vector( ) );
+ break;
+ case PMVColor:
+ if( v.vector( ).size( ) == 5 )
+ v.setColor( v.vector( ) * v2.color( ) );
+ else
+ printError( i18n( "You can't multiply a vector with a color" ) );
+ break;
+ }
+ break;
+ case PMVColor:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setColor( v.color( ) * v2.floatValue( ) );
+ break;
+ case PMVVector:
+ if( v2.vector( ).size( ) == 5 )
+ v.setColor( v2.vector( ) * v.color( ) );
+ else
+ printError( i18n( "You can't multiply a vector with a color" ) );
+ break;
+ case PMVColor:
+ v.setColor( v.color( ) * v2.color( ) );
+ break;
+ }
+ break;
+ }
+ break;
+ case '/':
+ nextToken( );
+ if( !parseNumericItem( v2 ) )
+ break;
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setFloat( v.floatValue( ) / v2.floatValue( ) );
+ break;
+ case PMVVector:
+ hv.resize( v2.vector( ).size( ) );
+ hv = v.floatValue( );
+ v.setVector( hv / v2.vector( ) );
+ break;
+ case PMVColor:
+ hv.resize( 5 );
+ hv = v.floatValue( );
+ v.setColor( hv / v.floatValue( ) );
+ break;
+ }
+ break;
+ case PMVVector:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setVector( v.vector( ) / v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v.vector( ) / v2.vector( ) );
+ break;
+ case PMVColor:
+ if( v.vector( ).size( ) == 5 )
+ v.setColor( v.vector( ) / v2.color( ) );
+ else
+ printError( i18n( "You can't divide a vector by a color" ) );
+ break;
+ }
+ break;
+ case PMVColor:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setColor( v.color( ) / v2.floatValue( ) );
+ break;
+ case PMVVector:
+ if( v2.vector( ).size( ) == 5 )
+ v.setColor( v2.vector( ) / v.color( ) );
+ else
+ printError( i18n( "You can't divide a color by a vector" ) );
+ break;
+ case PMVColor:
+ v.setColor( v.color( ) / v2.color( ) );
+ break;
+ }
+ break;
+ }
+ break;
+ case '+':
+ nextToken( );
+ if( !parseNumericExpression( v2 ) )
+ break;
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setFloat( v.floatValue( ) + v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v2.vector( ) + v.floatValue( ) );
+ break;
+ case PMVColor:
+ v.setColor( v2.color( ) + v.floatValue( ) );
+ break;
+ }
+ break;
+ case PMVVector:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setVector( v.vector( ) + v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v.vector( ) + v2.vector( ) );
+ break;
+ case PMVColor:
+ if( v.vector( ).size( ) == 5 )
+ v.setColor( v.vector( ) + v2.color( ) );
+ else
+ printError( i18n( "You can't add a vector and a color" ) );
+ break;
+ }
+ break;
+ case PMVColor:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setColor( v.color( ) + v2.floatValue( ) );
+ break;
+ case PMVVector:
+ if( v2.vector( ).size( ) == 5 )
+ v.setColor( v2.vector( ) + v.color( ) );
+ else
+ printError( i18n( "You can't add a vector with a color" ) );
+ break;
+ case PMVColor:
+ v.setColor( v.color( ) + v2.color( ) );
+ break;
+ }
+ break;
+ }
+ break;
+ case '-':
+ nextToken( );
+ if( !parseNumericExpression( v2 ) )
+ break;
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setFloat( v.floatValue( ) - v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v2.vector( ) - v.floatValue( ) );
+ break;
+ case PMVColor:
+ v.setColor( v2.color( ) - v.floatValue( ) );
+ break;
+ }
+ break;
+ case PMVVector:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setVector( v.vector( ) - v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v.vector( ) - v2.vector( ) );
+ break;
+ case PMVColor:
+ if( v.vector( ).size( ) == 5 )
+ v.setColor( v.vector( ) - v2.color( ) );
+ else
+ printError( i18n( "You can't subtract a vector and a color" ) );
+ break;
+ }
+ break;
+ case PMVColor:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setColor( v.color( ) - v2.floatValue( ) );
+ break;
+ case PMVVector:
+ if( v2.vector( ).size( ) == 5 )
+ v.setColor( v2.vector( ) - v.color( ) );
+ else
+ printError( i18n( "You can't subtract a vector and a color" ) );
+ break;
+ case PMVColor:
+ v.setColor( v.color( ) - v2.color( ) );
+ break;
+ }
+ break;
+ }
+ break;
+ default:
+ end = true;
+ break;
+ }
+ }
+ while( !end );
+
+ return true;
+}
+
+bool PMPovrayParser::parseVector( PMVector& vector, unsigned int size )
+{
+ PMValue v;
+ unsigned int i;
+
+ if( !parseNumericExpression( v ) )
+ return false;
+
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ vector.resize( size );
+ for( i = 0; i < size; i++ )
+ vector[i] = v.floatValue( );
+ break;
+ case PMVVector:
+ vector = v.vector( );
+ vector.resize( size );
+ break;
+ default:
+ printError( i18n( "Float or vector expression expected" ) );
+ return false;
+ }
+ return true;
+}
+
+bool PMPovrayParser::parseFloat( double& d, bool suppressError )
+{
+ PMValue v;
+
+ if( !parseNumericExpression( v, suppressError ) )
+ return false;
+
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ d = v.floatValue( );
+ break;
+ case PMVVector:
+ d = ( v.vector( ) )[0];
+ break;
+ default:
+ printError( i18n( "Float expression expected" ) );
+ return false;
+ }
+ return true;
+}
+
+bool PMPovrayParser::parseInt( int& i )
+{
+ double d;
+
+ if( !parseFloat( d ) )
+ return false;
+
+ i = ( int ) ( d + 0.5 );
+ return true;
+}
+
+bool PMPovrayParser::parseColor( PMColor& c )
+{
+ PMValue v;
+
+ if( !parseNumericExpression( v ) )
+ return false;
+
+ if( v.type( ) == PMVColor )
+ c = PMColor( v.color( ) );
+ else if( v.type( ) == PMVVector )
+ {
+ if( v.vector( ).size( ) == 5 )
+ c = PMColor( v.vector( ) );
+ else
+ {
+ printError( i18n( "Color expression expected" ) );
+ return false;
+ }
+ }
+ else if( v.type( ) == PMVFloat )
+ {
+ double d = v.floatValue( );
+ c = PMColor( d, d, d, d, d );
+ }
+ else
+ {
+ printError( i18n( "Color expression expected" ) );
+ return false;
+ }
+
+ return true;
+}
+
+bool PMPovrayParser::parseObjectModifiers( PMGraphicalObject* o )
+{
+ bool finished = false;
+
+ PMSolidObject* so = 0;
+ if( o->isA( "SolidObject" ) )
+ so = ( PMSolidObject* ) o;
+
+ do
+ {
+ finished = true;
+ switch( m_token )
+ {
+ case NO_SHADOW_TOK:
+ o->setNoShadow( true );
+ nextToken( );
+ finished = false;
+ break;
+ case NO_IMAGE_TOK:
+ o->setNoImage( true );
+ nextToken( );
+ finished = false;
+ break;
+ case NO_REFLECTION_TOK:
+ o->setNoReflection( true );
+ nextToken( );
+ finished = false;
+ break;
+ case DOUBLE_ILLUMINATE_TOK:
+ o->setDoubleIlluminate( true );
+ nextToken( );
+ finished = false;
+ break;
+ default:
+ break;
+ }
+ if( so )
+ {
+ switch( m_token )
+ {
+ case HOLLOW_TOK:
+ so->setHollow( PMTrue );
+ nextToken( );
+ if( isTrue( ) )
+ nextToken( );
+ else if( isFalse( ) )
+ {
+ nextToken( );
+ so->setHollow( PMFalse );
+ }
+ finished = false;
+ break;
+ case INVERSE_TOK:
+ so->setInverse( true );
+ nextToken( );
+ finished = false;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ while( !finished );
+ return true;
+}
+
+bool PMPovrayParser::parseCSG( PMCSG* pNewCSG )
+{
+ int oldConsumed;
+
+ switch( m_token )
+ {
+ case UNION_TOK:
+ pNewCSG->setCSGType( PMCSG::CSGUnion );
+ break;
+ case INTERSECTION_TOK:
+ pNewCSG->setCSGType( PMCSG::CSGIntersection );
+ break;
+ case DIFFERENCE_TOK:
+ pNewCSG->setCSGType( PMCSG::CSGDifference );
+ break;
+ case MERGE_TOK:
+ pNewCSG->setCSGType( PMCSG::CSGMerge );
+ break;
+ default:
+ printUnexpected( m_pScanner->sValue( ) );
+ return false;
+ break;
+ }
+ nextToken( );
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewCSG );
+ parseObjectModifiers( pNewCSG );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBox( PMBox* pNewBox )
+{
+ PMVector vector;
+
+ int oldConsumed;
+
+ if( !parseToken( BOX_TOK, "box" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBox->setCorner1( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBox->setCorner2( vector );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewBox );
+ parseObjectModifiers( pNewBox );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSphere( PMSphere* pNewSphere )
+{
+ PMVector vector;
+ double radius;
+
+ int oldConsumed;
+
+ if( !parseToken( SPHERE_TOK, "sphere" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewSphere->setCentre( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseFloat( radius ) )
+ return false;
+ pNewSphere->setRadius( radius );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewSphere );
+ parseObjectModifiers( pNewSphere );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseCylinder( PMCylinder* pNewCyl )
+{
+ PMVector vector;
+ double radius;
+ int oldConsumed;
+
+ if( !parseToken( CYLINDER_TOK, "cylinder" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewCyl->setEnd1( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewCyl->setEnd2( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseFloat(radius) )
+ return false;
+ pNewCyl->setRadius( radius );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewCyl );
+ parseObjectModifiers( pNewCyl );
+ switch( m_token )
+ {
+ case OPEN_TOK:
+ nextToken( );
+ pNewCyl->setOpen( true );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseCone( PMCone* pNewCone )
+{
+ PMVector vector;
+ double radius;
+ int oldConsumed;
+
+ if( !parseToken( CONE_TOK, "cone" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewCone->setEnd1( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( radius ) )
+ return false;
+ pNewCone->setRadius1( radius );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseVector( vector ) )
+ return false;
+ pNewCone->setEnd2( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( radius ) )
+ return false;
+ pNewCone->setRadius2( radius );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewCone );
+ parseObjectModifiers( pNewCone );
+ switch( m_token )
+ {
+ case OPEN_TOK:
+ nextToken( );
+ pNewCone->setOpen( true );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+
+}
+
+bool PMPovrayParser::parseTorus( PMTorus* pNewTorus )
+{
+ double radius;
+ int oldConsumed;
+
+ if( !parseToken( TORUS_TOK, "torus" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseFloat( radius ) )
+ return false;
+ pNewTorus->setMajorRadius( radius );
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( radius ) )
+ return false;
+ pNewTorus->setMinorRadius( radius );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewTorus );
+ parseObjectModifiers( pNewTorus );
+ switch( m_token )
+ {
+ case STURM_TOK:
+ nextToken( );
+ pNewTorus->setSturm( true );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBlob( PMBlob* pNewBlob )
+{
+ PMVector vector;
+ double threshold;
+ int oldConsumed;
+
+ if( !parseToken( BLOB_TOK, "blob" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ pNewBlob->setThreshold( 1.0 );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case STURM_TOK:
+ nextToken( );
+ pNewBlob->setSturm( true );
+ break;
+ case HIERARCHY_TOK:
+ pNewBlob->setHierarchy( true );
+ nextToken( );
+ if( isTrue( ) )
+ nextToken( );
+ else if( isFalse( ) )
+ {
+ nextToken( );
+ pNewBlob->setHierarchy( false );
+ }
+ break;
+ case THRESHOLD_TOK:
+ nextToken( );
+ if( parseFloat( threshold ) )
+ {
+ if( threshold <= 0 )
+ printError( i18n( "The threshold value has to be positive" ) );
+ else
+ pNewBlob->setThreshold( threshold );
+ }
+ break;
+ }
+
+ parseChildObjects( pNewBlob );
+ parseObjectModifiers( pNewBlob );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBlobSphere( PMBlobSphere* pNewBlobSphere )
+{
+ PMVector vector;
+ double radius;
+ double strength;
+
+ int oldConsumed;
+
+ if( !parseToken( SPHERE_TOK, "sphere" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBlobSphere->setCentre( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseFloat( radius ) )
+ return false;
+ pNewBlobSphere->setRadius( radius );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( m_token == STRENGTH_TOK )
+ nextToken( );
+
+ if( !parseFloat( strength ) )
+ return false;
+ pNewBlobSphere->setStrength( strength );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewBlobSphere );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBlobComponent( PMBlobSphere* pNewBlobSphere )
+{
+ PMVector vector;
+ double radius;
+ double strength;
+
+ if( !parseToken( COMPONENT_TOK, "component" ) )
+ return false;
+
+ if( !parseFloat( strength ) )
+ return false;
+ pNewBlobSphere->setStrength( strength );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseFloat( radius ) )
+ return false;
+ pNewBlobSphere->setRadius( radius );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBlobSphere->setCentre( vector );
+
+ return true;
+}
+
+bool PMPovrayParser::parseBlobCylinder( PMBlobCylinder* pNewBlobCylinder )
+{
+ PMVector vector;
+ double radius;
+ double strength;
+ int oldConsumed;
+
+ if( !parseToken( CYLINDER_TOK, "cylinder" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBlobCylinder->setEnd1( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBlobCylinder->setEnd2( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseFloat( radius ) )
+ return false;
+ pNewBlobCylinder->setRadius( radius );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( m_token == STRENGTH_TOK )
+ nextToken( );
+
+ if( !parseFloat( strength ) )
+ return false;
+ pNewBlobCylinder->setStrength( strength );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewBlobCylinder );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseHeightField( PMHeightField* pNewHeightField )
+{
+ int oldConsumed;
+ double wl;
+
+ if( !parseToken( HEIGHT_FIELD_TOK, "height_field" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ switch( m_token )
+ {
+ case GIF_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFgif );
+ nextToken( );
+ break;
+ case TGA_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFtga );
+ nextToken( );
+ break;
+ case POT_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFpot );
+ nextToken( );
+ break;
+ case PNG_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFpng );
+ nextToken( );
+ break;
+ case PGM_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFpgm );
+ nextToken( );
+ break;
+ case PPM_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFppm );
+ nextToken( );
+ break;
+ case SYS_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFsys );
+ nextToken( );
+ break;
+ default:
+ printExpected( i18n( "height field type" ), m_pScanner->sValue( ) );
+ return false;
+ }
+ if( m_token != STRING_TOK )
+ {
+ printExpected( i18n( "height field file" ), m_pScanner->sValue( ) );
+ return false;
+ }
+ else
+ {
+ pNewHeightField->setFileName( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case SMOOTH_TOK:
+ nextToken( );
+ pNewHeightField->setSmooth( true );
+ if( isTrue( ) )
+ nextToken( );
+ else if( isFalse( ) )
+ {
+ nextToken( );
+ pNewHeightField->setSmooth( false );
+ }
+ break;
+ case HIERARCHY_TOK:
+ pNewHeightField->setHierarchy( true );
+ nextToken( );
+ if( isTrue( ) )
+ nextToken( );
+ else if( isFalse( ) )
+ {
+ nextToken( );
+ pNewHeightField->setHierarchy( false );
+ }
+ break;
+ case WATER_LEVEL_TOK:
+ nextToken( );
+ if( parseFloat( wl ) )
+ {
+ if( ( wl < 0.0 ) || ( wl > 1.0 ) )
+ printError( i18n( "The water level has to be between 0 and 1" ) );
+ else
+ pNewHeightField->setWaterLevel( wl );
+ }
+ break;
+ }
+
+ parseChildObjects( pNewHeightField );
+ parseObjectModifiers( pNewHeightField );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseText( PMText* pNewText )
+{
+ int oldConsumed;
+ double thickness;
+ PMVector offset;
+
+ if( !parseToken( TEXT_TOK, "text" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseToken( TTF_TOK, "ttf" ) )
+ return false;
+
+ if( m_token != STRING_TOK )
+ {
+ printExpected( i18n( "font file name" ), m_pScanner->sValue( ) );
+ return false;
+ }
+ else
+ {
+ pNewText->setFont( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+ if( m_token != STRING_TOK )
+ {
+ printExpected( i18n( "string of text" ), m_pScanner->sValue( ) );
+ return false;
+ }
+ else
+ {
+ pNewText->setText( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+
+ if( !parseFloat( thickness ) )
+ return false;
+ pNewText->setThickness( thickness );
+
+ parseToken( ',' );
+
+ if( parseVector( offset, 2 ) )
+ pNewText->setOffset( offset );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewText );
+ parseObjectModifiers( pNewText );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseJuliaFractal( PMJuliaFractal* pNewFractal )
+{
+ int oldConsumed;
+ double d;
+ int i;
+ PMVector v( 4 ), v2( 2 );
+
+ if( !parseToken( JULIA_FRACTAL_TOK, "julia_fractal" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( v, 4 ) )
+ return false;
+ pNewFractal->setJuliaParameter( v );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case QUATERNION_TOK:
+ pNewFractal->setAlgebraType( PMJuliaFractal::Quaternion );
+ nextToken( );
+ break;
+ case HYPERCOMPLEX_TOK:
+ pNewFractal->setAlgebraType( PMJuliaFractal::Hypercomplex );
+ nextToken( );
+ break;
+ case SQR_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTsqr );
+ nextToken( );
+ break;
+ case CUBE_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTcube );
+ nextToken( );
+ break;
+ case EXP_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTexp );
+ nextToken( );
+ break;
+ case RECIPROCAL_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTreciprocal );
+ nextToken( );
+ break;
+ case SIN_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTsin );
+ nextToken( );
+ break;
+ case ASIN_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTasin );
+ nextToken( );
+ break;
+ case SINH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTsinh );
+ nextToken( );
+ break;
+ case ASINH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTasinh );
+ nextToken( );
+ break;
+ case COS_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTcos );
+ nextToken( );
+ break;
+ case ACOS_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTacos );
+ nextToken( );
+ break;
+ case COSH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTcosh );
+ nextToken( );
+ break;
+ case ACOSH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTacosh );
+ nextToken( );
+ break;
+ case TAN_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTtan );
+ nextToken( );
+ break;
+ case ATAN_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTatan );
+ nextToken( );
+ break;
+ case TANH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTtanh );
+ nextToken( );
+ break;
+ case ATANH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTatanh );
+ nextToken( );
+ break;
+ case LOG_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTlog );
+ nextToken( );
+ break;
+ case PWR_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTpwr );
+ nextToken( );
+ if( !parseToken( '(' ) )
+ return false;
+ if( !parseFloat( v2[0] ) )
+ return false;
+ parseToken( ',' );
+ if( !parseFloat( v2[1] ) )
+ return false;
+ if( !parseToken( ')' ) )
+ return false;
+ pNewFractal->setExponent( v2 );
+ break;
+ case MAX_ITERATION_TOK:
+ nextToken( );
+ if( !parseInt( i ) )
+ return false;
+ if( i <= 0 )
+ {
+ printWarning( i18n( "Maximum iterations are less than 1, fixed" ) );
+ i = 1;
+ }
+ pNewFractal->setMaximumIterations( i );
+ break;
+ case PRECISION_TOK:
+ nextToken( );
+ if( !parseFloat( d ) )
+ return false;
+ if( d < 1.0 )
+ {
+ printWarning( i18n( "Precision is less than 1.0, fixed" ) );
+ d = 1.0;
+ }
+ pNewFractal->setPrecision( d );
+ break;
+ case SLICE_TOK:
+ nextToken( );
+ if( !parseVector( v, 4 ) )
+ return false;
+ pNewFractal->setSliceNormal( v );
+ parseToken( ',' );
+ if( !parseFloat( d ) )
+ return false;
+ pNewFractal->setSliceDistance( d );
+ break;
+ }
+
+ parseChildObjects( pNewFractal );
+ parseObjectModifiers( pNewFractal );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePlane( PMPlane* pNewPlane )
+{
+ double dist;
+ PMVector vector;
+ int oldConsumed;
+
+ if( !parseToken( PLANE_TOK, "plane" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewPlane->setNormal( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( dist ) )
+ return false;
+ pNewPlane->setDistance( dist );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewPlane );
+ parseObjectModifiers( pNewPlane );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+const int c_polynomSize[8] = { 0, 0, 10, 20, 35, 56, 84, 120 };
+
+bool PMPovrayParser::parsePolynom( PMPolynom* pNewPoly )
+{
+ PMVector vector;
+ double d;
+ PMVector c;
+ int oldConsumed;
+ int order = 2;
+ int type = m_token;
+
+ pNewPoly->setSturm( false );
+
+ if( ( m_token == QUADRIC_TOK ) || ( m_token == CUBIC_TOK ) ||
+ ( m_token == QUARTIC_TOK ) || ( m_token == POLY_TOK ) )
+ {
+ nextToken( );
+ if( !parseToken( '{' ) )
+ return false;
+ }
+ else
+ printExpected( "poly", m_pScanner->sValue( ) );
+
+ if( type == QUADRIC_TOK )
+ {
+ c = PMVector( 10 );
+ pNewPoly->setPolynomOrder( 2 );
+
+ // parse the quadric coefficients
+ if( !parseVectorLiteral( vector ) )
+ return false;
+ vector.resize( 3 );
+ c[0] = vector[0];
+ c[4] = vector[1];
+ c[7] = vector[2];
+ parseToken( ',' );
+
+ if( !parseVectorLiteral( vector ) )
+ return false;
+ vector.resize( 3 );
+ c[1] = vector[0];
+ c[2] = vector[1];
+ c[5] = vector[2];
+ parseToken( ',' );
+
+ if( !parseVectorLiteral( vector ) )
+ return false;
+ vector.resize( 3 );
+ c[3] = vector[0];
+ c[6] = vector[1];
+ c[8] = vector[2];
+ parseToken( ',' );
+
+ if( !parseFloat( d ) )
+ return false;
+ c[9] = d;
+
+ pNewPoly->setCoefficients( c );
+ }
+ else
+ {
+ if( type == CUBIC_TOK )
+ order = 3;
+ else if( type == QUARTIC_TOK )
+ order = 4;
+ else
+ {
+ if( !parseInt( order ) )
+ return false;
+ if( ( order < 2 ) || ( order > 7 ) )
+ {
+ printError( i18n( "The polynom order has to be between 2 and 7 inclusive" ) );
+ return false;
+ }
+ parseToken( ',' );
+ }
+
+ pNewPoly->setPolynomOrder( order );
+
+ if( !parseVectorLiteral( vector ) )
+ return false;
+
+ if( vector.size( ) != ( unsigned ) c_polynomSize[order] )
+ {
+ printError( i18n( "%1 coefficients are needed for a polynom with order %2" )
+ .arg( c_polynomSize[order] ).arg( order ) );
+ vector.resize( c_polynomSize[order] );
+ }
+ pNewPoly->setCoefficients( vector );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == STURM_TOK )
+ {
+ pNewPoly->setSturm( true );
+ nextToken( );
+ }
+
+ parseChildObjects( pNewPoly );
+ parseObjectModifiers( pNewPoly );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBicubicPatch( PMBicubicPatch* pNewPatch )
+{
+ PMVector vector;
+ bool stop = false;
+ int oldConsumed;
+ int type;
+ int steps;
+ double flatness;
+ int i;
+
+ if( !parseToken( BICUBIC_PATCH_TOK, "bicubic_patch" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ // parse patch items
+ do
+ {
+ switch( m_token )
+ {
+ case TYPE_TOK:
+ nextToken( );
+ if( parseInt( type ) )
+ {
+ if( ( type == 0 ) || ( type == 1 ) )
+ pNewPatch->setPatchType( type );
+ else
+ printError( i18n( "Patch type has to be 0 or 1" ) );
+ }
+ break;
+ case U_STEPS_TOK:
+ nextToken( );
+ if( parseInt( steps ) )
+ pNewPatch->setUSteps( steps );
+ break;
+ case V_STEPS_TOK:
+ nextToken( );
+ if( parseInt( steps ) )
+ pNewPatch->setVSteps( steps );
+ break;
+ case FLATNESS_TOK:
+ nextToken( );
+ if( parseFloat( flatness ) )
+ pNewPatch->setFlatness( flatness );
+ break;
+ case UV_VECTORS_TOK:
+ pNewPatch->enableUV( true );
+ nextToken( );
+ for ( i = 0; i < 4; ++i )
+ {
+ if( parseVector( vector ) )
+ pNewPatch->setUVVector( i, vector );
+ else
+ return false;
+ }
+ break;
+ case ',':
+ nextToken( );
+ stop = true;
+ break;
+ default:
+ stop = true;
+ break;
+ }
+ }
+ while( !stop );
+
+ // parse control points
+ stop = false;
+ for( i = 0; ( i < 16 ) && !stop; i++ )
+ {
+ if( parseVector( vector ) )
+ {
+ pNewPatch->setControlPoint( i, vector );
+ if( i < 15 )
+ if( !parseToken( ',' ) )
+ stop = true;
+ }
+ else
+ stop = true;
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewPatch );
+ parseObjectModifiers( pNewPatch );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseDisc( PMDisc* pNewDisc )
+{
+ double d;
+ PMVector vector;
+ int oldConsumed;
+
+ if( !parseToken( DISC_TOK, "disc" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewDisc->setCenter( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseVector( vector ) )
+ return false;
+ pNewDisc->setNormal( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( d ) )
+ return false;
+ pNewDisc->setRadius( d );
+
+ if( m_token == ',' )
+ {
+ nextToken( );
+ if( !parseFloat( d ) )
+ return false;
+ pNewDisc->setHoleRadius( d );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewDisc );
+ parseObjectModifiers( pNewDisc );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseTriangle( PMTriangle* pNewTriangle )
+{
+ PMVector vector;
+ int oldConsumed;
+ int i;
+
+ if( m_token == SMOOTH_TRIANGLE_TOK )
+ pNewTriangle->setSmoothTriangle( true );
+ else if( m_token == TRIANGLE_TOK )
+ pNewTriangle->setSmoothTriangle( false );
+ else
+ {
+ printExpected( "triangle", m_pScanner->sValue( ) );
+ return false;
+ }
+ nextToken( );
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ for( i = 0; i < 3; i++ )
+ {
+ if( i != 0 )
+ parseToken( ',' );
+ if( !parseVector( vector ) )
+ return false;
+ pNewTriangle->setPoint( i, vector );
+
+ if( pNewTriangle->isSmoothTriangle( ) )
+ {
+ parseToken( ',' );
+ if( !parseVector( vector ) )
+ return false;
+ pNewTriangle->setNormal( i, vector );
+ }
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewTriangle );
+ parseObjectModifiers( pNewTriangle );
+ if( m_token == UV_VECTORS_TOK )
+ {
+ nextToken( );
+ pNewTriangle->enableUV( true );
+ for ( i = 0; i < 3; ++i )
+ {
+ if( parseVector( vector ) )
+ pNewTriangle->setUVVector( i, vector );
+ else
+ return false;
+ }
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseLathe( PMLathe* pNewLathe )
+{
+ PMVector vector;
+ int oldConsumed;
+ int i;
+ bool stop = false;
+
+ if( !parseToken( LATHE_TOK, "lathe" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ int minp = 2;
+ while( !stop )
+ {
+ switch( m_token )
+ {
+ case LINEAR_SPLINE_TOK:
+ pNewLathe->setSplineType( PMLathe::LinearSpline );
+ nextToken( );
+ minp = 2;
+ break;
+ case QUADRATIC_SPLINE_TOK:
+ pNewLathe->setSplineType( PMLathe::QuadraticSpline );
+ nextToken( );
+ minp = 3;
+ break;
+ case CUBIC_SPLINE_TOK:
+ pNewLathe->setSplineType( PMLathe::CubicSpline );
+ nextToken( );
+ minp = 4;
+ break;
+ case BEZIER_SPLINE_TOK:
+ pNewLathe->setSplineType( PMLathe::BezierSpline );
+ nextToken( );
+ minp = 4;
+ break;
+ default:
+ stop = true;
+ break;
+ }
+ }
+
+ int nump;
+ if( !parseInt( nump ) )
+ return false;
+
+ QValueList<PMVector> points;
+ for( i = 0; i < nump; i++ )
+ {
+ parseToken( ',' );
+ if( !parseVector( vector ) )
+ return false;
+ vector.resize( 2 );
+ points.append( vector );
+ }
+
+ if( nump < minp )
+ printError( i18n( "At least %1 points are needed for that spline type" )
+ .arg( minp ) );
+ else if( ( pNewLathe->splineType( ) == PMLathe::BezierSpline ) &&
+ ( ( nump % 4 ) != 0 ) )
+ printError( i18n( "Bezier splines need 4 points for each segment" ) );
+ else
+ pNewLathe->setPoints( points );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == STURM_TOK )
+ {
+ pNewLathe->setSturm( true );
+ nextToken( );
+ }
+
+ parseChildObjects( pNewLathe );
+ parseObjectModifiers( pNewLathe );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePrism( PMPrism* pNewPrism )
+{
+ PMVector vector;
+ double height;
+ int oldConsumed;
+ int i;
+ bool stop = false;
+
+ if( !parseToken( PRISM_TOK, "prism" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ int minp = 3;
+ while( !stop )
+ {
+ switch( m_token )
+ {
+ case LINEAR_SPLINE_TOK:
+ pNewPrism->setSplineType( PMPrism::LinearSpline );
+ nextToken( );
+ minp = 3;
+ break;
+ case QUADRATIC_SPLINE_TOK:
+ pNewPrism->setSplineType( PMPrism::QuadraticSpline );
+ nextToken( );
+ minp = 4;
+ break;
+ case CUBIC_SPLINE_TOK:
+ pNewPrism->setSplineType( PMPrism::CubicSpline );
+ nextToken( );
+ minp = 5;
+ break;
+ case BEZIER_SPLINE_TOK:
+ pNewPrism->setSplineType( PMPrism::BezierSpline );
+ nextToken( );
+ minp = 4;
+ break;
+ case LINEAR_SWEEP_TOK:
+ pNewPrism->setSweepType( PMPrism::LinearSweep );
+ nextToken( );
+ break;
+ case CONIC_SWEEP_TOK:
+ pNewPrism->setSweepType( PMPrism::ConicSweep );
+ nextToken( );
+ break;
+ default:
+ stop = true;
+ break;
+ }
+ }
+
+ if( !parseFloat( height ) )
+ return false;
+ pNewPrism->setHeight1( height );
+ parseToken( ',' );
+ if( !parseFloat( height ) )
+ return false;
+ pNewPrism->setHeight2( height );
+ parseToken( ',' );
+
+ int nump;
+ if( !parseInt( nump ) )
+ return false;
+
+ QValueList<PMVector> allPoints;
+ for( i = 0; i < nump; i++ )
+ {
+ parseToken( ',' );
+ if( !parseVector( vector ) )
+ return false;
+ vector.resize( 2 );
+ allPoints.append( vector );
+ }
+
+ QValueList< QValueList<PMVector> > points;
+ QValueList<PMVector> subPoints;
+ QValueList<PMVector>::Iterator it = allPoints.begin( );
+ int pnr = 0, pmod4;
+ PMVector ref( 2 ), ref2( 2 );
+ bool error = false;
+ bool last = false;
+
+ switch( pNewPrism->splineType( ) )
+ {
+ case PMPrism::LinearSpline:
+ for( ; ( it != allPoints.end( ) ) && !error; ++it, pnr++ )
+ {
+ if( pnr == 0 )
+ {
+ ref = *it;
+ subPoints.append( *it );
+ }
+ else
+ {
+ if( ref.approxEqual( *it ) )
+ {
+ if( pnr < 3 )
+ {
+ printError( i18n( "Linear splines need at least 4 points." ) );
+ error = true;
+ }
+ else
+ {
+ points.append( subPoints );
+ subPoints.clear( );
+ pnr = -1;
+ }
+ }
+ else
+ subPoints.append( *it );
+ }
+ }
+ if( ( pnr != 0 ) && ( !error ) )
+ {
+ printWarning( i18n( "Linear spline not closed" ) );
+ if( pnr < 3 )
+ {
+ printError( i18n( "Linear splines need at least 4 points." ) );
+ error = true;
+ }
+ else
+ {
+ points.append( subPoints );
+ subPoints.clear( );
+ }
+ }
+ break;
+ case PMPrism::QuadraticSpline:
+ for( ; ( it != allPoints.end( ) ) && !error; ++it, pnr++ )
+ {
+ if( pnr == 0 )
+ subPoints.append( *it );
+ else if( pnr == 1 )
+ {
+ ref = *it;
+ subPoints.append( *it );
+ }
+ else
+ {
+ if( ref.approxEqual( *it ) )
+ {
+ if( pnr < 4 )
+ {
+ printError( i18n( "Quadratic splines need at least 5 points." ) );
+ error = true;
+ }
+ else
+ {
+ points.append( subPoints );
+ subPoints.clear( );
+ pnr = -1;
+ }
+ }
+ else
+ subPoints.append( *it );
+ }
+ }
+ if( ( pnr != 0 ) && ( !error ) )
+ {
+ printError( i18n( "Quadratic spline not closed" ) );
+ error = true;
+ }
+ break;
+ case PMPrism::CubicSpline:
+ for( ; ( it != allPoints.end( ) ) && !error; ++it, pnr++ )
+ {
+ if( pnr == 0 )
+ subPoints.append( *it );
+ else if( pnr == 1 )
+ {
+ ref = *it;
+ subPoints.append( *it );
+ }
+ else if( last )
+ {
+ if( pnr < 5 )
+ {
+ printError( i18n( "Cubic splines need at least 6 points." ) );
+ error = true;
+ }
+ else
+ {
+ subPoints.append( *it );
+ points.append( subPoints );
+ subPoints.clear( );
+ pnr = -1;
+ last = false;
+ }
+ }
+ else
+ {
+ if( ref.approxEqual( *it ) )
+ last = true;
+ else
+ subPoints.append( *it );
+ }
+ }
+ if( ( pnr != 0 ) && ( !error ) )
+ {
+ printError( i18n( "Cubic spline not closed" ) );
+ error = true;
+ }
+ break;
+ case PMPrism::BezierSpline:
+ for( ; ( it != allPoints.end( ) ) && !error; ++it, pnr++ )
+ {
+ pmod4 = pnr % 4;
+
+ if( pnr == 0 )
+ {
+ ref = *it;
+ subPoints.append( *it );
+ }
+ else if( pmod4 == 0 )
+ {
+ if( !ref2.approxEqual( *it ) )
+ {
+ printError( i18n( "Bezier spline not closed" ) );
+ error = true;
+ }
+ }
+ else if( pmod4 == 3 )
+ {
+ if( ref.approxEqual( *it ) )
+ {
+ points.append( subPoints );
+ subPoints.clear( );
+ pnr = -1;
+ }
+ else
+ {
+ subPoints.append( *it );
+ ref2 = *it;
+ }
+ }
+ else
+ subPoints.append( *it );
+ }
+ if( ( pnr != 0 ) && ( !error ) )
+ {
+ printError( i18n( "Bezier spline not closed" ) );
+ error = true;
+ }
+ break;
+ }
+
+ if( !error )
+ pNewPrism->setPoints( points );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case STURM_TOK:
+ pNewPrism->setSturm( true );
+ nextToken( );
+ break;
+ case OPEN_TOK:
+ pNewPrism->setOpen( true );
+ nextToken( );
+ break;
+ default:
+ break;
+ }
+
+ parseChildObjects( pNewPrism );
+ parseObjectModifiers( pNewPrism );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSor( PMSurfaceOfRevolution* pNewSor )
+{
+ PMVector vector;
+ int oldConsumed;
+ int i;
+
+ if( !parseToken( SOR_TOK, "sor" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ int nump;
+ if( !parseInt( nump ) )
+ return false;
+
+ QValueList<PMVector> points;
+ for( i = 0; i < nump; i++ )
+ {
+ parseToken( ',' );
+ if( !parseVector( vector ) )
+ return false;
+ vector.resize( 2 );
+ points.append( vector );
+ }
+
+ if( nump < 4 )
+ printError( i18n( "At least 4 points are needed for the surface of revolution" ) );
+ else
+ {
+ QValueList<PMVector>::Iterator it1 = points.begin( );
+ QValueList<PMVector>::Iterator it2 = it1; ++it2;
+ QValueList<PMVector>::Iterator it3 = it2; ++it3;
+ int pnr = 0;
+
+ for( ; it3 != points.end( ); ++it1, ++it2, ++it3, pnr++ )
+ {
+ if( ( pnr == 0 ) || ( pnr == ( nump - 3 ) ) )
+ {
+ if( approxZero( ( *it1 )[1] - ( *it3 )[1], c_sorTolerance ) )
+ {
+ printError( i18n( "The v coordinate of point %1 and %2 must be different; fixed" )
+ .arg( pnr + 1 ).arg( pnr + 3 ) );
+ if( pnr == 0 )
+ ( *it1 )[1] = ( *it3 )[1] - c_sorTolerance;
+ else
+ ( *it3 )[1] = ( *it1 )[1] + c_sorTolerance;
+ }
+ }
+
+ if( pnr != 0 )
+ {
+ if( ( ( *it2 )[1] - ( *it1 )[1] ) < c_sorTolerance )
+ {
+ printError( i18n( "The v coordinates must be strictly increasing; fixed" ) );
+ ( *it2 )[1] = ( *it1 )[1] + c_sorTolerance;
+ }
+ }
+ }
+ pNewSor->setPoints( points );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case STURM_TOK:
+ pNewSor->setSturm( true );
+ nextToken( );
+ break;
+ case OPEN_TOK:
+ pNewSor->setOpen( true );
+ nextToken( );
+ break;
+ default:
+ break;
+ }
+
+ parseChildObjects( pNewSor );
+ parseObjectModifiers( pNewSor );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSqe( PMSuperquadricEllipsoid* pNewSqe )
+{
+ PMVector vector;
+ int oldConsumed;
+
+ if( !parseToken( SUPERELLIPSOID_TOK ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ vector.resize( 2 );
+
+ if( vector[0] < 0.001 )
+ {
+ printError( i18n( "The east-west exponent must be greater than 0.001" ) );
+ vector[0] = 0.001;
+ }
+ if( vector[1] < 0.001 )
+ {
+ printError( i18n( "The north-south exponent must be greater than 0.001" ) );
+ vector[1] = 0.001;
+ }
+
+ pNewSqe->setEastWestExponent( vector[0] );
+ pNewSqe->setNorthSouthExponent( vector[1] );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewSqe );
+ parseObjectModifiers( pNewSqe );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseRotate( PMRotate* rotate )
+{
+ PMVector v;
+
+ if( !parseToken( ROTATE_TOK, "rotate" ) )
+ return false;
+ if( !parseVector( v ) )
+ return false;
+
+ rotate->setRotation( v );
+ return true;
+}
+
+bool PMPovrayParser::parseScale( PMScale* scale )
+{
+ PMVector v;
+
+ if( !parseToken( SCALE_TOK, "scale" ) )
+ return false;
+ if( !parseVector( v ) )
+ return false;
+
+ scale->setScale( v );
+ return true;
+}
+
+bool PMPovrayParser::parseTranslate( PMTranslate* translate )
+{
+ PMVector v;
+
+ if( !parseToken( TRANSLATE_TOK, "translate" ) )
+ return false;
+ if( !parseVector( v ) )
+ return false;
+
+ translate->setTranslation( v );
+ return true;
+}
+
+bool PMPovrayParser::parseMatrix( PMPovrayMatrix* matrix )
+{
+ PMVector v;
+
+ if( !parseToken( MATRIX_TOK ), "matrix" )
+ return false;
+ if( !parseVectorLiteral( v ) )
+ return false;
+
+ if( v.size( ) != 12 )
+ {
+ printError( i18n( "Wrong number of matrix values." ) );
+ v.resize( 12 );
+ }
+ matrix->setValues( v );
+ return true;
+}
+
+bool PMPovrayParser::parseBoundedBy( PMBoundedBy* bound )
+{
+ int oldConsumed;
+
+ if( !parseToken( BOUNDED_BY_TOK, "bounded_by" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == CLIPPED_BY_TOK )
+ nextToken( );
+
+ parseChildObjects( bound );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseClippedBy( PMClippedBy* clipped )
+{
+ int oldConsumed;
+
+ if( !parseToken( CLIPPED_BY_TOK, "clipped_by" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == BOUNDED_BY_TOK )
+ nextToken( );
+
+ parseChildObjects( clipped );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseCamera( PMCamera* camera )
+{
+ PMVector v;
+ double d;
+ int i;
+
+ int oldConsumed;
+
+ if( !parseToken( CAMERA_TOK, "camera" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case PERSPECTIVE_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::Perspective );
+ break;
+ case ORTHOGRAPHIC_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::Orthographic );
+ break;
+ case FISHEYE_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::FishEye );
+ break;
+ case ULTRA_WIDE_ANGLE_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::UltraWideAngle );
+ break;
+ case OMNIMAX_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::Omnimax );
+ break;
+ case PANORAMIC_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::Panoramic );
+ break;
+ case CYLINDER_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::Cylinder );
+ if( parseInt( i ) )
+ camera->setCylinderType( i );
+ break;
+ case LOCATION_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setLocation( v );
+ break;
+ case SKY_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setSky( v );
+ break;
+ case UP_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setUp( v );
+ break;
+ case RIGHT_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setRight( v );
+ break;
+ case DIRECTION_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setDirection( v );
+ break;
+ case LOOK_AT_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setLookAt( v );
+ break;
+ case ANGLE_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ {
+ camera->enableAngle( true );
+ camera->setAngle( d );
+ }
+ break;
+ case BLUR_SAMPLES_TOK:
+ nextToken( );
+ camera->enableFocalBlur( true );
+ if( parseInt( i ) )
+ camera->setBlurSamples( i );
+ break;
+ case APERTURE_TOK:
+ nextToken( );
+ camera->enableFocalBlur( true );
+ if( parseFloat( d ) )
+ camera->setAperture( d );
+ break;
+ case FOCAL_POINT_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setFocalPoint( v );
+ break;
+ case CONFIDENCE_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ camera->setConfidence( d );
+ break;
+ case VARIANCE_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ camera->setVariance( d );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+ parseChildObjects( camera );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseLight( PMLight* light )
+{
+ PMVector v;
+ PMColor c;
+ double d;
+ int i;
+
+ int oldConsumed;
+
+ if( !parseToken( LIGHT_SOURCE_TOK, "light_source" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+ if( !parseVector( v ) )
+ return false;
+ light->setLocation( v );
+ if( m_token == ',' )
+ nextToken( );
+ if( !parseColor( c ) )
+ return false;
+ light->setColor( c );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( light );
+
+ switch( m_token )
+ {
+ case SPOTLIGHT_TOK:
+ nextToken( );
+ light->setLightType( PMLight::SpotLight );
+ break;
+ case CYLINDER_TOK:
+ nextToken( );
+ light->setLightType( PMLight::CylinderLight );
+ break;
+ case SHADOWLESS_TOK:
+ nextToken( );
+ light->setLightType( PMLight::ShadowlessLight );
+ break;
+ case RADIUS_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ light->setRadius( d );
+ break;
+ case FALLOFF_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ light->setFalloff( d );
+ break;
+ case TIGHTNESS_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ light->setTightness( d );
+ break;
+ case POINT_AT_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ light->setPointAt( v );
+ break;
+ case PARALLEL_TOK:
+ nextToken( );
+ light->setParallel( parseBool( ) );
+ break;
+ case AREA_LIGHT_TOK:
+ nextToken( );
+ light->setAreaLight( true );
+ if( parseVector( v ) )
+ light->setAxis1( v );
+ parseToken( ',' );
+ if( parseVector( v ) )
+ light->setAxis2( v );
+ parseToken( ',' );
+ if( parseInt( i ) )
+ light->setSize1( i );
+ parseToken( ',' );
+ if( parseInt( i ) )
+ light->setSize2( i );
+ break;
+ case AREA_CIRCULAR_TOK:
+ nextToken( );
+ light->setAreaType( PMLight::Circular );
+ break;
+ case ADAPTIVE_TOK:
+ nextToken( );
+ if( parseInt( i ) )
+ light->setAdaptive( i );
+ break;
+ case ORIENT_TOK:
+ nextToken( );
+ light->setOrient( parseBool( ) );
+ break;
+ case JITTER_TOK:
+ nextToken( );
+ light->setJitter( parseBool( ) );
+ break;
+ case FADE_POWER_TOK:
+ nextToken( );
+ light->setFading( true );
+ if( parseInt( i ) )
+ light->setFadePower( i );
+ break;
+ case FADE_DISTANCE_TOK:
+ nextToken( );
+ light->setFading( true );
+ if( parseFloat( d ) )
+ light->setFadeDistance( d );
+ break;
+ case MEDIA_INTERACTION_TOK:
+ nextToken( );
+ light->setMediaInteraction( parseBool( ) );
+ break;
+ case MEDIA_ATTENUATION_TOK:
+ nextToken( );
+ light->setMediaAttenuation( parseBool( ) );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseLooksLike( PMLooksLike* ll )
+{
+ if( !parseToken( LOOKS_LIKE_TOK, "looks_like" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ parseChildObjects( ll );
+
+ if( !parseToken( '}' ) )
+ return false;
+ return true;
+}
+
+bool PMPovrayParser::parseProjectedThrough( PMProjectedThrough* ll )
+{
+ if( !parseToken( PROJECTED_THROUGH_TOK, "projected_through" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ parseChildObjects( ll );
+
+ if( !parseToken( '}' ) )
+ return false;
+ return true;
+}
+
+bool PMPovrayParser::parseTexture( PMTexture* texture, bool parseOuter )
+{
+ int oldConsumed;
+
+ if( parseOuter )
+ {
+ if( !parseToken( TEXTURE_TOK, "texture" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+ }
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !texture->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( texture );
+ if( m_token == UV_MAPPING_TOK )
+ {
+ nextToken();
+ texture->setUVMapping( parseBool( ) );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( parseOuter )
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePattern( PMPattern* pattern, bool normal )
+{
+ PMVector vector;
+ double f_number;
+ int i_number;
+ int oldConsumed;
+ bool type;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ type = false;
+
+ switch( m_token )
+ {
+ case AGATE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternAgate );
+ type = true;
+ break;
+ case AGATE_TURB_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setAgateTurbulence( f_number );
+ break;
+ case AVERAGE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternAverage );
+ type = true;
+ break;
+ case BOXED_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternBoxed );
+ type = true;
+ break;
+ case BOZO_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternBozo );
+ type = true;
+ break;
+ case BUMPS_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternBumps );
+ type = true;
+ break;
+ case CELLS_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternCells );
+ type = true;
+ break;
+ case CRACKLE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternCrackle );
+ type = true;
+ break;
+ case CYLINDRICAL_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternCylindrical );
+ type = true;
+ break;
+ case DENTS_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternDents );
+ type = true;
+ break;
+ case DENSITY_FILE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternDensity );
+ type = true;
+ if( !parseToken( DF3_TOK, "df3" ) )
+ return false;
+ if( m_token != STRING_TOK )
+ {
+ printError( i18n( "Expecting a file name." ) );
+ return false;
+ }
+ else
+ {
+ pattern->setDensityFile( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+ if( parseToken( INTERPOLATE_TOK, "interpolate" ) )
+ {
+ if( !parseInt( i_number ) )
+ return false;
+ else
+ pattern->setDensityInterpolate( i_number );
+ }
+ break;
+ case GRADIENT_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternGradient );
+ type = true;
+ if( !parseVector( vector ) )
+ return false;
+ pattern->setGradient( vector );
+ break;
+ case GRANITE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternGranite );
+ type = true;
+ break;
+ case JULIA_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternJulia );
+ type = true;
+ if( !parseVector( vector ) )
+ return false;
+ pattern->setJuliaComplex( vector );
+ if( !parseInt( i_number ) )
+ return false;
+ pattern->setMaxIterations( i_number );
+ break;
+ case LEOPARD_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternLeopard );
+ type = true;
+ break;
+ case MANDEL_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternMandel );
+ type = true;
+ if( !parseInt( i_number ) )
+ return false;
+ pattern->setMaxIterations( i_number );
+ break;
+ case MARBLE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternMarble );
+ type = true;
+ break;
+ case ONION_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternOnion );
+ type = true;
+ break;
+ case PLANAR_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternPlanar );
+ type = true;
+ break;
+ case QUILTED_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternQuilted );
+ type = true;
+ break;
+ case CONTROL0_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setQuiltControl0( f_number );
+ break;
+ case CONTROL1_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setQuiltControl1( f_number );
+ break;
+ case RADIAL_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternRadial );
+ type = true;
+ break;
+ case RIPPLES_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternRipples );
+ type = true;
+ break;
+ case SLOPE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternSlope );
+ type = true;
+ if( !parseToken( '{' ) )
+ return false;
+ if( !parseVector( vector ) )
+ return false;
+ pattern->setSlopeDirection( vector );
+ if ( parseToken( ',' ) )
+ {
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setSlopeLoSlope( f_number );
+ if ( parseToken( ',' ) )
+ {
+ if ( !parseFloat( f_number ) )
+ return false;
+ pattern->setSlopeHiSlope( f_number );
+ }
+ }
+ if( m_token == ALTITUDE_TOK )
+ {
+ pattern->setSlopeAltFlag( true );
+ nextToken( );
+ if ( !parseVector( vector ) )
+ return false;
+ pattern->setSlopeAltitude( vector );
+ if( parseToken( ',' ) )
+ {
+ if ( !parseFloat( f_number ) )
+ return false;
+ pattern->setSlopeLoAlt( f_number );
+ if ( parseToken( ',' ) )
+ {
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setSlopeHiAlt( f_number );
+ }
+ }
+ }
+ if( !parseToken( '}' ) )
+ return false;
+ break;
+ case SPHERICAL_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternSpherical );
+ type = true;
+ break;
+ case SPIRAL1_TOK:
+ case SPIRAL2_TOK:
+ if( m_token == SPIRAL1_TOK )
+ pattern->setPatternType( PMPattern::PatternSpiral1 );
+ else
+ pattern->setPatternType( PMPattern::PatternSpiral2 );
+ type = true;
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ pattern->setSpiralNumberArms( i_number );
+ break;
+ case SPOTTED_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternSpotted );
+ type = true;
+ break;
+ case WAVES_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternWaves );
+ type = true;
+ break;
+ case WOOD_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternWood );
+ type = true;
+ break;
+ case WRINKLES_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternWrinkles );
+ type = true;
+ break;
+
+ //crackle parameters
+ case FORM_TOK:
+ nextToken( );
+ if( !parseVector( vector ) )
+ return false;
+ pattern->setCrackleForm( vector );
+ break;
+ case METRIC_TOK:
+ nextToken( );
+ if ( !parseInt( i_number ) )
+ return false;
+ pattern->setCrackleMetric( i_number );
+ break;
+ case OFFSET_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setCrackleOffset( f_number );
+ break;
+ case SOLID_TOK:
+ nextToken( );
+ pattern->setCrackleSolid( true );
+ break;
+
+ //fractal parameters
+ case MAGNET_TOK:
+ nextToken( );
+ pattern->setFractalMagnet( true );
+ if ( !parseInt( i_number ) )
+ return false;
+ pattern->setFractalMagnetType( i_number );
+ break;
+ case EXPONENT_TOK:
+ nextToken( );
+ if ( !parseInt( i_number ) )
+ return false;
+ pattern->setFractalExponent( i_number );
+ break;
+ case EXTERIOR_TOK:
+ nextToken( );
+ if ( !parseInt( i_number ) )
+ return false;
+ pattern->setFractalExtType( i_number );
+ if ( !parseFloat( f_number ) )
+ return false;
+ pattern->setFractalExtFactor( f_number );
+ break;
+ case INTERIOR_TOK:
+ nextToken( );
+ if ( !parseInt( i_number ) )
+ return false;
+ pattern->setFractalIntType( i_number );
+ if ( !parseFloat( f_number ) )
+ return false;
+ pattern->setFractalIntFactor( f_number );
+ break;
+
+ //turbulence
+ case TURBULENCE_TOK:
+ nextToken( );
+ pattern->enableTurbulence( true );
+ if( !parseVector( vector ) )
+ return false;
+ pattern->setValueVector( vector );
+ break;
+ case OCTAVES_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ pattern->setOctaves( i_number );
+ break;
+ case OMEGA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setOmega( f_number );
+ break;
+ case LAMBDA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setLambda( f_number );
+ break;
+
+ case NOISE_GENERATOR_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ pattern->setNoiseGenerator( ( PMPattern::PMNoiseType ) ( i_number ) );
+ break;
+ default:
+ break;
+ }
+
+ if( type && normal )
+ {
+ // try to parse the normal pattern depth
+ double depth;
+ if( parseFloat( depth, true ) )
+ pattern->setDepth( depth );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ return true;
+}
+
+bool PMPovrayParser::parseBlendMapModifiers( PMBlendMapModifiers* blend )
+{
+ int oldConsumed;
+ double f_number;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case FREQUENCY_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ blend->enableFrequency( true );
+ blend->setFrequency( f_number );
+ break;
+ case PHASE_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ blend->enablePhase( true );
+ blend->setPhase( f_number );
+ break;
+ case RAMP_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::RampWave );
+ break;
+ case TRIANGLE_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::TriangleWave );
+ break;
+ case SINE_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::SineWave );
+ break;
+ case SCALLOP_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::ScallopWave );
+ break;
+ case CUBIC_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::CubicWave );
+ break;
+ case POLY_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::PolyWave );
+ if( parseFloat( f_number, true ) )
+ blend->setWaveFormExponent( f_number );
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ return true;
+}
+
+bool PMPovrayParser::parseWarp( PMWarp* warp )
+{
+ int oldConsumed;
+ PMVector vector;
+ double f_number;
+ int i_number;
+ bool parsedFirst;
+ bool mapping;
+
+ if( !parseToken( WARP_TOK, "warp" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ mapping = false;
+ parsedFirst = false;
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ if( !parsedFirst &&
+ ( m_token != REPEAT_TOK ||
+ m_token != BLACK_HOLE_TOK ||
+ m_token != TURBULENCE_TOK ||
+ m_token != CYLINDRICAL_TOK ||
+ m_token != SPHERICAL_TOK ||
+ m_token != TOROIDAL_TOK ||
+ m_token != PLANAR_TOK ) )
+ {
+ printError( i18n( "Expecting a warp type" ) );
+ return false;
+ }
+ switch( m_token )
+ {
+ case REPEAT_TOK:
+ nextToken( );
+ if( !parsedFirst )
+ {
+ warp->setWarpType( PMWarp::Repeat );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setDirection( vector );
+ parsedFirst = true;
+ }
+ else
+ {
+ if( !parseVector( vector ) )
+ return false;
+ warp->setRepeat( vector );
+ }
+ break;
+ case OFFSET_TOK:
+ nextToken( );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setOffset( vector );
+ break;
+ case FLIP_TOK:
+ nextToken( );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setFlip( vector );
+ break;
+ case BLACK_HOLE_TOK:
+ nextToken( );
+ warp->setWarpType( PMWarp::BlackHole );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setLocation( vector );
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setRadius( f_number );
+ parsedFirst = true;
+ break;
+ case STRENGTH_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setStrength( f_number );
+ break;
+ case FALLOFF_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setFalloff( f_number );
+ break;
+ case INVERSE_TOK:
+ nextToken( );
+ warp->setInverse( true );
+ break;
+ case TURBULENCE_TOK:
+ if( !parsedFirst )
+ {
+ nextToken( );
+ warp->setWarpType( PMWarp::Turbulence );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setValueVector( vector );
+ parsedFirst = true;
+ }
+ else
+ {
+ if( !parseVector( vector ) )
+ return false;
+ warp->setTurbulence( vector );
+ }
+ break;
+ case OCTAVES_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ warp->setOctaves( i_number );
+ break;
+ case OMEGA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setOmega( f_number );
+ break;
+ case LAMBDA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setLambda( f_number );
+ break;
+ case CYLINDRICAL_TOK:
+ warp->setWarpType( PMWarp::Cylindrical );
+ mapping = true;
+ break;
+ case SPHERICAL_TOK:
+ warp->setWarpType( PMWarp::Spherical );
+ mapping = true;
+ break;
+ case TOROIDAL_TOK:
+ warp->setWarpType( PMWarp::Toroidal );
+ mapping = true;
+ break;
+ case PLANAR_TOK:
+ nextToken( );
+ warp->setWarpType( PMWarp::Planar );
+ if( parseVector( vector ) )
+ {
+ warp->setOrientation( vector );
+ if( parseToken( ',' ) )
+ {
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setDistExp( f_number );
+ }
+ }
+ parsedFirst = true;
+ break;
+ case DIST_EXP_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setDistExp( f_number );
+ break;
+ case MAJOR_RADIUS_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setMajorRadius( f_number );
+ break;
+ default:
+ break;
+ }
+
+ if( mapping)
+ {
+ nextToken( );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setOrientation( vector );
+ parsedFirst = true;
+ mapping = false;
+ }
+
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePigment( PMPigment* pigment, bool parseOuter )
+{
+ PMColor c;
+ PMSolidColor* sc;
+ int oldConsumed;
+
+ if( parseOuter )
+ {
+ if( !parseToken( PIGMENT_TOK, "pigment" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+ }
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMSymbol* s = getSymbol( id );
+ bool skipID = false;
+
+ if( s )
+ if( s->type( ) == PMSymbol::Value )
+ skipID = true;
+
+ if( !skipID )
+ {
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !pigment->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pigment );
+
+ switch( m_token )
+ {
+ case '<':
+ case COLOR_TOK:
+ case COLOUR_TOK:
+ case RGB_TOK:
+ case RGBT_TOK:
+ case RGBF_TOK:
+ case RGBFT_TOK:
+ case RED_TOK:
+ case GREEN_TOK:
+ case BLUE_TOK:
+ case TRANSMIT_TOK:
+ case FILTER_TOK:
+ case ID_TOK:
+ if( parseColor( c ) )
+ {
+ sc = new PMSolidColor( m_pPart );
+ sc->setColor( c );
+ if( !insertChild( sc, pigment ) )
+ {
+ delete sc;
+ sc = 0;
+ }
+ }
+ break;
+ case UV_MAPPING_TOK:
+ nextToken();
+ pigment->setUVMapping( parseBool( ) );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( parseOuter )
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseNormal( PMNormal* normal )
+{
+ double f_number;
+ int oldConsumed;
+
+ if( !parseToken( NORMAL_TOK, "normal" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !normal->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( normal );
+ switch( m_token )
+ {
+ case BUMP_SIZE_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ normal->enableBumpSize( true );
+ normal->setBumpSize( f_number );
+ break;
+ case ACCURACY_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ normal->setAccuracy( f_number );
+ break;
+ case UV_MAPPING_TOK:
+ nextToken( );
+ normal->setUVMapping( parseBool( ) );
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseTextureMap( PMTextureMap* textureMap )
+{
+ int oldConsumed;
+ double f_number1;
+ PMTexture* texture;
+ QValueList<double> mapValues;
+
+ if( !parseToken( TEXTURE_MAP_TOK, "texture_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !textureMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == '[' )
+ {
+ nextToken( );
+
+ if( !parseFloat( f_number1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ texture = new PMTexture( m_pPart );
+
+ parseTexture( texture, false );
+
+ if( !insertChild( texture, textureMap ) )
+ delete texture;
+
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ textureMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePigmentMap( PMPigmentMap* pigmentMap )
+{
+ int oldConsumed;
+ double f_number1;
+ PMPigment* pigment;
+ QValueList<double> mapValues;
+
+ if( !parseToken( PIGMENT_MAP_TOK, "pigment_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !pigmentMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == '[' )
+ {
+ nextToken( );
+ if( !parseFloat( f_number1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ pigment = new PMPigment( m_pPart );
+
+ parsePigment( pigment, false );
+ if( !insertChild( pigment, pigmentMap ) )
+ delete pigment;
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ pigmentMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseNormalMap( PMNormalMap* normalMap )
+{
+ int oldConsumed;
+ double f_number1;
+ PMNormal* normal;
+ QValueList<double> mapValues;
+
+ if( !parseToken( NORMAL_MAP_TOK, "normal_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !normalMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ // If we find '}' no need to search for an entry
+ if( m_token != '}' && parseToken( '[' ) )
+ {
+ if( !parseFloat( f_number1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ normal = new PMNormal( m_pPart );
+ if( !parseNormal( normal ) )
+ {
+ delete normal;
+ return false;
+ }
+ if( !insertChild( normal, normalMap ) )
+ delete normal;
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ normalMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBumpMap( PMBumpMap* bumpMap )
+{
+ int oldConsumed;
+ int i_number;
+ double f_number;
+
+ if( !parseToken( BUMP_MAP_TOK, "bump_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ // Parse the bitmap type
+ if( m_token != STRING_TOK )
+ {
+ switch( m_token )
+ {
+ case GIF_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapGif );
+ nextToken( );
+ break;
+ case TGA_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapTga );
+ nextToken( );
+ break;
+ case IFF_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapIff );
+ nextToken( );
+ break;
+ case PPM_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapPpm );
+ nextToken( );
+ break;
+ case PGM_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapPgm );
+ nextToken( );
+ break;
+ case PNG_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapPng );
+ nextToken( );
+ break;
+ case SYS_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapSys );
+ nextToken( );
+ break;
+ default:
+ printError( i18n( "Unknown bitmap type" ) );
+ return false;
+ }
+ }
+
+ // Parse the bitmap file name
+ if( m_token != STRING_TOK )
+ {
+ printError( i18n( "Expecting a file name." ) );
+ return false;
+ }
+ else
+ {
+ bumpMap->setBitmapFileName( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case ONCE_TOK:
+ nextToken( );
+ bumpMap->enableOnce( true );
+ break;
+ case MAP_TYPE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 0:
+ bumpMap->setMapType( PMBumpMap::MapPlanar );
+ break;
+ case 1:
+ bumpMap->setMapType( PMBumpMap::MapSpherical );
+ break;
+ case 2:
+ bumpMap->setMapType( PMBumpMap::MapCylindrical );
+ break;
+ case 5:
+ bumpMap->setMapType( PMBumpMap::MapToroidal );
+ break;
+ }
+ break;
+ case INTERPOLATE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 2:
+ bumpMap->setInterpolateType( PMBumpMap::InterpolateBilinear );
+ break;
+ case 4:
+ bumpMap->setInterpolateType( PMBumpMap::InterpolateNormalized );
+ break;
+ }
+ break;
+ case USE_INDEX_TOK:
+ nextToken( );
+ bumpMap->enableUseIndex( true );
+ break;
+ case BUMP_SIZE_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ bumpMap->setBumpSize( f_number );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseMaterialMap( PMMaterialMap* materialMap )
+{
+ int oldConsumed;
+ int i_number;
+
+ if( !parseToken( MATERIAL_MAP_TOK, "material_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ // Parse the bitmap type
+ if( m_token != STRING_TOK )
+ {
+ switch( m_token )
+ {
+ case GIF_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapGif );
+ nextToken( );
+ break;
+ case TGA_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapTga );
+ nextToken( );
+ break;
+ case IFF_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapIff );
+ nextToken( );
+ break;
+ case PPM_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapPpm );
+ nextToken( );
+ break;
+ case PGM_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapPgm );
+ nextToken( );
+ break;
+ case PNG_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapPng );
+ nextToken( );
+ break;
+ case SYS_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapSys );
+ nextToken( );
+ break;
+ default:
+ printError( i18n( "Unknown bitmap type" ) );
+ return false;
+ }
+ }
+
+ // Parse the bitmap file name
+ if( m_token != STRING_TOK )
+ {
+ printError( i18n( "Expecting a file name." ) );
+ return false;
+ }
+ else
+ {
+ materialMap->setBitmapFileName( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( materialMap );
+ switch( m_token )
+ {
+ case ONCE_TOK:
+ nextToken( );
+ materialMap->enableOnce( true );
+ break;
+ case MAP_TYPE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 0:
+ materialMap->setMapType( PMMaterialMap::MapPlanar );
+ break;
+ case 1:
+ materialMap->setMapType( PMMaterialMap::MapSpherical );
+ break;
+ case 2:
+ materialMap->setMapType( PMMaterialMap::MapCylindrical );
+ break;
+ case 5:
+ materialMap->setMapType( PMMaterialMap::MapToroidal );
+ break;
+ }
+ break;
+ case INTERPOLATE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 2:
+ materialMap->setInterpolateType( PMMaterialMap::InterpolateBilinear );
+ break;
+ case 4:
+ materialMap->setInterpolateType( PMMaterialMap::InterpolateNormalized );
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSlopeMap( PMSlopeMap* slopeMap )
+{
+ int oldConsumed;
+ double f_number1;
+ PMSlope* slope;
+ QValueList<double> mapValues;
+
+ if( !parseToken( SLOPE_MAP_TOK, "slope_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !slopeMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ // If we find '}' no need to search for an entry
+ if( m_token != '}' && parseToken( '[' ) )
+ {
+ if( !parseFloat( f_number1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ slope = new PMSlope( m_pPart );
+ if( !parseSlope( slope ) )
+ {
+ delete slope;
+ return false;
+ }
+ if( !insertChild( slope, slopeMap ) )
+ delete slope;
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ slopeMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseDensityMap( PMDensityMap* densityMap )
+{
+ int oldConsumed;
+ double f_number1;
+ PMDensity* density;
+ QValueList<double> mapValues;
+
+ if( !parseToken( DENSITY_MAP_TOK, "density_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !densityMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ // If we find '}' no need to search for an entry
+ if( m_token != '}' && parseToken( '[' ) )
+ {
+ if( !parseFloat( f_number1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ density = new PMDensity( m_pPart );
+ if( !parseDensity( density ) )
+ {
+ delete density;
+ return false;
+ }
+ if( !insertChild( density, densityMap ) )
+ delete density;
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ densityMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseImageMap( PMImageMap* imageMap )
+{
+ int oldConsumed;
+ int i_number;
+ double f_number;
+ PMPaletteValue newPaletteValue;
+ QValueList<PMPaletteValue> l_valuesFilter;
+ QValueList<PMPaletteValue> l_valuesTransmit;
+
+ if( !parseToken( IMAGE_MAP_TOK, "image_map" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ // Parse the bitmap type
+ if( m_token != STRING_TOK )
+ {
+ switch( m_token )
+ {
+ case GIF_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapGif );
+ nextToken( );
+ break;
+ case TGA_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapTga );
+ nextToken( );
+ break;
+ case IFF_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapIff );
+ nextToken( );
+ break;
+ case PPM_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapPpm );
+ nextToken( );
+ break;
+ case PGM_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapPgm );
+ nextToken( );
+ break;
+ case PNG_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapPng );
+ nextToken( );
+ break;
+ case SYS_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapSys );
+ nextToken( );
+ break;
+ default:
+ printError( i18n( "Unknown bitmap type" ) );
+ return false;
+ }
+ }
+
+ // Parse the bitmap file name
+ if( m_token != STRING_TOK )
+ {
+ printError( i18n( "Expecting a file name." ) );
+ return false;
+ }
+ else
+ {
+ imageMap->setBitmapFileName( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case TRANSMIT_TOK:
+ nextToken( );
+ if( m_token == ALL_TOK )
+ {
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ imageMap->enableTransmitAll( true );
+ imageMap->setTransmitAll( f_number );
+ }
+ else
+ {
+ if( !parseInt( i_number ) )
+ return false;
+ parseToken( ',' );
+ if( !parseFloat( f_number ) )
+ return false;
+ newPaletteValue.setIndex( i_number );
+ newPaletteValue.setValue( f_number );
+ l_valuesTransmit.append( newPaletteValue );
+ }
+ break;
+ case FILTER_TOK:
+ nextToken( );
+ if( m_token == ALL_TOK )
+ {
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ imageMap->enableFilterAll( true );
+ imageMap->setFilterAll( f_number );
+ }
+ else
+ {
+ if( !parseInt( i_number ) )
+ return false;
+ parseToken( ',' );
+ if( !parseFloat( f_number ) )
+ return false;
+ newPaletteValue.setIndex( i_number );
+ newPaletteValue.setValue( f_number );
+ l_valuesFilter.append( newPaletteValue );
+ }
+ break;
+ case ONCE_TOK:
+ nextToken( );
+ imageMap->enableOnce( true );
+ break;
+ case MAP_TYPE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 0:
+ imageMap->setMapType( PMImageMap::MapPlanar );
+ break;
+ case 1:
+ imageMap->setMapType( PMImageMap::MapSpherical );
+ break;
+ case 2:
+ imageMap->setMapType( PMImageMap::MapCylindrical );
+ break;
+ case 5:
+ imageMap->setMapType( PMImageMap::MapToroidal );
+ break;
+ }
+ break;
+ case INTERPOLATE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 2:
+ imageMap->setInterpolateType( PMImageMap::InterpolateBilinear );
+ break;
+ case 4:
+ imageMap->setInterpolateType( PMImageMap::InterpolateNormalized );
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+ imageMap->setFilters( l_valuesFilter );
+ imageMap->setTransmits( l_valuesTransmit );
+
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePigmentList( PMPigmentList* pigmentList, int expectedItems )
+{
+ int oldConsumed;
+ PMPigment* pigment;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ pigment = new PMPigment( m_pPart );
+ if( !parsePigment( pigment ) )
+ {
+ delete pigment;
+ return false;
+ }
+ if( !insertChild( pigment, pigmentList ) )
+ delete pigment;
+
+ // In the last entry don't expect a comma
+ if( expectedItems-- )
+ if( m_token == ',' )
+ nextToken( );
+ }
+ while( oldConsumed != m_consumedTokens && expectedItems );
+
+ return true;
+}
+
+bool PMPovrayParser::parseColorList( PMColorList* colorList, int expectedItems )
+{
+ int oldConsumed;
+ PMColor color;
+ PMSolidColor* sc;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ if( !parseColor( color ) )
+ {
+ return false;
+ }
+ sc = new PMSolidColor( m_pPart );
+ sc->setColor( color );
+ if( !insertChild( sc, colorList ) )
+ delete sc;
+
+ // In the last entry don't expect a comma
+ if( expectedItems-- )
+ if( m_token == ',' )
+ nextToken( );
+ }
+ while( oldConsumed != m_consumedTokens && expectedItems );
+
+ return true;
+}
+
+bool PMPovrayParser::parseNormalList( PMNormalList* normalList, int expectedItems )
+{
+ int oldConsumed;
+ PMNormal* normal;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ normal = new PMNormal( m_pPart );
+ if( !parseNormal( normal ) )
+ {
+ delete normal;
+ return false;
+ }
+ if( !insertChild( normal, normalList ) )
+ delete normal;
+
+ // In the last entry don't expect a comma
+ if( expectedItems-- )
+ if( m_token == ',' )
+ nextToken( );
+ }
+ while( oldConsumed != m_consumedTokens && expectedItems );
+
+ return true;
+}
+
+bool PMPovrayParser::parseTextureList( PMTextureList* textureList, int expectedItems )
+{
+ int oldConsumed;
+ PMTexture* texture;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ texture = new PMTexture( m_pPart );
+ if( !parseTexture( texture ) )
+ {
+ delete texture;
+ return false;
+ }
+ if( !insertChild( texture, textureList ) )
+ delete texture;
+
+ // In the last entry don't expect a comma
+ if( expectedItems-- )
+ if( m_token == ',' )
+ nextToken( );
+ }
+ while( oldConsumed != m_consumedTokens && expectedItems );
+
+ return true;
+}
+
+bool PMPovrayParser::parseDensityList( PMDensityList* densityList, int expectedItems )
+{
+ int oldConsumed;
+ PMDensity* density;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ density = new PMDensity( m_pPart );
+ if( !parseDensity( density ) )
+ {
+ delete density;
+ return false;
+ }
+ if( !insertChild( density, densityList ) )
+ delete density;
+
+ // In the last entry don't expect a comma
+ if( expectedItems-- )
+ if( m_token == ',' )
+ nextToken( );
+ }
+ while( oldConsumed != m_consumedTokens && expectedItems );
+
+ return true;
+}
+
+bool PMPovrayParser::parseColorMap( PMColorMap* colorMap )
+{
+ int oldConsumed;
+ double f_number1, f_number2;
+ PMColor color1, color2;
+ PMSolidColor* solidColor;
+ PMSolidColor* lastColor = 0;
+ QValueList<double> mapValues;
+ bool newEntry;
+ bool twoColors;
+
+ if( m_token != COLOR_MAP_TOK && m_token != COLOUR_MAP_TOK )
+ return false;
+ nextToken( );
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !colorMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == '[' )
+ {
+ nextToken( );
+ if( !parseFloat( f_number1 ) )
+ return false;
+
+ twoColors = false;
+ if( m_token == ',' )
+ {
+ twoColors = true;
+ nextToken( );
+ }
+ else if( ( m_token == INTEGER_TOK ) || ( m_token == FLOAT_TOK ) )
+ twoColors = true;
+
+ if( twoColors )
+ {
+ // Two colors in the same entry
+
+ if( parseFloat( f_number2 ) )
+ {
+ if( !parseColor( color1 ) )
+ return false;
+ if( !parseColor( color2 ) )
+ return false;
+ // If the first value doesn't pick up from the previous,
+ // or the color is different...
+ newEntry = true;
+ if( lastColor && !mapValues.isEmpty( ) )
+ if( ( mapValues.last( ) == f_number1 ) &&
+ ( lastColor->color( ) == color1 ) )
+ newEntry = false;
+
+ if( newEntry )
+ {
+ // ... add the two colors in two different entries ...
+ mapValues.append( f_number1 );
+ solidColor = new PMSolidColor( m_pPart );
+ solidColor->setColor( color1 );
+ if( !insertChild( solidColor, colorMap ) )
+ delete solidColor;
+ else
+ lastColor = solidColor;
+
+ mapValues.append( f_number2 );
+ solidColor = new PMSolidColor( m_pPart );
+ solidColor->setColor( color2 );
+ if( !insertChild( solidColor, colorMap ) )
+ delete solidColor;
+ else
+ lastColor = solidColor;
+ }
+ else
+ {
+ // ... else just add the last value and color
+ mapValues.append( f_number2 );
+ solidColor = new PMSolidColor( m_pPart );
+ solidColor->setColor( color2 );
+ if( !insertChild( solidColor, colorMap ) )
+ delete solidColor;
+ else
+ lastColor = solidColor;
+ }
+ }
+ }
+ else
+ {
+ // Only one color in the entry
+ if( !parseColor( color1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ solidColor = new PMSolidColor( m_pPart );
+ solidColor->setColor( color1 );
+ if( !insertChild( solidColor, colorMap ) )
+ delete solidColor;
+ else
+ lastColor = solidColor;
+ }
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ colorMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSkySphere( PMSkySphere* sky )
+{
+ int oldConsumed;
+
+ if( !parseToken( SKY_SPHERE_TOK, "sky_sphere" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !sky->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( sky );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseRainbow( PMRainbow* rainbow )
+{
+ PMVector vector;
+ double f_number;
+ int oldConsumed;
+
+ if( !parseToken( RAINBOW_TOK, "rainbow" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !rainbow->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( rainbow );
+ switch( m_token )
+ {
+ case DIRECTION_TOK:
+ nextToken( );
+ if( parseVector( vector ) )
+ {
+ rainbow->enableDirection( true );
+ rainbow->setDirection( vector );
+ }
+ break;
+ case ANGLE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableAngle( true );
+ rainbow->setAngle( f_number );
+ }
+ break;
+ case WIDTH_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableWidth( true );
+ rainbow->setWidth( f_number );
+ }
+ break;
+ case DISTANCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableDistance( true );
+ rainbow->setDistance( f_number );
+ }
+ break;
+ case JITTER_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableJitter( true );
+ rainbow->setJitter( f_number );
+ }
+ break;
+ case UP_TOK:
+ nextToken( );
+ if( parseVector( vector ) )
+ {
+ rainbow->enableUp( true );
+ rainbow->setUp( vector );
+ }
+ break;
+ case ARC_ANGLE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableArcAngle( true );
+ rainbow->setArcAngle( f_number );
+ }
+ break;
+ case FALLOFF_ANGLE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableFalloffAngle( true );
+ rainbow->setFalloffAngle( f_number );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseFog( PMFog* fog )
+{
+ PMColor color;
+ PMVector vector;
+ double f_number;
+ int i_number;
+ int fog_type;
+ int oldConsumed;
+
+ if( !parseToken( FOG_TOK, "fog" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !fog->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ fog_type = 1;
+ if( parseToken( FOG_TYPE_TOK, "fog_type" ) )
+ {
+ if( !parseInt( i_number ) )
+ return false;
+ fog_type = i_number;
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case DISTANCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ fog->setDistance( f_number );
+ break;
+ case '<':
+ case COLOR_TOK:
+ case COLOUR_TOK:
+ case RGB_TOK:
+ case RGBT_TOK:
+ case RGBF_TOK:
+ case RGBFT_TOK:
+ case RED_TOK:
+ case GREEN_TOK:
+ case BLUE_TOK:
+ case TRANSMIT_TOK:
+ case FILTER_TOK:
+ case ID_TOK:
+ if( parseColor( color ) )
+ fog->setColor( color );
+ break;
+ case TURBULENCE_TOK:
+ nextToken( );
+ fog->enableTurbulence( true );
+ if( !parseVector( vector ) )
+ return false;
+ fog->setValueVector( vector );
+ break;
+ case OCTAVES_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ fog->setOctaves( i_number );
+ break;
+ case OMEGA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ fog->setOmega( f_number );
+ break;
+ case LAMBDA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ fog->setLambda( f_number );
+ break;
+ case TURB_DEPTH_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ fog->setDepth( f_number );
+ break;
+ case FOG_OFFSET_TOK:
+ nextToken( );
+ fog_type = 2;
+ if( parseFloat( f_number ) )
+ fog->setFogOffset( f_number );
+ break;
+ case FOG_ALT_TOK:
+ nextToken( );
+ fog_type = 2;
+ if( parseFloat( f_number ) )
+ fog->setFogAlt( f_number );
+ break;
+ case UP_TOK:
+ nextToken( );
+ fog_type = 2;
+ if( !parseVector( vector ) )
+ return false;
+ fog->setUp( vector );
+ break;
+ default:
+ break;
+ }
+ // Only parseChildObjects() if the token is not turbulence, because this
+ // function parses that token.
+ if( m_token != TURBULENCE_TOK )
+ parseChildObjects( fog );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ fog->setFogType( fog_type );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseMedia( PMMedia* media )
+{
+ PMColor color;
+ double f_number;
+ int i_number;
+ int oldConsumed, oldConsumed1;
+
+ if( !parseToken( MEDIA_TOK, "media" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !media->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( media );
+ switch( m_token )
+ {
+ case METHOD_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ media->setMethod( i_number );
+ break;
+ case INTERVALS_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ media->setIntervals( i_number );
+ break;
+ case SAMPLES_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ media->setSamplesMin( i_number );
+ parseToken( ',' );
+ if( parseInt( i_number ) )
+ media->setSamplesMax( i_number );
+ break;
+ case CONFIDENCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ media->setConfidence( f_number );
+ break;
+ case VARIANCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ media->setVariance( f_number );
+ break;
+ case RATIO_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ media->setRatio( f_number );
+ break;
+ case AA_LEVEL_TOK:
+ nextToken( );
+ if ( parseInt( i_number ) )
+ media->setAALevel( i_number );
+ break;
+ case AA_THRESHOLD_TOK:
+ nextToken( );
+ if ( parseFloat( f_number ) )
+ media->setAAThreshold( f_number );
+ break;
+ case ABSORPTION_TOK:
+ nextToken( );
+ if( parseColor( color ) )
+ {
+ media->enableAbsorption( true );
+ media->setAbsorption( color );
+ }
+ break;
+ case EMISSION_TOK:
+ nextToken( );
+ media->enableEmission( true );
+ if( parseColor( color ) )
+ media->setEmission( color );
+ break;
+ case SCATTERING_TOK:
+ nextToken( );
+ parseToken( '{' );
+ media->enableScattering( true );
+ if( parseInt( i_number ) )
+ media->setScatteringType( i_number );
+ parseToken( ',' );
+ if( parseColor( color ) )
+ media->setScatteringColor( color );
+ do
+ {
+ oldConsumed1 = m_consumedTokens;
+ switch( m_token )
+ {
+ case ECCENTRICITY_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ media->setScatteringEccentricity( f_number );
+ break;
+ case EXTINCTION_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ media->setScatteringExtinction( f_number );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed1 != m_consumedTokens );
+ parseToken( '}' );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseDensity( PMDensity* density )
+{
+ int oldConsumed;
+
+ if( !parseToken( DENSITY_TOK, "density" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !density->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( density );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseInterior( PMInterior* interior )
+{
+ double f_number;
+ int i_number;
+ int oldConsumed;
+
+ if( !parseToken( INTERIOR_TOK, "interior" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !interior->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( interior );
+ switch( m_token )
+ {
+ case IOR_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ interior->enableIor( true );
+ interior->setIor( f_number );
+ }
+ break;
+ case CAUSTICS_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ interior->enableCaustics( true );
+ interior->setCaustics( f_number );
+ }
+ break;
+ case DISPERSION_TOK:
+ nextToken( );
+ if ( parseFloat( f_number ) )
+ {
+ interior->enableDispersion( true );
+ interior->setDispersion( f_number );
+ }
+ break;
+ case DISPERSION_SAMPLES_TOK:
+ nextToken( );
+ if ( parseInt( i_number ) )
+ {
+ interior->enableDispSamples( true );
+ interior->setDispSamples( i_number );
+ }
+ break;
+ case FADE_DISTANCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ interior->enableFadeDistance( true );
+ interior->setFadeDistance( f_number );
+ }
+ break;
+ case FADE_POWER_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ interior->enableFadePower( true );
+ interior->setFadePower( f_number );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseMaterial( PMMaterial* material )
+{
+ int oldConsumed;
+
+ if( !parseToken( MATERIAL_TOK, "material" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !material->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( material );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSlope( PMSlope* slope )
+{
+ double f_number;
+
+ if( !parseToken( '<' ) )
+ return false;
+ if( !parseFloat( f_number ) )
+ return false;
+ slope->setHeight( f_number );
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( f_number ) )
+ return false;
+ slope->setSlope( f_number );
+ if( !parseToken( '>' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseGlobalSettings( PMGlobalSettings* globalsettings )
+{
+ PMColor color;
+ double f_number;
+ int i_number;
+ int oldConsumed;
+
+ // Initial global settings tokens
+ if( !parseToken( GLOBAL_SETTINGS_TOK, "global_settings" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ // Parse global settings tokens
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( globalsettings );
+
+ switch( m_token )
+ {
+ case ADC_BAILOUT_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ globalsettings->setAdcBailout( f_number );
+ break;
+ case AMBIENT_LIGHT_TOK:
+ nextToken( );
+ if( parseColor( color ) )
+ globalsettings->setAmbientLight( color );
+ break;
+ case ASSUMED_GAMMA_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ globalsettings->setAssumedGamma( f_number );
+ break;
+ case HF_GRAY_16_TOK:
+ nextToken( );
+ switch( m_token )
+ {
+ case ON_TOK:
+ globalsettings->setHfGray16( true );
+ nextToken( );
+ break;
+ case OFF_TOK:
+ globalsettings->setHfGray16( false );
+ nextToken( );
+ break;
+ default:
+ break;
+ }
+ break;
+ case IRID_WAVELENGTH_TOK:
+ nextToken( );
+ if( parseColor( color ) )
+ globalsettings->setIridWaveLength( color );
+ break;
+ case MAX_INTERSECTIONS_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ globalsettings->setMaxIntersections( i_number );
+ break;
+ case MAX_TRACE_LEVEL_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ globalsettings->setMaxTraceLevel( i_number );
+ break;
+ case NUMBER_OF_WAVES_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ globalsettings->setNumberWaves( i_number );
+ break;
+ case NOISE_GENERATOR_TOK:
+ nextToken( );
+ if ( parseInt( i_number ) )
+ globalsettings->setNoiseGenerator(
+ ( PMGlobalSettings::PMNoiseType ) ( i_number - 1 ) );
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseFinish( PMFinish* finish )
+{
+ PMColor color;
+ double f_number;
+ int oldConsumed, oldConsumed1;
+
+ // Initial finish tokens "finish {"
+ if( !parseToken( FINISH_TOK, "finish" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ // Parse a possible declare link identifier
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !finish->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ // Parse finish tokens
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case AMBIENT_TOK:
+ nextToken( );
+ finish->enableAmbient( true );
+ if( parseColor( color ) )
+ finish->setAmbientColor( color );
+ break;
+ case DIFFUSE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableDiffuse( true );
+ finish->setDiffuse( f_number );
+ }
+ break;
+ case BRILLIANCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableBrilliance( true );
+ finish->setBrilliance( f_number );
+ }
+ break;
+ case PHONG_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enablePhong( true );
+ finish->setPhong( f_number );
+ }
+ break;
+ case PHONG_SIZE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enablePhongSize( true );
+ finish->setPhongSize( f_number );
+ }
+ break;
+ case METALLIC_TOK:
+ nextToken( );
+ finish->enableMetallic( true );
+ finish->setMetallic( 1.0 );
+ if( parseFloat( f_number, true ) )
+ finish->setMetallic( f_number );
+ break;
+ case SPECULAR_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableSpecular( true );
+ finish->setSpecular( f_number );
+ }
+ break;
+ case ROUGHNESS_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableRoughness( true );
+ finish->setRoughness( f_number );
+ }
+ break;
+ case CRAND_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableCrand( true );
+ finish->setCrand( f_number );
+ }
+ break;
+ case CONSERVE_ENERGY_TOK:
+ nextToken( );
+ finish->setConserveEnergy( parseBool( ) );
+ break;
+ case REFLECTION_TOK:
+ nextToken( );
+ finish->enableReflection( true );
+ if( !parseToken( '{' ) )
+ {
+ printError( i18n( "Using Old Reflection Syntax" ) );
+ if( parseColor( color ) )
+ finish->setReflectionColor( color );
+ }
+ else if( parseColor( color ) )
+ {
+ if( parseToken( ',' ) )
+ {
+ finish->enableReflectionMin( true );
+ finish->setReflectionMinColor( color );
+ if( parseColor( color ) )
+ finish->setReflectionColor( color );
+ else
+ return false;
+ }
+ else
+ finish->setReflectionColor( color );
+
+ do
+ {
+ oldConsumed1 = m_consumedTokens;
+ switch( m_token )
+ {
+ case FRESNEL_TOK:
+ nextToken( );
+ finish->setReflectionFresnel( parseBool( ) );
+ break;
+ case FALLOFF_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableRefFalloff( true );
+ finish->setReflectionFalloff( f_number );
+ }
+ break;
+ case EXPONENT_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableRefExponent( true );
+ finish->setReflectionExponent( f_number );
+ }
+ break;
+ case METALLIC_TOK:
+ nextToken( );
+ if ( parseFloat( f_number ) )
+ {
+ finish->enableRefMetallic( true );
+ finish->setReflectionMetallic( f_number );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed1 != m_consumedTokens );
+ parseToken( '}' );
+ }
+ else
+ return false;
+ break;
+ case REFLECTION_EXPONENT_TOK:
+ nextToken( );
+ if ( parseFloat( f_number ) )
+ {
+ finish->enableRefExponent( true );
+ finish->setReflectionExponent( f_number );
+ }
+ break;
+ case IRID_TOK:
+ nextToken( );
+ parseToken( '{' );
+ finish->setIrid( true );
+ if( parseFloat( f_number ) )
+ finish->setIridAmount( f_number );
+ do
+ {
+ oldConsumed1 = m_consumedTokens;
+ switch( m_token )
+ {
+ case THICKNESS_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ finish->setIridThickness( f_number );
+ break;
+ case TURBULENCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ finish->setIridTurbulence( f_number );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed1 != m_consumedTokens );
+ parseToken( '}' );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseDeclare( PMDeclare* decl )
+{
+ PMObject* child = 0;
+ PMTexture* texture = 0;
+ bool error = false;
+
+ switch( m_token )
+ {
+ case OBJECT_TOK:
+ error = !parseObject( decl );
+ break;
+ // finite solid
+ case BLOB_TOK:
+ child = new PMBlob( m_pPart );
+ error = !parseBlob( ( PMBlob* ) child );
+ break;
+ case BOX_TOK:
+ child = new PMBox( m_pPart );
+ error = !parseBox( ( PMBox* ) child );
+ break;
+ case CONE_TOK:
+ child = new PMCone( m_pPart );
+ error = !parseCone( ( PMCone* ) child );
+ break;
+ case CYLINDER_TOK:
+ child = new PMCylinder( m_pPart );
+ error = !parseCylinder( ( PMCylinder* ) child );
+ break;
+ case HEIGHT_FIELD_TOK:
+ child = new PMHeightField( m_pPart );
+ error = !parseHeightField( ( PMHeightField* ) child );
+ break;
+ case JULIA_FRACTAL_TOK:
+ child = new PMJuliaFractal( m_pPart );
+ error = !parseJuliaFractal( ( PMJuliaFractal* ) child );
+ break;
+ case LATHE_TOK:
+ child = new PMLathe( m_pPart );
+ error = !parseLathe( ( PMLathe* ) child );
+ break;
+ case PRISM_TOK:
+ child = new PMPrism( m_pPart );
+ error = !parsePrism( ( PMPrism* ) child );
+ break;
+ case SPHERE_TOK:
+ child = new PMSphere( m_pPart );
+ error = !parseSphere( ( PMSphere* ) child );
+ break;
+ case SUPERELLIPSOID_TOK:
+ child = new PMSuperquadricEllipsoid( m_pPart );
+ error = !parseSqe( ( PMSuperquadricEllipsoid* ) child );
+ break;
+ case SOR_TOK:
+ child = new PMSurfaceOfRevolution( m_pPart );
+ error = !parseSor( ( PMSurfaceOfRevolution* ) child );
+ break;
+ case TEXT_TOK:
+ child = new PMText( m_pPart );
+ error = !parseText( ( PMText* ) child );
+ break;
+ case TORUS_TOK:
+ child = new PMTorus( m_pPart );
+ error = !parseTorus( ( PMTorus* ) child );
+ break;
+ // finite patch
+ case BICUBIC_PATCH_TOK:
+ child = new PMBicubicPatch( m_pPart );
+ error = !parseBicubicPatch( ( PMBicubicPatch* ) child );
+ break;
+ case DISC_TOK:
+ child = new PMDisc( m_pPart );
+ error = !parseDisc( ( PMDisc* ) child );
+ break;
+ case TRIANGLE_TOK:
+ case SMOOTH_TRIANGLE_TOK:
+ child = new PMTriangle( m_pPart );
+ error = !parseTriangle( ( PMTriangle* ) child );
+ break;
+ // infinite solid
+ case PLANE_TOK:
+ child = new PMPlane( m_pPart );
+ error = !parsePlane( ( PMPlane* ) child );
+ break;
+ case QUADRIC_TOK:
+ case CUBIC_TOK:
+ case QUARTIC_TOK:
+ case POLY_TOK:
+ child = new PMPolynom( m_pPart );
+ error = !parsePolynom( ( PMPolynom* ) child );
+ break;
+ // csg
+ case UNION_TOK:
+ case DIFFERENCE_TOK:
+ case INTERSECTION_TOK:
+ case MERGE_TOK:
+ child = new PMCSG( m_pPart );
+ error = !parseCSG( ( PMCSG* ) child );
+ break;
+ // textures
+ case TEXTURE_TOK:
+ while( m_token == TEXTURE_TOK )
+ {
+ texture = new PMTexture( m_pPart );
+ if( !parseTexture( texture ) )
+ error = true;
+ if( !insertChild( texture, decl ) )
+ {
+ delete texture;
+ texture = 0;
+ }
+ }
+ break;
+ case PIGMENT_TOK:
+ child = new PMPigment( m_pPart );
+ error = !parsePigment( ( PMPigment* ) child );
+ break;
+ case NORMAL_TOK:
+ child = new PMNormal( m_pPart );
+ error = !parseNormal( ( PMNormal* ) child );
+ break;
+ case FINISH_TOK:
+ child = new PMFinish( m_pPart );
+ error = !parseFinish( ( PMFinish* ) child );
+ break;
+ case TEXTURE_MAP_TOK:
+ child = new PMTextureMap( m_pPart );
+ error = !parseTextureMap( ( PMTextureMap* ) child );
+ break;
+ case PIGMENT_MAP_TOK:
+ child = new PMPigmentMap( m_pPart );
+ error = !parsePigmentMap( ( PMPigmentMap* ) child );
+ break;
+ case COLOR_MAP_TOK:
+ case COLOUR_MAP_TOK:
+ child = new PMColorMap( m_pPart );
+ error = !parseColorMap( ( PMColorMap* ) child );
+ break;
+ case NORMAL_MAP_TOK:
+ child = new PMNormalMap( m_pPart );
+ error = !parseNormalMap( ( PMNormalMap* ) child );
+ break;
+ case SLOPE_MAP_TOK:
+ child = new PMSlopeMap( m_pPart );
+ error = !parseSlopeMap( ( PMSlopeMap* ) child );
+ break;
+ case DENSITY_MAP_TOK:
+ child = new PMDensityMap( m_pPart );
+ error = !parseDensityMap( ( PMDensityMap* ) child );
+ break;
+ case INTERIOR_TOK:
+ child = new PMInterior( m_pPart );
+ error = !parseInterior( ( PMInterior* ) child );
+ break;
+ case MEDIA_TOK:
+ child = new PMMedia( m_pPart );
+ error = !parseMedia( ( PMMedia* ) child );
+ break;
+ case DENSITY_TOK:
+ child = new PMDensity( m_pPart );
+ error = !parseDensity( ( PMDensity* ) child );
+ break;
+ case MATERIAL_TOK:
+ child = new PMMaterial( m_pPart );
+ error = !parseMaterial( ( PMMaterial* ) child );
+ break;
+ case SKY_SPHERE_TOK:
+ child = new PMSkySphere( m_pPart );
+ error = !parseSkySphere( ( PMSkySphere* ) child );
+ break;
+ case RAINBOW_TOK:
+ child = new PMRainbow( m_pPart );
+ error = !parseRainbow( ( PMRainbow* ) child );
+ break;
+ case FOG_TOK:
+ child = new PMFog( m_pPart );
+ error = !parseFog( ( PMFog* ) child );
+ break;
+ // misc
+ case LIGHT_SOURCE_TOK:
+ child = new PMLight( m_pPart );
+ error = !parseLight( ( PMLight* ) child );
+ break;
+ case ISOSURFACE_TOK:
+ child = new PMIsoSurface( m_pPart );
+ error = !parseIsoSurface( ( PMIsoSurface* ) child );
+ break;
+ case PHOTONS_TOK:
+ child = new PMPhotons( m_pPart );
+ error = !parsePhotons( ( PMPhotons* ) child );
+ break;
+ case LIGHT_GROUP_TOK:
+ child = new PMLightGroup( m_pPart );
+ error = !parseLightGroup( ( PMLightGroup* ) child );
+ break;
+ case INTERIOR_TEXTURE_TOK:
+ child = new PMInteriorTexture( m_pPart );
+ error = !parseInteriorTexture( ( PMInteriorTexture* ) child );
+ break;
+ case SPHERE_SWEEP_TOK:
+ child = new PMSphereSweep( m_pPart );
+ error = !parseSphereSweep( ( PMSphereSweep* ) child );
+ break;
+ case MESH_TOK:
+ child = new PMMesh( m_pPart );
+ error = !parseMesh( ( PMMesh* ) child );
+ break;
+ }
+
+ if( child )
+ {
+ if( !insertChild( child, decl ) )
+ {
+ delete child;
+ child = 0;
+ }
+ }
+ return !error;
+}
+
+bool PMPovrayParser::parseObject( PMCompositeObject* parent )
+{
+ PMObject* child;
+ bool error = false;
+ if( !parseToken( OBJECT_TOK, "object" ) )
+ return false;
+
+ if( parseToken( '{' ) )
+ {
+ switch( m_token )
+ {
+ case ID_TOK:
+ child = new PMObjectLink( m_pPart );
+ error = !parseObjectLink( ( PMObjectLink* ) child );
+ if( !insertChild( child, parent ) )
+ delete child;
+ break;
+ default:
+ {
+ PMObject* lastChild = 0;
+ if( parent )
+ lastChild = parent->lastChild( );
+ else
+ lastChild = m_pResultList->last( );
+
+ error = !parseChildObjects( parent, 1 );
+ if( !error )
+ {
+ PMObject* newLast = 0;
+ if( parent )
+ newLast = parent->lastChild( );
+ else
+ newLast = m_pResultList->last( );
+
+ if( newLast && ( newLast != lastChild ) &&
+ newLast->isA( "CompositeObject" ) )
+ {
+ // one child was parsed
+ // append all following objects
+ error = !parseChildObjects( ( PMCompositeObject* ) newLast );
+ }
+ else
+ {
+ printError( i18n( "One graphical object expected" ) );
+ error = true;
+ }
+ }
+ break;
+ }
+ }
+ if( !parseToken( '}' ))
+ error = true;
+ }
+ else
+ error = true;
+ return !error;
+}
+
+bool PMPovrayParser::parseObjectLink( PMObjectLink* link )
+{
+ int oldConsumed;
+
+ if( m_token != ID_TOK )
+ {
+ printExpected( "identifier", m_pScanner->sValue( ) );
+ return false;
+ }
+
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !link->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( link );
+ parseObjectModifiers( link );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ return true;
+}
+
+bool PMPovrayParser::parseIsoSurface( PMIsoSurface* iso )
+{
+ PMVector vector;
+ double f;
+ int i;
+ int oldConsumed;
+
+ if( !parseToken( ISOSURFACE_TOK, "isosurface" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( iso );
+ parseObjectModifiers( iso );
+
+ switch( m_token )
+ {
+ case FUNCTION_TOK:
+ nextToken( );
+ if( m_token != '{' )
+ {
+ printExpected( '{', m_pScanner->sValue( ) );
+ return false;
+ }
+
+ m_pScanner->scanFunction( );
+ nextToken( );
+ if( m_token != FUNCTION_TOK )
+ return false;
+ iso->setFunction( QString( m_pScanner->sValue( ) ).simplifyWhiteSpace( ) );
+
+ nextToken( );
+ parseToken( '}' );
+
+ break;
+ case CONTAINED_BY_TOK:
+ nextToken( );
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == BOX_TOK )
+ {
+ iso->setContainedBy( PMIsoSurface::Box );
+ nextToken( );
+ parseToken( '{' );
+ if( parseVector( vector ) )
+ iso->setCorner1( vector );
+ parseToken( ',' );
+ if( parseVector( vector ) )
+ iso->setCorner2( vector );
+ if( !parseToken( '}' ) )
+ return false;
+ }
+ else if( m_token == SPHERE_TOK )
+ {
+ iso->setContainedBy( PMIsoSurface::Sphere );
+ nextToken( );
+ parseToken( '{' );
+ if( parseVector( vector ) )
+ iso->setCenter( vector );
+ parseToken( ',' );
+ if( parseFloat( f ) )
+ iso->setRadius( f );
+ if( !parseToken( '}' ) )
+ return false;
+ }
+ else
+ {
+ printUnexpected( m_pScanner->sValue( ) );
+ return false;
+ }
+
+ if( !parseToken( '}' ) )
+ return false;
+ break;
+ case THRESHOLD_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ iso->setThreshold( f );
+ break;
+ case ACCURACY_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ iso->setAccuracy( f );
+ break;
+ case MAX_GRADIENT_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ iso->setMaxGradient( f );
+ break;
+ case EVALUATE_TOK:
+ nextToken( );
+ iso->setEvaluate( true );
+ if( parseFloat( f ) )
+ {
+ iso->setEvaluateValue( 0, f );
+ if( parseToken( ',' ) && parseFloat( f ) )
+ {
+ iso->setEvaluateValue( 1, f );
+ if( parseToken( ',' ) && parseFloat( f ) )
+ iso->setEvaluateValue( 2, f );
+ }
+ }
+ break;
+ case OPEN_TOK:
+ nextToken( );
+ iso->setOpen( true );
+ break;
+ case MAX_TRACE_TOK:
+ nextToken( );
+ if( parseInt( i ) )
+ iso->setMaxTrace( i );
+ break;
+ case ALL_INTERSECTIONS_TOK:
+ nextToken( );
+ iso->setAllIntersections( true );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseRadiosity( PMRadiosity* rad )
+{
+ double f;
+ int i;
+ int oldConsumed;
+
+
+ if( !parseToken( RADIOSITY_TOK, "radiosity" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case ADC_BAILOUT_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setAdcBailout( f );
+ break;
+ case ALWAYS_SAMPLE_TOK:
+ nextToken( );
+ rad->setAlwaysSample( parseBool( ) );
+ break;
+ case BRIGHTNESS_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setBrightness( f );
+ break;
+ case COUNT_TOK:
+ nextToken( );
+ if( parseInt( i ) )
+ rad->setCount( i );
+ break;
+ case ERROR_BOUND_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setErrorBound( f );
+ break;
+ case GRAY_THRESHOLD_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setGrayThreshold( f );
+ break;
+ case LOW_ERROR_FACTOR_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setLowErrorFactor( f );
+ break;
+ case MAX_SAMPLE_TOK:
+ nextToken( );
+ if ( parseFloat( f ) )
+ rad->setMaxSample( f );
+ break;
+ case MEDIA_TOK:
+ nextToken( );
+ rad->setMedia( parseBool( ) );
+ break;
+ case MINIMUM_REUSE_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setMinimumReuse( f );
+ break;
+ case NEAREST_COUNT_TOK:
+ nextToken( );
+ if( parseInt( i ) )
+ rad->setNearestCount( i );
+ break;
+ case NORMAL_TOK:
+ nextToken( );
+ rad->setNormal( parseBool( ) );
+ break;
+ case PRETRACE_START_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setPretraceStart( f );
+ break;
+ case PRETRACE_END_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setPretraceEnd( f );
+ break;
+ case RECURSION_LIMIT_TOK:
+ nextToken( );
+ if( parseInt( i) )
+ rad->setRecursionLimit( i );
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseGlobalPhotons( PMGlobalPhotons* gp )
+{
+ double f;
+ int i;
+ int oldConsumed;
+
+
+ if( !parseToken( PHOTONS_TOK, "photons" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case SPACING_TOK:
+ gp->setNumberType( PMGlobalPhotons::Spacing );
+ nextToken( );
+ if ( parseFloat( f ) )
+ gp->setSpacing( f );
+ break;
+ case COUNT_TOK:
+ gp->setNumberType( PMGlobalPhotons::Count );
+ nextToken( );
+ if ( parseInt( i ) )
+ gp->setCount( i );
+ break;
+ case GATHER_TOK:
+ nextToken( );
+ if ( parseInt( i ) )
+ {
+ gp->setGatherMin( i );
+ if ( parseToken( ',' ) && parseInt( i ) )
+ gp->setGatherMax( i );
+ }
+ break;
+ case MEDIA_TOK:
+ nextToken( );
+ if ( parseInt( i ) )
+ {
+ gp->setMediaMaxSteps( i );
+ if ( parseToken( ',' ) && parseFloat( f ) )
+ gp->setMediaFactor( f );
+ }
+ case JITTER_TOK:
+ nextToken( );
+ if ( parseFloat( f ) )
+ gp->setJitter( f );
+ break;
+ case MAX_TRACE_LEVEL_TOK:
+ nextToken( );
+ gp->setMaxTraceLevelGlobal( false );
+ if ( parseInt( i ) )
+ gp->setMaxTraceLevel( i );
+ break;
+ case ADC_BAILOUT_TOK:
+ nextToken( );
+ gp->setAdcBailoutGlobal( false );
+ if ( parseFloat( f ) )
+ gp->setAdcBailout( f );
+ break;
+ case AUTOSTOP_TOK:
+ nextToken( );
+ if ( parseFloat( f ) )
+ gp->setAutostop( f );
+ break;
+ case EXPAND_THRESHOLDS_TOK:
+ nextToken( );
+ if ( parseFloat( f ) )
+ {
+ gp->setExpandIncrease( f );
+ if ( parseToken( ',' ) && parseInt( i ) )
+ gp->setExpandMin( i );
+ }
+ break;
+ case RADIUS_TOK:
+ nextToken( );
+ if ( parseFloat( f ) )
+ {
+ gp->setRadiusGather( f );
+ if ( parseToken( ',' ) && parseFloat( f ) )
+ {
+ gp->setRadiusGatherMulti( f );
+ if ( parseToken( ',' ) && parseFloat( f ) )
+ {
+ gp->setRadiusMedia( f );
+ if ( parseToken( ',' ) && parseFloat( f ) )
+ gp->setRadiusMediaMulti( f );
+ }
+ }
+ }
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePhotons( PMPhotons* p )
+{
+ double f;
+ int oldConsumed;
+
+ if( !parseToken( PHOTONS_TOK, "photons" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ p->setTarget( false );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case TARGET_TOK:
+ nextToken( );
+ p->setTarget( true );
+ if ( parseFloat( f ) )
+ p->setSpacingMulti( f );
+ break;
+ case REFRACTION_TOK:
+ nextToken( );
+ p->setRefraction( parseBool( ) );
+ break;
+ case REFLECTION_TOK:
+ nextToken( );
+ p->setReflection( parseBool( ) );
+ break;
+ case COLLECT_TOK:
+ nextToken( );
+ p->setCollect( parseBool( ) );
+ break;
+ case PASS_THROUGH_TOK:
+ nextToken( );
+ p->setPassThrough( parseBool( ) );
+ break;
+ case AREA_LIGHT_TOK:
+ nextToken( );
+ p->setAreaLight( parseBool( ) );
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseLightGroup( PMLightGroup* lg )
+{
+ int oldConsumed;
+
+ if ( !parseToken( LIGHT_GROUP_TOK, "light_group" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ if ( m_token == GLOBAL_LIGHTS_TOK )
+ {
+ nextToken( );
+ lg->setGlobalLights( parseBool( ) );
+ }
+ else
+ {
+ parseChildObjects( lg );
+ parseObjectModifiers( lg );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseInteriorTexture( PMInteriorTexture* it )
+{
+ int oldConsumed;
+
+ if( !parseToken( INTERIOR_TEXTURE_TOK, "interior_texture" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( it );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSphereSweep( PMSphereSweep* ss )
+{
+ int oldConsumed, numspheres;
+ QValueList<PMVector> points;
+ QValueList<double> radii;
+ PMVector point;
+ double f;
+
+ if( !parseToken( SPHERE_SWEEP_TOK, "sphere_sweep" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ nextToken( );
+ switch ( m_token )
+ {
+ case LINEAR_SPLINE_TOK:
+ ss->setSplineType( PMSphereSweep::LinearSpline );
+ break;
+ case B_SPLINE_TOK:
+ ss->setSplineType( PMSphereSweep::BSpline );
+ break;
+ case CUBIC_SPLINE_TOK:
+ ss->setSplineType( PMSphereSweep::CubicSpline );
+ break;
+ default:
+ return false;
+ }
+
+ if ( !parseInt( numspheres ) )
+ return false;
+
+ for ( int i = 0; i < numspheres; ++i )
+ {
+ if ( !parseVector( point ) )
+ return false;
+ points.append( point );
+ if ( !parseToken( ',' ) )
+ return false;
+ if ( !parseFloat( f ) )
+ return false;
+ radii.append( f );
+ }
+
+ ss->setPoints( points );
+ ss->setRadii( radii );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ if ( m_token == TOLERANCE_TOK )
+ {
+ nextToken( );
+ if ( !parseFloat( f ) )
+ return false;
+ ss->setTolerance( f );
+ }
+ else
+ {
+ parseObjectModifiers( ss );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseMesh( PMMesh* m )
+{
+ int oldConsumed;
+ PMVector vector;
+
+ if( !parseToken( MESH_TOK, "mesh" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ if ( m_token == HIERARCHY_TOK )
+ {
+ nextToken( );
+ m->setHierarchy( parseBool( ) );
+ }
+ else if ( m_token == INSIDE_VECTOR_TOK )
+ {
+ nextToken( );
+ if ( !parseVector( vector ) )
+ return false;
+ m->enableInsideVector( true );
+ m->setInsideVector( vector );
+ }
+ else
+ {
+ parseChildObjects( m );
+ parseObjectModifiers( m );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}