504 lines
17 KiB
C++
504 lines
17 KiB
C++
//-*****************************************************************************
|
|
//
|
|
// 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 <ri.h>
|
|
|
|
#include <Alembic/AbcGeom/All.h>
|
|
#include <boost/smart_ptr.hpp>
|
|
#include <set>
|
|
|
|
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 <typename T>
|
|
std::vector<RtFloat> * addAsFloat( const std::string & declaration, const T * length,
|
|
size_t numValues );
|
|
|
|
template <typename T>
|
|
std::vector<RtInt> * 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<RtToken> m_outputDeclarations;
|
|
std::vector<RtPointer> m_values;
|
|
std::vector<ArraySamplePtr> m_retainedSamples;
|
|
|
|
std::vector<RtString> m_retainedStrings;
|
|
|
|
typedef boost::shared_ptr<std::vector<RtString> > SharedRtStringVector;
|
|
std::vector<SharedRtStringVector> m_convertedStringVectors;
|
|
|
|
typedef boost::shared_ptr<std::vector<RtFloat> > SharedRtFloatVector;
|
|
std::vector<SharedRtFloatVector> m_convertedFloatVectors;
|
|
|
|
typedef boost::shared_ptr<std::vector<RtInt> > SharedRtIntVector;
|
|
std::vector<SharedRtIntVector> m_convertedIntVectors;
|
|
|
|
};
|
|
|
|
//-*****************************************************************************
|
|
|
|
template <typename T>
|
|
std::vector<RtFloat> * ParamListBuilder::addAsFloat( const std::string & declaration,
|
|
const T * value, size_t length)
|
|
{
|
|
SharedRtFloatVector convertedValues( new std::vector<RtFloat> );
|
|
convertedValues->reserve( length );
|
|
|
|
convertedValues->insert( convertedValues->end(), value, value + length );
|
|
m_convertedFloatVectors.push_back( convertedValues );
|
|
|
|
add( declaration, &( ( *convertedValues )[0] ) );
|
|
|
|
return &(*convertedValues);
|
|
}
|
|
|
|
//-*****************************************************************************
|
|
|
|
template <typename T>
|
|
std::vector<RtInt> * ParamListBuilder::addAsInt( const std::string & declaration,
|
|
const T * value, size_t length)
|
|
{
|
|
SharedRtIntVector convertedValues( new std::vector<RtInt> );
|
|
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 <typename T>
|
|
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 <typename T, typename podT>
|
|
std::vector<RtFloat> * 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<const podT *>( 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 <typename T, typename podT>
|
|
std::vector<RtInt> * 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<const podT *>( valueSample->get() ),
|
|
valueSample->size() * arrayExtent );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-*****************************************************************************
|
|
|
|
void AddArbitraryGeomParams( ICompoundProperty &parent,
|
|
ISampleSelector &sampleSelector,
|
|
ParamListBuilder &ParamListBuilder,
|
|
const std::set<std::string> * excludeNames = NULL
|
|
);
|
|
|
|
|
|
//-*****************************************************************************
|
|
|
|
|
|
//[array, scalar], [as float, as int, as string];
|
|
|
|
|
|
template <typename propT, typename podT>
|
|
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<podT>(
|
|
buffer.str(), reinterpret_cast<const podT *>( sample->get() ),
|
|
sample->size() * dataTypeExtent);
|
|
}
|
|
|
|
|
|
template <typename propT, typename podT>
|
|
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<podT>(
|
|
buffer.str(), reinterpret_cast<const podT *>(&scalarValue),
|
|
dataTypeExtent);
|
|
}
|
|
|
|
|
|
// template <typename propT, typename podT>
|
|
// void AddArrayPropertyAsIntToParamListBuilder(
|
|
// ICompoundProperty & parent,
|
|
// const PropertyHeader &propHeader,
|
|
// ISampleSelector &sampleSelector,
|
|
// const std::string & name,
|
|
// ParamListBuilder &ParamListBuilder);
|
|
|
|
template <typename propT, typename podT>
|
|
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<podT>(
|
|
buffer.str(), reinterpret_cast<const podT *>(&scalarValue),
|
|
dataTypeExtent);
|
|
}
|
|
|
|
template <typename propT>
|
|
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 <typename propT>
|
|
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<std::string*>(&scalarValue)[i], true);
|
|
}
|
|
|
|
paramListBuilder.add(buffer.str(),
|
|
paramListBuilder.finishStringVector());
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|