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; }
ShadingResults( size_t numPoints ) : m_results( new CompoundData ), m_ci( NULL ) { Color3fVectorDataPtr ciData = new Color3fVectorData(); m_ci = &ciData->writable(); m_ci->resize( numPoints, Color3f( 0.0f ) ); CompoundDataPtr result = new CompoundData(); m_results->writable()["Ci"] = ciData; }
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" ); } }
void LuminanceOp::modifyPrimitive( Primitive * primitive, const CompoundObject * operands ) { DataPtr luminanceData = 0; PrimitiveVariable::Interpolation interpolation = PrimitiveVariable::Invalid; int steps[3] = { 1, 1, 1 }; PrimitiveVariableMap::iterator colorIt = primitive->variables.find( m_colorPrimVarParameter->getTypedValue() ); if( colorIt!=primitive->variables.end() && colorIt->second.data ) { // RGB in a single channel switch( colorIt->second.data->typeId() ) { case Color3fDataTypeId : { FloatDataPtr l = new FloatData; const float *d = staticPointerCast<Color3fData>( colorIt->second.data )->baseReadable(); calculate( d, d + 1, d + 2, steps, 1, l->baseWritable() ); luminanceData = l; } break; case Color3fVectorDataTypeId : { FloatVectorDataPtr l = new FloatVectorData; Color3fVectorDataPtr d = staticPointerCast<Color3fVectorData>( colorIt->second.data ); l->writable().resize( d->readable().size() ); const float *dd = d->baseReadable(); steps[0] = steps[1] = steps[2] = 3; calculate( dd, dd + 1, dd + 2, steps, d->readable().size(), l->baseWritable() ); luminanceData = l; } break; default : throw Exception( "PrimitiveVariable has unsupported type." ); break; } interpolation = colorIt->second.interpolation; } else { // separate RGB channels? PrimitiveVariableMap::iterator rIt = primitive->variables.find( m_redPrimVarParameter->getTypedValue() ); PrimitiveVariableMap::iterator gIt = primitive->variables.find( m_greenPrimVarParameter->getTypedValue() ); PrimitiveVariableMap::iterator bIt = primitive->variables.find( m_bluePrimVarParameter->getTypedValue() ); if( rIt==primitive->variables.end() || gIt==primitive->variables.end() || bIt==primitive->variables.end() ) { throw Exception( "Primitive does not have appropriately named PrimitiveVariables." ); } TypeId type = rIt->second.data->typeId(); if( gIt->second.data->typeId() != type || bIt->second.data->typeId() != type ) { throw Exception( "PrimitiveVariable types do not match." ); } size_t rSize = despatchTypedData<TypedDataSize>( rIt->second.data ); size_t gSize = despatchTypedData<TypedDataSize>( gIt->second.data ); size_t bSize = despatchTypedData<TypedDataSize>( bIt->second.data ); if( rSize!=gSize || rSize!=bSize ) { throw Exception( "PrimitiveVariable sizes do not match." ); } switch( type ) { case HalfDataTypeId : { HalfDataPtr l = new HalfData; calculate( staticPointerCast<HalfData>( rIt->second.data )->baseReadable(), staticPointerCast<HalfData>( gIt->second.data )->baseReadable(), staticPointerCast<HalfData>( bIt->second.data )->baseReadable(), steps, rSize, l->baseWritable() ); luminanceData = l; } break; case HalfVectorDataTypeId : { HalfVectorDataPtr l = new HalfVectorData; l->writable().resize( rSize ); calculate( staticPointerCast<HalfVectorData>( rIt->second.data )->baseReadable(), staticPointerCast<HalfVectorData>( gIt->second.data )->baseReadable(), staticPointerCast<HalfVectorData>( bIt->second.data )->baseReadable(), steps, rSize, l->baseWritable() ); luminanceData = l; } break; case FloatDataTypeId : { FloatDataPtr l = new FloatData; calculate( staticPointerCast<FloatData>( rIt->second.data )->baseReadable(), staticPointerCast<FloatData>( gIt->second.data )->baseReadable(), staticPointerCast<FloatData>( bIt->second.data )->baseReadable(), steps, rSize, l->baseWritable() ); luminanceData = l; } break; case FloatVectorDataTypeId : { FloatVectorDataPtr l = new FloatVectorData; l->writable().resize( rSize ); calculate( staticPointerCast<FloatVectorData>( rIt->second.data )->baseReadable(), staticPointerCast<FloatVectorData>( gIt->second.data )->baseReadable(), staticPointerCast<FloatVectorData>( bIt->second.data )->baseReadable(), steps, rSize, l->baseWritable() ); luminanceData = l; } break; default : throw Exception( "PrimitiveVariables have unsupported type." ); break; } interpolation = rIt->second.interpolation; } assert( interpolation != PrimitiveVariable::Invalid ); assert( luminanceData ); primitive->variables[luminancePrimVarParameter()->getTypedValue()] = PrimitiveVariable( interpolation, luminanceData ); if( removeColorPrimVarsParameter()->getTypedValue() ) { primitive->variables.erase( colorPrimVarParameter()->getTypedValue() ); primitive->variables.erase( redPrimVarParameter()->getTypedValue() ); primitive->variables.erase( greenPrimVarParameter()->getTypedValue() ); primitive->variables.erase( bluePrimVarParameter()->getTypedValue() ); } }
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; }
IECoreScene::PrimitiveVariable FromMayaMeshConverter::colors( const MString &colorSet, bool forceRgb ) const { MFnMesh fnMesh( object() ); MFnMesh::MColorRepresentation rep = fnMesh.getColorRepresentation( colorSet ); int numColors = fnMesh.numFaceVertices(); MColorArray colors; MColor defaultColor(0,0,0,1); if ( !fnMesh.getFaceVertexColors( colors, &colorSet, &defaultColor ) ) { throw Exception( ( boost::format( "Failed to obtain colors from color set '%s'" ) % colorSet ).str() ); } int availableColors = colors.length(); if ( availableColors > numColors ) { availableColors = numColors; } DataPtr data; if ( rep == MFnMesh::kAlpha ) { if ( forceRgb ) { Color3fVectorDataPtr colorVec = new Color3fVectorData(); colorVec->writable().resize( numColors, Imath::Color3f(1) ); std::vector< Imath::Color3f >::iterator it = colorVec->writable().begin(); for ( int i = 0; i < availableColors; i++, it++ ) { *it = Imath::Color3f( colors[i][3] ); } data = colorVec; } else { FloatVectorDataPtr colorVec = new FloatVectorData(); colorVec->writable().resize( numColors, 1 ); std::vector< float >::iterator it = colorVec->writable().begin(); for ( int i = 0; i < availableColors; i++, it++ ) { *it = colors[i][3]; } data = colorVec; } } else { if ( rep == MFnMesh::kRGB || forceRgb ) { Color3fVectorDataPtr colorVec = new Color3fVectorData(); colorVec->writable().resize( numColors, Imath::Color3f(0,0,0) ); std::vector< Imath::Color3f >::iterator it = colorVec->writable().begin(); for ( int i = 0; i < availableColors; i++, it++ ) { const MColor &c = colors[i]; *it = Imath::Color3f( c[0], c[1], c[2] ); } data = colorVec; } else { Color4fVectorDataPtr colorVec = new Color4fVectorData(); colorVec->writable().resize( numColors, Imath::Color4f(0,0,0,1) ); std::vector< Imath::Color4f >::iterator it = colorVec->writable().begin(); for ( int i = 0; i < availableColors; i++, it++ ) { const MColor &c = colors[i]; *it = Imath::Color4f( c[0], c[1], c[2], c[3] ); } data = colorVec; } } return PrimitiveVariable( PrimitiveVariable::FaceVarying, data ); }