Blender  V2.93
abc_archive.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2020 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 #include "abc_archive.h"
21 
22 #include "BKE_blender_version.h"
23 #include "BKE_main.h"
24 #include "BKE_scene.h"
25 
26 #include "DEG_depsgraph_query.h"
27 
28 #include "DNA_scene_types.h"
29 
30 #include <Alembic/AbcCoreOgawa/All.h>
31 #include <Alembic/AbcGeom/All.h>
32 
33 #ifdef WIN32
34 # include "BLI_path_util.h"
35 # include "BLI_string.h"
36 
37 # include "utfconv.h"
38 #endif
39 
41 
42 using Alembic::Abc::ErrorHandler;
43 using Alembic::Abc::kWrapExisting;
44 using Alembic::Abc::MetaData;
45 using Alembic::Abc::OArchive;
46 using Alembic::Abc::TimeSampling;
47 using Alembic::Abc::TimeSamplingPtr;
48 using Alembic::Abc::TimeSamplingType;
49 
50 static MetaData create_abc_metadata(const Main *bmain, double scene_fps)
51 {
52  MetaData abc_metadata;
53 
54  std::string abc_user_description(bmain->name);
55  if (abc_user_description.empty()) {
56  abc_user_description = "unknown";
57  }
58 
59  abc_metadata.set(Alembic::Abc::kApplicationNameKey, "Blender");
60  abc_metadata.set(Alembic::Abc::kUserDescriptionKey, abc_user_description);
61  abc_metadata.set("blender_version", std::string("v") + BKE_blender_version_string());
62  abc_metadata.set("FramesPerTimeUnit", std::to_string(scene_fps));
63 
64  time_t raw_time;
65  time(&raw_time);
66  char buffer[128];
67 
68 #if defined _WIN32 || defined _WIN64
69  ctime_s(buffer, 128, &raw_time);
70 #else
71  ctime_r(&raw_time, buffer);
72 #endif
73 
74  const std::size_t buffer_len = strlen(buffer);
75  if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') {
76  buffer[buffer_len - 1] = '\0';
77  }
78 
79  abc_metadata.set(Alembic::Abc::kDateWrittenKey, buffer);
80  return abc_metadata;
81 }
82 
83 static OArchive *create_archive(std::ofstream *abc_ostream,
84  const std::string &filename,
85  MetaData &abc_metadata)
86 {
87  /* Use stream to support unicode character paths on Windows. */
88 #ifdef WIN32
89  char filename_cstr[FILE_MAX];
90  BLI_strncpy(filename_cstr, filename.c_str(), FILE_MAX);
91 
92  UTF16_ENCODE(filename_cstr);
93  std::wstring wstr(filename_cstr_16);
94  abc_ostream->open(wstr.c_str(), std::ios::out | std::ios::binary);
95  UTF16_UN_ENCODE(filename_cstr);
96 #else
97  abc_ostream->open(filename, std::ios::out | std::ios::binary);
98 #endif
99 
100  ErrorHandler::Policy policy = ErrorHandler::kThrowPolicy;
101 
102  Alembic::AbcCoreOgawa::WriteArchive archive_writer;
103  return new OArchive(archive_writer(abc_ostream, abc_metadata), kWrapExisting, policy);
104 }
105 
106 /* Construct list of shutter samples.
107  *
108  * These are taken from the interval [shutter open, shutter close),
109  * uniformly sampled with 'nr_of_samples' samples.
110  *
111  * TODO(Sybren): test that the above interval is indeed half-open.
112  *
113  * If 'time_relative' is true, samples are returned as time (in seconds) from params.frame_start.
114  * If 'time_relative' is false, samples are returned as fractional frames from 0.
115  */
116 static void get_shutter_samples(double scene_fps,
118  int nr_of_samples,
119  bool time_relative,
120  std::vector<double> &r_samples)
121 {
122  int frame_offset = time_relative ? params.frame_start : 0;
123  double time_factor = time_relative ? scene_fps : 1.0;
124  double shutter_open = params.shutter_open;
125  double shutter_close = params.shutter_close;
126  double time_inc = (shutter_close - shutter_open) / nr_of_samples;
127 
128  /* sample between shutter open & close */
129  for (int sample = 0; sample < nr_of_samples; sample++) {
130  double sample_time = shutter_open + time_inc * sample;
131  double time = (frame_offset + sample_time) / time_factor;
132 
133  r_samples.push_back(time);
134  }
135 }
136 
137 static TimeSamplingPtr create_time_sampling(double scene_fps,
139  int nr_of_samples)
140 {
141  std::vector<double> samples;
142 
143  if (params.frame_start == params.frame_end) {
144  return TimeSamplingPtr(new TimeSampling()); // NOLINT: modernize-make-shared
145  }
146 
147  get_shutter_samples(scene_fps, params, nr_of_samples, true, samples);
148 
149  TimeSamplingType ts(static_cast<uint32_t>(samples.size()), 1.0 / scene_fps);
150  return TimeSamplingPtr(new TimeSampling(ts, samples)); // NOLINT: modernize-make-shared
151 }
152 
153 static void get_frames(double scene_fps,
155  unsigned int nr_of_samples,
156  std::set<double> &r_frames)
157 {
158  /* Get one set of shutter samples, then add those around each frame to export. */
159  std::vector<double> shutter_samples;
160  get_shutter_samples(scene_fps, params, nr_of_samples, false, shutter_samples);
161 
162  for (double frame = params.frame_start; frame <= params.frame_end; frame += 1.0) {
163  for (size_t j = 0; j < nr_of_samples; j++) {
164  r_frames.insert(frame + shutter_samples[j]);
165  }
166  }
167 }
168 
169 /* ****************************************************************** */
170 
172  const Scene *scene,
174  std::string filename)
175  : archive(nullptr)
176 {
177  double scene_fps = FPS;
178  MetaData abc_metadata = create_abc_metadata(bmain, scene_fps);
179 
180  /* Create the Archive. */
181  archive = create_archive(&abc_ostream_, filename, abc_metadata);
182 
183  /* Create time samples for transforms and shapes. */
184  TimeSamplingPtr ts_xform;
185  TimeSamplingPtr ts_shapes;
186 
187  ts_xform = create_time_sampling(scene_fps, params, params.frame_samples_xform);
188  time_sampling_index_transforms_ = archive->addTimeSampling(*ts_xform);
189 
190  const bool export_animation = params.frame_start != params.frame_end;
191  if (!export_animation || params.frame_samples_shape == params.frame_samples_xform) {
192  ts_shapes = ts_xform;
193  time_sampling_index_shapes_ = time_sampling_index_transforms_;
194  }
195  else {
196  ts_shapes = create_time_sampling(scene_fps, params, params.frame_samples_shape);
197  time_sampling_index_shapes_ = archive->addTimeSampling(*ts_shapes);
198  }
199 
200  /* Construct the frames to export. */
201  get_frames(scene_fps, params, params.frame_samples_xform, xform_frames_);
202  get_frames(scene_fps, params, params.frame_samples_shape, shape_frames_);
203 
204  /* Merge all frames to get the final set of frames to export. */
205  export_frames_.insert(xform_frames_.begin(), xform_frames_.end());
206  export_frames_.insert(shape_frames_.begin(), shape_frames_.end());
207 
208  abc_archive_bbox_ = Alembic::AbcGeom::CreateOArchiveBounds(*archive,
209  time_sampling_index_transforms_);
210 }
211 
213 {
214  delete archive;
215 }
216 
218 {
219  return time_sampling_index_transforms_;
220 }
221 
223 {
224  return time_sampling_index_shapes_;
225 }
226 
227 ABCArchive::Frames::const_iterator ABCArchive::frames_begin() const
228 {
229  return export_frames_.begin();
230 }
231 ABCArchive::Frames::const_iterator ABCArchive::frames_end() const
232 {
233  return export_frames_.end();
234 }
236 {
237  return export_frames_.size();
238 }
239 
240 bool ABCArchive::is_xform_frame(double frame) const
241 {
242  return xform_frames_.find(frame) != xform_frames_.end();
243 }
244 bool ABCArchive::is_shape_frame(double frame) const
245 {
246  return shape_frames_.find(frame) != shape_frames_.end();
247 }
249 {
250  ExportSubset subset;
251  subset.transforms = is_xform_frame(frame);
252  subset.shapes = is_shape_frame(frame);
253  return subset;
254 }
255 
256 void ABCArchive::update_bounding_box(const Imath::Box3d &bounds)
257 {
258  abc_archive_bbox_.set(bounds);
259 }
260 
261 } // namespace blender::io::alembic
const char * BKE_blender_version_string(void)
Definition: blender.c:142
#define FILE_MAX
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define FPS
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:299
Frames::const_iterator frames_end() const
Definition: abc_archive.cc:231
ABCArchive(const Main *bmain, const Scene *scene, AlembicExportParams params, std::string filename)
Definition: abc_archive.cc:171
bool is_xform_frame(double frame) const
Definition: abc_archive.cc:240
ExportSubset export_subset_for_frame(double frame) const
Definition: abc_archive.cc:248
bool is_shape_frame(double frame) const
Definition: abc_archive.cc:244
Frames::const_iterator frames_begin() const
Definition: abc_archive.cc:227
uint32_t time_sampling_index_shapes() const
Definition: abc_archive.cc:222
Alembic::Abc::OArchive * archive
Definition: abc_archive.h:49
void update_bounding_box(const Imath::Box3d &bounds)
Definition: abc_archive.cc:256
uint32_t time_sampling_index_transforms() const
Definition: abc_archive.cc:217
double time
Scene scene
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
static void sample(SocketReader *reader, int x, int y, float color[4])
static void get_frames(double scene_fps, const AlembicExportParams &params, unsigned int nr_of_samples, std::set< double > &r_frames)
Definition: abc_archive.cc:153
static MetaData create_abc_metadata(const Main *bmain, double scene_fps)
Definition: abc_archive.cc:50
static OArchive * create_archive(std::ofstream *abc_ostream, const std::string &filename, MetaData &abc_metadata)
Definition: abc_archive.cc:83
static TimeSamplingPtr create_time_sampling(double scene_fps, const AlembicExportParams &params, int nr_of_samples)
Definition: abc_archive.cc:137
static void get_shutter_samples(double scene_fps, const AlembicExportParams &params, int nr_of_samples, bool time_relative, std::vector< double > &r_samples)
Definition: abc_archive.cc:116
std::string to_string(const T &n)
unsigned int uint32_t
Definition: stdint.h:83
Definition: BKE_main.h:116
char name[1024]
Definition: BKE_main.h:118
#define UTF16_ENCODE(in8str)
Definition: utfconv.h:96
#define UTF16_UN_ENCODE(in8str)
Definition: utfconv.h:100