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.
1065 lines
32 KiB
1065 lines
32 KiB
15 years ago
|
/*
|
||
|
**************************************************************************
|
||
|
description
|
||
|
--------------------
|
||
|
copyright : (C) 2000-2002 by Andreas Zehender
|
||
|
email : zehender@kde.org
|
||
|
**************************************************************************
|
||
|
|
||
|
**************************************************************************
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||
|
* (at your option) any later version. *
|
||
|
* *
|
||
|
**************************************************************************/
|
||
|
|
||
|
|
||
|
#include "pmlight.h"
|
||
|
|
||
|
#include "pmxmlhelper.h"
|
||
|
#include "pmlightedit.h"
|
||
|
#include "pmmemento.h"
|
||
|
#include "pmviewstructure.h"
|
||
|
#include "pm3dcontrolpoint.h"
|
||
|
#include "pmmath.h"
|
||
|
#include "pmmatrix.h"
|
||
|
#include "pmenumproperty.h"
|
||
|
|
||
|
#include <klocale.h>
|
||
|
|
||
|
const PMVector locationDefault = PMVector( 0, 0, 0 );
|
||
|
const PMColor colorDefault = PMColor( 1.0, 1.0, 1.0 );
|
||
|
const double radiusDefault = 70.0;
|
||
|
const double falloffDefault = 70.0;
|
||
|
const double tightnessDefault = 10;
|
||
|
const PMVector pointAtDefault = PMVector( 0, 0, 1 );
|
||
|
const bool parallelDefault = false;
|
||
|
const PMVector areaAxis1Default = PMVector( 1, 0, 0 );
|
||
|
const PMVector areaAxis2Default = PMVector( 0, 1, 0 );
|
||
|
const int areaSize1Default = 3;
|
||
|
const int areaSize2Default = 3;
|
||
|
const int adaptiveDefault = 0;
|
||
|
const bool orientDefault = false;
|
||
|
const bool jitterDefault = false;
|
||
|
const int fadePowerDefault = 1;
|
||
|
const double fadeDistanceDefault = 10.0;
|
||
|
|
||
|
PMViewStructure* PMLight::s_pDefaultPointStructure = 0;
|
||
|
PMViewStructure* PMLight::s_pDefaultSpotStructure = 0;
|
||
|
PMViewStructure* PMLight::s_pDefaultCylindricalStructure = 0;
|
||
|
double PMLight::s_pointLightSize = 0.25;
|
||
|
int PMLight::s_nCylinderLines = 8;
|
||
|
int PMLight::s_nSpotLines = 8;
|
||
|
double PMLight::s_length = 1.0;
|
||
|
|
||
|
PMDefinePropertyClass( PMLight, PMLightProperty );
|
||
|
PMDefineEnumPropertyClass( PMLight, PMLight::PMLightType, PMTypeProperty );
|
||
|
PMDefineEnumPropertyClass( PMLight, PMLight::PMAreaType, PMAreaProperty );
|
||
|
|
||
|
PMMetaObject* PMLight::s_pMetaObject = 0;
|
||
|
PMObject* createNewLight( PMPart* part )
|
||
|
{
|
||
|
return new PMLight( part );
|
||
|
}
|
||
|
|
||
|
PMLight::PMLight( PMPart* part )
|
||
|
: Base( part )
|
||
|
{
|
||
|
m_location = locationDefault;
|
||
|
m_color = colorDefault;
|
||
|
m_type = PointLight;
|
||
|
m_radius = radiusDefault;
|
||
|
m_falloff = falloffDefault;
|
||
|
m_tightness = tightnessDefault;
|
||
|
m_pointAt = pointAtDefault;
|
||
|
m_parallel = parallelDefault;
|
||
|
m_bAreaLight = false;
|
||
|
m_areaType = Rectangular;
|
||
|
m_areaAxis1 = areaAxis1Default;
|
||
|
m_areaAxis2 = areaAxis2Default;
|
||
|
m_areaSize1 = areaSize1Default;
|
||
|
m_areaSize2 = areaSize2Default;
|
||
|
m_adaptive = adaptiveDefault;
|
||
|
m_orient = orientDefault;
|
||
|
m_jitter = jitterDefault;
|
||
|
m_bFading = false;
|
||
|
m_fadeDistance = fadeDistanceDefault;
|
||
|
m_fadePower = fadePowerDefault;
|
||
|
m_bMediaInteraction = true;
|
||
|
m_bMediaAttenuation = true;
|
||
|
}
|
||
|
|
||
|
PMLight::PMLight( const PMLight& l )
|
||
|
: Base( l )
|
||
|
{
|
||
|
m_location = l.m_location;
|
||
|
m_color = l.m_color;
|
||
|
m_type = l.m_type;
|
||
|
m_radius = l.m_radius;
|
||
|
m_falloff = l.m_falloff;
|
||
|
m_tightness = l.m_tightness;
|
||
|
m_pointAt = l.m_pointAt;
|
||
|
m_parallel = l.m_parallel;
|
||
|
m_bAreaLight = l.m_bAreaLight;
|
||
|
m_areaType = l.m_areaType;
|
||
|
m_areaAxis1 = l.m_areaAxis1;
|
||
|
m_areaAxis2 = l.m_areaAxis2;
|
||
|
m_areaSize1 = l.m_areaSize1;
|
||
|
m_areaSize2 = l.m_areaSize2;
|
||
|
m_adaptive = l.m_adaptive;
|
||
|
m_orient = l.m_orient;
|
||
|
m_jitter = l.m_jitter;
|
||
|
m_bFading = l.m_bFading;
|
||
|
m_fadeDistance = l.m_fadeDistance;
|
||
|
m_fadePower = l.m_fadePower;
|
||
|
m_bMediaInteraction = l.m_bMediaInteraction;
|
||
|
m_bMediaAttenuation = l.m_bMediaAttenuation;
|
||
|
}
|
||
|
|
||
|
PMLight::~PMLight( )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
QString PMLight::description( ) const
|
||
|
{
|
||
|
return i18n( "light" );
|
||
|
}
|
||
|
|
||
|
void PMLight::serialize( QDomElement& e, QDomDocument& doc ) const
|
||
|
{
|
||
|
e.setAttribute( "location", m_location.serializeXML( ) );
|
||
|
e.setAttribute( "color", m_color.serializeXML( ) );
|
||
|
|
||
|
switch( m_type )
|
||
|
{
|
||
|
case SpotLight:
|
||
|
e.setAttribute( "lighttype", "spotlight" );
|
||
|
break;
|
||
|
case CylinderLight:
|
||
|
e.setAttribute( "lighttype", "cylinder" );
|
||
|
break;
|
||
|
case ShadowlessLight:
|
||
|
e.setAttribute( "lighttype", "shadowless" );
|
||
|
break;
|
||
|
case PointLight:
|
||
|
e.setAttribute( "lighttype", "point" );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if( ( m_type == SpotLight ) || ( m_type == CylinderLight ) )
|
||
|
{
|
||
|
e.setAttribute( "radius", m_radius );
|
||
|
e.setAttribute( "falloff", m_falloff );
|
||
|
e.setAttribute( "tightness", m_tightness );
|
||
|
e.setAttribute( "point_at", m_pointAt.serializeXML( ) );
|
||
|
}
|
||
|
|
||
|
if ( m_parallel )
|
||
|
e.setAttribute( "parallel", "1" );
|
||
|
else
|
||
|
e.setAttribute( "parallel", "0" );
|
||
|
|
||
|
if( m_bAreaLight )
|
||
|
{
|
||
|
if ( m_areaType == Rectangular )
|
||
|
e.setAttribute( "areatype", "rectangular" );
|
||
|
else
|
||
|
e.setAttribute( "areatype", "circular" );
|
||
|
|
||
|
e.setAttribute( "area_light", "1" );
|
||
|
e.setAttribute( "area_light_a", m_areaAxis1.serializeXML( ) );
|
||
|
e.setAttribute( "area_light_b", m_areaAxis2.serializeXML( ) );
|
||
|
e.setAttribute( "area_size_a", m_areaSize1 );
|
||
|
e.setAttribute( "area_size_b", m_areaSize2 );
|
||
|
e.setAttribute( "adaptive", m_adaptive );
|
||
|
|
||
|
if( m_orient )
|
||
|
e.setAttribute( "orient", "1" );
|
||
|
else
|
||
|
e.setAttribute( "orient", "0" );
|
||
|
|
||
|
if( m_jitter )
|
||
|
e.setAttribute( "jitter", "1" );
|
||
|
else
|
||
|
e.setAttribute( "jitter", "0" );
|
||
|
}
|
||
|
else
|
||
|
e.setAttribute( "area_light", "0" );
|
||
|
|
||
|
if( m_bFading )
|
||
|
{
|
||
|
e.setAttribute( "fading", "1" );
|
||
|
e.setAttribute( "fade_distance" , m_fadeDistance );
|
||
|
e.setAttribute( "fade_power", m_fadePower );
|
||
|
}
|
||
|
else
|
||
|
e.setAttribute( "fading", "0" );
|
||
|
|
||
|
if( m_bMediaInteraction )
|
||
|
e.setAttribute( "media_interaction", "1" );
|
||
|
else
|
||
|
e.setAttribute( "media_interaction", "0" );
|
||
|
|
||
|
if( m_bMediaAttenuation )
|
||
|
e.setAttribute( "media_attenuation", "1" );
|
||
|
else
|
||
|
e.setAttribute( "media_attenuation", "0" );
|
||
|
|
||
|
Base::serialize( e, doc );
|
||
|
}
|
||
|
|
||
|
void PMLight::readAttributes( const PMXMLHelper& h )
|
||
|
{
|
||
|
QString str;
|
||
|
|
||
|
m_location = h.vectorAttribute( "location", locationDefault );
|
||
|
m_color = h.colorAttribute( "color", colorDefault );
|
||
|
|
||
|
str = h.stringAttribute( "lighttype", "point" );
|
||
|
if( str == "point" )
|
||
|
m_type = PointLight;
|
||
|
else if( str == "spotlight" )
|
||
|
m_type = SpotLight;
|
||
|
else if( str == "cylinder" )
|
||
|
m_type = CylinderLight;
|
||
|
else if( str == "shadowless" )
|
||
|
m_type = ShadowlessLight;
|
||
|
else
|
||
|
m_type = PointLight;
|
||
|
|
||
|
if( ( m_type == SpotLight ) || ( m_type == CylinderLight ) )
|
||
|
{
|
||
|
m_radius = h.doubleAttribute( "radius", radiusDefault );
|
||
|
m_falloff = h.doubleAttribute( "falloff", falloffDefault );
|
||
|
m_tightness = h.doubleAttribute( "tightness", tightnessDefault );
|
||
|
m_pointAt = h.vectorAttribute( "point_at", pointAtDefault );
|
||
|
}
|
||
|
|
||
|
m_parallel = h.boolAttribute( "parallel", parallelDefault );
|
||
|
|
||
|
m_bAreaLight = h.boolAttribute( "area_light", false );
|
||
|
if( m_bAreaLight )
|
||
|
{
|
||
|
str = h.stringAttribute( "areatype", "rectangular" );
|
||
|
if ( str == "circular" )
|
||
|
m_areaType = Circular;
|
||
|
else
|
||
|
m_areaType = Rectangular;
|
||
|
|
||
|
m_areaAxis1 = h.vectorAttribute( "area_light_a", areaAxis1Default );
|
||
|
m_areaAxis2 = h.vectorAttribute( "area_light_b", areaAxis2Default );
|
||
|
m_areaSize1 = h.intAttribute( "area_size_a", areaSize1Default );
|
||
|
m_areaSize2 = h.intAttribute( "area_size_b", areaSize2Default );
|
||
|
m_adaptive = h.intAttribute( "adaptive", adaptiveDefault );
|
||
|
m_orient = h.boolAttribute( "orient", orientDefault );
|
||
|
m_jitter = h.boolAttribute( "jitter", jitterDefault );
|
||
|
}
|
||
|
m_bFading = h.boolAttribute( "fading", false );
|
||
|
if( m_bFading )
|
||
|
{
|
||
|
m_fadeDistance = h.doubleAttribute( "fade_distance", fadeDistanceDefault );
|
||
|
m_fadePower = h.intAttribute( "fade_power", m_fadePower );
|
||
|
}
|
||
|
m_bMediaInteraction = h.boolAttribute( "media_interaction", true );
|
||
|
m_bMediaAttenuation = h.boolAttribute( "media_attenuation", true );
|
||
|
|
||
|
Base::readAttributes( h );
|
||
|
}
|
||
|
|
||
|
PMMetaObject* PMLight::metaObject( ) const
|
||
|
{
|
||
|
if( !s_pMetaObject )
|
||
|
{
|
||
|
s_pMetaObject = new PMMetaObject( "Light", Base::metaObject( ),
|
||
|
createNewLight );
|
||
|
PMTypeProperty* p = new PMTypeProperty( "lightType", &PMLight::setLightType,
|
||
|
&PMLight::lightType );
|
||
|
p->addEnumValue( "PointLight", PointLight );
|
||
|
p->addEnumValue( "SpotLight", SpotLight );
|
||
|
p->addEnumValue( "CylinderLight", CylinderLight );
|
||
|
p->addEnumValue( "ShadowlessLight", ShadowlessLight );
|
||
|
s_pMetaObject->addProperty( p );
|
||
|
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "location", &PMLight::setLocation, &PMLight::location ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "color", &PMLight::setColor, &PMLight::color ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "radius", &PMLight::setRadius, &PMLight::radius ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "falloff", &PMLight::setFalloff, &PMLight::falloff ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "tightness", &PMLight::setTightness, &PMLight::tightness ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "pointAt", &PMLight::setPointAt, &PMLight::pointAt ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "parallel", &PMLight::setParallel, &PMLight::parallel ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "areaLight", &PMLight::setAreaLight, &PMLight::isAreaLight ) );
|
||
|
|
||
|
PMAreaProperty* p2 = new PMAreaProperty( "areaType", &PMLight::setAreaType,
|
||
|
&PMLight::areaType );
|
||
|
p2->addEnumValue( "Rectangular", Rectangular );
|
||
|
p2->addEnumValue( "Circular", Circular );
|
||
|
s_pMetaObject->addProperty( p2 );
|
||
|
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "axis1", &PMLight::setAxis1, &PMLight::axis1 ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "axis2", &PMLight::setAxis2, &PMLight::axis2 ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "adaptive", &PMLight::setAdaptive, &PMLight::adaptive ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "orient", &PMLight::setOrient, &PMLight::orient ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "jitter", &PMLight::setJitter, &PMLight::jitter ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "fading", &PMLight::setFading, &PMLight::fading ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "fadeDistance", &PMLight::setFadeDistance, &PMLight::fadeDistance ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "fadePower", &PMLight::setFadePower, &PMLight::fadePower ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "mediaInteraction", &PMLight::setMediaInteraction,
|
||
|
&PMLight::mediaInteraction ) );
|
||
|
s_pMetaObject->addProperty(
|
||
|
new PMLightProperty( "mediaAttenuation", &PMLight::setMediaAttenuation,
|
||
|
&PMLight::mediaAttenuation ) );
|
||
|
}
|
||
|
return s_pMetaObject;
|
||
|
}
|
||
|
|
||
|
void PMLight::setLocation( const PMVector& p )
|
||
|
{
|
||
|
if( p != m_location )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMLocationID, m_location );
|
||
|
m_location = p;
|
||
|
m_location.resize( 3 );
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setColor( const PMColor& c )
|
||
|
{
|
||
|
if( c != m_color )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMColorID, m_color );
|
||
|
m_color = c;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setLightType( PMLightType t )
|
||
|
{
|
||
|
if( t != m_type )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMTypeID, m_type );
|
||
|
m_type = t;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setRadius( double r )
|
||
|
{
|
||
|
if( !approx( r, m_radius ) )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMRadiusID, m_radius );
|
||
|
m_radius = r;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setFalloff( double f )
|
||
|
{
|
||
|
if( !approx( f, m_falloff ) )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMFalloffID, m_falloff );
|
||
|
m_falloff = f;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setTightness( double t )
|
||
|
{
|
||
|
if( !approx( t, m_tightness ) )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMTightnessID, m_tightness );
|
||
|
m_tightness = t;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setPointAt( const PMVector& v )
|
||
|
{
|
||
|
if( !m_pointAt.approxEqual( v ) )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMPointAtID, m_pointAt );
|
||
|
m_pointAt = v;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setParallel( bool p )
|
||
|
{
|
||
|
if ( p != m_parallel )
|
||
|
{
|
||
|
if ( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMParallelID, m_parallel );
|
||
|
m_parallel = p;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setAreaLight( bool yes )
|
||
|
{
|
||
|
if( yes != m_bAreaLight )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMAreaLightID, m_bAreaLight );
|
||
|
m_bAreaLight = yes;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setAreaType( PMAreaType at )
|
||
|
{
|
||
|
if ( at != m_areaType )
|
||
|
{
|
||
|
if ( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMAreaTypeID, m_areaType );
|
||
|
m_areaType = at;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setAxis1( const PMVector& v )
|
||
|
{
|
||
|
if( !m_areaAxis1.approxEqual( v ) )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMAreaAxis1ID, m_areaAxis1 );
|
||
|
m_areaAxis1 = v;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setAxis2( const PMVector& v )
|
||
|
{
|
||
|
if( !m_areaAxis2.approxEqual( v ) )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMAreaAxis2ID, m_areaAxis2 );
|
||
|
m_areaAxis2 = v;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setSize1( int s )
|
||
|
{
|
||
|
if( s != m_areaSize1 )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMAreaSize1ID, m_areaSize1 );
|
||
|
m_areaSize1 = s;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setSize2( int s )
|
||
|
{
|
||
|
if( s != m_areaSize2 )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMAreaSize2ID, m_areaSize2 );
|
||
|
m_areaSize2 = s;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setAdaptive( int a )
|
||
|
{
|
||
|
if( a != m_adaptive )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMAdaptiveID, m_adaptive );
|
||
|
m_adaptive = a;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setOrient( bool o )
|
||
|
{
|
||
|
if( o != m_orient )
|
||
|
{
|
||
|
if ( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMOrientID, m_orient );
|
||
|
m_orient = o;
|
||
|
setViewStructureChanged( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setJitter( bool j )
|
||
|
{
|
||
|
if( j != m_jitter )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMJitterID, m_jitter );
|
||
|
m_jitter = j;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setFading( bool y )
|
||
|
{
|
||
|
if( y != m_bFading )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMFadingID, m_bFading );
|
||
|
m_bFading = y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setFadeDistance( double d )
|
||
|
{
|
||
|
if( !approx( d, m_fadeDistance ) )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMFadeDistanceID, m_fadeDistance );
|
||
|
m_fadeDistance = d;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setFadePower( int p )
|
||
|
{
|
||
|
if( p != m_fadePower )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMFadePowerID, m_fadePower );
|
||
|
m_fadePower = p;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setMediaInteraction( bool y )
|
||
|
{
|
||
|
if( y != m_bMediaInteraction )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMInteractionID, m_bMediaInteraction );
|
||
|
m_bMediaInteraction = y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::setMediaAttenuation( bool y )
|
||
|
{
|
||
|
if( y != m_bMediaAttenuation )
|
||
|
{
|
||
|
if( m_pMemento )
|
||
|
m_pMemento->addData( s_pMetaObject, PMAttenuationID, m_bMediaAttenuation );
|
||
|
m_bMediaAttenuation = y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PMDialogEditBase* PMLight::editWidget( QWidget* parent ) const
|
||
|
{
|
||
|
return new PMLightEdit( parent );
|
||
|
}
|
||
|
|
||
|
void PMLight::restoreMemento( PMMemento* s )
|
||
|
{
|
||
|
PMMementoDataIterator it( s );
|
||
|
PMMementoData* data;
|
||
|
|
||
|
for( ; it.current( ); ++it )
|
||
|
{
|
||
|
data = it.current( );
|
||
|
if( data->objectType( ) == s_pMetaObject )
|
||
|
{
|
||
|
switch( data->valueID( ) )
|
||
|
{
|
||
|
case PMLocationID:
|
||
|
setLocation( data->vectorData( ) );
|
||
|
break;
|
||
|
case PMColorID:
|
||
|
setColor( data->colorData( ) );
|
||
|
break;
|
||
|
case PMTypeID:
|
||
|
setLightType( ( PMLightType ) ( data->intData( ) ) );
|
||
|
break;
|
||
|
case PMRadiusID:
|
||
|
setRadius( data->doubleData( ) );
|
||
|
break;
|
||
|
case PMFalloffID:
|
||
|
setFalloff( data->doubleData( ) );
|
||
|
break;
|
||
|
case PMTightnessID:
|
||
|
setTightness( data->doubleData( ) );
|
||
|
break;
|
||
|
case PMPointAtID:
|
||
|
setPointAt( data->vectorData( ) );
|
||
|
break;
|
||
|
case PMParallelID:
|
||
|
setParallel( data->boolData( ) );
|
||
|
break;
|
||
|
case PMAreaLightID:
|
||
|
setAreaLight( data->boolData( ) );
|
||
|
break;
|
||
|
case PMAreaTypeID:
|
||
|
setAreaType( ( PMAreaType ) ( data->intData( ) ) );
|
||
|
break;
|
||
|
case PMAreaAxis1ID:
|
||
|
setAxis1( data->vectorData( ) );
|
||
|
break;
|
||
|
case PMAreaAxis2ID:
|
||
|
setAxis2( data->vectorData( ) );
|
||
|
break;
|
||
|
case PMAreaSize1ID:
|
||
|
setSize1( data->intData( ) );
|
||
|
break;
|
||
|
case PMAreaSize2ID:
|
||
|
setSize2( data->intData( ) );
|
||
|
break;
|
||
|
case PMAdaptiveID:
|
||
|
setAdaptive( data->intData( ) );
|
||
|
break;
|
||
|
case PMOrientID:
|
||
|
setOrient( data->boolData( ) );
|
||
|
break;
|
||
|
case PMJitterID:
|
||
|
setJitter( data->boolData( ) );
|
||
|
break;
|
||
|
case PMFadingID:
|
||
|
setFading( data->boolData( ) );
|
||
|
break;
|
||
|
case PMFadeDistanceID:
|
||
|
setFadeDistance( data->doubleData( ) );
|
||
|
break;
|
||
|
case PMFadePowerID:
|
||
|
setFadePower( data->intData( ) );
|
||
|
break;
|
||
|
case PMInteractionID:
|
||
|
setMediaInteraction( data->boolData( ) );
|
||
|
break;
|
||
|
case PMAttenuationID:
|
||
|
setMediaAttenuation( data->boolData( ) );
|
||
|
break;
|
||
|
default:
|
||
|
kdError( PMArea ) << "Wrong ID in PMLight::restoreMemento\n";
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Base::restoreMemento( s );
|
||
|
}
|
||
|
|
||
|
void PMLight::createViewStructure( )
|
||
|
{
|
||
|
if( ( m_type == PointLight ) || ( m_type == ShadowlessLight ) )
|
||
|
{
|
||
|
if( !m_pViewStructure )
|
||
|
{
|
||
|
m_pViewStructure = new PMViewStructure( defaultPointStructure( ) );
|
||
|
m_pViewStructure->points( ).detach( );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pViewStructure->points( ).resize(
|
||
|
defaultPointStructure( )->points( ).size( ) );
|
||
|
m_pViewStructure->lines( ) = defaultPointStructure( )->lines( );
|
||
|
}
|
||
|
|
||
|
PMPointArray& points = m_pViewStructure->points( );
|
||
|
|
||
|
int i;
|
||
|
double c = s_pointLightSize / sqrt( 3.0 );
|
||
|
for( i = 0; i < 14; i++ )
|
||
|
points[i] = PMPoint( m_location );
|
||
|
|
||
|
points[0][0] += s_pointLightSize;
|
||
|
points[1][0] -= s_pointLightSize;
|
||
|
points[2][1] += s_pointLightSize;
|
||
|
points[3][1] -= s_pointLightSize;
|
||
|
points[4][2] += s_pointLightSize;
|
||
|
points[5][2] -= s_pointLightSize;
|
||
|
|
||
|
for( i = 0; i < 4; i++ )
|
||
|
{
|
||
|
points[6+2*i][0] += c;
|
||
|
points[6+2*i][1] += ( i & 1 ? c : -c );
|
||
|
points[6+2*i][2] += ( i & 2 ? c : -c );
|
||
|
points[7+2*i][0] -= c;
|
||
|
points[7+2*i][1] -= ( i & 1 ? c : -c );
|
||
|
points[7+2*i][2] -= ( i & 2 ? c : -c );
|
||
|
}
|
||
|
}
|
||
|
else if( m_type == SpotLight )
|
||
|
{
|
||
|
if( !m_pViewStructure )
|
||
|
{
|
||
|
m_pViewStructure = new PMViewStructure( defaultSpotStructure( ) );
|
||
|
m_pViewStructure->points( ).detach( );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pViewStructure->points( ).resize(
|
||
|
defaultSpotStructure( )->points( ).size( ) );
|
||
|
m_pViewStructure->lines( ) = defaultSpotStructure( )->lines( );
|
||
|
}
|
||
|
|
||
|
PMPointArray& points = m_pViewStructure->points( );
|
||
|
|
||
|
points[0] = PMPoint( m_location );
|
||
|
|
||
|
PMVector pointAtVector = m_pointAt - m_location;
|
||
|
double pl = pointAtVector.abs( );
|
||
|
if( approxZero( pl ) )
|
||
|
pointAtVector = PMVector( 0.0, 0.0, 1.0 );
|
||
|
else
|
||
|
pointAtVector /= pl;
|
||
|
PMVector endPoint = pointAtVector.orthogonal( );
|
||
|
PMMatrix rotation = PMMatrix::rotation( pointAtVector,
|
||
|
2 * M_PI / s_nSpotLines );
|
||
|
double length, r1, r2, a1, a2;
|
||
|
length = s_length;
|
||
|
a1 = m_radius;
|
||
|
a2 = m_falloff;
|
||
|
if( a1 < 0 ) a1 = 0;
|
||
|
if( a2 < 0 ) a2 = 0;
|
||
|
if( a1 > a2 ) a1 = a2;
|
||
|
if( a1 >= 89.9 ) a1 = 89.9;
|
||
|
if( a2 >= 89.9 ) a2 = 89.9;
|
||
|
a1 *= M_PI / 180;
|
||
|
a2 *= M_PI / 180;
|
||
|
r1 = tan( a1 ) * length;
|
||
|
r2 = tan( a2 ) * length;
|
||
|
|
||
|
if( r2 > length )
|
||
|
{
|
||
|
double d = length / r2;
|
||
|
r1 *= d;
|
||
|
r2 *= d;
|
||
|
length *= d;
|
||
|
}
|
||
|
|
||
|
endPoint *= r2;
|
||
|
double r;
|
||
|
if( approxZero( r2 ) )
|
||
|
r = 1;
|
||
|
else
|
||
|
r = r1 / r2;
|
||
|
|
||
|
PMVector circleCenter = m_location + length * pointAtVector;
|
||
|
points[1] = PMPoint( circleCenter + endPoint );
|
||
|
points[s_nSpotLines + 1] = PMPoint( circleCenter + endPoint * r );
|
||
|
|
||
|
int i;
|
||
|
for( i = 2; i < ( s_nSpotLines + 1 ); i++ )
|
||
|
{
|
||
|
endPoint = rotation * endPoint;
|
||
|
points[i] = PMPoint( circleCenter + endPoint );
|
||
|
points[s_nSpotLines + i] = PMPoint( circleCenter + endPoint * r );
|
||
|
}
|
||
|
points[s_nSpotLines*2+1] = m_pointAt;
|
||
|
}
|
||
|
else if( m_type == CylinderLight )
|
||
|
{
|
||
|
if( !m_pViewStructure )
|
||
|
{
|
||
|
m_pViewStructure = new PMViewStructure( defaultCylindricalStructure( ) );
|
||
|
m_pViewStructure->points( ).detach( );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pViewStructure->points( ).resize(
|
||
|
defaultCylindricalStructure( )->points( ).size( ) );
|
||
|
m_pViewStructure->lines( ) = defaultCylindricalStructure( )->lines( );
|
||
|
}
|
||
|
|
||
|
PMPointArray& points = m_pViewStructure->points( );
|
||
|
|
||
|
points[s_nCylinderLines*4] = PMPoint( m_location );
|
||
|
points[s_nCylinderLines*4+1] = PMPoint( m_pointAt );
|
||
|
|
||
|
PMVector pointAtVector = m_pointAt - m_location;
|
||
|
double pl = pointAtVector.abs( );
|
||
|
if( approxZero( pl ) )
|
||
|
pointAtVector = PMVector( 0.0, 0.0, 1.0 );
|
||
|
else
|
||
|
pointAtVector /= pl;
|
||
|
PMVector endPoint = pointAtVector.orthogonal( );
|
||
|
PMMatrix rotation = PMMatrix::rotation( pointAtVector,
|
||
|
2 * M_PI / s_nCylinderLines );
|
||
|
double r1, r2;
|
||
|
r1 = m_radius / 100;
|
||
|
r2 = m_falloff / 100;
|
||
|
if( r1 < 0 ) r1 = 0;
|
||
|
if( r2 < 0 ) r2 = 0;
|
||
|
if( r1 > r2 ) r1 = r2;
|
||
|
|
||
|
endPoint *= r2;
|
||
|
double r;
|
||
|
if( approxZero( r2 ) )
|
||
|
r = 1;
|
||
|
else
|
||
|
r = r1 / r2;
|
||
|
|
||
|
PMVector circleCenter = m_location + s_length * pointAtVector;
|
||
|
points[0] = PMPoint( circleCenter + endPoint );
|
||
|
points[s_nCylinderLines] = PMPoint( m_location + endPoint );
|
||
|
points[2*s_nCylinderLines] = PMPoint( circleCenter + endPoint * r );
|
||
|
points[3*s_nCylinderLines] = PMPoint( m_location + endPoint * r );
|
||
|
|
||
|
int i;
|
||
|
for( i = 1; i < s_nCylinderLines; i++ )
|
||
|
{
|
||
|
endPoint = rotation * endPoint;
|
||
|
points[i] = PMPoint( circleCenter + endPoint );
|
||
|
points[s_nCylinderLines + i] = PMPoint( m_location + endPoint );
|
||
|
points[2*s_nCylinderLines + i] = PMPoint( circleCenter + endPoint * r );
|
||
|
points[3*s_nCylinderLines + i] = PMPoint( m_location + endPoint * r );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( m_bAreaLight )
|
||
|
{
|
||
|
int s1, s2;
|
||
|
|
||
|
s1 = m_areaSize1;
|
||
|
s2 = m_areaSize2;
|
||
|
if( s1 < 1 ) s1 = 1;
|
||
|
if( s2 < 1 ) s2 = 1;
|
||
|
|
||
|
if( ( s1 > 1 ) || ( s2 > 1 ) )
|
||
|
{
|
||
|
int x, y, h;
|
||
|
int ps, ls;
|
||
|
PMVector bp;
|
||
|
|
||
|
PMPointArray& points = m_pViewStructure->points( );
|
||
|
PMLineArray& lines = m_pViewStructure->lines( );
|
||
|
points.detach( );
|
||
|
lines.detach( );
|
||
|
|
||
|
ps = points.size( );
|
||
|
ls = lines.size( );
|
||
|
points.resize( ps + s1*s2 );
|
||
|
lines.resize( ls + s1*(s2-1) + s2*(s1-1) );
|
||
|
|
||
|
if( s1 == 1 )
|
||
|
{
|
||
|
bp = m_location - m_areaAxis2/2;
|
||
|
for( y = 0; y < s2; y++ )
|
||
|
points[ps + y] = PMPoint( bp + m_areaAxis2
|
||
|
* ( (double)y/(double)(s2-1) ) );
|
||
|
for( y = 0; y < ( s2-1 ); y++ )
|
||
|
lines[ls+y] = PMLine( ps + y, ps + y+1 );
|
||
|
}
|
||
|
else if( s2 == 1 )
|
||
|
{
|
||
|
bp = m_location - m_areaAxis1/2;
|
||
|
for( x = 0; x < s1; x++ )
|
||
|
points[ps + x] = PMPoint( bp + m_areaAxis1
|
||
|
* ( (double)x/(double)(s1-1) ) );
|
||
|
for( x = 0; x < ( s1-1 ); x++ )
|
||
|
lines[ls+x] = PMLine( ps + x, ps + x+1 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bp = m_location - m_areaAxis1/2 - m_areaAxis2/2;
|
||
|
|
||
|
if ( m_areaType == Rectangular || s1 < 2 || s2 < 2 )
|
||
|
{
|
||
|
for( x = 0; x < s1; x++ )
|
||
|
for( y = 0; y < s2; y++ )
|
||
|
points[ps + y*s1 + x] =
|
||
|
PMPoint( bp + m_areaAxis1 * ( (double)x/(double)(s1-1) )
|
||
|
+ m_areaAxis2 * ( (double)y/(double)(s2-1) ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
double stepX = ( 2.0 / (double)(s1-1) );
|
||
|
double stepY = ( 2.0 / (double)(s2-1) );
|
||
|
double doubleX, doubleY, xSqr, scaleFactor;
|
||
|
|
||
|
for ( x = 0; x < s1; ++x )
|
||
|
{
|
||
|
doubleX = ( (double)x * stepX ) - 1.0;
|
||
|
xSqr = doubleX * doubleX;
|
||
|
for ( y = 0; y < s2; ++y )
|
||
|
{
|
||
|
doubleY = ( (double)y * stepY ) - 1.0;
|
||
|
|
||
|
if ( doubleX == 0.0 && doubleY == 0.0 )
|
||
|
scaleFactor = 1.0;
|
||
|
else
|
||
|
{
|
||
|
if ( fabs( doubleX ) > fabs( doubleY ) )
|
||
|
scaleFactor = fabs( doubleX );
|
||
|
else
|
||
|
scaleFactor = fabs( doubleY );
|
||
|
scaleFactor /= sqrt( xSqr + doubleY * doubleY );
|
||
|
}
|
||
|
|
||
|
points[ps + y*s1 + x] =
|
||
|
PMPoint( bp + m_areaAxis1 *
|
||
|
( ( ( doubleX * scaleFactor ) / 2.0 ) + 0.5 )
|
||
|
+ m_areaAxis2 *
|
||
|
( ( ( doubleY * scaleFactor ) / 2.0 ) + 0.5 ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for( x = 0; x < s1; x++ )
|
||
|
{
|
||
|
for( y = 0; y < (s2-1); y++ )
|
||
|
{
|
||
|
h = ps + x + s1*y;
|
||
|
lines[ls + x*(s2-1) + y] = PMLine( h, h+s1 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ls += s1*(s2-1);
|
||
|
for( y = 0; y < s2; y++ )
|
||
|
{
|
||
|
for( x = 0; x < (s1-1); x++ )
|
||
|
{
|
||
|
h = ps + x + s1*y;
|
||
|
lines[ls + y*(s1-1) + x] = PMLine( h, h+1 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PMViewStructure* PMLight::defaultPointStructure( ) const
|
||
|
{
|
||
|
if( !s_pDefaultPointStructure )
|
||
|
{
|
||
|
s_pDefaultPointStructure = new PMViewStructure( 14, 7 );
|
||
|
// PMPointArray& points = s_pDefaultPointStructure->points( );
|
||
|
PMLineArray& lines = s_pDefaultPointStructure->lines( );
|
||
|
|
||
|
lines[0] = PMLine( 0, 1 );
|
||
|
lines[1] = PMLine( 2, 3 );
|
||
|
lines[2] = PMLine( 4, 5 );
|
||
|
lines[3] = PMLine( 6, 7 );
|
||
|
lines[4] = PMLine( 8, 9 );
|
||
|
lines[5] = PMLine( 10, 11 );
|
||
|
lines[6] = PMLine( 12, 13 );
|
||
|
}
|
||
|
return s_pDefaultPointStructure;
|
||
|
}
|
||
|
|
||
|
PMViewStructure* PMLight::defaultSpotStructure( ) const
|
||
|
{
|
||
|
if( !s_pDefaultSpotStructure )
|
||
|
{
|
||
|
s_pDefaultSpotStructure = new PMViewStructure( s_nSpotLines * 2 + 2, s_nSpotLines * 3 + 1 );
|
||
|
// PMPointArray& points = s_pDefaultSpotStructure->points( );
|
||
|
PMLineArray& lines = s_pDefaultSpotStructure->lines( );
|
||
|
|
||
|
int i;
|
||
|
for( i = 0; i < s_nSpotLines; i++ )
|
||
|
{
|
||
|
lines[i] = PMLine( 0, i+1 );
|
||
|
lines[s_nSpotLines + i] = PMLine( i+1, i+2 );
|
||
|
lines[2*s_nSpotLines + i] = PMLine( s_nSpotLines + i+1,
|
||
|
s_nSpotLines + i+2 );
|
||
|
}
|
||
|
// fix for the last line
|
||
|
lines[2*s_nSpotLines - 1] = PMLine( 1, s_nSpotLines );
|
||
|
lines[3*s_nSpotLines - 1] = PMLine( s_nSpotLines + 1, s_nSpotLines*2 );
|
||
|
lines[3*s_nSpotLines] = PMLine( 0, s_nSpotLines*2 + 1 );
|
||
|
}
|
||
|
return s_pDefaultSpotStructure;
|
||
|
}
|
||
|
|
||
|
PMViewStructure* PMLight::defaultCylindricalStructure( ) const
|
||
|
{
|
||
|
if( !s_pDefaultCylindricalStructure )
|
||
|
{
|
||
|
s_pDefaultCylindricalStructure = new PMViewStructure( s_nCylinderLines * 4 + 2, s_nCylinderLines * 5 + 1 );
|
||
|
// PMPointArray& points = s_pDefaultCylindricalStructure->points( );
|
||
|
PMLineArray& lines = s_pDefaultCylindricalStructure->lines( );
|
||
|
|
||
|
int i;
|
||
|
for( i = 0; i < s_nCylinderLines; i++ )
|
||
|
{
|
||
|
lines[i] = PMLine( i, i+1 );
|
||
|
lines[s_nCylinderLines + i] = PMLine( i + s_nCylinderLines,
|
||
|
i + s_nCylinderLines + 1 );
|
||
|
lines[2*s_nCylinderLines + i] = PMLine( i + 2*s_nCylinderLines,
|
||
|
i + 2*s_nCylinderLines + 1 );
|
||
|
lines[3*s_nCylinderLines + i] = PMLine( i + 3*s_nCylinderLines,
|
||
|
i + 3*s_nCylinderLines + 1 );
|
||
|
lines[4*s_nCylinderLines + i] = PMLine( i, i + s_nCylinderLines );
|
||
|
}
|
||
|
// fix for some lines
|
||
|
lines[s_nCylinderLines-1] = PMLine( 0, s_nCylinderLines - 1 );
|
||
|
lines[2*s_nCylinderLines-1] = PMLine( s_nCylinderLines,
|
||
|
2*s_nCylinderLines - 1 );
|
||
|
lines[3*s_nCylinderLines-1] = PMLine( 2*s_nCylinderLines,
|
||
|
3*s_nCylinderLines - 1 );
|
||
|
lines[4*s_nCylinderLines-1] = PMLine( 3*s_nCylinderLines,
|
||
|
4*s_nCylinderLines - 1 );
|
||
|
lines[5*s_nCylinderLines] = PMLine( 4*s_nCylinderLines,
|
||
|
4*s_nCylinderLines + 1 );
|
||
|
}
|
||
|
return s_pDefaultCylindricalStructure;
|
||
|
}
|
||
|
|
||
|
void PMLight::controlPoints( PMControlPointList& list )
|
||
|
{
|
||
|
list.append( new PM3DControlPoint( m_location, PMLocationID, i18n( "Location" ) ) );
|
||
|
if( ( m_type == SpotLight ) || ( m_type == CylinderLight ) )
|
||
|
list.append( new PM3DControlPoint( m_pointAt, PMPointAtID, i18n( "Point at" ) ) );
|
||
|
}
|
||
|
|
||
|
void PMLight::controlPointsChanged( PMControlPointList& list )
|
||
|
{
|
||
|
PMControlPoint* p;
|
||
|
|
||
|
for( p = list.first( ); p; p = list.next( ) )
|
||
|
{
|
||
|
if( p->changed( ) )
|
||
|
{
|
||
|
switch( p->id( ) )
|
||
|
{
|
||
|
case PMLocationID:
|
||
|
setLocation( ( ( PM3DControlPoint* ) p )->point( ) );
|
||
|
break;
|
||
|
case PMPointAtID:
|
||
|
setPointAt( ( ( PM3DControlPoint* ) p )->point( ) );
|
||
|
break;
|
||
|
default:
|
||
|
kdError( PMArea ) << "Wrong ID in PMLight::controlPointsChanged\n";
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PMLight::cleanUp( ) const
|
||
|
{
|
||
|
if( s_pDefaultPointStructure )
|
||
|
delete s_pDefaultPointStructure;
|
||
|
s_pDefaultPointStructure = 0;
|
||
|
if( s_pDefaultSpotStructure )
|
||
|
delete s_pDefaultSpotStructure;
|
||
|
s_pDefaultSpotStructure = 0;
|
||
|
if( s_pDefaultCylindricalStructure )
|
||
|
delete s_pDefaultCylindricalStructure;
|
||
|
s_pDefaultCylindricalStructure = 0;
|
||
|
if( s_pMetaObject )
|
||
|
{
|
||
|
delete s_pMetaObject;
|
||
|
s_pMetaObject = 0;
|
||
|
}
|
||
|
Base::cleanUp( );
|
||
|
}
|