ObjectPtr FromHoudiniCortexObjectConverter::doDetailConversion( const GU_Detail *geo, const CompoundObject *operands ) const
{
	const GA_Primitive *prim = geo->getPrimitiveList().get( geo->getPrimitiveRange().begin().getOffset() );
	if ( prim->getTypeId() != GU_CortexPrimitive::typeId() )
	{
		throw std::runtime_error( "FromHoudiniCortexObjectConverter: Geometry does not contain a single CortexObject primitive" );
	}
	
	ConstObjectPtr object = ((GU_CortexPrimitive *)prim)->getObject();
	ObjectPtr result = filterAttribs( object, operands->member<StringData>( "attributeFilter" )->readable().c_str() );
	
	if ( result )
	{
		return result;
	}
	
	if ( object )
	{
		if ( object->isInstanceOf( IECore::ParameterisedProcedural::staticTypeId() ) )
		{
			return IECore::constPointerCast<IECore::Object>( object );
		}
		
		return object->copy();
	}
	
	return 0;
}
bool ToHoudiniCortexObjectConverter::doConversion( const Object *object, GU_Detail *geo ) const
{
	ConstObjectPtr result = filterAttribs( object );

	GA_Size numPrims = geo->getNumPrimitives();

	CortexPrimitive::build( geo, result.get() );

	GA_OffsetList offsets;
	offsets.append( geo->primitiveOffset( numPrims ) );
	GA_Range newPrims( geo->getPrimitiveMap(), offsets );

	if ( nameParameter()->getTypedValue() != "" )
	{
		setName( geo, newPrims );
	}
	// backwards compatibility with older data
	else if ( const BlindDataHolder *holder = IECore::runTimeCast<const BlindDataHolder>( object ) )
	{
		if ( const StringData *nameData = holder->blindData()->member<StringData>( "name" ) )
		{
			ToHoudiniStringVectorAttribConverter::convertString( "name", nameData->readable(), geo, newPrims );
		}
	}

	return ( (GA_Size)geo->getNumPrimitives() > numPrims );
}
示例#3
0
IECore::ConstCompoundObjectPtr Set::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const
{
	std::string name = namePlug()->getValue();
	if( !name.size() )
	{
		return inputGlobals;
	}

	IECore::CompoundObjectPtr result = new IECore::CompoundObject;
	// Since we're not going to modify any existing members other than the sets,
	// and our result becomes const on returning it, we can directly reference
	// the input members in our result without copying. We have to be careful not
	// to modify the input sets though.
	result->members() = inputGlobals->members();

	CompoundDataPtr sets = new CompoundData;
	if( const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets" ) )
	{
		sets->writable() = inputSets->readable();
	}
	result->members()["gaffer:sets"] = sets;

	ConstObjectPtr set = pathMatcherPlug()->getValue();
	// const cast is acceptable because we're just using it to place a const object into a
	// container that will be treated as const everywhere immediately after return from this method.
	sets->writable()[name] = const_cast<Data *>( static_cast<const Data *>( set.get() ) );

	return result;
}
ObjectPtr FromMayaObjectDataConverter::doConversion( const MObject &obj, ConstCompoundObjectPtr operands ) const
{
	MStatus s;
	MFnPluginData fnPluginData( obj, &s );
	if ( !s )
	{
		return 0;
	}

	/// If we ever support more than one type of data, we can handle them here.
	const ObjectData *objectData = dynamic_cast< const ObjectData * >( fnPluginData.data( &s ) );
	if ( !objectData || !s )
	{
		return 0;
	}

	ConstObjectPtr object = objectData->getObject();
	if ( !object )
	{
		return 0;
	}

	assert( object );
	return object->copy();
}
示例#5
0
IECore::ConstCompoundObjectPtr AttributeProcessor::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputAttributes ) const
{
	if( inputAttributes->members().empty() )
	{
		return inputAttributes;
	}

	const std::string names = namesPlug()->getValue();
	const bool invert = invertNamesPlug()->getValue();

	CompoundObjectPtr result = new CompoundObject;
	for( CompoundObject::ObjectMap::const_iterator it = inputAttributes->members().begin(), eIt = inputAttributes->members().end(); it != eIt; ++it )
	{
		ConstObjectPtr attribute = it->second;
		if( matchMultiple( it->first, names ) != invert )
		{
			attribute = processAttribute( path, context, it->first, attribute.get() );
		}

		if( attribute )
		{
			result->members().insert(
				CompoundObject::ObjectMap::value_type(
					it->first,
					// cast is ok - result is const immediately on
					// returning from this function, and attribute will
					// therefore not be modified.
					boost::const_pointer_cast<Object>( attribute )
				)
			);
		}
	}

	return result;
}
示例#6
0
Imath::Box3f PointsType::computeProcessedBound( const ScenePath &path, const Gaffer::Context *context, const Imath::Box3f &inputBound ) const
{
	ConstObjectPtr object = outPlug()->objectPlug()->getValue();
	if( const Primitive *primitive = runTimeCast<const Primitive>( object.get() ) )
	{
		return primitive->bound();
	}
	return inputBound;
}
ObjectPtr readObjectAtSample( SampledSceneInterface &m, size_t sampleIndex )
{
	ConstObjectPtr o = m.readObjectAtSample(sampleIndex);
	if ( o )
	{
		return o->copy();
	}
	return 0;
}
ObjectPtr readAttributeAtSample( SampledSceneInterface &m, const SceneInterface::Name &name, size_t sampleIndex )
{
	ConstObjectPtr o = m.readAttributeAtSample(name,sampleIndex);
	if ( o )
	{
		return o->copy();
	}
	return 0;
}
示例#9
0
void SceneWriter::writeLocation( const GafferScene::ScenePlug *scene, const ScenePlug::ScenePath &scenePath, Context *context, IECore::SceneInterface *output, double time ) const
{
	context->set( ScenePlug::scenePathContextName, scenePath );

	ConstCompoundObjectPtr attributes = scene->attributesPlug()->getValue();
	for( CompoundObject::ObjectMap::const_iterator it = attributes->members().begin(), eIt = attributes->members().end(); it != eIt; it++ )
	{
		output->writeAttribute( it->first, it->second.get(), time );
	}

	if( scenePath.empty() )
	{
		ConstCompoundObjectPtr globals = scene->globalsPlug()->getValue();
		output->writeAttribute( "gaffer:globals", globals.get(), time );
	}

	ConstObjectPtr object = scene->objectPlug()->getValue();

	if( object->typeId() != IECore::NullObjectTypeId && scenePath.size() > 0 )
	{
		output->writeObject( object.get(), time );
	}

	Imath::Box3f b = scene->boundPlug()->getValue();

	output->writeBound( Imath::Box3d( Imath::V3f( b.min ), Imath::V3f( b.max ) ), time );

	if( scenePath.size() )
	{
		Imath::M44f t = scene->transformPlug()->getValue();
		Imath::M44d transform(
			t[0][0], t[0][1], t[0][2], t[0][3],
			t[1][0], t[1][1], t[1][2], t[1][3],
			t[2][0], t[2][1], t[2][2], t[2][3],
			t[3][0], t[3][1], t[3][2], t[3][3]
		);

		output->writeTransform( new IECore::M44dData( transform ), time );
	}

	ConstInternedStringVectorDataPtr childNames = scene->childNamesPlug()->getValue();

	ScenePlug::ScenePath childScenePath = scenePath;
	childScenePath.push_back( InternedString() );
	for( vector<InternedString>::const_iterator it=childNames->readable().begin(); it!=childNames->readable().end(); it++ )
	{
		childScenePath[scenePath.size()] = *it;

		SceneInterfacePtr outputChild = output->child( *it, SceneInterface::CreateIfMissing );

		writeLocation( scene, childScenePath, context, outputChild.get(), time );
	}
}
ToNukeGeometryConverterPtr ToNukeGeometryConverter::create( ConstObjectPtr object )
{
	const TypesToFnsMap *m = typesToFns();
	TypesToFnsMap::const_iterator it = m->find( Types( object->typeId() ) );
	if( it!=m->end() )
	{
		return it->second( object );
	}
	return 0;
}
ToMayaObjectConverterPtr ToMayaObjectConverter::create( ConstObjectPtr object, MFn::Type resultType )
{
	const TypesToFnsMap *m = typesToFns();
	TypesToFnsMap::const_iterator it = m->find( Types( object->typeId(), resultType ) );
	if( it!=m->end() )
	{
		return it->second( object );
	}
	return 0;
}
示例#12
0
IECore::ConstCompoundObjectPtr AttributeProcessor::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputAttributes ) const
{
	if( inputAttributes->members().empty() )
	{
		return inputAttributes;
	}
		
	/// \todo See todos about name matching in PrimitiveVariableProcessor.
	typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
	std::string namesValue = namesPlug()->getValue();
	Tokenizer names( namesValue, boost::char_separator<char>( " " ) );
		
	bool invert = invertNamesPlug()->getValue();

	CompoundObjectPtr result = new CompoundObject;
	IECore::PrimitiveVariableMap::iterator next;
	for( CompoundObject::ObjectMap::const_iterator it = inputAttributes->members().begin(), eIt = inputAttributes->members().end(); it != eIt; ++it )
	{
		ConstObjectPtr attribute = it->second;
		bool found = std::find( names.begin(), names.end(), it->first.string() ) != names.end();
		if( found != invert )
		{
			attribute = processAttribute( path, context, it->first, attribute.get() );
		}
		if( attribute )
		{
			result->members().insert(
				CompoundObject::ObjectMap::value_type(
					it->first,
					// cast is ok - result is const immediately on
					// returning from this function, and attribute will
					// therefore not be modified.
					constPointerCast<Object>( attribute )
				)
			);
		}
	}
	
	return result;
}
示例#13
0
GA_Detail::IOStatus GEO_CobIOTranslator::fileLoad( GEO_Detail *geo, UT_IStream &is, int ate_magic )
{
	((UT_IFStream&)is).close();
	
	ConstObjectPtr object = 0;
	try
	{
		ReaderPtr reader = Reader::create( is.getLabel() );
		if ( !reader )
		{
			return false;
		}
		
		object = reader->read();
	}
	catch ( IECore::Exception e )
	{
		return false;
	}
	
	if ( !object )
	{
		return false;
	}
	
	ToHoudiniGeometryConverterPtr converter = ToHoudiniGeometryConverter::create( object.get() );
	if ( !converter )
	{
		return false;
	}
	
	GU_DetailHandle handle;
	handle.allocateAndSet( (GU_Detail*)geo, false );
	
	return converter->convert( handle );
}
void SOP_SceneCacheSource::loadObjects( const IECore::SceneInterface *scene, Imath::M44d transform, double time, Space space, Parameters &params, size_t rootSize )
{
	UT_Interrupt *progress = UTgetInterrupt();
	progress->setLongOpText( ( "Loading " + scene->name().string() ).c_str() );
	if ( progress->opInterrupt() )
	{
		return;
	}
	
	if ( scene->hasObject() && UT_String( scene->name() ).multiMatch( params.shapeFilter ) && tagged( scene, params.tagFilter ) )
	{
		std::string name = relativePath( scene, rootSize );
		
		Imath::M44d currentTransform;
		if ( space == Local )
		{
			currentTransform = scene->readTransformAsMatrix( time );
		}
		else if ( space != Object )
		{
			currentTransform = transform;
		}
		
		ConstObjectPtr object = 0;
		if ( params.geometryType == BoundingBox )
		{
			Imath::Box3d bound = scene->readBound( time );
			object = MeshPrimitive::createBox( Imath::Box3f( bound.min, bound.max ) );
			
			params.hasAnimatedTopology = false;
			params.hasAnimatedPrimVars = true;
			params.animatedPrimVars.clear();
			params.animatedPrimVars.push_back( "P" );
		}
		else if ( params.geometryType == PointCloud )
		{
			std::vector<Imath::V3f> point( 1, scene->readBound( time ).center() );
			PointsPrimitivePtr points = new PointsPrimitive( new V3fVectorData( point ) );
			std::vector<Imath::V3f> basis1( 1, Imath::V3f( currentTransform[0][0], currentTransform[0][1], currentTransform[0][2] ) );
			std::vector<Imath::V3f> basis2( 1, Imath::V3f( currentTransform[1][0], currentTransform[1][1], currentTransform[1][2] ) );
			std::vector<Imath::V3f> basis3( 1, Imath::V3f( currentTransform[2][0], currentTransform[2][1], currentTransform[2][2] ) );
			points->variables["basis1"] = PrimitiveVariable( PrimitiveVariable::Vertex, new V3fVectorData( basis1 ) );
			points->variables["basis2"] = PrimitiveVariable( PrimitiveVariable::Vertex, new V3fVectorData( basis2 ) );
			points->variables["basis3"] = PrimitiveVariable( PrimitiveVariable::Vertex, new V3fVectorData( basis3 ) );
			
			params.hasAnimatedTopology = false;
			params.hasAnimatedPrimVars = true;
			params.animatedPrimVars.clear();
			params.animatedPrimVars.push_back( "P" );
			params.animatedPrimVars.push_back( "basis1" );
			params.animatedPrimVars.push_back( "basis2" );
			params.animatedPrimVars.push_back( "basis3" );
			
			object = points;
		}
		else
		{
			object = scene->readObject( time );
			
			params.hasAnimatedTopology = scene->hasAttribute( SceneCache::animatedObjectTopologyAttribute );
			params.hasAnimatedPrimVars = scene->hasAttribute( SceneCache::animatedObjectPrimVarsAttribute );
			if ( params.hasAnimatedPrimVars )
			{
				const ConstObjectPtr animatedPrimVarObj = scene->readAttribute( SceneCache::animatedObjectPrimVarsAttribute, 0 );
				const InternedStringVectorData *animatedPrimVarData = IECore::runTimeCast<const InternedStringVectorData>( animatedPrimVarObj.get() );
				if ( animatedPrimVarData )
				{
					const std::vector<InternedString> &values = animatedPrimVarData->readable();
					params.animatedPrimVars.clear();
					params.animatedPrimVars.resize( values.size() );
					std::copy( values.begin(), values.end(), params.animatedPrimVars.begin() );
				}
			}
		}
		
		// modify the object if necessary
		object = modifyObject( object.get(), params );
		
		// transform the object unless its an identity
		if ( currentTransform != Imath::M44d() )
		{
			object = transformObject( object.get(), currentTransform, params );
		}
		
		// convert the object to Houdini
		if ( !convertObject( object.get(), name, scene, params ) )
		{
			std::string fullName;
			SceneInterface::Path path;
			scene->path( path );
			SceneInterface::pathToString( path, fullName );
			addWarning( SOP_MESSAGE, ( "Could not convert " + fullName + " to Houdini" ).c_str() );
		}
	}
	
	if ( evalInt( pObjectOnly.getToken(), 0, 0 ) )
	{
		return;
	}
	
	SceneInterface::NameList children;
	scene->childNames( children );
	std::sort( children.begin(), children.end(), InternedStringSort() );
	for ( SceneInterface::NameList::const_iterator it=children.begin(); it != children.end(); ++it )
	{
		ConstSceneInterfacePtr child = scene->child( *it );
		if ( tagged( child.get(), params.tagFilter ) )
		{
			loadObjects( child.get(), child->readTransformAsMatrix( time ) * transform, time, space, params, rootSize );
		}
	}
}
示例#15
0
void SceneProcedural::render( RendererPtr renderer ) const
{	
	Context::Scope scopedContext( m_context );
	
	/// \todo See above.
	try
	{
	
		// get all the attributes, and early out if we're not visibile
	
		ConstCompoundObjectPtr attributes = m_scenePlug->attributesPlug()->getValue();
		const BoolData *visibilityData = attributes->member<BoolData>( "gaffer:visibility" );
		if( visibilityData && !visibilityData->readable() )
		{
			return;
		}

		// if we are visible then make an attribute block to contain everything, set the name
		// and get on with generating things.

		AttributeBlock attributeBlock( renderer );

		std::string name = "";
		for( ScenePlug::ScenePath::const_iterator it = m_scenePath.begin(), eIt = m_scenePath.end(); it != eIt; it++ )
		{
			name += "/" + it->string();
		}
		renderer->setAttribute( "name", new StringData( name ) );

		// transform
		
		std::set<float> transformTimes;
		motionTimes( ( m_options.transformBlur && m_attributes.transformBlur ) ? m_attributes.transformBlurSegments : 0, transformTimes );
		{
			ContextPtr timeContext = new Context( *m_context );
			Context::Scope scopedTimeContext( timeContext );
			
			MotionBlock motionBlock( renderer, transformTimes, transformTimes.size() > 1 );
			
			for( std::set<float>::const_iterator it = transformTimes.begin(), eIt = transformTimes.end(); it != eIt; it++ )
			{
				timeContext->setFrame( *it );
				renderer->concatTransform( m_scenePlug->transformPlug()->getValue() );
			}
		}
		
		// attributes
		
		for( CompoundObject::ObjectMap::const_iterator it = attributes->members().begin(), eIt = attributes->members().end(); it != eIt; it++ )
		{
			if( const StateRenderable *s = runTimeCast<const StateRenderable>( it->second.get() ) )
			{
				s->render( renderer );
			}
			else if( const ObjectVector *o = runTimeCast<const ObjectVector>( it->second.get() ) )
			{
				for( ObjectVector::MemberContainer::const_iterator it = o->members().begin(), eIt = o->members().end(); it != eIt; it++ )
				{
					const StateRenderable *s = runTimeCast<const StateRenderable>( it->get() );
					if( s )
					{
						s->render( renderer );
					}
				}
			}
			else if( const Data *d = runTimeCast<const Data>( it->second.get() ) )
			{
				renderer->setAttribute( it->first, d );
			}
		}
		
		// object
		
		std::set<float> deformationTimes;
		motionTimes( ( m_options.deformationBlur && m_attributes.deformationBlur ) ? m_attributes.deformationBlurSegments : 0, deformationTimes );
		{
			ContextPtr timeContext = new Context( *m_context );
			Context::Scope scopedTimeContext( timeContext );
		
			unsigned timeIndex = 0;
			for( std::set<float>::const_iterator it = deformationTimes.begin(), eIt = deformationTimes.end(); it != eIt; it++, timeIndex++ )
			{
				timeContext->setFrame( *it );
				ConstObjectPtr object = m_scenePlug->objectPlug()->getValue();
				if( const Primitive *primitive = runTimeCast<const Primitive>( object.get() ) )
				{
					if( deformationTimes.size() > 1 && timeIndex == 0 )
					{
						renderer->motionBegin( deformationTimes );
					}
						
						primitive->render( renderer );
					
					if( deformationTimes.size() > 1 && timeIndex == deformationTimes.size() - 1 )
					{
						renderer->motionEnd();
					}
				}
				else if( const Camera *camera = runTimeCast<const Camera>( object.get() ) )
				{
					/// \todo This absolutely does not belong here, but until we have
					/// a mechanism for drawing manipulators, we don't have any other
					/// means of visualising the cameras.
					if( renderer->isInstanceOf( "IECoreGL::Renderer" ) )
					{
						drawCamera( camera, renderer.get() );
					}
					break; // no motion blur for these chappies.
				}
				else if( const Light *light = runTimeCast<const Light>( object.get() ) )
				{
					/// \todo This doesn't belong here.
					if( renderer->isInstanceOf( "IECoreGL::Renderer" ) )
					{
						drawLight( light, renderer.get() );
					}
					break; // no motion blur for these chappies.
				}
				else if( const VisibleRenderable* renderable = runTimeCast< const VisibleRenderable >( object.get() ) )
				{
					renderable->render( renderer );
					break; // no motion blur for these chappies.
				}
			
			}
		}
	
		// children

		ConstInternedStringVectorDataPtr childNames = m_scenePlug->childNamesPlug()->getValue();
		if( childNames->readable().size() )
		{		
			bool expand = true;
			if( m_pathsToExpand )
			{
				expand = m_pathsToExpand->readable().match( m_scenePath ) & Filter::ExactMatch;
			}
			
			if( !expand )
			{
				renderer->setAttribute( "gl:primitive:wireframe", new BoolData( true ) );
				renderer->setAttribute( "gl:primitive:solid", new BoolData( false ) );
				renderer->setAttribute( "gl:curvesPrimitive:useGLLines", new BoolData( true ) );
				Box3f b = m_scenePlug->boundPlug()->getValue();
				CurvesPrimitive::createBox( b )->render( renderer );	
			}
			else
			{
				ScenePlug::ScenePath childScenePath = m_scenePath;
				childScenePath.push_back( InternedString() ); // for the child name
				for( vector<InternedString>::const_iterator it=childNames->readable().begin(); it!=childNames->readable().end(); it++ )
				{
					childScenePath[m_scenePath.size()] = *it;
					renderer->setAttribute( "name", new StringData( *it ) );
					renderer->procedural( new SceneProcedural( *this, childScenePath ) );
				}
			}	
		}
	}
	catch( const std::exception &e )
	{
		IECore::msg( IECore::Msg::Error, "SceneProcedural::render()", e.what() );
	}	
}
示例#16
0
void SceneProcedural::render( Renderer *renderer ) const
{
	tbb::task_scheduler_init tsi( tbb::task_scheduler_init::deferred );
	initializeTaskScheduler( tsi );

	Context::Scope scopedContext( m_context.get() );

	std::string name;
	ScenePlug::pathToString( m_scenePath, name );

	/// \todo See above.
	try
	{

		// get all the attributes, and early out if we're not visibile

		const BoolData *visibilityData = m_attributesObject->member<BoolData>( g_visibleAttributeName );
		if( visibilityData && !visibilityData->readable() )
		{

			if( !m_rendered )
			{
				decrementPendingProcedurals();
			}
			m_rendered = true;
			return;
		}

		// if we are visible then make an attribute block to contain everything, set the name
		// and get on with generating things.

		AttributeBlock attributeBlock( renderer );

		renderer->setAttribute( "name", new StringData( name ) );

		// transform

		std::set<float> transformTimes;
		motionTimes( ( m_options.transformBlur && m_attributes.transformBlur ) ? m_attributes.transformBlurSegments : 0, transformTimes );
		{
			ContextPtr timeContext = new Context( *m_context, Context::Borrowed );
			Context::Scope scopedTimeContext( timeContext.get() );

			MotionBlock motionBlock( renderer, transformTimes, transformTimes.size() > 1 );

			for( std::set<float>::const_iterator it = transformTimes.begin(), eIt = transformTimes.end(); it != eIt; it++ )
			{
				timeContext->setFrame( *it );
				renderer->concatTransform( m_scenePlug->transformPlug()->getValue() );
			}
		}

		// attributes

		outputAttributes( m_attributesObject.get(), renderer );

		// object

		std::set<float> deformationTimes;
		motionTimes( ( m_options.deformationBlur && m_attributes.deformationBlur ) ? m_attributes.deformationBlurSegments : 0, deformationTimes );
		{
			ContextPtr timeContext = new Context( *m_context, Context::Borrowed );
			Context::Scope scopedTimeContext( timeContext.get() );

			unsigned timeIndex = 0;
			for( std::set<float>::const_iterator it = deformationTimes.begin(), eIt = deformationTimes.end(); it != eIt; it++, timeIndex++ )
			{
				timeContext->setFrame( *it );
				ConstObjectPtr object = m_scenePlug->objectPlug()->getValue();
				if( const Primitive *primitive = runTimeCast<const Primitive>( object.get() ) )
				{
					if( deformationTimes.size() > 1 && timeIndex == 0 )
					{
						renderer->motionBegin( deformationTimes );
					}

						primitive->render( renderer );

					if( deformationTimes.size() > 1 && timeIndex == deformationTimes.size() - 1 )
					{
						renderer->motionEnd();
					}
				}
				else if( const VisibleRenderable* renderable = runTimeCast< const VisibleRenderable >( object.get() ) )
				{
					renderable->render( renderer );
					break; // no motion blur for these chappies.
				}

			}
		}

		// children

		ConstInternedStringVectorDataPtr childNames = m_scenePlug->childNamesPlug()->getValue();
		if( childNames->readable().size() )
		{
			// Creating a SceneProcedural involves an attribute/bound evaluation, which are
			// potentially expensive, so we're parallelizing them.

			// allocate space for child procedurals:
			SceneProceduralCreate::SceneProceduralContainer childProcedurals( childNames->readable().size() );

			// create procedurals in parallel:
			SceneProceduralCreate s(
				childProcedurals,
				*this,
				childNames->readable()
			);
			tbb::parallel_for( tbb::blocked_range<int>( 0, childNames->readable().size() ), s );

			// send to the renderer in series:

			std::vector<SceneProceduralPtr>::const_iterator procIt = childProcedurals.begin(), procEit = childProcedurals.end();
			for( ; procIt != procEit; ++procIt )
			{
				renderer->procedural( *procIt );
			}
		}
	}
	catch( const std::exception &e )
	{
		IECore::msg( IECore::Msg::Error, "SceneProcedural::render() " + name, e.what() );
	}
	if( !m_rendered )
	{
		decrementPendingProcedurals();
	}
	m_rendered = true;
}