Skip to content

Commit 0d067cd

Browse files
committed
Fix particle count sampling rate not set resulting in division by zero exception
1 parent 6b7735a commit 0d067cd

File tree

6 files changed

+180
-31
lines changed

6 files changed

+180
-31
lines changed

lib/XMLReader.cpp

+21-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include <errno.h>
1313

1414
#include <boost/format.hpp>
15-
// #include <boost/filesystem.hpp>
15+
#include <boost/filesystem.hpp>
1616
#include <boost/algorithm/string.hpp>
1717
#include <boost/property_tree/ptree.hpp>
1818
#include <boost/property_tree/xml_parser.hpp>
@@ -37,8 +37,17 @@ XMLReader::~XMLReader()
3737
void XMLReader::read(const std::string& i_ncache_xml_filename)
3838
{
3939
try {
40+
std::cout << boost::format("i_ncache_xml_filename '%1%'") % i_ncache_xml_filename << std::endl;
4041
boost::property_tree::ptree pt;
4142

43+
// This is Autodesk convention
44+
boost::filesystem::path p(i_ncache_xml_filename);
45+
boost::filesystem::directory_entry d(p);
46+
47+
_base_cache_name = p.stem().c_str();
48+
_cache_directory = p.parent_path().c_str();
49+
std::cout << boost::format("_base_cache_name '%1%', _cache_directory '%2%'") % _base_cache_name % _cache_directory << std::endl;
50+
4251
// Load XML file and put its contents in property tree.
4352
// No namespace qualification is needed, because of Koenig
4453
// lookup on the second argument. If reading fails, exception
@@ -56,6 +65,12 @@ void XMLReader::read(const std::string& i_ncache_xml_filename)
5665
_cache_type = pt.get<std::string>("Autodesk_Cache_File.cacheType.<xmlattr>.Type");
5766
_cache_format = pt.get<std::string>("Autodesk_Cache_File.cacheType.<xmlattr>.Format");
5867
}
68+
else if (v.first.compare("time")==0)
69+
{
70+
std::string time_range = pt.get<std::string>("Autodesk_Cache_File.time.<xmlattr>.Range");
71+
std::cout << boost::format("time_range = '%1%'") % time_range << std::endl;
72+
sscanf(time_range.c_str(),"%d-%d",&_time_range_start,&_time_range_end);
73+
}
5974
else if (v.first.compare("cacheTimePerFrame")==0)
6075
{
6176
_cacheTimePerFrame_TimePerFrame = atoi(pt.get<std::string>("Autodesk_Cache_File.cacheTimePerFrame.<xmlattr>.TimePerFrame").c_str());
@@ -70,10 +85,9 @@ void XMLReader::read(const std::string& i_ncache_xml_filename)
7085
// Now, focus on just the channel information
7186
BOOST_FOREACH(boost::property_tree::ptree::value_type &c, pt.get_child("Autodesk_Cache_File.Channels"))
7287
{
73-
std::cout << boost::format("Channels %1% : %2%") % c.first % c.second.data() << std::endl;
74-
7588
ChannelInfo channel_info;
7689
std::string channel_name = pt.get<std::string>((boost::format("Autodesk_Cache_File.Channels.%1%.<xmlattr>.ChannelName")%c.first).str());
90+
std::cout << boost::format("Channels %1% : %2%") % c.first % channel_name << std::endl;
7791
channel_info._channel_type = pt.get<std::string>((boost::format("Autodesk_Cache_File.Channels.%1%.<xmlattr>.ChannelType")%c.first).str());
7892
channel_info._channel_interpretation = pt.get<std::string>((boost::format("Autodesk_Cache_File.Channels.%1%.<xmlattr>.ChannelInterpretation")%c.first).str());
7993
std::string sampling_type_string = pt.get<std::string>((boost::format("Autodesk_Cache_File.Channels.%1%.<xmlattr>.SamplingType")%c.first).str());
@@ -86,6 +100,10 @@ void XMLReader::read(const std::string& i_ncache_xml_filename)
86100
channel_info._start_time = atoi(pt.get<std::string>((boost::format("Autodesk_Cache_File.Channels.%1%.<xmlattr>.StartTime")%c.first).str()).c_str());
87101
channel_info._end_time = atoi(pt.get<std::string>((boost::format("Autodesk_Cache_File.Channels.%1%.<xmlattr>.EndTime")%c.first).str()).c_str());
88102

103+
if (channel_info._channel_interpretation.compare("count")==0)
104+
{
105+
_particle_count_sampling_rate = channel_info._sampling_rate;
106+
}
89107
_channels.insert(ChannelInfoContainer::value_type(channel_name,channel_info));
90108
}
91109
}

lib/XMLReader.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ namespace nCache
2626
XMLReader();
2727
~XMLReader();
2828
void read(const std::string& i_ncache_xml_filename);
29-
std::string getCacheType() const { return _cache_type; }
30-
std::string getCacheFormat() const { return _cache_format; }
31-
const ChannelInfoContainer& getChannels() const {return _channels; }
32-
std::string get_cache_name() const { return _base_cache_name;};
29+
std::string get_cache_type() const { return _cache_type; }
30+
std::string get_cache_format() const { return _cache_format; }
31+
const ChannelInfoContainer& get_channels() const {return _channels; }
32+
std::string get_base_cache_name() const { return _base_cache_name;};
3333
std::string get_cache_directory() const { return _cache_directory;};
3434
// size_t get_num_frames() const { return _num_frames;};
3535

lib/nCacheAlembic.cpp

+123-8
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ bool nCacheAlembic::process(const std::string& i_alembic_filename,
2525
Alembic::Abc::OArchive archive(Alembic::Abc::CreateArchiveWithInfo(Alembic::AbcCoreHDF5::WriteArchive(),
2626
std::string(i_alembic_filename.c_str()),
2727
std::string("Procedural Insight Pty. Ltd."),
28-
std::string("Multiple Samples Random points"),
28+
std::string("nCache2Alembic points"),
2929
Alembic::Abc::ErrorHandler::kThrowPolicy));
3030

3131
Alembic::AbcGeom::OObject iParent( archive, Alembic::AbcGeom::kTop );
@@ -44,7 +44,7 @@ bool nCacheAlembic::process(const std::string& i_alembic_filename,
4444
std::cout << boost::format("FPS (calculated) = %1%") % fps << std::endl;
4545
std::cout << boost::format("ncache_sampling_rate = %1%") % ncache_sampling_rate << std::endl;
4646

47-
Alembic::Util::uint32_t num_time_samples = (i_ncache_loader.get_xml_reader().get_time_range_end() - i_ncache_loader.get_xml_reader().get_time_range_start())/i_ncache_loader.get_xml_reader().get_particle_count_sampling_rate() + 1;
47+
Alembic::Util::uint32_t num_time_samples = ((ncache_end - ncache_start)/ncache_sampling_rate) + 1;
4848
std::cout << boost::format("num_time_samples = %1%") % num_time_samples << std::endl;
4949
// Create the time sampling type.
5050
Alembic::AbcCoreAbstract::TimeSampling ts(ncache_sampling_rate/6000.0, ncache_start/(ncache_ticks_per_frame*fps));
@@ -83,7 +83,7 @@ bool nCacheAlembic::process(const std::string& i_alembic_filename,
8383

8484

8585
// Now process the individual *.mc/*.mcx files
86-
bool is_mcx = xml_reader.getCacheFormat().compare("mcx") == 0;
86+
bool is_mcx = xml_reader.get_cache_format().compare("mcx") == 0;
8787
std::string cache_extension("mc");
8888
if (is_mcx)
8989
cache_extension = "mcx";
@@ -92,7 +92,7 @@ bool nCacheAlembic::process(const std::string& i_alembic_filename,
9292
CacheReaderSharedPointerType cache_reader_ptr;
9393
for (size_t frame_index = start_frame; frame_index <= end_frame; frame_index++)
9494
{
95-
std::string per_initial_frame_full_path = (boost::format("%1%/%2%Frame%3%.%4%") % xml_reader.get_cache_directory() % xml_reader.get_cache_name() % frame_index % cache_extension).str();
95+
std::string per_initial_frame_full_path = (boost::format("%1%/%2%Frame%3%.%4%") % xml_reader.get_cache_directory() % xml_reader.get_base_cache_name() % frame_index % cache_extension).str();
9696
// std::cout << boost::format("per_initial_frame_full_path = '%1%'") % per_initial_frame_full_path << std::endl;
9797

9898
if (is_mcx)
@@ -113,7 +113,121 @@ bool nCacheAlembic::process(const std::string& i_alembic_filename,
113113
size_t accumulated_ticks = ncache_sampling_rate;
114114
while ((accumulated_ticks < ncache_ticks_per_frame) && ((ncache_ticks_per_frame-accumulated_ticks)>=ncache_sampling_rate) )
115115
{
116-
std::string per_sub_frame_full_path = (boost::format("%1%/%2%Frame%3%Tick%4%.%5%") % xml_reader.get_cache_directory() % xml_reader.get_cache_name() % frame_index % accumulated_ticks % cache_extension).str();
116+
std::string per_sub_frame_full_path = (boost::format("%1%/%2%Frame%3%Tick%4%.%5%") % xml_reader.get_cache_directory() % xml_reader.get_base_cache_name() % frame_index % accumulated_ticks % cache_extension).str();
117+
// std::cout << boost::format("\t""per_sub_frame_full_path '%1%'") % per_sub_frame_full_path << std::endl;
118+
119+
if (is_mcx)
120+
cache_reader_ptr.reset(new MCXMemoryReader(per_sub_frame_full_path));
121+
else
122+
cache_reader_ptr.reset(new MCMemoryReader(per_sub_frame_full_path));
123+
124+
if (cache_reader_ptr)
125+
{
126+
process_single_sample(cache_reader_ptr,
127+
position_channel_name,
128+
id_channel_name,
129+
pSchema);
130+
}
131+
accumulated_ticks += ncache_sampling_rate;
132+
}
133+
}
134+
}
135+
return true;
136+
}
137+
138+
bool nCacheAlembic::process_per_frame(const std::string& i_alembic_format_filename,
139+
const nCacheLoader& i_ncache_loader)
140+
{
141+
const nCache::XMLReader& xml_reader = i_ncache_loader.get_xml_reader();
142+
size_t ncache_start = xml_reader.get_time_range_start();
143+
size_t ncache_end = xml_reader.get_time_range_end();
144+
size_t ncache_ticks_per_frame = xml_reader.get_cacheTimePerFrame_TimePerFrame();
145+
146+
// Now process the individual *.mc/*.mcx files
147+
bool is_mcx = xml_reader.get_cache_format().compare("mcx") == 0;
148+
std::string cache_extension("mc");
149+
if (is_mcx)
150+
cache_extension = "mcx";
151+
size_t start_frame = ncache_start / ncache_ticks_per_frame;
152+
size_t end_frame = ncache_end / ncache_ticks_per_frame;
153+
CacheReaderSharedPointerType cache_reader_ptr;
154+
for (size_t frame_index = start_frame; frame_index <= end_frame; frame_index++)
155+
{
156+
std::string alembic_filename = (boost::format(i_alembic_format_filename) % frame_index).str();
157+
158+
// Alembic file setup - START
159+
Alembic::Abc::OArchive archive(Alembic::Abc::CreateArchiveWithInfo(Alembic::AbcCoreHDF5::WriteArchive(),
160+
std::string(alembic_filename.c_str()),
161+
std::string("Procedural Insight Pty. Ltd."),
162+
std::string("nCache2Alembic points"),
163+
Alembic::Abc::ErrorHandler::kThrowPolicy));
164+
165+
Alembic::AbcGeom::OObject iParent( archive, Alembic::AbcGeom::kTop );
166+
Alembic::AbcGeom::OXform xform = addXform(iParent,"Xform");
167+
168+
size_t ncache_sampling_rate = xml_reader.get_particle_count_sampling_rate();
169+
double fps = 6000.0/ncache_ticks_per_frame;
170+
171+
std::cout << boost::format("ncache_start = %1%") % ncache_start << std::endl;
172+
std::cout << boost::format("ncache_end = %1%") % ncache_end << std::endl;
173+
std::cout << boost::format("ncache_ticks_per_frame = %1%") % ncache_ticks_per_frame << std::endl;
174+
std::cout << boost::format("FPS (calculated) = %1%") % fps << std::endl;
175+
std::cout << boost::format("ncache_sampling_rate = %1%") % ncache_sampling_rate << std::endl;
176+
177+
Alembic::Util::uint32_t num_time_samples = (i_ncache_loader.get_xml_reader().get_time_range_end() - i_ncache_loader.get_xml_reader().get_time_range_start())/i_ncache_loader.get_xml_reader().get_particle_count_sampling_rate() + 1;
178+
std::cout << boost::format("num_time_samples = %1%") % num_time_samples << std::endl;
179+
// Create the time sampling type.
180+
Alembic::AbcCoreAbstract::TimeSampling ts(ncache_sampling_rate/6000.0, ncache_start/(ncache_ticks_per_frame*fps));
181+
std::cout << boost::format("getNumStoredTimes = %1%") % ts.getNumStoredTimes() << std::endl;
182+
Alembic::Util::uint32_t tsidx = iParent.getArchive().addTimeSampling(ts);
183+
184+
// Find the required channels
185+
std::string position_channel_name;
186+
std::string id_channel_name;
187+
if (!xml_reader.find_channel_ends_with("_position",position_channel_name))
188+
{
189+
DLOG(INFO) << "BAD" << std::endl;
190+
return false;
191+
}
192+
if (!xml_reader.find_channel_ends_with("_id",id_channel_name))
193+
{
194+
DLOG(INFO) << "BAD" << std::endl;
195+
return false;
196+
}
197+
std::cout << boost::format("position_channel_name = '%1%'") % position_channel_name << std::endl;
198+
199+
// Create the Alembic OPoints schema
200+
// Create our object.
201+
Alembic::AbcGeom::OPoints partsOut( xform, "nCacheParticles", tsidx );
202+
203+
// Add attributes
204+
Alembic::AbcGeom::OPointsSchema &pSchema = partsOut.getSchema();
205+
206+
// Alembic file setup - END
207+
208+
209+
std::string per_initial_frame_full_path = (boost::format("%1%/%2%Frame%3%.%4%") % xml_reader.get_cache_directory() % xml_reader.get_base_cache_name() % frame_index % cache_extension).str();
210+
// std::cout << boost::format("per_initial_frame_full_path = '%1%'") % per_initial_frame_full_path << std::endl;
211+
212+
if (is_mcx)
213+
cache_reader_ptr.reset(new MCXMemoryReader(per_initial_frame_full_path));
214+
else
215+
cache_reader_ptr.reset(new MCMemoryReader(per_initial_frame_full_path));
216+
217+
if (cache_reader_ptr)
218+
{
219+
process_single_sample(cache_reader_ptr,
220+
position_channel_name,
221+
id_channel_name,
222+
pSchema);
223+
}
224+
// sub frame data
225+
if ((ncache_sampling_rate < ncache_ticks_per_frame) && (frame_index!=end_frame))
226+
{
227+
size_t accumulated_ticks = ncache_sampling_rate;
228+
while ((accumulated_ticks < ncache_ticks_per_frame) && ((ncache_ticks_per_frame-accumulated_ticks)>=ncache_sampling_rate) )
229+
{
230+
std::string per_sub_frame_full_path = (boost::format("%1%/%2%Frame%3%Tick%4%.%5%") % xml_reader.get_cache_directory() % xml_reader.get_base_cache_name() % frame_index % accumulated_ticks % cache_extension).str();
117231
// std::cout << boost::format("\t""per_sub_frame_full_path '%1%'") % per_sub_frame_full_path << std::endl;
118232

119233
if (is_mcx)
@@ -136,9 +250,9 @@ bool nCacheAlembic::process(const std::string& i_alembic_filename,
136250
}
137251

138252
void nCacheAlembic::process_single_sample(const CacheReaderSharedPointerType& i_cache_reader_ptr,
139-
const std::string& i_position_channel_name,
140-
const std::string& i_id_channel_name,
141-
Alembic::AbcGeom::OPointsSchema &o_pSchema)
253+
const std::string& i_position_channel_name,
254+
const std::string& i_id_channel_name,
255+
Alembic::AbcGeom::OPointsSchema& o_pSchema)
142256
{
143257
const nCache::ChannelDataContainer& cdc = i_cache_reader_ptr->get_channels_data();
144258

@@ -182,3 +296,4 @@ void nCacheAlembic::process_single_sample(const CacheReaderSharedPointerType& i_
182296
std::cout << boost::format("position_data.size() = %1%, id_data.size() = %2%") % position_data.size() % id_data.size() << std::endl;
183297

184298
}
299+

lib/nCacheAlembic.h

+13-5
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,21 @@ namespace nCache
2121
public:
2222
nCacheAlembic();
2323
virtual ~nCacheAlembic();
24-
bool process(const std::string& i_alembic_filename, const nCacheLoader& i_ncache_loader);
24+
/*!
25+
* \brief Write a single Alembic file
26+
*/
27+
bool process(const std::string& i_alembic_filename,
28+
const nCacheLoader& i_ncache_loader);
29+
/*!
30+
* \brief Write one Alembic file for each frame
31+
*/
32+
bool process_per_frame(const std::string& i_alembic_format_filename,
33+
const nCacheLoader& i_ncache_loader);
2534
protected:
2635
void process_single_sample(const CacheReaderSharedPointerType& i_cache_reader_ptr,
27-
const std::string& i_position_channel_name,
28-
const std::string& i_id_channel_name,
29-
Alembic::AbcGeom::OPointsSchema &o_pSchema
30-
);
36+
const std::string& i_position_channel_name,
37+
const std::string& i_id_channel_name,
38+
Alembic::AbcGeom::OPointsSchema& o_pSchema);
3139
};
3240

3341
} // namespace nCache

lib/nCacheLoader.cpp

+16-8
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,30 @@ void nCacheLoader::process(const std::string& i_ncache_xml_filename)
3535
_ncache_xml_filename = i_ncache_xml_filename;
3636
_xml_reader.read(i_ncache_xml_filename);
3737

38-
size_t num_channels = _xml_reader.getChannels().size();
38+
size_t num_channels = _xml_reader.get_channels().size();
3939
// size_t num_frames = _xml_reader.get_num_frames();
4040
size_t cache_start_time_tick = _xml_reader.get_time_range_start();
4141
size_t cache_end_time_tick = _xml_reader.get_time_range_end();
4242
size_t cache_per_frame_tick = _xml_reader.get_cacheTimePerFrame_TimePerFrame();
4343
size_t start_frame = cache_start_time_tick / cache_per_frame_tick;
4444
size_t end_frame = cache_end_time_tick / cache_per_frame_tick;
4545
size_t sampling_rate = _xml_reader.get_particle_count_sampling_rate();
46-
// std::cout << boost::format("cache_per_frame_tick = %1%") % cache_per_frame_tick << std::endl;
47-
// std::cout << boost::format("sampling_rate = %1%") % sampling_rate << std::endl;
48-
std::cout << boost::format("cache type = '%1%'") % _xml_reader.getCacheType() << std::endl;
49-
std::cout << boost::format("cache format = '%1%'") % _xml_reader.getCacheFormat() << std::endl;
50-
bool is_mcx = _xml_reader.getCacheFormat().compare("mcx") == 0;
46+
std::cout << boost::format("cache_per_frame_tick = %1%") % cache_per_frame_tick << std::endl;
47+
std::cout << boost::format("sampling_rate = %1%") % sampling_rate << std::endl;
48+
std::cout << boost::format("start_frame = %1%") % start_frame << std::endl;
49+
std::cout << boost::format("end_frame = %1%") % end_frame << std::endl;
50+
std::cout << boost::format("cache type = '%1%'") % _xml_reader.get_cache_type() << std::endl;
51+
std::cout << boost::format("cache format = '%1%'") % _xml_reader.get_cache_format() << std::endl;
52+
std::cout << boost::format("cache directory = '%1%'") % _xml_reader.get_cache_directory() << std::endl;
53+
std::cout << boost::format("cache name = '%1%'") % _xml_reader.get_base_cache_name() << std::endl;
54+
55+
bool is_mcx = _xml_reader.get_cache_format().compare("mcx") == 0;
5156
std::string cache_extension("mc");
5257
if (is_mcx)
5358
cache_extension = "mcx";
5459
for (size_t frame_index = start_frame; frame_index <= end_frame; frame_index++)
5560
{
56-
std::string per_initial_frame_mcx_full_path = (boost::format("%1%/%2%Frame%3%.%4%") % _xml_reader.get_cache_directory() % _xml_reader.get_cache_name() % frame_index % cache_extension).str();
61+
std::string per_initial_frame_mcx_full_path = (boost::format("%1%/%2%Frame%3%.%4%") % _xml_reader.get_cache_directory() % _xml_reader.get_base_cache_name() % frame_index % cache_extension).str();
5762
std::cout << boost::format("START processing %1%") % per_initial_frame_mcx_full_path << std::endl;
5863

5964
#ifdef FILE_BASED
@@ -82,16 +87,19 @@ void nCacheLoader::process(const std::string& i_ncache_xml_filename)
8287
// % frame_index
8388
// % end_frame
8489
// << std::endl;
90+
#ifdef SUBSAMPLING_NOT_WORKING
8591
if ((sampling_rate < cache_per_frame_tick) && (frame_index!=end_frame))
8692
{
8793
size_t accumulated_ticks = sampling_rate;
8894
while ((accumulated_ticks < cache_per_frame_tick) && ((cache_per_frame_tick-accumulated_ticks)>=sampling_rate) )
8995
{
90-
std::string per_sub_frame_mcx_full_path = (boost::format("%1%/%2%Frame%3%Tick%4%.%5%") % _xml_reader.get_cache_directory() % _xml_reader.get_cache_name() % frame_index % accumulated_ticks % cache_extension).str();
96+
std::string per_sub_frame_mcx_full_path = (boost::format("%1%/%2%Frame%3%Tick%4%.%5%") % _xml_reader.get_cache_directory() % _xml_reader.get_base_cache_name() % frame_index % accumulated_ticks % cache_extension).str();
9197
std::cout << boost::format("\t""SUBFRAME PROCESSING %1%") % per_sub_frame_mcx_full_path << std::endl;
98+
std::cout << boost::format("accumulated_ticks = %1%, cache_per_frame_tick = %2%, sampling_rate = %3%") % accumulated_ticks % cache_per_frame_tick % sampling_rate << std::endl;
9299
accumulated_ticks += sampling_rate;
93100
}
94101
}
102+
#endif // SUBSAMPLING_NOT_WORKING
95103
}
96104
// _xml_reader.debugDump();
97105

0 commit comments

Comments
 (0)