Exemple #1
0
Imath::Box3f ObjectSource::computeBound( const SceneNode::ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	Imath::Box3f result;
	IECore::ConstObjectPtr object = sourcePlug()->getValue();

	if( const IECore::VisibleRenderable *renderable = IECore::runTimeCast<const IECore::VisibleRenderable>( object.get() ) )
	{
		result = renderable->bound();
	}
	else if( object->isInstanceOf( IECore::Camera::staticTypeId() ) )
	{
		result = Imath::Box3f( Imath::V3f( -0.5, -0.5, 0 ), Imath::V3f( 0.5, 0.5, 2.0 ) );
	}
	else if( object->isInstanceOf( IECore::CoordinateSystem::staticTypeId() ) )
	{
		result = Imath::Box3f( Imath::V3f( 0 ), Imath::V3f( 1 ) );
	}
	else
	{
		result = Imath::Box3f( Imath::V3f( -0.5 ), Imath::V3f( 0.5 ) );
	}

	if( path.size() == 0 )
	{
		result = Imath::transform( result, transformPlug()->matrix() );
	}
	return result;
}
static IECore::ObjectPtr getClipboardContents( ApplicationRoot &a )
{
	IECore::ConstObjectPtr o = a.getClipboardContents();
	if( o )
	{
		return o->copy();
	}
	return 0;
}
Exemple #3
0
Imath::Box3f ObjectSource::computeBound( const SceneNode::ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	IECore::ConstObjectPtr object = sourcePlug()->getValue();
	Imath::Box3f result = bound( object.get() );

	if( path.size() == 0 )
	{
		result = Imath::transform( result, transformPlug()->matrix() );
	}
	return result;
}
void VectorTypedParameterHandler<ParameterType>::setParameterValue()
{
	IECore::ConstObjectPtr o = m_plug->getValue();
	if( o )
	{
		m_parameter->setValue( o->copy() );
	}
	else
	{
		m_parameter->setValue( m_parameter->defaultValue()->copy() );
	}
}
Exemple #5
0
void ValuePlug::setObjectValue( IECore::ConstObjectPtr value )
{
	bool haveInput = getInput<Plug>();
	if( direction()==In && !haveInput )
	{
		// input plug with no input connection. there can only ever be a single value,
		// which we store directly on the plug. when setting this we need to take care
		// of undo, and also of triggering the plugValueSet signal and propagating the
		// plugDirtiedSignal.

		if( getFlags( ReadOnly ) )
		{
			// We don't allow static values to be set on read only plugs, so we throw.
			// Note that it is perfectly acceptable to call setValue() on a read only
			// plug during a computation because the result is not written onto the
			// plug itself, so we don't make the check in the case that we call
			// receiveResult() below. This allows plugs which have inputs to be made
			// read only after having their input set.
			throw IECore::Exception( boost::str( boost::format( "Cannot set value for read only plug \"%s\"" ) % fullName() ) );
		}

		if( value->isNotEqualTo( m_staticValue.get() ) )
		{
			Action::enact( new SetValueAction( this, value ) );
		}

		return;
	}

	// An input plug with an input connection or an output plug. We must be currently in a computation
	// triggered by getObjectValue() for a setObjectValue() call to be valid (receiveResult will check this).
	// We never trigger plugValueSet or plugDirtiedSignals during computation.
	ComputeProcess::receiveResult( this, value );
}
Exemple #6
0
IECore::ConstObjectPtr PointsType::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	const PointsPrimitive *inputPoints = runTimeCast<const PointsPrimitive>( inputObject.get() );
	if( !inputPoints )
	{
		return inputObject;
	}

	const std::string type = typePlug()->getValue();
	if( type == "" )
	{
		return inputObject;
	}

	if( const StringData *existingType = inputPoints->variableData<StringData>( "type" ) )
	{
		if( existingType->readable() == type )
		{
			return inputObject;
		}
	}

	PointsPrimitivePtr result = inputPoints->copy();
	result->variables["type"] = PrimitiveVariable( PrimitiveVariable::Constant, new StringData( type ) );

	return result;
}
IECore::ConstObjectPtr PointsGridToPoints::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	const VDBObject *vdbObject = runTimeCast<const VDBObject>( inputObject.get() );
	if( !vdbObject )
	{
		return inputObject;
	}

	openvdb::GridBase::ConstPtr grid = vdbObject->findGrid( gridPlug()->getValue() );

	if ( !grid )
	{
		return inputObject;
	}

	std::string names = namesPlug()->getValue();
	bool invert = invertNamesPlug()->getValue();
	auto primitiveVariableFilter = [names, invert](const std::string& primitiveVariableName) -> bool
	{
		if (primitiveVariableName == "P")
		{
			return false;
		}
		return StringAlgo::matchMultiple( primitiveVariableName, names ) != invert;
	};

	IECoreScene::PointsPrimitivePtr points =  createPointsPrimitive( grid, primitiveVariableFilter );

	if ( !points )
	{
		return inputObject;
	}

	return points;
}
Exemple #8
0
std::string StringPlug::getValue() const
{	
	IECore::ConstObjectPtr o = getObjectValue();
	const IECore::StringData *s = IECore::runTimeCast<const IECore::StringData>( o.get() );
	if( !s )
	{
		throw IECore::Exception( "StringPlug::getObjectValue() didn't return StringData - is the hash being computed correctly?" );
	}

	bool performSubstitution =
		direction()==Plug::In &&
		inCompute() &&
		Plug::getFlags( Plug::PerformsSubstitutions ) &&
		Context::hasSubstitutions( s->readable() );

	return performSubstitution ? Context::current()->substitute( s->readable() ) : s->readable();
}
Exemple #9
0
IECore::MurmurHash StringPlug::hash() const
{
	bool performSubstitution = direction()==Plug::In && !getInput<ValuePlug>() && Plug::getFlags( Plug::PerformsSubstitutions );
	if( performSubstitution )
	{
		IECore::ConstObjectPtr o = getObjectValue();
		const IECore::StringData *s = IECore::runTimeCast<const IECore::StringData>( o.get() );
		if( !s )
		{
			throw IECore::Exception( "StringPlug::getObjectValue() didn't return StringData - is the hash being computed correctly?" );
		}
		
		if( Context::hasSubstitutions( s->readable() ) )
		{
			IECore::MurmurHash result;
			result.append( Context::current()->substitute( s->readable() ) );
			return result;
		}
	}

	// no substitutions
	return ValuePlug::hash();
}
Exemple #10
0
IECore::ConstObjectPtr OSLObject::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
    const Primitive *inputPrimitive = runTimeCast<const Primitive>( inputObject.get() );
    if( !inputPrimitive )
    {
        return inputObject;
    }

    if( !inputPrimitive->variableData<V3fVectorData>( "P", PrimitiveVariable::Vertex ) )
    {
        return inputObject;
    }

    ConstOSLShaderPtr shader = runTimeCast<const OSLShader>( shaderPlug()->source<Plug>()->node() );
    ConstShadingEnginePtr shadingEngine = shader ? shader->shadingEngine() : NULL;

    if( !shadingEngine )
    {
        return inputObject;
    }

    CompoundDataPtr shadingPoints = new CompoundData;
    for( PrimitiveVariableMap::const_iterator it = inputPrimitive->variables.begin(), eIt = inputPrimitive->variables.end(); it != eIt; ++it )
    {
        if( it->second.interpolation == PrimitiveVariable::Vertex )
        {
            // cast is ok - we're only using it to be able to reference the data from the shadingPoints,
            // but nothing will modify the data itself.
            shadingPoints->writable()[it->first] = boost::const_pointer_cast<Data>( it->second.data );
        }
    }

    PrimitivePtr outputPrimitive = inputPrimitive->copy();

    ShadingEngine::Transforms transforms;

    transforms[ g_world ] = ShadingEngine::Transform( inPlug()->fullTransform( path ));

    CompoundDataPtr shadedPoints = shadingEngine->shade( shadingPoints.get(), transforms );
    for( CompoundDataMap::const_iterator it = shadedPoints->readable().begin(), eIt = shadedPoints->readable().end(); it != eIt; ++it )
    {
        if( it->first != "Ci" )
        {
            outputPrimitive->variables[it->first] = PrimitiveVariable( PrimitiveVariable::Vertex, it->second );
        }
    }

    return outputPrimitive;
}
Exemple #11
0
Format FormatPlug::getValue( const IECore::MurmurHash *precomputedHash ) const
{
	IECore::ConstObjectPtr o = getObjectValue( precomputedHash );
	const GafferImage::FormatData *d = IECore::runTimeCast<const GafferImage::FormatData>( o.get() );
	if( !d )
	{
		throw IECore::Exception( "FormatPlug::getObjectValue() didn't return FormatData - is the hash being computed correctly?" );
	}
	Format result = d->readable();
	if( result.getDisplayWindow().isEmpty() && inCompute() )
	{
		return Context::current()->get<Format>( Format::defaultFormatContextName, Format() );
	}
	return result;
}
Exemple #12
0
IECore::ConstObjectPtr MapOffset::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	// early out if it's not a primitive
	const Primitive *inputPrimitive = runTimeCast<const Primitive>( inputObject.get() );
	if( !inputPrimitive )
	{
		return inputObject;
	}

	// early out if the s/t names haven't been provided.

	std::string sName = sNamePlug()->getValue();
	std::string tName = tNamePlug()->getValue();

	if( sName == "" || tName == "" )
	{
		return inputObject;
	}

	// do the work

	PrimitivePtr result = inputPrimitive->copy();

	V2f offset = offsetPlug()->getValue();

	const int udim = udimPlug()->getValue();
	offset.x += (udim - 1001) % 10;
	offset.y += (udim - 1001) / 10;

	if( FloatVectorDataPtr sData = result->variableData<FloatVectorData>( sName ) )
	{
		for( vector<float>::iterator it = sData->writable().begin(), eIt = sData->writable().end(); it != eIt; ++it )
		{
			*it += offset.x;
		}
	}

	if( FloatVectorDataPtr tData = result->variableData<FloatVectorData>( tName ) )
	{
		for( vector<float>::iterator it = tData->writable().begin(), eIt = tData->writable().end(); it != eIt; ++it )
		{
			*it += offset.y;
		}
	}

	return result;
}
Exemple #13
0
IECore::ConstObjectPtr LevelSetToMesh::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	const VDBObject *vdbObject = runTimeCast<const VDBObject>( inputObject.get() );
	if( !vdbObject )
	{
		return inputObject;
	}

	openvdb::GridBase::ConstPtr grid = vdbObject->findGrid( gridPlug()->getValue() );

	if (!grid)
	{
		return inputObject;
	}

	return volumeToMesh( grid, isoValuePlug()->getValue(), adaptivityPlug()->getValue() );
}
Exemple #14
0
IECore::ConstObjectPtr OSLObject::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	const Primitive *inputPrimitive = runTimeCast<const Primitive>( inputObject.get() );
	if( !inputPrimitive )
	{
		return inputObject;
	}

	if( !inputPrimitive->variableData<V3fVectorData>( "P", PrimitiveVariable::Vertex ) )
	{
		return inputObject;
	}

	OSLRenderer::ConstShadingEnginePtr shadingEngine = OSLImage::shadingEngine( shaderPlug() );
	if( !shadingEngine )
	{
		return inputObject;	
	}
	
	CompoundDataPtr shadingPoints = new CompoundData;
	for( PrimitiveVariableMap::const_iterator it = inputPrimitive->variables.begin(), eIt = inputPrimitive->variables.end(); it != eIt; ++it )
	{
		if( it->second.interpolation == PrimitiveVariable::Vertex )
		{
			// cast is ok - we're only using it to be able to reference the data from the shadingPoints,
			// but nothing will modify the data itself.
			shadingPoints->writable()[it->first] = constPointerCast<Data>( it->second.data );
		}
	}

	PrimitivePtr outputPrimitive = inputPrimitive->copy();

	ConstCompoundDataPtr shadedPoints = shadingEngine->shade( shadingPoints );
	const std::vector<Color3f> &ci = shadedPoints->member<Color3fVectorData>( "Ci" )->readable();
	
	V3fVectorDataPtr p = new V3fVectorData;
	p->writable().reserve( ci.size() );
	std::copy( ci.begin(), ci.end(), back_inserter( p->writable() ) );
	
	outputPrimitive->variables["P"] = PrimitiveVariable( PrimitiveVariable::Vertex, p );

	/// \todo Allow shaders to write arbitrary primitive variables.
			
	return outputPrimitive;
}
Exemple #15
0
IECore::ConstObjectPtr MeshDistortion::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	const MeshPrimitive *mesh = runTimeCast<const MeshPrimitive>( inputObject.get() );
	if( !mesh )
	{
		return inputObject;
	}

	const std::string position = positionPlug()->getValue();
	const std::string referencePosition = referencePositionPlug()->getValue();
	const std::string uvSet = uvSetPlug()->getValue();
	if( position.empty() || referencePosition.empty() || uvSet.empty() )
	{
		return inputObject;
	}

	const std::string distortion = distortionPlug()->getValue();
	const std::string uvDistortion = uvDistortionPlug()->getValue();
	if( distortion.empty() && uvDistortion.empty() )
	{
		return inputObject;
	}

	auto distortions = MeshAlgo::calculateDistortion(
		mesh,
		uvSet,
		referencePosition,
		position
	);

	MeshPrimitivePtr result = mesh->copy();

	if( !distortion.empty() )
	{
		result->variables[distortion] = distortions.first;
	}

	if( !uvDistortion.empty() )
	{
		result->variables[uvDistortion] = distortions.second;
	}

	return result;
}
Exemple #16
0
IECore::ConstObjectPtr OSLObject::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	const Primitive *inputPrimitive = runTimeCast<const Primitive>( inputObject.get() );
	if( !inputPrimitive )
	{
		return inputObject;
	}

	const OSLShader *shader = runTimeCast<const OSLShader>( shaderPlug()->source()->node() );
	ConstShadingEnginePtr shadingEngine = shader ? shader->shadingEngine() : nullptr;

	if( !shadingEngine )
	{
		return inputObject;
	}

	PrimitiveVariable::Interpolation interpolation = static_cast<PrimitiveVariable::Interpolation>( interpolationPlug()->getValue() );

	IECoreScene::ConstPrimitivePtr resampledObject = IECore::runTimeCast<const IECoreScene::Primitive>( resampledInPlug()->objectPlug()->getValue() );
	CompoundDataPtr shadingPoints = prepareShadingPoints( resampledObject.get(), shadingEngine.get() );

	PrimitivePtr outputPrimitive = inputPrimitive->copy();

	ShadingEngine::Transforms transforms;

	transforms[ g_world ] = ShadingEngine::Transform( inPlug()->fullTransform( path ));

	CompoundDataPtr shadedPoints = shadingEngine->shade( shadingPoints.get(), transforms );
	for( CompoundDataMap::const_iterator it = shadedPoints->readable().begin(), eIt = shadedPoints->readable().end(); it != eIt; ++it )
	{

		// Ignore the output color closure as the debug closures are used to define what is 'exported' from the shader
		if( it->first != "Ci" )
		{
			outputPrimitive->variables[it->first] = PrimitiveVariable( interpolation, it->second );
		}
	}

	return outputPrimitive;
}
IECore::RunTimeTypedPtr ToGLStateConverter::doConversion( IECore::ConstObjectPtr src, IECore::ConstCompoundObjectPtr operands ) const
{
	const CompoundObject *co = runTimeCast<const CompoundObject>( src.get() );
	if( !co )
	{
		throw Exception( "Expected a CompoundObject" );
	}

	const AttributeToStateMap &m = attributeToStateMap();

	const StatePtr result = new State( false );
	for( CompoundObject::ObjectMap::const_iterator it = co->members().begin(), eIt = co->members().end(); it != eIt; ++it )
	{
		AttributeToStateMap::const_iterator mIt = m.find( it->first );
		if( mIt != m.end() )
		{
			StateComponentPtr s = mIt->second( it->second.get() );
			result->add( s );
		}
	}
	return result;
}
Exemple #18
0
IECore::ConstObjectPtr DeleteCurves::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	const CurvesPrimitive *curves = runTimeCast<const CurvesPrimitive>( inputObject.get() );
	if( !curves )
	{
		return inputObject;
	}

	std::string deletePrimVarName = curvesPlug()->getValue();

	if( boost::trim_copy( deletePrimVarName ).empty() )
	{
		return inputObject;
	}

	PrimitiveVariableMap::const_iterator it = curves->variables.find( deletePrimVarName );
	if (it == curves->variables.end())
	{
		throw InvalidArgumentException( boost::str( boost::format( "DeleteCurves : No primitive variable \"%s\" found" ) % deletePrimVarName ) );
	}

	return CurvesAlgo::deleteCurves(curves, it->second);
}
Exemple #19
0
IECore::ConstObjectPtr MeshTangents::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	const MeshPrimitive *mesh = runTimeCast<const MeshPrimitive>( inputObject.get() );
	if( !mesh )
	{
		return inputObject;
	}

	std::string uvSet = uvSetPlug()->getValue();
	std::string position = positionPlug()->getValue();
	bool ortho = orthogonalPlug()->getValue();

	std::string uTangent = uTangentPlug()->getValue();
	std::string vTangent = vTangentPlug()->getValue();

	std::pair<PrimitiveVariable, PrimitiveVariable> tangentPrimvars = MeshAlgo::calculateTangents( mesh, uvSet, ortho, position);
	MeshPrimitivePtr meshWithTangents = runTimeCast<MeshPrimitive>( mesh->copy() );

	meshWithTangents->variables[uTangent] = tangentPrimvars.first;
	meshWithTangents->variables[vTangent] = tangentPrimvars.second;

	return meshWithTangents;
}
static IECore::ObjectPtr getValue( Detail::PythonObjectKnob &knob )
{
	check( knob );
	IECore::ConstObjectPtr v = knob.objectKnob->getValue();
	return v ? v->copy() : 0;
}
Exemple #21
0
IECore::ConstObjectPtr MapProjection::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	// early out if it's not a primitive with a "P" variable
	const Primitive *inputPrimitive = runTimeCast<const Primitive>( inputObject.get() );
	if( !inputPrimitive )
	{
		return inputObject;
	}

	const V3fVectorData *pData = inputPrimitive->variableData<V3fVectorData>( "P" );
	if( !pData )
	{
		return inputObject;
	}

	// early out if the uv set name hasn't been provided

	const string uvSet = uvSetPlug()->getValue();

	if( uvSet == "" )
	{
		return inputObject;
	}

	// get the camera and early out if we can't find one

	ScenePath cameraPath;
	ScenePlug::stringToPath( cameraPlug()->getValue(), cameraPath );

	ConstCameraPtr constCamera = runTimeCast<const Camera>( inPlug()->object( cameraPath ) );
	if( !constCamera )
	{
		return inputObject;
	}

	M44f cameraMatrix = inPlug()->fullTransform( cameraPath );
	M44f objectMatrix = inPlug()->fullTransform( path );
	M44f objectToCamera = objectMatrix * cameraMatrix.inverse();

	bool perspective = constCamera->getProjection() == "perspective";

	Box2f normalizedScreenWindow;
	if( constCamera->hasResolution() )
	{
		normalizedScreenWindow = constCamera->frustum();
	}
	else
	{
		// We don't know what resolution the camera is meant to render with, so take the whole aperture
		// as the screen window
		normalizedScreenWindow = constCamera->frustum( Camera::Distort );
	}

	// do the work

	PrimitivePtr result = inputPrimitive->copy();

	V2fVectorDataPtr uvData = new V2fVectorData();
	uvData->setInterpretation( GeometricData::UV );

	result->variables[uvSet] = PrimitiveVariable( PrimitiveVariable::Vertex, uvData );

	const vector<V3f> &p = pData->readable();
	vector<V2f> &uv = uvData->writable();
	uv.reserve( p.size() );

	for( size_t i = 0, e = p.size(); i < e; ++i )
	{
		V3f pCamera = p[i] * objectToCamera;
		V2f pScreen = V2f( pCamera.x, pCamera.y );
		if( perspective )
		{
			pScreen /= -pCamera.z;
		}
		uv.push_back(
			V2f(
				lerpfactor( pScreen.x, normalizedScreenWindow.min.x, normalizedScreenWindow.max.x ),
				lerpfactor( pScreen.y, normalizedScreenWindow.min.y, normalizedScreenWindow.max.y )
			)
		);
	}

	return result;
}
Exemple #22
0
bool SceneShapeUI::snap( MSelectInfo &snapInfo ) const
{
	MStatus s;

	if( snapInfo.displayStatus() != M3dView::kHilite )
	{
		MSelectionMask meshMask( MSelectionMask::kSelectMeshes );
		if( !snapInfo.selectable( meshMask ) )
		{
			return false;
		}
	}

	// early out if we have no scene to draw
	SceneShape *sceneShape = static_cast<SceneShape *>( surfaceShape() );
	const IECore::SceneInterface *sceneInterface = sceneShape->getSceneInterface().get();
	if( !sceneInterface )
	{
		return false;
	}

	IECoreGL::ConstScenePtr scene = sceneShape->glScene();
	if( !scene )
	{
		return false;
	}

	// Get the viewport that the snapping operation is taking place in.
	M3dView view = snapInfo.view();

	// Use an IECoreGL::Selector to find the point in world space that we wish to snap to.
	// We do this by first getting the origin of the selection ray and transforming it into
	// NDC space using the OpenGL projection and transformation matrices. Once we have the
	// point in NDC we can use it to define the viewport that the IECoreGL::Selector will use.

	MPoint localRayOrigin;
	MVector localRayDirection;
	snapInfo.getLocalRay( localRayOrigin, localRayDirection );
	
	Imath::V3d org( localRayOrigin[0], localRayOrigin[1], localRayOrigin[2] );
	MDagPath camera;
	view.getCamera( camera );
	MMatrix localToCamera = snapInfo.selectPath().inclusiveMatrix() * camera.inclusiveMatrix().inverse();
	
	view.beginSelect();
		Imath::M44d projectionMatrix;
		glGetDoublev( GL_PROJECTION_MATRIX, projectionMatrix.getValue() );
	view.endSelect();

	double v[4][4];
	localToCamera.get( v ); 
	Imath::M44d cam( v );
	Imath::V3d ndcPt3d = ( (org * cam ) * projectionMatrix + Imath::V3d( 1. ) ) * Imath::V3d( .5 );
	Imath::V2d ndcPt( std::max( std::min( ndcPt3d[0], 1. ), 0. ), 1. - std::max( std::min( ndcPt3d[1], 1. ), 0. ) );

	view.beginGL();
	
		glMatrixMode( GL_PROJECTION );
		glLoadMatrixd( projectionMatrix.getValue() );
		
		float radius = .001; // The radius of the selection area in NDC.
		double aspect = double( view.portWidth() ) / view.portHeight();
		Imath::V2f selectionWH( radius, radius * aspect );
		
		std::vector<IECoreGL::HitRecord> hits;
		{
			IECoreGL::Selector selector( Imath::Box2f( ndcPt - selectionWH, ndcPt + selectionWH ), IECoreGL::Selector::IDRender, hits );
				
			IECoreGL::State::bindBaseState();
			selector.baseState()->bind();
			scene->render( selector.baseState() );			
		}
				
	view.endGL();

	if( hits.empty() )
	{
		return false;
	}

	// Get the closest mesh hit.	
	float depthMin = std::numeric_limits<float>::max();
	int depthMinIndex = -1;
	for( unsigned int i=0, e = hits.size(); i < e; i++ )
	{		
		if( hits[i].depthMin < depthMin )
		{
			depthMin = hits[i].depthMin;
			depthMinIndex = i;
		}
	}

	// Get the absolute path of the hit object.
	IECore::SceneInterface::Path objPath;
	std::string objPathStr;
	sceneInterface->path( objPath );
	IECore::SceneInterface::pathToString( objPath, objPathStr );
	
	objPathStr += IECoreGL::NameStateComponent::nameFromGLName( hits[depthMinIndex].name );
	IECore::SceneInterface::stringToPath( objPathStr, objPath );

	// Validate the hit selection.
	IECore::ConstSceneInterfacePtr childInterface;
	try
	{
		childInterface = sceneInterface->scene( objPath );
	}
	catch(...)
	{
		return false;
	}

	if( !childInterface )
	{
		return false;
	}
	
	if( !childInterface->hasObject() )
	{
		return false;
	}

	// Get the mesh primitive so that we can query it's vertices.
	double time = sceneShape->time();
	IECore::ConstObjectPtr object = childInterface->readObject( time );
	IECore::ConstMeshPrimitivePtr meshPtr = IECore::runTimeCast<const IECore::MeshPrimitive>( object.get() );
	
	if ( !meshPtr )
	{
		return false;
	}
	
	// Calculate the snap point in object space.
	MPoint worldIntersectionPoint;
	selectionRayToWorldSpacePoint( camera, snapInfo, depthMin, worldIntersectionPoint );
	Imath::V3f pt( worldIntersectionPoint[0], worldIntersectionPoint[1], worldIntersectionPoint[2] );
	Imath::M44f objToWorld( worldTransform( childInterface.get(), time ) );
	pt = pt * objToWorld.inverse();

	// Get the list of vertices in the mesh.
	IECore::V3fVectorData::ConstPtr pointData( meshPtr->variableData<IECore::V3fVectorData>( "P", IECore::PrimitiveVariable::Vertex ) ); 
	const std::vector<Imath::V3f> &vertices( pointData->readable() ); 
	
	// Find the vertex that is closest to the snap point.
	Imath::V3d closestVertex;
	float closestDistance = std::numeric_limits<float>::max(); 
	
	for( std::vector<Imath::V3f>::const_iterator it( vertices.begin() ); it != vertices.end(); ++it )
	{
		Imath::V3d vert( *it );
		float d( ( pt - vert ).length() ); // Calculate the distance between the vertex and the snap point.
		if( d < closestDistance )
		{
			closestDistance = d;
			closestVertex = vert;
		}
	}

	// Snap to the vertex.
	closestVertex *= objToWorld;
	snapInfo.setSnapPoint( MPoint( closestVertex[0], closestVertex[1], closestVertex[2] ) );
	return true;
}
IECore::RunTimeTypedPtr ToGLMeshConverter::doConversion( IECore::ConstObjectPtr src, IECore::ConstCompoundObjectPtr operands ) const
{
	IECore::MeshPrimitivePtr mesh = IECore::staticPointerCast<IECore::MeshPrimitive>( src->copy() ); // safe because the parameter validated it for us
	
	if( !mesh->variableData<IECore::V3fVectorData>( "P", IECore::PrimitiveVariable::Vertex ) )
	{
		throw IECore::Exception( "Must specify primitive variable \"P\", of type V3fVectorData and interpolation type Vertex." );
	}

	if( mesh->variables.find( "N" )==mesh->variables.end() )
	{
		// the mesh has no normals - we need to explicitly add some. if it's a polygon
		// mesh (interpolation==linear) then we add per-face normals for a faceted look
		// and if it's a subdivision mesh we add smooth per-vertex normals.
		IECore::MeshNormalsOpPtr normalOp = new IECore::MeshNormalsOp();
		normalOp->inputParameter()->setValue( mesh );
		normalOp->copyParameter()->setTypedValue( false );
		normalOp->interpolationParameter()->setNumericValue(
			mesh->interpolation() == "linear" ? IECore::PrimitiveVariable::Uniform : IECore::PrimitiveVariable::Vertex
		);
		normalOp->operate();
	}
	
	IECore::TriangulateOpPtr op = new IECore::TriangulateOp();
	op->inputParameter()->setValue( mesh );
	op->throwExceptionsParameter()->setTypedValue( false ); // it's better to see something than nothing
	op->copyParameter()->setTypedValue( false );
	op->operate();

	IECore::FaceVaryingPromotionOpPtr faceVaryingOp = new IECore::FaceVaryingPromotionOp;
	faceVaryingOp->inputParameter()->setValue( mesh );
	faceVaryingOp->copyParameter()->setTypedValue( false );
	faceVaryingOp->operate();

	MeshPrimitivePtr glMesh = new MeshPrimitive( mesh->vertexIds() );

	for ( IECore::PrimitiveVariableMap::iterator pIt = mesh->variables.begin(); pIt != mesh->variables.end(); ++pIt )
	{
		if ( pIt->second.data )
		{
			glMesh->addPrimitiveVariable( pIt->first, pIt->second );
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToGLMeshConverter", boost::format( "No data given for primvar \"%s\"" ) % pIt->first );
		}
	}

	IECore::PrimitiveVariableMap::const_iterator sIt = mesh->variables.find( "s" );
	IECore::PrimitiveVariableMap::const_iterator tIt = mesh->variables.find( "t" );
	if ( sIt != mesh->variables.end() && tIt != mesh->variables.end() )
	{
		if ( sIt->second.interpolation != IECore::PrimitiveVariable::Constant  
			&&  tIt->second.interpolation != IECore::PrimitiveVariable::Constant
			&& sIt->second.interpolation == tIt->second.interpolation )
		{
			IECore::ConstFloatVectorDataPtr s = IECore::runTimeCast< const IECore::FloatVectorData >( sIt->second.data );
			IECore::ConstFloatVectorDataPtr t = IECore::runTimeCast< const IECore::FloatVectorData >( tIt->second.data );

			if ( s && t )
			{
				/// Should hold true if primvarsAreValid
				assert( s->readable().size() == t->readable().size() );

				IECore::V2fVectorDataPtr stData = new IECore::V2fVectorData();
				stData->writable().resize( s->readable().size() );

				for ( unsigned i = 0; i < s->readable().size(); i++ )
				{
					stData->writable()[i] = Imath::V2f( s->readable()[i], t->readable()[i] );
				}
				glMesh->addPrimitiveVariable( "st", IECore::PrimitiveVariable( sIt->second.interpolation, stData ) );
			}
			else
			{
				IECore::msg( IECore::Msg::Warning, "ToGLMeshConverter", "If specified, primitive variables \"s\" and \"t\" must be of type FloatVectorData and interpolation type FaceVarying." );
			}
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToGLMeshConverter", "If specified, primitive variables \"s\" and \"t\" must be of type FloatVectorData and non-Constant interpolation type." );
		}
	}
	else if ( sIt != mesh->variables.end() || tIt != mesh->variables.end() )
	{
		IECore::msg( IECore::Msg::Warning, "ToGLMeshConverter", "Primitive variable \"s\" or \"t\" found, but not both." );
	}

	return glMesh;
}
Exemple #24
0
		virtual task *execute()
		{
			ScenePlug::PathScope pathScope( m_sceneGadget->m_context.get(), m_scenePath );

			// Update attributes, and compute visibility.

			const bool previouslyVisible = m_sceneGraph->m_visible;
			if( m_dirtyFlags & AttributesDirty )
			{
				const IECore::MurmurHash attributesHash = m_sceneGadget->m_scene->attributesPlug()->hash();
				if( attributesHash != m_sceneGraph->m_attributesHash )
				{
					IECore::ConstCompoundObjectPtr attributes = m_sceneGadget->m_scene->attributesPlug()->getValue( &attributesHash );
					const IECore::BoolData *visibilityData = attributes->member<IECore::BoolData>( "scene:visible" );
					m_sceneGraph->m_visible = visibilityData ? visibilityData->readable() : true;

					IECore::ConstRunTimeTypedPtr glStateCachedTyped = IECoreGL::CachedConverter::defaultCachedConverter()->convert( attributes.get() );
					IECoreGL::ConstStatePtr glStateCached = IECore::runTimeCast<const IECoreGL::State>( glStateCachedTyped );



					IECoreGL::ConstStatePtr visState = NULL;

					deferReferenceRemoval( m_sceneGraph->m_attributesRenderable );
					m_sceneGraph->m_attributesRenderable = AttributeVisualiser::allVisualisations( attributes.get(), visState );

					deferReferenceRemoval( m_sceneGraph->m_state );
					if( visState )
					{
						IECoreGL::StatePtr glState = new IECoreGL::State( *glStateCached );
						glState->add( const_cast< IECoreGL::State* >( visState.get() ) );

						m_sceneGraph->m_state = glState;
					}
					else
					{
						m_sceneGraph->m_state = glStateCached;
					}


					m_sceneGraph->m_attributesHash = attributesHash;
				}
			}

			if( !m_sceneGraph->m_visible )
			{
				// No need to update further since we're not visible.
				return NULL;
			}
			else if( !previouslyVisible )
			{
				// We didn't perform any updates when we were invisible,
				// so we need to update everything now.
				m_dirtyFlags = AllDirty;
			}

			// Update the object - converting it into an IECoreGL::Renderable

			if( m_dirtyFlags & ObjectDirty )
			{
				const IECore::MurmurHash objectHash = m_sceneGadget->m_scene->objectPlug()->hash();
				if( objectHash != m_sceneGraph->m_objectHash )
				{
					IECore::ConstObjectPtr object = m_sceneGadget->m_scene->objectPlug()->getValue( &objectHash );
					deferReferenceRemoval( m_sceneGraph->m_renderable );
					if( !object->isInstanceOf( IECore::NullObjectTypeId ) )
					{
						m_sceneGraph->m_renderable = objectToRenderable( object.get() );
					}
					m_sceneGraph->m_objectHash = objectHash;
				}
			}

			// Update the transform and bound

			if( m_dirtyFlags & TransformDirty )
			{
				m_sceneGraph->m_transform = m_sceneGadget->m_scene->transformPlug()->getValue();
			}

			m_sceneGraph->m_bound = m_sceneGraph->m_renderable ? m_sceneGraph->m_renderable->bound() : Box3f();

			// Update the expansion state

			const bool previouslyExpanded = m_sceneGraph->m_expanded;
			if( m_dirtyFlags & ExpansionDirty )
			{
				m_sceneGraph->m_expanded = m_sceneGadget->m_minimumExpansionDepth >= m_scenePath.size();
				if( !m_sceneGraph->m_expanded )
				{
					m_sceneGraph->m_expanded = m_sceneGadget->m_expandedPaths->readable().match( m_scenePath ) & Filter::ExactMatch;
				}
			}

			// If we're not expanded, then we can early out after creating a bounding box.

			deferReferenceRemoval( m_sceneGraph->m_boundRenderable );
			if( !m_sceneGraph->m_expanded )
			{
				// We're not expanded, so we early out before updating the children.
				// We do however need to see if we have any children, and arrange to
				// draw their bounding box if we do.
				bool haveChildren = m_sceneGraph->m_children.size();
				if( m_dirtyFlags & ChildNamesDirty || !previouslyExpanded )
				{
					IECore::ConstInternedStringVectorDataPtr childNamesData = m_sceneGadget->m_scene->childNamesPlug()->getValue();
					haveChildren = childNamesData->readable().size();
				}

				m_sceneGraph->clearChildren();

				m_sceneGraph->m_bound.extendBy( m_sceneGadget->m_scene->boundPlug()->getValue() );

				if( haveChildren )
				{
					IECore::CurvesPrimitivePtr curvesBound = IECore::CurvesPrimitive::createBox( m_sceneGraph->m_bound );
					m_sceneGraph->m_boundRenderable = boost::static_pointer_cast<const IECoreGL::Renderable>(
						IECoreGL::CachedConverter::defaultCachedConverter()->convert( curvesBound.get() )
					);
				}
				return NULL;
			}

			// We are expanded, so we need to visit all the children
			// and update those too.

			if( !previouslyExpanded )
			{
				m_dirtyFlags = AllDirty;
			}

			// Make sure we have a child for each child name

			if( m_dirtyFlags & ChildNamesDirty )
			{
				IECore::ConstInternedStringVectorDataPtr childNamesData = m_sceneGadget->m_scene->childNamesPlug()->getValue();
				const std::vector<IECore::InternedString> &childNames = childNamesData->readable();
				if( !existingChildNamesValid( childNames ) )
				{
					m_sceneGraph->clearChildren();

					for( std::vector<IECore::InternedString>::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it )
					{
						SceneGraph *child = new SceneGraph();
						child->m_name = *it;
						m_sceneGraph->m_children.push_back( child );
					}

					m_dirtyFlags = AllDirty; // We've made brand new children, so they need a full update.
				}
			}

			// And then update each child

			if( m_sceneGraph->m_children.size() )
			{
				set_ref_count( 1 + m_sceneGraph->m_children.size() );

				ScenePlug::ScenePath childPath = m_scenePath;
				childPath.push_back( IECore::InternedString() ); // space for the child name
				for( std::vector<SceneGraph *>::const_iterator it = m_sceneGraph->m_children.begin(), eIt = m_sceneGraph->m_children.end(); it != eIt; ++it )
				{
					childPath.back() = (*it)->m_name;
					UpdateTask *t = new( allocate_child() ) UpdateTask( m_sceneGadget, *it, m_dirtyFlags, childPath );
					spawn( *t );
				}

				wait_for_all();
			}

			// Finally compute our bound from the child bounds.

			for( std::vector<SceneGraph *>::const_iterator it = m_sceneGraph->m_children.begin(), eIt = m_sceneGraph->m_children.end(); it != eIt; ++it )
			{
				const Box3f childBound = transform( (*it)->m_bound, (*it)->m_transform );
				m_sceneGraph->m_bound.extendBy( childBound );
			}

			return NULL;
		}