Ejemplo n.º 1
0
static void rna_Mesh_flip_normals(Mesh *mesh)
{
	BKE_mesh_polygons_flip(mesh->mpoly, mesh->mloop, &mesh->ldata, mesh->totpoly);
	BKE_mesh_tessface_clear(mesh);
	BKE_mesh_calc_normals(mesh);

	DAG_id_tag_update(&mesh->id, 0);
}
Ejemplo n.º 2
0
void MeshImporter::bmeshConversion()
{
	for (std::map<COLLADAFW::UniqueId, Mesh *>::iterator m = uid_mesh_map.begin();
	     m != uid_mesh_map.end(); ++m)
	{
		if ((*m).second) {
			Mesh *me = (*m).second;
			BKE_mesh_tessface_clear(me);
			BKE_mesh_calc_normals(me);
			//BKE_mesh_validate(me, 1);
		}
	}
}
Ejemplo n.º 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);

	// must validate before calculating edges
	BKE_mesh_calc_normals(me);
	BKE_mesh_validate(me, false, false);
	// validation does this
	// 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;
}
Ejemplo n.º 4
0
Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
                                         bool isController,
                                         std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
                                         std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map)
{
	const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId();
	
	// check if node instanciates controller or geometry
	if (isController) {
		
		geom_uid = armature_importer->get_geometry_uid(*geom_uid);
		
		if (!geom_uid) {
			fprintf(stderr, "Couldn't find a mesh UID by controller's UID.\n");
			return NULL;
		}
	}
	else {
		
		if (uid_mesh_map.find(*geom_uid) == uid_mesh_map.end()) {
			// this could happen if a mesh was not created
			// (e.g. if it contains unsupported geometry)
			fprintf(stderr, "Couldn't find a mesh by UID.\n");
			return NULL;
		}
	}
	if (!uid_mesh_map[*geom_uid]) return NULL;
	
	// name Object
	const std::string& id = node->getName().size() ? node->getName() : node->getOriginalId();
	const char *name = (id.length()) ? id.c_str() : NULL;
	
	// add object
	Object *ob = bc_add_object(scene, OB_MESH, name);
	bc_set_mark(ob); // used later for material assignement optimization


	// store object pointer for ArmatureImporter
	uid_object_map[*geom_uid] = ob;
	imported_objects.push_back(ob);
	
	// replace ob->data freeing the old one
	Mesh *old_mesh = (Mesh *)ob->data;
	Mesh *new_mesh = uid_mesh_map[*geom_uid];

	BKE_mesh_assign_object(ob, new_mesh);
	BKE_mesh_calc_normals(new_mesh);

	if (old_mesh->id.us == 0) BKE_libblock_free(G.main, old_mesh);
	
	char layername[100];
	layername[0] = '\0';
	MTFace *texture_face = NULL;
	
	COLLADAFW::MaterialBindingArray& mat_array =
	    geom->getMaterialBindings();
	
	// loop through geom's materials
	for (unsigned int i = 0; i < mat_array.getCount(); i++) {
		
		if (mat_array[i].getReferencedMaterial().isValid()) {
			texture_face = assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid,
			                                       layername, texture_face,
			                                       material_texture_mapping_map, i);
		}
		else {
			fprintf(stderr, "invalid referenced material for %s\n", mat_array[i].getName().c_str());
		}
	}

	return ob;
}
static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_loc, bool apply_rot, bool apply_scale)
{
	Main *bmain = CTX_data_main(C);
	Scene *scene = CTX_data_scene(C);
	float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
	bool changed = true;
	
	/* first check if we can execute */
	CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
	{
		if (ELEM(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF, OB_FONT)) {
			ID *obdata = ob->data;
			if (ID_REAL_USERS(obdata) > 1) {
				BKE_reportf(reports, RPT_ERROR,
				            "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}

			if (obdata->lib) {
				BKE_reportf(reports, RPT_ERROR,
				            "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}
		}

		if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
			ID *obdata = ob->data;
			Curve *cu;

			cu = ob->data;

			if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
				BKE_reportf(reports, RPT_ERROR,
				            "Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}
			if (cu->key) {
				BKE_reportf(reports, RPT_ERROR,
				            "Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}
		}

		if (ob->type == OB_FONT) {
			if (apply_rot || apply_loc) {
				BKE_reportf(reports, RPT_ERROR,
				            "Font's can only have scale applied: \"%s\"",
				            ob->id.name + 2);
				changed = false;
			}
		}
	}
	CTX_DATA_END;
	
	if (!changed)
		return OPERATOR_CANCELLED;

	changed = false;

	/* now execute */
	CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
	{

		/* calculate rotation/scale matrix */
		if (apply_scale && apply_rot)
			BKE_object_to_mat3(ob, rsmat);
		else if (apply_scale)
			BKE_object_scale_to_mat3(ob, rsmat);
		else if (apply_rot) {
			float tmat[3][3], timat[3][3];

			/* simple rotation matrix */
			BKE_object_rot_to_mat3(ob, rsmat, true);

			/* correct for scale, note mul_m3_m3m3 has swapped args! */
			BKE_object_scale_to_mat3(ob, tmat);
			invert_m3_m3(timat, tmat);
			mul_m3_m3m3(rsmat, timat, rsmat);
			mul_m3_m3m3(rsmat, rsmat, tmat);
		}
		else
			unit_m3(rsmat);

		copy_m4_m3(mat, rsmat);

		/* calculate translation */
		if (apply_loc) {
			copy_v3_v3(mat[3], ob->loc);

			if (!(apply_scale && apply_rot)) {
				float tmat[3][3];
				/* correct for scale and rotation that is still applied */
				BKE_object_to_mat3(ob, obmat);
				invert_m3_m3(iobmat, obmat);
				mul_m3_m3m3(tmat, rsmat, iobmat);
				mul_m3_v3(tmat, mat[3]);
			}
		}

		/* apply to object data */
		if (ob->type == OB_MESH) {
			Mesh *me = ob->data;

			if (apply_scale)
				multiresModifier_scale_disp(scene, ob);
			
			/* adjust data */
			BKE_mesh_transform(me, mat, true);
			
			/* update normals */
			BKE_mesh_calc_normals(me);
		}
		else if (ob->type == OB_ARMATURE) {
			ED_armature_apply_transform(ob, mat);
		}
		else if (ob->type == OB_LATTICE) {
			Lattice *lt = ob->data;

			BKE_lattice_transform(lt, mat, true);
		}
		else if (ob->type == OB_MBALL) {
			MetaBall *mb = ob->data;
			BKE_mball_transform(mb, mat);
		}
		else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
			Curve *cu = ob->data;
			scale = mat3_to_scale(rsmat);
			BKE_curve_transform_ex(cu, mat, true, scale);
		}
		else if (ob->type == OB_FONT) {
			Curve *cu = ob->data;
			int i;

			scale = mat3_to_scale(rsmat);

			for (i = 0; i < cu->totbox; i++) {
				TextBox *tb = &cu->tb[i];
				tb->x *= scale;
				tb->y *= scale;
				tb->w *= scale;
				tb->h *= scale;
			}

			cu->fsize *= scale;
		}
		else if (ob->type == OB_CAMERA) {
			MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);

			/* applying scale on camera actually scales clip's reconstruction.
			 * of there's clip assigned to camera nothing to do actually.
			 */
			if (!clip)
				continue;

			if (apply_scale)
				BKE_tracking_reconstruction_scale(&clip->tracking, ob->size);
		}
		else if (ob->type == OB_EMPTY) {
			/* It's possible for empties too, even though they don't 
			 * really have obdata, since we can simply apply the maximum
			 * scaling to the empty's drawsize.
			 *
			 * Core Assumptions:
			 * 1) Most scaled empties have uniform scaling 
			 *    (i.e. for visibility reasons), AND/OR
			 * 2) Preserving non-uniform scaling is not that important,
			 *    and is something that many users would be willing to
			 *    sacrifice for having an easy way to do this.
			 */

			if ((apply_loc == false) &&
			    (apply_rot == false) &&
			    (apply_scale == true))
			{
				float max_scale = max_fff(fabsf(ob->size[0]), fabsf(ob->size[1]), fabsf(ob->size[2]));
				ob->empty_drawsize *= max_scale;
			}
		}
		else {
			continue;
		}

		if (apply_loc)
			zero_v3(ob->loc);
		if (apply_scale)
			ob->size[0] = ob->size[1] = ob->size[2] = 1.0f;
		if (apply_rot) {
			zero_v3(ob->rot);
			unit_qt(ob->quat);
			unit_axis_angle(ob->rotAxis, &ob->rotAngle);
		}

		BKE_object_where_is_calc(scene, ob);
		if (ob->type == OB_ARMATURE) {
			BKE_pose_where_is(scene, ob); /* needed for bone parents */
		}

		ignore_parent_tx(bmain, scene, ob);

		DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);

		changed = true;
	}
	CTX_DATA_END;

	if (!changed) {
		BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
		return OPERATOR_CANCELLED;
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	return OPERATOR_FINISHED;
}
Ejemplo n.º 6
0
void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
{
  DispList *dl;
  MVert *mvert;
  MLoop *mloop, *allloop;
  MPoly *mpoly;
  const float *nors, *verts;
  int a, *index;

  dl = lb->first;
  if (dl == NULL) {
    return;
  }

  if (dl->type == DL_INDEX4) {
    mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, dl->nr);
    allloop = mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, dl->parts * 4);
    mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, dl->parts);
    me->mvert = mvert;
    me->mloop = mloop;
    me->mpoly = mpoly;
    me->totvert = dl->nr;
    me->totpoly = dl->parts;

    a = dl->nr;
    nors = dl->nors;
    verts = dl->verts;
    while (a--) {
      copy_v3_v3(mvert->co, verts);
      normal_float_to_short_v3(mvert->no, nors);
      mvert++;
      nors += 3;
      verts += 3;
    }

    a = dl->parts;
    index = dl->index;
    while (a--) {
      int count = index[2] != index[3] ? 4 : 3;

      mloop[0].v = index[0];
      mloop[1].v = index[1];
      mloop[2].v = index[2];
      if (count == 4) {
        mloop[3].v = index[3];
      }

      mpoly->totloop = count;
      mpoly->loopstart = (int)(mloop - allloop);
      mpoly->flag = ME_SMOOTH;

      mpoly++;
      mloop += count;
      me->totloop += count;
      index += 4;
    }

    BKE_mesh_update_customdata_pointers(me, true);

    BKE_mesh_calc_normals(me);

    BKE_mesh_calc_edges(me, true, false);
  }
}
Ejemplo n.º 7
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);
  }
}
static int apply_objects_internal(bContext *C, ReportList *reports, int apply_loc, int apply_rot, int apply_scale)
{
	Main *bmain = CTX_data_main(C);
	Scene *scene = CTX_data_scene(C);
	float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
	bool changed = true;
	
	/* first check if we can execute */
	CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
	{
		if (ELEM6(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF)) {
			ID *obdata = ob->data;
			if (ID_REAL_USERS(obdata) > 1) {
				BKE_reportf(reports, RPT_ERROR,
				            "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}

			if (obdata->lib) {
				BKE_reportf(reports, RPT_ERROR,
				            "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}
		}

		if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
			ID *obdata = ob->data;
			Curve *cu;

			cu = ob->data;

			if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
				BKE_reportf(reports, RPT_ERROR,
				            "Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}
			if (cu->key) {
				BKE_reportf(reports, RPT_ERROR,
				            "Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting",
				            ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
				changed = false;
			}
		}
	}
	CTX_DATA_END;
	
	if (!changed)
		return OPERATOR_CANCELLED;

	changed = false;

	/* now execute */
	CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
	{

		/* calculate rotation/scale matrix */
		if (apply_scale && apply_rot)
			BKE_object_to_mat3(ob, rsmat);
		else if (apply_scale)
			BKE_object_scale_to_mat3(ob, rsmat);
		else if (apply_rot) {
			float tmat[3][3], timat[3][3];

			/* simple rotation matrix */
			BKE_object_rot_to_mat3(ob, rsmat, TRUE);

			/* correct for scale, note mul_m3_m3m3 has swapped args! */
			BKE_object_scale_to_mat3(ob, tmat);
			invert_m3_m3(timat, tmat);
			mul_m3_m3m3(rsmat, timat, rsmat);
			mul_m3_m3m3(rsmat, rsmat, tmat);
		}
		else
			unit_m3(rsmat);

		copy_m4_m3(mat, rsmat);

		/* calculate translation */
		if (apply_loc) {
			copy_v3_v3(mat[3], ob->loc);

			if (!(apply_scale && apply_rot)) {
				float tmat[3][3];
				/* correct for scale and rotation that is still applied */
				BKE_object_to_mat3(ob, obmat);
				invert_m3_m3(iobmat, obmat);
				mul_m3_m3m3(tmat, rsmat, iobmat);
				mul_m3_v3(tmat, mat[3]);
			}
		}

		/* apply to object data */
		if (ob->type == OB_MESH) {
			Mesh *me = ob->data;
			MVert *mvert;
			int a;

			if (apply_scale)
				multiresModifier_scale_disp(scene, ob);
			
			/* adjust data */
			mvert = me->mvert;
			for (a = 0; a < me->totvert; a++, mvert++)
				mul_m4_v3(mat, mvert->co);
			
			if (me->key) {
				KeyBlock *kb;
				
				for (kb = me->key->block.first; kb; kb = kb->next) {
					float *fp = kb->data;
					
					for (a = 0; a < kb->totelem; a++, fp += 3)
						mul_m4_v3(mat, fp);
				}
			}
			
			/* update normals */
			BKE_mesh_calc_normals(me);
		}
		else if (ob->type == OB_ARMATURE) {
			ED_armature_apply_transform(ob, mat);
		}
		else if (ob->type == OB_LATTICE) {
			Lattice *lt = ob->data;
			BPoint *bp = lt->def;
			int a = lt->pntsu * lt->pntsv * lt->pntsw;
			
			while (a--) {
				mul_m4_v3(mat, bp->vec);
				bp++;
			}
		}
		else if (ob->type == OB_MBALL) {
			MetaBall *mb = ob->data;
			ED_mball_transform(mb, mat);
		}
		else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
			Curve *cu = ob->data;

			Nurb *nu;
			BPoint *bp;
			BezTriple *bezt;
			int a;

			scale = mat3_to_scale(rsmat);

			for (nu = cu->nurb.first; nu; nu = nu->next) {
				if (nu->type == CU_BEZIER) {
					a = nu->pntsu;
					for (bezt = nu->bezt; a--; bezt++) {
						mul_m4_v3(mat, bezt->vec[0]);
						mul_m4_v3(mat, bezt->vec[1]);
						mul_m4_v3(mat, bezt->vec[2]);
						bezt->radius *= scale;
					}
					BKE_nurb_handles_calc(nu);
				}
				else {
					a = nu->pntsu * nu->pntsv;
					for (bp = nu->bp; a--; bp++)
						mul_m4_v3(mat, bp->vec);
				}
			}
		}
		else if (ob->type == OB_CAMERA) {
			MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);

			/* applying scale on camera actually scales clip's reconstruction.
			 * of there's clip assigned to camera nothing to do actually.
			 */
			if (!clip)
				continue;

			if (apply_scale)
				BKE_tracking_reconstruction_scale(&clip->tracking, ob->size);
		}
		else if (ob->type == OB_EMPTY) {
			/* It's possible for empties too, even though they don't 
			 * really have obdata, since we can simply apply the maximum
			 * scaling to the empty's drawsize.
			 *
			 * Core Assumptions:
			 * 1) Most scaled empties have uniform scaling 
			 *    (i.e. for visibility reasons), AND/OR
			 * 2) Preserving non-uniform scaling is not that important,
			 *    and is something that many users would be willing to
			 *    sacrifice for having an easy way to do this.
			 */
			 float max_scale = MAX3(ob->size[0], ob->size[1], ob->size[2]);
			 ob->empty_drawsize *= max_scale;
		}
		else {
			continue;
		}

		if (apply_loc)
			zero_v3(ob->loc);
		if (apply_scale)
			ob->size[0] = ob->size[1] = ob->size[2] = 1.0f;
		if (apply_rot) {
			zero_v3(ob->rot);
			unit_qt(ob->quat);
			unit_axis_angle(ob->rotAxis, &ob->rotAngle);
		}

		BKE_object_where_is_calc(scene, ob);
		if (ob->type == OB_ARMATURE) {
			BKE_pose_where_is(scene, ob); /* needed for bone parents */
		}

		ignore_parent_tx(bmain, scene, ob);

		DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);

		changed = true;
	}
	CTX_DATA_END;

	if (!changed) {
		BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
		return OPERATOR_CANCELLED;
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	return OPERATOR_FINISHED;
}