Blender  V2.93
MeshImporter.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <algorithm>
22 #include <iostream>
23 
24 /* COLLADABU_ASSERT, may be able to remove later */
25 #include "COLLADABUPlatform.h"
26 
27 #include "COLLADAFWMeshPrimitive.h"
28 #include "COLLADAFWMeshVertexData.h"
29 #include "COLLADAFWPolygons.h"
30 
31 #include "MEM_guardedalloc.h"
32 
33 #include "BKE_customdata.h"
34 #include "BKE_displist.h"
35 #include "BKE_global.h"
36 #include "BKE_lib_id.h"
37 #include "BKE_material.h"
38 #include "BKE_mesh.h"
39 #include "BKE_object.h"
40 
41 #include "BLI_edgehash.h"
42 #include "BLI_listbase.h"
43 #include "BLI_math.h"
44 #include "BLI_string.h"
45 
46 #include "ArmatureImporter.h"
47 #include "MeshImporter.h"
48 #include "collada_utils.h"
49 
50 /* get node name, or fall back to original id if not present (name is optional) */
51 template<class T> static std::string bc_get_dae_name(T *node)
52 {
53  return node->getName().empty() ? node->getOriginalId() : node->getName();
54 }
55 
57 {
58  switch (type) {
59  case COLLADAFW::MeshPrimitive::LINES:
60  return "LINES";
61  case COLLADAFW::MeshPrimitive::LINE_STRIPS:
62  return "LINESTRIPS";
63  case COLLADAFW::MeshPrimitive::POLYGONS:
64  return "POLYGONS";
65  case COLLADAFW::MeshPrimitive::POLYLIST:
66  return "POLYLIST";
67  case COLLADAFW::MeshPrimitive::TRIANGLES:
68  return "TRIANGLES";
69  case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
70  return "TRIANGLE_FANS";
71  case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
72  return "TRIANGLE_STRIPS";
73  case COLLADAFW::MeshPrimitive::POINTS:
74  return "POINTS";
75  case COLLADAFW::MeshPrimitive::UNDEFINED_PRIMITIVE_TYPE:
76  return "UNDEFINED_PRIMITIVE_TYPE";
77  }
78  return "UNKNOWN";
79 }
80 
81 static const char *bc_geomTypeToStr(COLLADAFW::Geometry::GeometryType type)
82 {
83  switch (type) {
84  case COLLADAFW::Geometry::GEO_TYPE_MESH:
85  return "MESH";
86  case COLLADAFW::Geometry::GEO_TYPE_SPLINE:
87  return "SPLINE";
88  case COLLADAFW::Geometry::GEO_TYPE_CONVEX_MESH:
89  return "CONVEX_MESH";
90  case COLLADAFW::Geometry::GEO_TYPE_UNKNOWN:
91  default:
92  return "UNKNOWN";
93  }
94 }
95 
96 UVDataWrapper::UVDataWrapper(COLLADAFW::MeshVertexData &vdata) : mVData(&vdata)
97 {
98 }
99 
100 #ifdef COLLADA_DEBUG
101 void WVDataWrapper::print()
102 {
103  fprintf(stderr, "UVs:\n");
104  switch (mVData->getType()) {
105  case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: {
106  COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
107  if (values->getCount()) {
108  for (int i = 0; i < values->getCount(); i += 2) {
109  fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i + 1]);
110  }
111  }
112  } break;
113  case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: {
114  COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
115  if (values->getCount()) {
116  for (int i = 0; i < values->getCount(); i += 2) {
117  fprintf(stderr, "%.1f, %.1f\n", (float)(*values)[i], (float)(*values)[i + 1]);
118  }
119  }
120  } break;
121  }
122  fprintf(stderr, "\n");
123 }
124 #endif
125 
126 void UVDataWrapper::getUV(int uv_index, float *uv)
127 {
128  int stride = mVData->getStride(0);
129  if (stride == 0) {
130  stride = 2;
131  }
132 
133  switch (mVData->getType()) {
134  case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: {
135  COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
136  if (values->empty()) {
137  return;
138  }
139  uv[0] = (*values)[uv_index * stride];
140  uv[1] = (*values)[uv_index * stride + 1];
141 
142  } break;
143  case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: {
144  COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
145  if (values->empty()) {
146  return;
147  }
148  uv[0] = (float)(*values)[uv_index * stride];
149  uv[1] = (float)(*values)[uv_index * stride + 1];
150 
151  } break;
152  case COLLADAFW::MeshVertexData::DATA_TYPE_UNKNOWN:
153  default:
154  fprintf(stderr, "MeshImporter.getUV(): unknown data type\n");
155  }
156 }
157 
158 VCOLDataWrapper::VCOLDataWrapper(COLLADAFW::MeshVertexData &vdata) : mVData(&vdata)
159 {
160 }
161 
162 template<typename T>
163 static void colladaAddColor(T values, MLoopCol *mloopcol, int v_index, int stride)
164 {
165  if (values->empty() || values->getCount() < (v_index + 1) * stride) {
166  fprintf(stderr,
167  "VCOLDataWrapper.getvcol(): Out of Bounds error: index %d points outside value "
168  "list of length %zd (with stride=%d) \n",
169  v_index,
170  values->getCount(),
171  stride);
172  return;
173  }
174 
175  mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]);
176  mloopcol->g = unit_float_to_uchar_clamp((*values)[v_index * stride + 1]);
177  mloopcol->b = unit_float_to_uchar_clamp((*values)[v_index * stride + 2]);
178  if (stride == 4) {
179  mloopcol->a = unit_float_to_uchar_clamp((*values)[v_index * stride + 3]);
180  }
181 }
182 
183 void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
184 {
185  int stride = mVData->getStride(0);
186  if (stride == 0) {
187  stride = 3;
188  }
189 
190  switch (mVData->getType()) {
191  case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: {
192  COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
193  colladaAddColor<COLLADAFW::ArrayPrimitiveType<float> *>(values, mloopcol, v_index, stride);
194  } break;
195 
196  case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: {
197  COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
198  colladaAddColor<COLLADAFW::ArrayPrimitiveType<double> *>(values, mloopcol, v_index, stride);
199  } break;
200 
201  default:
202  fprintf(stderr, "VCOLDataWrapper.getvcol(): unknown data type\n");
203  }
204 }
205 
207  UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer)
208  : unitconverter(unitconv),
209  m_bmain(bmain),
210  scene(sce),
211  view_layer(view_layer),
212  armature_importer(arm)
213 {
214  /* pass */
215 }
216 
217 bool MeshImporter::set_poly_indices(
218  MPoly *mpoly, MLoop *mloop, int loop_index, const unsigned int *indices, int loop_count)
219 {
220  mpoly->loopstart = loop_index;
221  mpoly->totloop = loop_count;
222  bool broken_loop = false;
223  for (int index = 0; index < loop_count; index++) {
224 
225  /* Test if loop defines a hole */
226  if (!broken_loop) {
227  for (int i = 0; i < index; i++) {
228  if (indices[i] == indices[index]) {
229  /* duplicate index -> not good */
230  broken_loop = true;
231  }
232  }
233  }
234 
235  mloop->v = indices[index];
236  mloop++;
237  }
238  return broken_loop;
239 }
240 
241 void MeshImporter::set_vcol(MLoopCol *mloopcol,
242  VCOLDataWrapper &vob,
243  int loop_index,
244  COLLADAFW::IndexList &index_list,
245  int count)
246 {
247  int index;
248  for (index = 0; index < count; index++, mloopcol++) {
249  int v_index = index_list.getIndex(index + loop_index);
250  vob.get_vcol(v_index, mloopcol);
251  }
252 }
253 
254 void MeshImporter::set_face_uv(MLoopUV *mloopuv,
255  UVDataWrapper &uvs,
256  int start_index,
257  COLLADAFW::IndexList &index_list,
258  int count)
259 {
260  /* per face vertex indices, this means for quad we have 4 indices, not 8 */
261  COLLADAFW::UIntValuesArray &indices = index_list.getIndices();
262 
263  for (int index = 0; index < count; index++) {
264  int uv_index = indices[index + start_index];
265  uvs.getUV(uv_index, mloopuv[index].uv);
266  }
267 }
268 
269 #ifdef COLLADA_DEBUG
270 void MeshImporter::print_index_list(COLLADAFW::IndexList &index_list)
271 {
272  fprintf(stderr, "Index list for \"%s\":\n", index_list.getName().c_str());
273  for (int i = 0; i < index_list.getIndicesCount(); i += 2) {
274  fprintf(stderr, "%u, %u\n", index_list.getIndex(i), index_list.getIndex(i + 1));
275  }
276  fprintf(stderr, "\n");
277 }
278 #endif
279 
280 /* checks if mesh has supported primitive types: lines, polylist, triangles, triangle_fans */
281 bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh)
282 {
283  COLLADAFW::MeshPrimitiveArray &prim_arr = mesh->getMeshPrimitives();
284 
285  const std::string &name = bc_get_dae_name(mesh);
286 
287  for (unsigned int i = 0; i < prim_arr.getCount(); i++) {
288 
289  COLLADAFW::MeshPrimitive *mp = prim_arr[i];
290  COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();
291 
292  const char *type_str = bc_primTypeToStr(type);
293 
294  /* OpenCollada passes POLYGONS type for <polylist> */
295  if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
296 
297  COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
298  COLLADAFW::Polygons::VertexCountArray &vca = mpvc->getGroupedVerticesVertexCountArray();
299 
300  int hole_count = 0;
301  int nonface_count = 0;
302 
303  for (unsigned int j = 0; j < vca.getCount(); j++) {
304  int count = vca[j];
305  if (abs(count) < 3) {
306  nonface_count++;
307  }
308 
309  if (count < 0) {
310  hole_count++;
311  }
312  }
313 
314  if (hole_count > 0) {
315  fprintf(stderr,
316  "WARNING: Primitive %s in %s: %d holes not imported (unsupported)\n",
317  type_str,
318  name.c_str(),
319  hole_count);
320  }
321 
322  if (nonface_count > 0) {
323  fprintf(stderr,
324  "WARNING: Primitive %s in %s: %d faces with vertex count < 3 (rejected)\n",
325  type_str,
326  name.c_str(),
327  nonface_count);
328  }
329  }
330 
331  else if (type == COLLADAFW::MeshPrimitive::LINES) {
332  /* TODO: Add Checker for line syntax here */
333  }
334 
335  else if (type != COLLADAFW::MeshPrimitive::TRIANGLES &&
336  type != COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
337  fprintf(stderr, "ERROR: Primitive type %s is not supported.\n", type_str);
338  return false;
339  }
340  }
341 
342  return true;
343 }
344 
345 void MeshImporter::read_vertices(COLLADAFW::Mesh *mesh, Mesh *me)
346 {
347  /* vertices */
348  COLLADAFW::MeshVertexData &pos = mesh->getPositions();
349  if (pos.empty()) {
350  return;
351  }
352 
353  int stride = pos.getStride(0);
354  if (stride == 0) {
355  stride = 3;
356  }
357 
358  me->totvert = pos.getFloatValues()->getCount() / stride;
359  me->mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, nullptr, me->totvert);
360 
361  MVert *mvert;
362  int i;
363 
364  for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
365  get_vector(mvert->co, pos, i, stride);
366  }
367 }
368 
369 /* =====================================================================
370  * condition 1: The Primitive has normals
371  * condition 2: The number of normals equals the number of faces.
372  * return true if both conditions apply.
373  * return false otherwise.
374  * ===================================================================== */
375 bool MeshImporter::primitive_has_useable_normals(COLLADAFW::MeshPrimitive *mp)
376 {
377 
378  bool has_useable_normals = false;
379 
380  int normals_count = mp->getNormalIndices().getCount();
381  if (normals_count > 0) {
382  int index_count = mp->getPositionIndices().getCount();
383  if (index_count == normals_count) {
384  has_useable_normals = true;
385  }
386  else {
387  fprintf(stderr,
388  "Warning: Number of normals %d is different from the number of vertices %d, "
389  "skipping normals\n",
390  normals_count,
391  index_count);
392  }
393  }
394 
395  return has_useable_normals;
396 }
397 
398 /* =====================================================================
399  * Assume that only TRIANGLES, TRIANGLE_FANS, POLYLIST and POLYGONS
400  * have faces. (to be verified)
401  * ===================================================================== */
402 bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp)
403 {
404 
405  bool has_faces = false;
406  int type = mp->getPrimitiveType();
407  switch (type) {
408  case COLLADAFW::MeshPrimitive::TRIANGLES:
409  case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
410  case COLLADAFW::MeshPrimitive::POLYLIST:
411  case COLLADAFW::MeshPrimitive::POLYGONS: {
412  has_faces = true;
413  break;
414  }
415  default: {
416  has_faces = false;
417  break;
418  }
419  }
420  return has_faces;
421 }
422 
423 static std::string extract_vcolname(const COLLADAFW::String &collada_id)
424 {
425  std::string colname = collada_id;
426  int spos = colname.find("-mesh-colors-");
427  if (spos != std::string::npos) {
428  colname = colname.substr(spos + 13);
429  }
430  return colname;
431 }
432 
433 /* =================================================================
434  * Return the number of faces by summing up
435  * the face-counts of the parts.
436  * hint: This is done because `mesh->getFacesCount()` does
437  * count loose edges as extra faces, which is not what we want here.
438  * ================================================================= */
439 void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
440 {
441  COLLADAFW::MeshPrimitiveArray &prim_arr = collada_mesh->getMeshPrimitives();
442  int total_poly_count = 0;
443  int total_loop_count = 0;
444 
445  /* collect edge_count and face_count from all parts */
446  for (int i = 0; i < prim_arr.getCount(); i++) {
447  COLLADAFW::MeshPrimitive *mp = prim_arr[i];
448  int type = mp->getPrimitiveType();
449  switch (type) {
450  case COLLADAFW::MeshPrimitive::TRIANGLES:
451  case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
452  case COLLADAFW::MeshPrimitive::POLYLIST:
453  case COLLADAFW::MeshPrimitive::POLYGONS: {
454  COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
455  size_t prim_poly_count = mpvc->getFaceCount();
456 
457  size_t prim_loop_count = 0;
458  for (int index = 0; index < prim_poly_count; index++) {
459  int vcount = get_vertex_count(mpvc, index);
460  if (vcount > 0) {
461  prim_loop_count += vcount;
462  total_poly_count++;
463  }
464  else {
465  /* TODO: this is a hole and not another polygon! */
466  }
467  }
468 
469  total_loop_count += prim_loop_count;
470 
471  break;
472  }
473  default:
474  break;
475  }
476  }
477 
478  /* Add the data containers */
479  if (total_poly_count > 0) {
480  me->totpoly = total_poly_count;
481  me->totloop = total_loop_count;
483  &me->pdata, CD_MPOLY, CD_CALLOC, nullptr, me->totpoly);
485  &me->ldata, CD_MLOOP, CD_CALLOC, nullptr, me->totloop);
486 
487  unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount();
488  for (int i = 0; i < totuvset; i++) {
489  if (collada_mesh->getUVCoords().getLength(i) == 0) {
490  totuvset = 0;
491  break;
492  }
493  }
494 
495  if (totuvset > 0) {
496  for (int i = 0; i < totuvset; i++) {
497  COLLADAFW::MeshVertexData::InputInfos *info =
498  collada_mesh->getUVCoords().getInputInfosArray()[i];
499  COLLADAFW::String &uvname = info->mName;
500  /* Allocate space for UV_data */
502  &me->ldata, CD_MLOOPUV, CD_DEFAULT, nullptr, me->totloop, uvname.c_str());
503  }
504  /* activate the first uv map */
506  }
507 
508  int totcolset = collada_mesh->getColors().getInputInfosArray().getCount();
509  if (totcolset > 0) {
510  for (int i = 0; i < totcolset; i++) {
511  COLLADAFW::MeshVertexData::InputInfos *info =
512  collada_mesh->getColors().getInputInfosArray()[i];
513  COLLADAFW::String colname = extract_vcolname(info->mName);
515  &me->ldata, CD_MLOOPCOL, CD_DEFAULT, nullptr, me->totloop, colname.c_str());
516  }
518  }
519  }
520 }
521 
522 unsigned int MeshImporter::get_vertex_count(COLLADAFW::Polygons *mp, int index)
523 {
524  int type = mp->getPrimitiveType();
525  int result;
526  switch (type) {
527  case COLLADAFW::MeshPrimitive::TRIANGLES:
528  case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: {
529  result = 3;
530  break;
531  }
532  case COLLADAFW::MeshPrimitive::POLYLIST:
533  case COLLADAFW::MeshPrimitive::POLYGONS: {
534  result = mp->getGroupedVerticesVertexCountArray()[index];
535  break;
536  }
537  default: {
538  result = -1;
539  break;
540  }
541  }
542  return result;
543 }
544 
545 unsigned int MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh)
546 {
547  COLLADAFW::MeshPrimitiveArray &prim_arr = mesh->getMeshPrimitives();
548  int loose_edge_count = 0;
549 
550  /* collect edge_count and face_count from all parts */
551  for (int i = 0; i < prim_arr.getCount(); i++) {
552  COLLADAFW::MeshPrimitive *mp = prim_arr[i];
553  int type = mp->getPrimitiveType();
554  switch (type) {
555  case COLLADAFW::MeshPrimitive::LINES: {
556  size_t prim_totface = mp->getFaceCount();
557  loose_edge_count += prim_totface;
558  break;
559  }
560  default:
561  break;
562  }
563  }
564  return loose_edge_count;
565 }
566 
567 /* =================================================================
568  * This function is copied from source/blender/editors/mesh/mesh_data.c
569  *
570  * TODO: (As discussed with sergey-) :
571  * Maybe move this function to blenderkernel/intern/mesh.c
572  * and add definition to BKE_mesh.c
573  * ================================================================= */
574 void MeshImporter::mesh_add_edges(Mesh *mesh, int len)
575 {
576  CustomData edata;
577  MEdge *medge;
578  int totedge;
579 
580  if (len == 0) {
581  return;
582  }
583 
584  totedge = mesh->totedge + len;
585 
586  /* update customdata */
587  CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge);
588  CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
589 
590  if (!CustomData_has_layer(&edata, CD_MEDGE)) {
591  CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, nullptr, totedge);
592  }
593 
594  CustomData_free(&mesh->edata, mesh->totedge);
595  mesh->edata = edata;
596  BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */
597 
598  /* set default flags */
599  medge = &mesh->medge[mesh->totedge];
600  for (int i = 0; i < len; i++, medge++) {
601  medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT;
602  }
603 
604  mesh->totedge = totedge;
605 }
606 
607 /* =================================================================
608  * Read all loose edges.
609  * Important: This function assumes that all edges from existing
610  * faces have already been generated and added to me->medge
611  * So this function MUST be called after read_faces() (see below)
612  * ================================================================= */
613 void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me)
614 {
615  unsigned int loose_edge_count = get_loose_edge_count(mesh);
616  if (loose_edge_count > 0) {
617 
618  unsigned int face_edge_count = me->totedge;
619  /* unsigned int total_edge_count = loose_edge_count + face_edge_count; */ /* UNUSED */
620 
621  mesh_add_edges(me, loose_edge_count);
622  MEdge *med = me->medge + face_edge_count;
623 
624  COLLADAFW::MeshPrimitiveArray &prim_arr = mesh->getMeshPrimitives();
625 
626  for (int index = 0; index < prim_arr.getCount(); index++) {
627  COLLADAFW::MeshPrimitive *mp = prim_arr[index];
628 
629  int type = mp->getPrimitiveType();
630  if (type == COLLADAFW::MeshPrimitive::LINES) {
631  unsigned int edge_count = mp->getFaceCount();
632  unsigned int *indices = mp->getPositionIndices().getData();
633 
634  for (int j = 0; j < edge_count; j++, med++) {
635  med->bweight = 0;
636  med->crease = 0;
637  med->flag |= ME_LOOSEEDGE;
638  med->v1 = indices[2 * j];
639  med->v2 = indices[2 * j + 1];
640  }
641  }
642  }
643  }
644 }
645 
646 /* =======================================================================
647  * Read all faces from TRIANGLES, TRIANGLE_FANS, POLYLIST, POLYGON
648  * Important: This function MUST be called before read_lines()
649  * Otherwise we will lose all edges from faces (see read_lines() above)
650  *
651  * TODO: import uv set names
652  * ======================================================================== */
653 void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
654 {
655  unsigned int i;
656 
657  allocate_poly_data(collada_mesh, me);
658 
659  UVDataWrapper uvs(collada_mesh->getUVCoords());
660  VCOLDataWrapper vcol(collada_mesh->getColors());
661 
662  MPoly *mpoly = me->mpoly;
663  MLoop *mloop = me->mloop;
664  int loop_index = 0;
665 
666  MaterialIdPrimitiveArrayMap mat_prim_map;
667 
668  COLLADAFW::MeshPrimitiveArray &prim_arr = collada_mesh->getMeshPrimitives();
669  COLLADAFW::MeshVertexData &nor = collada_mesh->getNormals();
670 
671  for (i = 0; i < prim_arr.getCount(); i++) {
672 
673  COLLADAFW::MeshPrimitive *mp = prim_arr[i];
674 
675  /* faces */
676  size_t prim_totpoly = mp->getFaceCount();
677  unsigned int *position_indices = mp->getPositionIndices().getData();
678  unsigned int *normal_indices = mp->getNormalIndices().getData();
679 
680  bool mp_has_normals = primitive_has_useable_normals(mp);
681  bool mp_has_faces = primitive_has_faces(mp);
682 
683  int collada_meshtype = mp->getPrimitiveType();
684 
685  /* since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive */
686  Primitive prim = {mpoly, 0};
687 
688  /* If MeshPrimitive is TRIANGLE_FANS we split it into triangles
689  * The first triangle-fan vertex will be the first vertex in every triangle
690  * XXX The proper function of TRIANGLE_FANS is not tested!!!
691  * XXX In particular the handling of the normal_indices looks very wrong to me */
692  if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
693  unsigned int grouped_vertex_count = mp->getGroupedVertexElementsCount();
694  for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) {
695  unsigned int first_vertex = position_indices[0]; /* Store first trifan vertex */
696  unsigned int first_normal = normal_indices[0]; /* Store first trifan vertex normal */
697  unsigned int vertex_count = mp->getGroupedVerticesVertexCount(group_index);
698 
699  for (unsigned int vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++) {
700  /* For each triangle store indices of its 3 vertices */
701  unsigned int triangle_vertex_indices[3] = {
702  first_vertex, position_indices[1], position_indices[2]};
703  set_poly_indices(mpoly, mloop, loop_index, triangle_vertex_indices, 3);
704 
705  if (mp_has_normals) { /* vertex normals, same implementation as for the triangles */
706  /* The same for vertices normals. */
707  unsigned int vertex_normal_indices[3] = {
708  first_normal, normal_indices[1], normal_indices[2]};
709  if (!is_flat_face(vertex_normal_indices, nor, 3)) {
710  mpoly->flag |= ME_SMOOTH;
711  }
712  normal_indices++;
713  }
714 
715  mpoly++;
716  mloop += 3;
717  loop_index += 3;
718  prim.totpoly++;
719  }
720 
721  /* Moving cursor to the next triangle fan. */
722  if (mp_has_normals) {
723  normal_indices += 2;
724  }
725 
726  position_indices += 2;
727  }
728  }
729 
730  if (collada_meshtype == COLLADAFW::MeshPrimitive::POLYLIST ||
731  collada_meshtype == COLLADAFW::MeshPrimitive::POLYGONS ||
732  collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLES) {
733  COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
734  unsigned int start_index = 0;
735 
736  COLLADAFW::IndexListArray &index_list_array_uvcoord = mp->getUVCoordIndicesArray();
737  COLLADAFW::IndexListArray &index_list_array_vcolor = mp->getColorIndicesArray();
738 
739  int invalid_loop_holes = 0;
740  for (unsigned int j = 0; j < prim_totpoly; j++) {
741 
742  /* Vertices in polygon: */
743  int vcount = get_vertex_count(mpvc, j);
744  if (vcount < 0) {
745  continue; /* TODO: add support for holes */
746  }
747 
748  bool broken_loop = set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount);
749  if (broken_loop) {
750  invalid_loop_holes += 1;
751  }
752 
753  for (unsigned int uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount();
754  uvset_index++) {
755  /* get mtface by face index and uv set index */
756  COLLADAFW::IndexList &index_list = *index_list_array_uvcoord[uvset_index];
758  &me->ldata, CD_MLOOPUV, index_list.getName().c_str());
759  if (mloopuv == nullptr) {
760  fprintf(stderr,
761  "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].\n",
762  me->id.name,
763  index_list.getName().c_str());
764  }
765  else {
766  set_face_uv(mloopuv + loop_index,
767  uvs,
768  start_index,
769  *index_list_array_uvcoord[uvset_index],
770  vcount);
771  }
772  }
773 
774  if (mp_has_normals) {
775  if (!is_flat_face(normal_indices, nor, vcount)) {
776  mpoly->flag |= ME_SMOOTH;
777  }
778  }
779 
780  if (mp->hasColorIndices()) {
781  int vcolor_count = index_list_array_vcolor.getCount();
782 
783  for (unsigned int vcolor_index = 0; vcolor_index < vcolor_count; vcolor_index++) {
784 
785  COLLADAFW::IndexList &color_index_list = *mp->getColorIndices(vcolor_index);
786  COLLADAFW::String colname = extract_vcolname(color_index_list.getName());
788  &me->ldata, CD_MLOOPCOL, colname.c_str());
789  if (mloopcol == nullptr) {
790  fprintf(stderr,
791  "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n",
792  me->id.name,
793  color_index_list.getName().c_str());
794  }
795  else {
796  set_vcol(mloopcol + loop_index, vcol, start_index, color_index_list, vcount);
797  }
798  }
799  }
800 
801  mpoly++;
802  mloop += vcount;
803  loop_index += vcount;
804  start_index += vcount;
805  prim.totpoly++;
806 
807  if (mp_has_normals) {
808  normal_indices += vcount;
809  }
810 
811  position_indices += vcount;
812  }
813 
814  if (invalid_loop_holes > 0) {
815  fprintf(stderr,
816  "Collada import: Mesh [%s] : contains %d unsupported loops (holes).\n",
817  me->id.name,
818  invalid_loop_holes);
819  }
820  }
821 
822  else if (collada_meshtype == COLLADAFW::MeshPrimitive::LINES) {
823  continue; /* read the lines later after all the rest is done */
824  }
825 
826  if (mp_has_faces) {
827  mat_prim_map[mp->getMaterialId()].push_back(prim);
828  }
829  }
830 
831  geom_uid_mat_mapping_map[collada_mesh->getUniqueId()] = mat_prim_map;
832 }
833 
834 void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData &arr, int i, int stride)
835 {
836  i *= stride;
837 
838  switch (arr.getType()) {
839  case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: {
840  COLLADAFW::ArrayPrimitiveType<float> *values = arr.getFloatValues();
841  if (values->empty()) {
842  return;
843  }
844 
845  v[0] = (*values)[i++];
846  v[1] = (*values)[i++];
847  if (stride >= 3) {
848  v[2] = (*values)[i];
849  }
850  else {
851  v[2] = 0.0f;
852  }
853 
854  } break;
855  case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: {
856  COLLADAFW::ArrayPrimitiveType<double> *values = arr.getDoubleValues();
857  if (values->empty()) {
858  return;
859  }
860 
861  v[0] = (float)(*values)[i++];
862  v[1] = (float)(*values)[i++];
863  if (stride >= 3) {
864  v[2] = (float)(*values)[i];
865  }
866  else {
867  v[2] = 0.0f;
868  }
869  } break;
870  default:
871  break;
872  }
873 }
874 
875 bool MeshImporter::is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData &nor, int count)
876 {
877  float a[3], b[3];
878 
879  get_vector(a, nor, *nind, 3);
880  normalize_v3(a);
881 
882  nind++;
883 
884  for (int i = 1; i < count; i++, nind++) {
885  get_vector(b, nor, *nind, 3);
886  normalize_v3(b);
887 
888  float dp = dot_v3v3(a, b);
889 
890  if (dp < 0.99999f || dp > 1.00001f) {
891  return false;
892  }
893  }
894 
895  return true;
896 }
897 
898 Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId &geom_uid)
899 {
900  if (uid_object_map.find(geom_uid) != uid_object_map.end()) {
901  return uid_object_map[geom_uid];
902  }
903  return nullptr;
904 }
905 
906 Mesh *MeshImporter::get_mesh_by_geom_uid(const COLLADAFW::UniqueId &geom_uid)
907 {
908  if (uid_mesh_map.find(geom_uid) != uid_mesh_map.end()) {
909  return uid_mesh_map[geom_uid];
910  }
911  return nullptr;
912 }
913 
914 std::string *MeshImporter::get_geometry_name(const std::string &mesh_name)
915 {
916  if (this->mesh_geom_map.find(mesh_name) != this->mesh_geom_map.end()) {
917  return &this->mesh_geom_map[mesh_name];
918  }
919  return nullptr;
920 }
921 
928 {
929  if (ob1->totcol != ob2->totcol) {
930  return false; /* not same number of materials */
931  }
932  if (ob1->totcol == 0) {
933  return false; /* no material at all */
934  }
935 
936  for (int index = 0; index < ob1->totcol; index++) {
937  if (ob1->matbits[index] != ob2->matbits[index]) {
938  return false; /* shouldn't happen */
939  }
940  if (ob1->matbits[index] == 0) {
941  return false; /* shouldn't happen */
942  }
943  if (ob1->mat[index] != ob2->mat[index]) {
944  return false; /* different material assignment */
945  }
946  }
947  return true;
948 }
949 
957 static void bc_copy_materials_to_data(Object *ob, Mesh *me)
958 {
959  for (int index = 0; index < ob->totcol; index++) {
960  ob->matbits[index] = 0;
961  me->mat[index] = ob->mat[index];
962  }
963 }
964 
971 {
972  for (int index = 0; index < ob->totcol; index++) {
973  ob->matbits[index] = 0;
974  ob->mat[index] = nullptr;
975  }
976 }
977 
983 std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh)
984 {
985  std::vector<Object *> mesh_users;
986  for (Object *ob : imported_objects) {
987  if (bc_is_marked(ob)) {
988  bc_remove_mark(ob);
989  Mesh *me = (Mesh *)ob->data;
990  if (me == reference_mesh) {
991  mesh_users.push_back(ob);
992  }
993  }
994  }
995  return mesh_users;
996 }
997 
1017 {
1018  for (Object *ob : imported_objects) {
1019  Mesh *me = (Mesh *)ob->data;
1020  if (ID_REAL_USERS(&me->id) == 1) {
1021  bc_copy_materials_to_data(ob, me);
1023  bc_remove_mark(ob);
1024  }
1025  else if (ID_REAL_USERS(&me->id) > 1) {
1026  bool can_move = true;
1027  std::vector<Object *> mesh_users = get_all_users_of(me);
1028  if (mesh_users.size() > 1) {
1029  Object *ref_ob = mesh_users[0];
1030  for (int index = 1; index < mesh_users.size(); index++) {
1031  if (!bc_has_same_material_configuration(ref_ob, mesh_users[index])) {
1032  can_move = false;
1033  break;
1034  }
1035  }
1036  if (can_move) {
1037  bc_copy_materials_to_data(ref_ob, me);
1038  for (Object *object : mesh_users) {
1039  bc_remove_materials_from_object(object, me);
1040  bc_remove_mark(object);
1041  }
1042  }
1043  }
1044  }
1045  }
1046 }
1047 
1057  COLLADAFW::MaterialBinding cmaterial,
1058  std::map<COLLADAFW::UniqueId, Material *> &uid_material_map,
1059  Object *ob,
1060  const COLLADAFW::UniqueId *geom_uid,
1061  short mat_index)
1062 {
1063  const COLLADAFW::UniqueId &ma_uid = cmaterial.getReferencedMaterial();
1064 
1065  /* do we know this material? */
1066  if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
1067 
1068  fprintf(stderr, "Cannot find material by UID.\n");
1069  return;
1070  }
1071 
1072  /* first time we get geom_uid, ma_uid pair. Save for later check. */
1073  materials_mapped_to_geom.insert(
1074  std::pair<COLLADAFW::UniqueId, COLLADAFW::UniqueId>(*geom_uid, ma_uid));
1075 
1076  Material *ma = uid_material_map[ma_uid];
1077 
1078  /* Attention! This temporarily assigns material to object on purpose!
1079  * See note above. */
1080  ob->actcol = 0;
1081  BKE_object_material_assign(m_bmain, ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT);
1082 
1083  MaterialIdPrimitiveArrayMap &mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
1084  COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId();
1085 
1086  /* assign material indices to mesh faces */
1087  if (mat_prim_map.find(mat_id) != mat_prim_map.end()) {
1088 
1089  std::vector<Primitive> &prims = mat_prim_map[mat_id];
1090 
1091  std::vector<Primitive>::iterator it;
1092 
1093  for (it = prims.begin(); it != prims.end(); it++) {
1094  Primitive &prim = *it;
1095  MPoly *mpoly = prim.mpoly;
1096 
1097  for (int i = 0; i < prim.totpoly; i++, mpoly++) {
1098  mpoly->mat_nr = mat_index;
1099  }
1100  }
1101  }
1102 }
1103 
1105  COLLADAFW::Node *node,
1106  COLLADAFW::InstanceGeometry *geom,
1107  bool isController,
1108  std::map<COLLADAFW::UniqueId, Material *> &uid_material_map)
1109 {
1110  const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId();
1111 
1112  /* check if node instantiates controller or geometry */
1113  if (isController) {
1114 
1115  geom_uid = armature_importer->get_geometry_uid(*geom_uid);
1116 
1117  if (!geom_uid) {
1118  fprintf(stderr, "Couldn't find a mesh UID by controller's UID.\n");
1119  return nullptr;
1120  }
1121  }
1122  else {
1123 
1124  if (uid_mesh_map.find(*geom_uid) == uid_mesh_map.end()) {
1125  /* this could happen if a mesh was not created
1126  * (e.g. if it contains unsupported geometry) */
1127  fprintf(stderr, "Couldn't find a mesh by UID.\n");
1128  return nullptr;
1129  }
1130  }
1131  if (!uid_mesh_map[*geom_uid]) {
1132  return nullptr;
1133  }
1134 
1135  /* name Object */
1136  const std::string &id = node->getName().empty() ? node->getOriginalId() : node->getName();
1137  const char *name = (id.length()) ? id.c_str() : nullptr;
1138 
1139  /* add object */
1140  Object *ob = bc_add_object(m_bmain, scene, view_layer, OB_MESH, name);
1141  bc_set_mark(ob); /* used later for material assignment optimization */
1142 
1143  /* store object pointer for ArmatureImporter */
1144  uid_object_map[*geom_uid] = ob;
1145  imported_objects.push_back(ob);
1146 
1147  /* replace ob->data freeing the old one */
1148  Mesh *old_mesh = (Mesh *)ob->data;
1149  Mesh *new_mesh = uid_mesh_map[*geom_uid];
1150 
1151  BKE_mesh_assign_object(m_bmain, ob, new_mesh);
1152  BKE_mesh_calc_normals(new_mesh);
1153 
1154  /* Because BKE_mesh_assign_object would have already decreased it... */
1155  id_us_plus(&old_mesh->id);
1156 
1157  BKE_id_free_us(m_bmain, old_mesh);
1158 
1159  COLLADAFW::MaterialBindingArray &mat_array = geom->getMaterialBindings();
1160 
1161  /* loop through geom's materials */
1162  for (unsigned int i = 0; i < mat_array.getCount(); i++) {
1163 
1164  if (mat_array[i].getReferencedMaterial().isValid()) {
1165  assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid, i);
1166  }
1167  else {
1168  fprintf(stderr, "invalid referenced material for %s\n", mat_array[i].getName().c_str());
1169  }
1170  }
1171 
1172  /* clean up the mesh */
1173  BKE_mesh_validate((Mesh *)ob->data, false, false);
1174 
1175  return ob;
1176 }
1177 
1178 /* create a mesh storing a pointer in a map so it can be retrieved later by geometry UID */
1180 {
1181 
1182  if (geom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) {
1183  /* TODO: report warning */
1184  fprintf(stderr, "Mesh type %s is not supported\n", bc_geomTypeToStr(geom->getType()));
1185  return true;
1186  }
1187 
1189 
1190  if (!is_nice_mesh(mesh)) {
1191  fprintf(stderr, "Ignoring mesh %s\n", bc_get_dae_name(mesh).c_str());
1192  return true;
1193  }
1194 
1195  const std::string &str_geom_id = mesh->getName().empty() ? mesh->getOriginalId() :
1196  mesh->getName();
1197  Mesh *me = BKE_mesh_add(m_bmain, (char *)str_geom_id.c_str());
1198  id_us_min(&me->id); /* is already 1 here, but will be set later in BKE_mesh_assign_object */
1199 
1200  /* store the Mesh pointer to link it later with an Object
1201  * mesh_geom_map needed to map mesh to its geometry name (for shape key naming) */
1202  this->uid_mesh_map[mesh->getUniqueId()] = me;
1203  this->mesh_geom_map[std::string(me->id.name)] = str_geom_id;
1204 
1205  read_vertices(mesh, me);
1206  read_polys(mesh, me);
1207  BKE_mesh_calc_edges(me, false, false);
1208  /* read_lines() must be called after the face edges have been generated.
1209  * Otherwise the loose edges will be silently deleted again. */
1210  read_lines(mesh, me);
1211 
1212  return true;
1213 }
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
void CustomData_free(struct CustomData *data, int totelem)
Definition: customdata.c:2239
@ CD_CALLOC
@ CD_DEFAULT
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
Definition: customdata.c:2637
void * CustomData_get_layer_named(const struct CustomData *data, int type, const char *name)
Definition: customdata.c:3217
void * CustomData_get_layer_n(const struct CustomData *data, int type, int n)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.c:2620
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, eCDAllocType alloctype, int totelem)
Definition: customdata.c:2193
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
const CustomData_MeshMasks CD_MASK_MESH
Definition: customdata.c:1933
display list (or rather multi purpose list) stuff.
void id_us_min(struct ID *id)
Definition: lib_id.c:297
void id_us_plus(struct ID *id)
Definition: lib_id.c:288
void BKE_id_free_us(struct Main *bmain, void *idv) ATTR_NONNULL()
General operations, lookup, etc. for materials.
@ BKE_MAT_ASSIGN_OBJECT
Definition: BKE_material.h:73
void BKE_object_material_assign(struct Main *bmain, struct Object *ob, struct Material *ma, short act, int assign_type)
Definition: material.c:850
void BKE_mesh_assign_object(struct Main *bmain, struct Object *ob, struct Mesh *me)
Definition: mesh.c:1283
struct Mesh * BKE_mesh_add(struct Main *bmain, const char *name)
Definition: mesh.c:849
void BKE_mesh_calc_normals(struct Mesh *me)
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd)
Definition: mesh.c:766
void BKE_mesh_calc_edges(struct Mesh *mesh, bool keep_existing_edges, const bool select_new_edges)
bool BKE_mesh_validate(struct Mesh *me, const bool do_verbose, const bool cddata_check_mask)
General operations, lookup, etc. for blender objects.
MINLINE float normalize_v3(float r[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void bc_remove_mark(Object *ob)
int bc_is_marked(Object *ob)
void bc_set_mark(Object *ob)
#define ID_REAL_USERS(id)
Definition: DNA_ID.h:413
@ CD_MLOOPCOL
@ CD_MVERT
@ CD_MLOOPUV
struct Mesh Mesh
@ ME_EDGEDRAW
@ ME_EDGERENDER
@ ME_LOOSEEDGE
@ ME_SMOOTH
@ OB_MESH
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei stride
Read Guarded memory(de)allocation.
static bool bc_has_same_material_configuration(Object *ob1, Object *ob2)
static void bc_copy_materials_to_data(Object *ob, Mesh *me)
static const char * bc_geomTypeToStr(COLLADAFW::Geometry::GeometryType type)
static std::string extract_vcolname(const COLLADAFW::String &collada_id)
static void bc_remove_materials_from_object(Object *ob, Mesh *me)
static void colladaAddColor(T values, MLoopCol *mloopcol, int v_index, int stride)
static std::string bc_get_dae_name(T *node)
static const char * bc_primTypeToStr(COLLADAFW::MeshPrimitive::PrimitiveType type)
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Geometry
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky Noise Wave Voronoi Brick Texture Vector Combine Vertex Separate Vector White RGB Map Separate Set Z Dilate Combine Combine Color Channel Split ID Combine Luminance Directional Alpha Distance Hue Movie Ellipse Bokeh View Corner Anti Mix RGB Hue Separate TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC Boolean Random String
ATTR_WARN_UNUSED_RESULT const BMVert * v
virtual const char * getName() const
Definition: btBox2dShape.h:301
COLLADAFW::UniqueId * get_geometry_uid(const COLLADAFW::UniqueId &controller_uid)
virtual Mesh * get_mesh_by_geom_uid(const COLLADAFW::UniqueId &geom_uid)
virtual Object * get_object_by_geom_uid(const COLLADAFW::UniqueId &geom_uid)
void optimize_material_assignements()
bool write_geometry(const COLLADAFW::Geometry *geom)
void assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial, std::map< COLLADAFW::UniqueId, Material * > &uid_material_map, Object *ob, const COLLADAFW::UniqueId *geom_uid, short mat_index)
Object * create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom, bool isController, std::map< COLLADAFW::UniqueId, Material * > &uid_material_map)
MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer)
std::string * get_geometry_name(const std::string &mesh_name)
UVDataWrapper(COLLADAFW::MeshVertexData &vdata)
void getUV(int uv_index, float *uv)
void get_vcol(int v_index, MLoopCol *mloopcol)
VCOLDataWrapper(COLLADAFW::MeshVertexData &vdata)
Object * bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
#define SELECT
OperationNode * node
Scene scene
static ushort indices[]
uint pos
uint nor
int count
PrimitiveType
Definition: kernel_types.h:684
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
#define T
static unsigned a[3]
Definition: RandGen.cpp:92
char name[66]
Definition: DNA_ID.h:283
unsigned int v1
unsigned int v2
unsigned char a
unsigned char b
unsigned char r
unsigned char g
unsigned int v
short mat_nr
float co[3]
Definition: BKE_main.h:116
struct MEdge * medge
struct CustomData pdata ldata
struct MVert * mvert
struct MLoopCol * mloopcol
struct Material ** mat
int totedge
struct MLoopUV * mloopuv
int totvert
struct MLoop * mloop
int totpoly
int totloop
struct MPoly * mpoly
struct Material ** mat
char * matbits
void * data
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
uint len