Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
{
	Mesh *tmpmesh;
	CustomDataMask mask = CD_MASK_MESH;
	Mesh *mesh = (Mesh *)ob->data;
	DerivedMesh *dm = NULL;
	if (apply_modifiers) {
		switch (export_mesh_type) {
			case BC_MESH_TYPE_VIEW:
			{
				dm = mesh_create_derived_view(scene, ob, mask);
				break;
			}
			case BC_MESH_TYPE_RENDER:
			{
				dm = mesh_create_derived_render(scene, ob, mask);
				break;
			}
		}
	}
	else {
		dm = mesh_create_derived((Mesh *)ob->data, NULL);
	}

	tmpmesh = BKE_mesh_add(G.main, "ColladaMesh"); // name is not important here
	DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH, true);
	tmpmesh->flag = mesh->flag;

	if (triangulate) {
		bc_triangulate_mesh(tmpmesh);
	}
	BKE_mesh_tessface_ensure(tmpmesh);
	return tmpmesh;
}
示例#2
0
// A replacement of BKE_object_add() for better performance.
Object *BlenderStrokeRenderer::NewMesh() const
{
	Object *ob;
	Base *base;
	char name[MAX_ID_NAME];
	unsigned int mesh_id = get_stroke_mesh_id();

	/* XXX this is for later review, for now we start names with 27 (DEL) 
	   to allow ignoring them in DAG_ids_check_recalc() */
	BLI_snprintf(name, MAX_ID_NAME, "%c0%08xOB", 27, mesh_id);
	ob = BKE_object_add_only_object(freestyle_bmain, OB_MESH, name);
	BLI_snprintf(name, MAX_ID_NAME, "%c0%08xME", 27, mesh_id);
	ob->data = BKE_mesh_add(freestyle_bmain, name);
	ob->lay = 1;

	base = BKE_scene_base_add(freestyle_scene, ob);
#if 0
	BKE_scene_base_deselect_all(scene);
	BKE_scene_base_select(scene, base);
#else
	(void)base;
#endif
	ob->recalc = OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;

	return ob;
}
示例#3
0
// create a mesh storing a pointer in a map so it can be retrieved later by geometry UID
bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom)
{

	if (geom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) {
		// TODO: report warning
		fprintf(stderr, "Mesh type %s is not supported\n", bc_geomTypeToStr(geom->getType()));
		return true;
	}
	
	COLLADAFW::Mesh *mesh = (COLLADAFW::Mesh *)geom;
	
	if (!is_nice_mesh(mesh)) {
		fprintf(stderr, "Ignoring mesh %s\n", bc_get_dae_name(mesh).c_str());
		return true;
	}
	
	const std::string& str_geom_id = mesh->getName().size() ? mesh->getName() : mesh->getOriginalId();
	Mesh *me = BKE_mesh_add(G.main, (char *)str_geom_id.c_str());
	me->id.us--; // is already 1 here, but will be set later in BKE_mesh_assign_object

	// store the Mesh pointer to link it later with an Object
	// mesh_geom_map needed to map mesh to its geometry name (for shape key naming)
	this->uid_mesh_map[mesh->getUniqueId()] = me;
	this->mesh_geom_map[std::string(me->id.name)] = str_geom_id;
	
	read_vertices(mesh, me);
	read_polys(mesh, me);
	BKE_mesh_calc_edges(me, false, false);

	// read_lines() must be called after the face edges have been generated.
	// Oterwise the loose edges will be silently deleted again.
	read_lines(mesh, me);
	return true;
}
示例#4
0
/* settings: 1 - preview, 2 - render
 *
 * The convention goes as following:
 *
 * - Passing original object with apply_modifiers=false will give a
 *   non-modified non-deformed mesh.
 *   The result mesh will point to datablocks from the original "domain". For
 *   example, materials will be original.
 *
 * - Passing original object with apply_modifiers=true will give a mesh which
 *   has all modifiers applied.
 *   The result mesh will point to datablocks from the original "domain". For
 *   example, materials will be original.
 *
 * - Passing evaluated object will ignore apply_modifiers argument, and the
 *   result always contains all modifiers applied.
 *   The result mesh will point to an evaluated datablocks. For example,
 *   materials will be an evaluated IDs from the dependency graph.
 */
