<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2011, 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 "OpenEXR/ImathBoxAlgo.h"

#include "boost/format.hpp"

#include "IECore/MessageHandler.h"
#include "IECore/MeshPrimitive.h"
#include "IECore/Camera.h"
#include "IECore/Transform.h"
#include "IECore/SimpleTypedData.h"
#include "IECore/CurvesPrimitive.h"

#include "IECoreArnold/private/RendererImplementation.h"
#include "IECoreArnold/ToArnoldMeshConverter.h"
#include "IECoreArnold/ToArnoldCameraConverter.h"
#include "IECoreArnold/ToArnoldCurvesConverter.h"

using namespace IECore;
using namespace IECoreArnold;
using namespace Imath;
using namespace std;
using namespace boost;

////////////////////////////////////////////////////////////////////////
// AttributeState implementation
////////////////////////////////////////////////////////////////////////

RendererImplementation::AttributeState::AttributeState()
{
	surfaceShader = AiNode( "utility" );
	attributes = new CompoundData;
}

RendererImplementation::AttributeState::AttributeState( const AttributeState &other )
{
	surfaceShader = other.surfaceShader;
	attributes = other.attributes->copy();
}
				
////////////////////////////////////////////////////////////////////////
// RendererImplementation implementation
////////////////////////////////////////////////////////////////////////

extern AtNodeMethods *ieDisplayDriverMethods;

IECoreArnold::RendererImplementation::RendererImplementation()
	:	m_defaultFilter( 0 )
{
	constructCommon( Render );
}

IECoreArnold::RendererImplementation::RendererImplementation( const std::string &assFileName )
	:	m_defaultFilter( 0 )
{
	m_assFileName = assFileName;
	constructCommon( AssGen );
}

IECoreArnold::RendererImplementation::RendererImplementation( const RendererImplementation &other )
{
	constructCommon( Procedural );
	m_transformStack.push( other.m_transformStack.top() );
	m_attributeStack.push( AttributeState( other.m_attributeStack.top() ) );
}

IECoreArnold::RendererImplementation::RendererImplementation( const AtNode *proceduralNode )
{
	constructCommon( Procedural );
	/// \todo Initialise stacks properly!!
	m_transformStack.push( M44f() );
	m_attributeStack.push( AttributeState() );
}

void IECoreArnold::RendererImplementation::constructCommon( Mode mode )
{
	m_mode = mode;
	if( mode != Procedural )
	{
		AiBegin();
	
		/// \todo Control with an option
		AiMsgSetConsoleFlags( AI_LOG_ALL );

		const char *pluginPaths = getenv( "ARNOLD_PLUGIN_PATH" );
		if( pluginPaths )
		{
			AiLoadPlugins( pluginPaths );
		}
		
		// create a generic filter we can use for all displays
		m_defaultFilter = AiNode( "gaussian_filter" );
		AiNodeSetStr( m_defaultFilter, "name", "ieCoreArnold:defaultFilter" );

		m_transformStack.push( M44f() );
		m_attributeStack.push( AttributeState() );
	}
}

IECoreArnold::RendererImplementation::~RendererImplementation()
{
	if( m_mode != Procedural )
	{
		AiEnd();
	}
}

////////////////////////////////////////////////////////////////////////
// options
////////////////////////////////////////////////////////////////////////

void IECoreArnold::RendererImplementation::setOption( const std::string &name, IECore::ConstDataPtr value )
{
	if( 0 == name.compare( 0, 3, "ai:" ) )
	{
		AtNode *options = AiUniverseGetOptions();
		const AtParamEntry *parameter = AiNodeEntryLookUpParameter( AiNodeGetNodeEntry( options ), name.c_str() + 3 );
		if( parameter )
		{
			ToArnoldConverter::setParameter( options, name.c_str() + 3, value );
			return;
		}
	}
	else if( 0 == name.compare( 0, 5, "user:" ) )
	{
		AtNode *options = AiUniverseGetOptions();
		ToArnoldConverter::setParameter( options, name.c_str(), value );
		return;
	}
	else if( name.find_first_of( ":" )!=string::npos )
	{
		// ignore options prefixed for some other renderer
		return;
	}
	
	msg( Msg::Warning, "IECoreArnold::RendererImplementation::setOption", format( "Unknown option \"%s\"." ) % name );	
}

