|
Katana Plug-in APIs 0.1
|
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
1.7.3