Skip to content

Commit

Permalink
Merge pull request #334 from johnhaddon/externalProcedurals
Browse files Browse the repository at this point in the history
External procedurals
  • Loading branch information
andrewkaufman committed Sep 11, 2014
2 parents f778a35 + b6553ae commit fc82687
Show file tree
Hide file tree
Showing 20 changed files with 788 additions and 42 deletions.
35 changes: 23 additions & 12 deletions contrib/IECoreArnold/src/IECoreArnold/RendererImplementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -638,22 +638,33 @@ void IECoreArnold::RendererImplementation::procedural( IECore::Renderer::Procedu
return;
}

// we have to transform the bound, as we're not applying the current transform to the
// procedural node, but instead applying absolute transforms to the shapes the procedural
// generates.
bound = transform( bound, m_transformStack.top() );

AtNode *procedural = AiNode( "procedural" );
AiNodeSetPnt( procedural, "min", bound.min.x, bound.min.y, bound.min.z );
AiNodeSetPnt( procedural, "max", bound.max.x, bound.max.y, bound.max.z );

if( ExternalProcedural *externalProc = dynamic_cast<ExternalProcedural *>( proc.get() ) )
{
AiNodeSetStr( procedural, "dso", externalProc->fileName().c_str() );
ToArnoldConverter::setParameters( procedural, externalProc->parameters() );
applyTransformToNode( procedural );
}
else
{

// we have to transform the bound, as we're not applying the current transform to the
// procedural node, but instead applying absolute transforms to the shapes the procedural
// generates.
bound = transform( bound, m_transformStack.top() );

AiNodeSetPtr( procedural, "funcptr", (void *)procLoader );
AiNodeSetPtr( procedural, "funcptr", (void *)procLoader );

ProceduralData *data = new ProceduralData;
data->procedural = proc;
data->renderer = new IECoreArnold::Renderer( new RendererImplementation( *this ) );
ProceduralData *data = new ProceduralData;
data->procedural = proc;
data->renderer = new IECoreArnold::Renderer( new RendererImplementation( *this ) );

AiNodeSetPtr( procedural, "userptr", data );
AiNodeSetPtr( procedural, "userptr", data );
}

AiNodeSetPnt( procedural, "min", bound.min.x, bound.min.y, bound.min.z );
AiNodeSetPnt( procedural, "max", bound.max.x, bound.max.y, bound.max.z );

// we call addNode() rather than addShape() as we don't want to apply transforms and
// shaders and attributes to procedurals. if we do, they override the things we set
Expand Down
39 changes: 39 additions & 0 deletions contrib/IECoreArnold/test/IECoreArnold/RendererTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,46 @@ def testLight( self ) :
self.assertTrue( result.floatPrimVar( e.R() ) > 0.2 )
self.assertAlmostEqual( result.floatPrimVar( e.R() ) * 0.5, result.floatPrimVar( e.G() ) )
self.assertAlmostEqual( result.floatPrimVar( e.R() ) * 0.25, result.floatPrimVar( e.B() ) )

def testExternalProcedural( self ) :

r = IECoreArnold.Renderer( self.__assFileName )

with IECore.WorldBlock( r ) :

r.procedural(
r.ExternalProcedural(
"test.so",
IECore.Box3f(
IECore.V3f( 1, 2, 3 ),
IECore.V3f( 4, 5, 6 )
),
{
"colorParm" : IECore.Color3f( 1, 2, 3 ),
"stringParm" : "test",
"floatParm" : 1.5,
"intParm" : 2,
}
)
)


ass = "".join( file( self.__assFileName ).readlines() )
print ass

self.assertTrue( "procedural" in ass )
self.assertTrue( "min 1 2 3" in ass )
self.assertTrue( "max 4 5 6" in ass )
self.assertTrue( "dso \"test.so\"" in ass )
self.assertTrue( "declare stringParm constant STRING" in ass )
self.assertTrue( "declare floatParm constant FLOAT" in ass )
self.assertTrue( "declare intParm constant INT" in ass )
self.assertTrue( "declare colorParm constant RGB" in ass )
self.assertTrue( "stringParm \"test\"" in ass )
self.assertTrue( "floatParm 1.5" in ass )
self.assertTrue( "intParm 2" in ass )
self.assertTrue( "colorParm 1 2 3" in ass )

def tearDown( self ) :

