Blender  V2.93
alembic.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2018 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "render/alembic.h"
18 
19 #include "render/camera.h"
20 #include "render/curves.h"
21 #include "render/mesh.h"
22 #include "render/object.h"
23 #include "render/scene.h"
24 #include "render/shader.h"
25 
26 #include "util/util_foreach.h"
27 #include "util/util_progress.h"
28 #include "util/util_transform.h"
29 #include "util/util_vector.h"
30 
31 #ifdef WITH_ALEMBIC
32 
33 using namespace Alembic::AbcGeom;
34 
36 
37 /* TODO(@kevindietrich): motion blur support */
38 
39 void CachedData::clear()
40 {
41  attributes.clear();
42  curve_first_key.clear();
43  curve_keys.clear();
44  curve_radius.clear();
45  curve_shader.clear();
46  num_ngons.clear();
47  shader.clear();
48  subd_creases_edge.clear();
49  subd_creases_weight.clear();
50  subd_face_corners.clear();
51  subd_num_corners.clear();
52  subd_ptex_offset.clear();
53  subd_smooth.clear();
54  subd_start_corner.clear();
55  transforms.clear();
56  triangles.clear();
57  triangles_loops.clear();
58  vertices.clear();
59 
60  for (CachedAttribute &attr : attributes) {
61  attr.data.clear();
62  }
63 
64  attributes.clear();
65 }
66 
67 CachedData::CachedAttribute &CachedData::add_attribute(const ustring &name,
68  const TimeSampling &time_sampling)
69 {
70  for (auto &attr : attributes) {
71  if (attr.name == name) {
72  return attr;
73  }
74  }
75 
76  CachedAttribute &attr = attributes.emplace_back();
77  attr.name = name;
78  attr.data.set_time_sampling(time_sampling);
79  return attr;
80 }
81 
82 bool CachedData::is_constant() const
83 {
84 # define CHECK_IF_CONSTANT(data) \
85  if (!data.is_constant()) { \
86  return false; \
87  }
88 
89  CHECK_IF_CONSTANT(curve_first_key)
90  CHECK_IF_CONSTANT(curve_keys)
91  CHECK_IF_CONSTANT(curve_radius)
92  CHECK_IF_CONSTANT(curve_shader)
93  CHECK_IF_CONSTANT(num_ngons)
94  CHECK_IF_CONSTANT(shader)
95  CHECK_IF_CONSTANT(subd_creases_edge)
96  CHECK_IF_CONSTANT(subd_creases_weight)
97  CHECK_IF_CONSTANT(subd_face_corners)
98  CHECK_IF_CONSTANT(subd_num_corners)
99  CHECK_IF_CONSTANT(subd_ptex_offset)
100  CHECK_IF_CONSTANT(subd_smooth)
101  CHECK_IF_CONSTANT(subd_start_corner)
102  CHECK_IF_CONSTANT(transforms)
103  CHECK_IF_CONSTANT(triangles)
104  CHECK_IF_CONSTANT(triangles_loops)
105  CHECK_IF_CONSTANT(vertices)
106 
107  for (const CachedAttribute &attr : attributes) {
108  if (!attr.data.is_constant()) {
109  return false;
110  }
111  }
112 
113  return true;
114 
115 # undef CHECK_IF_CONSTANT
116 }
117 
118 void CachedData::invalidate_last_loaded_time(bool attributes_only)
119 {
120  if (attributes_only) {
121  for (CachedAttribute &attr : attributes) {
122  attr.data.invalidate_last_loaded_time();
123  }
124 
125  return;
126  }
127 
128  curve_first_key.invalidate_last_loaded_time();
129  curve_keys.invalidate_last_loaded_time();
130  curve_radius.invalidate_last_loaded_time();
131  curve_shader.invalidate_last_loaded_time();
132  num_ngons.invalidate_last_loaded_time();
133  shader.invalidate_last_loaded_time();
134  subd_creases_edge.invalidate_last_loaded_time();
135  subd_creases_weight.invalidate_last_loaded_time();
136  subd_face_corners.invalidate_last_loaded_time();
137  subd_num_corners.invalidate_last_loaded_time();
138  subd_ptex_offset.invalidate_last_loaded_time();
139  subd_smooth.invalidate_last_loaded_time();
140  subd_start_corner.invalidate_last_loaded_time();
141  transforms.invalidate_last_loaded_time();
142  triangles.invalidate_last_loaded_time();
143  triangles_loops.invalidate_last_loaded_time();
144  vertices.invalidate_last_loaded_time();
145 }
146 
147 void CachedData::set_time_sampling(TimeSampling time_sampling)
148 {
149  curve_first_key.set_time_sampling(time_sampling);
150  curve_keys.set_time_sampling(time_sampling);
151  curve_radius.set_time_sampling(time_sampling);
152  curve_shader.set_time_sampling(time_sampling);
153  num_ngons.set_time_sampling(time_sampling);
154  shader.set_time_sampling(time_sampling);
155  subd_creases_edge.set_time_sampling(time_sampling);
156  subd_creases_weight.set_time_sampling(time_sampling);
157  subd_face_corners.set_time_sampling(time_sampling);
158  subd_num_corners.set_time_sampling(time_sampling);
159  subd_ptex_offset.set_time_sampling(time_sampling);
160  subd_smooth.set_time_sampling(time_sampling);
161  subd_start_corner.set_time_sampling(time_sampling);
162  transforms.set_time_sampling(time_sampling);
163  triangles.set_time_sampling(time_sampling);
164  triangles_loops.set_time_sampling(time_sampling);
165  vertices.set_time_sampling(time_sampling);
166 
167  for (CachedAttribute &attr : attributes) {
168  attr.data.set_time_sampling(time_sampling);
169  }
170 }
171 
172 /* get the sample times to load data for the given the start and end frame of the procedural */
173 static set<chrono_t> get_relevant_sample_times(AlembicProcedural *proc,
174  const TimeSampling &time_sampling,
175  size_t num_samples)
176 {
177  set<chrono_t> result;
178 
179  if (num_samples < 2) {
180  result.insert(0.0);
181  return result;
182  }
183 
184  double start_frame = (double)(proc->get_start_frame() / proc->get_frame_rate());
185  double end_frame = (double)((proc->get_end_frame() + 1) / proc->get_frame_rate());
186 
187  size_t start_index = time_sampling.getFloorIndex(start_frame, num_samples).first;
188  size_t end_index = time_sampling.getCeilIndex(end_frame, num_samples).first;
189 
190  for (size_t i = start_index; i < end_index; ++i) {
191  result.insert(time_sampling.getSampleTime(i));
192  }
193 
194  return result;
195 }
196 
197 static float3 make_float3_from_yup(const V3f &v)
198 {
199  return make_float3(v.x, -v.z, v.y);
200 }
201 
202 static M44d convert_yup_zup(const M44d &mtx, float scale_mult)
203 {
204  V3d scale, shear, rotation, translation;
205  extractSHRT(mtx,
206  scale,
207  shear,
208  rotation,
209  translation,
210  true,
211  IMATH_INTERNAL_NAMESPACE::Euler<double>::XZY);
212 
213  M44d rot_mat, scale_mat, trans_mat;
214  rot_mat.setEulerAngles(V3d(rotation.x, -rotation.z, rotation.y));
215  scale_mat.setScale(V3d(scale.x, scale.z, scale.y));
216  trans_mat.setTranslation(V3d(translation.x, -translation.z, translation.y));
217 
218  M44d temp_mat = scale_mat * rot_mat * trans_mat;
219 
220  scale_mat.setScale(static_cast<double>(scale_mult));
221 
222  return temp_mat * scale_mat;
223 }
224 
225 static void transform_decompose(
226  const M44d &mat, V3d &scale, V3d &shear, Quatd &rotation, V3d &translation)
227 {
228  M44d mat_remainder(mat);
229 
230  /* extract scale and shear */
231  Imath::extractAndRemoveScalingAndShear(mat_remainder, scale, shear);
232 
233  /* extract translation */
234  translation.x = mat_remainder[3][0];
235  translation.y = mat_remainder[3][1];
236  translation.z = mat_remainder[3][2];
237 
238  /* extract rotation */
239  rotation = extractQuat(mat_remainder);
240 }
241 
242 static M44d transform_compose(const V3d &scale,
243  const V3d &shear,
244  const Quatd &rotation,
245  const V3d &translation)
246 {
247  M44d scale_mat, shear_mat, rot_mat, trans_mat;
248 
249  scale_mat.setScale(scale);
250  shear_mat.setShear(shear);
251  rot_mat = rotation.toMatrix44();
252  trans_mat.setTranslation(translation);
253 
254  return scale_mat * shear_mat * rot_mat * trans_mat;
255 }
256 
257 /* get the matrix for the specified time, or return the identity matrix if there is no exact match
258  */
259 static M44d get_matrix_for_time(const MatrixSampleMap &samples, chrono_t time)
260 {
261  MatrixSampleMap::const_iterator iter = samples.find(time);
262  if (iter != samples.end()) {
263  return iter->second;
264  }
265 
266  return M44d();
267 }
268 
269 /* get the matrix for the specified time, or interpolate between samples if there is no exact match
270  */
271 static M44d get_interpolated_matrix_for_time(const MatrixSampleMap &samples, chrono_t time)
272 {
273  if (samples.empty()) {
274  return M44d();
275  }
276 
277  /* see if exact match */
278  MatrixSampleMap::const_iterator iter = samples.find(time);
279  if (iter != samples.end()) {
280  return iter->second;
281  }
282 
283  if (samples.size() == 1) {
284  return samples.begin()->second;
285  }
286 
287  if (time <= samples.begin()->first) {
288  return samples.begin()->second;
289  }
290 
291  if (time >= samples.rbegin()->first) {
292  return samples.rbegin()->second;
293  }
294 
295  /* find previous and next time sample to interpolate */
296  chrono_t prev_time = samples.begin()->first;
297  chrono_t next_time = samples.rbegin()->first;
298 
299  for (MatrixSampleMap::const_iterator I = samples.begin(); I != samples.end(); ++I) {
300  chrono_t current_time = (*I).first;
301 
302  if (current_time > prev_time && current_time <= time) {
303  prev_time = current_time;
304  }
305 
306  if (current_time > next_time && current_time >= time) {
307  next_time = current_time;
308  }
309  }
310 
311  const M44d prev_mat = get_matrix_for_time(samples, prev_time);
312  const M44d next_mat = get_matrix_for_time(samples, next_time);
313 
314  V3d prev_scale, next_scale;
315  V3d prev_shear, next_shear;
316  V3d prev_translation, next_translation;
317  Quatd prev_rotation, next_rotation;
318 
319  transform_decompose(prev_mat, prev_scale, prev_shear, prev_rotation, prev_translation);
320  transform_decompose(next_mat, next_scale, next_shear, next_rotation, next_translation);
321 
322  chrono_t t = (time - prev_time) / (next_time - prev_time);
323 
324  /* ensure rotation around the shortest angle */
325  if ((prev_rotation ^ next_rotation) < 0) {
326  next_rotation = -next_rotation;
327  }
328 
329  return transform_compose(Imath::lerp(prev_scale, next_scale, t),
330  Imath::lerp(prev_shear, next_shear, t),
331  Imath::slerp(prev_rotation, next_rotation, t),
332  Imath::lerp(prev_translation, next_translation, t));
333 }
334 
335 static void concatenate_xform_samples(const MatrixSampleMap &parent_samples,
336  const MatrixSampleMap &local_samples,
337  MatrixSampleMap &output_samples)
338 {
339  set<chrono_t> union_of_samples;
340 
341  for (const std::pair<chrono_t, M44d> pair : parent_samples) {
342  union_of_samples.insert(pair.first);
343  }
344 
345  for (const std::pair<chrono_t, M44d> pair : local_samples) {
346  union_of_samples.insert(pair.first);
347  }
348 
349  foreach (chrono_t time, union_of_samples) {
350  M44d parent_matrix = get_interpolated_matrix_for_time(parent_samples, time);
351  M44d local_matrix = get_interpolated_matrix_for_time(local_samples, time);
352 
353  output_samples[time] = local_matrix * parent_matrix;
354  }
355 }
356 
357 static Transform make_transform(const M44d &a, float scale)
358 {
359  M44d m = convert_yup_zup(a, scale);
360  Transform trans;
361  for (int j = 0; j < 3; j++) {
362  for (int i = 0; i < 4; i++) {
363  trans[j][i] = static_cast<float>(m[i][j]);
364  }
365  }
366  return trans;
367 }
368 
369 static void add_uvs(AlembicProcedural *proc,
370  const IV2fGeomParam &uvs,
371  CachedData &cached_data,
372  Progress &progress)
373 {
374  if (uvs.getScope() != kFacevaryingScope) {
375  return;
376  }
377 
378  const TimeSamplingPtr time_sampling_ptr = uvs.getTimeSampling();
379 
380  TimeSampling time_sampling;
381  if (time_sampling_ptr) {
382  time_sampling = *time_sampling_ptr;
383  }
384 
385  std::string name = Alembic::Abc::GetSourceName(uvs.getMetaData());
386 
387  /* According to the convention, primary UVs should have had their name
388  * set using Alembic::Abc::SetSourceName, but you can't expect everyone
389  * to follow it! :) */
390  if (name.empty()) {
391  name = uvs.getName();
392  }
393 
394  CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(name), time_sampling);
395  attr.std = ATTR_STD_UV;
396 
397  ccl::set<chrono_t> times = get_relevant_sample_times(proc, time_sampling, uvs.getNumSamples());
398 
399  /* Keys used to determine if the UVs do actually change over time. */
400  ArraySample::Key previous_indices_key;
401  ArraySample::Key previous_values_key;
402 
403  foreach (chrono_t time, times) {
404  if (progress.get_cancel()) {
405  return;
406  }
407 
408  const ISampleSelector iss = ISampleSelector(time);
409  const IV2fGeomParam::Sample uvsample = uvs.getIndexedValue(iss);
410 
411  if (!uvsample.valid()) {
412  continue;
413  }
414 
415  const array<int3> *triangles =
416  cached_data.triangles.data_for_time_no_check(time).get_data_or_null();
417  const array<int3> *triangles_loops =
418  cached_data.triangles_loops.data_for_time_no_check(time).get_data_or_null();
419 
420  if (!triangles || !triangles_loops) {
421  continue;
422  }
423 
425  data.resize(triangles->size() * 3 * sizeof(float2));
426 
427  float2 *data_float2 = reinterpret_cast<float2 *>(data.data());
428 
429  const ArraySample::Key indices_key = uvsample.getIndices()->getKey();
430  const ArraySample::Key values_key = uvsample.getVals()->getKey();
431 
432  if (indices_key == previous_indices_key && values_key == previous_values_key) {
433  attr.data.reuse_data_for_last_time(time);
434  }
435  else {
436  const unsigned int *indices = uvsample.getIndices()->get();
437  const V2f *values = uvsample.getVals()->get();
438 
439  for (const int3 &loop : *triangles_loops) {
440  unsigned int v0 = indices[loop.x];
441  unsigned int v1 = indices[loop.y];
442  unsigned int v2 = indices[loop.z];
443 
444  data_float2[0] = make_float2(values[v0][0], values[v0][1]);
445  data_float2[1] = make_float2(values[v1][0], values[v1][1]);
446  data_float2[2] = make_float2(values[v2][0], values[v2][1]);
447  data_float2 += 3;
448  }
449 
450  attr.data.add_data(data, time);
451  }
452 
453  previous_indices_key = indices_key;
454  previous_values_key = values_key;
455  }
456 }
457 
458 static void add_normals(const Int32ArraySamplePtr face_indices,
459  const IN3fGeomParam &normals,
460  double time,
461  CachedData &cached_data)
462 {
463  switch (normals.getScope()) {
464  case kFacevaryingScope: {
465  const ISampleSelector iss = ISampleSelector(time);
466  const IN3fGeomParam::Sample sample = normals.getExpandedValue(iss);
467 
468  if (!sample.valid()) {
469  return;
470  }
471 
472  CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(normals.getName()),
473  *normals.getTimeSampling());
474  attr.std = ATTR_STD_VERTEX_NORMAL;
475 
476  const array<float3> *vertices =
477  cached_data.vertices.data_for_time_no_check(time).get_data_or_null();
478 
479  if (!vertices) {
480  return;
481  }
482 
484  data.resize(vertices->size() * sizeof(float3));
485 
486  float3 *data_float3 = reinterpret_cast<float3 *>(data.data());
487 
488  const int *face_indices_array = face_indices->get();
489  const N3fArraySamplePtr values = sample.getVals();
490 
491  for (size_t i = 0; i < face_indices->size(); ++i) {
492  int point_index = face_indices_array[i];
493  data_float3[point_index] = make_float3_from_yup(values->get()[i]);
494  }
495 
496  attr.data.add_data(data, time);
497  break;
498  }
499  case kVaryingScope:
500  case kVertexScope: {
501  const ISampleSelector iss = ISampleSelector(time);
502  const IN3fGeomParam::Sample sample = normals.getExpandedValue(iss);
503 
504  if (!sample.valid()) {
505  return;
506  }
507 
508  CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(normals.getName()),
509  *normals.getTimeSampling());
510  attr.std = ATTR_STD_VERTEX_NORMAL;
511 
512  const array<float3> *vertices =
513  cached_data.vertices.data_for_time_no_check(time).get_data_or_null();
514 
515  if (!vertices) {
516  return;
517  }
518 
520  data.resize(vertices->size() * sizeof(float3));
521 
522  float3 *data_float3 = reinterpret_cast<float3 *>(data.data());
523 
524  const Imath::V3f *values = sample.getVals()->get();
525 
526  for (size_t i = 0; i < vertices->size(); ++i) {
527  data_float3[i] = make_float3_from_yup(values[i]);
528  }
529 
530  attr.data.add_data(data, time);
531 
532  break;
533  }
534  default: {
535  break;
536  }
537  }
538 }
539 
540 static void add_positions(const P3fArraySamplePtr positions, double time, CachedData &cached_data)
541 {
542  if (!positions) {
543  return;
544  }
545 
546  array<float3> vertices;
547  vertices.reserve(positions->size());
548 
549  for (size_t i = 0; i < positions->size(); i++) {
550  V3f f = positions->get()[i];
551  vertices.push_back_reserved(make_float3_from_yup(f));
552  }
553 
554  cached_data.vertices.add_data(vertices, time);
555 }
556 
557 static void add_triangles(const Int32ArraySamplePtr face_counts,
558  const Int32ArraySamplePtr face_indices,
559  double time,
560  CachedData &cached_data,
561  const array<int> &polygon_to_shader)
562 {
563  if (!face_counts || !face_indices) {
564  return;
565  }
566 
567  const size_t num_faces = face_counts->size();
568  const int *face_counts_array = face_counts->get();
569  const int *face_indices_array = face_indices->get();
570 
571  size_t num_triangles = 0;
572  for (size_t i = 0; i < face_counts->size(); i++) {
573  num_triangles += face_counts_array[i] - 2;
574  }
575 
577  array<int3> triangles;
578  array<int3> triangles_loops;
579  shader.reserve(num_triangles);
580  triangles.reserve(num_triangles);
581  triangles_loops.reserve(num_triangles);
582  int index_offset = 0;
583 
584  for (size_t i = 0; i < num_faces; i++) {
585  int current_shader = 0;
586 
587  if (!polygon_to_shader.empty()) {
588  current_shader = polygon_to_shader[i];
589  }
590 
591  for (int j = 0; j < face_counts_array[i] - 2; j++) {
592  int v0 = face_indices_array[index_offset];
593  int v1 = face_indices_array[index_offset + j + 1];
594  int v2 = face_indices_array[index_offset + j + 2];
595 
596  shader.push_back_reserved(current_shader);
597 
598  /* Alembic orders the loops following the RenderMan convention, so need to go in reverse. */
599  triangles.push_back_reserved(make_int3(v2, v1, v0));
600  triangles_loops.push_back_reserved(
601  make_int3(index_offset + j + 2, index_offset + j + 1, index_offset));
602  }
603 
604  index_offset += face_counts_array[i];
605  }
606 
607  cached_data.triangles.add_data(triangles, time);
608  cached_data.triangles_loops.add_data(triangles_loops, time);
609  cached_data.shader.add_data(shader, time);
610 }
611 
612 NODE_DEFINE(AlembicObject)
613 {
614  NodeType *type = NodeType::add("alembic_object", create);
615 
616  SOCKET_STRING(path, "Alembic Path", ustring());
617  SOCKET_NODE_ARRAY(used_shaders, "Used Shaders", Shader::get_node_type());
618 
619  SOCKET_INT(subd_max_level, "Max Subdivision Level", 1);
620  SOCKET_FLOAT(subd_dicing_rate, "Subdivision Dicing Rate", 1.0f);
621 
622  SOCKET_FLOAT(radius_scale, "Radius Scale", 1.0f);
623 
624  return type;
625 }
626 
627 AlembicObject::AlembicObject() : Node(get_node_type())
628 {
629  schema_type = INVALID;
630 }
631 
632 AlembicObject::~AlembicObject()
633 {
634 }
635 
636 void AlembicObject::set_object(Object *object_)
637 {
638  object = object_;
639 }
640 
641 Object *AlembicObject::get_object()
642 {
643  return object;
644 }
645 
646 bool AlembicObject::has_data_loaded() const
647 {
648  return data_loaded;
649 }
650 
651 void AlembicObject::update_shader_attributes(const ICompoundProperty &arb_geom_params,
652  Progress &progress)
653 {
654  AttributeRequestSet requested_attributes = get_requested_attributes();
655 
656  foreach (const AttributeRequest &attr, requested_attributes.requests) {
657  if (progress.get_cancel()) {
658  return;
659  }
660 
661  bool attr_exists = false;
662  foreach (CachedData::CachedAttribute &cached_attr, cached_data.attributes) {
663  if (cached_attr.name == attr.name) {
664  attr_exists = true;
665  break;
666  }
667  }
668 
669  if (attr_exists) {
670  continue;
671  }
672 
673  read_attribute(arb_geom_params, attr.name, progress);
674  }
675 
676  cached_data.invalidate_last_loaded_time(true);
677  need_shader_update = false;
678 }
679 
680 template<typename SchemaType>
681 void AlembicObject::read_face_sets(SchemaType &schema,
682  array<int> &polygon_to_shader,
683  ISampleSelector sample_sel)
684 {
685  std::vector<std::string> face_sets;
686  schema.getFaceSetNames(face_sets);
687 
688  if (face_sets.empty()) {
689  return;
690  }
691 
692  const Int32ArraySamplePtr face_counts = schema.getFaceCountsProperty().getValue();
693 
694  polygon_to_shader.resize(face_counts->size());
695 
696  foreach (const std::string &face_set_name, face_sets) {
697  int shader_index = 0;
698 
699  foreach (Node *node, get_used_shaders()) {
700  if (node->name == face_set_name) {
701  break;
702  }
703 
704  ++shader_index;
705  }
706 
707  if (shader_index >= get_used_shaders().size()) {
708  /* use the first shader instead if none was found */
709  shader_index = 0;
710  }
711 
712  const IFaceSet face_set = schema.getFaceSet(face_set_name);
713 
714  if (!face_set.valid()) {
715  continue;
716  }
717 
718  const IFaceSetSchema face_schem = face_set.getSchema();
719  const IFaceSetSchema::Sample face_sample = face_schem.getValue(sample_sel);
720  const Int32ArraySamplePtr group_faces = face_sample.getFaces();
721  const size_t num_group_faces = group_faces->size();
722 
723  for (size_t l = 0; l < num_group_faces; l++) {
724  size_t pos = (*group_faces)[l];
725 
726  if (pos >= polygon_to_shader.size()) {
727  continue;
728  }
729 
730  polygon_to_shader[pos] = shader_index;
731  }
732  }
733 }
734 
735 void AlembicObject::load_all_data(AlembicProcedural *proc,
736  IPolyMeshSchema &schema,
737  Progress &progress)
738 {
739  cached_data.clear();
740 
741  /* Only load data for the original Geometry. */
742  if (instance_of) {
743  return;
744  }
745 
746  const TimeSamplingPtr time_sampling = schema.getTimeSampling();
747  cached_data.set_time_sampling(*time_sampling);
748 
749  const IN3fGeomParam &normals = schema.getNormalsParam();
750 
751  ccl::set<chrono_t> times = get_relevant_sample_times(
752  proc, *time_sampling, schema.getNumSamples());
753 
754  /* Key used to determine if the triangles change over time, if the key is the same as the
755  * last one, we can avoid creating a new entry in the cache and simply point to the last
756  * frame. */
757  ArraySample::Key previous_key;
758 
759  /* read topology */
760  foreach (chrono_t time, times) {
761  if (progress.get_cancel()) {
762  return;
763  }
764 
765  const ISampleSelector iss = ISampleSelector(time);
766  const IPolyMeshSchema::Sample sample = schema.getValue(iss);
767 
768  add_positions(sample.getPositions(), time, cached_data);
769 
770  /* Only copy triangles for other frames if the topology is changing over time as well. */
771  if (schema.getTopologyVariance() != kHomogenousTopology || cached_data.triangles.size() == 0) {
772  const ArraySample::Key key = sample.getFaceIndices()->getKey();
773 
774  if (key == previous_key) {
775  cached_data.triangles.reuse_data_for_last_time(time);
776  cached_data.triangles_loops.reuse_data_for_last_time(time);
777  cached_data.shader.reuse_data_for_last_time(time);
778  }
779  else {
780  /* start by reading the face sets (per face shader), as we directly split polygons to
781  * triangles
782  */
783  array<int> polygon_to_shader;
784  read_face_sets(schema, polygon_to_shader, iss);
785 
786  add_triangles(
787  sample.getFaceCounts(), sample.getFaceIndices(), time, cached_data, polygon_to_shader);
788  }
789 
790  previous_key = key;
791  }
792 
793  if (normals.valid()) {
794  add_normals(sample.getFaceIndices(), normals, time, cached_data);
795  }
796  }
797 
798  if (progress.get_cancel()) {
799  return;
800  }
801 
802  update_shader_attributes(schema.getArbGeomParams(), progress);
803 
804  if (progress.get_cancel()) {
805  return;
806  }
807 
808  const IV2fGeomParam &uvs = schema.getUVsParam();
809 
810  if (uvs.valid()) {
811  add_uvs(proc, uvs, cached_data, progress);
812  }
813 
814  data_loaded = true;
815 }
816 
817 void AlembicObject::load_all_data(AlembicProcedural *proc, ISubDSchema &schema, Progress &progress)
818 {
819  cached_data.clear();
820 
821  /* Only load data for the original Geometry. */
822  if (instance_of) {
823  return;
824  }
825 
826  AttributeRequestSet requested_attributes = get_requested_attributes();
827 
828  const TimeSamplingPtr time_sampling = schema.getTimeSampling();
829  cached_data.set_time_sampling(*time_sampling);
830 
831  ccl::set<chrono_t> times = get_relevant_sample_times(
832  proc, *time_sampling, schema.getNumSamples());
833 
834  /* read topology */
835  foreach (chrono_t time, times) {
836  if (progress.get_cancel()) {
837  return;
838  }
839 
840  const ISampleSelector iss = ISampleSelector(time);
841  const ISubDSchema::Sample sample = schema.getValue(iss);
842 
843  add_positions(sample.getPositions(), time, cached_data);
844 
845  const Int32ArraySamplePtr face_counts = sample.getFaceCounts();
846  const Int32ArraySamplePtr face_indices = sample.getFaceIndices();
847 
848  /* start by reading the face sets (per face shader) */
849  array<int> polygon_to_shader;
850  read_face_sets(schema, polygon_to_shader, iss);
851 
852  /* read faces */
853  array<int> subd_start_corner;
855  array<int> subd_num_corners;
856  array<bool> subd_smooth;
857  array<int> subd_ptex_offset;
858  array<int> subd_face_corners;
859 
860  const size_t num_faces = face_counts->size();
861  const int *face_counts_array = face_counts->get();
862  const int *face_indices_array = face_indices->get();
863 
864  int num_ngons = 0;
865  int num_corners = 0;
866  for (size_t i = 0; i < face_counts->size(); i++) {
867  num_ngons += (face_counts_array[i] == 4 ? 0 : 1);
868  num_corners += face_counts_array[i];
869  }
870 
871  subd_start_corner.reserve(num_faces);
872  subd_num_corners.reserve(num_faces);
873  subd_smooth.reserve(num_faces);
874  subd_ptex_offset.reserve(num_faces);
875  shader.reserve(num_faces);
876  subd_face_corners.reserve(num_corners);
877 
878  int start_corner = 0;
879  int current_shader = 0;
880  int ptex_offset = 0;
881 
882  for (size_t i = 0; i < face_counts->size(); i++) {
883  num_corners = face_counts_array[i];
884 
885  if (!polygon_to_shader.empty()) {
886  current_shader = polygon_to_shader[i];
887  }
888 
889  subd_start_corner.push_back_reserved(start_corner);
890  subd_num_corners.push_back_reserved(num_corners);
891 
892  for (int j = 0; j < num_corners; ++j) {
893  subd_face_corners.push_back_reserved(face_indices_array[start_corner + j]);
894  }
895 
896  shader.push_back_reserved(current_shader);
897  subd_smooth.push_back_reserved(1);
898  subd_ptex_offset.push_back_reserved(ptex_offset);
899 
900  ptex_offset += (num_corners == 4 ? 1 : num_corners);
901 
902  start_corner += num_corners;
903  }
904 
905  cached_data.shader.add_data(shader, time);
906  cached_data.subd_start_corner.add_data(subd_start_corner, time);
907  cached_data.subd_num_corners.add_data(subd_num_corners, time);
908  cached_data.subd_smooth.add_data(subd_smooth, time);
909  cached_data.subd_ptex_offset.add_data(subd_ptex_offset, time);
910  cached_data.subd_face_corners.add_data(subd_face_corners, time);
911  cached_data.num_ngons.add_data(num_ngons, time);
912 
913  /* read creases */
914  Int32ArraySamplePtr creases_length = sample.getCreaseLengths();
915  Int32ArraySamplePtr creases_indices = sample.getCreaseIndices();
916  FloatArraySamplePtr creases_sharpnesses = sample.getCreaseSharpnesses();
917 
918  if (creases_length && creases_indices && creases_sharpnesses) {
919  array<int> creases_edge;
920  array<float> creases_weight;
921 
922  creases_edge.reserve(creases_sharpnesses->size() * 2);
923  creases_weight.reserve(creases_sharpnesses->size());
924 
925  int length_offset = 0;
926  int weight_offset = 0;
927  for (size_t c = 0; c < creases_length->size(); ++c) {
928  const int crease_length = creases_length->get()[c];
929 
930  for (size_t j = 0; j < crease_length - 1; ++j) {
931  creases_edge.push_back_reserved(creases_indices->get()[length_offset + j]);
932  creases_edge.push_back_reserved(creases_indices->get()[length_offset + j + 1]);
933  creases_weight.push_back_reserved(creases_sharpnesses->get()[weight_offset++]);
934  }
935 
936  length_offset += crease_length;
937  }
938 
939  cached_data.subd_creases_edge.add_data(creases_edge, time);
940  cached_data.subd_creases_weight.add_data(creases_weight, time);
941  }
942  }
943 
944  /* TODO(@kevindietrich) : attributes, need test files */
945 
946  if (progress.get_cancel()) {
947  return;
948  }
949 
950  data_loaded = true;
951 }
952 
953 void AlembicObject::load_all_data(AlembicProcedural *proc,
954  const ICurvesSchema &schema,
955  Progress &progress,
956  float default_radius)
957 {
958  cached_data.clear();
959 
960  /* Only load data for the original Geometry. */
961  if (instance_of) {
962  return;
963  }
964 
965  const TimeSamplingPtr time_sampling = schema.getTimeSampling();
966  cached_data.set_time_sampling(*time_sampling);
967 
968  ccl::set<chrono_t> times = get_relevant_sample_times(
969  proc, *time_sampling, schema.getNumSamples());
970 
971  foreach (chrono_t time, times) {
972  if (progress.get_cancel()) {
973  return;
974  }
975 
976  const ISampleSelector iss = ISampleSelector(time);
977  const ICurvesSchema::Sample sample = schema.getValue(iss);
978 
979  const Int32ArraySamplePtr curves_num_vertices = sample.getCurvesNumVertices();
980  const P3fArraySamplePtr position = sample.getPositions();
981 
982  const IFloatGeomParam widths_param = schema.getWidthsParam();
983  FloatArraySamplePtr radiuses;
984 
985  if (widths_param.valid()) {
986  IFloatGeomParam::Sample wsample = widths_param.getExpandedValue(iss);
987  radiuses = wsample.getVals();
988  }
989 
990  const bool do_radius = (radiuses != nullptr) && (radiuses->size() > 1);
991  float radius = (radiuses && radiuses->size() == 1) ? (*radiuses)[0] : default_radius;
992 
993  array<float3> curve_keys;
994  array<float> curve_radius;
995  array<int> curve_first_key;
996  array<int> curve_shader;
997 
998  const bool is_homogenous = schema.getTopologyVariance() == kHomogenousTopology;
999 
1000  curve_keys.reserve(position->size());
1001  curve_radius.reserve(position->size());
1002  curve_first_key.reserve(curves_num_vertices->size());
1003  curve_shader.reserve(curves_num_vertices->size());
1004 
1005  int offset = 0;
1006  for (size_t i = 0; i < curves_num_vertices->size(); i++) {
1007  const int num_vertices = curves_num_vertices->get()[i];
1008 
1009  for (int j = 0; j < num_vertices; j++) {
1010  const V3f &f = position->get()[offset + j];
1011  curve_keys.push_back_reserved(make_float3_from_yup(f));
1012 
1013  if (do_radius) {
1014  radius = (*radiuses)[offset + j];
1015  }
1016 
1017  curve_radius.push_back_reserved(radius * radius_scale);
1018  }
1019 
1020  if (!is_homogenous || cached_data.curve_first_key.size() == 0) {
1021  curve_first_key.push_back_reserved(offset);
1022  curve_shader.push_back_reserved(0);
1023  }
1024 
1025  offset += num_vertices;
1026  }
1027 
1028  cached_data.curve_keys.add_data(curve_keys, time);
1029  cached_data.curve_radius.add_data(curve_radius, time);
1030 
1031  if (!is_homogenous || cached_data.curve_first_key.size() == 0) {
1032  cached_data.curve_first_key.add_data(curve_first_key, time);
1033  cached_data.curve_shader.add_data(curve_shader, time);
1034  }
1035  }
1036 
1037  // TODO(@kevindietrich): attributes, need example files
1038 
1039  data_loaded = true;
1040 }
1041 
1042 void AlembicObject::setup_transform_cache(float scale)
1043 {
1044  cached_data.transforms.clear();
1045  cached_data.transforms.invalidate_last_loaded_time();
1046 
1047  if (scale == 0.0f) {
1048  scale = 1.0f;
1049  }
1050 
1051  if (xform_time_sampling) {
1052  cached_data.transforms.set_time_sampling(*xform_time_sampling);
1053  }
1054 
1055  if (xform_samples.size() == 0) {
1056  Transform tfm = transform_scale(make_float3(scale));
1057  cached_data.transforms.add_data(tfm, 0.0);
1058  }
1059  else {
1060  /* It is possible for a leaf node of the hierarchy to have multiple samples for its transforms
1061  * if a sibling has animated transforms. So check if we indeed have animated transformations.
1062  */
1063  M44d first_matrix = xform_samples.begin()->first;
1064  bool has_animation = false;
1065  for (const std::pair<chrono_t, M44d> pair : xform_samples) {
1066  if (pair.second != first_matrix) {
1067  has_animation = true;
1068  break;
1069  }
1070  }
1071 
1072  if (!has_animation) {
1073  Transform tfm = make_transform(first_matrix, scale);
1074  cached_data.transforms.add_data(tfm, 0.0);
1075  }
1076  else {
1077  for (const std::pair<chrono_t, M44d> pair : xform_samples) {
1078  Transform tfm = make_transform(pair.second, scale);
1079  cached_data.transforms.add_data(tfm, pair.first);
1080  }
1081  }
1082  }
1083 }
1084 
1085 AttributeRequestSet AlembicObject::get_requested_attributes()
1086 {
1087  AttributeRequestSet requested_attributes;
1088 
1089  Geometry *geometry = object->get_geometry();
1090  assert(geometry);
1091 
1092  foreach (Node *node, geometry->get_used_shaders()) {
1093  Shader *shader = static_cast<Shader *>(node);
1094 
1095  foreach (const AttributeRequest &attr, shader->attributes.requests) {
1096  if (attr.name != "") {
1097  requested_attributes.add(attr.name);
1098  }
1099  }
1100  }
1101 
1102  return requested_attributes;
1103 }
1104 
1105 void AlembicObject::read_attribute(const ICompoundProperty &arb_geom_params,
1106  const ustring &attr_name,
1107  Progress &progress)
1108 {
1109  const PropertyHeader *prop = arb_geom_params.getPropertyHeader(attr_name.c_str());
1110 
1111  if (prop == nullptr) {
1112  return;
1113  }
1114 
1115  if (IV2fProperty::matches(prop->getMetaData()) && Alembic::AbcGeom::isUV(*prop)) {
1116  const IV2fGeomParam &param = IV2fGeomParam(arb_geom_params, prop->getName());
1117 
1118  CachedData::CachedAttribute &attribute = cached_data.add_attribute(attr_name,
1119  *param.getTimeSampling());
1120 
1121  for (size_t i = 0; i < param.getNumSamples(); ++i) {
1122  if (progress.get_cancel()) {
1123  return;
1124  }
1125 
1126  ISampleSelector iss = ISampleSelector(index_t(i));
1127 
1128  IV2fGeomParam::Sample sample;
1129  param.getIndexed(sample, iss);
1130 
1131  const chrono_t time = param.getTimeSampling()->getSampleTime(index_t(i));
1132 
1133  if (param.getScope() == kFacevaryingScope) {
1134  V2fArraySamplePtr values = sample.getVals();
1135  UInt32ArraySamplePtr indices = sample.getIndices();
1136 
1137  attribute.std = ATTR_STD_NONE;
1138  attribute.element = ATTR_ELEMENT_CORNER;
1139  attribute.type_desc = TypeFloat2;
1140 
1141  const array<int3> *triangles =
1142  cached_data.triangles.data_for_time_no_check(time).get_data_or_null();
1143  const array<int3> *triangles_loops =
1144  cached_data.triangles_loops.data_for_time_no_check(time).get_data_or_null();
1145 
1146  if (!triangles || !triangles_loops) {
1147  return;
1148  }
1149 
1150  array<char> data;
1151  data.resize(triangles->size() * 3 * sizeof(float2));
1152 
1153  float2 *data_float2 = reinterpret_cast<float2 *>(data.data());
1154 
1155  for (const int3 &loop : *triangles_loops) {
1156  unsigned int v0 = (*indices)[loop.x];
1157  unsigned int v1 = (*indices)[loop.y];
1158  unsigned int v2 = (*indices)[loop.z];
1159 
1160  data_float2[0] = make_float2((*values)[v0][0], (*values)[v0][1]);
1161  data_float2[1] = make_float2((*values)[v1][0], (*values)[v1][1]);
1162  data_float2[2] = make_float2((*values)[v2][0], (*values)[v2][1]);
1163  data_float2 += 3;
1164  }
1165 
1166  attribute.data.set_time_sampling(*param.getTimeSampling());
1167  attribute.data.add_data(data, time);
1168  }
1169  }
1170  }
1171  else if (IC3fProperty::matches(prop->getMetaData())) {
1172  const IC3fGeomParam &param = IC3fGeomParam(arb_geom_params, prop->getName());
1173 
1174  CachedData::CachedAttribute &attribute = cached_data.add_attribute(attr_name,
1175  *param.getTimeSampling());
1176 
1177  for (size_t i = 0; i < param.getNumSamples(); ++i) {
1178  if (progress.get_cancel()) {
1179  return;
1180  }
1181 
1182  ISampleSelector iss = ISampleSelector(index_t(i));
1183 
1184  IC3fGeomParam::Sample sample;
1185  param.getIndexed(sample, iss);
1186 
1187  const chrono_t time = param.getTimeSampling()->getSampleTime(index_t(i));
1188 
1189  C3fArraySamplePtr values = sample.getVals();
1190 
1191  attribute.std = ATTR_STD_NONE;
1192 
1193  if (param.getScope() == kVaryingScope) {
1194  attribute.element = ATTR_ELEMENT_CORNER_BYTE;
1195  attribute.type_desc = TypeRGBA;
1196 
1197  const array<int3> *triangles =
1198  cached_data.triangles.data_for_time_no_check(time).get_data_or_null();
1199 
1200  if (!triangles) {
1201  return;
1202  }
1203 
1204  array<char> data;
1205  data.resize(triangles->size() * 3 * sizeof(uchar4));
1206 
1207  uchar4 *data_uchar4 = reinterpret_cast<uchar4 *>(data.data());
1208 
1209  int offset = 0;
1210  for (const int3 &tri : *triangles) {
1211  Imath::C3f v = (*values)[tri.x];
1212  data_uchar4[offset + 0] = color_float_to_byte(make_float3(v.x, v.y, v.z));
1213 
1214  v = (*values)[tri.y];
1215  data_uchar4[offset + 1] = color_float_to_byte(make_float3(v.x, v.y, v.z));
1216 
1217  v = (*values)[tri.z];
1218  data_uchar4[offset + 2] = color_float_to_byte(make_float3(v.x, v.y, v.z));
1219 
1220  offset += 3;
1221  }
1222 
1223  attribute.data.set_time_sampling(*param.getTimeSampling());
1224  attribute.data.add_data(data, time);
1225  }
1226  }
1227  }
1228  else if (IC4fProperty::matches(prop->getMetaData())) {
1229  const IC4fGeomParam &param = IC4fGeomParam(arb_geom_params, prop->getName());
1230 
1231  CachedData::CachedAttribute &attribute = cached_data.add_attribute(attr_name,
1232  *param.getTimeSampling());
1233 
1234  for (size_t i = 0; i < param.getNumSamples(); ++i) {
1235  if (progress.get_cancel()) {
1236  return;
1237  }
1238 
1239  ISampleSelector iss = ISampleSelector(index_t(i));
1240 
1241  IC4fGeomParam::Sample sample;
1242  param.getIndexed(sample, iss);
1243 
1244  const chrono_t time = param.getTimeSampling()->getSampleTime(index_t(i));
1245 
1246  C4fArraySamplePtr values = sample.getVals();
1247 
1248  attribute.std = ATTR_STD_NONE;
1249 
1250  if (param.getScope() == kVaryingScope) {
1251  attribute.element = ATTR_ELEMENT_CORNER_BYTE;
1252  attribute.type_desc = TypeRGBA;
1253 
1254  const array<int3> *triangles =
1255  cached_data.triangles.data_for_time_no_check(time).get_data_or_null();
1256 
1257  if (!triangles) {
1258  return;
1259  }
1260 
1261  array<char> data;
1262  data.resize(triangles->size() * 3 * sizeof(uchar4));
1263 
1264  uchar4 *data_uchar4 = reinterpret_cast<uchar4 *>(data.data());
1265 
1266  int offset = 0;
1267  for (const int3 &tri : *triangles) {
1268  Imath::C4f v = (*values)[tri.x];
1269  data_uchar4[offset + 0] = color_float4_to_uchar4(make_float4(v.r, v.g, v.b, v.a));
1270 
1271  v = (*values)[tri.y];
1272  data_uchar4[offset + 1] = color_float4_to_uchar4(make_float4(v.r, v.g, v.b, v.a));
1273 
1274  v = (*values)[tri.z];
1275  data_uchar4[offset + 2] = color_float4_to_uchar4(make_float4(v.r, v.g, v.b, v.a));
1276 
1277  offset += 3;
1278  }
1279 
1280  attribute.data.set_time_sampling(*param.getTimeSampling());
1281  attribute.data.add_data(data, time);
1282  }
1283  }
1284  }
1285 }
1286 
1287 /* Update existing attributes and remove any attribute not in the cached_data, those attributes
1288  * were added by Cycles (e.g. face normals) */
1289 static void update_attributes(AttributeSet &attributes, CachedData &cached_data, double frame_time)
1290 {
1291  set<Attribute *> cached_attributes;
1292 
1293  for (CachedData::CachedAttribute &attribute : cached_data.attributes) {
1294  const array<char> *attr_data = attribute.data.data_for_time(frame_time).get_data_or_null();
1295 
1296  Attribute *attr = nullptr;
1297  if (attribute.std != ATTR_STD_NONE) {
1298  attr = attributes.add(attribute.std, attribute.name);
1299  }
1300  else {
1301  attr = attributes.add(attribute.name, attribute.type_desc, attribute.element);
1302  }
1303  assert(attr);
1304 
1305  cached_attributes.insert(attr);
1306 
1307  if (!attr_data) {
1308  /* no new data */
1309  continue;
1310  }
1311 
1312  /* weak way of detecting if the topology has changed
1313  * todo: reuse code from device_update patch */
1314  if (attr->buffer.size() != attr_data->size()) {
1315  attr->buffer.resize(attr_data->size());
1316  }
1317 
1318  memcpy(attr->data(), attr_data->data(), attr_data->size());
1319  attr->modified = true;
1320  }
1321 
1322  /* remove any attributes not in cached_attributes */
1323  list<Attribute>::iterator it;
1324  for (it = attributes.attributes.begin(); it != attributes.attributes.end();) {
1325  if (cached_attributes.find(&(*it)) == cached_attributes.end()) {
1326  attributes.attributes.erase(it++);
1327  attributes.modified = true;
1328  continue;
1329  }
1330 
1331  it++;
1332  }
1333 }
1334 
1335 NODE_DEFINE(AlembicProcedural)
1336 {
1337  NodeType *type = NodeType::add("alembic", create);
1338 
1339  SOCKET_STRING(filepath, "Filename", ustring());
1340  SOCKET_FLOAT(frame, "Frame", 1.0f);
1341  SOCKET_FLOAT(start_frame, "Start Frame", 1.0f);
1342  SOCKET_FLOAT(end_frame, "End Frame", 1.0f);
1343  SOCKET_FLOAT(frame_rate, "Frame Rate", 24.0f);
1344  SOCKET_FLOAT(frame_offset, "Frame Offset", 0.0f);
1345  SOCKET_FLOAT(default_radius, "Default Radius", 0.01f);
1346  SOCKET_FLOAT(scale, "Scale", 1.0f);
1347 
1348  SOCKET_NODE_ARRAY(objects, "Objects", AlembicObject::get_node_type());
1349 
1350  return type;
1351 }
1352 
1353 AlembicProcedural::AlembicProcedural() : Procedural(get_node_type())
1354 {
1355  objects_loaded = false;
1356  scene_ = nullptr;
1357 }
1358 
1359 AlembicProcedural::~AlembicProcedural()
1360 {
1361  ccl::set<Geometry *> geometries_set;
1362  ccl::set<Object *> objects_set;
1363  ccl::set<AlembicObject *> abc_objects_set;
1364 
1365  foreach (Node *node, objects) {
1366  AlembicObject *abc_object = static_cast<AlembicObject *>(node);
1367 
1368  if (abc_object->get_object()) {
1369  objects_set.insert(abc_object->get_object());
1370 
1371  if (abc_object->get_object()->get_geometry()) {
1372  geometries_set.insert(abc_object->get_object()->get_geometry());
1373  }
1374  }
1375 
1376  delete_node(abc_object);
1377  }
1378 
1379  /* We may delete a Procedural before rendering started, so scene_ can be null. */
1380  if (!scene_) {
1381  assert(geometries_set.empty());
1382  assert(objects_set.empty());
1383  return;
1384  }
1385 
1386  scene_->delete_nodes(geometries_set, this);
1387  scene_->delete_nodes(objects_set, this);
1388 }
1389 
1391 {
1392  assert(scene_ == nullptr || scene_ == scene);
1393  scene_ = scene;
1394 
1395  if (frame < start_frame || frame > end_frame) {
1396  clear_modified();
1397  return;
1398  }
1399 
1400  bool need_shader_updates = false;
1401  bool need_data_updates = false;
1402 
1403  foreach (Node *object_node, objects) {
1404  AlembicObject *object = static_cast<AlembicObject *>(object_node);
1405 
1406  if (object->is_modified()) {
1407  need_data_updates = true;
1408  }
1409 
1410  /* Check if the shaders were modified. */
1411  if (object->used_shaders_is_modified() && object->get_object() &&
1412  object->get_object()->get_geometry()) {
1413  Geometry *geometry = object->get_object()->get_geometry();
1414  array<Node *> used_shaders = object->get_used_shaders();
1415  geometry->set_used_shaders(used_shaders);
1416  need_shader_updates = true;
1417  }
1418 
1419  /* Check for changes in shaders (e.g. newly requested attributes). */
1420  foreach (Node *shader_node, object->get_used_shaders()) {
1421  Shader *shader = static_cast<Shader *>(shader_node);
1422 
1423  if (shader->need_update_geometry()) {
1424  object->need_shader_update = true;
1425  need_shader_updates = true;
1426  }
1427  }
1428  }
1429 
1430  if (!is_modified() && !need_shader_updates && !need_data_updates) {
1431  return;
1432  }
1433 
1434  if (!archive.valid()) {
1435  Alembic::AbcCoreFactory::IFactory factory;
1436  factory.setPolicy(Alembic::Abc::ErrorHandler::kQuietNoopPolicy);
1437  archive = factory.getArchive(filepath.c_str());
1438 
1439  if (!archive.valid()) {
1440  /* avoid potential infinite update loops in viewport synchronization */
1441  filepath.clear();
1442  clear_modified();
1443  return;
1444  }
1445  }
1446 
1447  if (!objects_loaded || objects_is_modified()) {
1448  load_objects(progress);
1449  objects_loaded = true;
1450  }
1451 
1452  const chrono_t frame_time = (chrono_t)((frame - frame_offset) / frame_rate);
1453 
1454  build_caches(progress);
1455 
1456  foreach (Node *node, objects) {
1457  AlembicObject *object = static_cast<AlembicObject *>(node);
1458 
1459  if (progress.get_cancel()) {
1460  return;
1461  }
1462 
1463  /* skip constant objects */
1464  if (object->is_constant() && !object->is_modified() && !object->need_shader_update &&
1465  !scale_is_modified()) {
1466  continue;
1467  }
1468 
1469  if (object->schema_type == AlembicObject::POLY_MESH) {
1470  read_mesh(object, frame_time);
1471  }
1472  else if (object->schema_type == AlembicObject::CURVES) {
1473  read_curves(object, frame_time);
1474  }
1475  else if (object->schema_type == AlembicObject::SUBD) {
1476  read_subd(object, frame_time);
1477  }
1478 
1479  object->clear_modified();
1480  }
1481 
1482  clear_modified();
1483 }
1484 
1485 void AlembicProcedural::add_object(AlembicObject *object)
1486 {
1487  objects.push_back_slow(object);
1488  tag_objects_modified();
1489 }
1490 
1491 void AlembicProcedural::tag_update(Scene *scene)
1492 {
1494 }
1495 
1496 AlembicObject *AlembicProcedural::get_or_create_object(const ustring &path)
1497 {
1498  foreach (Node *node, objects) {
1499  AlembicObject *object = static_cast<AlembicObject *>(node);
1500 
1501  if (object->get_path() == path) {
1502  return object;
1503  }
1504  }
1505 
1506  AlembicObject *object = create_node<AlembicObject>();
1507  object->set_path(path);
1508 
1509  add_object(object);
1510 
1511  return object;
1512 }
1513 
1514 void AlembicProcedural::load_objects(Progress &progress)
1515 {
1516  unordered_map<string, AlembicObject *> object_map;
1517 
1518  foreach (Node *node, objects) {
1519  AlembicObject *object = static_cast<AlembicObject *>(node);
1520 
1521  /* only consider newly added objects */
1522  if (object->get_object() == nullptr) {
1523  object_map.insert({object->get_path().c_str(), object});
1524  }
1525  }
1526 
1527  IObject root = archive.getTop();
1528 
1529  for (size_t i = 0; i < root.getNumChildren(); ++i) {
1530  walk_hierarchy(root, root.getChildHeader(i), {}, object_map, progress);
1531  }
1532 
1533  /* Create nodes in the scene. */
1534  for (std::pair<string, AlembicObject *> pair : object_map) {
1535  AlembicObject *abc_object = pair.second;
1536 
1537  Geometry *geometry = nullptr;
1538 
1539  if (!abc_object->instance_of) {
1540  if (abc_object->schema_type == AlembicObject::CURVES) {
1541  geometry = scene_->create_node<Hair>();
1542  }
1543  else if (abc_object->schema_type == AlembicObject::POLY_MESH ||
1544  abc_object->schema_type == AlembicObject::SUBD) {
1545  geometry = scene_->create_node<Mesh>();
1546  }
1547  else {
1548  continue;
1549  }
1550 
1551  geometry->set_owner(this);
1552  geometry->name = abc_object->iobject.getName();
1553 
1554  array<Node *> used_shaders = abc_object->get_used_shaders();
1555  geometry->set_used_shaders(used_shaders);
1556  }
1557 
1558  Object *object = scene_->create_node<Object>();
1559  object->set_owner(this);
1560  object->set_geometry(geometry);
1561  object->name = abc_object->iobject.getName();
1562 
1563  abc_object->set_object(object);
1564  }
1565 
1566  /* Share geometries between instances. */
1567  foreach (Node *node, objects) {
1568  AlembicObject *abc_object = static_cast<AlembicObject *>(node);
1569 
1570  if (abc_object->instance_of) {
1571  abc_object->get_object()->set_geometry(
1572  abc_object->instance_of->get_object()->get_geometry());
1573  abc_object->schema_type = abc_object->instance_of->schema_type;
1574  }
1575  }
1576 }
1577 
1578 void AlembicProcedural::read_mesh(AlembicObject *abc_object, Abc::chrono_t frame_time)
1579 {
1580  CachedData &cached_data = abc_object->get_cached_data();
1581 
1582  /* update sockets */
1583 
1584  Object *object = abc_object->get_object();
1585  cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket());
1586 
1587  if (object->is_modified()) {
1588  object->tag_update(scene_);
1589  }
1590 
1591  /* Only update sockets for the original Geometry. */
1592  if (abc_object->instance_of) {
1593  return;
1594  }
1595 
1596  Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
1597 
1598  /* Make sure shader ids are also updated. */
1599  if (mesh->used_shaders_is_modified()) {
1600  mesh->tag_shader_modified();
1601  }
1602 
1603  cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket());
1604 
1605  cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_shader_socket());
1606 
1607  array<int3> *triangle_data = cached_data.triangles.data_for_time(frame_time).get_data_or_null();
1608  if (triangle_data) {
1609  array<int> triangles;
1610  array<bool> smooth;
1611 
1612  triangles.reserve(triangle_data->size() * 3);
1613  smooth.reserve(triangle_data->size());
1614 
1615  for (size_t i = 0; i < triangle_data->size(); ++i) {
1616  int3 tri = (*triangle_data)[i];
1617  triangles.push_back_reserved(tri.x);
1618  triangles.push_back_reserved(tri.y);
1619  triangles.push_back_reserved(tri.z);
1620  smooth.push_back_reserved(1);
1621  }
1622 
1623  mesh->set_triangles(triangles);
1624  mesh->set_smooth(smooth);
1625  }
1626 
1627  /* update attributes */
1628 
1629  update_attributes(mesh->attributes, cached_data, frame_time);
1630 
1631  /* we don't yet support arbitrary attributes, for now add vertex
1632  * coordinates as generated coordinates if requested */
1633  if (mesh->need_attribute(scene_, ATTR_STD_GENERATED)) {
1635  memcpy(
1636  attr->data_float3(), mesh->get_verts().data(), sizeof(float3) * mesh->get_verts().size());
1637  }
1638 
1639  if (mesh->is_modified()) {
1640  bool need_rebuild = mesh->triangles_is_modified();
1641  mesh->tag_update(scene_, need_rebuild);
1642  }
1643 }
1644 
1645 void AlembicProcedural::read_subd(AlembicObject *abc_object, Abc::chrono_t frame_time)
1646 {
1647  CachedData &cached_data = abc_object->get_cached_data();
1648 
1649  if (abc_object->subd_max_level_is_modified() || abc_object->subd_dicing_rate_is_modified()) {
1650  /* need to reset the current data is something changed */
1651  cached_data.invalidate_last_loaded_time();
1652  }
1653 
1654  /* Update sockets. */
1655 
1656  Object *object = abc_object->get_object();
1657  cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket());
1658 
1659  if (object->is_modified()) {
1660  object->tag_update(scene_);
1661  }
1662 
1663  /* Only update sockets for the original Geometry. */
1664  if (abc_object->instance_of) {
1665  return;
1666  }
1667 
1668  Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
1669 
1670  /* Make sure shader ids are also updated. */
1671  if (mesh->used_shaders_is_modified()) {
1672  mesh->tag_shader_modified();
1673  }
1674 
1675  /* Cycles overwrites the original triangles when computing displacement, so we always have to
1676  * repass the data if something is animated (vertices most likely) to avoid buffer overflows. */
1677  if (!cached_data.is_constant()) {
1678  cached_data.invalidate_last_loaded_time();
1679 
1680  /* remove previous triangles, if any */
1681  array<int> triangles;
1682  mesh->set_triangles(triangles);
1683  }
1684 
1686 
1687  /* Alembic is OpenSubDiv compliant, there is no option to set another subdivision type. */
1688  mesh->set_subdivision_type(Mesh::SubdivisionType::SUBDIVISION_CATMULL_CLARK);
1689  mesh->set_subd_max_level(abc_object->get_subd_max_level());
1690  mesh->set_subd_dicing_rate(abc_object->get_subd_dicing_rate());
1691 
1692  cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket());
1693 
1694  /* cached_data.shader is also used for subd_shader */
1695  cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_subd_shader_socket());
1696 
1697  cached_data.subd_start_corner.copy_to_socket(
1698  frame_time, mesh, mesh->get_subd_start_corner_socket());
1699 
1700  cached_data.subd_num_corners.copy_to_socket(
1701  frame_time, mesh, mesh->get_subd_num_corners_socket());
1702 
1703  cached_data.subd_smooth.copy_to_socket(frame_time, mesh, mesh->get_subd_smooth_socket());
1704 
1705  cached_data.subd_ptex_offset.copy_to_socket(
1706  frame_time, mesh, mesh->get_subd_ptex_offset_socket());
1707 
1708  cached_data.subd_face_corners.copy_to_socket(
1709  frame_time, mesh, mesh->get_subd_face_corners_socket());
1710 
1711  cached_data.num_ngons.copy_to_socket(frame_time, mesh, mesh->get_num_ngons_socket());
1712 
1713  cached_data.subd_creases_edge.copy_to_socket(
1714  frame_time, mesh, mesh->get_subd_creases_edge_socket());
1715 
1716  cached_data.subd_creases_weight.copy_to_socket(
1717  frame_time, mesh, mesh->get_subd_creases_weight_socket());
1718 
1719  mesh->set_num_subd_faces(mesh->get_subd_shader().size());
1720 
1721  /* Update attributes. */
1722 
1723  update_attributes(mesh->subd_attributes, cached_data, frame_time);
1724 
1725  /* we don't yet support arbitrary attributes, for now add vertex
1726  * coordinates as generated coordinates if requested */
1727  if (mesh->need_attribute(scene_, ATTR_STD_GENERATED)) {
1729  memcpy(
1730  attr->data_float3(), mesh->get_verts().data(), sizeof(float3) * mesh->get_verts().size());
1731  }
1732 
1733  if (mesh->is_modified()) {
1734  bool need_rebuild = (mesh->triangles_is_modified()) ||
1735  (mesh->subd_num_corners_is_modified()) ||
1736  (mesh->subd_shader_is_modified()) || (mesh->subd_smooth_is_modified()) ||
1737  (mesh->subd_ptex_offset_is_modified()) ||
1738  (mesh->subd_start_corner_is_modified()) ||
1739  (mesh->subd_face_corners_is_modified());
1740 
1741  mesh->tag_update(scene_, need_rebuild);
1742  }
1743 }
1744 
1745 void AlembicProcedural::read_curves(AlembicObject *abc_object, Abc::chrono_t frame_time)
1746 {
1747  CachedData &cached_data = abc_object->get_cached_data();
1748 
1749  /* update sockets */
1750 
1751  Object *object = abc_object->get_object();
1752  cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket());
1753 
1754  if (object->is_modified()) {
1755  object->tag_update(scene_);
1756  }
1757 
1758  /* Only update sockets for the original Geometry. */
1759  if (abc_object->instance_of) {
1760  return;
1761  }
1762 
1763  Hair *hair = static_cast<Hair *>(object->get_geometry());
1764 
1765  /* Make sure shader ids are also updated. */
1766  if (hair->used_shaders_is_modified()) {
1767  hair->tag_curve_shader_modified();
1768  }
1769 
1770  cached_data.curve_keys.copy_to_socket(frame_time, hair, hair->get_curve_keys_socket());
1771 
1772  cached_data.curve_radius.copy_to_socket(frame_time, hair, hair->get_curve_radius_socket());
1773 
1774  cached_data.curve_shader.copy_to_socket(frame_time, hair, hair->get_curve_shader_socket());
1775 
1776  cached_data.curve_first_key.copy_to_socket(frame_time, hair, hair->get_curve_first_key_socket());
1777 
1778  /* update attributes */
1779 
1780  update_attributes(hair->attributes, cached_data, frame_time);
1781 
1782  /* we don't yet support arbitrary attributes, for now add first keys as generated coordinates if
1783  * requested */
1784  if (hair->need_attribute(scene_, ATTR_STD_GENERATED)) {
1785  Attribute *attr_generated = hair->attributes.add(ATTR_STD_GENERATED);
1786  float3 *generated = attr_generated->data_float3();
1787 
1788  for (size_t i = 0; i < hair->num_curves(); i++) {
1789  generated[i] = hair->get_curve_keys()[hair->get_curve(i).first_key];
1790  }
1791  }
1792 
1793  const bool rebuild = (hair->curve_keys_is_modified() || hair->curve_radius_is_modified());
1794  hair->tag_update(scene_, rebuild);
1795 }
1796 
1797 void AlembicProcedural::walk_hierarchy(
1798  IObject parent,
1799  const ObjectHeader &header,
1800  MatrixSamplesData matrix_samples_data,
1801  const unordered_map<std::string, AlembicObject *> &object_map,
1802  Progress &progress)
1803 {
1804  if (progress.get_cancel()) {
1805  return;
1806  }
1807 
1808  IObject next_object;
1809 
1810  MatrixSampleMap concatenated_xform_samples;
1811 
1812  if (IXform::matches(header)) {
1813  IXform xform(parent, header.getName());
1814 
1815  IXformSchema &xs = xform.getSchema();
1816 
1817  if (xs.getNumOps() > 0) {
1818  TimeSamplingPtr ts = xs.getTimeSampling();
1819  MatrixSampleMap local_xform_samples;
1820 
1821  MatrixSampleMap *temp_xform_samples = nullptr;
1822  if (matrix_samples_data.samples == nullptr) {
1823  /* If there is no parent transforms, fill the map directly. */
1824  temp_xform_samples = &concatenated_xform_samples;
1825  }
1826  else {
1827  /* use a temporary map */
1828  temp_xform_samples = &local_xform_samples;
1829  }
1830 
1831  for (size_t i = 0; i < xs.getNumSamples(); ++i) {
1832  chrono_t sample_time = ts->getSampleTime(index_t(i));
1833  XformSample sample = xs.getValue(ISampleSelector(sample_time));
1834  temp_xform_samples->insert({sample_time, sample.getMatrix()});
1835  }
1836 
1837  if (matrix_samples_data.samples != nullptr) {
1838  concatenate_xform_samples(
1839  *matrix_samples_data.samples, local_xform_samples, concatenated_xform_samples);
1840  }
1841 
1842  matrix_samples_data.samples = &concatenated_xform_samples;
1843  matrix_samples_data.time_sampling = ts;
1844  }
1845 
1846  next_object = xform;
1847  }
1848  else if (ISubD::matches(header)) {
1849  ISubD subd(parent, header.getName());
1850 
1851  unordered_map<std::string, AlembicObject *>::const_iterator iter;
1852  iter = object_map.find(subd.getFullName());
1853 
1854  if (iter != object_map.end()) {
1855  AlembicObject *abc_object = iter->second;
1856  abc_object->iobject = subd;
1857  abc_object->schema_type = AlembicObject::SUBD;
1858 
1859  if (matrix_samples_data.samples) {
1860  abc_object->xform_samples = *matrix_samples_data.samples;
1861  abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
1862  }
1863  }
1864 
1865  next_object = subd;
1866  }
1867  else if (IPolyMesh::matches(header)) {
1868  IPolyMesh mesh(parent, header.getName());
1869 
1870  unordered_map<std::string, AlembicObject *>::const_iterator iter;
1871  iter = object_map.find(mesh.getFullName());
1872 
1873  if (iter != object_map.end()) {
1874  AlembicObject *abc_object = iter->second;
1875  abc_object->iobject = mesh;
1876  abc_object->schema_type = AlembicObject::POLY_MESH;
1877 
1878  if (matrix_samples_data.samples) {
1879  abc_object->xform_samples = *matrix_samples_data.samples;
1880  abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
1881  }
1882  }
1883 
1884  next_object = mesh;
1885  }
1886  else if (ICurves::matches(header)) {
1887  ICurves curves(parent, header.getName());
1888 
1889  unordered_map<std::string, AlembicObject *>::const_iterator iter;
1890  iter = object_map.find(curves.getFullName());
1891 
1892  if (iter != object_map.end()) {
1893  AlembicObject *abc_object = iter->second;
1894  abc_object->iobject = curves;
1895  abc_object->schema_type = AlembicObject::CURVES;
1896 
1897  if (matrix_samples_data.samples) {
1898  abc_object->xform_samples = *matrix_samples_data.samples;
1899  abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
1900  }
1901  }
1902 
1903  next_object = curves;
1904  }
1905  else if (IFaceSet::matches(header)) {
1906  // ignore the face set, it will be read along with the data
1907  }
1908  else if (IPoints::matches(header)) {
1909  // unsupported for now
1910  }
1911  else if (INuPatch::matches(header)) {
1912  // unsupported for now
1913  }
1914  else {
1915  next_object = parent.getChild(header.getName());
1916 
1917  if (next_object.isInstanceRoot()) {
1918  unordered_map<std::string, AlembicObject *>::const_iterator iter;
1919 
1920  /* Was this object asked to be rendered? */
1921  iter = object_map.find(next_object.getFullName());
1922 
1923  if (iter != object_map.end()) {
1924  AlembicObject *abc_object = iter->second;
1925 
1926  /* Only try to render an instance if the original object is also rendered. */
1927  iter = object_map.find(next_object.instanceSourcePath());
1928 
1929  if (iter != object_map.end()) {
1930  abc_object->iobject = next_object;
1931  abc_object->instance_of = iter->second;
1932 
1933  if (matrix_samples_data.samples) {
1934  abc_object->xform_samples = *matrix_samples_data.samples;
1935  abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
1936  }
1937  }
1938  }
1939  }
1940  }
1941 
1942  if (next_object.valid()) {
1943  for (size_t i = 0; i < next_object.getNumChildren(); ++i) {
1944  walk_hierarchy(
1945  next_object, next_object.getChildHeader(i), matrix_samples_data, object_map, progress);
1946  }
1947  }
1948 }
1949 
1950 void AlembicProcedural::build_caches(Progress &progress)
1951 {
1952  for (Node *node : objects) {
1953  AlembicObject *object = static_cast<AlembicObject *>(node);
1954 
1955  if (progress.get_cancel()) {
1956  return;
1957  }
1958 
1959  if (object->schema_type == AlembicObject::POLY_MESH) {
1960  if (!object->has_data_loaded()) {
1961  IPolyMesh polymesh(object->iobject, Alembic::Abc::kWrapExisting);
1962  IPolyMeshSchema schema = polymesh.getSchema();
1963  object->load_all_data(this, schema, progress);
1964  }
1965  else if (object->need_shader_update) {
1966  IPolyMesh polymesh(object->iobject, Alembic::Abc::kWrapExisting);
1967  IPolyMeshSchema schema = polymesh.getSchema();
1968  object->update_shader_attributes(schema.getArbGeomParams(), progress);
1969  }
1970  }
1971  else if (object->schema_type == AlembicObject::CURVES) {
1972  if (!object->has_data_loaded() || default_radius_is_modified() ||
1973  object->radius_scale_is_modified()) {
1974  ICurves curves(object->iobject, Alembic::Abc::kWrapExisting);
1975  ICurvesSchema schema = curves.getSchema();
1976  object->load_all_data(this, schema, progress, default_radius);
1977  }
1978  }
1979  else if (object->schema_type == AlembicObject::SUBD) {
1980  if (!object->has_data_loaded()) {
1981  ISubD subd_mesh(object->iobject, Alembic::Abc::kWrapExisting);
1982  ISubDSchema schema = subd_mesh.getSchema();
1983  object->load_all_data(this, schema, progress);
1984  }
1985  else if (object->need_shader_update) {
1986  ISubD subd_mesh(object->iobject, Alembic::Abc::kWrapExisting);
1987  ISubDSchema schema = subd_mesh.getSchema();
1988  object->update_shader_attributes(schema.getArbGeomParams(), progress);
1989  }
1990  }
1991 
1992  if (scale_is_modified() || object->get_cached_data().transforms.size() == 0) {
1993  object->setup_transform_cache(scale);
1994  }
1995  }
1996 }
1997 
1999 
2000 #endif
typedef double(DMatrix)[4][4]
struct Key Key
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE btQuaternion slerp(const btQuaternion &q1, const btQuaternion &q2, const btScalar &t)
Return the result of spherical linear interpolation betwen two quaternions.
Definition: btQuaternion.h:920
vector< AttributeRequest > requests
Definition: attribute.h:235
void add(ustring name)
Definition: attribute.cpp:770
Attribute * add(ustring name, TypeDesc type, AttributeElement element)
Definition: attribute.cpp:428
list< Attribute > attributes
Definition: attribute.h:181
bool modified
Definition: attribute.h:182
char * data()
Definition: attribute.h:77
vector< char > buffer
Definition: attribute.h:53
bool modified
Definition: attribute.h:57
float3 * data_float3()
Definition: attribute.h:86
bool need_attribute(Scene *scene, AttributeStandard std)
Definition: geometry.cpp:102
void tag_update(Scene *scene, bool rebuild)
Definition: geometry.cpp:271
AttributeSet attributes
Definition: geometry.h:81
bool get_cancel()
Definition: shader.h:80
T * data()
Definition: util_array.h:208
size_t size() const
Definition: util_array.h:203
size_t empty() const
Definition: util_array.h:198
void push_back_reserved(const T &t)
Definition: util_array.h:272
T * resize(size_t newsize)
Definition: util_array.h:150
void reserve(size_t newcapacity)
Definition: util_array.h:244
void clear()
Definition: util_array.h:188
OperationNode * node
double time
Scene scene
static ushort indices[]
static float normals[][3]
uint pos
#define CCL_NAMESPACE_END
#define make_float2(x, y)
#define make_float4(x, y, z, w)
#define make_int3(x, y, z)
#define make_float3(x, y, z)
void KERNEL_FUNCTION_FULL_NAME() shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int filter, int i, int offset, int sample)
@ ATTR_STD_UV
Definition: kernel_types.h:748
@ ATTR_STD_VERTEX_NORMAL
Definition: kernel_types.h:746
@ ATTR_STD_NONE
Definition: kernel_types.h:745
@ ATTR_STD_GENERATED
Definition: kernel_types.h:752
@ ATTR_ELEMENT_CORNER_BYTE
Definition: kernel_types.h:737
@ ATTR_ELEMENT_CORNER
Definition: kernel_types.h:736
static char * generate(GHash *messages, size_t *r_output_size)
Definition: msgfmt.c:186
static void clear(Message *msg)
Definition: msgfmt.c:294
static float lerp(float t, float a, float b)
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
static void sample(SocketReader *reader, int x, int y, float color[4])
#define I
#define SOCKET_NODE_ARRAY(name, ui_name, node_type,...)
Definition: node_type.h:281
#define SOCKET_FLOAT(name, ui_name, default_value,...)
Definition: node_type.h:204
#define SOCKET_INT(name, ui_name, default_value,...)
Definition: node_type.h:200
#define NODE_DEFINE(structname)
Definition: node_type.h:154
#define SOCKET_STRING(name, ui_name, default_value,...)
Definition: node_type.h:216
int first_key
Definition: hair.h:30
Curve get_curve(size_t i) const
Definition: hair.h:119
size_t num_curves() const
Definition: hair.h:133
float size[3]
void clear_non_sockets()
Definition: mesh.cpp:280
void set_num_subd_faces(size_t num_subd_faces_)
Definition: mesh.h:251
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=NULL)
Definition: node.h:98
bool is_modified()
Definition: node.cpp:781
ustring name
Definition: node.h:174
void set_owner(const NodeOwner *owner_)
Definition: node.cpp:770
void tag_update(Scene *scene)
Definition: object.cpp:206
ProceduralManager * procedural_manager
Definition: scene.h:250
ccl_device uchar4 color_float4_to_uchar4(float4 c)
Definition: util_color.h:46
ccl_device uchar4 color_float_to_byte(float3 c)
Definition: util_color.h:35
static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR)
CCL_NAMESPACE_BEGIN static constexpr OIIO_NAMESPACE_USING TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2)
static void transform_decompose(DecomposedTransform *decomp, const Transform *tfm)
ccl_device_inline Transform make_transform(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l)
ccl_device_inline Transform transform_scale(float3 s)
ccl_device_inline void transform_compose(Transform *tfm, const DecomposedTransform *decomp)