IECore::ConstDataPtr IECoreArnold::RendererImplementation::getOption( const std::string &name ) const
{
	if( 0 == name.compare( 0, 3, "ai:" ) )
	{
		AtNode *options = AiUniverseGetOptions();
		return ToArnoldConverter::getParameter( options, name.c_str() + 3 );
	}
	else if( 0 == name.compare( 0, 5, "user:" ) )
	{
		AtNode *options = AiUniverseGetOptions();
		return ToArnoldConverter::getParameter( options, name.c_str() );
	}
	else if( name == "shutter" )
	{
		AtNode *camera = AiUniverseGetCamera();
		float start = AiNodeGetFlt( camera, "shutter_start" );
		float end = AiNodeGetFlt( camera, "shutter_end" );
		return new V2fData( V2f( start, end ) );
	}

	return 0;
}

void IECoreArnold::RendererImplementation::camera( const std::string &name, const IECore::CompoundDataMap &parameters )
{
	CameraPtr cortexCamera = new Camera( name, 0, new CompoundData( parameters ) );
	ToArnoldCameraConverterPtr converter = new ToArnoldCameraConverter( cortexCamera );
	AtNode *arnoldCamera = converter->convert();
	AtNode *options = AiUniverseGetOptions();
	AiNodeSetPtr( options, "camera", arnoldCamera );
	
	applyTransformToNode( arnoldCamera );
	
	ConstV2iDataPtr resolution = cortexCamera->parametersData()->member<V2iData>( "resolution" );
	AiNodeSetInt( options, "xres", resolution ? resolution->readable().x : 640 );
	AiNodeSetInt( options, "yres", resolution ? resolution->readable().y : 480 );
}

void IECoreArnold::RendererImplementation::display( const std::string &name, const std::string &type, const std::string &data, const IECore::CompoundDataMap &parameters )
{
	AtNode *driver = AiNode( type.c_str() );
	if( !driver )
	{
		msg( Msg::Error, "IECoreArnold::RendererImplementation::display", boost::format( "Unable to create display of type \"%s\"" ) % type );
		return;
	}
		
	string nodeName = boost::str( boost::format( "ieCoreArnold:display%d" ) % m_outputDescriptions.size() );
	AiNodeSetStr( driver, "name", nodeName.c_str() );
	
	const AtParamEntry *fileNameParameter = AiNodeEntryLookUpParameter( AiNodeGetNodeEntry( driver ), "filename" );
	if( fileNameParameter )
	{
		AiNodeSetStr( driver, AiParamGetName( fileNameParameter ), name.c_str() );
	}

	ToArnoldConverter::setParameters( driver, parameters );
	
	string d = data;
	if( d=="rgb" )
	{
		d = "RGB RGB";
	}
	else if( d=="rgba" )
	{
		d = "RGBA RGBA";
	}
	
	std::string outputDescription = str( format( "%s %s %s" ) % d.c_str() % AiNodeGetName( m_defaultFilter ) % nodeName.c_str() );
	m_outputDescriptions.push_back( outputDescription );
}

/////////////////////////////////////////////////////////////////////////////////////////
// world
/////////////////////////////////////////////////////////////////////////////////////////

void IECoreArnold::RendererImplementation::worldBegin()
{
	// reset transform stack
	if( m_transformStack.size() > 1 )
	{
		msg( Msg::Warning, "IECoreArnold::RendererImplementation::worldBegin", "Missing transformEnd() call detected." );
		while( m_transformStack.size() > 1 )
		{
			m_transformStack.pop();
		}
		m_transformStack.top() = M44f();
	}
	
	// specify default camera if none has been specified yet
	AtNode *options = AiUniverseGetOptions();

	if( !AiNodeGetPtr( options, "camera" ) )
	{
		// no camera has been specified - make a default one
		camera( "ieCoreArnold:defaultCamera", CompoundDataMap() );
	}

	// specify all the outputs
	AtArray *outputsArray = AiArrayAllocate( m_outputDescriptions.size(), 1, AI_TYPE_STRING );
	for( int i = 0, e = m_outputDescriptions.size(); i < e; i++ )
	{
		AiArraySetStr( outputsArray, 0, m_outputDescriptions[i].c_str() );
	}
	AiNodeSetArray( options, "outputs", outputsArray ); 

}

void IECoreArnold::RendererImplementation::worldEnd()
{
	if( m_mode == Render )
	{
		AiRender( AI_RENDER_MODE_CAMERA );
	}
	else if( m_mode == AssGen )
	{
		AiASSWrite( m_assFileName.c_str(), AI_NODE_ALL, true );
	}
}

/////////////////////////////////////////////////////////////////////////////////////////
// transforms
/////////////////////////////////////////////////////////////////////////////////////////

void IECoreArnold::RendererImplementation::transformBegin()
{
	m_transformStack.push( ( m_transformStack.top() ) );	
}
<commit_msg>Fixing bug which prevented the proper output of multiple displays.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2011, Image Engine Design Inc. All rights reserved.
//  Copyright (c) 2012, <NAME>. 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 "OpenEXR/ImathBoxAlgo.h"