for f in [
Expand Down
79 changes: 79 additions & 0 deletions include/IECore/ExternalProcedural.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//////////////////////////////////////////////////////////////////////////
//
// 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 IECORE_EXTERNALPROCEDURAL_H
#define IECORE_EXTERNALPROCEDURAL_H

#include "IECore/VisibleRenderable.h"

namespace IECore
{

/// \ingroup renderingGroup
/// \ingroup coreGroup
class ExternalProcedural : public VisibleRenderable
{

public :

ExternalProcedural( const std::string &fileName = "", const Imath::Box3f &bound = Imath::Box3f(), const CompoundData *parameters = NULL );
virtual ~ExternalProcedural();

IE_CORE_DECLAREOBJECT( ExternalProcedural, VisibleRenderable );

void setFileName( const std::string &fileName );
const std::string &getFileName() const;

void setBound( const Imath::Box3f &bound );
const Imath::Box3f &getBound() const;

CompoundData *parameters();
const CompoundData *parameters() const;

virtual void render( Renderer *renderer ) const;
virtual Imath::Box3f bound() const;

private :

std::string m_fileName;
Imath::Box3f m_bound;
CompoundDataPtr m_parameters;

};

IE_CORE_DECLAREPTR( ExternalProcedural );

} // namespace IECore

#endif // IECORE_EXTERNALPROCEDURAL_H
27 changes: 27 additions & 0 deletions include/IECore/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,33 @@ class Renderer : public RunTimeTyped
};
IE_CORE_DECLAREPTR( Procedural );

/// A placeholder for specifying a procedural which the Renderer
/// must load from a file on disk.
class ExternalProcedural : public Procedural
{
public :

IE_CORE_DECLAREMEMBERPTR( ExternalProcedural )

ExternalProcedural( const std::string &fileName, const Imath::Box3f &bound, const CompoundDataMap &parameters );
virtual ~ExternalProcedural();

const std::string &fileName() const;
const CompoundDataMap &parameters() const;

virtual Imath::Box3f bound() const;
virtual void render( Renderer *renderer ) const;
virtual MurmurHash hash() const;

private :

std::string m_fileName;
Imath::Box3f m_bound;
CompoundDataMap m_parameters;

};
IE_CORE_DECLAREPTR( ExternalProcedural );

/// Renders a piece of procedural geometry.
virtual void procedural( ProceduralPtr proc ) = 0;

Expand Down
3 changes: 2 additions & 1 deletion include/IECore/TypeIds.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,8 @@ enum TypeId
TransferSmoothSkinningWeightsOpTypeId = 390,
EXRDeepImageReaderTypeId = 391,
EXRDeepImageWriterTypeId = 392,

ExternalProceduralTypeId = 393,

// Remember to update TypeIdBinding.cpp !!!

// If we ever get this far then the core library is too big.
Expand Down
3 changes: 3 additions & 0 deletions include/IECore/TypeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ template<typename T> struct HasVectorValueType< TypedData< std::vector< T > > >
template<typename T> struct HasVectorValueType< GeometricTypedData<std::vector<T> > > : public boost::true_type {};
template<typename T> struct HasVectorValueType< const T > : public HasVectorValueType<T> {};

/// HasBaseType
template<typename T> struct HasBaseType : public boost::mpl::not_< boost::is_void<typename T::BaseType> > {};

namespace Detail
{

Expand Down
45 changes: 45 additions & 0 deletions include/IECorePython/ExternalProceduralBinding.h
Original file line number Diff line number Diff line change
@@ -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 IECOREPYTHON_EXTERNALPROCEDURALBINDING_H
#define IECOREPYTHON_EXTERNALPROCEDURALBINDING_H

namespace IECorePython
{

void bindExternalProcedural();

} // namespace IECorePython

#endif // IECOREPYTHON_EXTERNALPROCEDURALBINDING_H
10 changes: 10 additions & 0 deletions include/IECoreRI/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,16 @@ class Renderer : public IECore::Renderer

virtual void geometry( const std::string &type, const IECore::CompoundDataMap &topology, const IECore::PrimitiveVariableMap &primVars );

/// ExternalProcedurals are treated as DelayedReadArchives if their filename ends with ".rib"
/// and as DynamicLoad procedurals otherwise. Because RenderMan has very poor support for passing
/// parameters to DynamicLoad procedurals (you can only pass a single string), the arbitrary parameters
/// of the ExternalProcedural are treated as follows :
///
/// - If an "ri:data" StringData parameter exists, it is passed verbatim to the procedural. This
/// allows procedurals which require data in a specific format to be supported.
/// - All other parameters are serialised in a command line "--name value" style and concatenated.
/// This allows the convenience of arbitrary typed parameters provided that the procedural itself
/// uses a command line style parser.
virtual void procedural( IECore::Renderer::ProceduralPtr proc );

virtual void instanceBegin( const std::string &name, const IECore::CompoundDataMap &parameters );
Expand Down
3 changes: 3 additions & 0 deletions include/IECoreRI/private/RendererImplementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ class RendererImplementation : public IECore::Renderer
// This constructor is used to create a child renderer in procSubdivide()
RendererImplementation( SharedData::Ptr sharedData, IECore::CompoundDataPtr options );

void standardProcedural( Procedural *proc );
void externalProcedural( ExternalProcedural *proc );

static void procSubdivide( void *data, float detail );
static void procFree( void *data );

Expand Down
Loading

0 comments on commit fc82687

Please sign in to comment.