Mesh *BKE_mesh_new_from_object(Depsgraph *depsgraph,
                               Main *bmain,
                               Scene *sce,
                               Object *ob,
                               const bool apply_modifiers,
                               const bool calc_undeformed)
{
  Mesh *tmpmesh;
  Curve *tmpcu = NULL, *copycu;
  int i;
  const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
  bool effective_apply_modifiers = apply_modifiers;
  bool do_mat_id_data_us = true;

  Object *object_input = ob;
  Object *object_eval = DEG_get_evaluated_object(depsgraph, object_input);
  Object object_for_eval;

  if (object_eval == object_input) {
    /* Evaluated mesh contains all modifiers applied already.
     * The other types of object has them applied, but are stored in other
     * data structures than a mesh. So need to apply modifiers again on a
     * temporary copy before converting result to mesh. */
    if (object_input->type == OB_MESH) {
      effective_apply_modifiers = false;
    }
    else {
      effective_apply_modifiers = true;
    }
    object_for_eval = *object_eval;
  }
  else {
    if (apply_modifiers) {
      object_for_eval = *object_eval;
      if (object_for_eval.runtime.mesh_orig != NULL) {
        object_for_eval.data = object_for_eval.runtime.mesh_orig;
      }
    }
    else {
      object_for_eval = *object_input;
    }
  }

  const bool cage = !effective_apply_modifiers;

  /* perform the mesh extraction based on type */
  switch (object_for_eval.type) {
    case OB_FONT:
    case OB_CURVE:
    case OB_SURF: {
      ListBase dispbase = {NULL, NULL};
      Mesh *me_eval_final = NULL;
      int uv_from_orco;

      /* copies object and modifiers (but not the data) */
      Object *tmpobj;
      BKE_id_copy_ex(NULL, &object_for_eval.id, (ID **)&tmpobj, LIB_ID_COPY_LOCALIZE);
      tmpcu = (Curve *)tmpobj->data;

      /* Copy cached display list, it might be needed by the stack evaluation.
       * Ideally stack should be able to use render-time display list, but doing
       * so is quite tricky and not safe so close to the release.
       *
       * TODO(sergey): Look into more proper solution.
       */
      if (object_for_eval.runtime.curve_cache != NULL) {
        if (tmpobj->runtime.curve_cache == NULL) {
          tmpobj->runtime.curve_cache = MEM_callocN(sizeof(CurveCache),
                                                    "CurveCache for curve types");
        }
        BKE_displist_copy(&tmpobj->runtime.curve_cache->disp,
                          &object_for_eval.runtime.curve_cache->disp);
      }

      /* if getting the original caged mesh, delete object modifiers */
      if (cage) {
        BKE_object_free_modifiers(tmpobj, LIB_ID_CREATE_NO_USER_REFCOUNT);
      }

      /* copies the data, but *not* the shapekeys. */
      BKE_id_copy_ex(NULL, object_for_eval.data, (ID **)&copycu, LIB_ID_COPY_LOCALIZE);
      tmpobj->data = copycu;

      /* make sure texture space is calculated for a copy of curve,
       * it will be used for the final result.
       */
      BKE_curve_texspace_calc(copycu);

      /* temporarily set edit so we get updates from edit mode, but
       * also because for text datablocks copying it while in edit
       * mode gives invalid data structures */
      copycu->editfont = tmpcu->editfont;
      copycu->editnurb = tmpcu->editnurb;

      /* get updated display list, and convert to a mesh */
      BKE_displist_make_curveTypes_forRender(
          depsgraph, sce, tmpobj, &dispbase, &me_eval_final, false, NULL);

      copycu->editfont = NULL;
      copycu->editnurb = NULL;

      tmpobj->runtime.mesh_eval = me_eval_final;

      /* convert object type to mesh */
      uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
      BKE_mesh_from_nurbs_displist(
          bmain, tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2, true);
      /* Function above also frees copycu (aka tmpobj->data), make this obvious here. */
      copycu = NULL;

      tmpmesh = tmpobj->data;
      id_us_min(
          &tmpmesh->id); /* Gets one user from its creation in BKE_mesh_from_nurbs_displist(). */

      BKE_displist_free(&dispbase);

      /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked.
       * if it didn't the curve did not have any segments or otherwise
       * would have generated an empty mesh */
      if (tmpobj->type != OB_MESH) {
        BKE_id_free(NULL, tmpobj);
        return NULL;
      }

      BKE_id_free(NULL, tmpobj);

      /* XXX The curve to mesh conversion is convoluted...
       *     But essentially, BKE_mesh_from_nurbs_displist()
       *     already transfers the ownership of materials from the temp copy of the Curve ID to the
       *     new Mesh ID, so we do not want to increase materials' usercount later. */
      do_mat_id_data_us = false;

      break;
    }

    case OB_MBALL: {
      /* metaballs don't have modifiers, so just convert to mesh */
      Object *basis_ob = BKE_mball_basis_find(sce, object_input);
      /* todo, re-generatre for render-res */
      /* metaball_polygonize(scene, ob) */

      if (basis_ob != object_input) {
        /* Only do basis metaball. */
        return NULL;
      }

      tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2);
      /* BKE_mesh_add gives us a user count we don't need */
      id_us_min(&tmpmesh->id);

      if (render) {
        ListBase disp = {NULL, NULL};
        BKE_displist_make_mball_forRender(depsgraph, sce, &object_for_eval, &disp);
        BKE_mesh_from_metaball(&disp, tmpmesh);
        BKE_displist_free(&disp);
      }
      else {
        ListBase disp = {NULL, NULL};
        if (object_for_eval.runtime.curve_cache) {
          disp = object_for_eval.runtime.curve_cache->disp;
        }
        BKE_mesh_from_metaball(&disp, tmpmesh);
      }

      BKE_mesh_texspace_copy_from_object(tmpmesh, &object_for_eval);

      break;
    }
    case OB_MESH:
      /* copies object and modifiers (but not the data) */
      if (cage) {
        /* copies the data (but *not* the shapekeys). */
        Mesh *mesh = object_for_eval.data;
        BKE_id_copy_ex(bmain, &mesh->id, (ID **)&tmpmesh, 0);
        /* XXX BKE_mesh_copy() already handles materials usercount. */
        do_mat_id_data_us = false;
      }
      /* if not getting the original caged mesh, get final derived mesh */
      else {
        /* Make a dummy mesh, saves copying */
        Mesh *me_eval;
        CustomData_MeshMasks mask = CD_MASK_MESH; /* this seems more suitable, exporter,
                                                   * for example, needs CD_MASK_MDEFORMVERT */

        if (calc_undeformed) {
          mask.vmask |= CD_MASK_ORCO;
        }

        if (render) {
          me_eval = mesh_create_eval_final_render(depsgraph, sce, &object_for_eval, &mask);
        }
        else {
          me_eval = mesh_create_eval_final_view(depsgraph, sce, &object_for_eval, &mask);
        }

        tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2);
        BKE_mesh_nomain_to_mesh(me_eval, tmpmesh, &object_for_eval, &mask, true);

        /* Copy autosmooth settings from original mesh. */
        Mesh *me = (Mesh *)object_for_eval.data;
        tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH);
        tmpmesh->smoothresh = me->smoothresh;
      }

      /* BKE_mesh_add/copy gives us a user count we don't need */
      id_us_min(&tmpmesh->id);

      break;
    default:
      /* "Object does not have geometry data") */
      return NULL;
  }

  /* Copy materials to new mesh */
  switch (object_for_eval.type) {
    case OB_SURF:
    case OB_FONT:
    case OB_CURVE:
      tmpmesh->totcol = tmpcu->totcol;

      /* free old material list (if it exists) and adjust user counts */
      if (tmpcu->mat) {
        for (i = tmpcu->totcol; i-- > 0;) {
          /* are we an object material or data based? */
          tmpmesh->mat[i] = give_current_material(object_input, i + 1);

          if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
              tmpmesh->mat[i]) {
            id_us_plus(&tmpmesh->mat[i]->id);
          }
        }
      }
      break;

    case OB_MBALL: {
      MetaBall *tmpmb = (MetaBall *)object_for_eval.data;
      tmpmesh->mat = MEM_dupallocN(tmpmb->mat);
      tmpmesh->totcol = tmpmb->totcol;

      /* free old material list (if it exists) and adjust user counts */
      if (tmpmb->mat) {
        for (i = tmpmb->totcol; i-- > 0;) {
          /* are we an object material or data based? */
          tmpmesh->mat[i] = give_current_material(object_input, i + 1);

          if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
              tmpmesh->mat[i]) {
            id_us_plus(&tmpmesh->mat[i]->id);
          }
        }
      }
      break;
    }

    case OB_MESH:
      if (!cage) {
        Mesh *origmesh = object_for_eval.data;
        tmpmesh->flag = origmesh->flag;
        tmpmesh->mat = MEM_dupallocN(origmesh->mat);
        tmpmesh->totcol = origmesh->totcol;
        tmpmesh->smoothresh = origmesh->smoothresh;
        if (origmesh->mat) {
          for (i = origmesh->totcol; i-- > 0;) {
            /* are we an object material or data based? */
            tmpmesh->mat[i] = give_current_material(object_input, i + 1);

            if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
                tmpmesh->mat[i]) {
              id_us_plus(&tmpmesh->mat[i]->id);
            }
          }
        }
      }
      break;
  } /* end copy materials */

  return tmpmesh;
}
示例#5
0
/* this may fail replacing ob->data, be sure to check ob->type */
void BKE_mesh_from_nurbs_displist(Main *bmain,
                                  Object *ob,
                                  ListBase *dispbase,
                                  const bool use_orco_uv,
                                  const char *obdata_name,
                                  bool temporary)
{
  Object *ob1;
  Mesh *me_eval = ob->runtime.mesh_eval;
  Mesh *me;
  Curve *cu;
  MVert *allvert = NULL;
  MEdge *alledge = NULL;
  MLoop *allloop = NULL;
  MLoopUV *alluv = NULL;
  MPoly *allpoly = NULL;
  int totvert, totedge, totloop, totpoly;

  cu = ob->data;

  if (me_eval == NULL) {
    if (BKE_mesh_nurbs_displist_to_mdata(ob,
                                         dispbase,
                                         &allvert,
                                         &totvert,
                                         &alledge,
                                         &totedge,
                                         &allloop,
                                         &allpoly,
                                         (use_orco_uv) ? &alluv : NULL,
                                         &totloop,
                                         &totpoly) != 0) {
      /* Error initializing */
      return;
    }

    /* make mesh */
    me = BKE_mesh_add(bmain, obdata_name);
    me->totvert = totvert;
    me->totedge = totedge;
    me->totloop = totloop;
    me->totpoly = totpoly;

    me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert);
    me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge);
    me->mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop);
    me->mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly);

    if (alluv) {
      const char *uvname = "Orco";
      me->mloopuv = CustomData_add_layer_named(
          &me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, uvname);
    }

    BKE_mesh_calc_normals(me);
  }
  else {
    me = BKE_mesh_add(bmain, obdata_name);
    ob->runtime.mesh_eval = NULL;
    BKE_mesh_nomain_to_mesh(me_eval, me, ob, &CD_MASK_MESH, true);
  }

  me->totcol = cu->totcol;
  me->mat = cu->mat;

  /* Copy evaluated texture space from curve to mesh.
   *
   * Note that we disable auto texture space feature since that will cause
   * texture space to evaluate differently for curve and mesh, since curve
   * uses CV to calculate bounding box, and mesh uses what is coming from
   * tessellated curve.
   */
  me->texflag = cu->texflag & ~CU_AUTOSPACE;
  copy_v3_v3(me->loc, cu->loc);
  copy_v3_v3(me->size, cu->size);
  copy_v3_v3(me->rot, cu->rot);
  BKE_mesh_texspace_calc(me);

  cu->mat = NULL;
  cu->totcol = 0;

  /* Do not decrement ob->data usercount here,
   * it's done at end of func with BKE_id_free_us() call. */
  ob->data = me;
  ob->type = OB_MESH;

  /* other users */
  ob1 = bmain->objects.first;
  while (ob1) {
    if (ob1->data == cu) {
      ob1->type = OB_MESH;

      id_us_min((ID *)ob1->data);
      ob1->data = ob->data;
      id_us_plus((ID *)ob1->data);
    }
    ob1 = ob1->id.next;
  }

  if (temporary) {
    /* For temporary objects in BKE_mesh_new_from_object don't remap
     * the entire scene with associated depsgraph updates, which are
     * problematic for renderers exporting data. */
    BKE_id_free(NULL, cu);
  }
  else {
    BKE_id_free_us(bmain, cu);
  }
}