#include "boost/format.hpp"

#include "IECore/MessageHandler.h"
#include "IECore/MeshPrimitive.h"
#include "IECore/Camera.h"
#include "IECore/Transform.h"
#include "IECore/SimpleTypedData.h"
#include "IECore/CurvesPrimitive.h"

#include "IECoreArnold/private/RendererImplementation.h"
#include "IECoreArnold/ToArnoldMeshConverter.h"
#include "IECoreArnold/ToArnoldCameraConverter.h"
#include "IECoreArnold/ToArnoldCurvesConverter.h"

using namespace IECore;
using namespace IECoreArnold;
using namespace Imath;
using namespace std;
using namespace boost;

////////////////////////////////////////////////////////////////////////
// AttributeState implementation
////////////////////////////////////////////////////////////////////////

RendererImplementation::AttributeState::AttributeState()
{
	surfaceShader = AiNode( "utility" );
	attributes = new CompoundData;
}

RendererImplementation::AttributeState::AttributeState( const AttributeState &other )
{
	surfaceShader = other.surfaceShader;
	attributes = other.attributes->copy();
}
				
////////////////////////////////////////////////////////////////////////
// RendererImplementation implementation
////////////////////////////////////////////////////////////////////////

extern AtNodeMethods *ieDisplayDriverMethods;

IECoreArnold::RendererImplementation::RendererImplementation()
	:	m_defaultFilter( 0 )
{
	constructCommon( Render );
}

IECoreArnold::RendererImplementation::RendererImplementation( const std::string &assFileName )
	:	m_defaultFilter( 0 )
{
	m_assFileName = assFileName;
	constructCommon( AssGen );
}

IECoreArnold::RendererImplementation::RendererImplementation( const RendererImplementation &other )
{
	constructCommon( Procedural );
	m_transformStack.push( other.m_transformStack.top() );
	m_attributeStack.push( AttributeState( other.m_attributeStack.top() ) );
}

IECoreArnold::RendererImplementation::RendererImplementation( const AtNode *proceduralNode )
{
	constructCommon( Procedural );
	/// \todo Initialise stacks properly!!
	m_transformStack.push( M44f() );
	m_attributeStack.push( AttributeState() );
}

void IECoreArnold::RendererImplementation::constructCommon( Mode mode )
{
	m_mode = mode;
	if( mode != Procedural )
	{
		AiBegin();
	
		/// \todo Control with an option
		AiMsgSetConsoleFlags( AI_LOG_ALL );

		const char *pluginPaths = getenv( "ARNOLD_PLUGIN_PATH" );
		if( pluginPaths )
		{
			AiLoadPlugins( pluginPaths );
		}
		
		// create a generic filter we can use for all displays
		m_defaultFilter = AiNode( "gaussian_filter" );
		AiNodeSetStr( m_defaultFilter, "name", "ieCoreArnold:defaultFilter" );

		m_transformStack.push( M44f() );
		m_attributeStack.push( AttributeState() );
	}
}

IECoreArnold::RendererImplementation::~RendererImplementation()
{
	if( m_mode != Procedural )
	{
		AiEnd();
	}
}

////////////////////////////////////////////////////////////////////////
// options
////////////////////////////////////////////////////////////////////////

void IECoreArnold::RendererImplementation::setOption( const std::string &name, IECore::ConstDataPtr value )
{
	if( 0 == name.compare( 0, 3, "ai:" ) )
	{
		AtNode *options = AiUniverseGetOptions();
		const AtParamEntry *parameter = AiNodeEntryLookUpParameter( AiNodeGetNodeEntry( options ), name.c_str() + 3 );
		if( parameter )
		{
			ToArnoldConverter::setParameter( options, name.c_str() + 3, value );
			return;
		}
	}
	else if( 0 == name.compare( 0, 5, "user:" ) )
	{
		AtNode *options = AiUniverseGetOptions();
		ToArnoldConverter::setParameter( options, name.c_str(), value );
		return;
	}
	else if( name.find_first_of( ":" )!=string::npos )
	{
		// ignore options prefixed for some other renderer
		return;
	}
	
	msg( Msg::Warning, "IECoreArnold::RendererImplementation::setOption", format( "Unknown option \"%s\"." ) % name );	
}

IECore::ConstDataPtr IECoreArnold::RendererImplementation::getOption( const std::string &name ) const
{
	if( 0 == name.compare( 0, 3, "ai:" ) )
	{
		AtNode *options = AiUniverseGetOptions();
		return ToArnoldConverter::getParameter( options, name.c_str() + 3 );
	}
	else if( 0 == name.compare( 0, 5, "user:" ) )
	{
		AtNode *options = AiUniverseGetOptions();
		return ToArnoldConverter::getParameter( options, name.c_str() );
	}
	else if( name == "shutter" )
	{
		AtNode *camera = AiUniverseGetCamera();
		float start = AiNodeGetFlt( camera, "shutter_start" );
		float end = AiNodeGetFlt( camera, "shutter_end" );
		return new V2fData( V2f( start, end ) );
	}

	return 0;
}

