Blender  V3.3
blender/mesh.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "blender/session.h"
5 #include "blender/sync.h"
6 #include "blender/util.h"
7 
8 #include "scene/camera.h"
9 #include "scene/colorspace.h"
10 #include "scene/mesh.h"
11 #include "scene/object.h"
12 #include "scene/scene.h"
13 
14 #include "subd/patch.h"
15 #include "subd/split.h"
16 
17 #include "util/algorithm.h"
18 #include "util/color.h"
19 #include "util/disjoint_set.h"
20 #include "util/foreach.h"
21 #include "util/hash.h"
22 #include "util/log.h"
23 #include "util/math.h"
24 
25 #include "mikktspace.h"
26 
28 
29 /* Tangent Space */
30 
31 struct MikkUserData {
32  MikkUserData(const BL::Mesh &b_mesh,
33  const char *layer_name,
34  const Mesh *mesh,
35  float3 *tangent,
36  float *tangent_sign)
38  {
39  const AttributeSet &attributes = (mesh->get_num_subd_faces()) ? mesh->subd_attributes :
41 
42  Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
43  vertex_normal = attr_vN->data_float3();
44 
45  if (layer_name == NULL) {
46  Attribute *attr_orco = attributes.find(ATTR_STD_GENERATED);
47 
48  if (attr_orco) {
49  orco = attr_orco->data_float3();
51  }
52  }
53  else {
54  Attribute *attr_uv = attributes.find(ustring(layer_name));
55  if (attr_uv != NULL) {
56  texface = attr_uv->data_float2();
57  }
58  }
59  }
60 
61  const Mesh *mesh;
62  int num_faces;
63 
68 
70  float *tangent_sign;
71 };
72 
74 {
75  const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
76  if (userdata->mesh->get_num_subd_faces()) {
77  return userdata->mesh->get_num_subd_faces();
78  }
79  else {
80  return userdata->mesh->num_triangles();
81  }
82 }
83 
84 static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num)
85 {
86  const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
87  if (userdata->mesh->get_num_subd_faces()) {
88  const Mesh *mesh = userdata->mesh;
89  return mesh->get_subd_num_corners()[face_num];
90  }
91  else {
92  return 3;
93  }
94 }
95 
96 static int mikk_vertex_index(const Mesh *mesh, const int face_num, const int vert_num)
97 {
98  if (mesh->get_num_subd_faces()) {
99  const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
100  return mesh->get_subd_face_corners()[face.start_corner + vert_num];
101  }
102  else {
103  return mesh->get_triangles()[face_num * 3 + vert_num];
104  }
105 }
106 
107 static int mikk_corner_index(const Mesh *mesh, const int face_num, const int vert_num)
108 {
109  if (mesh->get_num_subd_faces()) {
110  const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
111  return face.start_corner + vert_num;
112  }
113  else {
114  return face_num * 3 + vert_num;
115  }
116 }
117 
119  float P[3],
120  const int face_num,
121  const int vert_num)
122 {
123  const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
124  const Mesh *mesh = userdata->mesh;
125  const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
126  const float3 vP = mesh->get_verts()[vertex_index];
127  P[0] = vP.x;
128  P[1] = vP.y;
129  P[2] = vP.z;
130 }
131 
133  float uv[2],
134  const int face_num,
135  const int vert_num)
136 {
137  const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
138  const Mesh *mesh = userdata->mesh;
139  if (userdata->texface != NULL) {
140  const int corner_index = mikk_corner_index(mesh, face_num, vert_num);
141  float2 tfuv = userdata->texface[corner_index];
142  uv[0] = tfuv.x;
143  uv[1] = tfuv.y;
144  }
145  else if (userdata->orco != NULL) {
146  const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
147  const float3 orco_loc = userdata->orco_loc;
148  const float3 orco_size = userdata->orco_size;
149  const float3 orco = (userdata->orco[vertex_index] + orco_loc) / orco_size;
150 
151  const float2 tmp = map_to_sphere(orco);
152  uv[0] = tmp.x;
153  uv[1] = tmp.y;
154  }
155  else {
156  uv[0] = 0.0f;
157  uv[1] = 0.0f;
158  }
159 }
160 
162  float N[3],
163  const int face_num,
164  const int vert_num)
165 {
166  const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
167  const Mesh *mesh = userdata->mesh;
168  float3 vN;
169  if (mesh->get_num_subd_faces()) {
170  const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
171  if (face.smooth) {
172  const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
173  vN = userdata->vertex_normal[vertex_index];
174  }
175  else {
176  vN = face.normal(mesh);
177  }
178  }
179  else {
180  if (mesh->get_smooth()[face_num]) {
181  const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
182  vN = userdata->vertex_normal[vertex_index];
183  }
184  else {
185  const Mesh::Triangle tri = mesh->get_triangle(face_num);
186  vN = tri.compute_normal(&mesh->get_verts()[0]);
187  }
188  }
189  N[0] = vN.x;
190  N[1] = vN.y;
191  N[2] = vN.z;
192 }
193 
195  const float T[],
196  const float sign,
197  const int face_num,
198  const int vert_num)
199 {
200  MikkUserData *userdata = (MikkUserData *)context->m_pUserData;
201  const Mesh *mesh = userdata->mesh;
202  const int corner_index = mikk_corner_index(mesh, face_num, vert_num);
203  userdata->tangent[corner_index] = make_float3(T[0], T[1], T[2]);
204  if (userdata->tangent_sign != NULL) {
205  userdata->tangent_sign[corner_index] = sign;
206  }
207 }
208 
210  const BL::Mesh &b_mesh, const char *layer_name, Mesh *mesh, bool need_sign, bool active_render)
211 {
212  /* Create tangent attributes. */
213  AttributeSet &attributes = (mesh->get_num_subd_faces()) ? mesh->subd_attributes :
214  mesh->attributes;
215  Attribute *attr;
216  ustring name;
217  if (layer_name != NULL) {
218  name = ustring((string(layer_name) + ".tangent").c_str());
219  }
220  else {
221  name = ustring("orco.tangent");
222  }
223  if (active_render) {
224  attr = attributes.add(ATTR_STD_UV_TANGENT, name);
225  }
226  else {
227  attr = attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
228  }
229  float3 *tangent = attr->data_float3();
230  /* Create bitangent sign attribute. */
231  float *tangent_sign = NULL;
232  if (need_sign) {
233  Attribute *attr_sign;
234  ustring name_sign;
235  if (layer_name != NULL) {
236  name_sign = ustring((string(layer_name) + ".tangent_sign").c_str());
237  }
238  else {
239  name_sign = ustring("orco.tangent_sign");
240  }
241 
242  if (active_render) {
243  attr_sign = attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
244  }
245  else {
246  attr_sign = attributes.add(name_sign, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
247  }
248  tangent_sign = attr_sign->data_float();
249  }
250  /* Setup userdata. */
251  MikkUserData userdata(b_mesh, layer_name, mesh, tangent, tangent_sign);
252  /* Setup interface. */
253  SMikkTSpaceInterface sm_interface;
254  memset(&sm_interface, 0, sizeof(sm_interface));
255  sm_interface.m_getNumFaces = mikk_get_num_faces;
257  sm_interface.m_getPosition = mikk_get_position;
259  sm_interface.m_getNormal = mikk_get_normal;
261  /* Setup context. */
263  memset(&context, 0, sizeof(context));
264  context.m_pUserData = &userdata;
265  context.m_pInterface = &sm_interface;
266  /* Compute tangents. */
268 }
269 
270 template<typename TypeInCycles, typename GetValueAtIndex>
271 static void fill_generic_attribute(BL::Mesh &b_mesh,
272  TypeInCycles *data,
273  const BL::Attribute::domain_enum b_domain,
274  const bool subdivision,
275  const GetValueAtIndex &get_value_at_index)
276 {
277  switch (b_domain) {
278  case BL::Attribute::domain_CORNER: {
279  if (subdivision) {
280  for (BL::MeshPolygon &p : b_mesh.polygons) {
281  int n = p.loop_total();
282  for (int i = 0; i < n; i++) {
283  *data = get_value_at_index(p.loop_start() + i);
284  data++;
285  }
286  }
287  }
288  else {
289  for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
290  const int index = t.index() * 3;
291  BL::Array<int, 3> loops = t.loops();
292  data[index] = get_value_at_index(loops[0]);
293  data[index + 1] = get_value_at_index(loops[1]);
294  data[index + 2] = get_value_at_index(loops[2]);
295  }
296  }
297  break;
298  }
299  case BL::Attribute::domain_EDGE: {
300  if constexpr (std::is_same_v<TypeInCycles, uchar4>) {
301  /* uchar4 edge attributes do not exist, and averaging in place
302  * would not work. */
303  assert(0);
304  }
305  else {
306  /* Average edge attributes at vertices. */
307  const size_t num_verts = b_mesh.vertices.length();
308  vector<int> count(num_verts, 0);
309 
310  for (BL::MeshEdge &e : b_mesh.edges) {
311  BL::Array<int, 2> vertices = e.vertices();
312  TypeInCycles value = get_value_at_index(e.index());
313 
314  data[vertices[0]] += value;
315  data[vertices[1]] += value;
316  count[vertices[0]]++;
317  count[vertices[1]]++;
318  }
319 
320  for (size_t i = 0; i < num_verts; i++) {
321  if (count[i] > 1) {
322  data[i] /= (float)count[i];
323  }
324  }
325  }
326  break;
327  }
328  case BL::Attribute::domain_POINT: {
329  const int num_verts = b_mesh.vertices.length();
330  for (int i = 0; i < num_verts; i++) {
331  data[i] = get_value_at_index(i);
332  }
333  break;
334  }
335  case BL::Attribute::domain_FACE: {
336  if (subdivision) {
337  const int num_polygons = b_mesh.polygons.length();
338  for (int i = 0; i < num_polygons; i++) {
339  data[i] = get_value_at_index(i);
340  }
341  }
342  else {
343  for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
344  data[t.index()] = get_value_at_index(t.polygon_index());
345  }
346  }
347  break;
348  }
349  default: {
350  assert(false);
351  break;
352  }
353  }
354 }
355 
356 static void attr_create_motion(Mesh *mesh, BL::Attribute &b_attribute, const float motion_scale)
357 {
358  if (!(b_attribute.domain() == BL::Attribute::domain_POINT) &&
359  (b_attribute.data_type() == BL::Attribute::data_type_FLOAT_VECTOR)) {
360  return;
361  }
362 
363  BL::FloatVectorAttribute b_vector_attribute(b_attribute);
364  const int numverts = mesh->get_verts().size();
365 
366  /* Find or add attribute */
367  float3 *P = &mesh->get_verts()[0];
369 
370  if (!attr_mP) {
372  }
373 
374  /* Only export previous and next frame, we don't have any in between data. */
375  float motion_times[2] = {-1.0f, 1.0f};
376  for (int step = 0; step < 2; step++) {
377  const float relative_time = motion_times[step] * 0.5f * motion_scale;
378  float3 *mP = attr_mP->data_float3() + step * numverts;
379 
380  for (int i = 0; i < numverts; i++) {
381  mP[i] = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time;
382  }
383  }
384 }
385 
387  Mesh *mesh,
388  BL::Mesh &b_mesh,
389  const bool subdivision,
390  const bool need_motion,
391  const float motion_scale)
392 {
393  AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
394  static const ustring u_velocity("velocity");
395 
396  int attribute_index = 0;
397  int render_color_index = b_mesh.attributes.render_color_index();
398 
399  for (BL::Attribute &b_attribute : b_mesh.attributes) {
400  const ustring name{b_attribute.name().c_str()};
401  const bool is_render_color = (attribute_index++ == render_color_index);
402 
403  if (need_motion && name == u_velocity) {
404  attr_create_motion(mesh, b_attribute, motion_scale);
405  }
406 
407  if (!(mesh->need_attribute(scene, name) ||
408  (is_render_color && mesh->need_attribute(scene, ATTR_STD_VERTEX_COLOR)))) {
409  continue;
410  }
411  if (attributes.find(name)) {
412  continue;
413  }
414 
415  const BL::Attribute::domain_enum b_domain = b_attribute.domain();
416  const BL::Attribute::data_type_enum b_data_type = b_attribute.data_type();
417 
419  switch (b_domain) {
420  case BL::Attribute::domain_CORNER:
422  break;
423  case BL::Attribute::domain_POINT:
425  break;
426  case BL::Attribute::domain_EDGE:
428  break;
429  case BL::Attribute::domain_FACE:
431  break;
432  default:
433  break;
434  }
435  if (element == ATTR_ELEMENT_NONE) {
436  /* Not supported. */
437  continue;
438  }
439  switch (b_data_type) {
440  case BL::Attribute::data_type_FLOAT: {
441  BL::FloatAttribute b_float_attribute{b_attribute};
442  Attribute *attr = attributes.add(name, TypeFloat, element);
443  float *data = attr->data_float();
444  fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) {
445  return b_float_attribute.data[i].value();
446  });
447  break;
448  }
449  case BL::Attribute::data_type_BOOLEAN: {
450  BL::BoolAttribute b_bool_attribute{b_attribute};
451  Attribute *attr = attributes.add(name, TypeFloat, element);
452  float *data = attr->data_float();
453  fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) {
454  return (float)b_bool_attribute.data[i].value();
455  });
456  break;
457  }
458  case BL::Attribute::data_type_INT: {
459  BL::IntAttribute b_int_attribute{b_attribute};
460  Attribute *attr = attributes.add(name, TypeFloat, element);
461  float *data = attr->data_float();
462  fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) {
463  return (float)b_int_attribute.data[i].value();
464  });
465  break;
466  }
467  case BL::Attribute::data_type_FLOAT_VECTOR: {
468  BL::FloatVectorAttribute b_vector_attribute{b_attribute};
469  Attribute *attr = attributes.add(name, TypeVector, element);
470  float3 *data = attr->data_float3();
471  fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) {
472  BL::Array<float, 3> v = b_vector_attribute.data[i].vector();
473  return make_float3(v[0], v[1], v[2]);
474  });
475  break;
476  }
477  case BL::Attribute::data_type_BYTE_COLOR: {
478  BL::ByteColorAttribute b_color_attribute{b_attribute};
479 
480  if (element == ATTR_ELEMENT_CORNER) {
482  }
483  Attribute *attr = attributes.add(name, TypeRGBA, element);
484  if (is_render_color) {
485  attr->std = ATTR_STD_VERTEX_COLOR;
486  }
487 
489  uchar4 *data = attr->data_uchar4();
490  fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) {
491  /* Compress/encode vertex color using the sRGB curve. */
492  const float4 c = get_float4(b_color_attribute.data[i].color());
494  });
495  }
496  else {
497  float4 *data = attr->data_float4();
498  fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) {
499  BL::Array<float, 4> v = b_color_attribute.data[i].color();
500  return make_float4(v[0], v[1], v[2], v[3]);
501  });
502  }
503  break;
504  }
505  case BL::Attribute::data_type_FLOAT_COLOR: {
506  BL::FloatColorAttribute b_color_attribute{b_attribute};
507 
508  Attribute *attr = attributes.add(name, TypeRGBA, element);
509  if (is_render_color) {
510  attr->std = ATTR_STD_VERTEX_COLOR;
511  }
512 
513  float4 *data = attr->data_float4();
514  fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) {
515  BL::Array<float, 4> v = b_color_attribute.data[i].color();
516  return make_float4(v[0], v[1], v[2], v[3]);
517  });
518  break;
519  }
520  case BL::Attribute::data_type_FLOAT2: {
521  BL::Float2Attribute b_float2_attribute{b_attribute};
522  Attribute *attr = attributes.add(name, TypeFloat2, element);
523  float2 *data = attr->data_float2();
524  fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) {
525  BL::Array<float, 2> v = b_float2_attribute.data[i].vector();
526  return make_float2(v[0], v[1]);
527  });
528  break;
529  }
530  default:
531  /* Not supported. */
532  break;
533  }
534  }
535 }
536 
537 /* Create uv map attributes. */
538 static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh)
539 {
540  if (!b_mesh.uv_layers.empty()) {
541  for (BL::MeshUVLoopLayer &l : b_mesh.uv_layers) {
542  const bool active_render = l.active_render();
543  AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE;
544  ustring uv_name = ustring(l.name().c_str());
545  AttributeStandard tangent_std = (active_render) ? ATTR_STD_UV_TANGENT : ATTR_STD_NONE;
546  ustring tangent_name = ustring((string(l.name().c_str()) + ".tangent").c_str());
547 
548  /* Denotes whether UV map was requested directly. */
549  const bool need_uv = mesh->need_attribute(scene, uv_name) ||
550  mesh->need_attribute(scene, uv_std);
551  /* Denotes whether tangent was requested directly. */
552  const bool need_tangent = mesh->need_attribute(scene, tangent_name) ||
553  (active_render && mesh->need_attribute(scene, tangent_std));
554 
555  /* UV map */
556  /* NOTE: We create temporary UV layer if its needed for tangent but
557  * wasn't requested by other nodes in shaders.
558  */
559  Attribute *uv_attr = NULL;
560  if (need_uv || need_tangent) {
561  if (active_render) {
562  uv_attr = mesh->attributes.add(uv_std, uv_name);
563  }
564  else {
565  uv_attr = mesh->attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER);
566  }
567 
568  float2 *fdata = uv_attr->data_float2();
569 
570  for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
571  int3 li = get_int3(t.loops());
572  fdata[0] = get_float2(l.data[li[0]].uv());
573  fdata[1] = get_float2(l.data[li[1]].uv());
574  fdata[2] = get_float2(l.data[li[2]].uv());
575  fdata += 3;
576  }
577  }
578 
579  /* UV tangent */
580  if (need_tangent) {
581  AttributeStandard sign_std = (active_render) ? ATTR_STD_UV_TANGENT_SIGN : ATTR_STD_NONE;
582  ustring sign_name = ustring((string(l.name().c_str()) + ".tangent_sign").c_str());
583  bool need_sign = (mesh->need_attribute(scene, sign_name) ||
584  mesh->need_attribute(scene, sign_std));
585  mikk_compute_tangents(b_mesh, l.name().c_str(), mesh, need_sign, active_render);
586  }
587  /* Remove temporarily created UV attribute. */
588  if (!need_uv && uv_attr != NULL) {
589  mesh->attributes.remove(uv_attr);
590  }
591  }
592  }
595  mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true);
598  }
599  }
600 }
601 
602 static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivide_uvs)
603 {
604  if (!b_mesh.uv_layers.empty()) {
605  BL::Mesh::uv_layers_iterator l;
606  int i = 0;
607 
608  for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) {
609  bool active_render = l->active_render();
610  AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE;
611  ustring uv_name = ustring(l->name().c_str());
612  AttributeStandard tangent_std = (active_render) ? ATTR_STD_UV_TANGENT : ATTR_STD_NONE;
613  ustring tangent_name = ustring((string(l->name().c_str()) + ".tangent").c_str());
614 
615  /* Denotes whether UV map was requested directly. */
616  const bool need_uv = mesh->need_attribute(scene, uv_name) ||
617  mesh->need_attribute(scene, uv_std);
618  /* Denotes whether tangent was requested directly. */
619  const bool need_tangent = mesh->need_attribute(scene, tangent_name) ||
620  (active_render && mesh->need_attribute(scene, tangent_std));
621 
622  Attribute *uv_attr = NULL;
623 
624  /* UV map */
625  if (need_uv || need_tangent) {
626  if (active_render)
627  uv_attr = mesh->subd_attributes.add(uv_std, uv_name);
628  else
629  uv_attr = mesh->subd_attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER);
630 
631  if (subdivide_uvs) {
632  uv_attr->flags |= ATTR_SUBDIVIDED;
633  }
634 
635  float2 *fdata = uv_attr->data_float2();
636 
637  for (BL::MeshPolygon &p : b_mesh.polygons) {
638  int n = p.loop_total();
639  for (int j = 0; j < n; j++) {
640  *(fdata++) = get_float2(l->data[p.loop_start() + j].uv());
641  }
642  }
643  }
644 
645  /* UV tangent */
646  if (need_tangent) {
647  AttributeStandard sign_std = (active_render) ? ATTR_STD_UV_TANGENT_SIGN : ATTR_STD_NONE;
648  ustring sign_name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
649  bool need_sign = (mesh->need_attribute(scene, sign_name) ||
650  mesh->need_attribute(scene, sign_std));
651  mikk_compute_tangents(b_mesh, l->name().c_str(), mesh, need_sign, active_render);
652  }
653  /* Remove temporarily created UV attribute. */
654  if (!need_uv && uv_attr != NULL) {
655  mesh->subd_attributes.remove(uv_attr);
656  }
657  }
658  }
661  mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true);
663  mesh->subd_attributes.remove(ATTR_STD_GENERATED);
664  }
665  }
666 }
667 
668 /* Create vertex pointiness attributes. */
669 
670 /* Compare vertices by sum of their coordinates. */
672  public:
674  {
675  }
676 
677  bool operator()(const int &vert_idx_a, const int &vert_idx_b)
678  {
679  const float3 &vert_a = verts_[vert_idx_a];
680  const float3 &vert_b = verts_[vert_idx_b];
681  if (vert_a == vert_b) {
682  /* Special case for doubles, so we ensure ordering. */
683  return vert_idx_a > vert_idx_b;
684  }
685  const float x1 = vert_a.x + vert_a.y + vert_a.z;
686  const float x2 = vert_b.x + vert_b.y + vert_b.z;
687  return x1 < x2;
688  }
689 
690  protected:
692 };
693 
694 static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision)
695 {
697  return;
698  }
699  const int num_verts = b_mesh.vertices.length();
700  if (num_verts == 0) {
701  return;
702  }
703  /* STEP 1: Find out duplicated vertices and point duplicates to a single
704  * original vertex.
705  */
706  vector<int> sorted_vert_indeices(num_verts);
707  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
708  sorted_vert_indeices[vert_index] = vert_index;
709  }
710  VertexAverageComparator compare(mesh->get_verts());
711  sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare);
712  /* This array stores index of the original vertex for the given vertex
713  * index.
714  */
715  vector<int> vert_orig_index(num_verts);
716  for (int sorted_vert_index = 0; sorted_vert_index < num_verts; ++sorted_vert_index) {
717  const int vert_index = sorted_vert_indeices[sorted_vert_index];
718  const float3 &vert_co = mesh->get_verts()[vert_index];
719  bool found = false;
720  for (int other_sorted_vert_index = sorted_vert_index + 1; other_sorted_vert_index < num_verts;
721  ++other_sorted_vert_index) {
722  const int other_vert_index = sorted_vert_indeices[other_sorted_vert_index];
723  const float3 &other_vert_co = mesh->get_verts()[other_vert_index];
724  /* We are too far away now, we wouldn't have duplicate. */
725  if ((other_vert_co.x + other_vert_co.y + other_vert_co.z) -
726  (vert_co.x + vert_co.y + vert_co.z) >
727  3 * FLT_EPSILON) {
728  break;
729  }
730  /* Found duplicate. */
731  if (len_squared(other_vert_co - vert_co) < FLT_EPSILON) {
732  found = true;
733  vert_orig_index[vert_index] = other_vert_index;
734  break;
735  }
736  }
737  if (!found) {
738  vert_orig_index[vert_index] = vert_index;
739  }
740  }
741  /* Make sure we always points to the very first orig vertex. */
742  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
743  int orig_index = vert_orig_index[vert_index];
744  while (orig_index != vert_orig_index[orig_index]) {
745  orig_index = vert_orig_index[orig_index];
746  }
747  vert_orig_index[vert_index] = orig_index;
748  }
749  sorted_vert_indeices.free_memory();
750  /* STEP 2: Calculate vertex normals taking into account their possible
751  * duplicates which gets "welded" together.
752  */
753  vector<float3> vert_normal(num_verts, zero_float3());
754  /* First we accumulate all vertex normals in the original index. */
755  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
756  const float3 normal = get_float3(b_mesh.vertices[vert_index].normal());
757  const int orig_index = vert_orig_index[vert_index];
758  vert_normal[orig_index] += normal;
759  }
760  /* Then we normalize the accumulated result and flush it to all duplicates
761  * as well.
762  */
763  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
764  const int orig_index = vert_orig_index[vert_index];
765  vert_normal[vert_index] = normalize(vert_normal[orig_index]);
766  }
767  /* STEP 3: Calculate pointiness using single ring neighborhood. */
768  vector<int> counter(num_verts, 0);
769  vector<float> raw_data(num_verts, 0.0f);
770  vector<float3> edge_accum(num_verts, zero_float3());
771  BL::Mesh::edges_iterator e;
772  EdgeMap visited_edges;
773  int edge_index = 0;
774  memset(&counter[0], 0, sizeof(int) * counter.size());
775  for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
776  const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
777  v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
778  if (visited_edges.exists(v0, v1)) {
779  continue;
780  }
781  visited_edges.insert(v0, v1);
782  float3 co0 = get_float3(b_mesh.vertices[v0].co()), co1 = get_float3(b_mesh.vertices[v1].co());
783  float3 edge = normalize(co1 - co0);
784  edge_accum[v0] += edge;
785  edge_accum[v1] += -edge;
786  ++counter[v0];
787  ++counter[v1];
788  }
789  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
790  const int orig_index = vert_orig_index[vert_index];
791  if (orig_index != vert_index) {
792  /* Skip duplicates, they'll be overwritten later on. */
793  continue;
794  }
795  if (counter[vert_index] > 0) {
796  const float3 normal = vert_normal[vert_index];
797  const float angle = safe_acosf(dot(normal, edge_accum[vert_index] / counter[vert_index]));
798  raw_data[vert_index] = angle * M_1_PI_F;
799  }
800  else {
801  raw_data[vert_index] = 0.0f;
802  }
803  }
804  /* STEP 3: Blur vertices to approximate 2 ring neighborhood. */
805  AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
806  Attribute *attr = attributes.add(ATTR_STD_POINTINESS);
807  float *data = attr->data_float();
808  memcpy(data, &raw_data[0], sizeof(float) * raw_data.size());
809  memset(&counter[0], 0, sizeof(int) * counter.size());
810  edge_index = 0;
811  visited_edges.clear();
812  for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
813  const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
814  v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
815  if (visited_edges.exists(v0, v1)) {
816  continue;
817  }
818  visited_edges.insert(v0, v1);
819  data[v0] += raw_data[v1];
820  data[v1] += raw_data[v0];
821  ++counter[v0];
822  ++counter[v1];
823  }
824  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
825  data[vert_index] /= counter[vert_index] + 1;
826  }
827  /* STEP 4: Copy attribute to the duplicated vertices. */
828  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
829  const int orig_index = vert_orig_index[vert_index];
830  data[vert_index] = data[orig_index];
831  }
832 }
833 
834 /* The Random Per Island attribute is a random float associated with each
835  * connected component (island) of the mesh. The attribute is computed by
836  * first classifying the vertices into different sets using a Disjoint Set
837  * data structure. Then the index of the root of each vertex (Which is the
838  * representative of the set the vertex belongs to) is hashed and stored.
839  *
840  * We are using a face attribute to avoid interpolation during rendering,
841  * allowing the user to safely hash the output further. Had we used vertex
842  * attribute, the interpolation will introduce very slight variations,
843  * making the output unsafe to hash. */
845  Mesh *mesh,
846  BL::Mesh &b_mesh,
847  bool subdivision)
848 {
850  return;
851  }
852 
853  int number_of_vertices = b_mesh.vertices.length();
854  if (number_of_vertices == 0) {
855  return;
856  }
857 
858  DisjointSet vertices_sets(number_of_vertices);
859 
860  for (BL::MeshEdge &e : b_mesh.edges) {
861  vertices_sets.join(e.vertices()[0], e.vertices()[1]);
862  }
863 
864  AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
866  float *data = attribute->data_float();
867 
868  if (!subdivision) {
869  for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
870  data[t.index()] = hash_uint_to_float(vertices_sets.find(t.vertices()[0]));
871  }
872  }
873  else {
874  for (BL::MeshPolygon &p : b_mesh.polygons) {
875  data[p.index()] = hash_uint_to_float(vertices_sets.find(p.vertices()[0]));
876  }
877  }
878 }
879 
880 /* Create Mesh */
881 
882 static void create_mesh(Scene *scene,
883  Mesh *mesh,
884  BL::Mesh &b_mesh,
885  const array<Node *> &used_shaders,
886  const bool need_motion,
887  const float motion_scale,
888  const bool subdivision = false,
889  const bool subdivide_uvs = true)
890 {
891  /* count vertices and faces */
892  int numverts = b_mesh.vertices.length();
893  int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length();
894  int numtris = 0;
895  int numcorners = 0;
896  int numngons = 0;
897  bool use_loop_normals = b_mesh.use_auto_smooth() &&
898  (mesh->get_subdivision_type() != Mesh::SUBDIVISION_CATMULL_CLARK);
899 
900  /* If no faces, create empty mesh. */
901  if (numfaces == 0) {
902  return;
903  }
904 
905  if (!subdivision) {
906  numtris = numfaces;
907  }
908  else {
909  for (BL::MeshPolygon &p : b_mesh.polygons) {
910  numngons += (p.loop_total() == 4) ? 0 : 1;
911  numcorners += p.loop_total();
912  }
913  }
914 
915  /* allocate memory */
916  if (subdivision) {
917  mesh->reserve_subd_faces(numfaces, numngons, numcorners);
918  }
919 
920  mesh->reserve_mesh(numverts, numtris);
921 
922  /* create vertex coordinates and normals */
923  BL::Mesh::vertices_iterator v;
924  for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
925  mesh->add_vertex(get_float3(v->co()));
926 
927  AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
928  Attribute *attr_N = attributes.add(ATTR_STD_VERTEX_NORMAL);
929  float3 *N = attr_N->data_float3();
930 
931  for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
932  *N = get_float3(v->normal());
933  N = attr_N->data_float3();
934 
935  /* create generated coordinates from undeformed coordinates */
936  const bool need_default_tangent = (subdivision == false) && (b_mesh.uv_layers.empty()) &&
938  if (mesh->need_attribute(scene, ATTR_STD_GENERATED) || need_default_tangent) {
939  Attribute *attr = attributes.add(ATTR_STD_GENERATED);
940  attr->flags |= ATTR_SUBDIVIDED;
941 
942  float3 loc, size;
943  mesh_texture_space(b_mesh, loc, size);
944 
945  float3 *generated = attr->data_float3();
946  size_t i = 0;
947 
948  for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) {
949  generated[i++] = get_float3(v->undeformed_co()) * size - loc;
950  }
951  }
952 
953  /* create faces */
954  if (!subdivision) {
955  for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
956  BL::MeshPolygon p = b_mesh.polygons[t.polygon_index()];
957  int3 vi = get_int3(t.vertices());
958 
959  int shader = clamp(p.material_index(), 0, used_shaders.size() - 1);
960  bool smooth = p.use_smooth() || use_loop_normals;
961 
962  if (use_loop_normals) {
963  BL::Array<float, 9> loop_normals = t.split_normals();
964  for (int i = 0; i < 3; i++) {
965  N[vi[i]] = make_float3(
966  loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]);
967  }
968  }
969 
970  /* Create triangles.
971  *
972  * NOTE: Autosmooth is already taken care about.
973  */
974  mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
975  }
976  }
977  else {
978  vector<int> vi;
979 
980  for (BL::MeshPolygon &p : b_mesh.polygons) {
981  int n = p.loop_total();
982  int shader = clamp(p.material_index(), 0, used_shaders.size() - 1);
983  bool smooth = p.use_smooth() || use_loop_normals;
984 
985  vi.resize(n);
986  for (int i = 0; i < n; i++) {
987  /* NOTE: Autosmooth is already taken care about. */
988  vi[i] = b_mesh.loops[p.loop_start() + i].vertex_index();
989  }
990 
991  /* create subd faces */
992  mesh->add_subd_face(&vi[0], n, shader, smooth);
993  }
994  }
995 
996  /* Create all needed attributes.
997  * The calculate functions will check whether they're needed or not.
998  */
999  attr_create_pointiness(scene, mesh, b_mesh, subdivision);
1000  attr_create_random_per_island(scene, mesh, b_mesh, subdivision);
1001  attr_create_generic(scene, mesh, b_mesh, subdivision, need_motion, motion_scale);
1002 
1003  if (subdivision) {
1004  attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs);
1005  }
1006  else {
1007  attr_create_uv_map(scene, mesh, b_mesh);
1008  }
1009 
1010  /* For volume objects, create a matrix to transform from object space to
1011  * mesh texture space. this does not work with deformations but that can
1012  * probably only be done well with a volume grid mapping of coordinates. */
1015  Transform *tfm = attr->data_transform();
1016 
1017  float3 loc, size;
1018  mesh_texture_space(b_mesh, loc, size);
1019 
1020  *tfm = transform_translate(-loc) * transform_scale(size);
1021  }
1022 }
1023 
1025  Mesh *mesh,
1026  BObjectInfo &b_ob_info,
1027  BL::Mesh &b_mesh,
1028  const array<Node *> &used_shaders,
1029  const bool need_motion,
1030  const float motion_scale,
1031  float dicing_rate,
1032  int max_subdivisions)
1033 {
1034  BL::Object b_ob = b_ob_info.real_object;
1035 
1036  BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length() - 1]);
1037  bool subdivide_uvs = subsurf_mod.uv_smooth() != BL::SubsurfModifier::uv_smooth_NONE;
1038 
1039  create_mesh(scene, mesh, b_mesh, used_shaders, need_motion, motion_scale, true, subdivide_uvs);
1040 
1041  /* export creases */
1042  size_t num_creases = 0;
1043 
1044  for (BL::MeshEdge &e : b_mesh.edges) {
1045  if (e.crease() != 0.0f) {
1046  num_creases++;
1047  }
1048  }
1049 
1050  mesh->reserve_subd_creases(num_creases);
1051 
1052  for (BL::MeshEdge &e : b_mesh.edges) {
1053  if (e.crease() != 0.0f) {
1054  mesh->add_edge_crease(e.vertices()[0], e.vertices()[1], e.crease());
1055  }
1056  }
1057 
1058  for (BL::MeshVertexCreaseLayer &c : b_mesh.vertex_creases) {
1059  for (int i = 0; i < c.data.length(); ++i) {
1060  if (c.data[i].value() != 0.0f) {
1061  mesh->add_vertex_crease(i, c.data[i].value());
1062  }
1063  }
1064  }
1065 
1066  /* set subd params */
1067  PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
1068  float subd_dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate);
1069 
1070  mesh->set_subd_dicing_rate(subd_dicing_rate);
1071  mesh->set_subd_max_level(max_subdivisions);
1072  mesh->set_subd_objecttoworld(get_transform(b_ob.matrix_world()));
1073 }
1074 
1075 /* Sync */
1076 
1077 void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh)
1078 {
1079  /* make a copy of the shaders as the caller in the main thread still need them for syncing the
1080  * attributes */
1081  array<Node *> used_shaders = mesh->get_used_shaders();
1082 
1083  Mesh new_mesh;
1084  new_mesh.set_used_shaders(used_shaders);
1085 
1086  if (view_layer.use_surfaces) {
1087  /* Adaptive subdivision setup. Not for baking since that requires
1088  * exact mapping to the Blender mesh. */
1089  if (!scene->bake_manager->get_baking()) {
1090  new_mesh.set_subdivision_type(
1091  object_subdivision_type(b_ob_info.real_object, preview, experimental));
1092  }
1093 
1094  /* For some reason, meshes do not need this... */
1095  bool need_undeformed = new_mesh.need_attribute(scene, ATTR_STD_GENERATED);
1096  BL::Mesh b_mesh = object_to_mesh(
1097  b_data, b_ob_info, b_depsgraph, need_undeformed, new_mesh.get_subdivision_type());
1098 
1099  if (b_mesh) {
1100  /* Motion blur attribute is relative to seconds, we need it relative to frames. */
1101  const bool need_motion = object_need_motion_attribute(b_ob_info, scene);
1102  const float motion_scale = (need_motion) ?
1103  scene->motion_shutter_time() /
1104  (b_scene.render().fps() / b_scene.render().fps_base()) :
1105  0.0f;
1106 
1107  /* Sync mesh itself. */
1108  if (new_mesh.get_subdivision_type() != Mesh::SUBDIVISION_NONE)
1109  create_subd_mesh(scene,
1110  &new_mesh,
1111  b_ob_info,
1112  b_mesh,
1113  new_mesh.get_used_shaders(),
1114  need_motion,
1115  motion_scale,
1116  dicing_rate,
1117  max_subdivisions);
1118  else
1119  create_mesh(scene,
1120  &new_mesh,
1121  b_mesh,
1122  new_mesh.get_used_shaders(),
1123  need_motion,
1124  motion_scale,
1125  false);
1126 
1127  free_object_to_mesh(b_data, b_ob_info, b_mesh);
1128  }
1129  }
1130 
1131  /* update original sockets */
1132 
1134 
1135  for (const SocketType &socket : new_mesh.type->inputs) {
1136  /* Those sockets are updated in sync_object, so do not modify them. */
1137  if (socket.name == "use_motion_blur" || socket.name == "motion_steps" ||
1138  socket.name == "used_shaders") {
1139  continue;
1140  }
1141  mesh->set_value(socket, new_mesh, socket);
1142  }
1143 
1144  mesh->attributes.update(std::move(new_mesh.attributes));
1145  mesh->subd_attributes.update(std::move(new_mesh.subd_attributes));
1146 
1148 
1149  /* tag update */
1150  bool rebuild = (mesh->triangles_is_modified()) || (mesh->subd_num_corners_is_modified()) ||
1151  (mesh->subd_shader_is_modified()) || (mesh->subd_smooth_is_modified()) ||
1152  (mesh->subd_ptex_offset_is_modified()) ||
1153  (mesh->subd_start_corner_is_modified()) ||
1154  (mesh->subd_face_corners_is_modified());
1155 
1156  mesh->tag_update(scene, rebuild);
1157 }
1158 
1159 void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
1160  BObjectInfo &b_ob_info,
1161  Mesh *mesh,
1162  int motion_step)
1163 {
1164  /* Skip if no vertices were exported. */
1165  size_t numverts = mesh->get_verts().size();
1166  if (numverts == 0) {
1167  return;
1168  }
1169 
1170  /* Skip objects without deforming modifiers. this is not totally reliable,
1171  * would need a more extensive check to see which objects are animated. */
1172  BL::Mesh b_mesh(PointerRNA_NULL);
1173  if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
1174  /* get derived mesh */
1175  b_mesh = object_to_mesh(b_data, b_ob_info, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
1176  }
1177 
1178  const std::string ob_name = b_ob_info.real_object.name();
1179 
1180  /* TODO(sergey): Perform preliminary check for number of vertices. */
1181  if (b_mesh) {
1182  /* Export deformed coordinates. */
1183  /* Find attributes. */
1187  bool new_attribute = false;
1188  /* Add new attributes if they don't exist already. */
1189  if (!attr_mP) {
1191  if (attr_N)
1193 
1194  new_attribute = true;
1195  }
1196  /* Load vertex data from mesh. */
1197  float3 *mP = attr_mP->data_float3() + motion_step * numverts;
1198  float3 *mN = (attr_mN) ? attr_mN->data_float3() + motion_step * numverts : NULL;
1199  /* NOTE: We don't copy more that existing amount of vertices to prevent
1200  * possible memory corruption.
1201  */
1202  BL::Mesh::vertices_iterator v;
1203  int i = 0;
1204  for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i) {
1205  mP[i] = get_float3(v->co());
1206  if (mN)
1207  mN[i] = get_float3(v->normal());
1208  }
1209  if (new_attribute) {
1210  /* In case of new attribute, we verify if there really was any motion. */
1211  if (b_mesh.vertices.length() != numverts ||
1212  memcmp(mP, &mesh->get_verts()[0], sizeof(float3) * numverts) == 0) {
1213  /* no motion, remove attributes again */
1214  if (b_mesh.vertices.length() != numverts) {
1215  VLOG_WARNING << "Topology differs, disabling motion blur for object " << ob_name;
1216  }
1217  else {
1218  VLOG_DEBUG << "No actual deformation motion for object " << ob_name;
1219  }
1221  if (attr_mN)
1223  }
1224  else if (motion_step > 0) {
1225  VLOG_DEBUG << "Filling deformation motion for object " << ob_name;
1226  /* motion, fill up previous steps that we might have skipped because
1227  * they had no motion, but we need them anyway now */
1228  float3 *P = &mesh->get_verts()[0];
1229  float3 *N = (attr_N) ? attr_N->data_float3() : NULL;
1230  for (int step = 0; step < motion_step; step++) {
1231  memcpy(attr_mP->data_float3() + step * numverts, P, sizeof(float3) * numverts);
1232  if (attr_mN)
1233  memcpy(attr_mN->data_float3() + step * numverts, N, sizeof(float3) * numverts);
1234  }
1235  }
1236  }
1237  else {
1238  if (b_mesh.vertices.length() != numverts) {
1239  VLOG_WARNING << "Topology differs, discarding motion blur for object " << ob_name
1240  << " at time " << motion_step;
1241  memcpy(mP, &mesh->get_verts()[0], sizeof(float3) * numverts);
1242  if (mN != NULL) {
1243  memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts);
1244  }
1245  }
1246  }
1247 
1248  free_object_to_mesh(b_data, b_ob_info, b_mesh);
1249  return;
1250  }
1251 
1252  /* No deformation on this frame, copy coordinates if other frames did have it. */
1253  mesh->copy_center_to_motion_step(motion_step);
1254 }
1255 
typedef float(TangentPoint)[2]
int BKE_object_is_deform_modified(struct Scene *scene, struct Object *ob)
Definition: object.cc:4982
MINLINE float safe_acosf(float a)
void map_to_sphere(float *r_u, float *r_v, float x, float y, float z)
Definition: math_geom.c:4932
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
struct Mesh Mesh
struct Object Object
_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 x2
_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
float float4[4]
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Attribute
static void attr_create_generic(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, const bool subdivision, const bool need_motion, const float motion_scale)
static int mikk_corner_index(const Mesh *mesh, const int face_num, const int vert_num)
static void fill_generic_attribute(BL::Mesh &b_mesh, TypeInCycles *data, const BL::Attribute::domain_enum b_domain, const bool subdivision, const GetValueAtIndex &get_value_at_index)
static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], const int face_num, const int vert_num)
static void attr_create_motion(Mesh *mesh, BL::Attribute &b_attribute, const float motion_scale)
static void attr_create_random_per_island(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision)
static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num)
static int mikk_vertex_index(const Mesh *mesh, const int face_num, const int vert_num)
static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], const int face_num, const int vert_num)
static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh)
static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, const array< Node * > &used_shaders, const bool need_motion, const float motion_scale, const bool subdivision=false, const bool subdivide_uvs=true)
static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivide_uvs)
static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const float T[], const float sign, const int face_num, const int vert_num)
static void mikk_compute_tangents(const BL::Mesh &b_mesh, const char *layer_name, Mesh *mesh, bool need_sign, bool active_render)
static void create_subd_mesh(Scene *scene, Mesh *mesh, BObjectInfo &b_ob_info, BL::Mesh &b_mesh, const array< Node * > &used_shaders, const bool need_motion, const float motion_scale, float dicing_rate, int max_subdivisions)
static int mikk_get_num_faces(const SMikkTSpaceContext *context)
static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision)
static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], const int face_num, const int vert_num)
ATTR_WARN_UNUSED_RESULT const void * element
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
Attribute * add(ustring name, TypeDesc type, AttributeElement element)
void update(AttributeSet &&new_attributes)
list< Attribute > attributes
Attribute * find(ustring name) const
void remove(ustring name)
float * data_float()
uchar4 * data_uchar4()
Transform * data_transform()
float4 * data_float4()
AttributeStandard std
float3 * data_float3()
float2 * data_float2()
bool get_baking() const
Definition: bake.cpp:25
void join(size_t x, size_t y)
Definition: disjoint_set.h:40
size_t find(size_t x)
Definition: disjoint_set.h:26
void insert(int v0, int v1)
bool exists(int v0, int v1)
bool need_attribute(Scene *scene, AttributeStandard std)
void tag_update(Scene *scene, bool rebuild)
AttributeSet attributes
VertexAverageComparator(const array< float3 > &verts)
bool operator()(const int &vert_idx_a, const int &vert_idx_b)
const array< float3 > & verts_
size_t size() const
void free_memory()
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
static float4 get_float4(const BL::Array< float, 4 > &array)
static void free_object_to_mesh(BL::BlendData &, BObjectInfo &b_ob_info, BL::Mesh &mesh)
static BL::Mesh object_to_mesh(BL::BlendData &, BObjectInfo &b_ob_info, BL::Depsgraph &, bool, Mesh::SubdivisionType subdivision_type)
static float3 get_float3(const BL::Array< float, 2 > &array)
static bool object_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
static int3 get_int3(const BL::Array< int, 3 > &array)
static float2 get_float2(const BL::Array< float, 2 > &array)
static Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob, bool preview, bool experimental)
static Transform get_transform(const BL::Array< float, 16 > &array)
static void mesh_texture_space(BL::Mesh &b_mesh, float3 &loc, float3 &size)
Scene scene
static float verts[][3]
ccl_device_inline float hash_uint_to_float(uint kx)
Definition: hash.h:117
IconTextureDrawCall normal
int count
ccl_device_inline Transform transform_translate(float3 t)
ccl_device_inline Transform transform_scale(float3 s)
ccl_gpu_kernel_postfix ccl_global int * counter
AttributeStandard
Definition: kernel/types.h:612
@ ATTR_STD_GENERATED_TRANSFORM
Definition: kernel/types.h:621
@ ATTR_STD_UV
Definition: kernel/types.h:616
@ ATTR_STD_MOTION_VERTEX_NORMAL
Definition: kernel/types.h:625
@ ATTR_STD_VERTEX_NORMAL
Definition: kernel/types.h:614
@ ATTR_STD_UV_TANGENT
Definition: kernel/types.h:617
@ ATTR_STD_NONE
Definition: kernel/types.h:613
@ ATTR_STD_VERTEX_COLOR
Definition: kernel/types.h:619
@ ATTR_STD_MOTION_VERTEX_POSITION
Definition: kernel/types.h:624
@ ATTR_STD_UV_TANGENT_SIGN
Definition: kernel/types.h:618
@ ATTR_STD_POINTINESS
Definition: kernel/types.h:642
@ ATTR_STD_GENERATED
Definition: kernel/types.h:620
@ ATTR_STD_RANDOM_PER_ISLAND
Definition: kernel/types.h:643
@ ATTR_SUBDIVIDED
Definition: kernel/types.h:652
AttributeElement
Definition: kernel/types.h:597
@ ATTR_ELEMENT_NONE
Definition: kernel/types.h:598
@ ATTR_ELEMENT_CORNER_BYTE
Definition: kernel/types.h:605
@ ATTR_ELEMENT_CORNER
Definition: kernel/types.h:604
@ ATTR_ELEMENT_VERTEX
Definition: kernel/types.h:602
@ ATTR_ELEMENT_FACE
Definition: kernel/types.h:601
#define VLOG_WARNING
Definition: log.h:75
#define VLOG_DEBUG
Definition: log.h:86
ccl_device_inline float3 zero_float3()
Definition: math_float3.h:80
ccl_device_inline float len_squared(const float3 a)
Definition: math_float3.h:423
static float P(float k)
Definition: math_interp.c:25
#define N
#define T
#define make_float2(x, y)
Definition: metal/compat.h:203
#define make_float4(x, y, z, w)
Definition: metal/compat.h:205
#define make_float3(x, y, z)
Definition: metal/compat.h:204
tbool genTangSpaceDefault(const SMikkTSpaceContext *pContext)
Definition: mikktspace.c:253
static unsigned c
Definition: RandGen.cpp:83
double sign(double arg)
Definition: utility.h:250
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T clamp(const T &a, const T &min, const T &max)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
smooth(Type::FLOAT, "mask_weight")
static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR)
CCL_NAMESPACE_BEGIN static constexpr OIIO_NAMESPACE_USING TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5167
const PointerRNA PointerRNA_NULL
Definition: rna_access.c:61
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
float co[3]
Definition: bmesh_class.h:87
BL::Object real_object
float3 normal(const Mesh *mesh) const
Definition: scene/mesh.cpp:102
float3 compute_normal(const float3 *verts) const
Definition: scene/mesh.cpp:82
void reserve_subd_faces(int numfaces, int num_ngons, int numcorners)
Definition: scene/mesh.cpp:250
size_t get_num_subd_faces() const
Definition: scene/mesh.h:232
void add_edge_crease(int v0, int v1, float weight)
Definition: scene/mesh.cpp:401
void reserve_subd_creases(size_t num_creases)
Definition: scene/mesh.cpp:264
float size[3]
Triangle get_triangle(size_t i) const
Definition: scene/mesh.h:73
void copy_center_to_motion_step(const int motion_step)
Definition: scene/mesh.cpp:421
void reserve_mesh(int numverts, int numfaces)
Definition: scene/mesh.cpp:220
@ SUBDIVISION_NONE
Definition: scene/mesh.h:120
@ SUBDIVISION_CATMULL_CLARK
Definition: scene/mesh.h:122
size_t num_triangles() const
Definition: scene/mesh.h:79
void clear_non_sockets()
Definition: scene/mesh.cpp:270
void set_num_subd_faces(size_t num_subd_faces_)
Definition: scene/mesh.h:237
void add_vertex(float3 P)
Definition: scene/mesh.cpp:320
void add_vertex_crease(int v, float weight)
Definition: scene/mesh.cpp:412
void add_triangle(int v0, int v1, int v2, int shader, bool smooth)
Definition: scene/mesh.cpp:342
SubdFace get_subd_face(size_t index) const
Definition: scene/mesh.cpp:390
void add_subd_face(const int *corners, int num_corners, int shader_, bool smooth_)
Definition: scene/mesh.cpp:360
float * tangent_sign
float2 * texface
const Mesh * mesh
float3 * vertex_normal
MikkUserData(const BL::Mesh &b_mesh, const char *layer_name, const Mesh *mesh, float3 *tangent, float *tangent_sign)
float3 * orco
float3 * tangent
float3 orco_size
vector< SocketType, std::allocator< SocketType > > inputs
Definition: node_type.h:118
const NodeType * type
Definition: graph/node.h:175
void set_value(const SocketType &input, const Node &other, const SocketType &other_input)
Definition: graph/node.cpp:388
void(* m_getNormal)(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert)
Definition: mikktspace.h:61
void(* m_getPosition)(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert)
Definition: mikktspace.h:57
void(* m_getTexCoord)(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert)
Definition: mikktspace.h:65
void(* m_setTSpaceBasic)(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert)
Definition: mikktspace.h:82
int(* m_getNumFaces)(const SMikkTSpaceContext *pContext)
Definition: mikktspace.h:49
int(* m_getNumVerticesOfFace)(const SMikkTSpaceContext *pContext, const int iFace)
Definition: mikktspace.h:53
BakeManager * bake_manager
Definition: scene.h:228
float motion_shutter_time()
Definition: scene.cpp:397
ustring name
Definition: node_type.h:72
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float z
float y
float x
float max
ccl_device uchar4 color_float4_to_uchar4(float4 c)
Definition: util/color.h:33
ccl_device float4 color_linear_to_srgb_v4(float4 c)
Definition: util/color.h:296
#define M_1_PI_F
Definition: util/math.h:43