//-***************************************************************************** // // Copyright (c) 2009-2012, // Sony Pictures Imageworks Inc. and // Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd. // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Sony Pictures Imageworks, nor // Industrial Light & Magic, nor the names of their contributors may be used // to endorse or promote products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //-***************************************************************************** #ifndef Alembic_Prman_ArbAttrUtil_h #define Alembic_Prman_ArbAttrUtil_h #include #include #include #include using namespace Alembic::AbcGeom; //-***************************************************************************** class ParamListBuilder { public: ~ParamListBuilder(); void add( const std::string & declaration, RtPointer value, ArraySamplePtr sampleToRetain = ArraySamplePtr() ); // used for conversion of DoubleGeomParams // NOTE: In addition to performing the conversion, this also makes and // returns an internal copy of the data. Even in cases in which you're // starting with float data, this can be usful if you need to manipulate // the values after-the-fact. template std::vector * addAsFloat( const std::string & declaration, const T * length, size_t numValues ); template std::vector * addAsInt( const std::string & declaration, const T * length, size_t numValues ); //returns the start of the current vector and pushes a new one RtPointer finishStringVector(); //If retainLocally is false, it's expected that "value" remain alive //The common case is out of a StringArraySamplePtr which is provided //as sampleToRetain in the add method void addStringValue( const std::string & value, bool retainLocally = false ); RtInt n(); RtToken* nms(); RtPointer* vals(); private: std::vector m_outputDeclarations; std::vector m_values; std::vector m_retainedSamples; std::vector m_retainedStrings; typedef boost::shared_ptr > SharedRtStringVector; std::vector m_convertedStringVectors; typedef boost::shared_ptr > SharedRtFloatVector; std::vector m_convertedFloatVectors; typedef boost::shared_ptr > SharedRtIntVector; std::vector m_convertedIntVectors; }; //-***************************************************************************** template std::vector * ParamListBuilder::addAsFloat( const std::string & declaration, const T * value, size_t length) { SharedRtFloatVector convertedValues( new std::vector ); convertedValues->reserve( length ); convertedValues->insert( convertedValues->end(), value, value + length ); m_convertedFloatVectors.push_back( convertedValues ); add( declaration, &( ( *convertedValues )[0] ) ); return &(*convertedValues); } //-***************************************************************************** template std::vector * ParamListBuilder::addAsInt( const std::string & declaration, const T * value, size_t length) { SharedRtIntVector convertedValues( new std::vector ); convertedValues->reserve( length ); convertedValues->insert( convertedValues->end(), value, value + length ); m_convertedIntVectors.push_back( convertedValues ); add( declaration, &( ( *convertedValues )[0] ) ); return &(*convertedValues); } //-***************************************************************************** std::string GetPrmanScopeString( GeometryScope scope ); //-***************************************************************************** template void AddGeomParamToParamListBuilder( ICompoundProperty & parent, const PropertyHeader &propHeader, ISampleSelector &sampleSelector, const std::string &rmanBaseType, ParamListBuilder &ParamListBuilder, size_t baseArrayExtent = 1, const std::string & overrideName = "" ) { T param( parent, propHeader.getName() ); if ( !param.valid() ) { //TODO error message? return; } std::string rmanType = GetPrmanScopeString( param.getScope() ) + " "; rmanType += rmanBaseType; size_t arrayExtent = baseArrayExtent * param.getArrayExtent(); if (arrayExtent > 1) { std::ostringstream buffer; buffer << "[" << arrayExtent << "]"; rmanType += buffer.str(); } rmanType += " " + ( overrideName.empty() ? propHeader.getName() : overrideName ); typename T::prop_type::sample_ptr_type valueSample = param.getExpandedValue( sampleSelector ).getVals(); ParamListBuilder.add( rmanType, (RtPointer)valueSample->get(), valueSample ); } //-***************************************************************************** // NOTE: In addition to performing the conversion, this also makes and // returns an internal copy of the data. Even in cases in which you're // starting with float data, this can be usful if you need to manipulate // the values after-the-fact. The AddGeomParamToParamListBuilder codepath // normally avoids a copy of the data as the GeomParam samples can be handed // to RenderMan directly. template std::vector * AddGeomParamToParamListBuilderAsFloat( ICompoundProperty & parent, const PropertyHeader &propHeader, ISampleSelector &sampleSelector, const std::string &rmanBaseType, ParamListBuilder &ParamListBuilder, const std::string & overrideName = "" ) { T param( parent, propHeader.getName() ); if ( !param.valid() ) { //TODO error message? return 0; } std::string rmanType = GetPrmanScopeString( param.getScope() ) + " "; rmanType += rmanBaseType; size_t dataTypeExtent = T::prop_type::traits_type::dataType().getExtent(); // If rmanBaseType is something other than float, the assumption is that the // specified rman type is in agreement with the dataTypeExtent -- i.e. color = 3 // If it's just float, we want to make sure that our data footprint matches // that of the incoming type in RenderMan terms. size_t baseArrayExtent = (rmanBaseType == "float") ? dataTypeExtent: 1; size_t arrayExtent = baseArrayExtent * param.getArrayExtent(); if (arrayExtent > 1) { std::ostringstream buffer; buffer << "[" << arrayExtent << "]"; rmanType += buffer.str(); } rmanType += " " + ( overrideName.empty() ? propHeader.getName() : overrideName ); typename T::prop_type::sample_ptr_type valueSample = param.getExpandedValue( sampleSelector ).getVals(); //always grab the natural extent of the incoming data for the internal copy int rawExtent = dataTypeExtent * param.getArrayExtent(); return ParamListBuilder.addAsFloat( rmanType, reinterpret_cast( valueSample->get() ), valueSample->size() * rawExtent ); } //-***************************************************************************** // NOTE: In addition to performing the conversion, this also makes and // returns an internal copy of the data. Even in cases in which you're // starting with int data, this can be usful if you need to manipulate // the values after-the-fact. The AddGeomParamToParamListBuilder codepath // normally avoids a copy of the data as the GeomParam samples can be handed // to RenderMan directly. template std::vector * AddGeomParamToParamListBuilderAsInt( ICompoundProperty & parent, const PropertyHeader &propHeader, ISampleSelector &sampleSelector, ParamListBuilder &ParamListBuilder, const std::string & overrideName = "" ) { T param( parent, propHeader.getName() ); if ( !param.valid() ) { //TODO error message? return 0; } //Unlike RtFloat, "int" is the only RenderMan type that takes something //compatible with RtInt. We can assume anything sent here is intended to be //written to RenderMan as int[n]. const std::string rmanBaseType("int"); std::string rmanType = GetPrmanScopeString( param.getScope() ) + " "; rmanType += rmanBaseType; size_t dataTypeExtent = T::prop_type::traits_type::dataType().getExtent(); size_t arrayExtent = dataTypeExtent * param.getArrayExtent(); if (arrayExtent > 1) { std::ostringstream buffer; buffer << "[" << arrayExtent << "]"; rmanType += buffer.str(); } rmanType += " " + ( overrideName.empty() ? propHeader.getName() : overrideName ); typename T::prop_type::sample_ptr_type valueSample = param.getExpandedValue( sampleSelector ).getVals(); return ParamListBuilder.addAsInt( rmanType, reinterpret_cast( valueSample->get() ), valueSample->size() * arrayExtent ); } //-***************************************************************************** void AddArbitraryGeomParams( ICompoundProperty &parent, ISampleSelector &sampleSelector, ParamListBuilder &ParamListBuilder, const std::set * excludeNames = NULL ); //-***************************************************************************** //[array, scalar], [as float, as int, as string]; template void AddArrayPropertyAsFloatToParamListBuilder( ICompoundProperty & parent, const PropertyHeader &propHeader, ISampleSelector &sampleSelector, const std::string & name, const std::string & rmanBaseType, ParamListBuilder & paramListBuilder) { propT prop(parent, propHeader.getName()); size_t dataTypeExtent = propT::traits_type::dataType().getExtent(); typename propT::sample_ptr_type sample = prop.getValue(sampleSelector); std::ostringstream buffer; buffer << rmanBaseType; size_t baseArrayExtent = (rmanBaseType == "float") ? dataTypeExtent: 1; size_t arrayExtent = baseArrayExtent * sample->size(); if (arrayExtent > 1) { buffer << "[" << arrayExtent << "]"; } buffer << " " << name; paramListBuilder.addAsFloat( buffer.str(), reinterpret_cast( sample->get() ), sample->size() * dataTypeExtent); } template void AddScalarPropertyAsFloatToParamListBuilder( ICompoundProperty & parent, const PropertyHeader &propHeader, ISampleSelector &sampleSelector, const std::string & name, const std::string & rmanBaseType, ParamListBuilder ¶mListBuilder) { propT prop(parent, propHeader.getName()); typename propT::value_type scalarValue; prop.get(scalarValue, sampleSelector); std::ostringstream buffer; buffer << rmanBaseType; size_t dataTypeExtent = propT::traits_type::dataType().getExtent(); if (rmanBaseType == "float" && dataTypeExtent > 1) { buffer << "[" << dataTypeExtent << "] "; } buffer << " " << name; paramListBuilder.addAsFloat( buffer.str(), reinterpret_cast(&scalarValue), dataTypeExtent); } // template // void AddArrayPropertyAsIntToParamListBuilder( // ICompoundProperty & parent, // const PropertyHeader &propHeader, // ISampleSelector &sampleSelector, // const std::string & name, // ParamListBuilder &ParamListBuilder); template void AddScalarPropertyAsIntToParamListBuilder( ICompoundProperty & parent, const PropertyHeader &propHeader, ISampleSelector &sampleSelector, const std::string & name, ParamListBuilder ¶mListBuilder) { propT prop(parent, propHeader.getName()); typename propT::value_type scalarValue; prop.get(scalarValue, sampleSelector); std::ostringstream buffer; buffer << "int"; size_t dataTypeExtent = propT::traits_type::dataType().getExtent(); if (dataTypeExtent > 1) { buffer << "[" << dataTypeExtent << "]"; } buffer << " " << name; paramListBuilder.addAsInt( buffer.str(), reinterpret_cast(&scalarValue), dataTypeExtent); } template void AddArrayPropertyAsStringToParamListBuilder( ICompoundProperty & parent, const PropertyHeader &propHeader, ISampleSelector &sampleSelector, const std::string & name, ParamListBuilder ¶mListBuilder) { propT prop(parent, propHeader.getName()); StringArraySamplePtr valueSample = prop.getValue(sampleSelector); std::ostringstream buffer; buffer << "string"; if (valueSample->size() > 1) { buffer << "[" << valueSample->size() << "]"; } buffer << " " << name; for ( size_t i = 0; i < valueSample->size(); ++i ) { paramListBuilder.addStringValue( (*valueSample)[i] ); } RtPointer dataStart = paramListBuilder.finishStringVector(); paramListBuilder.add(buffer.str(), dataStart, valueSample); } template void AddScalarPropertyAsStringToParamListBuilder( ICompoundProperty & parent, const PropertyHeader &propHeader, ISampleSelector &sampleSelector, const std::string & name, ParamListBuilder ¶mListBuilder) { propT prop(parent, propHeader.getName()); typename propT::value_type scalarValue; prop.get(scalarValue, sampleSelector); std::ostringstream buffer; buffer << "string"; size_t dataTypeExtent = propT::traits_type::dataType().getExtent(); if (dataTypeExtent > 1) { buffer << "[" << dataTypeExtent << "]"; } buffer << " " << name; for (size_t i = 0; i < dataTypeExtent; ++i) { paramListBuilder.addStringValue( reinterpret_cast(&scalarValue)[i], true); } paramListBuilder.add(buffer.str(), paramListBuilder.finishStringVector()); } #endif