void IECoreArnold::RendererImplementation::camera( const std::string &name, const IECore::CompoundDataMap &parameters )
{
	CameraPtr cortexCamera = new Camera( name, 0, new CompoundData( parameters ) );
	ToArnoldCameraConverterPtr converter = new ToArnoldCameraConverter( cortexCamera );
	AtNode *arnoldCamera = converter->convert();
	AtNode *options = AiUniverseGetOptions();
	AiNodeSetPtr( options, "camera", arnoldCamera );
	
	applyTransformToNode( arnoldCamera );
	
	ConstV2iDataPtr resolution = cortexCamera->parametersData()->member<V2iData>( "resolution" );
	AiNodeSetInt( options, "xres", resolution ? resolution->readable().x : 640 );
	AiNodeSetInt( options, "yres", resolution ? resolution->readable().y : 480 );
}

void IECoreArnold::RendererImplementation::display( const std::string &name, const std::string &type, const std::string &data, const IECore::CompoundDataMap &parameters )
{
	AtNode *driver = AiNode( type.c_str() );
	if( !driver )
	{
		msg( Msg::Error, "IECoreArnold::RendererImplementation::display", boost::format( "Unable to create display of type \"%s\"" ) % type );
		return;
	}
		
	string nodeName = boost::str( boost::format( "ieCoreArnold:display%d" ) % m_outputDescriptions.size() );
	AiNodeSetStr( driver, "name", nodeName.c_str() );
	
	const AtParamEntry *fileNameParameter = AiNodeEntryLookUpParameter( AiNodeGetNodeEntry( driver ), "filename" );
	if( fileNameParameter )
	{
		AiNodeSetStr( driver, AiParamGetName( fileNameParameter ), name.c_str() );
	}

	ToArnoldConverter::setParameters( driver, parameters );
	
	string d = data;
	if( d=="rgb" )
	{
		d = "RGB RGB";
	}
	else if( d=="rgba" )
	{
		d = "RGBA RGBA";
	}
	
	std::string outputDescription = str( format( "%s %s %s" ) % d.c_str() % AiNodeGetName( m_defaultFilter ) % nodeName.c_str() );
	m_outputDescriptions.push_back( outputDescription );
}

/////////////////////////////////////////////////////////////////////////////////////////
// world
/////////////////////////////////////////////////////////////////////////////////////////

void IECoreArnold::RendererImplementation::worldBegin()
{
	// reset transform stack
	if( m_transformStack.size() > 1 )
	{
		msg( Msg::Warning, "IECoreArnold::RendererImplementation::worldBegin", "Missing transformEnd() call detected." );
		while( m_transformStack.size() > 1 )
		{
			m_transformStack.pop();
		}
		m_transformStack.top() = M44f();
	}
	
	// specify default camera if none has been specified yet
	AtNode *options = AiUniverseGetOptions();

	if( !AiNodeGetPtr( options, "camera" ) )
	{
		// no camera has been specified - make a default one
		camera( "ieCoreArnold:defaultCamera", CompoundDataMap() );
	}

	// specify all the outputs
	AtArray *outputsArray = AiArrayAllocate( m_outputDescriptions.size(), 1, AI_TYPE_STRING );
	for( int i = 0, e = m_outputDescriptions.size(); i < e; i++ )
	{
		AiArraySetStr( outputsArray, i, m_outputDescriptions[i].c_str() );
	}
	AiNodeSetArray( options, "outputs", outputsArray ); 

}

void IECoreArnold::RendererImplementation::worldEnd()
{
	if( m_mode == Render )
	{
		AiRender( AI_RENDER_MODE_CAMERA );
	}
	else if( m_mode == AssGen )
	{
		AiASSWrite( m_assFileName.c_str(), AI_NODE_ALL, true );
	}
}

/////////////////////////////////////////////////////////////////////////////////////////
// transforms
/////////////////////////////////////////////////////////////////////////////////////////

void IECoreArnold::RendererImplementation::transformBegin()
{
	m_transformStack.push( ( m_transformStack.top() ) );	
}

{'fraction_non_alphanumeric': 0.20387565603552685, 'fraction_numerical': 0.004592248687928947, 'mean_word_length': 2.9953629032258067, 'pattern_counts': {'":': 2, '<': 8, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1462619', 'n_tokens_mistral': 6084, 'n_tokens_neox': 5696, 'n_words': 1500}