Blender  V3.3
BlenderFileLoader.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BlenderFileLoader.h"
8 
9 #include "BLI_utildefines.h"
10 
11 #include "BKE_global.h"
12 #include "BKE_object.h"
13 
14 #include <sstream>
15 
16 namespace Freestyle {
17 
19 {
20  _re = re;
22  _Scene = nullptr;
23  _numFacesRead = 0;
24 #if 0
25  _minEdgeSize = DBL_MAX;
26 #endif
28  _pRenderMonitor = nullptr;
29 }
30 
32 {
33  _Scene = nullptr;
34 }
35 
37 {
38  if (G.debug & G_DEBUG_FREESTYLE) {
39  cout << "\n=== Importing triangular meshes into Blender ===" << endl;
40  }
41 
42  // creation of the scene root node
43  _Scene = new NodeGroup;
44 
45  if (_re->clip_start < 0.0f) {
46  // Adjust clipping start/end and set up a Z offset when the viewport preview
47  // is used with the orthographic view. In this case, _re->clip_start is negative,
48  // while Freestyle assumes that imported mesh data are in the camera coordinate
49  // system with the view point located at origin [bug T36009].
50  _z_near = -0.001f;
53  }
54  else {
56  _z_far = -_re->clip_end;
57  _z_offset = 0.0f;
58  }
59 
60  int id = 0;
61  const eEvaluationMode eval_mode = DEG_get_mode(_depsgraph);
62 
64  ob,
69  break;
70  }
71 
72  if ((ob->base_flag & (BASE_HOLDOUT | BASE_INDIRECT_ONLY)) ||
73  (ob->visibility_flag & OB_HOLDOUT)) {
74  continue;
75  }
76 
77  if (!(BKE_object_visibility(ob, eval_mode) & OB_VISIBLE_SELF)) {
78  continue;
79  }
80 
81  Mesh *mesh = BKE_object_to_mesh(nullptr, ob, false);
82 
83  if (mesh) {
84  insertShapeNode(ob, mesh, ++id);
86  }
87  }
89 
90  // Return the built scene.
91  return _Scene;
92 }
93 
94 #define CLIPPED_BY_NEAR -1
95 #define NOT_CLIPPED 0
96 #define CLIPPED_BY_FAR 1
97 
98 // check if each vertex of a triangle (V1, V2, V3) is clipped by the near/far plane
99 // and calculate the number of triangles to be generated by clipping
100 int BlenderFileLoader::countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3])
101 {
102  float *v[3];
103  int numClipped, sum, numTris = 0;
104 
105  v[0] = v1;
106  v[1] = v2;
107  v[2] = v3;
108  numClipped = sum = 0;
109  for (int i = 0; i < 3; i++) {
110  if (v[i][2] > _z_near) {
111  clip[i] = CLIPPED_BY_NEAR;
112  numClipped++;
113  }
114  else if (v[i][2] < _z_far) {
115  clip[i] = CLIPPED_BY_FAR;
116  numClipped++;
117  }
118  else {
119  clip[i] = NOT_CLIPPED;
120  }
121 #if 0
122  if (G.debug & G_DEBUG_FREESTYLE) {
123  printf("%d %s\n",
124  i,
125  (clip[i] == NOT_CLIPPED) ? "not" : (clip[i] == CLIPPED_BY_NEAR) ? "near" : "far");
126  }
127 #endif
128  sum += clip[i];
129  }
130  switch (numClipped) {
131  case 0:
132  numTris = 1; // triangle
133  break;
134  case 1:
135  numTris = 2; // tetragon
136  break;
137  case 2:
138  if (sum == 0) {
139  numTris = 3; // pentagon
140  }
141  else {
142  numTris = 1; // triangle
143  }
144  break;
145  case 3:
146  if (ELEM(sum, 3, -3)) {
147  numTris = 0;
148  }
149  else {
150  numTris = 2; // tetragon
151  }
152  break;
153  }
154  return numTris;
155 }
156 
157 // find the intersection point C between the line segment from V1 to V2 and
158 // a clipping plane at depth Z (i.e., the Z component of C is known, while
159 // the X and Y components are unknown).
160 void BlenderFileLoader::clipLine(float v1[3], float v2[3], float c[3], float z)
161 {
162  // Order v1 and v2 by Z values to make sure that clipLine(P, Q, c, z)
163  // and clipLine(Q, P, c, z) gives exactly the same numerical result.
164  float *p, *q;
165  if (v1[2] < v2[2]) {
166  p = v1;
167  q = v2;
168  }
169  else {
170  p = v2;
171  q = v1;
172  }
173  double d[3];
174  for (int i = 0; i < 3; i++) {
175  d[i] = q[i] - p[i];
176  }
177  double t = (z - p[2]) / d[2];
178  c[0] = p[0] + t * d[0];
179  c[1] = p[1] + t * d[1];
180  c[2] = z;
181 }
182 
183 // clip the triangle (V1, V2, V3) by the near and far clipping plane and
184 // obtain a set of vertices after the clipping. The number of vertices
185 // is at most 5.
187  float triCoords[][3],
188  float v1[3],
189  float v2[3],
190  float v3[3],
191  float triNormals[][3],
192  float n1[3],
193  float n2[3],
194  float n3[3],
195  bool edgeMarks[],
196  bool em1,
197  bool em2,
198  bool em3,
199  const int clip[3])
200 {
201  float *v[3], *n[3];
202  bool em[3];
203  int i, j, k;
204 
205  v[0] = v1;
206  n[0] = n1;
207  v[1] = v2;
208  n[1] = n2;
209  v[2] = v3;
210  n[2] = n3;
211  em[0] = em1; /* edge mark of the edge between v1 and v2 */
212  em[1] = em2; /* edge mark of the edge between v2 and v3 */
213  em[2] = em3; /* edge mark of the edge between v3 and v1 */
214  k = 0;
215  for (i = 0; i < 3; i++) {
216  j = (i + 1) % 3;
217  if (clip[i] == NOT_CLIPPED) {
218  copy_v3_v3(triCoords[k], v[i]);
219  copy_v3_v3(triNormals[k], n[i]);
220  edgeMarks[k] = em[i];
221  k++;
222  if (clip[j] != NOT_CLIPPED) {
223  clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
224  copy_v3_v3(triNormals[k], n[j]);
225  edgeMarks[k] = false;
226  k++;
227  }
228  }
229  else if (clip[i] != clip[j]) {
230  if (clip[j] == NOT_CLIPPED) {
231  clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
232  copy_v3_v3(triNormals[k], n[i]);
233  edgeMarks[k] = em[i];
234  k++;
235  }
236  else {
237  clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
238  copy_v3_v3(triNormals[k], n[i]);
239  edgeMarks[k] = em[i];
240  k++;
241  clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
242  copy_v3_v3(triNormals[k], n[j]);
243  edgeMarks[k] = false;
244  k++;
245  }
246  }
247  }
248  BLI_assert(k == 2 + numTris);
249  (void)numTris; /* Ignored in release builds. */
250 }
251 
253  float v1[3],
254  float v2[3],
255  float v3[3],
256  float n1[3],
257  float n2[3],
258  float n3[3],
259  bool fm,
260  bool em1,
261  bool em2,
262  bool em3)
263 {
264  float *fv[3], *fn[3];
265 #if 0
266  float len;
267 #endif
268  unsigned int i, j;
270 
271  // initialize the bounding box by the first vertex
272  if (ls->currentIndex == 0) {
273  copy_v3_v3(ls->minBBox, v1);
274  copy_v3_v3(ls->maxBBox, v1);
275  }
276 
277  fv[0] = v1;
278  fn[0] = n1;
279  fv[1] = v2;
280  fn[1] = n2;
281  fv[2] = v3;
282  fn[2] = n3;
283  for (i = 0; i < 3; i++) {
284 
285  copy_v3_v3(ls->pv, fv[i]);
286  copy_v3_v3(ls->pn, fn[i]);
287 
288  // update the bounding box
289  for (j = 0; j < 3; j++) {
290  if (ls->minBBox[j] > ls->pv[j]) {
291  ls->minBBox[j] = ls->pv[j];
292  }
293 
294  if (ls->maxBBox[j] < ls->pv[j]) {
295  ls->maxBBox[j] = ls->pv[j];
296  }
297  }
298 
299 #if 0
300  len = len_v3v3(fv[i], fv[(i + 1) % 3]);
301  if (_minEdgeSize > len) {
302  _minEdgeSize = len;
303  }
304 #endif
305 
306  *ls->pvi = ls->currentIndex;
307  *ls->pni = ls->currentIndex;
308  *ls->pmi = ls->currentMIndex;
309 
310  ls->currentIndex += 3;
311  ls->pv += 3;
312  ls->pn += 3;
313 
314  ls->pvi++;
315  ls->pni++;
316  ls->pmi++;
317  }
318 
319  if (fm) {
320  marks |= IndexedFaceSet::FACE_MARK;
321  }
322  if (em1) {
324  }
325  if (em2) {
327  }
328  if (em3) {
330  }
331  *(ls->pm++) = marks;
332 }
333 
334 // With A, B and P indicating the three vertices of a given triangle, returns:
335 // 1 if points A and B are in the same position in the 3D space;
336 // 2 if the distance between point P and line segment AB is zero; and
337 // zero otherwise.
338 int BlenderFileLoader::testDegenerateTriangle(float v1[3], float v2[3], float v3[3])
339 {
340  const float eps = 1.0e-6;
341  const float eps_sq = eps * eps;
342 
343 #if 0
344  float area = area_tri_v3(v1, v2, v3);
345  bool verbose = (area < 1.0e-6);
346 #endif
347 
348  if (equals_v3v3(v1, v2) || equals_v3v3(v2, v3) || equals_v3v3(v1, v3)) {
349 #if 0
350  if (verbose && G.debug & G_DEBUG_FREESTYLE) {
351  printf("BlenderFileLoader::testDegenerateTriangle = 1\n");
352  }
353 #endif
354  return 1;
355  }
356  if (dist_squared_to_line_segment_v3(v1, v2, v3) < eps_sq ||
357  dist_squared_to_line_segment_v3(v2, v1, v3) < eps_sq ||
358  dist_squared_to_line_segment_v3(v3, v1, v2) < eps_sq) {
359 #if 0
360  if (verbose && G.debug & G_DEBUG_FREESTYLE) {
361  printf("BlenderFileLoader::testDegenerateTriangle = 2\n");
362  }
363 #endif
364  return 2;
365  }
366 #if 0
367  if (verbose && G.debug & G_DEBUG_FREESTYLE) {
368  printf("BlenderFileLoader::testDegenerateTriangle = 0\n");
369  }
370 #endif
371  return 0;
372 }
373 
374 static bool testEdgeMark(Mesh *me, const FreestyleEdge *fed, const MLoopTri *lt, int i)
375 {
376  MLoop *mloop = &me->mloop[lt->tri[i]];
377  MLoop *mloop_next = &me->mloop[lt->tri[(i + 1) % 3]];
378  MEdge *medge = &me->medge[mloop->e];
379 
380  if (!ELEM(mloop_next->v, medge->v1, medge->v2)) {
381  /* Not an edge in the original mesh before triangulation. */
382  return false;
383  }
384 
385  return (fed[mloop->e].flag & FREESTYLE_EDGE_MARK) != 0;
386 }
387 
389 {
390  char *name = ob->id.name + 2;
391 
392  // Compute loop triangles
393  int tottri = poly_to_tri_count(me->totpoly, me->totloop);
394  MLoopTri *mlooptri = (MLoopTri *)MEM_malloc_arrayN(tottri, sizeof(*mlooptri), __func__);
395  BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mlooptri);
396 
397  // Compute loop normals
399  const float(*lnors)[3] = nullptr;
400 
401  if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
402  lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
403  }
404 
405  // Get other mesh data
406  MVert *mvert = me->mvert;
407  MLoop *mloop = me->mloop;
408  MPoly *mpoly = me->mpoly;
411 
412  // Compute view matrix
414  float viewinv[4][4], viewmat[4][4];
415  RE_GetCameraModelMatrix(_re, ob_camera_eval, viewinv);
416  invert_m4_m4(viewmat, viewinv);
417 
418  // Compute matrix including camera transform
419  float obmat[4][4], nmat[4][4];
420  mul_m4_m4m4(obmat, viewmat, ob->obmat);
421  invert_m4_m4(nmat, obmat);
422  transpose_m4(nmat);
423 
424  // We count the number of triangles after the clipping by the near and far view
425  // planes is applied (NOTE: mesh vertices are in the camera coordinate system).
426  unsigned numFaces = 0;
427  float v1[3], v2[3], v3[3];
428  float n1[3], n2[3], n3[3], facenormal[3];
429  int clip[3];
430  for (int a = 0; a < tottri; a++) {
431  const MLoopTri *lt = &mlooptri[a];
432 
433  copy_v3_v3(v1, mvert[mloop[lt->tri[0]].v].co);
434  copy_v3_v3(v2, mvert[mloop[lt->tri[1]].v].co);
435  copy_v3_v3(v3, mvert[mloop[lt->tri[2]].v].co);
436 
437  mul_m4_v3(obmat, v1);
438  mul_m4_v3(obmat, v2);
439  mul_m4_v3(obmat, v3);
440 
441  v1[2] += _z_offset;
442  v2[2] += _z_offset;
443  v3[2] += _z_offset;
444 
445  numFaces += countClippedFaces(v1, v2, v3, clip);
446  }
447 #if 0
448  if (G.debug & G_DEBUG_FREESTYLE) {
449  cout << "numFaces " << numFaces << endl;
450  }
451 #endif
452  if (numFaces == 0) {
453  MEM_freeN(mlooptri);
454  return;
455  }
456 
457  // We allocate memory for the meshes to be imported
458  NodeGroup *currentMesh = new NodeGroup;
459  NodeShape *shape = new NodeShape;
460 
461  unsigned vSize = 3 * 3 * numFaces;
462  float *vertices = new float[vSize];
463  unsigned nSize = vSize;
464  float *normals = new float[nSize];
465  unsigned *numVertexPerFaces = new unsigned[numFaces];
466  vector<Material *> meshMaterials;
467  vector<FrsMaterial> meshFrsMaterials;
468 
470  unsigned i;
471  for (i = 0; i < numFaces; i++) {
472  faceStyle[i] = IndexedFaceSet::TRIANGLES;
473  numVertexPerFaces[i] = 3;
474  }
475 
476  IndexedFaceSet::FaceEdgeMark *faceEdgeMarks = new IndexedFaceSet::FaceEdgeMark[numFaces];
477 
478  unsigned viSize = 3 * numFaces;
479  unsigned *VIndices = new unsigned[viSize];
480  unsigned niSize = viSize;
481  unsigned *NIndices = new unsigned[niSize];
482  unsigned *MIndices = new unsigned[viSize]; // Material Indices
483 
484  struct LoaderState ls;
485  ls.pv = vertices;
486  ls.pn = normals;
487  ls.pm = faceEdgeMarks;
488  ls.pvi = VIndices;
489  ls.pni = NIndices;
490  ls.pmi = MIndices;
491  ls.currentIndex = 0;
492  ls.currentMIndex = 0;
493 
494  FrsMaterial tmpMat;
495 
496  // We parse the vlak nodes again and import meshes while applying the clipping
497  // by the near and far view planes.
498  for (int a = 0; a < tottri; a++) {
499  const MLoopTri *lt = &mlooptri[a];
500  const MPoly *mp = &mpoly[lt->poly];
501  Material *mat = BKE_object_material_get(ob, mp->mat_nr + 1);
502 
503  copy_v3_v3(v1, mvert[mloop[lt->tri[0]].v].co);
504  copy_v3_v3(v2, mvert[mloop[lt->tri[1]].v].co);
505  copy_v3_v3(v3, mvert[mloop[lt->tri[2]].v].co);
506 
507  mul_m4_v3(obmat, v1);
508  mul_m4_v3(obmat, v2);
509  mul_m4_v3(obmat, v3);
510 
511  v1[2] += _z_offset;
512  v2[2] += _z_offset;
513  v3[2] += _z_offset;
514 
515  if (_smooth && (mp->flag & ME_SMOOTH) && lnors) {
516  copy_v3_v3(n1, lnors[lt->tri[0]]);
517  copy_v3_v3(n2, lnors[lt->tri[1]]);
518  copy_v3_v3(n3, lnors[lt->tri[2]]);
519 
520  mul_mat3_m4_v3(nmat, n1);
521  mul_mat3_m4_v3(nmat, n2);
522  mul_mat3_m4_v3(nmat, n3);
523 
524  normalize_v3(n1);
525  normalize_v3(n2);
526  normalize_v3(n3);
527  }
528  else {
529  normal_tri_v3(facenormal, v3, v2, v1);
530 
531  copy_v3_v3(n1, facenormal);
532  copy_v3_v3(n2, facenormal);
533  copy_v3_v3(n3, facenormal);
534  }
535 
536  unsigned int numTris = countClippedFaces(v1, v2, v3, clip);
537  if (numTris == 0) {
538  continue;
539  }
540 
541  bool fm = (ffa) ? (ffa[lt->poly].flag & FREESTYLE_FACE_MARK) != 0 : false;
542  bool em1 = false, em2 = false, em3 = false;
543 
544  if (fed) {
545  em1 = testEdgeMark(me, fed, lt, 0);
546  em2 = testEdgeMark(me, fed, lt, 1);
547  em3 = testEdgeMark(me, fed, lt, 2);
548  }
549 
550  if (mat) {
551  tmpMat.setLine(mat->line_col[0], mat->line_col[1], mat->line_col[2], mat->line_col[3]);
552  tmpMat.setDiffuse(mat->r, mat->g, mat->b, 1.0f);
553  tmpMat.setSpecular(mat->specr, mat->specg, mat->specb, 1.0f);
554  tmpMat.setShininess(128.0f);
555  tmpMat.setPriority(mat->line_priority);
556  }
557 
558  if (meshMaterials.empty()) {
559  meshMaterials.push_back(mat);
560  meshFrsMaterials.push_back(tmpMat);
561  shape->setFrsMaterial(tmpMat);
562  }
563  else {
564  // find if the Blender material is already in the list
565  unsigned int i = 0;
566  bool found = false;
567 
568  for (vector<Material *>::iterator it = meshMaterials.begin(), itend = meshMaterials.end();
569  it != itend;
570  it++, i++) {
571  if (*it == mat) {
572  ls.currentMIndex = i;
573  found = true;
574  break;
575  }
576  }
577 
578  if (!found) {
579  meshMaterials.push_back(mat);
580  meshFrsMaterials.push_back(tmpMat);
581  ls.currentMIndex = meshFrsMaterials.size() - 1;
582  }
583  }
584 
585  float triCoords[5][3], triNormals[5][3];
586  bool edgeMarks[5]; // edgeMarks[i] is for the edge between i-th and (i+1)-th vertices
587 
588  clipTriangle(
589  numTris, triCoords, v1, v2, v3, triNormals, n1, n2, n3, edgeMarks, em1, em2, em3, clip);
590  for (i = 0; i < numTris; i++) {
591  addTriangle(&ls,
592  triCoords[0],
593  triCoords[i + 1],
594  triCoords[i + 2],
595  triNormals[0],
596  triNormals[i + 1],
597  triNormals[i + 2],
598  fm,
599  (i == 0) ? edgeMarks[0] : false,
600  edgeMarks[i + 1],
601  (i == numTris - 1) ? edgeMarks[i + 2] : false);
602  _numFacesRead++;
603  }
604  }
605 
606  MEM_freeN(mlooptri);
607 
608  // We might have several times the same vertex. We want a clean
609  // shape with no real-vertex. Here, we are making a cleaning pass.
610  float *cleanVertices = nullptr;
611  unsigned int cvSize;
612  unsigned int *cleanVIndices = nullptr;
613 
615  vertices, vSize, VIndices, viSize, &cleanVertices, &cvSize, &cleanVIndices);
616 
617  float *cleanNormals = nullptr;
618  unsigned int cnSize;
619  unsigned int *cleanNIndices = nullptr;
620 
622  normals, nSize, NIndices, niSize, &cleanNormals, &cnSize, &cleanNIndices);
623 
624  // format materials array
625  FrsMaterial **marray = new FrsMaterial *[meshFrsMaterials.size()];
626  unsigned int mindex = 0;
627  for (vector<FrsMaterial>::iterator m = meshFrsMaterials.begin(), mend = meshFrsMaterials.end();
628  m != mend;
629  ++m) {
630  marray[mindex] = new FrsMaterial(*m);
631  ++mindex;
632  }
633 
634  // deallocates memory:
635  delete[] vertices;
636  delete[] normals;
637  delete[] VIndices;
638  delete[] NIndices;
639 
640  // Fix for degenerated triangles
641  // A degenerate triangle is a triangle such that
642  // 1) A and B are in the same position in the 3D space; or
643  // 2) the distance between point P and line segment AB is zero.
644  // Only those degenerate triangles in the second form are resolved here
645  // by adding a small offset to P, whereas those in the first form are
646  // addressed later in WShape::MakeFace().
647  vector<detri_t> detriList;
648  Vec3r zero(0.0, 0.0, 0.0);
649  unsigned vi0, vi1, vi2;
650  for (i = 0; i < viSize; i += 3) {
651  detri_t detri;
652  vi0 = cleanVIndices[i];
653  vi1 = cleanVIndices[i + 1];
654  vi2 = cleanVIndices[i + 2];
655  Vec3r v0(cleanVertices[vi0], cleanVertices[vi0 + 1], cleanVertices[vi0 + 2]);
656  Vec3r v1(cleanVertices[vi1], cleanVertices[vi1 + 1], cleanVertices[vi1 + 2]);
657  Vec3r v2(cleanVertices[vi2], cleanVertices[vi2 + 1], cleanVertices[vi2 + 2]);
658  if (v0 == v1 || v0 == v2 || v1 == v2) {
659  continue; // do nothing for now
660  }
661  if (GeomUtils::distPointSegment<Vec3r>(v0, v1, v2) < 1.0e-6) {
662  detri.viP = vi0;
663  detri.viA = vi1;
664  detri.viB = vi2;
665  }
666  else if (GeomUtils::distPointSegment<Vec3r>(v1, v0, v2) < 1.0e-6) {
667  detri.viP = vi1;
668  detri.viA = vi0;
669  detri.viB = vi2;
670  }
671  else if (GeomUtils::distPointSegment<Vec3r>(v2, v0, v1) < 1.0e-6) {
672  detri.viP = vi2;
673  detri.viA = vi0;
674  detri.viB = vi1;
675  }
676  else {
677  continue;
678  }
679 
680  detri.v = zero;
681  detri.n = 0;
682  for (unsigned int j = 0; j < viSize; j += 3) {
683  if (i == j) {
684  continue;
685  }
686  vi0 = cleanVIndices[j];
687  vi1 = cleanVIndices[j + 1];
688  vi2 = cleanVIndices[j + 2];
689  Vec3r v0(cleanVertices[vi0], cleanVertices[vi0 + 1], cleanVertices[vi0 + 2]);
690  Vec3r v1(cleanVertices[vi1], cleanVertices[vi1 + 1], cleanVertices[vi1 + 2]);
691  Vec3r v2(cleanVertices[vi2], cleanVertices[vi2 + 1], cleanVertices[vi2 + 2]);
692  if (detri.viP == vi0 && (detri.viA == vi1 || detri.viB == vi1)) {
693  detri.v += (v2 - v0);
694  detri.n++;
695  }
696  else if (detri.viP == vi0 && (detri.viA == vi2 || detri.viB == vi2)) {
697  detri.v += (v1 - v0);
698  detri.n++;
699  }
700  else if (detri.viP == vi1 && (detri.viA == vi0 || detri.viB == vi0)) {
701  detri.v += (v2 - v1);
702  detri.n++;
703  }
704  else if (detri.viP == vi1 && (detri.viA == vi2 || detri.viB == vi2)) {
705  detri.v += (v0 - v1);
706  detri.n++;
707  }
708  else if (detri.viP == vi2 && (detri.viA == vi0 || detri.viB == vi0)) {
709  detri.v += (v1 - v2);
710  detri.n++;
711  }
712  else if (detri.viP == vi2 && (detri.viA == vi1 || detri.viB == vi1)) {
713  detri.v += (v0 - v2);
714  detri.n++;
715  }
716  }
717  if (detri.n > 0) {
718  detri.v.normalizeSafe();
719  }
720  detriList.push_back(detri);
721  }
722 
723  if (!detriList.empty()) {
724  vector<detri_t>::iterator v;
725  for (v = detriList.begin(); v != detriList.end(); v++) {
726  detri_t detri = (*v);
727  if (detri.n == 0) {
728  cleanVertices[detri.viP] = cleanVertices[detri.viA];
729  cleanVertices[detri.viP + 1] = cleanVertices[detri.viA + 1];
730  cleanVertices[detri.viP + 2] = cleanVertices[detri.viA + 2];
731  }
732  else if (detri.v.norm() > 0.0) {
733  cleanVertices[detri.viP] += 1.0e-5 * detri.v.x();
734  cleanVertices[detri.viP + 1] += 1.0e-5 * detri.v.y();
735  cleanVertices[detri.viP + 2] += 1.0e-5 * detri.v.z();
736  }
737  }
738  if (G.debug & G_DEBUG_FREESTYLE) {
739  printf("Warning: Object %s contains %lu degenerated triangle%s (strokes may be incorrect)\n",
740  name,
741  (long unsigned int)detriList.size(),
742  (detriList.size() > 1) ? "s" : "");
743  }
744  }
745 
746  // Create the IndexedFaceSet with the retrieved attributes
747  IndexedFaceSet *rep;
748  rep = new IndexedFaceSet(cleanVertices,
749  cvSize,
750  cleanNormals,
751  cnSize,
752  marray,
753  meshFrsMaterials.size(),
754  nullptr,
755  0,
756  numFaces,
757  numVertexPerFaces,
758  faceStyle,
759  faceEdgeMarks,
760  cleanVIndices,
761  viSize,
762  cleanNIndices,
763  niSize,
764  MIndices,
765  viSize,
766  nullptr,
767  0,
768  0);
769  // sets the id of the rep
770  rep->setId(Id(id, 0));
771  rep->setName(ob->id.name + 2);
772  rep->setLibraryPath(ob->id.lib ? ob->id.lib->filepath : "");
773 
774  const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(ls.minBBox[0], ls.minBBox[1], ls.minBBox[2]),
775  Vec3r(ls.maxBBox[0], ls.maxBBox[1], ls.maxBBox[2]));
776  rep->setBBox(bbox);
777  shape->AddRep(rep);
778 
779  currentMesh->AddChild(shape);
780  _Scene->AddChild(currentMesh);
781 }
782 
783 } /* namespace Freestyle */
typedef float(TangentPoint)[2]
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_get_layer(const struct CustomData *data, int type)
@ G_DEBUG_FREESTYLE
Definition: BKE_global.h:181
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
void BKE_mesh_recalc_looptri(const struct MLoop *mloop, const struct MPoly *mpoly, const struct MVert *mvert, int totloop, int totpoly, struct MLoopTri *mlooptri)
void BKE_mesh_calc_normals_split(struct Mesh *mesh)
Definition: mesh.cc:1911
General operations, lookup, etc. for blender objects.
void BKE_object_to_mesh_clear(struct Object *object)
Definition: object.cc:5529
@ OB_VISIBLE_SELF
Definition: BKE_object.h:150
struct Mesh * BKE_object_to_mesh(struct Depsgraph *depsgraph, struct Object *object, bool preserve_all_data_layers)
Definition: object.cc:5520
int BKE_object_visibility(const struct Object *ob, int dag_eval_mode)
#define BLI_assert(a)
Definition: BLI_assert.h:46
float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:485
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:92
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:33
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void mul_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:790
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
void transpose_m4(float R[4][4])
Definition: math_matrix.c:1377
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
#define ELEM(...)
#define NOT_CLIPPED
#define CLIPPED_BY_FAR
#define CLIPPED_BY_NEAR
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
eEvaluationMode
Definition: DEG_depsgraph.h:44
#define DEG_OBJECT_ITER_END
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
#define DEG_OBJECT_ITER_BEGIN(graph_, instance_, flag_)
@ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY
@ DEG_ITER_OBJECT_FLAG_VISIBLE
@ DEG_ITER_OBJECT_FLAG_DUPLI
@ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ CD_FREESTYLE_EDGE
@ CD_FREESTYLE_FACE
@ FREESTYLE_FACE_SMOOTHNESS_FLAG
@ BASE_INDIRECT_ONLY
@ BASE_HOLDOUT
@ FREESTYLE_EDGE_MARK
@ ME_SMOOTH
@ FREESTYLE_FACE_MARK
@ OB_HOLDOUT
_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 z
_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 BMVert * v
static T sum(const btAlignedObjectArray< T > &items)
static int verbose
Definition: cineonlib.c:29
BlenderFileLoader(Render *re, ViewLayer *view_layer, Depsgraph *depsgraph)
void clipLine(float v1[3], float v2[3], float c[3], float z)
void addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3], float n1[3], float n2[3], float n3[3], bool fm, bool em1, bool em2, bool em3)
int testDegenerateTriangle(float v1[3], float v2[3], float v3[3])
void insertShapeNode(Object *ob, Mesh *mesh, int id)
void clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3], float triNormals[][3], float n1[3], float n2[3], float n3[3], bool edgeMarks[5], bool em1, bool em2, bool em3, const int clip[3])
int countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3])
void setShininess(float s)
Definition: FrsMaterial.h:406
void setPriority(int priority)
Definition: FrsMaterial.h:411
void setDiffuse(float r, float g, float b, float a)
Definition: FrsMaterial.h:374
void setLine(float r, float g, float b, float a)
Definition: FrsMaterial.h:366
void setSpecular(float r, float g, float b, float a)
Definition: FrsMaterial.h:382
static void CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices, unsigned iISize, float **oVertices, unsigned *oVSize, unsigned **oIndices)
static const FaceEdgeMark EDGE_MARK_V2V3
static const FaceEdgeMark EDGE_MARK_V1V2
static const FaceEdgeMark FACE_MARK
static const FaceEdgeMark EDGE_MARK_V3V1
virtual void AddChild(Node *iChild)
Definition: NodeGroup.cpp:14
virtual void AddRep(Rep *iRep)
Definition: NodeShape.h:39
void setFrsMaterial(const FrsMaterial &iMaterial)
Definition: NodeShape.h:55
void setLibraryPath(const string &path)
Definition: Rep.h:150
void setId(const Id &id)
Definition: Rep.h:140
virtual void setBBox(const BBox< Vec3f > &iBox)
Definition: Rep.h:135
void setName(const string &name)
Definition: Rep.h:145
value_type x() const
Definition: VecMat.h:518
value_type z() const
Definition: VecMat.h:538
value_type y() const
Definition: VecMat.h:528
Vec< T, N > & normalizeSafe()
Definition: VecMat.h:114
value_type norm() const
Definition: VecMat.h:95
const Depsgraph * depsgraph
SyclQueue void void size_t num_bytes void
int len
Definition: draw_manager.c:108
void RE_GetCameraModelMatrix(const Render *re, const struct Object *camera, float r_modelmat[4][4])
Definition: initrender.c:205
struct Object * RE_GetCamera(Render *re)
Definition: initrender.c:150
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
#define G(x, y, z)
VecMat::Vec3< real > Vec3r
Definition: Geom.h:28
inherits from class Rep
Definition: AppCanvas.cpp:18
static unsigned c
Definition: RandGen.cpp:83
static bool testEdgeMark(Mesh *me, const FreestyleEdge *fed, const MLoopTri *lt, int i)
static unsigned a[3]
Definition: RandGen.cpp:78
static void area(int d1, int d2, int e1, int e2, float weights[2])
MutableSpan< float3 > normals
const btScalar eps
Definition: poly34.cpp:11
IndexedFaceSet::FaceEdgeMark * pm
struct Library * lib
Definition: DNA_ID.h:372
char name[66]
Definition: DNA_ID.h:378
char filepath[1024]
Definition: DNA_ID.h:461
unsigned int v1
unsigned int v2
unsigned int poly
unsigned int tri[3]
unsigned int e
unsigned int v
short mat_nr
float co[3]
float line_col[4]
struct MEdge * medge
struct MVert * mvert
struct MLoop * mloop
CustomData pdata
int totpoly
CustomData edata
int totloop
struct MPoly * mpoly
CustomData ldata
float obmat[4][4]
float clip_start
Definition: render_types.h:76
float clip_end
Definition: render_types.h:77
struct FreestyleConfig freestyle_config