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; }
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; }