Пример #1
0
static void get_dupliface_transform(MPoly *mpoly, MLoop *mloop, MVert *mvert,
                                    bool use_scale, float scale_fac, float mat[4][4])
{
	float loc[3], quat[4], scale, size[3];
	float f_no[3];

	/* location */
	BKE_mesh_calc_poly_center(mpoly, mloop, mvert, loc);
	/* rotation */
	{
		const float *v1, *v2, *v3;
		BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, f_no);
		v1 = mvert[mloop[0].v].co;
		v2 = mvert[mloop[1].v].co;
		v3 = mvert[mloop[2].v].co;
		tri_to_quat_ex(quat, v1, v2, v3, f_no);
	}
	/* scale */
	if (use_scale) {
		float area = BKE_mesh_calc_poly_area(mpoly, mloop, mvert);
		scale = sqrtf(area) * scale_fac;
	}
	else
		scale = 1.0f;
	size[0] = size[1] = size[2] = scale;

	loc_quat_size_to_mat4(mat, loc, quat, size);
}
Пример #2
0
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[4][4], int persistent_id[MAX_DUPLI_RECUR],
                           int level, short flag)
{
	Object *ob, *ob_iter;
	Base *base = NULL;
	DupliObject *dob;
	DerivedMesh *dm;
	Mesh *me = par->data;
	MLoopUV *mloopuv;
	MPoly *mpoly, *mp;
	MLoop *mloop;
	MVert *mvert;
	float pmat[4][4], imat[3][3], (*orco)[3] = NULL, w;
	int lay, oblay, totface, a;
	Scene *sce = NULL;
	Group *group = NULL;
	GroupObject *go = NULL;
	BMEditMesh *em;
	float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */
	
	/* simple preventing of too deep nested groups */
	if (level > MAX_DUPLI_RECUR) return;
	
	copy_m4_m4(pmat, par->obmat);
	em = BMEdit_FromObject(par);

	if (em) {
		dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
	}
	else {
		dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
	}

	totface = dm->getNumPolys(dm);
	mpoly = dm->getPolyArray(dm);
	mloop = dm->getLoopArray(dm);
	mvert = dm->getVertArray(dm);

	if (flag & DUPLILIST_FOR_RENDER) {
		orco = (float(*)[3])BKE_mesh_orco_verts_get(par);
		BKE_mesh_orco_verts_transform(me, orco, me->totvert, 0);
		mloopuv = me->mloopuv;
	}
	else {
		orco = NULL;
		mloopuv = NULL;
	}
	
	/* having to loop on scene OR group objects is NOT FUN */
	if (GS(id->name) == ID_SCE) {
		sce = (Scene *)id;
		lay = sce->lay;
		base = sce->base.first;
	}
	else {
		group = (Group *)id;
		lay = group->layer;
		go = group->gobject.first;
	}
	
	/* Start looping on Scene OR Group objects */
	while (base || go) {
		if (sce) {
			ob_iter = base->object;
			oblay = base->lay;
		}
		else {
			ob_iter = go->ob;
			oblay = ob_iter->lay;
		}
		
		if (lay & oblay && scene->obedit != ob_iter) {
			ob = ob_iter->parent;
			while (ob) {
				if (ob == par) {
					ob = ob_iter;
					/* End Scene/Group object loop, below is generic */
					
					/* par_space_mat - only used for groups so we can modify the space dupli's are in
					 * when par_space_mat is NULL ob->obmat can be used instead of ob__obmat
					 */
					if (par_space_mat)
						mult_m4_m4m4(ob__obmat, par_space_mat, ob->obmat);
					else
						copy_m4_m4(ob__obmat, ob->obmat);
					
					copy_m3_m4(imat, ob->parentinv);
						
					/* mballs have a different dupli handling */
					if (ob->type != OB_MBALL) ob->flag |= OB_DONE;  /* doesnt render */

					for (a = 0, mp = mpoly; a < totface; a++, mp++) {
						int mv1;
						int mv2;
						int mv3;
						/* int mv4; */ /* UNUSED */
						float *v1;
						float *v2;
						float *v3;
						/* float *v4; */ /* UNUSED */
						float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4];
						float f_no[3];
						MLoop *loopstart = mloop + mp->loopstart;

						if (UNLIKELY(mp->totloop < 3)) {
							continue;
						}
						else {
							BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mvert, f_no);
							v1 = mvert[(mv1 = loopstart[0].v)].co;
							v2 = mvert[(mv2 = loopstart[1].v)].co;
							v3 = mvert[(mv3 = loopstart[2].v)].co;
						}

						/* translation */
						BKE_mesh_calc_poly_center(mp, loopstart, mvert, cent);

						mul_m4_v3(pmat, cent);
						
						sub_v3_v3v3(cent, cent, pmat[3]);
						add_v3_v3(cent, ob__obmat[3]);
						
						copy_m4_m4(obmat, ob__obmat);
						
						copy_v3_v3(obmat[3], cent);
						
						/* rotation */
						tri_to_quat_ex(quat, v1, v2, v3, f_no);
						quat_to_mat3(mat, quat);
						
						/* scale */
						if (par->transflag & OB_DUPLIFACES_SCALE) {
							float size = BKE_mesh_calc_poly_area(mp, loopstart, mvert, f_no);
							size = sqrtf(size) * par->dupfacesca;
							mul_m3_fl(mat, size);
						}
						
						copy_m3_m3(mat3, mat);
						mul_m3_m3m3(mat, imat, mat3);
						
						copy_m4_m4(tmat, obmat);
						mul_m4_m4m3(obmat, tmat, mat);
						
						dob = new_dupli_object(lb, ob, obmat, par->lay, persistent_id, level, a, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED));
						if (flag & DUPLILIST_FOR_RENDER) {
							w = 1.0f / (float)mp->totloop;

							if (orco) {
								int j;
								for (j = 0; j < mpoly->totloop; j++) {
									madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w);
								}
							}

							if (mloopuv) {
								int j;
								for (j = 0; j < mpoly->totloop; j++) {
									madd_v2_v2fl(dob->orco, mloopuv[loopstart[j].v].uv, w);
								}
							}
						}
						
						if (ob->transflag & OB_DUPLI) {
							float tmpmat[4][4];
							copy_m4_m4(tmpmat, ob->obmat);
							copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */
							object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, persistent_id, level + 1, a, flag);
							copy_m4_m4(ob->obmat, tmpmat);
						}
					}
					
					break;
				}
				ob = ob->parent;
			}
		}
		if (sce) base = base->next;     /* scene loop */
		else go = go->next;             /* group loop */
	}

	if (orco)
		MEM_freeN(orco);
	
	dm->release(dm);
}