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