diff --git a/plugins/alembic/module/Testing/CMakeLists.txt b/plugins/alembic/module/Testing/CMakeLists.txt index 61e6e9784a..92adb36c7c 100644 --- a/plugins/alembic/module/Testing/CMakeLists.txt +++ b/plugins/alembic/module/Testing/CMakeLists.txt @@ -1,5 +1,6 @@ list(APPEND VTKExtensionsPluginAlembic_list TestF3DAlembicReader.cxx + TestF3DAlembicReaderRequestInformation.cxx ) if(VTK_VERSION VERSION_GREATER_EQUAL 9.5.20251210) diff --git a/plugins/alembic/module/Testing/TestF3DAlembicReaderRequestInformation.cxx b/plugins/alembic/module/Testing/TestF3DAlembicReaderRequestInformation.cxx new file mode 100644 index 0000000000..10252a7411 --- /dev/null +++ b/plugins/alembic/module/Testing/TestF3DAlembicReaderRequestInformation.cxx @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include + +#include "vtkF3DAlembicReader.h" + +#include + +int TestF3DAlembicReaderRequestInformation(int vtkNotUsed(argc), char* argv[]) +{ + static int NUMBER_OF_TIME_STEPS = 90; + static const double expectedTimeSteps[] = { 0.000000, 0.033333, 0.066667, 0.100000, 0.133333, + 0.166667, 0.200000, 0.233333, 0.266667, 0.300000, 0.333333, 0.366667, 0.400000, 0.433333, + 0.466667, 0.500000, 0.533333, 0.566667, 0.600000, 0.633333, 0.666667, 0.700000, 0.733333, + 0.766667, 0.800000, 0.833333, 0.866667, 0.900000, 0.933333, 0.966667, 1.000000, 1.033333, + 1.066667, 1.100000, 1.133333, 1.166667, 1.200000, 1.233333, 1.266667, 1.300000, 1.333333, + 1.366667, 1.400000, 1.433333, 1.466667, 1.500000, 1.533333, 1.566667, 1.600000, 1.633333, + 1.666667, 1.700000, 1.733333, 1.766667, 1.800000, 1.833333, 1.866667, 1.900000, 1.933333, + 1.966667, 2.000000, 2.033333, 2.066667, 2.100000, 2.133333, 2.166667, 2.200000, 2.233333, + 2.266667, 2.300000, 2.333333, 2.366667, 2.400000, 2.433333, 2.466667, 2.500000, 2.533333, + 2.566667, 2.600000, 2.633333, 2.666667, 2.700000, 2.733333, 2.766667, 2.800000, 2.833333, + 2.866667, 2.900000, 2.933333, 2.966667 }; + static const double expectedTimeRange[] = { 0.000000, 2.966667 }; + + std::string filename = std::string(argv[1]) + "data/drop.abc"; + vtkNew reader; + reader->SetFileName(filename); + reader->UpdateInformation(); + vtkInformation* readerInfo = reader->GetOutputInformation(0); + double* readerTimeSteps = nullptr; + if (readerInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS())) + { + readerTimeSteps = readerInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); + } + else + { + return EXIT_FAILURE; + } + double* readerTimeRange = nullptr; + if (readerInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_RANGE())) + { + readerTimeRange = readerInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_RANGE()); + } + else + { + return EXIT_FAILURE; + } + + for (int i = 0; i < 2; i++) + { + if (fabs(readerTimeRange[i] - expectedTimeRange[i]) > 1e-6) + { + return EXIT_FAILURE; + } + } + + for (int i = 0; i < NUMBER_OF_TIME_STEPS; i++) + { + if (fabs(readerTimeSteps[i] - expectedTimeSteps[i]) > 1e-6) + { + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} diff --git a/plugins/alembic/module/vtkF3DAlembicReader.cxx b/plugins/alembic/module/vtkF3DAlembicReader.cxx index 17cfa48ca0..fad4548174 100644 --- a/plugins/alembic/module/vtkF3DAlembicReader.cxx +++ b/plugins/alembic/module/vtkF3DAlembicReader.cxx @@ -604,10 +604,12 @@ class vtkF3DAlembicReader::vtkInternals } } - void ExtendTimeRange(double& start, double& end) + void ComputeTimeRangeAndSteps(double& start, double& end, std::vector& timeSteps) { Alembic::Abc::IObject top = this->Archive.getTop(); + // Using std::set since we need time steps to be unique and ordered + std::set timeStepSet; std::stack> objects; for (size_t i = 0; i < top.getNumChildren(); ++i) @@ -619,28 +621,24 @@ class vtkF3DAlembicReader::vtkInternals { const auto& [parent, ohead] = objects.top(); const Alembic::AbcGeom::IObject obj(parent, ohead.getName()); - int numSamples = 0; Alembic::Abc::TimeSamplingPtr ts; if (Alembic::AbcGeom::IXform::matches(ohead)) { const Alembic::AbcGeom::IXform xForm(parent, ohead.getName()); const Alembic::AbcGeom::IXformSchema& schema = xForm.getSchema(); ts = schema.getTimeSampling(); - numSamples = static_cast(schema.getNumSamples()); } else if (Alembic::AbcGeom::IPolyMesh::matches(ohead)) { const Alembic::AbcGeom::IPolyMesh polymesh(parent, ohead.getName()); const Alembic::AbcGeom::IPolyMeshSchema& schema = polymesh.getSchema(); ts = schema.getTimeSampling(); - numSamples = static_cast(schema.getNumSamples()); } else if (Alembic::AbcGeom::ICurves::matches(ohead)) { const Alembic::AbcGeom::ICurves curves(parent, ohead.getName()); const Alembic::AbcGeom::ICurvesSchema& schema = curves.getSchema(); ts = schema.getTimeSampling(); - numSamples = static_cast(schema.getNumSamples()); } objects.pop(); @@ -654,20 +652,19 @@ class vtkF3DAlembicReader::vtkInternals continue; } - if (ts->getTimeSamplingType().isUniform()) + // Collecting all time steps + const auto& times = ts->getStoredTimes(); + for (auto& timeStep : times) { - double min = ts->getSampleTime(0); - double max = min + (numSamples - 1) * ts->getTimeSamplingType().getTimePerCycle(); - start = std::min(start, min); - end = std::max(end, max); - } - else if (ts->getTimeSamplingType().isCyclic()) - { - const auto& times = ts->getStoredTimes(); - start = std::min(start, times.front()); - end = std::max(end, times.back()); + timeStepSet.insert(timeStep); } } + if (timeStepSet.size() > 0) + { + start = *timeStepSet.begin(); + end = *timeStepSet.rbegin(); + timeSteps = std::vector(timeStepSet.begin(), timeStepSet.end()); + } } bool ReadArchive( @@ -738,13 +735,19 @@ int vtkF3DAlembicReader::RequestInformation(vtkInformation* vtkNotUsed(request), double timeRange[2] = { std::numeric_limits::infinity(), -std::numeric_limits::infinity() }; - this->Internals->ExtendTimeRange(timeRange[0], timeRange[1]); + std::vector timeSteps{ 0 }; + this->Internals->ComputeTimeRangeAndSteps(timeRange[0], timeRange[1], timeSteps); vtkInformation* outInfo = outputVector->GetInformationObject(0); if (timeRange[0] < timeRange[1]) { outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_RANGE(), timeRange, 2); } + if (timeSteps.size() > 0) + { + outInfo->Set( + vtkStreamingDemandDrivenPipeline::TIME_STEPS(), timeSteps.data(), timeSteps.size()); + } return 1; }