IECoreScene::PrimitiveVariable FromMayaMeshConverter::points() const { MFnMesh fnMesh; const MDagPath *d = dagPath( true ); if( d ) { fnMesh.setObject( *d ); } else { fnMesh.setObject( object() ); } V3fVectorDataPtr points = new V3fVectorData; points->setInterpretation( GeometricData::Point ); int numVerts = fnMesh.numVertices(); points->writable().resize( numVerts ); if( space() == MSpace::kObject ) { const V3f* rawPoints = ( const V3f* )fnMesh.getRawPoints(0); copy( rawPoints, rawPoints + numVerts, points->writable().begin() ); } else { MFloatPointArray mPoints; fnMesh.getPoints( mPoints, space() ); std::transform( MArrayIter<MFloatPointArray>::begin( mPoints ), MArrayIter<MFloatPointArray>::end( mPoints ), points->writable().begin(), VecConvert<MFloatPoint, V3f>() ); } return PrimitiveVariable( PrimitiveVariable::Vertex, points ); }
IECoreGL::ConstRenderablePtr StandardLightVisualiser::pointRays() { IECoreGL::GroupPtr group = new IECoreGL::Group(); addWireframeCurveState( group.get() ); IECore::CompoundObjectPtr parameters = new CompoundObject; parameters->members()["aimType"] = new IntData( 1 ); group->getState()->add( new IECoreGL::ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), faceCameraVertexSource(), "", IECoreGL::Shader::constantFragmentSource(), parameters ) ); IntVectorDataPtr vertsPerCurve = new IntVectorData; V3fVectorDataPtr p = new V3fVectorData; const int numRays = 8; for( int i = 0; i < numRays; ++i ) { const float angle = M_PI * 2.0f * float(i)/(float)numRays; const V2f dir( cos( angle ), sin( angle ) ); addRay( dir * .5, dir * 1, vertsPerCurve->writable(), p->writable() ); } IECoreGL::CurvesPrimitivePtr curves = new IECoreGL::CurvesPrimitive( IECore::CubicBasisf::linear(), false, vertsPerCurve ); curves->addPrimitiveVariable( "P", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Vertex, p ) ); curves->addPrimitiveVariable( "Cs", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( Color3f( 1.0f, 0.835f, 0.07f ) ) ) ); group->addChild( curves ); return group; }
IECore::ObjectPtr FromNukePointsConverter::doConversion( IECore::ConstCompoundObjectPtr operands ) const { // get points V3fVectorDataPtr p = new V3fVectorData(); if( const DD::Image::PointList *pl = m_geo->point_list() ) { p->writable().resize( pl->size() ); std::transform( pl->begin(), pl->end(), p->writable().begin(), IECore::convert<Imath::V3f, DD::Image::Vector3> ); } PointsPrimitivePtr result = new PointsPrimitive( p ); // get colour const DD::Image::Attribute *colorAttr = m_geo->get_typed_attribute( "Cf", DD::Image::VECTOR4_ATTRIB ); if( colorAttr && colorAttr->size()==result->getNumPoints() ) { Color3fVectorDataPtr colorData = new Color3fVectorData(); colorData->writable().resize( result->getNumPoints() ); std::transform( colorAttr->vector4_list->begin(), colorAttr->vector4_list->end(), colorData->writable().begin(), IECore::convert<Imath::Color3f, DD::Image::Vector4> ); result->variables["Cs"] = PrimitiveVariable( PrimitiveVariable::Vertex, colorData ); } /// \todo Other primitive variables return result; }
IECoreScene::PrimitiveVariable FromMayaMeshConverter::normals() const { MFnMesh fnMesh; const MDagPath *d = dagPath( true ); if( d ) { fnMesh.setObject( *d ); } else { fnMesh.setObject( object() ); } V3fVectorDataPtr normalsData = new V3fVectorData; normalsData->setInterpretation( GeometricData::Normal ); vector<V3f> &normals = normalsData->writable(); normals.reserve( fnMesh.numFaceVertices() ); int numPolygons = fnMesh.numPolygons(); V3f blankVector; if( space() == MSpace::kObject ) { const float* rawNormals = fnMesh.getRawNormals(0); MIntArray normalIds; for( int i=0; i<numPolygons; i++ ) { fnMesh.getFaceNormalIds( i, normalIds ); for( unsigned j=0; j < normalIds.length(); ++j ) { const float* normalIt = rawNormals + 3 * normalIds[j]; normals.push_back( blankVector ); V3f& nn = normals.back(); nn.x = *normalIt++; nn.y = *normalIt++; nn.z = *normalIt; } } } else { MFloatVectorArray faceNormals; for( int i=0; i<numPolygons; i++ ) { fnMesh.getFaceVertexNormals( i, faceNormals, space() ); for( unsigned j=0; j<faceNormals.length(); j++ ) { MFloatVector& n = faceNormals[j]; normals.push_back( blankVector ); V3f& nn = normals.back(); nn.x = n.x; nn.y = n.y; nn.z = n.z; } } } return PrimitiveVariable( PrimitiveVariable::FaceVarying, normalsData ); }
MeshPrimitive::MeshPrimitive( ConstIntVectorDataPtr verticesPerFace, ConstIntVectorDataPtr vertexIds, const std::string &interpolation, V3fVectorDataPtr p ) { setTopology( verticesPerFace, vertexIds, interpolation ); if( p ) { V3fVectorDataPtr pData = p->copy(); pData->setInterpretation( GeometricData::Point ); variables.insert( PrimitiveVariableMap::value_type("P", PrimitiveVariable(PrimitiveVariable::Vertex, pData)) ); } }
NURBSPrimitive::NURBSPrimitive( int uOrder, ConstFloatVectorDataPtr uKnot, float uMin, float uMax, int vOrder, ConstFloatVectorDataPtr vKnot, float vMin, float vMax, ConstV3fVectorDataPtr p ) { setTopology( uOrder, uKnot, uMin, uMax, vOrder, vKnot, vMin, vMax ); if( p ) { V3fVectorDataPtr pData = p->copy(); pData->setInterpretation( GeometricData::Point ); variables.insert( PrimitiveVariableMap::value_type( "P", PrimitiveVariable( PrimitiveVariable::Vertex, pData ) ) ); } }
CurvesPrimitive::CurvesPrimitive( ConstIntVectorDataPtr vertsPerCurve, const CubicBasisf &basis, bool periodic, ConstV3fVectorDataPtr p ) : m_basis( CubicBasisf::linear() ) { setTopology( vertsPerCurve, basis, periodic ); if( p ) { V3fVectorDataPtr pData = p->copy(); pData->setInterpretation( GeometricData::Point ); variables["P"] = PrimitiveVariable( PrimitiveVariable::Vertex, pData ); } }
ObjectPtr PointNormalsOp::doOperation( const CompoundObject *operands ) { const int numNeighbours = m_numNeighboursParameter->getNumericValue(); const Object * points = pointParameter()->getValue(); ObjectPtr result = nullptr; switch( points->typeId() ) { case V3fVectorDataTypeId : { V3fVectorDataPtr resultT = new V3fVectorData; normals<V3f>( static_cast<const V3fVectorData *>( points )->readable(), numNeighbours, resultT->writable() ); result = resultT; } break; case V3dVectorDataTypeId : { V3dVectorDataPtr resultT = new V3dVectorData; normals<V3d>( static_cast<const V3dVectorData *>( points )->readable(), numNeighbours, resultT->writable() ); result = resultT; } break; default : // should never get here assert( 0 ); } 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; } 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::CompoundDataPtr IECoreRI::SXRendererImplementation::shadePlane( const V2i &resolution ) const { IECore::CompoundDataPtr points = new IECore::CompoundData(); V3fVectorDataPtr pData = new IECore::V3fVectorData(); V3fVectorDataPtr nData = new IECore::V3fVectorData(); FloatVectorDataPtr sData = new IECore::FloatVectorData(); FloatVectorDataPtr tData = new IECore::FloatVectorData(); std::vector<V3f> &p = pData->writable(); std::vector<V3f> &n = nData->writable(); std::vector<float> &s = sData->writable(); std::vector<float> &t = tData->writable(); unsigned numPoints = resolution[0] * resolution[1]; p.resize( numPoints ); n.resize( numPoints ); s.resize( numPoints ); t.resize( numPoints ); unsigned xResMinus1 = resolution[0] - 1; unsigned yResMinus1 = resolution[1] - 1; unsigned i = 0; for( int y = 0; y < resolution[1]; y++ ) { for( int x = 0; x < resolution[0]; x++ ) { p[i] = V3f( float(x) / xResMinus1 , float(y) / yResMinus1, 0.0 ); s[i] = p[i][0]; t[i] = p[i][1]; n[i] = V3f( 0.0f, 0.0f, 1.0f ); i++; } } points->writable()[ "P" ] = pData; points->writable()[ "N" ] = nData; points->writable()[ "s" ] = sData; points->writable()[ "t" ] = tData; return shade( points, resolution ); }
IECoreGL::ConstRenderablePtr StandardLightVisualiser::spotlightCone( float innerAngle, float outerAngle, float lensRadius ) { IECoreGL::GroupPtr group = new IECoreGL::Group(); addWireframeCurveState( group.get() ); group->getState()->add( new IECoreGL::CurvesPrimitive::GLLineWidth( 1.0f ) ); IECore::CompoundObjectPtr parameters = new CompoundObject; parameters->members()["aimType"] = new IntData( 0 ); group->getState()->add( new IECoreGL::ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), faceCameraVertexSource(), "", IECoreGL::Shader::constantFragmentSource(), parameters ) ); IntVectorDataPtr vertsPerCurve = new IntVectorData; V3fVectorDataPtr p = new V3fVectorData; addCone( innerAngle, lensRadius, vertsPerCurve->writable(), p->writable() ); IECoreGL::CurvesPrimitivePtr curves = new IECoreGL::CurvesPrimitive( IECore::CubicBasisf::linear(), false, vertsPerCurve ); curves->addPrimitiveVariable( "P", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Vertex, p ) ); curves->addPrimitiveVariable( "Cs", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( Color3f( 1.0f, 0.835f, 0.07f ) ) ) ); group->addChild( curves ); if( fabs( innerAngle - outerAngle ) > 0.1 ) { IECoreGL::GroupPtr outerGroup = new Group; outerGroup->getState()->add( new IECoreGL::CurvesPrimitive::GLLineWidth( 0.5f ) ); IntVectorDataPtr vertsPerCurve = new IntVectorData; V3fVectorDataPtr p = new V3fVectorData; addCone( outerAngle, lensRadius, vertsPerCurve->writable(), p->writable() ); IECoreGL::CurvesPrimitivePtr curves = new IECoreGL::CurvesPrimitive( IECore::CubicBasisf::linear(), false, vertsPerCurve ); curves->addPrimitiveVariable( "P", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Vertex, p ) ); curves->addPrimitiveVariable( "Cs", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( Color3f( 1.0f, 0.835f, 0.07f ) ) ) ); outerGroup->addChild( curves ); group->addChild( outerGroup ); } return group; }
CurvesPrimitivePtr CurvesPrimitive::createBox( const Imath::Box3f &b ) { IntVectorDataPtr vertsPerCurveData = new IntVectorData; std::vector<int> &vertsPerCurve = vertsPerCurveData->writable(); vertsPerCurve.reserve( 6 ); V3fVectorDataPtr pData = new V3fVectorData; std::vector<V3f> &p = pData->writable(); p.reserve( 18 ); vertsPerCurve.push_back( 5 ); p.push_back( b.min ); p.push_back( V3f( b.max.x, b.min.y, b.min.z ) ); p.push_back( V3f( b.max.x, b.min.y, b.max.z ) ); p.push_back( V3f( b.min.x, b.min.y, b.max.z ) ); p.push_back( b.min ); vertsPerCurve.push_back( 5 ); p.push_back( V3f( b.min.x, b.max.y, b.min.z ) ); p.push_back( V3f( b.max.x, b.max.y, b.min.z ) ); p.push_back( V3f( b.max.x, b.max.y, b.max.z ) ); p.push_back( V3f( b.min.x, b.max.y, b.max.z ) ); p.push_back( V3f( b.min.x, b.max.y, b.min.z ) ); vertsPerCurve.push_back( 2 ); p.push_back( b.min ); p.push_back( V3f( b.min.x, b.max.y, b.min.z ) ); vertsPerCurve.push_back( 2 ); p.push_back( V3f( b.max.x, b.min.y, b.min.z ) ); p.push_back( V3f( b.max.x, b.max.y, b.min.z ) ); vertsPerCurve.push_back( 2 ); p.push_back( V3f( b.max.x, b.min.y, b.max.z ) ); p.push_back( V3f( b.max.x, b.max.y, b.max.z ) ); vertsPerCurve.push_back( 2 ); p.push_back( V3f( b.min.x, b.min.y, b.max.z ) ); p.push_back( V3f( b.min.x, b.max.y, b.max.z ) ); return new CurvesPrimitive( vertsPerCurveData, CubicBasisf::linear(), false, pData ); }
IECoreGL::ConstRenderablePtr StandardLightVisualiser::ray() { IECoreGL::GroupPtr group = new IECoreGL::Group(); addWireframeCurveState( group.get() ); IECore::CompoundObjectPtr parameters = new CompoundObject; parameters->members()["aimType"] = new IntData( 0 ); group->getState()->add( new IECoreGL::ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), faceCameraVertexSource(), "", IECoreGL::Shader::constantFragmentSource(), parameters ) ); IntVectorDataPtr vertsPerCurve = new IntVectorData; V3fVectorDataPtr p = new V3fVectorData; addRay( V2f( 0 ), V2f( 1, 0 ), vertsPerCurve->writable(), p->writable() ); IECoreGL::CurvesPrimitivePtr curves = new IECoreGL::CurvesPrimitive( IECore::CubicBasisf::linear(), false, vertsPerCurve ); curves->addPrimitiveVariable( "P", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Vertex, p ) ); curves->addPrimitiveVariable( "Cs", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( Color3f( 1.0f, 0.835f, 0.07f ) ) ) ); group->addChild( curves ); return group; }
IECore::ConstObjectPtr Grid::computeObject( const SceneNode::ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { if( path.size() == 2 ) { IntVectorDataPtr vertsPerCurveData = new IntVectorData; vector<int> &vertsPerCurve = vertsPerCurveData->writable(); V3fVectorDataPtr pData = new V3fVectorData; pData->setInterpretation( GeometricData::Point ); vector<V3f> &p = pData->writable(); bool periodic = false; Color3f cs( 1 ); const V2f halfDimensions = dimensionsPlug()->getValue() / 2.0f; if( path.back() == g_gridLinesName ) { const float spacing = spacingPlug()->getValue(); const V2i n = V2f( halfDimensions / spacing ) - V2f( 0.01 ); for( int d = 0; d < 2; ++d ) { const int d0 = d; const int d1 = d == 0 ? 1 : 0; for( int i = -n[d]; i <= n[d]; ++i ) { if( i == 0 ) { continue; } vertsPerCurve.push_back( 2 ); V3f e( 0 ); e[d0] = i * spacing; e[d1] = -halfDimensions[d1]; p.push_back( e ); e[d1] = halfDimensions[d1]; p.push_back( e ); } } cs = gridColorPlug()->getValue(); } else if( path.back() == g_centerLinesName ) { vertsPerCurve.push_back( 2 ); p.push_back( V3f( halfDimensions.x, 0, 0 ) ); p.push_back( V3f( -halfDimensions.x, 0, 0 ) ); vertsPerCurve.push_back( 2 ); p.push_back( V3f( 0, halfDimensions.y, 0 ) ); p.push_back( V3f( 0, -halfDimensions.y, 0 ) ); cs = centerColorPlug()->getValue(); } else if( path.back() == g_borderLinesName ) { vertsPerCurve.push_back( 4 ); p.push_back( V3f( -halfDimensions.x, -halfDimensions.y, 0 ) ); p.push_back( V3f( halfDimensions.x, -halfDimensions.y, 0 ) ); p.push_back( V3f( halfDimensions.x, halfDimensions.y, 0 ) ); p.push_back( V3f( -halfDimensions.x, halfDimensions.y, 0 ) ); periodic = true; cs = borderColorPlug()->getValue(); } CurvesPrimitivePtr result = new CurvesPrimitive( vertsPerCurveData, CubicBasisf::linear(), periodic, pData ); result->variables["Cs"] = PrimitiveVariable( PrimitiveVariable::Constant, new Color3fData( cs ) ); return result; } return outPlug()->objectPlug()->defaultValue(); }
ObjectPtr EnvMapSampler::doOperation( const CompoundObject * operands ) { ImagePrimitivePtr image = static_cast<ImagePrimitive *>( imageParameter()->getValue() )->copy(); Box2i dataWindow = image->getDataWindow(); // find the rgb channels ConstFloatVectorDataPtr redData = image->getChannel<float>( "R" ); ConstFloatVectorDataPtr greenData = image->getChannel<float>( "G" ); ConstFloatVectorDataPtr blueData = image->getChannel<float>( "B" ); if( !(redData && greenData && blueData) ) { throw Exception( "Image does not contain valid RGB float channels." ); } const vector<float> &red = redData->readable(); const vector<float> &green = greenData->readable(); const vector<float> &blue = blueData->readable(); // get a luminance channel LuminanceOpPtr luminanceOp = new LuminanceOp(); luminanceOp->inputParameter()->setValue( image ); luminanceOp->copyParameter()->getTypedValue() = false; luminanceOp->removeColorPrimVarsParameter()->getTypedValue() = false; luminanceOp->operate(); // do the median cut thing to get some samples MedianCutSamplerPtr sampler = new MedianCutSampler; sampler->imageParameter()->setValue( image ); sampler->subdivisionDepthParameter()->setNumericValue( subdivisionDepthParameter()->getNumericValue() ); ConstCompoundObjectPtr samples = boost::static_pointer_cast<CompoundObject>( sampler->operate() ); const vector<V2f> ¢roids = boost::static_pointer_cast<V2fVectorData>( samples->members().find( "centroids" )->second )->readable(); const vector<Box2i> &areas = boost::static_pointer_cast<Box2iVectorData>( samples->members().find( "areas" )->second )->readable(); // get light directions and colors from the samples V3fVectorDataPtr directionsData = new V3fVectorData; Color3fVectorDataPtr colorsData = new Color3fVectorData; vector<V3f> &directions = directionsData->writable(); vector<Color3f> &colors = colorsData->writable(); float radiansPerPixel = M_PI / (dataWindow.size().y + 1); float angleAtTop = ( M_PI - radiansPerPixel ) / 2.0f; for( unsigned i=0; i<centroids.size(); i++ ) { const Box2i &area = areas[i]; Color3f color( 0 ); for( int y=area.min.y; y<=area.max.y; y++ ) { int yRel = y - dataWindow.min.y; float angle = angleAtTop - yRel * radiansPerPixel; float weight = cosf( angle ); int index = (area.min.x - dataWindow.min.x) + (dataWindow.size().x + 1 ) * yRel; for( int x=area.min.x; x<=area.max.x; x++ ) { color[0] += weight * red[index]; color[1] += weight * green[index]; color[2] += weight * blue[index]; index++; } } color /= red.size(); colors.push_back( color ); float phi = angleAtTop - (centroids[i].y - dataWindow.min.y) * radiansPerPixel; V3f direction; direction.y = sinf( phi ); float r = cosf( phi ); float theta = 2 * M_PI * lerpfactor( (float)centroids[i].x, (float)dataWindow.min.x, (float)dataWindow.max.x ); direction.x = r * cosf( theta ); direction.z = r * sinf( theta ); directions.push_back( -direction ); // negated so we output the direction the light shines in } // return the result CompoundObjectPtr result = new CompoundObject; result->members()["directions"] = directionsData; result->members()["colors"] = colorsData; return result; }
void YUVImageWriter::writeImage( const vector<string> &names, const ImagePrimitive * image, const Box2i &dataWindow ) const { const V2f &kBkR = m_kBkRParameter->getTypedValue(); const Box3f &range = m_rangeParameter->getTypedValue(); if ( range.isEmpty() ) { throw InvalidArgumentException("YUVImageWriter: Empty YUV range specified "); } const float kB = kBkR.x; const float kR = kBkR.y; int displayWidth = 1 + image->getDisplayWindow().size().x; int displayHeight = 1 + image->getDisplayWindow().size().y; if ( displayWidth % 2 != 0 || displayHeight % 2 != 0 ) { throw IOException("YUVImageWriter: Unsupported resolution"); } vector<string>::const_iterator rIt = std::find( names.begin(), names.end(), "R" ); vector<string>::const_iterator gIt = std::find( names.begin(), names.end(), "G" ); vector<string>::const_iterator bIt = std::find( names.begin(), names.end(), "B" ); if ( rIt == names.end() || gIt == names.end() || bIt == names.end() ) { throw IOException("YUVImageWriter: Unsupported channel names specified"); } std::ofstream outFile( fileName().c_str(), std::ios::trunc | std::ios::binary | std::ios::out ); if (! outFile.is_open() ) { throw IOException("Could not open '" + fileName() + "' for writing."); } Color3fVectorDataPtr rgbData = new Color3fVectorData(); rgbData->writable().resize( displayWidth * displayHeight, Color3f(0,0,0) ); try { for ( vector<string>::const_iterator it = names.begin(); it != names.end(); it++ ) { const string &name = *it; if (!( name == "R" || name == "G" || name == "B" ) ) { msg( Msg::Warning, "YUVImageWriter", format( "Channel \"%s\" was not encoded." ) % name ); continue; } int channelOffset = 0; if ( name == "R" ) { channelOffset = 0; } else if ( name == "G" ) { channelOffset = 1; } else { assert( name == "B" ); channelOffset = 2; } // get the image channel assert( image->variables.find( name ) != image->variables.end() ); DataPtr dataContainer = image->variables.find( name )->second.data; assert( dataContainer ); ChannelConverter converter( *it, image, dataWindow, channelOffset, rgbData ); despatchTypedData< ChannelConverter, TypeTraits::IsNumericVectorTypedData, ChannelConverter::ErrorHandler >( dataContainer, converter ); } V3fVectorDataPtr yuvData = new V3fVectorData(); yuvData->writable().resize( displayWidth * displayHeight, V3f(0,0,0) ); assert( yuvData->readable().size() == rgbData->readable().size() ); for ( int i = 0; i < displayWidth * displayHeight; i ++ ) { Color3f rgb = rgbData->readable()[i]; if ( rgb.x < 0.0 ) rgb.x = 0; if ( rgb.x > 1.0 ) rgb.x = 1.0; if ( rgb.y < 0.0 ) rgb.y = 0; if ( rgb.y > 1.0 ) rgb.y = 1.0; if ( rgb.z < 0.0 ) rgb.z = 0; if ( rgb.z > 1.0 ) rgb.z = 1.0; V3f yPbPr; float &Y = yPbPr.x; float &Pb = yPbPr.y; float &Pr = yPbPr.z; Y = kR * rgb.x + ( 1.0 - kR - kB ) * rgb.y + kB * rgb.z; Pb = 0.5 * ( rgb.z - Y ) / ( 1.0 - kB ); Pr = 0.5 * ( rgb.x - Y ) / ( 1.0 - kR ); V3f yCbCr = yPbPr; /// Map from 0-1 yCbCr.y += 0.5; yCbCr.z += 0.5; /// Apply any scaling for "head-room" and "toe-room" yCbCr.x = ( yCbCr.x * ( range.max.x - range.min.x ) ) + range.min.x; yCbCr.y = ( yCbCr.y * ( range.max.y - range.min.y ) ) + range.min.y; yCbCr.z = ( yCbCr.z * ( range.max.z - range.min.z ) ) + range.min.z; yuvData->writable()[i] = yCbCr; } /// \todo Chroma-filtering. Ideally we should do a proper sampled downsize of the chroma, rather than skipping data /// elements. This would avoid any aliasing. int lumaStepX = 1; int lumaStepY = 1; int chromaUStepX = 1; int chromaUStepY = 1; int chromaVStepX = 1; int chromaVStepY = 1; switch ( m_formatParameter->getNumericValue() ) { case YUV420P : /// Half res in U and V chromaUStepX = 2; chromaUStepY = 2; chromaVStepX = 2; chromaVStepY = 2; break; case YUV422P : /// Half horizonal res in U and V chromaUStepX = 2; chromaUStepY = 1; chromaVStepX = 2; chromaVStepY = 1; break; case YUV444P : /// Full res in U and V break; default : assert( false ); } ScaledDataConversion<float, unsigned char> converter; /// Y-plane for ( int y = 0; y < displayHeight; y += lumaStepX ) { for ( int x = 0; x < displayWidth; x += lumaStepY ) { const V3f yCbCr = yuvData->readable()[y*displayWidth + x]; const unsigned char val = converter( yCbCr.x ); outFile.write( (const char*)&val, 1 ); } } /// U-plane for ( int y = 0; y < displayHeight; y+=chromaUStepX ) { for ( int x = 0; x < displayWidth; x+=chromaUStepY ) { const V3f yCbCr = yuvData->readable()[y*displayWidth + x]; const unsigned char val = converter( yCbCr.y ); outFile.write( (const char*)&val, 1 ); } } /// V-plane for ( int y = 0; y < displayHeight; y+=chromaVStepX ) { for ( int x = 0; x < displayWidth; x+=chromaVStepY ) { const V3f yCbCr = yuvData->readable()[y*displayWidth + x]; const unsigned char val = converter( yCbCr.z ); outFile.write( (const char*)&val, 1 ); } } } catch ( std::exception &e ) { throw IOException( ( boost::format( "YUVImageWriter : %s" ) % e.what() ).str() ); } catch ( ... ) { throw IOException( "YUVImageWriter: Unexpected error" ); } }
IECore::ObjectPtr MeshFromNuke::doConversion( IECore::ConstCompoundObjectPtr operands ) const { // topology IntVectorDataPtr verticesPerFaceData = new IntVectorData; IntVectorDataPtr vertexIdsData = new IntVectorData; std::vector<int> &verticesPerFace = verticesPerFaceData->writable(); std::vector<int> &vertexIds = vertexIdsData->writable(); unsigned numPrimitives = m_geo->primitives(); const DD::Image::Primitive **primitives = m_geo->primitive_array(); std::vector<unsigned> tmpFaceVertices; for( unsigned primIndex=0; primIndex<numPrimitives; primIndex++ ) { const DD::Image::Primitive *prim = primitives[primIndex]; unsigned numFaces = prim->faces(); for( unsigned faceIndex=0; faceIndex<numFaces; faceIndex++ ) { unsigned numFaceVertices = prim->face_vertices( faceIndex ); verticesPerFace.push_back( numFaceVertices ); tmpFaceVertices.resize( numFaceVertices ); prim->get_face_vertices( faceIndex, &(tmpFaceVertices[0]) ); for( unsigned i=0; i<numFaceVertices; i++ ) { vertexIds.push_back( prim->vertex( tmpFaceVertices[i] ) ); } } } MeshPrimitivePtr result = new MeshPrimitive( verticesPerFaceData, vertexIdsData, "linear" ); // points if( const DD::Image::PointList *pl = m_geo->point_list() ) { V3fVectorDataPtr p = new V3fVectorData(); p->writable().resize( pl->size() ); std::transform( pl->begin(), pl->end(), p->writable().begin(), IECore::convert<Imath::V3f, DD::Image::Vector3> ); result->variables["P"] = PrimitiveVariable( PrimitiveVariable::Vertex, p ); } // uvs PrimitiveVariable::Interpolation uvInterpolation = PrimitiveVariable::Vertex; const DD::Image::Attribute *uvAttr = m_geo->get_typed_group_attribute( DD::Image::Group_Points, "uv", DD::Image::VECTOR4_ATTRIB ); if( !uvAttr ) { uvAttr = m_geo->get_typed_group_attribute( DD::Image::Group_Vertices, "uv", DD::Image::VECTOR4_ATTRIB ); uvInterpolation = PrimitiveVariable::FaceVarying; } if( uvAttr ) { V2fVectorDataPtr uvData = new V2fVectorData(); uvData->setInterpretation( GeometricData::UV ); std::vector<Imath::V2f> &uvs = uvData->writable(); uvs.reserve( uvAttr->size() ); unsigned numUVs = uvAttr->size(); for( unsigned i=0; i<numUVs; i++ ) { // as of Cortex 10, we take a UDIM centric approach // to UVs, which clashes with Nuke, so we must flip // the v values during conversion. uvs.emplace_back( uvAttr->vector4( i ).x, 1.0 - uvAttr->vector4( i ).y ); } result->variables["uv"] = PrimitiveVariable( uvInterpolation, uvData ); } // normals PrimitiveVariable::Interpolation nInterpolation = PrimitiveVariable::Vertex; const DD::Image::Attribute *nAttr = m_geo->get_typed_group_attribute( DD::Image::Group_Points, "N", DD::Image::NORMAL_ATTRIB ); if( !nAttr ) { nAttr = m_geo->get_typed_group_attribute( DD::Image::Group_Vertices, "N", DD::Image::NORMAL_ATTRIB ); nInterpolation = PrimitiveVariable::FaceVarying; } if( nAttr ) { V3fVectorDataPtr nd = new V3fVectorData(); std::vector<Imath::V3f> &n = nd->writable(); n.resize( nAttr->size() ); for( unsigned i=0; i<n.size(); i++ ) { n[i] = IECore::convert<Imath::V3f, DD::Image::Vector3>( nAttr->normal( i ) ); } result->variables["N"] = PrimitiveVariable( nInterpolation, nd ); } return result; }
IECore::ConstCompoundDataPtr OSLImage::computeShading( const Gaffer::Context *context ) const { OSLRenderer::ConstShadingEnginePtr shadingEngine; if( const OSLShader *shader = runTimeCast<const OSLShader>( shaderPlug()->source<Plug>()->node() ) ) { shadingEngine = shader->shadingEngine(); } if( !shadingEngine ) { return static_cast<const CompoundData *>( shadingPlug()->defaultValue() ); } const V2i tileOrigin = context->get<V2i>( ImagePlug::tileOriginContextName ); const Format format = inPlug()->formatPlug()->getValue(); CompoundDataPtr shadingPoints = new CompoundData(); V3fVectorDataPtr pData = new V3fVectorData; FloatVectorDataPtr uData = new FloatVectorData; FloatVectorDataPtr vData = new FloatVectorData; vector<V3f> &pWritable = pData->writable(); vector<float> &uWritable = uData->writable(); vector<float> &vWritable = vData->writable(); const size_t tileSize = ImagePlug::tileSize(); pWritable.reserve( tileSize * tileSize ); uWritable.reserve( tileSize * tileSize ); vWritable.reserve( tileSize * tileSize ); /// \todo Non-zero display window origins - do we have those? const float uStep = 1.0f / format.width(); const float uMin = 0.5f * uStep; const float vStep = 1.0f / format.height(); const float vMin = 0.5f * vStep; const size_t xMax = tileOrigin.x + tileSize; const size_t yMax = tileOrigin.y + tileSize; for( size_t y = tileOrigin.y; y < yMax; ++y ) { const float v = vMin + y * vStep; for( size_t x = tileOrigin.x; x < xMax; ++x ) { uWritable.push_back( uMin + x * uStep ); vWritable.push_back( v ); pWritable.push_back( V3f( x, y, 0.0f ) ); } } shadingPoints->writable()["P"] = pData; shadingPoints->writable()["u"] = uData; shadingPoints->writable()["v"] = vData; ConstStringVectorDataPtr channelNamesData = inPlug()->channelNamesPlug()->getValue(); const vector<string> &channelNames = channelNamesData->readable(); for( vector<string>::const_iterator it = channelNames.begin(), eIt = channelNames.end(); it != eIt; ++it ) { shadingPoints->writable()[*it] = boost::const_pointer_cast<FloatVectorData>( inPlug()->channelData( *it, tileOrigin ) ); } CompoundDataPtr result = shadingEngine->shade( shadingPoints.get() ); // remove results that aren't suitable to become channels for( CompoundDataMap::iterator it = result->writable().begin(); it != result->writable().end(); ) { CompoundDataMap::iterator nextIt = it; nextIt++; if( !runTimeCast<FloatVectorData>( it->second ) ) { result->writable().erase( it ); } it = nextIt; } return result; }
ObjectPtr BINMeshReader::doOperation( const CompoundObject *operands ) { const std::string &fileName = m_fileNameParameter->getTypedValue(); ifstream f( fileName.c_str() ); f.seekg( 0, ios_base::beg ); uint32_t magic = 0; readLittleEndian( f, magic ); uint32_t version = 0; readLittleEndian( f, version ); if ( version <= 3 ) { throw IOException(( boost::format( "BINMeshReader: '%s' is of an unsupported version" ) % fileName ).str() ); } MeshPrimitivePtr mesh = new MeshPrimitive(); uint32_t numVertices = 0; bool foundGeometryChunk = false; bool done = false; uint32_t chunkId = 0; while ( !done && !f.fail() ) { readLittleEndian( f, chunkId ); if ( f.fail() ) { throw IOException(( boost::format( "BINMeshReader: Error encountered while reading '%s'" ) % fileName ).str() ); } if ( chunkId == 0xDEDEDEDE ) /// EOF marker { if ( !foundGeometryChunk ) { throw IOException(( boost::format( "BINMeshReader: No geometry chunk encountered while reading '%s'" ) % fileName ).str() ); } done = true; } else if ( chunkId == 0xCCCCCCCC ) /// geometry chunk { if ( foundGeometryChunk ) { throw IOException(( boost::format( "BINMeshReader: Duplicate geometry chunk encountered while reading '%s'" ) % fileName ).str() ); } foundGeometryChunk = true; V3fVectorDataPtr pData = new V3fVectorData(); readLittleEndian( f, numVertices ); pData->writable().resize( numVertices ); for ( uint32_t i = 0; i < numVertices; i ++ ) { V3f p; readLittleEndian( f, p.x ); readLittleEndian( f, p.y ); readLittleEndian( f, p.z ); pData->writable()[i] = p; } uint32_t numFaces = 0; readLittleEndian( f, numFaces ); IntVectorDataPtr vertsPerFaceData = new IntVectorData(); /// All faces are triangles vertsPerFaceData->writable().resize( numFaces, 3 ); IntVectorDataPtr vertIdsData = new IntVectorData(); vertIdsData->writable().reserve( numFaces * 3 ); for ( uint32_t i = 0; i < numFaces; i ++ ) { uint32_t v0 = 0, v1 = 0, v2 = 0; readLittleEndian( f, v0 ); readLittleEndian( f, v1 ); readLittleEndian( f, v2 ); vertIdsData->writable().push_back( v0 ); vertIdsData->writable().push_back( v1 ); vertIdsData->writable().push_back( v2 ); } mesh->variables[ "P" ] = PrimitiveVariable( PrimitiveVariable::Vertex, pData ); mesh->setTopology( vertsPerFaceData, vertIdsData, "linear" ); } else if ( chunkId == 0xCCCCCC00 ) /// texture chunk { if ( !foundGeometryChunk ) { throw IOException(( boost::format( "BINMeshReader: No geometry chunk encountered while reading '%s'" ) % fileName ).str() ); } uint32_t numFluids = 0; readLittleEndian( f, numFluids ); V3fVectorDataPtr uvwData = new V3fVectorData(); uvwData->writable().resize( numVertices ); for ( uint32_t v = 0; v < numVertices; v ++ ) { for ( uint32_t fl = 0; fl < numFluids - 1; fl ++ ) { /// Just skip over there for now /// \todo Work out what to do with them float textureWeight = 0.0f; readLittleEndian( f, textureWeight ); } V3f uvw; readLittleEndian( f, uvw.x ); readLittleEndian( f, uvw.y ); readLittleEndian( f, uvw.z ); uvwData->writable()[v] = uvw; } mesh->variables[ "uvw" ] = PrimitiveVariable( PrimitiveVariable::Vertex, uvwData ); } else if ( chunkId == 0xCCCCCC11 ) /// velocity chunk { if ( !foundGeometryChunk ) { throw IOException(( boost::format( "BINMeshReader: No geometry chunk encountered while reading '%s'" ) % fileName ).str() ); } V3fVectorDataPtr velocityData = new V3fVectorData(); velocityData->writable().resize( numVertices ); for ( uint32_t i = 0; i < numVertices; i ++ ) { V3f vel; readLittleEndian( f, vel.x ); readLittleEndian( f, vel.y ); readLittleEndian( f, vel.z ); velocityData->writable()[i] = vel; } mesh->variables[ "velocity" ] = PrimitiveVariable( PrimitiveVariable::Vertex, velocityData ); } else { throw IOException(( boost::format( "BINMeshReader: Invalid chunk encountered while reading '%s'" ) % fileName ).str() ); } } if ( chunkId != 0xDEDEDEDE ) { throw IOException(( boost::format( "BINMeshReader: No end of file chunk encountered while reading '%s'" ) % fileName ).str() ); } assert( mesh ); return mesh; }
ObjectPtr SLOReader::doOperation( const CompoundObject * operands ) { tbb::mutex::scoped_lock lock( g_mutex ); if( Slo_SetShader( (char *)fileName().c_str() ) ) { throw Exception( boost::str( boost::format( "Unable to set shader to \"%s\"" ) % fileName() ) ); } string name = Slo_GetName(); string type = Slo_TypetoStr( Slo_GetType() ); ShaderPtr result = new Shader( name, type ); CompoundDataPtr typeHints = new CompoundData; result->blindData()->writable().insert( pair<string, DataPtr>( "ri:parameterTypeHints", typeHints ) ); // we lose the ordering of parameter names when we put them in result->parameters(), // so we stick the correct order in the blind data as a workaround for anyone interested // in the true ordering. StringVectorDataPtr orderedParameterNames = new StringVectorData; result->blindData()->writable().insert( pair<string, DataPtr>( "ri:orderedParameterNames", orderedParameterNames ) ); // we don't have a way of communicating which parameters are outputs in the Shader::parametersData(), // so we work around that using the blind data too. StringVectorDataPtr outputParameterNames = new StringVectorData; result->blindData()->writable().insert( pair<string, DataPtr>( "ri:outputParameterNames", outputParameterNames ) ); int numArgs = Slo_GetNArgs(); for( int i=1; i<=numArgs; i++ ) { DataPtr data = 0; SLO_VISSYMDEF *arg = Slo_GetArgById( i ); switch( arg->svd_type ) { case SLO_TYPE_POINT : case SLO_TYPE_VECTOR : case SLO_TYPE_NORMAL : { if( arg->svd_arraylen==0 ) { const SLO_POINT *p = arg->svd_default.pointval; if( p ) { data = new V3fData( V3f( p->xval, p->yval, p->zval ) ); } else { // 0 length and null value signifies a variable length array data = new V3fVectorData(); } } else { V3fVectorDataPtr vData = new V3fVectorData(); data = vData; for( int j=0; j<arg->svd_arraylen; j++ ) { SLO_VISSYMDEF *a = Slo_GetArrayArgElement( arg, j ); const SLO_POINT *p = a->svd_default.pointval; vData->writable().push_back( V3f( p->xval, p->yval, p->zval ) ); } } typeHints->writable().insert( pair<string, DataPtr>( arg->svd_name, new StringData( Slo_TypetoStr( arg->svd_type ) ) ) ); break; } case SLO_TYPE_COLOR : { if( arg->svd_arraylen==0 ) { const SLO_POINT *p = arg->svd_default.pointval; if( p ) { data = new Color3fData( Color3f( p->xval, p->yval, p->zval ) ); } else { // 0 length and null value signifies a variable length array data = new Color3fVectorData(); } } else { Color3fVectorDataPtr vData = new Color3fVectorData(); data = vData; for( int j=0; j<arg->svd_arraylen; j++ ) { SLO_VISSYMDEF *a = Slo_GetArrayArgElement( arg, j ); const SLO_POINT *p = a->svd_default.pointval; vData->writable().push_back( Color3f( p->xval, p->yval, p->zval ) ); } } } break; case SLO_TYPE_SCALAR : { if( arg->svd_arraylen==0 ) { const float *value = arg->svd_default.scalarval; if( value ) { data = new FloatData( *value ); } else { // 0 length and null value signifies a variable length array data = new FloatVectorData(); } } else { FloatVectorDataPtr vData = new FloatVectorData(); data = vData; for( int j=0; j<arg->svd_arraylen; j++ ) { SLO_VISSYMDEF *a = Slo_GetArrayArgElement( arg, j ); vData->writable().push_back( *(a->svd_default.scalarval) ); } if( arg->svd_arraylen==3 ) { // allow V3fData and V3fVectorData to be mapped to float[3] parameters. typeHints->writable().insert( pair<string, DataPtr>( arg->svd_name, new StringData( "float[3]" ) ) ); } } } break; case SLO_TYPE_STRING : { if( arg->svd_arraylen==0 ) { const char *defaultValue = arg->svd_default.stringval; if( defaultValue ) { data = new StringData( defaultValue ); } else { // 0 length and null value signifies a variable length array data = new StringVectorData(); } } else { StringVectorDataPtr vData = new StringVectorData(); data = vData; for( int j=0; j<arg->svd_arraylen; j++ ) { SLO_VISSYMDEF *a = Slo_GetArrayArgElement( arg, j ); // sometimes the default value for an element of a string array can be a null pointer. // i'm not sure what the meaning of this is. the 3delight shaderinfo utility reports such values // as "(null)", so that's what we do too. const char *defaultValue = a->svd_default.stringval; vData->writable().push_back( defaultValue ? defaultValue : "(null)" ); } } } break; case SLO_TYPE_MATRIX : { if( arg->svd_arraylen==0 ) { const float *m = arg->svd_default.matrixval; if( m ) { M44f mm( m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15] ); data = new M44fData( mm ); } else { // 0 length and null value signifies a variable length array data = new M44fVectorData(); } } else { M44fVectorDataPtr vData = new M44fVectorData(); data = vData; for( int j=0; j<arg->svd_arraylen; j++ ) { SLO_VISSYMDEF *a = Slo_GetArrayArgElement( arg, j ); const float *m = a->svd_default.matrixval; M44f mm( m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15] ); vData->writable().push_back( mm ); } } } break; case SLO_TYPE_SHADER : { if( arg->svd_arraylen==0 ) { if( !arg->svd_valisvalid ) { // variable length array data = new StringVectorData(); } else { data = new StringData(); } } else { StringVectorDataPtr sData = new StringVectorData(); data = sData; sData->writable().resize( arg->svd_arraylen ); } typeHints->writable().insert( pair<string, DataPtr>( arg->svd_name, new StringData( Slo_TypetoStr( arg->svd_type ) ) ) ); } break; default : msg( Msg::Warning, "SLOReader::read", format( "Parameter \"%s\" has unsupported type." ) % arg->svd_name ); } if( data ) { orderedParameterNames->writable().push_back( arg->svd_name ); result->parameters().insert( CompoundDataMap::value_type( arg->svd_name, data ) ); if( arg->svd_storage == SLO_STOR_OUTPUTPARAMETER ) { outputParameterNames->writable().push_back( arg->svd_name ); } } } // shader annotations CompoundDataPtr annotations = new CompoundData; result->blindData()->writable().insert( pair<string, DataPtr>( "ri:annotations", annotations ) ); #ifndef PRMANEXPORT for( int i=1, n=Slo_GetNAnnotations(); i <= n; i++ ) { const char *key = Slo_GetAnnotationKeyById( i ); annotations->writable()[key] = new StringData( Slo_GetAnnotationByKey( key ) ); } #endif Slo_EndShader(); return result; }
IECoreGL::ConstRenderablePtr StandardLightVisualiser::colorIndicator( const Imath::Color3f &color, bool faceCamera ) { float maxChannel = std::max( color[0], std::max( color[1], color[2] ) ); float exposure = 0; Imath::Color3f indicatorColor = color; if( maxChannel > 1 ) { indicatorColor = color / maxChannel; exposure = log( maxChannel ) / log( 2 ); } IECoreGL::GroupPtr group = new IECoreGL::Group(); IECoreGL::GroupPtr wirelessGroup = new IECoreGL::Group(); IECore::CompoundObjectPtr parameters = new CompoundObject; parameters->members()["aimType"] = new IntData( 1 ); group->getState()->add( new IECoreGL::ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), faceCamera ? faceCameraVertexSource() : "", "", IECoreGL::Shader::constantFragmentSource(), parameters ) ); wirelessGroup->getState()->add( new IECoreGL::Primitive::DrawWireframe( false ) ); float indicatorRad = 0.3; int indicatorAxis = faceCamera ? 0 : 2; { IntVectorDataPtr vertsPerPoly = new IntVectorData; IntVectorDataPtr vertIds = new IntVectorData; V3fVectorDataPtr p = new V3fVectorData; addSolidArc( indicatorAxis, V3f( 0 ), indicatorRad, indicatorRad * 0.9, 0, 1, vertsPerPoly->writable(), vertIds->writable(), p->writable() ); IECore::MeshPrimitivePtr mesh = new IECore::MeshPrimitive( vertsPerPoly, vertIds, "linear", p ); mesh->variables["N"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new V3fData( V3f( 0 ) ) ); mesh->variables["Cs"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( indicatorColor ) ); ToGLMeshConverterPtr meshConverter = new ToGLMeshConverter( mesh ); group->addChild( IECore::runTimeCast<IECoreGL::Renderable>( meshConverter->convert() ) ); } { IntVectorDataPtr vertsPerPoly = new IntVectorData; IntVectorDataPtr vertIds = new IntVectorData; V3fVectorDataPtr p = new V3fVectorData; addSolidArc( indicatorAxis, V3f( 0 ), indicatorRad * 0.4, 0.0, 0, 1, vertsPerPoly->writable(), vertIds->writable(), p->writable() ); for( int i = 0; i < exposure && i < 20; i++ ) { float startAngle = 1 - pow( 0.875, i ); float endAngle = 1 - pow( 0.875, std::min( i+1.0, (double)exposure ) ); float maxEndAngle = 1 - pow( 0.875, i+1.0); float sectorScale = ( maxEndAngle - startAngle - 0.008 ) / ( maxEndAngle - startAngle ); addSolidArc( indicatorAxis, V3f( 0 ), indicatorRad * 0.85, indicatorRad * 0.45, startAngle, startAngle + ( endAngle - startAngle ) * sectorScale, vertsPerPoly->writable(), vertIds->writable(), p->writable() ); } IECore::MeshPrimitivePtr mesh = new IECore::MeshPrimitive( vertsPerPoly, vertIds, "linear", p ); mesh->variables["N"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new V3fData( V3f( 0 ) ) ); mesh->variables["Cs"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( indicatorColor ) ); ToGLMeshConverterPtr meshConverter = new ToGLMeshConverter( mesh ); wirelessGroup->addChild( IECore::runTimeCast<IECoreGL::Renderable>( meshConverter->convert() ) ); } // For exposures greater than 20, draw an additional solid bar of a darker color at the very end, without any segment dividers if( exposure > 20 ) { IntVectorDataPtr vertsPerPoly = new IntVectorData; IntVectorDataPtr vertIds = new IntVectorData; V3fVectorDataPtr p = new V3fVectorData; float startAngle = 1 - pow( 0.875, 20 ); float endAngle = 1 - pow( 0.875, (double)exposure ); addSolidArc( indicatorAxis, V3f( 0 ), indicatorRad * 0.85, indicatorRad * 0.45, startAngle, endAngle, vertsPerPoly->writable(), vertIds->writable(), p->writable() ); IECore::MeshPrimitivePtr mesh = new IECore::MeshPrimitive( vertsPerPoly, vertIds, "linear", p ); mesh->variables["N"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new V3fData( V3f( 0 ) ) ); mesh->variables["Cs"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( 0.5f * indicatorColor ) ); ToGLMeshConverterPtr meshConverter = new ToGLMeshConverter( mesh ); wirelessGroup->addChild( IECore::runTimeCast<IECoreGL::Renderable>( meshConverter->convert() ) ); } group->addChild( wirelessGroup ); return group; }
MeshPrimitivePtr MeshPrimitive::createSphere( float radius, float zMin, float zMax, float thetaMax, const Imath::V2i &divisions ) { IntVectorDataPtr vertexIds = new IntVectorData; IntVectorDataPtr verticesPerFace = new IntVectorData; std::vector<int> &vpf = verticesPerFace->writable(); std::vector<int> &vIds = vertexIds->writable(); V3fVectorDataPtr pData = new V3fVectorData; V3fVectorDataPtr nData = new V3fVectorData; std::vector<V3f> &pVector = pData->writable(); std::vector<V3f> &nVector = nData->writable(); FloatVectorDataPtr sData = new FloatVectorData; FloatVectorDataPtr tData = new FloatVectorData; std::vector<float> &sVector = sData->writable(); std::vector<float> &tVector = tData->writable(); float oMin = Math<float>::asin( zMin ); float oMax = Math<float>::asin( zMax ); const unsigned int nO = max( 4u, (unsigned int)( ( divisions.x + 1 ) * (oMax - oMin) / M_PI ) ); float thetaMaxRad = thetaMax / 180.0f * M_PI; const unsigned int nT = max( 7u, (unsigned int)( ( divisions.y + 1 ) * thetaMaxRad / (M_PI*2) ) ); for ( unsigned int i=0; i<nO; i++ ) { float v = (float)i/(float)(nO-1); float o = lerp( oMin, oMax, v ); float z = radius * Math<float>::sin( o ); float r = radius * Math<float>::cos( o ); for ( unsigned int j=0; j<nT; j++ ) { float u = (float)j/(float)(nT-1); float theta = thetaMaxRad * u; V3f p( r * Math<float>::cos( theta ), r * Math<float>::sin( theta ), z ); sVector.push_back( u ); tVector.push_back( v ); pVector.push_back( p ); nVector.push_back( p ); if( i < nO - 1 && j < nT - 1 ) { unsigned int i0 = i * nT + j; unsigned int i1 = i0 + 1; unsigned int i2 = i0 + nT; unsigned int i3 = i2 + 1; vpf.push_back( 3 ); vIds.push_back( i0 ); vIds.push_back( i1 ); vIds.push_back( i2 ); vpf.push_back( 3 ); vIds.push_back( i1 ); vIds.push_back( i3 ); vIds.push_back( i2 ); } } } MeshPrimitivePtr result = new MeshPrimitive( verticesPerFace, vertexIds, "linear", pData ); result->variables["N"] = PrimitiveVariable( PrimitiveVariable::Vertex, nData ); result->variables["s"] = PrimitiveVariable( PrimitiveVariable::Vertex, sData ); result->variables["t"] = PrimitiveVariable( PrimitiveVariable::Vertex, tData ); return result; }
MeshPrimitivePtr MeshPrimitive::createPlane( const Box2f &b, const Imath::V2i &divisions ) { V3fVectorDataPtr pData = new V3fVectorData; std::vector<V3f> &p = pData->writable(); // add vertices float xStep = b.size().x / (float)divisions.x; float yStep = b.size().y / (float)divisions.y; for ( int i = 0; i <= divisions.y; ++i ) { for ( int j = 0; j <= divisions.x; ++j ) { p.push_back( V3f( b.min.x + j * xStep, b.min.y + i * yStep, 0 ) ); } } IntVectorDataPtr vertexIds = new IntVectorData; IntVectorDataPtr verticesPerFace = new IntVectorData; std::vector<int> &vpf = verticesPerFace->writable(); std::vector<int> &vIds = vertexIds->writable(); FloatVectorDataPtr sData = new FloatVectorData; FloatVectorDataPtr tData = new FloatVectorData; std::vector<float> &s = sData->writable(); std::vector<float> &t = tData->writable(); float sStep = 1.0f / (float)divisions.x; float tStep = 1.0f / (float)divisions.y; // add faces int v0, v1, v2, v3; for ( int i = 0; i < divisions.y; ++i ) { for ( int j = 0; j < divisions.x; ++j ) { v0 = j + (divisions.x+1) * i; v1 = j + 1 + (divisions.x+1) * i;; v2 = j + 1 + (divisions.x+1) * (i+1); v3 = j + (divisions.x+1) * (i+1); vpf.push_back( 4 ); vIds.push_back( v0 ); vIds.push_back( v1 ); vIds.push_back( v2 ); vIds.push_back( v3 ); s.push_back( j * sStep ); s.push_back( (j+1) * sStep ); s.push_back( (j+1) * sStep ); s.push_back( j * sStep ); t.push_back( 1 - i * tStep ); t.push_back( 1 - i * tStep ); t.push_back( 1 - (i+1) * tStep ); t.push_back( 1 - (i+1) * tStep ); } } MeshPrimitivePtr result = new MeshPrimitive( verticesPerFace, vertexIds, "linear", pData ); result->variables["s"] = PrimitiveVariable( PrimitiveVariable::FaceVarying, sData ); result->variables["t"] = PrimitiveVariable( PrimitiveVariable::FaceVarying, tData ); return result; }
void SceneProcedural::drawCamera( const IECore::Camera *camera, IECore::Renderer *renderer ) const { CameraPtr fullCamera = camera->copy(); fullCamera->addStandardParameters(); AttributeBlock attributeBlock( renderer ); renderer->setAttribute( "gl:primitive:wireframe", new BoolData( true ) ); renderer->setAttribute( "gl:primitive:solid", new BoolData( false ) ); renderer->setAttribute( "gl:curvesPrimitive:useGLLines", new BoolData( true ) ); renderer->setAttribute( "gl:primitive:wireframeColor", new Color4fData( Color4f( 0, 0.25, 0, 1 ) ) ); CurvesPrimitive::createBox( Box3f( V3f( -0.5, -0.5, 0 ), V3f( 0.5, 0.5, 2.0 ) ) )->render( renderer ); const std::string &projection = fullCamera->parametersData()->member<StringData>( "projection" )->readable(); const Box2f &screenWindow = fullCamera->parametersData()->member<Box2fData>( "screenWindow" )->readable(); /// \todo When we're drawing the camera by some means other than creating a primitive for it, /// use the actual clippings planes. Right now that's not a good idea as it results in /huge/ /// framing bounds when the viewer frames a selected camera. V2f clippingPlanes( 0, 5 ); Box2f near( screenWindow ); Box2f far( screenWindow ); if( projection == "perspective" ) { float fov = fullCamera->parametersData()->member<FloatData>( "projection:fov" )->readable(); float d = tan( degreesToRadians( fov / 2.0f ) ); near.min *= d * clippingPlanes[0]; near.max *= d * clippingPlanes[0]; far.min *= d * clippingPlanes[1]; far.max *= d * clippingPlanes[1]; } V3fVectorDataPtr p = new V3fVectorData; IntVectorDataPtr n = new IntVectorData; n->writable().push_back( 5 ); p->writable().push_back( V3f( near.min.x, near.min.y, -clippingPlanes[0] ) ); p->writable().push_back( V3f( near.max.x, near.min.y, -clippingPlanes[0] ) ); p->writable().push_back( V3f( near.max.x, near.max.y, -clippingPlanes[0] ) ); p->writable().push_back( V3f( near.min.x, near.max.y, -clippingPlanes[0] ) ); p->writable().push_back( V3f( near.min.x, near.min.y, -clippingPlanes[0] ) ); n->writable().push_back( 5 ); p->writable().push_back( V3f( far.min.x, far.min.y, -clippingPlanes[1] ) ); p->writable().push_back( V3f( far.max.x, far.min.y, -clippingPlanes[1] ) ); p->writable().push_back( V3f( far.max.x, far.max.y, -clippingPlanes[1] ) ); p->writable().push_back( V3f( far.min.x, far.max.y, -clippingPlanes[1] ) ); p->writable().push_back( V3f( far.min.x, far.min.y, -clippingPlanes[1] ) ); n->writable().push_back( 2 ); p->writable().push_back( V3f( near.min.x, near.min.y, -clippingPlanes[0] ) ); p->writable().push_back( V3f( far.min.x, far.min.y, -clippingPlanes[1] ) ); n->writable().push_back( 2 ); p->writable().push_back( V3f( near.max.x, near.min.y, -clippingPlanes[0] ) ); p->writable().push_back( V3f( far.max.x, far.min.y, -clippingPlanes[1] ) ); n->writable().push_back( 2 ); p->writable().push_back( V3f( near.max.x, near.max.y, -clippingPlanes[0] ) ); p->writable().push_back( V3f( far.max.x, far.max.y, -clippingPlanes[1] ) ); n->writable().push_back( 2 ); p->writable().push_back( V3f( near.min.x, near.max.y, -clippingPlanes[0] ) ); p->writable().push_back( V3f( far.min.x, far.max.y, -clippingPlanes[1] ) ); CurvesPrimitivePtr c = new IECore::CurvesPrimitive( n, CubicBasisf::linear(), false, p ); c->render( renderer ); }
std::pair<PrimitiveVariable, PrimitiveVariable> IECoreScene::MeshAlgo::calculateTangents( const MeshPrimitive *mesh, const std::string &uvSet, /* = "uv" */ bool orthoTangents, /* = true */ const std::string &position /* = "P" */ ) { if( mesh->minVerticesPerFace() != 3 || mesh->maxVerticesPerFace() != 3 ) { throw InvalidArgumentException( "MeshAlgo::calculateTangents : MeshPrimitive must only contain triangles" ); } const V3fVectorData *positionData = mesh->variableData<V3fVectorData>( position ); if( !positionData ) { std::string e = boost::str( boost::format( "MeshAlgo::calculateTangents : MeshPrimitive has no Vertex \"%s\" primitive variable." ) % position ); throw InvalidArgumentException( e ); } const V3fVectorData::ValueType &points = positionData->readable(); const IntVectorData *vertsPerFaceData = mesh->verticesPerFace(); const IntVectorData::ValueType &vertsPerFace = vertsPerFaceData->readable(); const IntVectorData *vertIdsData = mesh->vertexIds(); const IntVectorData::ValueType &vertIds = vertIdsData->readable(); const auto uvIt = mesh->variables.find( uvSet ); if( uvIt == mesh->variables.end() || uvIt->second.interpolation != PrimitiveVariable::FaceVarying || uvIt->second.data->typeId() != V2fVectorDataTypeId ) { throw InvalidArgumentException( ( boost::format( "MeshAlgo::calculateTangents : MeshPrimitive has no FaceVarying V2fVectorData primitive variable named \"%s\"." ) % ( uvSet ) ).str() ); } const V2fVectorData *uvData = runTimeCast<V2fVectorData>( uvIt->second.data.get() ); const V2fVectorData::ValueType &uvs = uvData->readable(); // I'm a little unsure about using the vertIds as a fallback for the stIndices. const IntVectorData::ValueType &uvIndices = uvIt->second.indices ? uvIt->second.indices->readable() : vertIds; size_t numUVs = uvs.size(); std::vector<V3f> uTangents( numUVs, V3f( 0 ) ); std::vector<V3f> vTangents( numUVs, V3f( 0 ) ); std::vector<V3f> normals( numUVs, V3f( 0 ) ); for( size_t faceIndex = 0; faceIndex < vertsPerFace.size(); faceIndex++ ) { assert( vertsPerFace[faceIndex] == 3 ); // indices into the facevarying data for this face size_t fvi0 = faceIndex * 3; size_t fvi1 = fvi0 + 1; size_t fvi2 = fvi1 + 1; assert( fvi2 < vertIds.size() ); assert( fvi2 < uvIndices.size() ); // positions for each vertex of this face const V3f &p0 = points[vertIds[fvi0]]; const V3f &p1 = points[vertIds[fvi1]]; const V3f &p2 = points[vertIds[fvi2]]; // uv coordinates for each vertex of this face const V2f &uv0 = uvs[uvIndices[fvi0]]; const V2f &uv1 = uvs[uvIndices[fvi1]]; const V2f &uv2 = uvs[uvIndices[fvi2]]; // compute tangents and normal for this face const V3f e0 = p1 - p0; const V3f e1 = p2 - p0; const V2f e0uv = uv1 - uv0; const V2f e1uv = uv2 - uv0; V3f tangent = ( e0 * -e1uv.y + e1 * e0uv.y ).normalized(); V3f bitangent = ( e0 * -e1uv.x + e1 * e0uv.x ).normalized(); V3f normal = ( p2 - p1 ).cross( p0 - p1 ); normal.normalize(); // and accumlate them into the computation so far uTangents[uvIndices[fvi0]] += tangent; uTangents[uvIndices[fvi1]] += tangent; uTangents[uvIndices[fvi2]] += tangent; vTangents[uvIndices[fvi0]] += bitangent; vTangents[uvIndices[fvi1]] += bitangent; vTangents[uvIndices[fvi2]] += bitangent; normals[uvIndices[fvi0]] += normal; normals[uvIndices[fvi1]] += normal; normals[uvIndices[fvi2]] += normal; } // normalize and orthogonalize everything for( size_t i = 0; i < uTangents.size(); i++ ) { normals[i].normalize(); uTangents[i].normalize(); vTangents[i].normalize(); // Make uTangent/vTangent orthogonal to normal uTangents[i] -= normals[i] * uTangents[i].dot( normals[i] ); vTangents[i] -= normals[i] * vTangents[i].dot( normals[i] ); uTangents[i].normalize(); vTangents[i].normalize(); if( orthoTangents ) { vTangents[i] -= uTangents[i] * vTangents[i].dot( uTangents[i] ); vTangents[i].normalize(); } // Ensure we have set of basis vectors (n, uT, vT) with the correct handedness. if( uTangents[i].cross( vTangents[i] ).dot( normals[i] ) < 0.0f ) { uTangents[i] *= -1.0f; } } // convert the tangents back to facevarying data and add that to the mesh V3fVectorDataPtr fvUD = new V3fVectorData(); V3fVectorDataPtr fvVD = new V3fVectorData(); std::vector<V3f> &fvU = fvUD->writable(); std::vector<V3f> &fvV = fvVD->writable(); fvU.resize( uvIndices.size() ); fvV.resize( uvIndices.size() ); for( unsigned i = 0; i < uvIndices.size(); i++ ) { fvU[i] = uTangents[uvIndices[i]]; fvV[i] = vTangents[uvIndices[i]]; } PrimitiveVariable tangentPrimVar( PrimitiveVariable::FaceVarying, fvUD ); PrimitiveVariable bitangentPrimVar( PrimitiveVariable::FaceVarying, fvVD ); return std::make_pair( tangentPrimVar, bitangentPrimVar ); }