#ifndef _CacheWriterAlembic_h_
#define _CacheWriterAlembic_h_
#include "CacheWriter.h"
#include <Alembic/Abc/OArchive.h>
#include <Alembic/Abc/OObject.h>
#include <Alembic/AbcGeom/OXform.h>
#include <Alembic/AbcGeom/OPolyMesh.h>
#include <Alembic/AbcGeom/Visibility.h>
#include <Alembic/AbcMaterial/OMaterial.h>
#include <Alembic/AbcMaterial/MaterialAssignment.h>
#include <memory>
class AlembicXformWriter;
class AlembicMeshWriter;
class AlembicCacheWriter : public CacheWriter
{
public:
static std::shared_ptr<CacheWriter> create(
~AlembicCacheWriter() override;
bool valid() const override;
void writeSubNodeHierarchy(
const GPUCache::SubNode::Ptr& topNode,
double secondsPerSample, double startTimeInSeconds) override;
void writeMaterials(
const GPUCache::MaterialGraphMap::Ptr& materialGraphMap,
double secondsPerSample, double startTimeInSeconds) override;
private:
GPUCACHE_DECLARE_MAKE_SHARED_FRIEND;
AlembicCacheWriter(
const MFileObject& file,
char compressLevel,
const MString& dataFormat);
char fCompressLevel;
Alembic::Abc::OArchive fAbcArchive;
Alembic::Abc::TimeSamplingPtr fAbcTimeSampling;
unsigned int fMaxNumSamples;
std::vector<MBoundingBox> fArchiveBounds;
};
class AlembicSubNodeWriter
{
public:
virtual ~AlembicSubNodeWriter(){}
virtual Alembic::Abc::OObject object() = 0;
};
class AlembicXformWriter: public AlembicSubNodeWriter
{
public:
AlembicXformWriter(
const Alembic::Abc::OObject& parent,
double secondsPerSample, double startTimeInSeconds);
Alembic::Abc::OObject object() override;
void write(const std::shared_ptr<const GPUCache::XformSample>& sample);
void write(const std::shared_ptr<const GPUCache::XformSample>& sample,
const std::shared_ptr<const GPUCache::XformSample>& prev);
private:
void fillXform(Alembic::AbcGeom::XformSample& xformSample,
const std::shared_ptr<const GPUCache::XformSample>& sample);
Alembic::Abc::TimeSamplingPtr fTimeSampPtr;
Alembic::AbcGeom::OXformSchema fAbcXform;
Alembic::AbcGeom::OVisibilityProperty fVisibility;
size_t fCachedWrite;
};
class AlembicMeshWriter: public AlembicSubNodeWriter
{
public:
AlembicMeshWriter(
const Alembic::Abc::OObject& parent,
double secondsPerSample, double startTimeInSeconds);
Alembic::Abc::OObject object() override;
void write(const std::shared_ptr<const GPUCache::ShapeSample>& sample);
void write(const std::shared_ptr<const GPUCache::ShapeSample>& sample,
const std::shared_ptr<const GPUCache::ShapeSample>& prev);
private:
void fillWireframeSample(Alembic::Abc::Int32ArraySample& wireIndicesSample,
const std::shared_ptr<const GPUCache::ShapeSample>& sample);
void fillTriangleSample(Alembic::AbcGeom::OPolyMeshSchema::Sample& meshSample,
Alembic::Abc::Int32ArraySample& groupSizesSample,
const std::shared_ptr<const GPUCache::ShapeSample>& sample);
void fillPositionSample(Alembic::AbcGeom::OPolyMeshSchema::Sample& meshSample,
const std::shared_ptr<const GPUCache::ShapeSample>& sample);
void fillNormalSample(Alembic::AbcGeom::OPolyMeshSchema::Sample& meshSample,
const std::shared_ptr<const GPUCache::ShapeSample>& sample,
bool forceWrite);
void fillUVSample(Alembic::AbcGeom::OPolyMeshSchema::Sample& meshSample,
const std::shared_ptr<const GPUCache::ShapeSample>& sample,
bool forceWrite);
void fillBoundingBoxSample(Alembic::AbcGeom::OPolyMeshSchema::Sample& meshSample,
const std::shared_ptr<const GPUCache::ShapeSample>& sample);
void fillDiffuseColorSample(Alembic::AbcGeom::C4f& diffuseColorSample,
const std::shared_ptr<const GPUCache::ShapeSample>& sample);
Alembic::Abc::TimeSamplingPtr fTimeSampPtr;
Alembic::AbcGeom::OPolyMeshSchema fAbcMesh;
Alembic::Abc::OStringProperty fAbcCreator;
Alembic::Abc::OStringProperty fAbcVersion;
Alembic::Abc::OInt32ArrayProperty fAbcWireIndices;
Alembic::Abc::OInt32ArrayProperty fAbcGroupSizes;
Alembic::Abc::OC4fProperty fAbcDiffuseColor;
std::vector<int> fGroupSizes;
std::vector<int> fPolygonCount;
std::vector<Alembic::Abc::int32_t> fFaceIndices;
std::vector<GPUCache::IndexBuffer::ReadableArrayPtr> fIndexReadInterfaces;
std::vector<GPUCache::VertexBuffer::ReadableArrayPtr> fVertexReadInterfaces;
Alembic::AbcGeom::OVisibilityProperty fVisibility;
size_t fCachedWrite;
};
class MaterialGraphWriter : boost::noncopyable
{
public:
MaterialGraphWriter(
Alembic::Abc::OObject parent,
double secondsPerSample,
double startTimeInSeconds,
const GPUCache::MaterialGraph::Ptr& graph);
void write();
private:
template<typename ABC_PROP>
void setMaterialProperty(
ABC_PROP& abcProp,
const GPUCache::MaterialProperty::Ptr& prop,
double timeInSeconds)
{}
template<typename ABC_PROP>
void writeMaterialProperty(Alembic::Abc::OCompoundProperty& parent,
const GPUCache::MaterialProperty::Ptr& prop)
{
ABC_PROP abcProp(
parent,
prop->name().asChar(),
fTimeSampPtr
);
if (prop->isAnimated()) {
double lastSampleTimeInSeconds =
(--prop->getSamples().end())->first + 0.5f * fSecondsPerSample;
for (double time = fStartTimeInSeconds;
time < lastSampleTimeInSeconds;
time += fSecondsPerSample) {
setMaterialProperty(abcProp, prop, time);
}
}
else {
setMaterialProperty(abcProp, prop, 0.0);
}
}
Alembic::AbcMaterial::OMaterialSchema fAbcMaterial;
Alembic::Abc::TimeSamplingPtr fTimeSampPtr;
const double fSecondsPerSample;
const double fStartTimeInSeconds;
const GPUCache::MaterialGraph::Ptr fGraph;
};
template<>
inline void MaterialGraphWriter::setMaterialProperty(
Alembic::Abc::OBoolProperty& abcProp,
const GPUCache::MaterialProperty::Ptr& prop,
double timeInSeconds)
{
abcProp.set(prop->asBool(timeInSeconds));
}
template<>
inline void MaterialGraphWriter::setMaterialProperty(
Alembic::Abc::OInt32Property& abcProp,
const GPUCache::MaterialProperty::Ptr& prop,
double timeInSeconds)
{
abcProp.set(prop->asInt32(timeInSeconds));
}
template<>
inline void MaterialGraphWriter::setMaterialProperty(
Alembic::Abc::OFloatProperty& abcProp,
const GPUCache::MaterialProperty::Ptr& prop,
double timeInSeconds)
{
abcProp.set(prop->asFloat(timeInSeconds));
}
template<>
inline void MaterialGraphWriter::setMaterialProperty(
Alembic::Abc::OV2fProperty& abcProp,
const GPUCache::MaterialProperty::Ptr& prop,
double timeInSeconds)
{
Alembic::Abc::V2f value;
prop->asFloat2(timeInSeconds, value.x, value.y);
abcProp.set(value);
}
template<>
inline void MaterialGraphWriter::setMaterialProperty(
Alembic::Abc::OV3fProperty& abcProp,
const GPUCache::MaterialProperty::Ptr& prop,
double timeInSeconds)
{
Alembic::Abc::V3f value;
prop->asFloat3(timeInSeconds, value.x, value.y, value.z);
abcProp.set(value);
}
template<>
inline void MaterialGraphWriter::setMaterialProperty(
Alembic::Abc::OC3fProperty& abcProp,
const GPUCache::MaterialProperty::Ptr& prop,
double timeInSeconds)
{
MColor value = prop->asColor(timeInSeconds);
abcProp.
set(Alembic::Abc::C3f(value.
r, value.
g, value.
b));
}
template<>
inline void MaterialGraphWriter::setMaterialProperty(
Alembic::Abc::OWstringProperty& abcProp,
const GPUCache::MaterialProperty::Ptr& prop,
double timeInSeconds)
{
MString value = prop->asString(timeInSeconds);
}
#endif