You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegraphics/kpovmodeler/pmheightfield.cpp

470 lines
13 KiB

/*
**************************************************************************
description
--------------------
copyright : (C) 2002 by Andreas Zehender
email : zehender@kde.org
**************************************************************************
**************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
**************************************************************************/
#include "pmheightfield.h"
#include "pmxmlhelper.h"
#include "pmheightfieldedit.h"
#include "pmheightfieldroam.h"
#include "pmmemento.h"
#include "pmviewstructure.h"
#include "pmenumproperty.h"
#include "pmdefaults.h"
#include <klocale.h>
const PMHeightField::HeightFieldType c_defaultType = PMHeightField::HFgif;
const TQString c_defaultTypeText = TQString( "gif" );
const TQString c_defaultFileName = TQString( "" );
const bool c_defaultHierarchy = true;
const bool c_defaultSmooth = false;
const double c_defaultWaterLevel = 0.0;
PMDefinePropertyClass( PMHeightField, PMHeightFieldProperty );
PMDefineEnumPropertyClass( PMHeightField, PMHeightField::HeightFieldType,
PMHeightFieldTypeProperty );
int PMHeightField::s_variance = c_defaultHeightFieldVariance;
int PMHeightField::s_parameterKey = 0;
PMViewStructure* PMHeightField::s_pDefaultViewStructure = 0;
PMMetaObject* PMHeightField::s_pMetaObject = 0;
PMObject* createNewHeightField( PMPart* part )
{
return new PMHeightField( part );
}
PMHeightField::PMHeightField( PMPart* part )
: Base( part )
{
m_hfType = c_defaultType;
m_fileName = c_defaultFileName;
m_hierarchy = c_defaultHierarchy;
m_smooth = c_defaultSmooth;
m_waterLevel = c_defaultWaterLevel;
m_modMap = true;
m_pROAM = 0;
}
PMHeightField::PMHeightField( const PMHeightField& f )
: Base( f )
{
m_hfType = f.m_hfType;
m_fileName = f.m_fileName;
m_hierarchy = f.m_hierarchy;
m_smooth = f.m_smooth;
m_waterLevel = f.m_waterLevel;
m_modMap = true;
m_pROAM = 0;
}
PMHeightField::~PMHeightField( )
{
delete m_pROAM;
}
TQString PMHeightField::description( ) const
{
return i18n( "height field" );
}
void PMHeightField::serialize( TQDomElement& e, TQDomDocument& doc ) const
{
e.setAttribute( "hf_type", typeToString( m_hfType ) );
e.setAttribute( "file_name", m_fileName );
e.setAttribute( "hierarchy", m_hierarchy );
e.setAttribute( "smooth", m_smooth );
e.setAttribute( "water_level", m_waterLevel );
Base::serialize( e, doc );
}
void PMHeightField::readAttributes( const PMXMLHelper& h )
{
m_hfType = stringToType( h.stringAttribute( "hf_type", c_defaultTypeText ) );
m_fileName = h.stringAttribute( "file_name", c_defaultFileName );
m_hierarchy = h.boolAttribute( "hierarchy", c_defaultHierarchy );
m_smooth = h.boolAttribute( "smooth", c_defaultSmooth );
m_waterLevel = h.doubleAttribute( "water_level", c_defaultWaterLevel );
Base::readAttributes( h );
}
PMMetaObject* PMHeightField::tqmetaObject( ) const
{
if( !s_pMetaObject )
{
s_pMetaObject = new PMMetaObject( "HeightField", Base::tqmetaObject( ),
createNewHeightField );
s_pMetaObject->addProperty(
new PMHeightFieldProperty( "fileName", &PMHeightField::setFileName, &PMHeightField::fileName ) );
s_pMetaObject->addProperty(
new PMHeightFieldProperty( "hierarchy", &PMHeightField::setHierarchy, &PMHeightField::hierarchy ) );
s_pMetaObject->addProperty(
new PMHeightFieldProperty( "smooth", &PMHeightField::setSmooth, &PMHeightField::smooth ) );
s_pMetaObject->addProperty(
new PMHeightFieldProperty( "waterLevel", &PMHeightField::setWaterLevel, &PMHeightField::waterLevel ) );
PMHeightFieldTypeProperty* p =
new PMHeightFieldTypeProperty( "heightFieldType", &PMHeightField::setHeightFieldType,
&PMHeightField::heightFieldType );
p->addEnumValue( "Gif", HFgif );
p->addEnumValue( "Tga", HFtga );
p->addEnumValue( "Pot", HFpot );
p->addEnumValue( "Png", HFpng );
p->addEnumValue( "Pgm", HFpgm );
p->addEnumValue( "Ppm", HFppm );
p->addEnumValue( "Sys", HFsys );
s_pMetaObject->addProperty( p );
}
return s_pMetaObject;
}
void PMHeightField::setHeightFieldType( PMHeightField::HeightFieldType t )
{
if( t != m_hfType )
{
if( m_pMemento )
m_pMemento->addData( s_pMetaObject, PMHeightFieldTypeID, m_hfType );
m_hfType = t;
}
}
void PMHeightField::setFileName( const TQString& f )
{
if( f != m_fileName )
{
if( m_pMemento )
m_pMemento->addData( s_pMetaObject, PMFileNameID, m_fileName );
m_fileName = f;
m_modMap = true;
setViewStructureChanged( );
}
}
void PMHeightField::setHierarchy( bool h )
{
if( h != m_hierarchy )
{
if( m_pMemento )
m_pMemento->addData( s_pMetaObject, PMHierarchyID, m_hierarchy );
m_hierarchy = h;
}
}
void PMHeightField::setSmooth( bool s )
{
if( s != m_smooth )
{
if( m_pMemento )
m_pMemento->addData( s_pMetaObject, PMSmoothID, m_smooth );
m_smooth = s;
}
}
void PMHeightField::setWaterLevel( double wl )
{
if( wl < 0.0 )
{
kdError( PMArea ) << "Water level < 0.0 in PMHeightField::setWaterLevel\n";
wl = 0.0;
}
if( wl > 1.0 )
{
kdError( PMArea ) << "Water level > 1.0 in PMHeightField::setWaterLevel\n";
wl = 1.0;
}
if( wl != m_waterLevel )
{
if( m_pMemento )
m_pMemento->addData( s_pMetaObject, PMWaterLevelID, m_waterLevel );
m_waterLevel = wl;
setViewStructureChanged( );
}
}
PMDialogEditBase* PMHeightField::editWidget( TQWidget* parent ) const
{
return new PMHeightFieldEdit( parent );
}
void PMHeightField::restoreMemento( PMMemento* s )
{
PMMementoDataIterator it( s );
PMMementoData* data;
for( ; it.current( ); ++it )
{
data = it.current( );
if( data->objectType( ) == s_pMetaObject )
{
switch( data->valueID( ) )
{
case PMHeightFieldTypeID:
m_hfType = ( HeightFieldType ) data->intData( );
break;
case PMFileNameID:
m_fileName = data->stringData( );
break;
case PMHierarchyID:
m_hierarchy = data->boolData( );
break;
case PMSmoothID:
m_smooth = data->boolData( );
break;
case PMWaterLevelID:
m_waterLevel = data->doubleData( );
break;
default:
kdError( PMArea ) << "Wrong ID in PMHeightField::restoreMemento\n";
break;
}
}
}
Base::restoreMemento( s );
}
bool PMHeightField::isDefault( )
{
return ( m_waterLevel == c_defaultWaterLevel && m_fileName.isEmpty( ) );
}
void PMHeightField::createViewStructure( )
{
int detail = 65200 - ( ( s_variance * 163 ) * ( displayDetail( ) * displayDetail( ) ) );
if ( m_modMap )
{
m_modMap = false;
if ( m_pROAM )
{
delete m_pROAM;
m_pROAM = 0;
}
if ( !m_fileName.isEmpty( ) )
{
m_pROAM = new PMHeightFieldROAM( m_fileName );
if ( m_pROAM->isFailed( ) )
{
delete m_pROAM;
m_pROAM = 0;
}
}
}
if ( m_pROAM )
{
m_pROAM->setDisplayDetail( detail );
m_pROAM->setWaterLevel( m_waterLevel );
m_pROAM->updateModel( );
roamViewStructure( );
return;
}
if ( !m_pViewStructure )
{
m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
m_pViewStructure->points( ).detach( );
m_pViewStructure->lines( ).detach( );
}
else
{
m_pViewStructure->points( ).resize(
defaultViewStructure( )->points( ).size( ) );
m_pViewStructure->lines( ).resize(
defaultViewStructure( )->lines( ).size( ) );
}
PMPointArray& points = m_pViewStructure->points( );
points[4][1] = m_waterLevel;
points[5][1] = m_waterLevel;
points[6][1] = m_waterLevel;
points[7][1] = m_waterLevel;
}
void PMHeightField::roamViewStructure( )
{
if ( !m_pViewStructure )
{
m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
m_pViewStructure->points( ).detach( );
m_pViewStructure->lines( ).detach( );
}
int x, z, i, pts;
int size = m_pROAM->size( );
int currentLine = defaultViewStructure( )->lines( ).size( );
int defPointsNum = defaultViewStructure( )->points( ).size( );
double dx, dy, dz;
double sizeM1 = size - 1.0;
m_pViewStructure->points( ).resize( m_pROAM->usedPoints( ) + defPointsNum );
m_pViewStructure->lines( ).resize( m_pROAM->numLines( ) + currentLine );
PMPointArray& points = m_pViewStructure->points( );
PMLineArray& lines = m_pViewStructure->lines( );
points[4][1] = m_waterLevel;
points[5][1] = m_waterLevel;
points[6][1] = m_waterLevel;
points[7][1] = m_waterLevel;
for ( x = 0; x < size; ++x )
{
dx = x / sizeM1;
for ( z = 0; z < size; ++z )
{
dz = z / sizeM1;
if ( m_pROAM->usedPoint( x, z ) )
{
pts = m_pROAM->posPoint( x, z ) + defPointsNum;
dy = m_pROAM->height( x, z, true ) / 65535.0;
points[ pts ] = PMPoint( dx, dy, dz );
for ( i = 0; m_pROAM->lineExist( x, z, i ) && i < 8; ++i )
{
lines[ currentLine++ ] =
PMLine( pts, m_pROAM->endPoint( x, z, i ) + defPointsNum );
}
}
}
}
}
PMViewStructure* PMHeightField::defaultViewStructure( ) const
{
if( !s_pDefaultViewStructure )
{
s_pDefaultViewStructure = new PMViewStructure( 12, 16 );
PMPointArray& points = s_pDefaultViewStructure->points( );
PMLineArray& lines = s_pDefaultViewStructure->lines( );
points[ 0] = PMPoint( 0.0, 0.0, 0.0 );
points[ 1] = PMPoint( 1.0, 0.0, 0.0 );
points[ 2] = PMPoint( 1.0, 0.0, 1.0 );
points[ 3] = PMPoint( 0.0, 0.0, 1.0 );
points[ 4] = PMPoint( 0.0, c_defaultWaterLevel, 0.0 );
points[ 5] = PMPoint( 1.0, c_defaultWaterLevel, 0.0 );
points[ 6] = PMPoint( 1.0, c_defaultWaterLevel, 1.0 );
points[ 7] = PMPoint( 0.0, c_defaultWaterLevel, 1.0 );
points[ 8] = PMPoint( 0.0, 1.0, 0.0 );
points[ 9] = PMPoint( 1.0, 1.0, 0.0 );
points[10] = PMPoint( 1.0, 1.0, 1.0 );
points[11] = PMPoint( 0.0, 1.0, 1.0 );
lines[ 0] = PMLine( 0, 1 );
lines[ 1] = PMLine( 1, 2 );
lines[ 2] = PMLine( 2, 3 );
lines[ 3] = PMLine( 0, 3 );
lines[ 4] = PMLine( 0, 8 );
lines[ 5] = PMLine( 1, 9 );
lines[ 6] = PMLine( 2, 10 );
lines[ 7] = PMLine( 3, 11 );
lines[ 8] = PMLine( 4, 5 );
lines[ 9] = PMLine( 5, 6 );
lines[10] = PMLine( 6, 7 );
lines[11] = PMLine( 4, 7 );
lines[12] = PMLine( 8, 9 );
lines[13] = PMLine( 9, 10 );
lines[14] = PMLine( 10, 11 );
lines[15] = PMLine( 8, 11 );
}
return s_pDefaultViewStructure;
}
TQString PMHeightField::typeToString( PMHeightField::HeightFieldType t )
{
TQString s;
switch( t )
{
case HFgif:
s = TQString( "gif" );
break;
case HFtga:
s = TQString( "tga" );
break;
case HFpot:
s = TQString( "pot" );
break;
case HFpng:
s = TQString( "png" );
break;
case HFpgm:
s = TQString( "pgm" );
break;
case HFppm:
s = TQString( "ppm" );
break;
case HFsys:
s = TQString( "sys" );
break;
}
return s;
}
PMHeightField::HeightFieldType PMHeightField::stringToType( const TQString &str )
{
HeightFieldType t = HFgif;
if( str == "gif" )
t = HFgif;
else if( str == "tga" )
t = HFtga;
else if( str == "pot" )
t = HFpot;
else if( str == "png" )
t = HFpng;
else if( str == "pgm" )
t = HFpgm;
else if( str == "ppm" )
t = HFppm;
else if( str == "sys" )
t = HFsys;
return t;
}
void PMHeightField::setVariance( int v )
{
if( v < 52 && v > 0 )
s_variance = v;
else
kdDebug( PMArea ) << "PMHeightField::setVariance: V must be less than 52 & greater than 0\n";
s_parameterKey++;
}
void PMHeightField::cleanUp( ) const
{
if( s_pDefaultViewStructure )
delete s_pDefaultViewStructure;
s_pDefaultViewStructure = 0;
if( s_pMetaObject )
{
delete s_pMetaObject;
s_pMetaObject = 0;
}
Base::cleanUp( );
}