예제 #1
0
// general cortex render function, takes a gu_detail and uses the NodePassData attribute
// to call the required render method
void GR_Cortex::render( GU_Detail *gdp, const IECoreGL::State *displayState )
{
	// gl scene from a parameterised procedural
	const GA_ROAttributeRef attrRef = gdp->findAttribute( GA_ATTRIB_DETAIL, GA_SCOPE_PRIVATE, "IECoreHoudiniNodePassData" );
	if ( attrRef.isInvalid() )
	{
		return;
	}
	
	const GA_Attribute *attr = attrRef.getAttribute();
	const GA_AIFBlindData *blindData = attr->getAIFBlindData();
	const NodePassData passData = blindData->getValue<NodePassData>( attr, 0 );
	
	switch( passData.type() )
	{
		case IECoreHoudini::NodePassData::CORTEX_OPHOLDER :
		{
			SOP_OpHolder *sop = dynamic_cast<SOP_OpHolder*>( const_cast<OP_Node*>( passData.nodePtr() ) );
			if ( !sop )
			{
				return;
			}

			IECore::OpPtr op = IECore::runTimeCast<IECore::Op>( sop->getParameterised() );
			if ( !op )
			{
				return;
			}

			const IECore::Parameter *result_parameter = op->resultParameter();
			const IECore::Object *result_object = result_parameter->getValue();
			renderObject( result_object, displayState );
			break;
		}
		case IECoreHoudini::NodePassData::CORTEX_PROCEDURALHOLDER :
		{
			SOP_ProceduralHolder *sop = dynamic_cast<SOP_ProceduralHolder*>( const_cast<OP_Node*>( passData.nodePtr() ) );
			if ( !sop )
			{
				return;
			}

			IECoreGL::ConstScenePtr scene = sop->scene();
			if ( !scene )
			{
				return;
			}

			scene->render( const_cast<IECoreGL::State *>( displayState ) );
			break;
		}
		default :
		{
			break;
		}
	}
}
예제 #2
0
MStatus OpHolder<B>::compute( const MPlug &plug, MDataBlock &block )
{
	IECore::OpPtr op = getOp();

	if (op)
	{
		MFnDependencyNode fnDN( B::thisMObject() );
		MPlug resultPlug( B::thisMObject(), fnDN.attribute( "result" ) );

		if (plug != resultPlug)
		{
			return MS::kUnknownParameter;
		}

		IECore::ObjectPtr result;

		try
		{
			ParameterisedHolder<B>::setParameterisedValues( true /* lazy */ );
			result = op->operate();
			if (!result)
			{
				return MS::kFailure;
			}
		}
		catch( std::exception &e )
		{
			MGlobal::displayError( e.what() );
			return MS::kFailure;
		}
		catch( boost::python::error_already_set & )
		{
			IECorePython::ScopedGILLock lock;
			PyErr_Print();
			return MS::kFailure;
		}
		catch (...)
		{
			return MS::kFailure;
		}

		assert( result );
		MStatus s = ParameterHandler::setValue( op->resultParameter(), resultPlug );

		block.setClean( resultPlug );

		return s;
	}

	return MS::kFailure;
}
예제 #3
0
MStatus OpHolder<B>::createResultAttribute()
{
	IECore::OpPtr op = IECore::runTimeCast<IECore::Op>( ParameterisedHolder<B>::m_parameterised );

	if( !op )
	{
		MString nodeName = ParameterisedHolder<B>::name();
		msg( Msg::Error, "OpHolder::createResultAttribute", boost::format( "No Op found on node \"%s\"." ) % nodeName.asChar() );
		return MStatus::kFailure;
	}
	
	MStatus s = ParameterisedHolder<B>::createOrUpdateAttribute( const_cast<IECore::Parameter *>( op->resultParameter() ), "result" );
	if( !s )
	{
		MString nodeName = ParameterisedHolder<B>::name();
		msg( Msg::Error, "OpHolder::createResultAttribute", boost::format( "Unable to update result attribute to represent class \"%s\" on node \"%s\"." ) % op->typeName() % nodeName.asChar() );
		return s;
	}
			
	MFnDependencyNode fnDN( B::thisMObject() );
	MObject attribute = fnDN.attribute( "result" );

	MFnAttribute fnAttr( attribute );
	fnAttr.setWritable( false );
	fnAttr.setStorable( false );
	
	return MStatus::kSuccess;
}
예제 #4
0
void SOP_ParameterisedHolder::setInputParameterValues( float now )
{
	for ( unsigned int i=0; i < m_inputParameters.size(); i++ )
	{
		useInputSource( i, m_dirty, false );
		
		IECore::ParameterPtr inputParameter = m_inputParameters[i];
		
		GU_DetailHandle inputHandle = inputGeoHandle( i );
		GU_DetailHandleAutoReadLock readHandle( inputHandle );
		const GU_Detail *inputGdp = readHandle.getGdp();
		if ( !inputGdp )
		{
			continue;
		}
		
		const GA_ROAttributeRef attrRef = inputGdp->findAttribute( GA_ATTRIB_DETAIL, GA_SCOPE_PRIVATE, "IECoreHoudiniNodePassData" );
		if ( attrRef.isValid() )
		{
			// looks like data passed from another ParameterisedHolder
			const GA_Attribute *attr = attrRef.getAttribute();
			const GA_AIFBlindData *blindData = attr->getAIFBlindData();
			const NodePassData passData = blindData->getValue<NodePassData>( attr, 0 );
			SOP_ParameterisedHolder *sop = dynamic_cast<SOP_ParameterisedHolder*>( const_cast<OP_Node*>( passData.nodePtr() ) );
			
			IECore::ConstObjectPtr result = 0;
			if ( passData.type() == IECoreHoudini::NodePassData::CORTEX_OPHOLDER )
			{
				IECore::OpPtr op = IECore::runTimeCast<IECore::Op>( sop->getParameterised() );
				result = op->resultParameter()->getValue();
			}
			else if ( passData.type() == IECoreHoudini::NodePassData::CORTEX_PROCEDURALHOLDER )
			{
				IECore::ParameterisedProcedural *procedural = IECore::runTimeCast<IECore::ParameterisedProcedural>( sop->getParameterised() );
				IECore::CapturingRendererPtr renderer = new IECore::CapturingRenderer();
				// We are acquiring and releasing the GIL here to ensure that it is released when we render. This has
				// to be done because a procedural might jump between c++ and python a few times (i.e. if it spawns
				// subprocedurals that are implemented in python). In a normal call to cookMySop, this wouldn't be an
				// issue, but if cookMySop was called from HOM, hou.Node.cook appears to be holding onto the GIL.
				IECorePython::ScopedGILLock gilLock;
				{
					IECorePython::ScopedGILRelease gilRelease;
					{
						IECore::WorldBlock worldBlock( renderer );
						procedural->render( renderer );
					}
				}
				result = IECore::runTimeCast<const IECore::Object>( renderer->world() );
			}
			else
			{
				continue;
			}
			
			try
			{
				inputParameter->setValidatedValue( IECore::constPointerCast<IECore::Object>( result ) );
			}
			catch ( const IECore::Exception &e )
			{
				addError( SOP_MESSAGE, e.what() );
			}
		}
		else
		{
			// looks like a regular Houdini detail
			IECore::ObjectParameterPtr objectParameter = IECore::runTimeCast<IECore::ObjectParameter>( inputParameter );
			if ( !objectParameter )
			{
				continue;
			}
			
			FromHoudiniGeometryConverterPtr converter = FromHoudiniGeometryConverter::create( inputHandle, objectParameter->validTypes() );
			if ( !converter )
			{
				continue;
			}
			
			// set converter parameters from the node values
			const CompoundParameter::ParameterVector &converterParameters = converter->parameters()->orderedParameters();
			for ( CompoundParameter::ParameterVector::const_iterator it=converterParameters.begin(); it != converterParameters.end(); ++it )
			{
				updateParameter( *it, now, "parm_" + inputParameter->name() + "_" );
			}
			
			try
			{
				IECore::ObjectPtr converted = converter->convert();
				if ( converted )
				{
					inputParameter->setValidatedValue( converted );
				}
			}
			catch ( const IECore::Exception &e )
			{
				addError( SOP_MESSAGE, e.what() );
			}
			catch ( std::runtime_error &e )
			{
				addError( SOP_MESSAGE, e.what() );
			}
		}
	}
}
예제 #5
0
/// Cook the SOP! This method does all the work
OP_ERROR SOP_OpHolder::cookMySop( OP_Context &context )
{
	IECore::MessageHandler::Scope handlerScope( getMessageHandler() );
	
	// some defaults and useful variables
	Imath::Box3f bbox( Imath::V3f(-1,-1,-1), Imath::V3f(1,1,1) );
	float now = context.getTime();

	// force eval of our nodes parameters with our hidden parameter expression
	evalInt( "__evaluateParameters", 0, now );

	// get our op
	IECore::OpPtr op = IECore::runTimeCast<IECore::Op>( getParameterised() );
	
	// check for a valid parameterised on this SOP
	if ( !op )
	{
		UT_String msg( "Op Holder has no parameterised class to operate on!" );
		addError( SOP_MESSAGE, msg );
		return error();
	}

	if( lockInputs(context)>=UT_ERROR_ABORT )
	{
		return error();
	}

	// start our work
	UT_Interrupt *boss = UTgetInterrupt();
	boss->opStart("Building OpHolder Geometry...");
	gdp->clearAndDestroy();
	
	setParameterisedValues( now );
	
	try
	{
		// make our Cortex op do it's thing...
		op->operate();

		// pass ourselves onto the GR_Cortex render hook
		IECoreHoudini::NodePassData data( this, IECoreHoudini::NodePassData::CORTEX_OPHOLDER );
		GA_RWAttributeRef attrRef = gdp->createAttribute( GA_ATTRIB_DETAIL, GA_SCOPE_PRIVATE, "IECoreHoudiniNodePassData", NULL, NULL, "blinddata" );
		GA_Attribute *attr = attrRef.getAttribute();
		const GA_AIFBlindData *blindData = attr->getAIFBlindData();
		blindData->setDataSize( attr, sizeof(IECoreHoudini::NodePassData), &data );

		// if our result is a visible renderable then set our bounds on our output gdp
		const IECore::Object *result = op->resultParameter()->getValue();
		IECore::ConstVisibleRenderablePtr renderable = IECore::runTimeCast<const IECore::VisibleRenderable>( result );
		if ( renderable )
		{
			Imath::Box3f bbox = renderable->bound();
			gdp->cube( bbox.min.x, bbox.max.x, bbox.min.y, bbox.max.y, bbox.min.z, bbox.max.z, 0, 0, 0, 1, 1 );
		}
	}
	catch( boost::python::error_already_set )
	{
		addError( SOP_MESSAGE, "Error raised during Python evaluation!" );
		IECorePython::ScopedGILLock lock;
		PyErr_Print();
	}
	catch( const IECore::Exception &e )
	{
		addError( SOP_MESSAGE, e.what() );
	}
	catch( const std::exception &e )
	{
		addError( SOP_MESSAGE, e.what() );
	}
	catch( ... )
	{
		addError( SOP_MESSAGE, "Caught unknown exception!" );
	}

	// tidy up & go home!
	boss->opEnd();
	unlockInputs();
	return error();
}