Katana Plug-in APIs 0.1

AbcCook.h

00001 #ifndef FnGeolibOp_AlembicIn_AbcCook_H
00002 #define FnGeolibOp_AlembicIn_AbcCook_H
00003 
00004 #include <Alembic/Abc/All.h>
00005 #include <Alembic/AbcGeom/All.h>
00006 
00007 #include <boost/shared_ptr.hpp>
00008 #include <boost/thread.hpp>
00009 
00010 #include <FnAttribute/FnAttribute.h>
00011 #include <FnAttribute/FnGroupBuilder.h>
00012 
00013 namespace AlembicIn
00014 {
00015 
00016 bool isBoundBox(const Alembic::AbcCoreAbstract::PropertyHeader & iPropHeader);
00017 
00018 Alembic::Util::PlainOldDataType FnAttrTypeToPODType(FnKatAttributeType iType);
00019 
00020 int64_t getTupleSize(const Alembic::AbcCoreAbstract::PropertyHeader & iHeader);
00021 
00022 class AbcCook;
00023 typedef boost::shared_ptr< AbcCook > AbcCookPtr;
00024 
00025 struct IndexedGeomParamPair
00026 {
00027     std::string name;
00028     Alembic::Abc::IArrayProperty prop;
00029     Alembic::Abc::IUInt32ArrayProperty indexed;
00030     Alembic::Util::PlainOldDataType asPod;
00031 };
00032 
00033 struct ArrayProp
00034 {
00035     std::string name;
00036     Alembic::Abc::IArrayProperty prop;
00037     Alembic::Util::PlainOldDataType asPod;
00038 };
00039 
00040 struct ScalarProp
00041 {
00042     std::string name;
00043     Alembic::Abc::IScalarProperty prop;
00044 };
00045 
00046 class AbcCook
00047 {
00048 public:
00049     AbcCook() { animatedSchema = false; }
00050 
00051     Foundry::Katana::GroupAttribute staticGroup;
00052 
00053     std::vector< ArrayProp > arrayProps;
00054     std::vector< ScalarProp > scalarProps;
00055     std::vector< IndexedGeomParamPair > forcedExpandProps;
00056 
00057     Alembic::AbcGeom::IVisibilityProperty visProp;
00058 
00059     Alembic::Abc::IObjectPtr objPtr;
00060     boost::mutex mutex;
00061 
00062     bool animatedSchema;
00063 };
00064 
00065 typedef std::vector<double> SampleTimes;
00066 
00067 struct OpArgs
00068 {
00069     double currentTime;
00070     double shutterOpen;
00071     double shutterClose;
00072     double fps;
00073     int numSamples;
00074 
00075     enum ExtraFrameRangeBehavior
00076     {
00077         kError = 0,
00078         kHold = 1,
00079         kSkip = 2
00080     };
00081 
00082     ExtraFrameRangeBehavior behavior;
00083     bool useOnlyShutterOpenCloseTimes;
00084 
00085     OpArgs()
00086     : currentTime(1.0)
00087     , shutterOpen(0.0)
00088     , shutterClose(0.0)
00089     , fps(24.0)
00090     , numSamples(1)
00091     , behavior(kHold)
00092     , useOnlyShutterOpenCloseTimes(false)
00093     {}
00094 
00095     double getAbcFrameTime() const { return currentTime / fps; }
00096 
00097     void getRelevantSampleTimes(
00098         Alembic::AbcCoreAbstract::TimeSamplingPtr iTimeSampling,
00099         size_t iPropertyNumSamples,
00100         SampleTimes & oTimes) const
00101     {
00102         double frameTime = currentTime / fps;
00103 
00104         if (numSamples < 2)
00105         {
00106             oTimes.push_back(frameTime);
00107             return;
00108         }
00109 
00110         if (iPropertyNumSamples < 2)
00111         {
00112             oTimes.push_back(0.0);
00113             return;
00114         }
00115 
00116         //TODO, what's a reasonable epsilon?
00117         static const double epsilon = 1.0/10000.0;
00118 
00119         double shutterOpenTime =
00120             (currentTime + shutterOpen) / fps;
00121         double shutterCloseTime =
00122             (currentTime + shutterClose) / fps;
00123 
00124         //
00125         // We don't want to grab samples from far outside the shutter window just
00126         // because the samples immediately near the shutter open and shutter
00127         // close times are a small epsilon outside the shutter we specify.  The
00128         // tolerance is already used for the upper bound below, but we'll use it
00129         // to grab a more expected lower and upper bound.
00130         //
00131 
00132         std::pair<Alembic::Abc::index_t, Alembic::Abc::chrono_t> shutterOpenFloor =
00133             iTimeSampling->getNearIndex(shutterOpenTime, iPropertyNumSamples);
00134         if (fabs(shutterOpenFloor.second - shutterOpenTime) > epsilon)
00135         {
00136             shutterOpenFloor =
00137                 iTimeSampling->getFloorIndex(shutterOpenTime, iPropertyNumSamples);
00138         }
00139 
00140         std::pair<Alembic::Abc::index_t, Alembic::Abc::chrono_t> shutterCloseCeil =
00141             iTimeSampling->getNearIndex(shutterCloseTime, iPropertyNumSamples);
00142         if (fabs(shutterCloseCeil.second - shutterCloseTime) > epsilon)
00143         {
00144             shutterCloseCeil =
00145                 iTimeSampling->getCeilIndex(shutterCloseTime, iPropertyNumSamples);
00146         }
00147 
00148         // Use shutter open/close times only if the number of samples is 2 and
00149         // we explicitly requested them to be used
00150         if (numSamples == 2 && useOnlyShutterOpenCloseTimes)
00151         {
00152             oTimes.push_back(shutterOpenFloor.second);
00153             if (fabs(shutterOpenFloor.second - shutterCloseCeil.second)
00154                                                                     > epsilon)
00155             {
00156                 oTimes.push_back(shutterCloseCeil.second);
00157             }
00158             return;
00159         }
00160 
00161         for (Alembic::Abc::index_t i = shutterOpenFloor.first;
00162              i < shutterCloseCeil.first; ++i)
00163         {
00164             oTimes.push_back(iTimeSampling->getSampleTime(i));
00165         }
00166 
00167         //no samples above? put frame time in there and get out
00168         if (oTimes.empty())
00169         {
00170             oTimes.push_back(frameTime);
00171             return;
00172         }
00173 
00174         double lastSample = *(oTimes.rbegin());
00175 
00176         //determine whether we need the extra sample at the end
00177         if ((fabs(lastSample-shutterCloseTime) > epsilon)
00178                 && lastSample<shutterCloseTime)
00179         {
00180             oTimes.push_back(shutterCloseCeil.second);
00181         }
00182     }
00183 
00184     float getRelativeSampleTime(Alembic::Abc::chrono_t iTime) const
00185     {
00186         double frameTime = currentTime / fps;
00187 
00188         double result = (iTime - frameTime) * fps;
00189 
00190         const double tolerance = 0.000165;
00191 
00192         if (Imath::equalWithAbsError(result, 0.0, tolerance))
00193         {
00194             result = 0;
00195         }
00196         else if (Imath::equalWithAbsError(result, shutterOpen, tolerance))
00197         {
00198             result = shutterOpen;
00199         }
00200         else if (Imath::equalWithAbsError(result, shutterClose, tolerance))
00201         {
00202             result = shutterClose;
00203         }
00204 
00205         return (float) result;
00206     }
00207 
00208 };
00209 
00210 void processUserProperties(AbcCookPtr ioCook,
00211     Alembic::Abc::ICompoundProperty & iParent,
00212     Foundry::Katana::GroupBuilder & oStaticGb,
00213     const std::string & iAttrPath);
00214 
00215 void initAbcCook(AbcCookPtr ioCookPtr,
00216                  Foundry::Katana::GroupBuilder & oStaticGb);
00217 
00218 void evalObject(AbcCookPtr ioCookPtr, const OpArgs & iArgs,
00219                 Foundry::Katana::GroupBuilder & oGb);
00220 
00221 void cookCamera(AbcCookPtr ioCook, Foundry::Katana::GroupBuilder & oStaticGb);
00222 
00223 void evalCamera(Alembic::AbcGeom::ICameraSchema & iSchema,
00224                 const OpArgs & iArgs,
00225                 Foundry::Katana::GroupBuilder & oGb);
00226 
00227 void cookCurves(AbcCookPtr ioCook, Foundry::Katana::GroupBuilder & oStaticGb);
00228 
00229 void evalCurves(Alembic::AbcGeom::ICurvesSchema & iSchema,
00230                 const OpArgs & iArgs,
00231                 Foundry::Katana::GroupBuilder & oGb);
00232 
00233 void cookFaceset(AbcCookPtr ioCook, Foundry::Katana::GroupBuilder & oStaticGb);
00234 
00235 void cookNuPatch(AbcCookPtr ioCook, Foundry::Katana::GroupBuilder & oStaticGb);
00236 void evalNuPatch(Alembic::AbcGeom::INuPatchSchema & iSchema,
00237                  const OpArgs & iArgs,
00238                  bool iIgnoreConstant,
00239                  Foundry::Katana::GroupBuilder & oGb);
00240 
00241 void cookPoints(AbcCookPtr ioCook, Foundry::Katana::GroupBuilder & oStaticGb);
00242 
00243 void cookPolyMesh(AbcCookPtr ioCook, Foundry::Katana::GroupBuilder & oStaticGb);
00244 
00245 void cookSubd(AbcCookPtr ioCook, Foundry::Katana::GroupBuilder & oStaticGb);
00246 
00247 void cookXform(AbcCookPtr ioCook, Foundry::Katana::GroupBuilder & oStaticGb);
00248 
00249 void evalXform(Alembic::AbcGeom::IXformSchema & iSchema,
00250                const OpArgs & iArgs,
00251                Foundry::Katana::GroupBuilder & oGb);
00252 
00253 }
00254 
00255 #endif
 All Classes Functions Variables Typedefs Enumerations Enumerator