Example #1
0
IECore::ConstCompoundObjectPtr CopyImageMetadata::computeProcessedMetadata( const Gaffer::Context *context, const IECore::CompoundObject *inputMetadata ) const
{
	ConstCompoundObjectPtr copyFrom = copyFromPlug()->metadataPlug()->getValue();
	if ( copyFrom->members().empty() )
	{
		return inputMetadata;
	}

	const std::string names = namesPlug()->getValue();
	const bool invert = invertNamesPlug()->getValue();
	if ( !invert && !names.size() )
	{
		return inputMetadata;
	}

	IECore::CompoundObjectPtr result = inputMetadata->copy();
	for ( IECore::CompoundObject::ObjectMap::const_iterator it = copyFrom->members().begin(), eIt = copyFrom->members().end(); it != eIt; ++it )
	{
		bool copy = false;
		if ( matchMultiple( it->first.c_str(), names.c_str() ) != invert )
		{
			copy = true;
		}
		
		if ( copy )
		{
			result->members()[it->first] = it->second;
		}
	}
	
	return result;
}
Example #2
0
IECore::CameraPtr GafferScene::camera( const ScenePlug *scene, const ScenePlug::ScenePath &cameraPath, const IECore::CompoundObject *globals )
{
	ConstCompoundObjectPtr computedGlobals;
	if( !globals )
	{
		computedGlobals = scene->globalsPlug()->getValue();
		globals = computedGlobals.get();
	}

	std::string cameraName;
	ScenePlug::pathToString( cameraPath, cameraName );

	if( !exists( scene, cameraPath ) )
	{
		throw IECore::Exception( "Camera \"" + cameraName + "\" does not exist" );
	}

	IECore::ConstCameraPtr constCamera = runTimeCast<const IECore::Camera>( scene->object( cameraPath ) );
	if( !constCamera )
	{
		std::string path; ScenePlug::pathToString( cameraPath, path );
		throw IECore::Exception( "Location \"" + cameraName + "\" is not a camera" );
	}

	IECore::CameraPtr camera = constCamera->copy();
	camera->setName( cameraName );

	const BoolData *cameraBlurData = globals->member<BoolData>( "option:render:cameraBlur" );
	const bool cameraBlur = cameraBlurData ? cameraBlurData->readable() : false;
	camera->setTransform( transform( scene, cameraPath, shutter( globals ), cameraBlur ) );

	applyCameraGlobals( camera.get(), globals );
	return camera;
}
Example #3
0
IECore::ConstCompoundObjectPtr Attributes::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue();
	if( !globalPlug()->getValue() )
	{
		return inputGlobals;
	}

	const CompoundDataPlug *p = attributesPlug();
	IECore::CompoundObjectPtr result = new CompoundObject;
	// Since we're not going to modify any existing members (only add new ones),
	// and our result becomes const on returning it, we can directly reference
	// the input members in our result without copying. Be careful not to modify
	// them though!
	result->members() = inputGlobals->members();

	std::string name;
	for( CompoundDataPlug::MemberPlugIterator it( p ); !it.done(); ++it )
	{
		IECore::DataPtr d = p->memberDataAndName( it->get(), name );
		if( d )
		{
			result->members()["attribute:" + name] = d;
		}
	}

	return result;
}
Example #4
0
IECore::ConstCompoundObjectPtr OSLLight::computeAttributes( const SceneNode::ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const
{
	IECore::CompoundObjectPtr result = new IECore::CompoundObject;

	ConstCompoundObjectPtr shaderAttributes = shaderInPlug()->attributes();
	result->members() = shaderAttributes->members();

	attributesPlug()->fillCompoundObject( result->members() );

	return result;
}
void ToNukeGeometryConverter::convert( GeometryList &geoList ) const
{
	int objIndex = m_objIndexParameter->getNumericValue();
	if ( objIndex == -1 )
	{
		objIndex = (int)geoList.objects();
	}
	geoList.add_object(objIndex);

	ConstCompoundObjectPtr operands = parameters()->getTypedValidatedValue<CompoundObject>();
	doConversion( srcParameter()->getValidatedValue(), geoList, objIndex, operands.get() );
}
Example #6
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 );
	}
}
Example #7
0
IECore::ConstCompoundObjectPtr SubTree::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue();
	const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets" );
	if( !inputSets )
	{
		return inputGlobals;
	}

	CompoundObjectPtr outputGlobals = inputGlobals->copy();
	CompoundDataPtr outputSets = new CompoundData;
	outputGlobals->members()["gaffer:sets"] = outputSets;

	std::string root = rootPlug()->getValue();
	if( !root.size() || root[root.size()-1] != '/' )
	{
		root += "/";
	}

	size_t prefixSize = root.size() - 1; // number of characters to remove from front of each declaration
	if( includeRootPlug()->getValue() && prefixSize )
	{
		size_t lastSlashButOne = root.rfind( "/", prefixSize-1 );
		if( lastSlashButOne != string::npos )
		{
			prefixSize = lastSlashButOne;
		}
	}

	for( CompoundDataMap::const_iterator it = inputSets->readable().begin(), eIt = inputSets->readable().end(); it != eIt; ++it )
	{
		/// \todo This could be more efficient if PathMatcher exposed the internal nodes,
		/// and allowed sharing between matchers. Then we could just pick the subtree within
		/// the matcher that we wanted.
		const PathMatcher &inputSet = static_cast<const PathMatcherData *>( it->second.get() )->readable();
		PathMatcher &outputSet = outputSets->member<PathMatcherData>( it->first, /* throwExceptions = */ false, /* createIfMissing = */ true )->writable();

		vector<string> inputPaths;
		inputSet.paths( inputPaths );
		for( vector<string>::const_iterator pIt = inputPaths.begin(), peIt = inputPaths.end(); pIt != peIt; ++pIt )
		{
			const string &inputPath = *pIt;
			if( inputPath.compare( 0, root.size(), root ) == 0 )
			{
				std::string outputPath( inputPath, prefixSize );
				outputSet.addPath( outputPath );
			}
		}
	}

	return outputGlobals;
}
Example #8
0
void ExecutableRender::execute() const
{
	const ScenePlug *scene = inPlug()->getInput<ScenePlug>();
	if( !scene )
	{
		throw IECore::Exception( "No input scene" );
	}

	ConstCompoundObjectPtr globals = scene->globalsPlug()->getValue();

	RendererAlgo::createDisplayDirectories( globals.get() );

	// Scoping the lifetime of the renderer so that
	// the destructor is run before we run the system
	// command. This can be essential for renderman
	// renders, where the rib stream may not be flushed
	// to disk before RiEnd is called.
	{
		IECore::RendererPtr renderer = createRenderer();
		RendererAlgo::outputOptions( globals.get(), renderer.get() );
		RendererAlgo::outputOutputs( globals.get(), renderer.get() );
		RendererAlgo::outputCameras( scene, globals.get(), renderer.get() );
		RendererAlgo::outputClippingPlanes( scene, globals.get(), renderer.get() );
		{
			WorldBlock world( renderer );

			RendererAlgo::outputGlobalAttributes( globals.get(), renderer.get() );
			RendererAlgo::outputCoordinateSystems( scene, globals.get(), renderer.get() );
			RendererAlgo::outputLights( scene, globals.get(), renderer.get() );
			outputWorldProcedural( scene, renderer.get() );
		}
	}
}
Example #9
0
IECore::ConstInternedStringVectorDataPtr CompoundObjectSource::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const
{
	ConstCompoundObjectPtr entry = entryForPath( path );
	ConstCompoundObjectPtr children = entry->member<CompoundObject>( "children" );
	if( !children )
	{
		return outPlug()->childNamesPlug()->defaultValue();
	}
	InternedStringVectorDataPtr result = new InternedStringVectorData;
	for( CompoundObject::ObjectMap::const_iterator it = children->members().begin(); it!=children->members().end(); it++ )
	{
		result->writable().push_back( it->first.value() );
	}
	return result;
}
Example #10
0
IECore::ImagePrimitivePtr ImagePlug::image() const
{
	Format format = formatPlug()->getValue();
	Box2i dataWindow = dataWindowPlug()->getValue();
	Box2i newDataWindow( Imath::V2i(0) );

	if( dataWindow.isEmpty() )
	{
		dataWindow = Box2i( Imath::V2i(0) );
	}
	else
	{
		newDataWindow = format.yDownToFormatSpace( dataWindow );
	}

	// use the default format if we don't have an explicit one.
	/// \todo: remove this once FormatPlug is handling it for
	/// us during ExecutableNode::execute (see issue #887).
	if( format.getDisplayWindow().isEmpty() )
	{
		format = Context::current()->get<Format>( Format::defaultFormatContextName, Format() );
	}
	
	ImagePrimitivePtr result = new ImagePrimitive( newDataWindow, format.getDisplayWindow() );
	
	ConstCompoundObjectPtr metadata = metadataPlug()->getValue();
	compoundObjectToCompoundData( metadata.get(), result->blindData() );
	
	ConstStringVectorDataPtr channelNamesData = channelNamesPlug()->getValue();
	const vector<string> &channelNames = channelNamesData->readable();

	vector<float *> imageChannelData;
	for( vector<string>::const_iterator it = channelNames.begin(), eIt = channelNames.end(); it!=eIt; it++ )
	{
		FloatVectorDataPtr cd = new FloatVectorData;
		vector<float> &c = cd->writable();
		c.resize( result->variableSize( PrimitiveVariable::Vertex ), 0.0f );
		result->variables[*it] = PrimitiveVariable( PrimitiveVariable::Vertex, cd );
		imageChannelData.push_back( &(c[0]) );
	}

	parallel_for( blocked_range3d<size_t>( 0, imageChannelData.size(), 1, 0, dataWindow.size().x+1, tileSize(), 0, dataWindow.size().y+1, tileSize() ),
		      GafferImage::Detail::CopyTiles( imageChannelData, channelNames, channelDataPlug(), dataWindow, Context::current(), tileSize()) );

	return result;
}
Example #11
0
bool outputLight( const ScenePlug *scene, const ScenePlug::ScenePath &path, IECore::Renderer *renderer )
{
	IECore::ConstLightPtr constLight = runTimeCast<const IECore::Light>( scene->object( path ) );
	if( !constLight )
	{
		return false;
	}

	if( !visible( scene, path ) )
	{
		/// \todo Since both visible() and fullAttributes() perform similar work,
		/// we may want to combine them into one query if we see this function
		/// being a significant fraction of render time. Maybe something like
		/// `fullAttributes( returnNullIfInvisible = true )`? It probably also
		/// makes sense to migrate all the convenience functions from ScenePlug
		/// into SceneAlgo.
		return false;
	}

	ConstCompoundObjectPtr attributes = scene->fullAttributes( path );
	const M44f transform = scene->fullTransform( path );

	std::string lightHandle;
	ScenePlug::pathToString( path, lightHandle );

	LightPtr light = constLight->copy();
	light->setHandle( lightHandle );

	{
		AttributeBlock attributeBlock( renderer );

		renderer->setAttribute( "name", new StringData( lightHandle ) );
		outputAttributes( attributes.get(), renderer );

		renderer->concatTransform( transform );

		light->render( renderer );
	}

	renderer->illuminate( lightHandle, true );

	return true;
}
Example #12
0
IECore::ConstCompoundObjectPtr Prune::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const
{	
	ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue();
	const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets" );
	if( !inputSets )
	{
		return inputGlobals;
	}

	CompoundObjectPtr outputGlobals = inputGlobals->copy();
	CompoundDataPtr outputSets = new CompoundData;
	outputGlobals->members()["gaffer:sets"] = outputSets;
	
	ContextPtr tmpContext = new Context( *Context::current() );
	Context::Scope scopedContext( tmpContext );
	ScenePath path;

	for( CompoundDataMap::const_iterator it = inputSets->readable().begin(), eIt = inputSets->readable().end(); it != eIt; ++it )
	{
		/// \todo This could be more efficient if PathMatcher exposed the internal nodes,
		/// and allowed sharing between matchers. Then we could do a really lightweight copy
		/// and just trim out the nodes we didn't want.
		const PathMatcher &inputSet = static_cast<const PathMatcherData *>( it->second.get() )->readable();
		PathMatcher &outputSet = outputSets->member<PathMatcherData>( it->first, /* throwExceptions = */ false, /* createIfMissing = */ true )->writable();
		
		vector<string> inputPaths;
		inputSet.paths( inputPaths );
		for( vector<string>::const_iterator pIt = inputPaths.begin(), peIt = inputPaths.end(); pIt != peIt; ++pIt )
		{
			path.clear();
			ScenePlug::stringToPath( *pIt, path );
			
			tmpContext->set( ScenePlug::scenePathContextName, path );
			if( !(filterPlug()->getValue() & ( Filter::ExactMatch | Filter::AncestorMatch ) ) )
			{
				outputSet.addPath( *pIt );
			}
		}
	}
	
	return outputGlobals;
}
Example #13
0
IECore::CameraPtr GafferScene::camera( const ScenePlug *scene, const IECore::CompoundObject *globals )
{
	ConstCompoundObjectPtr computedGlobals;
	if( !globals )
	{
		computedGlobals = scene->globalsPlug()->getValue();
		globals = computedGlobals.get();
	}

	if( const StringData *cameraPathData = globals->member<StringData>( "option:render:camera" ) )
	{
		ScenePlug::ScenePath cameraPath;
		ScenePlug::stringToPath( cameraPathData->readable(), cameraPath );
		return camera( scene, cameraPath, globals );
	}
	else
	{
		CameraPtr defaultCamera = new IECore::Camera();
		applyCameraGlobals( defaultCamera.get(), globals );
		return defaultCamera;
	}
}
Example #14
0
IECore::ImagePrimitivePtr ImagePlug::image() const
{
    Format format = formatPlug()->getValue();
    Box2i dataWindow = dataWindowPlug()->getValue();
    Box2i newDataWindow( Imath::V2i(0) );

    if( dataWindow.isEmpty() )
    {
        dataWindow = Box2i( Imath::V2i(0) );
    }
    else
    {
        newDataWindow = format.yDownToFormatSpace( dataWindow );
    }

    ImagePrimitivePtr result = new ImagePrimitive( newDataWindow, format.getDisplayWindow() );

    ConstCompoundObjectPtr metadata = metadataPlug()->getValue();
    compoundObjectToCompoundData( metadata.get(), result->blindData() );

    ConstStringVectorDataPtr channelNamesData = channelNamesPlug()->getValue();
    const vector<string> &channelNames = channelNamesData->readable();

    vector<float *> imageChannelData;
    for( vector<string>::const_iterator it = channelNames.begin(), eIt = channelNames.end(); it!=eIt; it++ )
    {
        FloatVectorDataPtr cd = new FloatVectorData;
        vector<float> &c = cd->writable();
        c.resize( result->variableSize( PrimitiveVariable::Vertex ), 0.0f );
        result->variables[*it] = PrimitiveVariable( PrimitiveVariable::Vertex, cd );
        imageChannelData.push_back( &(c[0]) );
    }

    parallel_for( blocked_range2d<size_t>( 0, dataWindow.size().x+1, tileSize(), 0, dataWindow.size().y+1, tileSize() ),
                  GafferImage::Detail::CopyTiles( imageChannelData, channelNames, channelDataPlug(), dataWindow, Context::current(), tileSize()) );

    return result;
}
Example #15
0
ConstCompoundObjectPtr SetVisualiser::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, ConstCompoundObjectPtr inputAttributes ) const
{
	CompoundObjectPtr result = new CompoundObject;

	// Since we're not going to modify any existing members (only add a new one),
	// and our result becomes const on returning it, we can directly reference
	// the input members in our result without copying. Be careful not to modify
	// them though!
	result->members() = inputAttributes->members();

	ConstCompoundDataPtr outSetsData = outSetsPlug()->getValue();
	const InternedStringVectorData *setNamesData = outSetsData->member<InternedStringVectorData>( "names" );
	const Color3fVectorData *setColorsData = outSetsData->member<Color3fVectorData>( "colors" );

	int matchResult = PathMatcher::ExactMatch;
	if( includeInheritedPlug()->getValue() )
	{
		matchResult |= PathMatcher::AncestorMatch;
	}

	ConstCompoundDataPtr targetSets = SceneAlgo::sets( inPlug(), setNamesData->readable() );
	std::vector<Color3f> shaderColors;

	size_t index = 0;
	for( auto &setName : setNamesData->readable() )
	{
		const PathMatcherData *pathMatchData = targetSets->member<const PathMatcherData>( setName );
		if( pathMatchData->readable().match( path ) & matchResult )
		{
			shaderColors.push_back( setColorsData->readable()[ index ] );
		}
		// We need to pass our colors to the shader as a fixed size array
		if( shaderColors.size() == g_maxShaderColors )
		{
			break;
		}
		++index;
	}

	// Avoids shader compilation errors as its expecting g_maxShaderColors elements
	const size_t numColorsUsed = shaderColors.size();
	shaderColors.resize( g_maxShaderColors );

	result->members()["gl:surface"] = stripeShader( stripeWidthPlug()->getValue(), numColorsUsed, shaderColors );

	return result;
}
Example #16
0
Parameter::Parameter( const std::string &name, const std::string &description, ObjectPtr defaultValue,
                      const PresetsContainer &presets, bool presetsOnly, ConstCompoundObjectPtr userData )
    :	m_name( name ), m_description( description ), m_defaultValue( defaultValue ), m_presetsOnly( presetsOnly ),
      m_userData( userData ? userData->copy() : 0 )
{
    if ( !defaultValue )
    {
        throw Exception( "Invalid NULL default value!" );
    }

    for( PresetsContainer::const_iterator it=presets.begin(); it!=presets.end(); it++ )
    {
        m_presets.push_back( PresetsContainer::value_type( it->first, it->second->copy() ) );
    }

    /// \todo If presetsOnly is true, doesn't this allow us to set a defaultValue that isn't in the presets list?
    setValue( defaultValue->copy() );
}
Example #17
0
void outputScene( const ScenePlug *scene, IECore::Renderer *renderer )
{
	ConstCompoundObjectPtr globals = scene->globalsPlug()->getValue();
	outputOptions( globals.get(), renderer );
	outputOutputs( globals.get(), renderer );
	outputCamera( scene, globals.get(), renderer );
	{
		WorldBlock world( renderer );

		outputGlobalAttributes( globals.get(), renderer );
		outputCoordinateSystems( scene, globals.get(), renderer );
		outputLights( scene, globals.get(), renderer );

		SceneProceduralPtr proc = new SceneProcedural( scene, Context::current() );
		renderer->procedural( proc );
	}
}
IECore::ConstCompoundObjectPtr AppleseedShaderAdaptor::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const
{
	ConstCompoundObjectPtr inputAttributes = inPlug()->attributesPlug()->getValue();

	/// \todo Drop support for "osl:shader" assignments. They were never desirable, and the ShaderAssignment node
	/// no longer makes them.
	const ShaderNetwork *shaderNetwork = inputAttributes->member<const ShaderNetwork>( g_oslShaderAttributeName );
	if( !shaderNetwork )
	{
		shaderNetwork = inputAttributes->member<const ShaderNetwork>( g_oslSurfaceAttributeName );
	}
	if( !shaderNetwork )
	{
		return inputAttributes;
	}

	const Shader *outputShader = shaderNetwork->outputShader();
	if( !outputShader )
	{
		return inputAttributes;
	}

	OSLQuery::Parameter *firstOutput = firstOutputParameter( outputShader->getName() );

	// Build an adaptor network

	ShaderNetworkPtr adaptedNetwork;
	if( firstOutput && firstOutput->isclosure )
	{
		adaptedNetwork = shaderNetwork->copy();
		ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" );
		InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) );
		adaptedNetwork->addConnection(
			{ { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { materialHandle, g_bsdfParameterName } }
		);
		adaptedNetwork->setOutput( materialHandle );

	}
	else if( firstOutput && firstOutput->type == TypeDesc::TypeColor )
	{
		adaptedNetwork = shaderNetwork->copy();
		ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" );
		InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) );
		adaptedNetwork->addConnection(
			{ { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { emissionHandle, "Color" } }
		);

		ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" );
		InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) );
		adaptedNetwork->addConnection(
			{ { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } }
		);

		adaptedNetwork->setOutput( materialHandle );
	}
	else if( firstOutput && ( firstOutput->type == TypeDesc::TypeFloat || firstOutput->type == TypeDesc::TypeInt ) )
	{
		adaptedNetwork = shaderNetwork->copy();
		ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" );
		InternedString colorBuildHandle = adaptedNetwork->addShader( "colorBuild", std::move( colorBuild ) );
		for( const auto &channel : { "R", "G", "B" } )
		{
			adaptedNetwork->addConnection(
				{ { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { colorBuildHandle, channel } }
			);
		}

		ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" );
		InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) );
		adaptedNetwork->addConnection(
			{ { colorBuildHandle, "ColorOut" }, { emissionHandle, "Color" } }
		);

		ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" );
		InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) );
		adaptedNetwork->addConnection(
			{ { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } }
		);
		adaptedNetwork->setOutput( materialHandle );
	}
	else if( firstOutput && firstOutput->type == TypeDesc::TypeVector )
	{
		adaptedNetwork = shaderNetwork->copy();
		ShaderPtr vectorSplit = new Shader( "vector/as_vector_split", "osl:shader" );
		InternedString vectorSplitHandle = adaptedNetwork->addShader( "vectorSplit", std::move( vectorSplit ) );
		adaptedNetwork->addConnection(
			{ { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { vectorSplitHandle, "Vector" } }
		);

		ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" );
		InternedString colorBuildHandle = adaptedNetwork->addShader( "colorBuild", std::move( colorBuild ) );
		for( const auto &c : { make_pair( "X", "R" ), make_pair( "Y", "G" ), make_pair( "Z", "B" ) } )
		{
			adaptedNetwork->addConnection(
				{ { vectorSplitHandle, c.first }, { colorBuildHandle, c.second } }
			);
		}

		ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" );
		InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) );
		adaptedNetwork->addConnection(
			{ { colorBuildHandle, "ColorOut" }, { emissionHandle, "Color" } }
		);

		ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" );
		InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) );
		adaptedNetwork->addConnection(
			{ { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } }
		);
		adaptedNetwork->setOutput( materialHandle );
	}
	else
	{
		// Shader has no output, or an output we can't map sensibly.
		// Make an "error" shader.
		adaptedNetwork = new ShaderNetwork;
		ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" );
		emission->parameters()["Color"] = new Color3fData( Imath::Color3f( 1, 0, 0 ) );
		InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) );

		ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" );
		InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) );
		adaptedNetwork->addConnection(
			{ { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } }
		);
		adaptedNetwork->setOutput( materialHandle );
	}

	// Place the new network into the "osl:surface" attribute
	// and remove the "osl:shader" attribute.

	CompoundObjectPtr outputAttributes = new CompoundObject;
	outputAttributes->members() = inputAttributes->members(); // Shallow copy for speed - do not modify in place!
	outputAttributes->members()[g_oslSurfaceAttributeName] = adaptedNetwork;
	outputAttributes->members().erase( g_oslShaderAttributeName );

	return outputAttributes;
}
Example #19
0
void InteractiveRender::update()
{
	Context::Scope scopedContext( m_context.get() );

	const State requiredState = (State)statePlug()->getValue();
	ConstScenePlugPtr requiredScene = inPlug()->getInput<ScenePlug>();

	// Stop the current render if it's not what we want,
	// and early-out if we don't want another one.

	if( !requiredScene || requiredScene != m_scene || requiredState == Stopped )
	{
		// stop the current render
		m_renderer = NULL;
		m_scene = NULL;
		m_state = Stopped;
		m_lightHandles.clear();
		m_shadersDirty = m_lightsDirty = m_cameraDirty = true;
		if( !requiredScene || requiredState == Stopped )
		{
			return;
		}
	}

	// If we've got this far, we know we want to be running or paused.
	// Start a render if we don't have one.

	if( !m_renderer )
	{
		m_renderer = createRenderer();
		m_renderer->setOption( "editable", new BoolData( true ) );

		ConstCompoundObjectPtr globals = inPlug()->globalsPlug()->getValue();
		outputOptions( globals.get(), m_renderer.get() );
		outputOutputs( globals.get(), m_renderer.get() );
		outputCamera( inPlug(), globals.get(), m_renderer.get() );
		{
			WorldBlock world( m_renderer );

			outputGlobalAttributes( globals.get(), m_renderer.get() );
			outputCoordinateSystems( inPlug(), globals.get(), m_renderer.get() );
			outputLightsInternal( globals.get(), /* editing = */ false );

			SceneProceduralPtr proc = new SceneProcedural( inPlug(), Context::current() );
			m_renderer->procedural( proc );
		}

		m_scene = requiredScene;
		m_state = Running;
		m_lightsDirty = m_shadersDirty = m_cameraDirty = false;
	}

	// Make sure the paused/running state is as we want.

	if( requiredState != m_state )
	{
		if( requiredState == Paused )
		{
			m_renderer->editBegin( "suspendrendering", CompoundDataMap() );
		}
		else
		{
			m_renderer->editEnd();
		}
		m_state = requiredState;
	}

	// If we're not paused, then send any edits we need.

	if( m_state == Running )
	{
		updateLights();
		updateShaders();
		updateCamera();
		updateCoordinateSystems();
	}
}
Example #20
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() );
	}	
}
IECore::ConstCompoundObjectPtr AppleseedShaderAdaptor::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const
{
	ConstCompoundObjectPtr inputAttributes = inPlug()->attributesPlug()->getValue();

	const ObjectVector *shaderNetwork = inputAttributes->member<const ObjectVector>( g_oslShaderAttributeName );
	if( !shaderNetwork || shaderNetwork->members().empty() )
	{
		return inputAttributes;
	}

	const Shader *rootShader = runTimeCast<const Shader>( shaderNetwork->members().back().get() );
	if( !rootShader )
	{
		return inputAttributes;
	}

	OSLQuery::Parameter *firstOutput = firstOutputParameter( rootShader->getName() );

	// Build an adapter network if we can.

	bool prependInputNetwork = true;
	vector<ShaderPtr> adapters;
	if( firstOutput && firstOutput->isclosure )
	{
		ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" );
		material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterInputHandle." + firstOutput->name.string() );
		adapters.push_back( material );
	}
	else if( firstOutput && firstOutput->type == TypeDesc::TypeColor )
	{
		ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" );
		emission->parameters()["Color"] = new StringData( "link:adapterInputHandle." + firstOutput->name.string() );
		emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" );

		ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" );
		material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" );

		adapters.push_back( emission );
		adapters.push_back( material );
	}
	else if( firstOutput && ( firstOutput->type == TypeDesc::TypeFloat || firstOutput->type == TypeDesc::TypeInt ) )
	{
		ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" );
		StringDataPtr colorLink = new StringData( "link:adapterInputHandle." + firstOutput->name.string() );
		colorBuild->parameters()["R"] = colorLink;
		colorBuild->parameters()["G"] = colorLink;
		colorBuild->parameters()["B"] = colorLink;
		colorBuild->parameters()[g_handleParameterName] = new StringData( "adapterColorBuildHandle" );

		ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" );
		emission->parameters()["Color"] = new StringData( "link:adapterColorBuildHandle.ColorOut" );
		emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" );

		ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" );
		material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" );

		adapters.push_back( colorBuild );
		adapters.push_back( emission );
		adapters.push_back( material );
	}
	else if( firstOutput && firstOutput->type == TypeDesc::TypeVector )
	{
		ShaderPtr vectorSplit = new Shader( "vector/as_vector_split", "osl:shader" );
		vectorSplit->parameters()["Vector"] = new StringData( "link:adapterInputHandle." + firstOutput->name.string() );
		vectorSplit->parameters()[g_handleParameterName] = new StringData( "adapterVectorSplit" );

		ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" );
		colorBuild->parameters()["R"] = new StringData( "link:adapterVectorSplit.X" );
		colorBuild->parameters()["G"] = new StringData( "link:adapterVectorSplit.Y" );
		colorBuild->parameters()["B"] = new StringData( "link:adapterVectorSplit.Z" );
		colorBuild->parameters()[g_handleParameterName] = new StringData( "adapterColorBuildHandle" );

		ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" );
		emission->parameters()["Color"] = new StringData( "link:adapterColorBuildHandle.ColorOut" );
		emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" );

		ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" );
		material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" );

		adapters.push_back( vectorSplit );
		adapters.push_back( colorBuild );
		adapters.push_back( emission );
		adapters.push_back( material );
	}
	else
	{
		// Shader has no output, or an output we can't map sensibly.
		// Make an "error" shader.
		ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" );
		emission->parameters()["Color"] = new Color3fData( Imath::Color3f( 1, 0, 0 ) );
		emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" );

		ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" );
		material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" );

		adapters.push_back( emission );
		adapters.push_back( material );

		prependInputNetwork = false; // We don't need the original shaders at all
	}

	// Make a new network with the adapter network
	// appended onto the input network

	ObjectVectorPtr adaptedNetwork = new ObjectVector();

	if( prependInputNetwork )
	{
		adaptedNetwork->members() = shaderNetwork->members(); // Shallow copy for speed - do not modify in place!

		ShaderPtr rootShaderCopy = rootShader->copy();
		rootShaderCopy->parameters()[g_handleParameterName] = new StringData( "adapterInputHandle" );;
		adaptedNetwork->members().back() = rootShaderCopy;
	}

	std::copy( adapters.begin(), adapters.end(), back_inserter( adaptedNetwork->members() ) );

	// Place the new network into the "osl:surface" attribute
	// and remove the "osl:shader" attribute.

	CompoundObjectPtr outputAttributes = new CompoundObject;
	outputAttributes->members() = inputAttributes->members(); // Shallow copy for speed - do not modify in place!
	outputAttributes->members()[g_oslSurfaceAttributeName] = adaptedNetwork;
	outputAttributes->members().erase( g_oslShaderAttributeName );

	return outputAttributes;
}
Example #22
0
ObjectPtr EnvMapSampler::doOperation( const CompoundObject * operands )
{
	ImagePrimitivePtr image = static_cast<ImagePrimitive *>( imageParameter()->getValue() )->copy();
	Box2i dataWindow = image->getDataWindow();

	// find the rgb channels
	ConstFloatVectorDataPtr redData = image->getChannel<float>( "R" );
	ConstFloatVectorDataPtr greenData = image->getChannel<float>( "G" );
	ConstFloatVectorDataPtr blueData = image->getChannel<float>( "B" );
	if( !(redData && greenData && blueData) )
	{
		throw Exception( "Image does not contain valid RGB float channels." );
	}
	const vector<float> &red = redData->readable();
	const vector<float> &green = greenData->readable();
	const vector<float> &blue = blueData->readable();

	// get a luminance channel
	LuminanceOpPtr luminanceOp = new LuminanceOp();
	luminanceOp->inputParameter()->setValue( image );
	luminanceOp->copyParameter()->getTypedValue() = false;
	luminanceOp->removeColorPrimVarsParameter()->getTypedValue() = false;
	luminanceOp->operate();

	// do the median cut thing to get some samples
	MedianCutSamplerPtr sampler = new MedianCutSampler;
	sampler->imageParameter()->setValue( image );
	sampler->subdivisionDepthParameter()->setNumericValue( subdivisionDepthParameter()->getNumericValue() );
	ConstCompoundObjectPtr samples = boost::static_pointer_cast<CompoundObject>( sampler->operate() );
	const vector<V2f> &centroids = boost::static_pointer_cast<V2fVectorData>( samples->members().find( "centroids" )->second )->readable();
	const vector<Box2i> &areas = boost::static_pointer_cast<Box2iVectorData>( samples->members().find( "areas" )->second )->readable();

	// get light directions and colors from the samples
	V3fVectorDataPtr directionsData = new V3fVectorData;
	Color3fVectorDataPtr colorsData = new Color3fVectorData;
	vector<V3f> &directions = directionsData->writable();
	vector<Color3f> &colors = colorsData->writable();

	float radiansPerPixel = M_PI / (dataWindow.size().y + 1);
	float angleAtTop = ( M_PI - radiansPerPixel ) / 2.0f;

	for( unsigned i=0; i<centroids.size(); i++ )
	{
		const Box2i &area = areas[i];
		Color3f color( 0 );
		for( int y=area.min.y; y<=area.max.y; y++ )
		{
			int yRel = y - dataWindow.min.y;

			float angle = angleAtTop - yRel * radiansPerPixel;
			float weight = cosf( angle );
			int index = (area.min.x - dataWindow.min.x) + (dataWindow.size().x + 1 ) * yRel;
			for( int x=area.min.x; x<=area.max.x; x++ )
			{
				color[0] += weight * red[index];
				color[1] += weight * green[index];
				color[2] += weight * blue[index];
				index++;
			}
		}
		color /= red.size();
		colors.push_back( color );

		float phi = angleAtTop - (centroids[i].y - dataWindow.min.y) * radiansPerPixel;

		V3f direction;
		direction.y = sinf( phi );
		float r = cosf( phi );
		float theta = 2 * M_PI * lerpfactor( (float)centroids[i].x, (float)dataWindow.min.x, (float)dataWindow.max.x );
		direction.x = r * cosf( theta );
		direction.z = r * sinf( theta );

		directions.push_back( -direction ); // negated so we output the direction the light shines in
	}

	// return the result
	CompoundObjectPtr result = new CompoundObject;
	result->members()["directions"] = directionsData;
	result->members()["colors"] = colorsData;
	return result;
}
Example #23
0
IECore::ConstCompoundObjectPtr BranchCreator::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue();

	ConstCompoundDataPtr mapping = boost::static_pointer_cast<const CompoundData>( mappingPlug()->getValue() );
	if( !mapping->readable().size() )
	{
		return inputGlobals;
	}

	const CompoundData *branchSets = NULL;
	ConstCompoundObjectPtr branchGlobals = computeBranchGlobals( mapping->member<InternedStringVectorData>( g_parentKey )->readable(), context );
	if( branchGlobals )
	{
		branchSets = branchGlobals->member<CompoundData>( "gaffer:sets", /* throwExceptions = */ false );
	}
	if( !branchSets )
	{
		return inputGlobals;
	}

	IECore::CompoundObjectPtr outputGlobals = new CompoundObject;
	// Shallow copy of the input, because most of it will remain unchanged.
	outputGlobals->members() = inputGlobals->members();
	// Deep copy of the input sets, because we'll be modifying them.
	const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets", /* throwExeptions = */ false );
	CompoundDataPtr outputSets = inputSets ? inputSets->copy() : new CompoundData;
	outputGlobals->members()["gaffer:sets"] = outputSets;

	const CompoundData *forwardMapping = mapping->member<CompoundData>( g_forwardMappingKey );

	string parentString;
	ScenePlug::pathToString( mapping->member<InternedStringVectorData>( g_parentKey )->readable(), parentString );
	if( !boost::ends_with( parentString, "/" ) )
	{
		parentString += "/";
	}

	for( CompoundDataMap::const_iterator it = branchSets->readable().begin(), eIt = branchSets->readable().end(); it != eIt; ++it )
	{
		const PathMatcher &branchSet = static_cast<const PathMatcherData *>( it->second.get() )->readable();
		PathMatcher &outputSet = outputSets->member<PathMatcherData>( it->first, /* throwExceptions = */ false, /* createIfMissing = */ true )->writable();

		/// \todo If PathMatcher allowed us to rename nodes and merge in other PathMatchers, this could
		/// be much more efficient.
		vector<string> branchPaths;
		branchSet.paths( branchPaths );
		for( vector<string>::const_iterator pIt = branchPaths.begin(), peIt = branchPaths.end(); pIt != peIt; ++pIt )
		{
			const string &branchPath = *pIt;
			const size_t secondSlashPos = branchPath.find( '/', 1 );
			const std::string branchName( branchPath, 1, secondSlashPos - 1 );
			const InternedStringData *outputName = forwardMapping->member<InternedStringData>( branchName );
			if( !outputName )
			{
				// See comments in Group::computeGlobals().
				continue;
			}

			std::string outputPath = parentString + outputName->readable().string();
			if( secondSlashPos != string::npos )
			{
				outputPath += branchPath.substr( secondSlashPos );
			}
			outputSet.addPath( outputPath );
		}
	}

	return outputGlobals;
}
Example #24
0
void InteractiveRender::update()
{
	Context::Scope scopedContext( m_context.get() );

	const State requiredState = (State)statePlug()->getValue();
	ConstScenePlugPtr requiredScene = inPlug()->getInput<ScenePlug>();

	// Stop the current render if it's not what we want,
	// and early-out if we don't want another one.

	if( !requiredScene || requiredScene != m_scene || requiredState == Stopped )
	{
		stop();
		if( !requiredScene || requiredState == Stopped )
		{
			return;
		}
	}

	// no point doing an update if the scene's empty
	if( inPlug()->childNames( ScenePlug::ScenePath() )->readable().empty() )
	{
		stop();
		return;
	}

	// If we've got this far, we know we want to be running or paused.
	// Start a render if we don't have one.

	if( !m_renderer )
	{
		m_renderer = createRenderer();
		m_renderer->setOption( "editable", new BoolData( true ) );

		ConstCompoundObjectPtr globals = inPlug()->globalsPlug()->getValue();
		outputOptions( globals.get(), m_renderer.get() );
		outputOutputs( globals.get(), m_renderer.get() );
		outputCameras( inPlug(), globals.get(), m_renderer.get() );
		outputClippingPlanes( inPlug(), globals.get(), m_renderer.get() );
		{
			WorldBlock world( m_renderer );

			outputGlobalAttributes( globals.get(), m_renderer.get() );
			outputCoordinateSystems( inPlug(), globals.get(), m_renderer.get() );
			outputLightsInternal( globals.get(), /* editing = */ false );

			// build the scene graph structure in parallel:
			m_sceneGraph.reset( new SceneGraph );
			SceneGraphBuildTask *task = new( tbb::task::allocate_root() ) SceneGraphBuildTask( inPlug(), m_context.get(), m_sceneGraph.get(), ScenePlug::ScenePath() );
			tbb::task::spawn_root_and_wait( *task );

			// output the scene for the first time:
			outputScene( false );
		}

		m_scene = requiredScene;
		m_state = Running;
		m_lightsDirty = m_attributesDirty = m_camerasDirty = false;
	}

	// Make sure the paused/running state is as we want.

	if( requiredState != m_state )
	{
		if( requiredState == Paused )
		{
			m_renderer->editBegin( "suspendrendering", CompoundDataMap() );
		}
		else
		{
			m_renderer->editEnd();
		}
		m_state = requiredState;
	}

	// If we're not paused, then send any edits we need.

	if( m_state == Running )
	{
		EditBlock edit( m_renderer.get(), "suspendrendering", CompoundDataMap() );
		updateLights();
		updateAttributes();
		updateCameras();
		updateCoordinateSystems();
	}
}
Example #25
0
void Render::outputLights( const ScenePlug *scene, const IECore::CompoundObject *globals, IECore::Renderer *renderer ) const
{
	const CompoundData *forwardDeclarations = globals->member<CompoundData>( "gaffer:forwardDeclarations" );
	if( !forwardDeclarations )
	{
		return;
	}

	CompoundDataMap::const_iterator it, eIt;
	for( it = forwardDeclarations->readable().begin(), eIt = forwardDeclarations->readable().end(); it != eIt; it++ )
	{
		const CompoundData *declaration = runTimeCast<const CompoundData>( it->second.get() );
		if( !declaration )
		{
			continue;
		}
		
		const IECore::TypeId type = (IECore::TypeId)declaration->member<IntData>( "type", true )->readable();
		if( type != IECore::LightTypeId )
		{
			continue;
		}
		
		ScenePlug::ScenePath path;
		ScenePlug::stringToPath( it->first.string(), path );
		
		IECore::ConstLightPtr constLight = runTimeCast<const IECore::Light>( scene->object( path ) );
		if( !constLight )
		{
			continue;
		}
		
		ConstCompoundObjectPtr attributes = scene->fullAttributes( path );
		const BoolData *visibilityData = attributes->member<BoolData>( "gaffer:visibility" );
		if( visibilityData && !visibilityData->readable() )
		{
			continue;
		}
		
		M44f transform = scene->fullTransform( path );
		
		LightPtr light = constLight->copy();
		light->setHandle( it->first.string() );
		
		{
			AttributeBlock attributeBlock( renderer );
		
			renderer->setAttribute( "name", new StringData( it->first ) );
		
			CompoundObject::ObjectMap::const_iterator aIt, aeIt;
			for( aIt = attributes->members().begin(), aeIt = attributes->members().end(); aIt != aeIt; aIt++ )
			{
				if( const Data *attribute = runTimeCast<const Data>( aIt->second.get() ) )
				{
					renderer->setAttribute( aIt->first.string(), attribute );
				}
			}
		
			renderer->concatTransform( transform );
			light->render( renderer );
		}
		
		renderer->illuminate( light->getHandle(), true );
	}
}