Beispiel #1
0
/* Returns a list of DupliObject
 * note; group dupli's already set transform matrix. see note in group_duplilist() */
ListBase *object_duplilist(Scene *sce, Object *ob)
{
	ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist");
	duplilist->first= duplilist->last= NULL;
	object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0);
	return duplilist;
}
Beispiel #2
0
static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR],
                            int level, short flag)
{
	DupliObject *dob;
	Group *group;
	GroupObject *go;
	float mat[4][4], tmat[4][4], id;
	
	if (ob->dup_group == NULL) return;
	group = ob->dup_group;
	
	/* simple preventing of too deep nested groups */
	if (level > MAX_DUPLI_RECUR) return;
	
	/* handles animated groups, and */

	/* we need to check update for objects that are not in scene... */
	if (flag & DUPLILIST_DO_UPDATE) {
		/* note: update is optional because we don't always need object
		 * transformations to be correct. Also fixes bug [#29616]. */
		group_handle_recalc_and_update(scene, ob, group);
	}

	if (group_is_animated(ob, group))
		flag |= DUPLILIST_ANIMATED;
	
	for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
		/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
		if (go->ob != ob) {
			
			/* group dupli offset, should apply after everything else */
			if (!is_zero_v3(group->dupli_ofs)) {
				copy_m4_m4(tmat, go->ob->obmat);
				sub_v3_v3v3(tmat[3], tmat[3], group->dupli_ofs);
				mult_m4_m4m4(mat, ob->obmat, tmat);
			}
			else {
				mult_m4_m4m4(mat, ob->obmat, go->ob->obmat);
			}
			
			dob = new_dupli_object(lb, go->ob, mat, ob->lay, persistent_id, level, id, OB_DUPLIGROUP, flag);

			/* check the group instance and object layers match, also that the object visible flags are ok. */
			if ((dob->origlay & group->layer) == 0 ||
			    ((G.is_rendering == FALSE) && dob->ob->restrictflag & OB_RESTRICT_VIEW) ||
			    ((G.is_rendering == TRUE)  && dob->ob->restrictflag & OB_RESTRICT_RENDER))
			{
				dob->no_draw = TRUE;
			}

			if (go->ob->transflag & OB_DUPLI) {
				copy_m4_m4(dob->ob->obmat, dob->mat);
				object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, persistent_id, level + 1, id, flag);
				copy_m4_m4(dob->ob->obmat, dob->omat);
			}
		}
	}
}
Beispiel #3
0
static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated)
{
	DupliObject *dob;
	Group *group;
	GroupObject *go;
	float mat[4][4], tmat[4][4];
	
	if (ob->dup_group==NULL) return;
	group= ob->dup_group;
	
	/* simple preventing of too deep nested groups */
	if (level>MAX_DUPLI_RECUR) return;
	
	/* handles animated groups, and */
	/* we need to check update for objects that are not in scene... */
	group_handle_recalc_and_update(scene, ob, group);
	animated= animated || group_is_animated(ob, group);
	
	for (go= group->gobject.first; go; go= go->next) {
		/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
		if (go->ob!=ob) {
			
			/* group dupli offset, should apply after everything else */
			if (!is_zero_v3(group->dupli_ofs)) {
				copy_m4_m4(tmat, go->ob->obmat);
				sub_v3_v3v3(tmat[3], tmat[3], group->dupli_ofs);
				mult_m4_m4m4(mat, ob->obmat, tmat);
			}
			else {
				mult_m4_m4m4(mat, ob->obmat, go->ob->obmat);
			}
			
			dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated);

			/* check the group instance and object layers match, also that the object visible flags are ok. */
			if (	(dob->origlay & group->layer)==0 ||
				(G.rendering==0 && dob->ob->restrictflag & OB_RESTRICT_VIEW) ||
				(G.rendering && dob->ob->restrictflag & OB_RESTRICT_RENDER)
			) {
				dob->no_draw= 1;
			}
			else {
				dob->no_draw= 0;
			}

			if (go->ob->transflag & OB_DUPLI) {
				copy_m4_m4(dob->ob->obmat, dob->mat);
				object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, level+1, animated);
				copy_m4_m4(dob->ob->obmat, dob->omat);
			}
		}
	}
}
Beispiel #4
0
/* Returns a list of DupliObject
 * note; group dupli's already set transform matrix. see note in group_duplilist() */
ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update, int for_render)
{
	ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist");
	int persistent_id[MAX_DUPLI_RECUR] = {0};
	int flag = 0;

	if (update)     flag |= DUPLILIST_DO_UPDATE;
	if (for_render) flag |= DUPLILIST_FOR_RENDER;

	duplilist->first = duplilist->last = NULL;
	object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, persistent_id, 0, 0, flag);
	return duplilist;
}
Beispiel #5
0
static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
                                  const float no_f[3], const short no_s[3])
{
	DupliObject *dob;
	vertexDupliData *vdd= userData;
	float vec[3], q2[4], mat[3][3], tmat[4][4], obmat[4][4];
	int origlay;
	
	mul_v3_m4v3(vec, vdd->pmat, co);
	sub_v3_v3(vec, vdd->pmat[3]);
	add_v3_v3(vec, vdd->obmat[3]);
	
	copy_m4_m4(obmat, vdd->obmat);
	copy_v3_v3(obmat[3], vec);
	
	if (vdd->par->transflag & OB_DUPLIROT) {
		if (no_f) {
			vec[0]= -no_f[0]; vec[1]= -no_f[1]; vec[2]= -no_f[2];
		}
		else if (no_s) {
			vec[0]= -no_s[0]; vec[1]= -no_s[1]; vec[2]= -no_s[2];
		}
		
		vec_to_quat( q2,vec, vdd->ob->trackflag, vdd->ob->upflag);
		
		quat_to_mat3( mat,q2);
		copy_m4_m4(tmat, obmat);
		mul_m4_m4m3(obmat, tmat, mat);
	}

	origlay = vdd->ob->lay;
	
	dob= new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS, vdd->animated);

	/* restore the original layer so that each dupli will have proper dob->origlay */
	vdd->ob->lay = origlay;

	if (vdd->orco)
		copy_v3_v3(dob->orco, vdd->orco[index]);
	
	if (vdd->ob->transflag & OB_DUPLI) {
		float tmpmat[4][4];
		copy_m4_m4(tmpmat, vdd->ob->obmat);
		copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
		object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->level+1, vdd->animated);
		copy_m4_m4(vdd->ob->obmat, tmpmat);
	}
}
Beispiel #6
0
static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated)
{
	DupliObject *dob;
	Group *group;
	GroupObject *go;
	float mat[4][4], tmat[4][4];
	
	if(ob->dup_group==NULL) return;
	group= ob->dup_group;
	
	/* simple preventing of too deep nested groups */
	if(level>MAX_DUPLI_RECUR) return;
	
	/* handles animated groups, and */
	/* we need to check update for objects that are not in scene... */
	group_handle_recalc_and_update(scene, ob, group);
	animated= animated || group_is_animated(ob, group);
	
	for(go= group->gobject.first; go; go= go->next) {
		/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
		if(go->ob!=ob) {
			
			/* Group Dupli Offset, should apply after everything else */
			if (group->dupli_ofs[0] || group->dupli_ofs[1] || group->dupli_ofs[2]) {
				Mat4CpyMat4(tmat, go->ob->obmat);
				VecSubf(tmat[3], tmat[3], group->dupli_ofs);
				Mat4MulMat4(mat, tmat, ob->obmat);
			} else {
				Mat4MulMat4(mat, go->ob->obmat, ob->obmat);
			}
			
			dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated);
			dob->no_draw= (dob->origlay & group->layer)==0;
			
			if(go->ob->transflag & OB_DUPLI) {
				Mat4CpyMat4(dob->ob->obmat, dob->mat);
				object_duplilist_recursive((ID *)group, scene, go->ob, lb, ob->obmat, level+1, animated);
				Mat4CpyMat4(dob->ob->obmat, dob->omat);
			}
		}
	}
}
Beispiel #7
0
static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
{
	DupliObject *dob;
	struct vertexDupliData *vdd= userData;
	float vec[3], q2[4], mat[3][3], tmat[4][4], obmat[4][4];
	
	VECCOPY(vec, co);
	Mat4MulVecfl(vdd->pmat, vec);
	VecSubf(vec, vec, vdd->pmat[3]);
	VecAddf(vec, vec, vdd->obmat[3]);
	
	Mat4CpyMat4(obmat, vdd->obmat);
	VECCOPY(obmat[3], vec);
	
	if(vdd->par->transflag & OB_DUPLIROT) {
		if(no_f) {
			vec[0]= -no_f[0]; vec[1]= -no_f[1]; vec[2]= -no_f[2];
		}
		else if(no_s) {
			vec[0]= -no_s[0]; vec[1]= -no_s[1]; vec[2]= -no_s[2];
		}
		
		vectoquat(vec, vdd->ob->trackflag, vdd->ob->upflag, q2);
		
		QuatToMat3(q2, mat);
		Mat4CpyMat4(tmat, obmat);
		Mat4MulMat43(obmat, tmat, mat);
	}
	dob= new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS, vdd->animated);
	if(vdd->orco)
		VECCOPY(dob->orco, vdd->orco[index]);
	
	if(vdd->ob->transflag & OB_DUPLI) {
		float tmpmat[4][4];
		Mat4CpyMat4(tmpmat, vdd->ob->obmat);
		Mat4CpyMat4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
		object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->level+1, vdd->animated);
		Mat4CpyMat4(vdd->ob->obmat, tmpmat);
	}
}
Beispiel #8
0
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated)
{
	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 = me->edit_btmesh;

	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 (G.rendering) {

		orco= (float(*)[3])get_mesh_orco_verts(par);
		transform_mesh_orco_verts(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];
						MLoop *loopstart= mloop + mp->loopstart;

						if (mp->totloop < 3) {
							/* highly unlikely but to be safe */
							continue;
						}
						else {
							v1= mvert[(mv1= loopstart[0].v)].co;
							v2= mvert[(mv2= loopstart[1].v)].co;
							v3= mvert[(mv3= loopstart[2].v)].co;
#if 0
							if (mp->totloop > 3) {
								v4= mvert[(mv4= loopstart[3].v)].co;
							}
#endif
						}

						/* translation */
						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( quat,v1, v2, v3);
						quat_to_mat3( mat,quat);
						
						/* scale */
						if (par->transflag & OB_DUPLIFACES_SCALE) {
							float size= mesh_calc_poly_area(mp, loopstart, mvert, NULL);
							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, a, OB_DUPLIFACES, animated);
						if (G.rendering) {
							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, level+1, animated);
							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);
}
Beispiel #9
0
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated)
{
	Object *ob, *ob_iter;
	Base *base = NULL;
	DupliObject *dob;
	DerivedMesh *dm;
	Mesh *me= par->data;
	MTFace *mtface;
	MFace *mface;
	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;
	EditMesh *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;
	
	Mat4CpyMat4(pmat, par->obmat);
	
	em = BKE_mesh_get_editmesh(me);
	if(em) {
		int totvert;
		
		dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
		
		totface= dm->getNumFaces(dm);
		mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp");
		dm->copyFaceArray(dm, mface);
		totvert= dm->getNumVerts(dm);
		mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp");
		dm->copyVertArray(dm, mvert);

		BKE_mesh_end_editmesh(me, em);
	}
	else {
		dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
		
		totface= dm->getNumFaces(dm);
		mface= dm->getFaceArray(dm);
		mvert= dm->getVertArray(dm);
	}

	if(G.rendering) {

		orco= (float(*)[3])get_mesh_orco_verts(par);
		transform_mesh_orco_verts(me, orco, me->totvert, 0);
		mtface= me->mtface;
	}
	else {
		orco= NULL;
		mtface= 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)
						Mat4MulMat4(ob__obmat, ob->obmat, par_space_mat);
					else
						Mat4CpyMat4(ob__obmat, ob->obmat);
					
					Mat3CpyMat4(imat, ob->parentinv);
						
					/* mballs have a different dupli handling */
					if(ob->type!=OB_MBALL) ob->flag |= OB_DONE;	/* doesnt render */

					for(a=0; a<totface; a++) {
						int mv1 = mface[a].v1;
						int mv2 = mface[a].v2;
						int mv3 = mface[a].v3;
						int mv4 = mface[a].v4;
						float *v1= mvert[mv1].co;
						float *v2= mvert[mv2].co;
						float *v3= mvert[mv3].co;
						float *v4= (mv4)? mvert[mv4].co: NULL;
						float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4];

						/* translation */
						if(v4)
							CalcCent4f(cent, v1, v2, v3, v4);
						else
							CalcCent3f(cent, v1, v2, v3);
						Mat4MulVecfl(pmat, cent);
						
						VecSubf(cent, cent, pmat[3]);
						VecAddf(cent, cent, ob__obmat[3]);
						
						Mat4CpyMat4(obmat, ob__obmat);
						
						VECCOPY(obmat[3], cent);
						
						/* rotation */
						triatoquat(v1, v2, v3, quat);
						QuatToMat3(quat, mat);
						
						/* scale */
						if(par->transflag & OB_DUPLIFACES_SCALE) {
							float size= v4?AreaQ3Dfl(v1, v2, v3, v4):AreaT3Dfl(v1, v2, v3);
							size= sqrt(size) * par->dupfacesca;
							Mat3MulFloat(mat[0], size);
						}
						
						Mat3CpyMat3(mat3, mat);
						Mat3MulMat3(mat, imat, mat3);
						
						Mat4CpyMat4(tmat, obmat);
						Mat4MulMat43(obmat, tmat, mat);
						
						dob= new_dupli_object(lb, ob, obmat, lay, a, OB_DUPLIFACES, animated);
						if(G.rendering) {
							w= (mv4)? 0.25f: 1.0f/3.0f;

							if(orco) {
								VECADDFAC(dob->orco, dob->orco, orco[mv1], w);
								VECADDFAC(dob->orco, dob->orco, orco[mv2], w);
								VECADDFAC(dob->orco, dob->orco, orco[mv3], w);
								if(mv4)
									VECADDFAC(dob->orco, dob->orco, orco[mv4], w);
							}

							if(mtface) {
								dob->uv[0] += w*mtface[a].uv[0][0];
								dob->uv[1] += w*mtface[a].uv[0][1];
								dob->uv[0] += w*mtface[a].uv[1][0];
								dob->uv[1] += w*mtface[a].uv[1][1];
								dob->uv[0] += w*mtface[a].uv[2][0];
								dob->uv[1] += w*mtface[a].uv[2][1];

								if(mv4) {
									dob->uv[0] += w*mtface[a].uv[3][0];
									dob->uv[1] += w*mtface[a].uv[3][1];
								}
							}
						}
						
						if(ob->transflag & OB_DUPLI) {
							float tmpmat[4][4];
							Mat4CpyMat4(tmpmat, ob->obmat);
							Mat4CpyMat4(ob->obmat, obmat); /* pretend we are really this mat */
							object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, level+1, animated);
							Mat4CpyMat4(ob->obmat, tmpmat);
						}
					}
					
					break;
				}
				ob= ob->parent;
			}
		}
		if (sce)	base= base->next;	/* scene loop */
		else		go= go->next;		/* group loop */
	}
	
	if(par->mode & OB_MODE_EDIT) {
		MEM_freeN(mface);
		MEM_freeN(mvert);
	}

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