diff --git a/include/IECore/RefCounted.h b/include/IECore/RefCounted.h index 051d9f2257..ef943eb058 100644 --- a/include/IECore/RefCounted.h +++ b/include/IECore/RefCounted.h @@ -169,6 +169,16 @@ inline void intrusive_ptr_release( const IECore::RefCounted *r ) r->removeRef(); } +/// Implementation of tbb_hasher to allow intrusive_ptrs to be used +/// with tbb_concurrent_* containers. +template +inline size_t tbb_hasher( const boost::intrusive_ptr &ptr ) +{ + // This is the same as what tbb uses for raw pointers + const size_t h = reinterpret_cast( ptr.get() ); + return (h >> 3) ^ h; +} + } // namespace IECore diff --git a/include/IECoreGL/HitRecord.h b/include/IECoreGL/HitRecord.h index 36ea3139a2..8878ca5e35 100644 --- a/include/IECoreGL/HitRecord.h +++ b/include/IECoreGL/HitRecord.h @@ -53,18 +53,15 @@ class HitRecord /// for the OpenGL select buffer. Raises an exception if /// more than one name is specified in the record. HitRecord( const GLuint *hitRecord ); - HitRecord( float dMin, float dMax, const IECore::InternedString &primName ); + HitRecord( float dMin, float dMax, GLuint name ); /// The minimum and maximum depths of the hit, normalised /// in the 0-1 range between the near and far clipping planes. float depthMin; float depthMax; - /// Unlike the gl hit record, the HitRecord stores - /// only one name - this is because the NameStateComponent - /// and the Renderer "name" attribute specify only a single - /// name for each primitive rendered. - IECore::InternedString name; + /// Identifier for the hit object. + GLuint name; /// Performs comparison based on the depth.min member. bool operator < ( const HitRecord &other ) const; diff --git a/include/IECoreGL/Selector.h b/include/IECoreGL/Selector.h index 2cd0640b05..d44da229fd 100644 --- a/include/IECoreGL/Selector.h +++ b/include/IECoreGL/Selector.h @@ -107,6 +107,10 @@ class Selector : boost::noncopyable /// If rendering a Scene, this will be called automatically /// by the NameStateComponents within the Scene. void loadName( GLuint name ); + /// Generates a new name (by incrementing an internal counter) and + /// loads and returns it. No guarantee is made that generated names + /// will not clash with names loaded explicitly with the method above. + GLuint loadName(); /// A State that should be used as the base state for /// selection drawing. diff --git a/include/IECoreGL/State.h b/include/IECoreGL/State.h index f2ffb385fe..3d6afc73b3 100644 --- a/include/IECoreGL/State.h +++ b/include/IECoreGL/State.h @@ -62,12 +62,16 @@ class State : public Bindable /// new bindings. It is the caller's responsibility to keep both arguments /// alive until after destruction of the ScopedBinding. ScopedBinding( const State &s, State ¤tState ); + /// As above, but does nothing if bind is false. + ScopedBinding( const State &s, State ¤tState, bool bind ); /// Reverts the state changes and modifications to currentState /// made by the constructor. ~ScopedBinding(); private : + void init( const State &s, bool bind = true ); + State &m_currentState; std::vector m_savedComponents; diff --git a/include/IECoreGL/ToGLStateConverter.h b/include/IECoreGL/ToGLStateConverter.h new file mode 100644 index 0000000000..d4c1a448b9 --- /dev/null +++ b/include/IECoreGL/ToGLStateConverter.h @@ -0,0 +1,84 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2014, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of Image Engine Design nor the names of any +// other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef IECOREGL_TOGLSTATECONVERTER_H +#define IECOREGL_TOGLSTATECONVERTER_H + +#include "IECoreGL/ToGLConverter.h" + +namespace IECore +{ + +IE_CORE_FORWARDDECLARE( CompoundObject ) +IE_CORE_FORWARDDECLARE( Data ) + +} // namespace IECore + +namespace IECoreGL +{ + +IE_CORE_FORWARDDECLARE( State ) +IE_CORE_FORWARDDECLARE( StateComponent ) + +/// Converts IECore::CompoundObject objects containing shaders and attributes +/// into IECoreGL::State objects. +/// \ingroup conversionGroup +class ToGLStateConverter : public ToGLConverter +{ + + public : + + typedef IECore::CompoundObject InputType; + typedef IECoreGL::State ResultType; + + IE_CORE_DECLARERUNTIMETYPEDEXTENSION( IECoreGL::ToGLStateConverter, ToGLStateConverterTypeId, ToGLConverter ); + + ToGLStateConverter( IECore::ConstCompoundObjectPtr toConvert = NULL ); + virtual ~ToGLStateConverter(); + + protected : + + virtual IECore::RunTimeTypedPtr doConversion( IECore::ConstObjectPtr src, IECore::ConstCompoundObjectPtr operands ) const; + + private : + + static ConverterDescription g_description; + +}; + +IE_CORE_DECLAREPTR( ToGLStateConverter ); + +} // namespace IECoreGL + +#endif // IECOREGL_TOGLSTATECONVERTER_H diff --git a/include/IECoreGL/TypeIds.h b/include/IECoreGL/TypeIds.h index 83b81b4c34..5a3c30b288 100644 --- a/include/IECoreGL/TypeIds.h +++ b/include/IECoreGL/TypeIds.h @@ -121,6 +121,7 @@ enum TypeId ToGLBufferConverterTypeId = 105078, UIntTextureTypeId = 105079, PrimitiveSelectableTypeId = 105080, + ToGLStateConverterTypeId = 105081, LastCoreGLTypeId = 105999, }; diff --git a/include/IECoreGL/TextureUnits.h b/include/IECoreGL/bindings/CurvesPrimitiveBinding.h similarity index 78% rename from include/IECoreGL/TextureUnits.h rename to include/IECoreGL/bindings/CurvesPrimitiveBinding.h index 4a7d541a43..77b3a039dd 100644 --- a/include/IECoreGL/TextureUnits.h +++ b/include/IECoreGL/bindings/CurvesPrimitiveBinding.h @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2007, Image Engine Design Inc. All rights reserved. +// Copyright (c) 2014, Image Engine Design Inc. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -32,23 +32,14 @@ // ////////////////////////////////////////////////////////////////////////// -#ifndef IECOREGL_TEXTUREUNITS_H -#define IECOREGL_TEXTUREUNITS_H - -#include "IECoreGL/GL.h" - -#include +#ifndef IECOREGL_CURVESPRIMITIVEBINDING_H +#define IECOREGL_CURVESPRIMITIVEBINDING_H namespace IECoreGL { -/// Returns a vector containing GL_TEXTURE0, GL_TEXTURE1, ... -/// GL_TEXTUREN for all texture unit enums up to -/// GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1. That way you can -/// actually program texture code like a grown up, -/// using like loops and stuff. -const std::vector &textureUnits(); +void bindCurvesPrimitive(); } // namespace IECoreGL -#endif // IECOREGL_TEXTUREUNITS_H +#endif // IECOREGL_CURVESPRIMITIVEBINDING_H diff --git a/include/IECoreGL/bindings/ToGLStateConverterBinding.h b/include/IECoreGL/bindings/ToGLStateConverterBinding.h new file mode 100644 index 0000000000..e737d541b7 --- /dev/null +++ b/include/IECoreGL/bindings/ToGLStateConverterBinding.h @@ -0,0 +1,45 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2014, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of Image Engine Design nor the names of any +// other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef IECOREGL_TOGLSTATECONVERTERBINDING_H +#define IECOREGL_TOGLSTATECONVERTERBINDING_H + +namespace IECoreGL +{ + +void bindToGLStateConverter(); + +} // namespace IECoreGL + +#endif // IECOREGL_TOGLSTATECONVERTERBINDING_H diff --git a/src/IECoreGL/HitRecord.cpp b/src/IECoreGL/HitRecord.cpp index 3d092b0271..dcf11bb1b1 100644 --- a/src/IECoreGL/HitRecord.cpp +++ b/src/IECoreGL/HitRecord.cpp @@ -46,7 +46,7 @@ using namespace IECoreGL; HitRecord::HitRecord( const GLuint *hitRecord ) : depthMin( (float)hitRecord[1]/(float)Imath::limits::max() ), depthMax( (float)hitRecord[2]/(float)Imath::limits::max() ), - name( NameStateComponent::nameFromGLName( hitRecord[3] ) ) + name( hitRecord[3] ) { if( hitRecord[0] != 1 ) @@ -55,8 +55,8 @@ HitRecord::HitRecord( const GLuint *hitRecord ) } } -HitRecord::HitRecord( float dMin, float dMax, const IECore::InternedString &primName ) - : depthMin( dMin ), depthMax( dMax ), name( primName ) +HitRecord::HitRecord( float dMin, float dMax, GLuint name ) + : depthMin( dMin ), depthMax( dMax ), name( name ) { } diff --git a/src/IECoreGL/Primitive.cpp b/src/IECoreGL/Primitive.cpp index 05f7054b65..1c61bbdfd4 100644 --- a/src/IECoreGL/Primitive.cpp +++ b/src/IECoreGL/Primitive.cpp @@ -45,7 +45,6 @@ #include "IECoreGL/TypedStateComponent.h" #include "IECoreGL/ShaderStateComponent.h" #include "IECoreGL/Shader.h" -#include "IECoreGL/TextureUnits.h" #include "IECoreGL/NumericTraits.h" #include "IECoreGL/UniformFunctions.h" #include "IECoreGL/CachedConverter.h" diff --git a/src/IECoreGL/Selector.cpp b/src/IECoreGL/Selector.cpp index 39b27dcf88..b5b295f151 100644 --- a/src/IECoreGL/Selector.cpp +++ b/src/IECoreGL/Selector.cpp @@ -66,7 +66,7 @@ class Selector::Implementation : public IECore::RefCounted public : Implementation( Selector *parent, const Imath::Box2f ®ion, Mode mode, std::vector &hits ) - : m_mode( mode ), m_hits( hits ), m_baseState( new State( true /* complete */ ) ), m_currentName( 0 ), m_currentIDShader( NULL ) + : m_mode( mode ), m_hits( hits ), m_baseState( new State( true /* complete */ ) ), m_currentName( 0 ), m_nextGeneratedName( 1 ), m_currentIDShader( NULL ) { // we don't want preexisting errors to trigger exceptions // from error checking code in the begin*() methods, because @@ -190,6 +190,13 @@ class Selector::Implementation : public IECore::RefCounted m_currentName = name; } + GLuint loadName() + { + const GLuint name = m_nextGeneratedName++; + loadName( name ); + return name; + } + State *baseState() { return m_baseState.get(); @@ -256,6 +263,7 @@ class Selector::Implementation : public IECore::RefCounted std::vector &m_hits; StatePtr m_baseState; GLuint m_currentName; + GLuint m_nextGeneratedName; static Selector *g_currentSelector; @@ -398,7 +406,7 @@ class Selector::Implementation : public IECore::RefCounted std::map::iterator it = idRecords.find( ids[i] ); if( it == idRecords.end() ) { - HitRecord r( Imath::limits::max(), Imath::limits::min(), NameStateComponent::nameFromGLName( ids[i] ) ); + HitRecord r( Imath::limits::max(), Imath::limits::min(), ids[i] ); it = idRecords.insert( std::pair( ids[i], r ) ).first; } it->second.depthMin = std::min( it->second.depthMin, z[i] ); @@ -461,7 +469,7 @@ class Selector::Implementation : public IECore::RefCounted glGetQueryObjectuivARB( m_queries[i], GL_QUERY_RESULT_ARB, &samplesPassed ); if( samplesPassed ) { - m_hits.push_back( HitRecord( 0, 0, NameStateComponent::nameFromGLName( m_queryNames[i] ) ) ); + m_hits.push_back( HitRecord( 0, 0, m_queryNames[i] ) ); } } @@ -501,6 +509,11 @@ void Selector::loadName( GLuint name ) m_implementation->loadName( name ); } +GLuint Selector::loadName() +{ + return m_implementation->loadName(); +} + State *Selector::baseState() { return m_implementation->baseState(); diff --git a/src/IECoreGL/Shader.cpp b/src/IECoreGL/Shader.cpp index 594a61b531..9878f2578d 100644 --- a/src/IECoreGL/Shader.cpp +++ b/src/IECoreGL/Shader.cpp @@ -51,7 +51,6 @@ #include "IECoreGL/Buffer.h" #include "IECoreGL/NumericTraits.h" #include "IECoreGL/CachedConverter.h" -#include "IECoreGL/TextureUnits.h" #include "IECoreGL/Selector.h" using namespace std; @@ -517,7 +516,7 @@ class Shader::Setup::MemberData : public IECore::RefCounted virtual void bind() { - glActiveTexture( textureUnits()[m_textureUnit] ); + glActiveTexture( GL_TEXTURE0 + m_textureUnit ); glGetIntegerv( GL_TEXTURE_BINDING_2D, &m_previousTexture ); if( m_texture ) { @@ -532,7 +531,7 @@ class Shader::Setup::MemberData : public IECore::RefCounted virtual void unbind() { - glActiveTexture( textureUnits()[m_textureUnit] ); + glActiveTexture( GL_TEXTURE0 + m_textureUnit ); glBindTexture( GL_TEXTURE_2D, m_previousTexture ); } diff --git a/src/IECoreGL/ShaderStateComponent.cpp b/src/IECoreGL/ShaderStateComponent.cpp index d8a8052d85..a6342b2143 100644 --- a/src/IECoreGL/ShaderStateComponent.cpp +++ b/src/IECoreGL/ShaderStateComponent.cpp @@ -92,6 +92,10 @@ class ShaderStateComponent::Implementation : public IECore::RefCounted void addParametersToShaderSetup( Shader::Setup *shaderSetup ) const { + if( !m_parameterMap ) + { + return; + } const IECore::CompoundObject::ObjectMap &d = m_parameterMap->members(); for( IECore::CompoundObject::ObjectMap::const_iterator it = d.begin(), eIt = d.end(); it != eIt; it++ ) { diff --git a/src/IECoreGL/State.cpp b/src/IECoreGL/State.cpp index e1bab2d86c..efaffee93c 100644 --- a/src/IECoreGL/State.cpp +++ b/src/IECoreGL/State.cpp @@ -186,6 +186,22 @@ class State::Implementation : public IECore::RefCounted State::ScopedBinding::ScopedBinding( const State &s, State ¤tState ) : m_currentState( currentState ) { + init( s ); +} + +State::ScopedBinding::ScopedBinding( const State &s, State ¤tState, bool bind ) + : m_currentState( currentState ) +{ + init( s, bind ); +} + +void State::ScopedBinding::init( const State &s, bool bind ) +{ + if( !bind ) + { + return; + } + m_savedComponents.reserve( s.m_implementation->m_components.size() ); for( Implementation::ComponentMap::const_iterator it=s.m_implementation->m_components.begin(); it!=s.m_implementation->m_components.end(); it++ ) diff --git a/src/IECoreGL/TextPrimitive.cpp b/src/IECoreGL/TextPrimitive.cpp index a62935f802..d414ab0fe8 100644 --- a/src/IECoreGL/TextPrimitive.cpp +++ b/src/IECoreGL/TextPrimitive.cpp @@ -38,7 +38,6 @@ #include "IECoreGL/State.h" #include "IECoreGL/Font.h" #include "IECoreGL/GL.h" -#include "IECoreGL/TextureUnits.h" using namespace IECoreGL; using namespace Imath; @@ -140,7 +139,7 @@ void TextPrimitive::renderSprites( State *state ) const glEnable( GL_TEXTURE_2D ); glDisable( GL_LIGHTING ); /// \todo Perhaps we could support lighting even in this mode? - glActiveTexture( textureUnits()[0] ); + glActiveTexture( GL_TEXTURE0 ); m_font->texture()->bind(); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); diff --git a/src/IECoreGL/ToGLStateConverter.cpp b/src/IECoreGL/ToGLStateConverter.cpp new file mode 100644 index 0000000000..3a84e163ed --- /dev/null +++ b/src/IECoreGL/ToGLStateConverter.cpp @@ -0,0 +1,218 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2014, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of Image Engine Design nor the names of any +// other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#include "IECore/CompoundObject.h" +#include "IECore/SimpleTypedData.h" +#include "IECore/Shader.h" +#include "IECore/ObjectVector.h" + +#include "IECoreGL/ToGLStateConverter.h" +#include "IECoreGL/Primitive.h" +#include "IECoreGL/State.h" +#include "IECoreGL/PointsPrimitive.h" +#include "IECoreGL/CurvesPrimitive.h" +#include "IECoreGL/ShaderStateComponent.h" +#include "IECoreGL/ShaderLoader.h" +#include "IECoreGL/TextureLoader.h" + +using namespace IECore; +using namespace IECoreGL; + +////////////////////////////////////////////////////////////////////////// +// Individual state converters +////////////////////////////////////////////////////////////////////////// + +namespace +{ + +template +StateComponentPtr attributeToTypedState( const IECore::Object *attribute ) +{ + typedef IECore::TypedData DataType; + const DataType *d = runTimeCast( attribute ); + if( !d ) + { + throw Exception( boost::str( boost::format( "Expected data of type \"%s\"" ) % DataType::staticTypeName() ) ); + } + + return new T( d->readable() ); +} + +StateComponentPtr attributeToUseGLPointsState( const IECore::Object *attribute ) +{ + const StringData *d = runTimeCast( attribute ); + if( !d ) + { + throw Exception( "Expected data of type StringData" ); + } + + GLPointsUsage u; + const std::string &v = d->readable(); + if( v=="forGLPoints" ) + { + u = ForPointsOnly; + } + else if( v=="forParticlesAndDisks" ) + { + u = ForPointsAndDisks; + } + else if( v=="forAll" ) + { + u = ForAll; + } + else + { + throw IECore::Exception( boost::str( boost::format( "Unsupported value \"%s\"." ) % v ) ); + } + + return new PointsPrimitive::UseGLPoints( u ); +} + +StateComponentPtr attributeToShaderState( const IECore::Object *attribute ) +{ + const IECore::Shader *shader = runTimeCast( attribute ); + if( !shader ) + { + const ObjectVector *o = runTimeCast( attribute ); + if( o && o->members().size() ) + { + shader = runTimeCast( o->members()[0].get() ); + } + } + if( !shader ) + { + throw Exception( "Expected a Shader" ); + } + + const StringData *vertexSourceData = shader->parametersData()->member( "gl:vertexSource" ); + const StringData *geometrySourceData = shader->parametersData()->member( "gl:geometrySource" ); + const StringData *fragmentSourceData = shader->parametersData()->member( "gl:fragmentSource" ); + + std::string vertexSource = vertexSourceData ? vertexSourceData->readable() : ""; + std::string geometrySource = geometrySourceData ? geometrySourceData->readable() : ""; + std::string fragmentSource = fragmentSourceData ? fragmentSourceData->readable() : ""; + + if( vertexSource == "" && geometrySource == "" && fragmentSource == "" ) + { + ShaderLoader::defaultShaderLoader()->loadSource( shader->getName(), vertexSource, geometrySource, fragmentSource ); + } + + CompoundObjectPtr parametersData = new CompoundObject; + for( CompoundDataMap::const_iterator it=shader->parameters().begin(); it!=shader->parameters().end(); it++ ) + { + if( it->first!="gl:fragmentSource" && it->first!="gl:geometrySource" && it->first!="gl:vertexSource" ) + { + parametersData->members()[it->first] = it->second; + } + } + + return new ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), vertexSource, geometrySource, fragmentSource, parametersData ); +} + +typedef StateComponentPtr (*AttributeToState)( const IECore::Object *attribute ); +typedef std::map AttributeToStateMap; + +const AttributeToStateMap &attributeToStateMap() +{ + static AttributeToStateMap m; + if( !m.size() ) + { + m["gl:primitive:wireframe"] = attributeToTypedState; + m["gl:primitive:wireframeWidth"] = attributeToTypedState; + m["gl:primitive:bound"] = attributeToTypedState; + m["gl:primitive:solid"] = attributeToTypedState; + m["gl:primitive:outline"] = attributeToTypedState; + m["gl:primitive:outlineWidth"] = attributeToTypedState; + m["gl:primitive:points"] = attributeToTypedState; + m["gl:primitive:pointWidth"] = attributeToTypedState; + m["gl:primitive:wireframeColor"] = attributeToTypedState; + m["gl:primitive:boundColor"] = attributeToTypedState; + m["gl:primitive:outlineColor"] = attributeToTypedState; + m["gl:primitive:pointColor"] = attributeToTypedState; + m["gl:pointsPrimitive:useGLPoints"] = attributeToUseGLPointsState; + m["gl:pointsPrimitive:glPointWidth"] = attributeToTypedState; + m["doubleSided"] = attributeToTypedState; + m["gl:curvesPrimitive:useGLLines"] = attributeToTypedState; + m["gl:curvesPrimitive:glLineWidth"] = attributeToTypedState; + m["gl:curvesPrimitive:ignoreBasis"] = attributeToTypedState; + m["gl:smoothing:points"] = attributeToTypedState; + m["gl:smoothing:lines"] = attributeToTypedState; + m["gl:smoothing:polygons"] = attributeToTypedState; + m["gl:surface"] = attributeToShaderState; + } + return m; +} + +} // namespace + +////////////////////////////////////////////////////////////////////////// +// ToGLStateConverter implementation +////////////////////////////////////////////////////////////////////////// + +IE_CORE_DEFINERUNTIMETYPED( ToGLStateConverter ); + +ToGLConverter::ConverterDescription ToGLStateConverter::g_description; + +ToGLStateConverter::ToGLStateConverter( IECore::ConstCompoundObjectPtr toConvert ) + : ToGLConverter( "Converts IECore::CompoundObject objects to IECoreGL::State objects.", IECore::CompoundObjectTypeId ) +{ + srcParameter()->setValue( boost::const_pointer_cast( toConvert ) ); +} + +ToGLStateConverter::~ToGLStateConverter() +{ +} + +IECore::RunTimeTypedPtr ToGLStateConverter::doConversion( IECore::ConstObjectPtr src, IECore::ConstCompoundObjectPtr operands ) const +{ + const CompoundObject *co = runTimeCast( src.get() ); + if( !co ) + { + throw Exception( "Expected a CompoundObject" ); + } + + const AttributeToStateMap &m = attributeToStateMap(); + + const StatePtr result = new State( false ); + for( CompoundObject::ObjectMap::const_iterator it = co->members().begin(), eIt = co->members().end(); it != eIt; ++it ) + { + AttributeToStateMap::const_iterator mIt = m.find( it->first ); + if( mIt != m.end() ) + { + StateComponentPtr s = mIt->second( it->second.get() ); + result->add( s ); + } + } + return result; +} diff --git a/src/IECoreGL/TextureUnits.cpp b/src/IECoreGL/bindings/CurvesPrimitiveBinding.cpp similarity index 57% rename from src/IECoreGL/TextureUnits.cpp rename to src/IECoreGL/bindings/CurvesPrimitiveBinding.cpp index 4ae4d8308f..5e5bc95e43 100644 --- a/src/IECoreGL/TextureUnits.cpp +++ b/src/IECoreGL/bindings/CurvesPrimitiveBinding.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2007, Image Engine Design Inc. All rights reserved. +// Copyright (c) 2014, Image Engine Design Inc. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -32,48 +32,42 @@ // ////////////////////////////////////////////////////////////////////////// -#include "IECoreGL/TextureUnits.h" +#include -const std::vector &IECoreGL::textureUnits() +#include "IECorePython/RunTimeTypedBinding.h" + +#include "IECoreGL/CurvesPrimitive.h" + +#include "IECoreGL/bindings/CurvesPrimitiveBinding.h" +#include "IECoreGL/bindings/TypedStateComponentBinding.inl" + +using namespace boost::python; + +namespace IECoreGL { - static std::vector t; - if( !t.size() ) - { - t.push_back( GL_TEXTURE0 ); - t.push_back( GL_TEXTURE1 ); - t.push_back( GL_TEXTURE2 ); - t.push_back( GL_TEXTURE3 ); - t.push_back( GL_TEXTURE4 ); - t.push_back( GL_TEXTURE5 ); - t.push_back( GL_TEXTURE6 ); - t.push_back( GL_TEXTURE7 ); - t.push_back( GL_TEXTURE8 ); - t.push_back( GL_TEXTURE9 ); - t.push_back( GL_TEXTURE10 ); - t.push_back( GL_TEXTURE11 ); - t.push_back( GL_TEXTURE12 ); - t.push_back( GL_TEXTURE13 ); - t.push_back( GL_TEXTURE14 ); - t.push_back( GL_TEXTURE15 ); - t.push_back( GL_TEXTURE16 ); - t.push_back( GL_TEXTURE17 ); - t.push_back( GL_TEXTURE18 ); - t.push_back( GL_TEXTURE19 ); - t.push_back( GL_TEXTURE20 ); - t.push_back( GL_TEXTURE21 ); - t.push_back( GL_TEXTURE22 ); - t.push_back( GL_TEXTURE23 ); - t.push_back( GL_TEXTURE24 ); - t.push_back( GL_TEXTURE25 ); - t.push_back( GL_TEXTURE26 ); - t.push_back( GL_TEXTURE27 ); - t.push_back( GL_TEXTURE28 ); - t.push_back( GL_TEXTURE29 ); - t.push_back( GL_TEXTURE30 ); - t.push_back( GL_TEXTURE31 ); - GLint max = 0; - glGetIntegerv( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max ); - t.resize( max ); - } - return t; + +void bindCurvesPrimitive() +{ + scope s = IECorePython::RunTimeTypedClass() + .def( + init< + const IECore::CubicBasisf &, + bool, + IECore::ConstIntVectorDataPtr, + float + >( ( + arg_( "basis" ), + arg_( "periodic" ), + arg_( "vertsPerCurve" ), + arg_( "width" ) = 1.0f + ) ) + ) + ; + + bindTypedStateComponent( "IgnoreBasis" ); + bindTypedStateComponent( "UseGLLines" ); + bindTypedStateComponent( "GLLineWidth" ); + } + +} // namespace IECoreGL diff --git a/src/IECoreGL/bindings/HitRecordBinding.cpp b/src/IECoreGL/bindings/HitRecordBinding.cpp index 7457cbccc1..ef62f9443e 100644 --- a/src/IECoreGL/bindings/HitRecordBinding.cpp +++ b/src/IECoreGL/bindings/HitRecordBinding.cpp @@ -48,7 +48,7 @@ void bindHitRecord() { class_( "HitRecord", init() ) - .def( init() ) + .def( init() ) .def_readwrite( "depthMin", &HitRecord::depthMin ) .def_readwrite( "depthMax", &HitRecord::depthMax ) .def_readwrite( "name", &HitRecord::name ) diff --git a/src/IECoreGL/bindings/IECoreGLBinding.cpp b/src/IECoreGL/bindings/IECoreGLBinding.cpp index 9952d60b51..086a11a101 100644 --- a/src/IECoreGL/bindings/IECoreGLBinding.cpp +++ b/src/IECoreGL/bindings/IECoreGLBinding.cpp @@ -75,6 +75,8 @@ #include "IECoreGL/bindings/BufferBinding.h" #include "IECoreGL/bindings/SplineToGLTextureConverterBinding.h" #include "IECoreGL/bindings/ShaderStateComponentBinding.h" +#include "IECoreGL/bindings/CurvesPrimitiveBinding.h" +#include "IECoreGL/bindings/ToGLStateConverterBinding.h" using namespace IECoreGL; using namespace boost::python; @@ -117,6 +119,8 @@ BOOST_PYTHON_MODULE( _IECoreGL ) bindBuffer(); bindSplineToGLTextureConverter(); bindShaderStateComponent(); + bindCurvesPrimitive(); + bindToGLStateConverter(); #ifdef IECORE_WITH_FREETYPE diff --git a/src/IECoreGL/bindings/ToGLStateConverterBinding.cpp b/src/IECoreGL/bindings/ToGLStateConverterBinding.cpp new file mode 100644 index 0000000000..023d8c3a47 --- /dev/null +++ b/src/IECoreGL/bindings/ToGLStateConverterBinding.cpp @@ -0,0 +1,53 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2014, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of Image Engine Design nor the names of any +// other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#include "boost/python.hpp" + +#include "IECore/CompoundObject.h" + +#include "IECoreGL/ToGLStateConverter.h" +#include "IECoreGL/bindings/ToGLStateConverterBinding.h" + +#include "IECorePython/RunTimeTypedBinding.h" + +using namespace boost::python; +using namespace std; + + +void IECoreGL::bindToGLStateConverter() +{ + IECorePython::RunTimeTypedClass() + .def( init() ) + ; +} diff --git a/src/IECoreGL/bindings/TypedStateComponentBinding.cpp b/src/IECoreGL/bindings/TypedStateComponentBinding.cpp index 492f40c773..a53d342c62 100644 --- a/src/IECoreGL/bindings/TypedStateComponentBinding.cpp +++ b/src/IECoreGL/bindings/TypedStateComponentBinding.cpp @@ -65,6 +65,9 @@ void bindTypedStateComponents() bindTypedStateComponent< ProceduralThreadingStateComponent >( "ProceduralThreadingStateComponent" ); bindTypedStateComponent< CameraVisibilityStateComponent >( "CameraVisibilityStateComponent" ); bindTypedStateComponent< AutomaticInstancingStateComponent >( "AutomaticInstancingStateComponent" ); + bindTypedStateComponent< PointSmoothingStateComponent >( "PointSmoothingStateComponent" ); + bindTypedStateComponent< LineSmoothingStateComponent >( "LineSmoothingStateComponent" ); + bindTypedStateComponent< PolygonSmoothingStateComponent >( "PolygonSmoothingStateComponent" ); enum_( "GLPointsUsage" ) .value( "ForPointsOnly", ForPointsOnly ) diff --git a/src/IECoreMaya/ProceduralHolderUI.cpp b/src/IECoreMaya/ProceduralHolderUI.cpp index 127f4a7ba7..323ab71915 100644 --- a/src/IECoreMaya/ProceduralHolderUI.cpp +++ b/src/IECoreMaya/ProceduralHolderUI.cpp @@ -402,7 +402,9 @@ bool ProceduralHolderUI::select( MSelectInfo &selectInfo, MSelectionList &select depthMinIndex = componentIndices.length(); } - ProceduralHolder::ComponentsMap::const_iterator compIt = proceduralHolder->m_componentsMap.find( hits[i].name.value() ); + ProceduralHolder::ComponentsMap::const_iterator compIt = proceduralHolder->m_componentsMap.find( + IECoreGL::NameStateComponent::nameFromGLName( hits[i].name ) + ); assert( compIt != proceduralHolder->m_componentsMap.end() ); componentIndices.append( compIt->second.first ); } diff --git a/test/IECoreGL/All.py b/test/IECoreGL/All.py index 1e03242c41..dbf0a21e4f 100644 --- a/test/IECoreGL/All.py +++ b/test/IECoreGL/All.py @@ -67,6 +67,7 @@ from ShadingTest import ShadingTest from ShaderLoaderTest import ShaderLoaderTest from ShaderStateComponentTest import ShaderStateComponentTest +from ToGLStateConverterTest import ToGLStateConverterTest if IECore.withFreeType() : diff --git a/test/IECoreGL/HitRecord.py b/test/IECoreGL/HitRecord.py index 75318d2add..c377fc61f2 100644 --- a/test/IECoreGL/HitRecord.py +++ b/test/IECoreGL/HitRecord.py @@ -44,17 +44,17 @@ class TestHitRecord( unittest.TestCase ) : def test( self ) : - d = HitRecord( 1, 2, InternedString( "hello" ) ) + d = HitRecord( 1, 2, 1 ) self.assertEqual( d.depthMin, 1 ) self.assertEqual( d.depthMax, 2 ) - self.assertEqual( d.name, InternedString( "hello" ) ) + self.assertEqual( d.name, 1 ) - d2 = HitRecord( 1.5, 2, InternedString( "goodbye" ) ) + d2 = HitRecord( 1.5, 2, 2 ) self.assertEqual( d2.depthMin, 1.5 ) self.assertEqual( d2.depthMax, 2 ) - self.assertEqual( d2.name, InternedString( "goodbye" ) ) + self.assertEqual( d2.name, 2 ) self.assert_( d < d2 ) diff --git a/test/IECoreGL/Selection.py b/test/IECoreGL/Selection.py index 68791a74e9..5feae904f7 100644 --- a/test/IECoreGL/Selection.py +++ b/test/IECoreGL/Selection.py @@ -68,7 +68,7 @@ def testSelect( self ) : s.setCamera( IECoreGL.PerspectiveCamera() ) ss = s.select( IECoreGL.Selector.Mode.GLSelect, IECore.Box2f( IECore.V2f( 0 ), IECore.V2f( 1 ) ) ) - names = [ x.name.value() for x in ss ] + names = [ IECoreGL.NameStateComponent.nameFromGLName( x.name ) for x in ss ] self.assertEqual( len( names ), 3 ) self.assert_( "one" in names ) self.assert_( "two" in names ) @@ -109,19 +109,19 @@ def testRegionSelect( self ) : ss = s.select( IECoreGL.Selector.Mode.GLSelect, IECore.Box2f( IECore.V2f( 0, 0.5 ), IECore.V2f( 0.5, 1 ) ) ) self.assertEqual( len( ss ), 1 ) - self.assertEqual( ss[0].name.value(), "red" ) + self.assertEqual( IECoreGL.NameStateComponent.nameFromGLName( ss[0].name ), "red" ) ss = s.select( IECoreGL.Selector.Mode.GLSelect, IECore.Box2f( IECore.V2f( 0 ), IECore.V2f( 0.5 ) ) ) self.assertEqual( len( ss ), 1 ) - self.assertEqual( ss[0].name.value(), "green" ) + self.assertEqual( IECoreGL.NameStateComponent.nameFromGLName( ss[0].name ), "green" ) ss = s.select( IECoreGL.Selector.Mode.GLSelect, IECore.Box2f( IECore.V2f( 0.5, 0 ), IECore.V2f( 1, 0.5 ) ) ) self.assertEqual( len( ss ), 1 ) - self.assertEqual( ss[0].name.value(), "blue" ) + self.assertEqual( IECoreGL.NameStateComponent.nameFromGLName( ss[0].name ), "blue" ) ss = s.select( IECoreGL.Selector.Mode.GLSelect, IECore.Box2f( IECore.V2f( 0.5 ), IECore.V2f( 1 ) ) ) self.assertEqual( len( ss ), 1 ) - self.assertEqual( ss[0].name.value(), "white" ) + self.assertEqual( IECoreGL.NameStateComponent.nameFromGLName( ss[0].name ), "white" ) def testIDSelect( self ) : @@ -153,11 +153,11 @@ def testIDSelect( self ) : ss = s.select( IECoreGL.Selector.Mode.IDRender, IECore.Box2f( IECore.V2f( 0.25, 0.5 ), IECore.V2f( 0.26, 0.51 ) ) ) self.assertEqual( len( ss ), 1 ) - self.assertEqual( ss[0].name.value(), "frontLeft" ) + self.assertEqual( IECoreGL.NameStateComponent.nameFromGLName( ss[0].name ), "frontLeft" ) ss = s.select( IECoreGL.Selector.Mode.IDRender, IECore.Box2f( IECore.V2f( 0.75, 0.5 ), IECore.V2f( 0.76, 0.51 ) ) ) self.assertEqual( len( ss ), 1 ) - self.assertEqual( ss[0].name.value(), "frontRight" ) + self.assertEqual( IECoreGL.NameStateComponent.nameFromGLName( ss[0].name ), "frontRight" ) def testIDSelectDepths( self ) : @@ -176,11 +176,11 @@ def testIDSelectDepths( self ) : s1 = scene.select( IECoreGL.Selector.Mode.GLSelect, IECore.Box2f( IECore.V2f( 0 ), IECore.V2f( 1 ) ) ) self.assertEqual( len( s1 ), 1 ) - self.assertEqual( s1[0].name.value(), "ball" ) + self.assertEqual( IECoreGL.NameStateComponent.nameFromGLName( s1[0].name ), "ball" ) s2 = scene.select( IECoreGL.Selector.Mode.IDRender, IECore.Box2f( IECore.V2f( 0 ), IECore.V2f( 1 ) ) ) self.assertEqual( len( s2 ), 1 ) - self.assertEqual( s2[0].name.value(), "ball" ) + self.assertEqual( IECoreGL.NameStateComponent.nameFromGLName( s2[0].name ), "ball" ) self.assertAlmostEqual( s1[0].depthMin, s2[0].depthMin, 5 ) @@ -214,11 +214,11 @@ def testOcclusionQuerySelect( self ) : ss = s.select( IECoreGL.Selector.Mode.OcclusionQuery, IECore.Box2f( IECore.V2f( 0, 0 ), IECore.V2f( 0.25, 1 ) ) ) self.assertEqual( len( ss ), 2 ) - self.assertEqual( set( [ x.name.value() for x in ss ] ), set( ( "frontLeft", "backLeft" ) ) ) + self.assertEqual( set( [ IECoreGL.NameStateComponent.nameFromGLName( x.name ) for x in ss ] ), set( ( "frontLeft", "backLeft" ) ) ) ss = s.select( IECoreGL.Selector.Mode.OcclusionQuery, IECore.Box2f( IECore.V2f( 0.75, 0 ), IECore.V2f( 1, 1 ) ) ) self.assertEqual( len( ss ), 2 ) - self.assertEqual( set( [ x.name.value() for x in ss ] ), set( ( "frontRight", "backRight" ) ) ) + self.assertEqual( set( [ IECoreGL.NameStateComponent.nameFromGLName( x.name ) for x in ss ] ), set( ( "frontRight", "backRight" ) ) ) def testIDSelectWithAdditionalDisplayStyles( self ) : @@ -255,11 +255,11 @@ def testIDSelectWithAdditionalDisplayStyles( self ) : ss = s.select( IECoreGL.Selector.Mode.IDRender, IECore.Box2f( IECore.V2f( 0.25, 0.5 ), IECore.V2f( 0.26, 0.51 ) ) ) self.assertEqual( len( ss ), 1 ) - self.assertEqual( ss[0].name.value(), "frontLeft" ) + self.assertEqual( IECoreGL.NameStateComponent.nameFromGLName( ss[0].name ), "frontLeft" ) ss = s.select( IECoreGL.Selector.Mode.IDRender, IECore.Box2f( IECore.V2f( 0.75, 0.5 ), IECore.V2f( 0.76, 0.51 ) ) ) self.assertEqual( len( ss ), 1 ) - self.assertEqual( ss[0].name.value(), "frontRight" ) + self.assertEqual( IECoreGL.NameStateComponent.nameFromGLName( ss[0].name ), "frontRight" ) def testPointsPrimitiveSelect( self ) : @@ -279,7 +279,7 @@ def testPointsPrimitiveSelect( self ) : for mode in ( IECoreGL.Selector.Mode.GLSelect, IECoreGL.Selector.Mode.OcclusionQuery, IECoreGL.Selector.Mode.IDRender ) : ss = s.select( mode, IECore.Box2f( IECore.V2f( 0 ), IECore.V2f( 1 ) ) ) - names = [ x.name.value() for x in ss ] + names = [ IECoreGL.NameStateComponent.nameFromGLName( x.name ) for x in ss ] self.assertEqual( len( names ), 1 ) self.assertEqual( names[0], "pointsNeedSelectingToo" ) @@ -312,7 +312,7 @@ def testCurvesPrimitiveSelect( self ) : for mode in ( IECoreGL.Selector.Mode.GLSelect, IECoreGL.Selector.Mode.OcclusionQuery, IECoreGL.Selector.Mode.IDRender ) : ss = s.select( mode, IECore.Box2f( IECore.V2f( 0 ), IECore.V2f( 1 ) ) ) - names = [ x.name.value() for x in ss ] + names = [ IECoreGL.NameStateComponent.nameFromGLName( x.name ) for x in ss ] self.assertEqual( len( names ), 1 ) self.assertEqual( names[0], "curvesNeedSelectingToo" ) @@ -346,7 +346,7 @@ def testCurvesPrimitiveSelectUsingLines( self ) : for mode in ( IECoreGL.Selector.Mode.GLSelect, IECoreGL.Selector.Mode.OcclusionQuery, IECoreGL.Selector.Mode.IDRender ) : ss = s.select( mode, IECore.Box2f( IECore.V2f( 0 ), IECore.V2f( 1 ) ) ) - names = [ x.name.value() for x in ss ] + names = [ IECoreGL.NameStateComponent.nameFromGLName( x.name ) for x in ss ] self.assertEqual( len( names ), 1 ) self.assertEqual( names[0], "curvesNeedSelectingToo" ) @@ -382,7 +382,7 @@ def testCurvesPrimitiveSelectUsingWireframeLines( self ) : for mode in ( IECoreGL.Selector.Mode.GLSelect, IECoreGL.Selector.Mode.OcclusionQuery, IECoreGL.Selector.Mode.IDRender ) : ss = s.select( mode, IECore.Box2f( IECore.V2f( 0 ), IECore.V2f( 1 ) ) ) - names = [ x.name.value() for x in ss ] + names = [ IECoreGL.NameStateComponent.nameFromGLName( x.name ) for x in ss ] self.assertEqual( len( names ), 1 ) self.assertEqual( names[0], "curvesNeedSelectingToo" ) @@ -415,7 +415,7 @@ def testContextManager( self ) : selector.baseState().bind() scene.root().render( selector.baseState() ) - names = [ x.name.value() for x in hits ] + names = [ IECoreGL.NameStateComponent.nameFromGLName( x.name ) for x in hits ] self.assertEqual( len( names ), 2 ) self.assert_( "one" in names ) self.assert_( "two" in names ) @@ -445,7 +445,7 @@ def testSelectableFlag( self ) : for mode in ( IECoreGL.Selector.Mode.GLSelect, IECoreGL.Selector.Mode.OcclusionQuery, IECoreGL.Selector.Mode.IDRender ) : ss = s.select( mode, IECore.Box2f( IECore.V2f( 0 ), IECore.V2f( 1 ) ) ) - names = [ x.name.value() for x in ss ] + names = [ IECoreGL.NameStateComponent.nameFromGLName( x.name ) for x in ss ] self.assertEqual( names, [ "selectableObj" ] ) if __name__ == "__main__": diff --git a/test/IECoreGL/ToGLStateConverterTest.py b/test/IECoreGL/ToGLStateConverterTest.py new file mode 100644 index 0000000000..9fa5f7e408 --- /dev/null +++ b/test/IECoreGL/ToGLStateConverterTest.py @@ -0,0 +1,102 @@ +########################################################################## +# +# Copyright (c) 2014, Image Engine Design Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Image Engine Design nor the names of any +# other contributors to this software may be used to endorse or +# promote products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +########################################################################## + +import unittest + +import IECore +import IECoreGL + +IECoreGL.init( False ) + +class ToGLStateConverterTest( unittest.TestCase ) : + + def test( self ) : + + attributes = [ + ( "doubleSided", IECore.BoolData( True ), IECoreGL.DoubleSidedStateComponent( True ) ), + ( "gl:primitive:wireframe", IECore.BoolData( True ), IECoreGL.Primitive.DrawWireframe( True ) ), + ( "gl:primitive:wireframeWidth", IECore.FloatData( 2.5 ), IECoreGL.Primitive.WireframeWidth( 2.5 ) ), + ( "gl:primitive:wireframeColor", IECore.Color4fData( IECore.Color4f( 0.1, 0.25, 0.5, 1 ) ), IECoreGL.WireframeColorStateComponent( IECore.Color4f( 0.1, 0.25, 0.5, 1 ) ) ), + ( "gl:primitive:bound", IECore.BoolData( True ), IECoreGL.Primitive.DrawBound( True ) ), + ( "gl:primitive:boundColor", IECore.Color4fData( IECore.Color4f( 0.1, 0.25, 0.5, 1 ) ), IECoreGL.BoundColorStateComponent( IECore.Color4f( 0.1, 0.25, 0.5, 1 ) ) ), + ( "gl:primitive:solid", IECore.BoolData( True ), IECoreGL.Primitive.DrawSolid( True ) ), + ( "gl:primitive:points", IECore.BoolData( True ), IECoreGL.Primitive.DrawPoints( True ) ), + ( "gl:primitive:pointWidth", IECore.FloatData( 2.5 ), IECoreGL.Primitive.PointWidth( 2.5 ) ), + ( "gl:primitive:pointColor", IECore.Color4fData( IECore.Color4f( 0.1, 0.25, 0.5, 1 ) ), IECoreGL.PointColorStateComponent( IECore.Color4f( 0.1, 0.25, 0.5, 1 ) ) ), + ( "gl:pointsPrimitive:useGLPoints", IECore.StringData( "forGLPoints" ), IECoreGL.PointsPrimitive.UseGLPoints( IECoreGL.GLPointsUsage.ForPointsOnly ) ), + ( "gl:pointsPrimitive:glPointWidth", IECore.FloatData( 1.5 ), IECoreGL.PointsPrimitive.GLPointWidth( 1.5 ) ), + ( "gl:curvesPrimitive:useGLLines", IECore.BoolData( True ), IECoreGL.CurvesPrimitive.UseGLLines( True ) ), + ( "gl:curvesPrimitive:glLineWidth", IECore.FloatData( 1.5 ), IECoreGL.CurvesPrimitive.GLLineWidth( 1.5 ) ), + ( "gl:curvesPrimitive:ignoreBasis", IECore.BoolData( True ), IECoreGL.CurvesPrimitive.IgnoreBasis( True ) ), + ( "gl:smoothing:points", IECore.BoolData( True ), IECoreGL.PointSmoothingStateComponent( True ) ), + ( "gl:smoothing:lines", IECore.BoolData( True ), IECoreGL.LineSmoothingStateComponent( True ) ), + ( "gl:smoothing:polygons", IECore.BoolData( True ), IECoreGL.PolygonSmoothingStateComponent( True ) ), + ] + + for name, value, component in attributes : + a = IECore.CompoundObject() + a[name] = value + s = IECoreGL.ToGLStateConverter( a ).convert() + c = s.get( component.typeId() ) + self.assertEqual( c.typeId(), component.typeId() ) + self.assertEqual( c.value, component.value ) + + def testShaderAttribute( self ) : + + vertexSource = """ + void main() + { + gl_Position = ftransform(); + } + """ + + fragmentSource = """ + void main() + { + gl_FragColor = vec4( 1, 0.5, 0.25, 1 ); + } + """ + + shader = IECore.Shader( "test", "surface", { "gl:vertexSource" : vertexSource, "gl:fragmentSource" : fragmentSource } ) + attributes = IECore.CompoundObject( { "gl:surface" : shader } ) + state = IECoreGL.ToGLStateConverter( attributes ).convert() + + shaderState = state.get( IECoreGL.ShaderStateComponent ) + self.assertTrue( isinstance( shaderState, IECoreGL.ShaderStateComponent ) ) + glShader = shaderState.shaderSetup().shader() + self.assertTrue( glShader.vertexSource(), vertexSource ) + self.assertTrue( glShader.fragmentSource(), fragmentSource ) + +if __name__ == "__main__": + unittest.main()