void mesh_deform_bind(
        Scene *scene, MeshDeformModifierData *mmd, DerivedMesh *cagedm,
        float *vertexcos, int totvert, float cagemat[4][4])
{
	MeshDeformBind mdb;
	MVert *mvert;
	int a;

	waitcursor(1);
	start_progress_bar();

	memset(&mdb, 0, sizeof(MeshDeformBind));

	/* get mesh and cage mesh */
	mdb.vertexcos = MEM_callocN(sizeof(float) * 3 * totvert, "MeshDeformCos");
	mdb.totvert = totvert;
	
	mdb.cagedm = cagedm;
	mdb.totcagevert = mdb.cagedm->getNumVerts(mdb.cagedm);
	mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.totcagevert, "MeshDeformBindCos");
	copy_m4_m4(mdb.cagemat, cagemat);

	mvert = mdb.cagedm->getVertArray(mdb.cagedm);
	for (a = 0; a < mdb.totcagevert; a++)
		copy_v3_v3(mdb.cagecos[a], mvert[a].co);
	for (a = 0; a < mdb.totvert; a++)
		mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a * 3);

	/* solve */
	harmonic_coordinates_bind(scene, mmd, &mdb);

	/* assign bind variables */
	mmd->bindcagecos = (float *)mdb.cagecos;
	mmd->totvert = mdb.totvert;
	mmd->totcagevert = mdb.totcagevert;
	copy_m4_m4(mmd->bindmat, mmd->object->obmat);

	/* transform bindcagecos to world space */
	for (a = 0; a < mdb.totcagevert; a++)
		mul_m4_v3(mmd->object->obmat, mmd->bindcagecos + a * 3);

	/* free */
	MEM_freeN(mdb.vertexcos);

	/* compact weights */
	modifier_mdef_compact_influences((ModifierData *)mmd);

	end_progress_bar();
	waitcursor(0);
}
Exemple #2
0
static void env_rotate_scene(Render *re, float mat[][4], int mode)
{
	GroupObject *go;
	ObjectRen *obr;
	ObjectInstanceRen *obi;
	LampRen *lar = NULL;
	HaloRen *har = NULL;
	float imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3], tmpmat[4][4];
	int a;
	
	if (mode == 0) {
		invert_m4_m4(tmat, mat);
		copy_m3_m4(imat, tmat);
	}
	else {
		copy_m4_m4(tmat, mat);
		copy_m3_m4(imat, mat);
	}

	for (obi = re->instancetable.first; obi; obi = obi->next) {
		/* append or set matrix depending on dupli */
		if (obi->flag & R_DUPLI_TRANSFORMED) {
			copy_m4_m4(tmpmat, obi->mat);
			mult_m4_m4m4(obi->mat, tmat, tmpmat);
		}
		else if (mode == 1)
			copy_m4_m4(obi->mat, tmat);
		else
			unit_m4(obi->mat);

		copy_m3_m4(cmat, obi->mat);
		invert_m3_m3(obi->nmat, cmat);
		transpose_m3(obi->nmat);

		/* indicate the renderer has to use transform matrices */
		if (mode == 0)
			obi->flag &= ~R_ENV_TRANSFORMED;
		else
			obi->flag |= R_ENV_TRANSFORMED;
	}
	

	for (obr = re->objecttable.first; obr; obr = obr->next) {
		for (a = 0; a < obr->tothalo; a++) {
			if ((a & 255) == 0) har = obr->bloha[a >> 8];
			else har++;
		
			mul_m4_v3(tmat, har->co);
		}
	}
/**
 * This function returns the coordinate and normal of a barycentric u,v for a face defined by the primitive_id index.
 * The returned coordinate is extruded along the normal by cage_extrusion
 */
static void calc_point_from_barycentric_extrusion(
        TriTessFace *triangles,
        float mat[4][4], float imat[4][4],
        int primitive_id, float u, float v,
        float cage_extrusion,
        float r_co[3], float r_dir[3],
        const bool is_cage)
{
	float data[3][3];
	float coord[3];
	float dir[3];
	float cage[3];
	bool is_smooth;

	TriTessFace *triangle = &triangles[primitive_id];
	is_smooth = triangle->is_smooth || is_cage;

	copy_v3_v3(data[0], triangle->mverts[0]->co);
	copy_v3_v3(data[1], triangle->mverts[1]->co);
	copy_v3_v3(data[2], triangle->mverts[2]->co);

	interp_barycentric_tri_v3(data, u, v, coord);

	if (is_smooth) {
		normal_short_to_float_v3(data[0], triangle->mverts[0]->no);
		normal_short_to_float_v3(data[1], triangle->mverts[1]->no);
		normal_short_to_float_v3(data[2], triangle->mverts[2]->no);

		interp_barycentric_tri_v3(data, u, v, dir);
		normalize_v3(dir);
	}
	else {
		copy_v3_v3(dir, triangle->normal);
	}

	mul_v3_v3fl(cage, dir, cage_extrusion);
	add_v3_v3(coord, cage);

	normalize_v3(dir);
	negate_v3(dir);

	/* convert from local to world space */
	mul_m4_v3(mat, coord);
	mul_transposed_mat3_m4_v3(imat, dir);
	normalize_v3(dir);

	copy_v3_v3(r_co, coord);
	copy_v3_v3(r_dir, dir);
}
Exemple #4
0
void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props)
{
	EditBone *ebone;
	float scale = mat4_to_scale(mat);   /* store the scale of the matrix here to use on envelopes */
	float mat3[3][3];

	copy_m3_m4(mat3, mat);
	normalize_m3(mat3);
	/* Do the rotations */
	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
		float tmat[3][3];

		/* find the current bone's roll matrix */
		ED_armature_ebone_to_mat3(ebone, tmat);

		/* transform the roll matrix */
		mul_m3_m3m3(tmat, mat3, tmat);

		/* transform the bone */
		mul_m4_v3(mat, ebone->head);
		mul_m4_v3(mat, ebone->tail);

		/* apply the transformed roll back */
		mat3_to_vec_roll(tmat, NULL, &ebone->roll);

		if (do_props) {
			ebone->rad_head *= scale;
			ebone->rad_tail *= scale;
			ebone->dist     *= scale;

			/* we could be smarter and scale by the matrix along the x & z axis */
			ebone->xwidth   *= scale;
			ebone->zwidth   *= scale;
		}
	}
}
Exemple #5
0
/**
 * cloth_to_object - copies the deformed vertices to the object.
 *
 **/
static void cloth_to_object (Object *ob,  ClothModifierData *clmd, float (*vertexCos)[3])
{
	unsigned int	i = 0;
	Cloth *cloth = clmd->clothObject;

	if (clmd->clothObject) {
		/* inverse matrix is not uptodate... */
		invert_m4_m4(ob->imat, ob->obmat);

		for (i = 0; i < cloth->numverts; i++) {
			copy_v3_v3 (vertexCos[i], cloth->verts[i].x);
			mul_m4_v3(ob->imat, vertexCos[i]);	/* cloth is in global coords */
		}
	}
}
static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
{
	ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
	ParticleEditSettings *pset= PE_settings(scene);
	ParticleData *pa;
	PTCacheEdit *edit;
	PTCacheEditPoint *point;
	PTCacheEditKey *ekey = NULL;
	HairKey *key;
	int i, k;
	float hairmat[4][4];

	if (!ob || !psys || psys->flag & PSYS_GLOBAL_HAIR)
		return;

	if (!psys->part || psys->part->type != PART_HAIR)
		return;
	
	edit = psys->edit;
	point= edit ? edit->points : NULL;

	for (i=0, pa=psys->particles; i<psys->totpart; i++, pa++) {
		if (point) {
			ekey = point->keys;
			point++;
		}

		psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);

		for (k=0, key=pa->hair; k<pa->totkey; k++, key++) {
			mul_m4_v3(hairmat, key->co);
			
			if (ekey) {
				ekey->flag &= ~PEK_USE_WCO;
				ekey++;
			}
		}
	}

	psys_free_path_cache(psys, psys->edit);

	psys->flag |= PSYS_GLOBAL_HAIR;

	if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF))
		pset->brushtype = PE_BRUSH_NONE;

	PE_update_object(scene, ob, 0);
}
Exemple #7
0
/* Meta object density, brute force for now 
 * (might be good enough anyway, don't need huge number of metaobs to model volumetric objects */
static float metadensity(Object *ob, const float co[3])
{
	float mat[4][4], imat[4][4], dens = 0.f;
	MetaBall *mb = (MetaBall *)ob->data;
	MetaElem *ml;
	
	/* transform co to meta-element */
	float tco[3] = {co[0], co[1], co[2]};
	mult_m4_m4m4(mat, R.viewmat, ob->obmat);
	invert_m4_m4(imat, mat);
	mul_m4_v3(imat, tco);
	
	for (ml = mb->elems.first; ml; ml = ml->next) {
		float bmat[3][3], dist2;
		
		/* element rotation transform */
		float tp[3] = {ml->x - tco[0], ml->y - tco[1], ml->z - tco[2]};
		quat_to_mat3(bmat, ml->quat);
		transpose_m3(bmat); /* rot.only, so inverse == transpose */
		mul_m3_v3(bmat, tp);

		/* MB_BALL default */
		switch (ml->type) {
			case MB_ELIPSOID:
				tp[0] /= ml->expx, tp[1] /= ml->expy, tp[2] /= ml->expz;
				break;
			case MB_CUBE:
				tp[2] = (tp[2] > ml->expz) ? (tp[2] - ml->expz) : ((tp[2] < -ml->expz) ? (tp[2] + ml->expz) : 0.f);
			/* no break, xy as plane */
			case MB_PLANE:
				tp[1] = (tp[1] > ml->expy) ? (tp[1] - ml->expy) : ((tp[1] < -ml->expy) ? (tp[1] + ml->expy) : 0.f);
			/* no break, x as tube */
			case MB_TUBE:
				tp[0] = (tp[0] > ml->expx) ? (tp[0] - ml->expx) : ((tp[0] < -ml->expx) ? (tp[0] + ml->expx) : 0.f);
		}

		/* ml->rad2 is not set */
		dist2 = 1.0f - (dot_v3v3(tp, tp) / (ml->rad * ml->rad));
		if (dist2 > 0.f)
			dens += (ml->flag & MB_NEGATIVE) ? -ml->s * dist2 * dist2 * dist2 : ml->s * dist2 * dist2 * dist2;
	}
	
	dens -= mb->thresh;
	return (dens < 0.f) ? 0.f : dens;
}
Exemple #8
0
static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int level, int animated)
{
	Object *ob, *obar[256]= {NULL};
	Curve *cu;
	struct chartrans *ct, *chartransdata;
	float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof;
	int slen, a;
	
	/* simple preventing of too deep nested groups */
	if (level>MAX_DUPLI_RECUR) return;
	
	copy_m4_m4(pmat, par->obmat);
	
	/* in par the family name is stored, use this to find the other objects */
	
	chartransdata= BKE_text_to_curve(G.main, scene, par, FO_DUPLI);
	if (chartransdata==NULL) return;

	cu= par->data;
	slen= strlen(cu->str);
	fsize= cu->fsize;
	xof= cu->xof;
	yof= cu->yof;
	
	ct= chartransdata;
	
	for (a=0; a<slen; a++, ct++) {
		
		ob= find_family_object(obar, cu->family, cu->str[a]);
		if (ob) {
			vec[0]= fsize*(ct->xof - xof);
			vec[1]= fsize*(ct->yof - yof);
			vec[2]= 0.0;
			
			mul_m4_v3(pmat, vec);
			
			copy_m4_m4(obmat, par->obmat);
			copy_v3_v3(obmat[3], vec);
			
			new_dupli_object(lb, ob, obmat, par->lay, a, OB_DUPLIVERTS, animated);
		}
	}
	
	MEM_freeN(chartransdata);
}
Exemple #9
0
static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
{
	ClothVertex *verts = NULL;
	Cloth *cloth;
	ListBase *effectors = NULL;
	MVert *mvert;
	unsigned int i = 0;
	int ret = 0;

	/* simulate 1 frame forward */
	cloth = clmd->clothObject;
	verts = cloth->verts;
	mvert = result->getVertArray(result);

	/* force any pinned verts to their constrained location. */
	for (i = 0; i < clmd->clothObject->numverts; i++, verts++) {
		/* save the previous position. */
		copy_v3_v3(verts->xold, verts->xconst);
		copy_v3_v3(verts->txold, verts->x);

		/* Get the current position. */
		copy_v3_v3(verts->xconst, mvert[i].co);
		mul_m4_v3(ob->obmat, verts->xconst);
	}

	effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights, true);

	/* Support for dynamic vertex groups, changing from frame to frame */
	cloth_apply_vgroup ( clmd, result );
	cloth_update_springs( clmd );
	
	// TIMEIT_START(cloth_step)

	/* call the solver. */
	if (solvers [clmd->sim_parms->solver_type].solver)
		ret = solvers[clmd->sim_parms->solver_type].solver(ob, framenr, clmd, effectors);

	// TIMEIT_END(cloth_step)

	pdEndEffectors(&effectors);

	// printf ( "%f\n", ( float ) tval() );
	
	return ret;
}
Exemple #10
0
/* don't set windows active in here, is used by renderwin too */
void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d)
{
	if (rv3d->persp == RV3D_CAMOB) {      /* obs/camera */
		if (v3d->camera) {
			BKE_object_where_is_calc(scene, v3d->camera);
			obmat_to_viewmat(v3d, rv3d, v3d->camera, 0);
		}
		else {
			quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
			rv3d->viewmat[3][2] -= rv3d->dist;
		}
	}
	else {
		/* should be moved to better initialize later on XXX */
		if (rv3d->viewlock)
			ED_view3d_lock(rv3d);
		
		quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
		if (rv3d->persp == RV3D_PERSP) rv3d->viewmat[3][2] -= rv3d->dist;
		if (v3d->ob_centre) {
			Object *ob = v3d->ob_centre;
			float vec[3];
			
			copy_v3_v3(vec, ob->obmat[3]);
			if (ob->type == OB_ARMATURE && v3d->ob_centre_bone[0]) {
				bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, v3d->ob_centre_bone);
				if (pchan) {
					copy_v3_v3(vec, pchan->pose_mat[3]);
					mul_m4_v3(ob->obmat, vec);
				}
			}
			translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
		}
		else if (v3d->ob_centre_cursor) {
			float vec[3];
			copy_v3_v3(vec, give_cursor(scene, v3d));
			translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
		}
		else {
			translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]);
		}
	}
}
static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max)
{
    //TODO:
    // *better bb.. calculated without rotations of bb
    // *maybe cache that better-fitted-BB at the InstanceRayObject
    InstanceRayObject *obj = (InstanceRayObject *)o;

    float m[3], M[3], t[3];
    int i, j;
    INIT_MINMAX(m, M);
    RE_rayobject_merge_bb(obj->target, m, M);

    //There must be a faster way than rotating all the 8 vertexs of the BB
    for (i = 0; i < 8; i++) {
        for (j = 0; j < 3; j++) t[j] = (i & (1 << j)) ? M[j] : m[j];
        mul_m4_v3(obj->target2global, t);
        DO_MINMAX(t, min, max);
    }
}
/* called from drawview.c, as an extra per-window draw option */
void drawPropCircle(const struct bContext *C, TransInfo *t)
{
	if (t->flag & T_PROP_EDIT) {
		RegionView3D *rv3d = CTX_wm_region_view3d(C);
		float tmat[4][4], imat[4][4];
		float center[3];

		UI_ThemeColor(TH_GRID);

		if(t->spacetype == SPACE_VIEW3D && rv3d != NULL)
		{
			copy_m4_m4(tmat, rv3d->viewmat);
			invert_m4_m4(imat, tmat);
		}
		else
		{
			unit_m4(tmat);
			unit_m4(imat);
		}

		glPushMatrix();

		VECCOPY(center, t->center);

		if((t->spacetype == SPACE_VIEW3D) && t->obedit)
		{
			mul_m4_v3(t->obedit->obmat, center); /* because t->center is in local space */
		}
		else if(t->spacetype == SPACE_IMAGE)
		{
			float aspx, aspy;

			ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
			glScalef(1.0f/aspx, 1.0f/aspy, 1.0);
		}

		set_inverted_drawing(1);
		drawcircball(GL_LINE_LOOP, center, t->prop_size, imat);
		set_inverted_drawing(0);

		glPopMatrix();
	}
}
Exemple #13
0
/* Convert Grease Pencil points to screen-space values
 * WARNING: This assumes that the caller has already checked whether the stroke in question can be drawn
 */
void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
                    int *r_x, int *r_y)
{
	ARegion *ar = gsc->ar;
	View2D *v2d = gsc->v2d;
	rctf *subrect = gsc->subrect;
	int xyval[2];
	
	/* sanity checks */
	BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
	BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
	
	
	if (gps->flag & GP_STROKE_3DSPACE) {
		if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
			*r_x = xyval[0];
			*r_y = xyval[1];
		}
		else {
			*r_x = V2D_IS_CLIPPED;
			*r_y = V2D_IS_CLIPPED;
		}
	}
	else if (gps->flag & GP_STROKE_2DSPACE) {
		float vec[3] = {pt->x, pt->y, 0.0f};
		mul_m4_v3(gsc->mat, vec);
		UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y);
	}
	else {
		if (subrect == NULL) {
			/* normal 3D view (or view space) */
			*r_x = (int)(pt->x / 100 * ar->winx);
			*r_y = (int)(pt->y / 100 * ar->winy);
		}
		else {
			/* camera view, use subrect */
			*r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
			*r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
		}
	}
}
Exemple #14
0
static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
{
	ClothVertex *verts = NULL;
	Cloth *cloth;
	ListBase *effectors = NULL;
	MVert *mvert;
	unsigned int i = 0;
	int ret = 0;

	/* simulate 1 frame forward */
	cloth = clmd->clothObject;
	verts = cloth->verts;
	mvert = result->getVertArray(result);

	/* force any pinned verts to their constrained location. */
	for(i = 0; i < clmd->clothObject->numverts; i++, verts++) {
		/* save the previous position. */
		VECCOPY(verts->xold, verts->xconst);
		VECCOPY(verts->txold, verts->x);

		/* Get the current position. */
		VECCOPY(verts->xconst, mvert[i].co);
		mul_m4_v3(ob->obmat, verts->xconst);
	}

	effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights);
	
	tstart();

	/* call the solver. */
	if(solvers [clmd->sim_parms->solver_type].solver)
		ret = solvers[clmd->sim_parms->solver_type].solver(ob, framenr, clmd, effectors);

	tend();

	pdEndEffectors(&effectors);

	// printf ( "%f\n", ( float ) tval() );
	
	return ret;
}
static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) 
{
	RegionView3D *rv3d = CTX_wm_region_view3d(C);
	Object *obedit = CTX_data_edit_object(C);
	EditBone *bone;
	float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
	char name[MAXBONENAME];
	
	RNA_string_get(op->ptr, "name", name);
	
	copy_v3_v3(curs, ED_view3d_cursor3d_get(CTX_data_scene(C), CTX_wm_view3d(C)));

	/* Get inverse point for head and orientation for tail */
	invert_m4_m4(obedit->imat, obedit->obmat);
	mul_m4_v3(obedit->imat, curs);

	if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
		copy_m3_m4(obmat, rv3d->viewmat);
	else unit_m3(obmat);
	
	copy_m3_m4(viewmat, obedit->obmat);
	mul_m3_m3m3(totmat, obmat, viewmat);
	invert_m3_m3(imat, totmat);
	
	ED_armature_deselect_all(obedit);
	
	/*	Create a bone	*/
	bone = ED_armature_edit_bone_add(obedit->data, name);

	copy_v3_v3(bone->head, curs);
	
	if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
		add_v3_v3v3(bone->tail, bone->head, imat[1]);   // bone with unit length 1
	else
		add_v3_v3v3(bone->tail, bone->head, imat[2]);   // bone with unit length 1, pointing up Z

	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);

	return OPERATOR_FINISHED;
}
Exemple #16
0
/**
 * cloth_to_object - copies the deformed vertices to the object.
 *
 **/
static void cloth_to_object (Object *ob,  ClothModifierData *clmd, DerivedMesh *dm)
{
	unsigned int	i = 0;
	MVert *mvert = NULL;
	unsigned int numverts;
	Cloth *cloth = clmd->clothObject;

	if (clmd->clothObject) {
		/* inverse matrix is not uptodate... */
		invert_m4_m4(ob->imat, ob->obmat);

		mvert = CDDM_get_verts(dm);
		numverts = dm->getNumVerts(dm);

		for (i = 0; i < numverts; i++)
		{
			VECCOPY (mvert[i].co, cloth->verts[i].x);
			mul_m4_v3(ob->imat, mvert[i].co);	/* cloth is in global coords */
		}
	}
}
Exemple #17
0
/* do the regular mapping options for blender textures */
static void node_shader_exec_mapping(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
{
	TexMapping *texmap= node->storage;
	float *vec= out[0]->vec;
	
	/* stack order input:  vector */
	/* stack order output: vector */
	nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
	mul_m4_v3(texmap->mat, vec);
	
	if (texmap->flag & TEXMAP_CLIP_MIN) {
		if (vec[0]<texmap->min[0]) vec[0]= texmap->min[0];
		if (vec[1]<texmap->min[1]) vec[1]= texmap->min[1];
		if (vec[2]<texmap->min[2]) vec[2]= texmap->min[2];
	}
	if (texmap->flag & TEXMAP_CLIP_MAX) {
		if (vec[0]>texmap->max[0]) vec[0]= texmap->max[0];
		if (vec[1]>texmap->max[1]) vec[1]= texmap->max[1];
		if (vec[2]>texmap->max[2]) vec[2]= texmap->max[2];
	}
}
Exemple #18
0
void initElbeemMesh(struct Scene *scene, struct Object *ob,
                    int *numVertices, float **vertices,
                    int *numTriangles, int **triangles,
                    int useGlobalCoords, int modifierIndex)
{
	DerivedMesh *dm;
	const MVert *mvert;
	const MLoop *mloop;
	const MLoopTri *looptri, *lt;
	int i, mvert_num, looptri_num;
	float *verts;
	int *tris;

	dm = mesh_create_derived_index_render(scene, ob, CD_MASK_BAREMESH, modifierIndex);

	mvert = dm->getVertArray(dm);
	mloop = dm->getLoopArray(dm);
	looptri = dm->getLoopTriArray(dm);
	mvert_num = dm->getNumVerts(dm);
	looptri_num = dm->getNumLoopTri(dm);

	*numVertices = mvert_num;
	verts = MEM_mallocN(mvert_num * sizeof(float[3]), "elbeemmesh_vertices");
	for (i = 0; i < mvert_num; i++) {
		copy_v3_v3(&verts[i * 3], mvert[i].co);
		if (useGlobalCoords) { mul_m4_v3(ob->obmat, &verts[i * 3]); }
	}
	*vertices = verts;

	*numTriangles = looptri_num;
	tris = MEM_mallocN(looptri_num * sizeof(int[3]), "elbeemmesh_triangles");
	for (i = 0, lt = looptri; i < looptri_num; i++, lt++) {
		tris[(i * 3) + 0] = mloop[lt->tri[0]].v;
		tris[(i * 3) + 1] = mloop[lt->tri[1]].v;
		tris[(i * 3) + 2] = mloop[lt->tri[2]].v;
	}
	*triangles = tris;

	dm->release(dm);
}
Exemple #19
0
static void precalculate_effector(EffectorCache *eff)
{
	unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra);
	if (!eff->pd->rng)
		eff->pd->rng = BLI_rng_new(eff->pd->seed + cfra);
	else
		BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra);

	if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) {
		Curve *cu= eff->ob->data;
		if (cu->flag & CU_PATH) {
			if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL)
				BKE_displist_make_curveTypes(eff->scene, eff->ob, 0);

			if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) {
				where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
				mul_m4_v3(eff->ob->obmat, eff->guide_loc);
				mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir);
			}
		}
	}
	else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) {
		eff->surmd = (SurfaceModifierData *)modifiers_findByType( eff->ob, eModifierType_Surface );
		if (eff->ob->type == OB_CURVE)
			eff->flag |= PE_USE_NORMAL_DATA;
	}
	else if (eff->psys)
		psys_update_particle_tree(eff->psys, eff->scene->r.cfra);

	/* Store object velocity */
	if (eff->ob) {
		float old_vel[3];

		BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra - 1.0f);
		copy_v3_v3(old_vel, eff->ob->obmat[3]);
		BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra);
		sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel);
	}
}
/* reset parent matrix for all layers */
void ED_gpencil_reset_layers_parent(bGPdata *gpd)
{
	bGPDspoint *pt;
	int i;
	float diff_mat[4][4];
	float cur_mat[4][4];

	for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
		if (gpl->parent != NULL) {
			/* calculate new matrix */
			if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
				invert_m4_m4(cur_mat, gpl->parent->obmat);
			}
			else if (gpl->partype == PARBONE) {
				bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr);
				if (pchan) {
					float tmp_mat[4][4];
					mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat);
					invert_m4_m4(cur_mat, tmp_mat);
				}
			}

			/* only redo if any change */
			if (!equals_m4m4(gpl->inverse, cur_mat)) {
				/* first apply current transformation to all strokes */
				ED_gpencil_parent_location(gpl, diff_mat);
				for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
					for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
						for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
							mul_m4_v3(diff_mat, &pt->x);
						}
					}
				}
				/* set new parent matrix */
				copy_m4_m4(gpl->inverse, cur_mat);
			}
		}
	}
}
Exemple #21
0
static void TargetSnapActive(TransInfo *t)
{
	/* Only need to calculate once */
	if ((t->tsnap.status & TARGET_INIT) == 0) {
		if (calculateCenterActive(t, true, t->tsnap.snapTarget)) {
			if (t->flag & (T_EDIT | T_POSE)) {
				Object *ob = t->obedit ? t->obedit : t->poseobj;
				mul_m4_v3(ob->obmat, t->tsnap.snapTarget);
			}

			TargetSnapOffset(t, NULL);

			t->tsnap.status |= TARGET_INIT;
		}
		/* No active, default to median */
		else {
			t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
			t->tsnap.targetSnap = TargetSnapMedian;
			TargetSnapMedian(t);
		}
	}
}
Exemple #22
0
void BKE_mball_transform(MetaBall *mb, float mat[4][4])
{
    MetaElem *me;
    float quat[4];
    const float scale = mat4_to_scale(mat);
    const float scale_sqrt = sqrtf(scale);

    mat4_to_quat(quat, mat);

    for (me = mb->elems.first; me; me = me->next) {
        mul_m4_v3(mat, &me->x);
        mul_qt_qtqt(me->quat, quat, me->quat);
        me->rad *= scale;
        /* hrmf, probably elems shouldn't be
         * treating scale differently - campbell */
        if (!MB_TYPE_SIZE_SQUARED(me->type)) {
            mul_v3_fl(&me->expx, scale);
        }
        else {
            mul_v3_fl(&me->expx, scale_sqrt);
        }
    }
}
Exemple #23
0
/* perform baking for the targets on the current frame */
static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
{
	MPathTarget *mpt;
	
	/* for each target, check if it can be baked on the current frame */
	for (mpt= targets->first; mpt; mpt= mpt->next) {	
		bMotionPath *mpath= mpt->mpath;
		bMotionPathVert *mpv;
		
		/* current frame must be within the range the cache works for 
		 *	- is inclusive of the first frame, but not the last otherwise we get buffer overruns
		 */
		if ((CFRA < mpath->start_frame) || (CFRA >= mpath->end_frame))
			continue;
		
		/* get the relevant cache vert to write to */
		mpv= mpath->points + (CFRA - mpath->start_frame);
		
		/* pose-channel or object path baking? */
		if (mpt->pchan) {
			/* heads or tails */
			if (mpath->flag & MOTIONPATH_FLAG_BHEAD) {
				copy_v3_v3(mpv->co, mpt->pchan->pose_head);
			}
			else {
				copy_v3_v3(mpv->co, mpt->pchan->pose_tail);
			}
			
			/* result must be in worldspace */
			mul_m4_v3(mpt->ob->obmat, mpv->co);
		}
		else {
			/* worldspace object location */
			copy_v3_v3(mpv->co, mpt->ob->obmat[3]);
		}
	}
}
static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
                                ParticleSystemModifierData *psmd, Scene *scene, Object *ob,
                                DerivedMesh *to_explode)
{
	DerivedMesh *explode, *dm = to_explode;
	MFace *mf = NULL, *mface;
	/* ParticleSettings *part=psmd->psys->part; */ /* UNUSED */
	ParticleSimulationData sim = {NULL};
	ParticleData *pa = NULL, *pars = psmd->psys->particles;
	ParticleKey state, birth;
	EdgeHash *vertpahash;
	EdgeHashIterator *ehi;
	float *vertco = NULL, imat[4][4];
	float rot[4];
	float cfra;
	/* float timestep; */
	const int *facepa = emd->facepa;
	int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0;
	int i, v, u;
	unsigned int ed_v1, ed_v2, mindex = 0;
	MTFace *mtface = NULL, *mtf;

	totface = dm->getNumTessFaces(dm);
	totvert = dm->getNumVerts(dm);
	mface = dm->getTessFaceArray(dm);
	totpart = psmd->psys->totpart;

	sim.scene = scene;
	sim.ob = ob;
	sim.psys = psmd->psys;
	sim.psmd = psmd;

	/* timestep = psys_get_timestep(&sim); */

	cfra = BKE_scene_frame_get(scene);

	/* hash table for vertice <-> particle relations */
	vertpahash = BLI_edgehash_new(__func__);

	for (i = 0; i < totface; i++) {
		if (facepa[i] != totpart) {
			pa = pars + facepa[i];

			if ((pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) ||
			    (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) ||
			    (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0))
			{
				delface++;
				continue;
			}
		}

		/* do mindex + totvert to ensure the vertex index to be the first
		 * with BLI_edgehashIterator_getKey */
		if (facepa[i] == totpart || cfra < (pars + facepa[i])->time)
			mindex = totvert + totpart;
		else 
			mindex = totvert + facepa[i];

		mf = &mface[i];

		/* set face vertices to exist in particle group */
		BLI_edgehash_reinsert(vertpahash, mf->v1, mindex, NULL);
		BLI_edgehash_reinsert(vertpahash, mf->v2, mindex, NULL);
		BLI_edgehash_reinsert(vertpahash, mf->v3, mindex, NULL);
		if (mf->v4)
			BLI_edgehash_reinsert(vertpahash, mf->v4, mindex, NULL);
	}

	/* make new vertice indexes & count total vertices after duplication */
	ehi = BLI_edgehashIterator_new(vertpahash);
	for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
		BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup));
		totdup++;
	}
	BLI_edgehashIterator_free(ehi);

	/* the final duplicated vertices */
	explode = CDDM_from_template_ex(dm, totdup, 0, totface - delface, 0, 0, CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
	mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname);
	/*dupvert = CDDM_get_verts(explode);*/

	/* getting back to object space */
	invert_m4_m4(imat, ob->obmat);

	psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);

	/* duplicate & displace vertices */
	ehi = BLI_edgehashIterator_new(vertpahash);
	for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
		MVert source;
		MVert *dest;

		/* get particle + vertex from hash */
		BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2);
		ed_v2 -= totvert;
		v = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));

		dm->getVert(dm, ed_v1, &source);
		dest = CDDM_get_vert(explode, v);

		DM_copy_vert_data(dm, explode, ed_v1, v, 1);
		*dest = source;

		if (ed_v2 != totpart) {
			/* get particle */
			pa = pars + ed_v2;

			psys_get_birth_coords(&sim, pa, &birth, 0, 0);

			state.time = cfra;
			psys_get_particle_state(&sim, ed_v2, &state, 1);

			vertco = CDDM_get_vert(explode, v)->co;
			mul_m4_v3(ob->obmat, vertco);

			sub_v3_v3(vertco, birth.co);

			/* apply rotation, size & location */
			sub_qt_qtqt(rot, state.rot, birth.rot);
			mul_qt_v3(rot, vertco);

			if (emd->flag & eExplodeFlag_PaSize)
				mul_v3_fl(vertco, pa->size);

			add_v3_v3(vertco, state.co);

			mul_m4_v3(imat, vertco);
		}
	}
	BLI_edgehashIterator_free(ehi);

	/*map new vertices to faces*/
	for (i = 0, u = 0; i < totface; i++) {
		MFace source;
		int orig_v4;

		if (facepa[i] != totpart) {
			pa = pars + facepa[i];

			if (pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) continue;
			if (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) continue;
			if (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0) continue;
		}

		dm->getTessFace(dm, i, &source);
		mf = CDDM_get_tessface(explode, u);
		
		orig_v4 = source.v4;

		if (facepa[i] != totpart && cfra < pa->time)
			mindex = totvert + totpart;
		else 
			mindex = totvert + facepa[i];

		source.v1 = edgecut_get(vertpahash, source.v1, mindex);
		source.v2 = edgecut_get(vertpahash, source.v2, mindex);
		source.v3 = edgecut_get(vertpahash, source.v3, mindex);
		if (source.v4)
			source.v4 = edgecut_get(vertpahash, source.v4, mindex);

		DM_copy_tessface_data(dm, explode, i, u, 1);

		*mf = source;

		/* override uv channel for particle age */
		if (mtface) {
			float age = (cfra - pa->time) / pa->lifetime;
			/* Clamp to this range to avoid flipping to the other side of the coordinates. */
			CLAMP(age, 0.001f, 0.999f);

			mtf = mtface + u;

			mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = age;
			mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = 0.5f;
		}

		test_index_face(mf, &explode->faceData, u, (orig_v4 ? 4 : 3));
		u++;
	}

	/* cleanup */
	BLI_edgehash_free(vertpahash, NULL);

	/* finalization */
	CDDM_calc_edges_tessface(explode);
	CDDM_tessfaces_to_faces(explode);
	explode->dirty |= DM_DIRTY_NORMALS;

	if (psmd->psys->lattice_deform_data) {
		end_latt_deform(psmd->psys->lattice_deform_data);
		psmd->psys->lattice_deform_data = NULL;
	}

	return explode;
}
Exemple #25
0
/* Evaluate spline IK for a given bone */
static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan,
                                   int index, float ctime)
{
	bSplineIKConstraint *ikData = tree->ikData;
	float poseHead[3], poseTail[3], poseMat[4][4];
	float splineVec[3], scaleFac, radius = 1.0f;

	/* firstly, calculate the bone matrix the standard way, since this is needed for roll control */
	BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);

	copy_v3_v3(poseHead, pchan->pose_head);
	copy_v3_v3(poseTail, pchan->pose_tail);

	/* step 1: determine the positions for the endpoints of the bone */
	{
		float vec[4], dir[3], rad;
		float tailBlendFac = 1.0f;

		/* determine if the bone should still be affected by SplineIK */
		if (tree->points[index + 1] >= 1.0f) {
			/* spline doesn't affect the bone anymore, so done... */
			pchan->flag |= POSE_DONE;
			return;
		}
		else if ((tree->points[index] >= 1.0f) && (tree->points[index + 1] < 1.0f)) {
			/* blending factor depends on the amount of the bone still left on the chain */
			tailBlendFac = (1.0f - tree->points[index + 1]) / (tree->points[index] - tree->points[index + 1]);
		}

		/* tail endpoint */
		if (where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad, NULL)) {
			/* apply curve's object-mode transforms to the position
			 * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root)
			 */
			if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0)
				mul_m4_v3(ikData->tar->obmat, vec);

			/* convert the position to pose-space, then store it */
			mul_m4_v3(ob->imat, vec);
			interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac);

			/* set the new radius */
			radius = rad;
		}

		/* head endpoint */
		if (where_on_path(ikData->tar, tree->points[index + 1], vec, dir, NULL, &rad, NULL)) {
			/* apply curve's object-mode transforms to the position
			 * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root)
			 */
			if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0)
				mul_m4_v3(ikData->tar->obmat, vec);

			/* store the position, and convert it to pose space */
			mul_m4_v3(ob->imat, vec);
			copy_v3_v3(poseHead, vec);

			/* set the new radius (it should be the average value) */
			radius = (radius + rad) / 2;
		}
	}

	/* step 2: determine the implied transform from these endpoints
	 *     - splineVec: the vector direction that the spline applies on the bone
	 *     - scaleFac: the factor that the bone length is scaled by to get the desired amount
	 */
	sub_v3_v3v3(splineVec, poseTail, poseHead);
	scaleFac = len_v3(splineVec) / pchan->bone->length;

	/* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis
	 *      - this uses the same method as is used for the Damped Track Constraint (see the code there for details)
	 */
	{
		float dmat[3][3], rmat[3][3], tmat[3][3];
		float raxis[3], rangle;

		/* compute the raw rotation matrix from the bone's current matrix by extracting only the
		 * orientation-relevant axes, and normalizing them
		 */
		copy_v3_v3(rmat[0], pchan->pose_mat[0]);
		copy_v3_v3(rmat[1], pchan->pose_mat[1]);
		copy_v3_v3(rmat[2], pchan->pose_mat[2]);
		normalize_m3(rmat);

		/* also, normalize the orientation imposed by the bone, now that we've extracted the scale factor */
		normalize_v3(splineVec);

		/* calculate smallest axis-angle rotation necessary for getting from the
		 * current orientation of the bone, to the spline-imposed direction
		 */
		cross_v3_v3v3(raxis, rmat[1], splineVec);

		rangle = dot_v3v3(rmat[1], splineVec);
		CLAMP(rangle, -1.0f, 1.0f);
		rangle = acosf(rangle);

		/* multiply the magnitude of the angle by the influence of the constraint to
		 * control the influence of the SplineIK effect
		 */
		rangle *= tree->con->enforce;

		/* construct rotation matrix from the axis-angle rotation found above
		 *	- this call takes care to make sure that the axis provided is a unit vector first
		 */
		axis_angle_to_mat3(dmat, raxis, rangle);

		/* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates,
		 * while still maintaining roll control from the existing bone animation
		 */
		mul_m3_m3m3(tmat, dmat, rmat); /* m1, m3, m2 */
		normalize_m3(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */
		copy_m4_m3(poseMat, tmat);
	}

	/* step 4: set the scaling factors for the axes */
	{
		/* only multiply the y-axis by the scaling factor to get nice volume-preservation */
		mul_v3_fl(poseMat[1], scaleFac);

		/* set the scaling factors of the x and z axes from... */
		switch (ikData->xzScaleMode) {
			case CONSTRAINT_SPLINEIK_XZS_ORIGINAL:
			{
				/* original scales get used */
				float scale;

				/* x-axis scale */
				scale = len_v3(pchan->pose_mat[0]);
				mul_v3_fl(poseMat[0], scale);
				/* z-axis scale */
				scale = len_v3(pchan->pose_mat[2]);
				mul_v3_fl(poseMat[2], scale);
				break;
			}
			case CONSTRAINT_SPLINEIK_XZS_INVERSE:
			{
				/* old 'volume preservation' method using the inverse scale */
				float scale;

				/* calculate volume preservation factor which is
				 * basically the inverse of the y-scaling factor
				 */
				if (fabsf(scaleFac) != 0.0f) {
					scale = 1.0f / fabsf(scaleFac);

					/* we need to clamp this within sensible values */
					/* NOTE: these should be fine for now, but should get sanitised in future */
					CLAMP(scale, 0.0001f, 100000.0f);
				}
				else
					scale = 1.0f;

				/* apply the scaling */
				mul_v3_fl(poseMat[0], scale);
				mul_v3_fl(poseMat[2], scale);
				break;
			}
			case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC:
			{
				/* improved volume preservation based on the Stretch To constraint */
				float final_scale;
				
				/* as the basis for volume preservation, we use the inverse scale factor... */
				if (fabsf(scaleFac) != 0.0f) {
					/* NOTE: The method here is taken wholesale from the Stretch To constraint */
					float bulge = powf(1.0f / fabsf(scaleFac), ikData->bulge);
					
					if (bulge > 1.0f) {
						if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MAX) {
							float bulge_max = max_ff(ikData->bulge_max, 1.0f);
							float hard = min_ff(bulge, bulge_max);
							
							float range = bulge_max - 1.0f;
							float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
							float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (float)M_PI_2;
							
							bulge = interpf(soft, hard, ikData->bulge_smooth);
						}
					}
					if (bulge < 1.0f) {
						if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MIN) {
							float bulge_min = CLAMPIS(ikData->bulge_min, 0.0f, 1.0f);
							float hard = max_ff(bulge, bulge_min);
							
							float range = 1.0f - bulge_min;
							float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
							float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (float)M_PI_2;
							
							bulge = interpf(soft, hard, ikData->bulge_smooth);
						}
					}
					
					/* compute scale factor for xz axes from this value */
					final_scale = sqrtf(bulge);
				}
				else {
					/* no scaling, so scale factor is simple */
					final_scale = 1.0f;
				}
				
				/* apply the scaling (assuming normalised scale) */
				mul_v3_fl(poseMat[0], final_scale);
				mul_v3_fl(poseMat[2], final_scale);
				break;
			}
		}

		/* finally, multiply the x and z scaling by the radius of the curve too,
		 * to allow automatic scales to get tweaked still
		 */
		if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) {
			mul_v3_fl(poseMat[0], radius);
			mul_v3_fl(poseMat[2], radius);
		}
	}

	/* step 5: set the location of the bone in the matrix */
	if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) {
		/* when the 'no-root' option is affected, the chain can retain
		 * the shape but be moved elsewhere
		 */
		copy_v3_v3(poseHead, pchan->pose_head);
	}
	else if (tree->con->enforce < 1.0f) {
		/* when the influence is too low
		 *	- blend the positions for the 'root' bone
		 *	- stick to the parent for any other
		 */
		if (pchan->parent) {
			copy_v3_v3(poseHead, pchan->pose_head);
		}
		else {
			/* FIXME: this introduces popping artifacts when we reach 0.0 */
			interp_v3_v3v3(poseHead, pchan->pose_head, poseHead, tree->con->enforce);
		}
	}
	copy_v3_v3(poseMat[3], poseHead);

	/* finally, store the new transform */
	copy_m4_m4(pchan->pose_mat, poseMat);
	copy_v3_v3(pchan->pose_head, poseHead);

	/* recalculate tail, as it's now outdated after the head gets adjusted above! */
	BKE_pose_where_is_bone_tail(pchan);

	/* done! */
	pchan->flag |= POSE_DONE;
}
Exemple #26
0
void curve_deform_verts(Scene *scene, Object *cuOb, Object *target,
                        DerivedMesh *dm, float (*vertexCos)[3],
                        int numVerts, const char *vgroup, short defaxis)
{
	Curve *cu;
	int a, flag;
	CurveDeform cd;
	int use_vgroups;
	const int is_neg_axis = (defaxis > 2);

	if (cuOb->type != OB_CURVE)
		return;

	cu = cuOb->data;
	flag = cu->flag;
	cu->flag |= (CU_PATH | CU_FOLLOW); // needed for path & bevlist

	init_curve_deform(cuOb, target, &cd);

	/* dummy bounds, keep if CU_DEFORM_BOUNDS_OFF is set */
	if (is_neg_axis == FALSE) {
		cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = 0.0f;
		cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 1.0f;
	}
	else {
		/* negative, these bounds give a good rest position */
		cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = -1.0f;
		cd.dmax[0] = cd.dmax[1] = cd.dmax[2] =  0.0f;
	}
	
	/* check whether to use vertex groups (only possible if target is a Mesh)
	 * we want either a Mesh with no derived data, or derived data with
	 * deformverts
	 */
	if (target && target->type == OB_MESH) {
		/* if there's derived data without deformverts, don't use vgroups */
		if (dm) {
			use_vgroups = (dm->getVertData(dm, 0, CD_MDEFORMVERT) != NULL);
		}
		else {
			Mesh *me = target->data;
			use_vgroups = (me->dvert != NULL);
		}
	}
	else {
		use_vgroups = FALSE;
	}
	
	if (vgroup && vgroup[0] && use_vgroups) {
		Mesh *me = target->data;
		int index = defgroup_name_index(target, vgroup);

		if (index != -1 && (me->dvert || dm)) {
			MDeformVert *dvert = me->dvert;
			float vec[3];
			float weight;
	

			if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
				dvert = me->dvert;
				for (a = 0; a < numVerts; a++, dvert++) {
					if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
					weight = defvert_find_weight(dvert, index);
	
					if (weight > 0.0f) {
						mul_m4_v3(cd.curvespace, vertexCos[a]);
						copy_v3_v3(vec, vertexCos[a]);
						calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
						interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
						mul_m4_v3(cd.objectspace, vertexCos[a]);
					}
				}
			}
			else {
				/* set mesh min/max bounds */
				INIT_MINMAX(cd.dmin, cd.dmax);
	
				for (a = 0; a < numVerts; a++, dvert++) {
					if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
					
					if (defvert_find_weight(dvert, index) > 0.0f) {
						mul_m4_v3(cd.curvespace, vertexCos[a]);
						minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]);
					}
				}
	
				dvert = me->dvert;
				for (a = 0; a < numVerts; a++, dvert++) {
					if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
					
					weight = defvert_find_weight(dvert, index);
	
					if (weight > 0.0f) {
						/* already in 'cd.curvespace', prev for loop */
						copy_v3_v3(vec, vertexCos[a]);
						calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
						interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
						mul_m4_v3(cd.objectspace, vertexCos[a]);
					}
				}
			}
		}
	}
	else {
		if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
			for (a = 0; a < numVerts; a++) {
				mul_m4_v3(cd.curvespace, vertexCos[a]);
				calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
				mul_m4_v3(cd.objectspace, vertexCos[a]);
			}
		}
		else {
			/* set mesh min max bounds */
			INIT_MINMAX(cd.dmin, cd.dmax);
				
			for (a = 0; a < numVerts; a++) {
				mul_m4_v3(cd.curvespace, vertexCos[a]);
				minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]);
			}
	
			for (a = 0; a < numVerts; a++) {
				/* already in 'cd.curvespace', prev for loop */
				calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
				mul_m4_v3(cd.objectspace, vertexCos[a]);
			}
		}
	}
	cu->flag = flag;
}
Exemple #27
0
static void make_duplis_font(const DupliContext *ctx)
{
	Object *par = ctx->object;
	GHash *family_gh;
	Object *ob;
	Curve *cu;
	struct CharTrans *ct, *chartransdata = NULL;
	float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof;
	int text_len, a;
	size_t family_len;
	const wchar_t *text = NULL;
	bool text_free = false;

	/* font dupliverts not supported inside groups */
	if (ctx->group)
		return;

	copy_m4_m4(pmat, par->obmat);

	/* in par the family name is stored, use this to find the other objects */

	BKE_vfont_to_curve_ex(G.main, par, FO_DUPLI, NULL,
	                      &text, &text_len, &text_free, &chartransdata);

	if (text == NULL || chartransdata == NULL) {
		return;
	}

	cu = par->data;
	fsize = cu->fsize;
	xof = cu->xof;
	yof = cu->yof;

	ct = chartransdata;

	/* cache result */
	family_len = strlen(cu->family);
	family_gh = BLI_ghash_int_new_ex(__func__, 256);

	/* advance matching BLI_strncpy_wchar_from_utf8 */
	for (a = 0; a < text_len; a++, ct++) {

		ob = find_family_object(cu->family, family_len, (unsigned int)text[a], family_gh);
		if (ob) {
			vec[0] = fsize * (ct->xof - xof);
			vec[1] = fsize * (ct->yof - yof);
			vec[2] = 0.0;

			mul_m4_v3(pmat, vec);

			copy_m4_m4(obmat, par->obmat);

			if (UNLIKELY(ct->rot != 0.0f)) {
				float rmat[4][4];

				zero_v3(obmat[3]);
				unit_m4(rmat);
				rotate_m4(rmat, 'Z', -ct->rot);
				mul_m4_m4m4(obmat, obmat, rmat);
			}

			copy_v3_v3(obmat[3], vec);

			make_dupli(ctx, ob, obmat, a, false, false);
		}
	}

	if (text_free) {
		MEM_freeN((void *)text);
	}

	BLI_ghash_free(family_gh, NULL, NULL);

	MEM_freeN(chartransdata);
}
Exemple #28
0
static void deformVerts(ModifierData *md, Object *ob,
						DerivedMesh *derivedData,
						float (*vertexCos)[3],
						int UNUSED(numVerts),
						int UNUSED(useRenderParams),
						int UNUSED(isFinalCalc))
{
	SurfaceModifierData *surmd = (SurfaceModifierData*) md;
	
	if(surmd->dm)
		surmd->dm->release(surmd->dm);

	/* if possible use/create DerivedMesh */
	if(derivedData) surmd->dm = CDDM_copy(derivedData);
	else surmd->dm = get_dm(ob, NULL, NULL, NULL, 0);
	
	if(!ob->pd)
	{
		printf("SurfaceModifier deformVerts: Should not happen!\n");
		return;
	}
	
	if(surmd->dm)
	{
		unsigned int numverts = 0, i = 0;
		int init = 0;
		float *vec;
		MVert *x, *v;

		CDDM_apply_vert_coords(surmd->dm, vertexCos);
		CDDM_calc_normals(surmd->dm);
		
		numverts = surmd->dm->getNumVerts ( surmd->dm );

		if(numverts != surmd->numverts || surmd->x == NULL || surmd->v == NULL || md->scene->r.cfra != surmd->cfra+1) {
			if(surmd->x) {
				MEM_freeN(surmd->x);
				surmd->x = NULL;
			}
			if(surmd->v) {
				MEM_freeN(surmd->v);
				surmd->v = NULL;
			}

			surmd->x = MEM_callocN(numverts * sizeof(MVert), "MVert");
			surmd->v = MEM_callocN(numverts * sizeof(MVert), "MVert");

			surmd->numverts = numverts;

			init = 1;
		}

		/* convert to global coordinates and calculate velocity */
		for(i = 0, x = surmd->x, v = surmd->v; i<numverts; i++, x++, v++) {
			vec = CDDM_get_vert(surmd->dm, i)->co;
			mul_m4_v3(ob->obmat, vec);

			if(init)
				v->co[0] = v->co[1] = v->co[2] = 0.0f;
			else
				sub_v3_v3v3(v->co, vec, x->co);
			
			copy_v3_v3(x->co, vec);
		}

		surmd->cfra = md->scene->r.cfra;

		if(surmd->bvhtree)
			free_bvhtree_from_mesh(surmd->bvhtree);
		else
			surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh");

		if(surmd->dm->getNumFaces(surmd->dm))
			bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
		else
			bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
	}
}
static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par,
                                 int heat, const bool mirror)
{
	/* This functions implements the automatic computation of vertex group
	 * weights, either through envelopes or using a heat equilibrium.
	 *
	 * This function can be called both when parenting a mesh to an armature,
	 * or in weightpaint + posemode. In the latter case selection is taken
	 * into account and vertex weights can be mirrored.
	 *
	 * The mesh vertex positions used are either the final deformed coords
	 * from the derivedmesh in weightpaint mode, the final subsurf coords
	 * when parenting, or simply the original mesh coords.
	 */

	bArmature *arm = par->data;
	Bone **bonelist, *bone;
	bDeformGroup **dgrouplist, **dgroupflip;
	bDeformGroup *dgroup;
	bPoseChannel *pchan;
	Mesh *mesh;
	Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
	float (*root)[3], (*tip)[3], (*verts)[3];
	int *selected;
	int numbones, vertsfilled = 0, i, j, segments = 0;
	int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
	struct { Object *armob; void *list; int heat; } looper_data;

	looper_data.armob = par;
	looper_data.heat = heat;
	looper_data.list = NULL;

	/* count the number of skinnable bones */
	numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
	
	if (numbones == 0)
		return;
	
	if (BKE_object_defgroup_data_create(ob->data) == NULL)
		return;

	/* create an array of pointer to bones that are skinnable
	 * and fill it with all of the skinnable bones */
	bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist");
	looper_data.list = bonelist;
	bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);

	/* create an array of pointers to the deform groups that
	 * correspond to the skinnable bones (creating them
	 * as necessary. */
	dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist");
	dgroupflip = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgroupflip");

	looper_data.list = dgrouplist;
	bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);

	/* create an array of root and tip positions transformed into
	 * global coords */
	root = MEM_callocN(numbones * sizeof(float) * 3, "root");
	tip = MEM_callocN(numbones * sizeof(float) * 3, "tip");
	selected = MEM_callocN(numbones * sizeof(int), "selected");

	for (j = 0; j < numbones; ++j) {
		bone = bonelist[j];
		dgroup = dgrouplist[j];
		
		/* handle bbone */
		if (heat) {
			if (segments == 0) {
				segments = 1;
				bbone = NULL;
				
				if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
					if (bone->segments > 1) {
						segments = bone->segments;
						b_bone_spline_setup(pchan, 1, bbone_array);
						bbone = bbone_array;
					}
				}
			}
			
			segments--;
		}
		
		/* compute root and tip */
		if (bbone) {
			mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
			if ((segments + 1) < bone->segments) {
				mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]);
			}
			else {
				copy_v3_v3(tip[j], bone->arm_tail);
			}
		}
		else {
			copy_v3_v3(root[j], bone->arm_head);
			copy_v3_v3(tip[j], bone->arm_tail);
		}
		
		mul_m4_v3(par->obmat, root[j]);
		mul_m4_v3(par->obmat, tip[j]);
		
		/* set selected */
		if (wpmode) {
			if ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))
				selected[j] = 1;
		}
		else
			selected[j] = 1;
		
		/* find flipped group */
		if (dgroup && mirror) {
			char name_flip[MAXBONENAME];

			BKE_deform_flip_side_name(name_flip, dgroup->name, false);
			dgroupflip[j] = defgroup_find_name(ob, name_flip);
		}
	}

	/* create verts */
	mesh = (Mesh *)ob->data;
	verts = MEM_callocN(mesh->totvert * sizeof(*verts), "closestboneverts");

	if (wpmode) {
		/* if in weight paint mode, use final verts from derivedmesh */
		DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
		
		if (dm->foreachMappedVert) {
			mesh_get_mapped_verts_coords(dm, verts, mesh->totvert);
			vertsfilled = 1;
		}
		
		dm->release(dm);
	}
	else if (modifiers_findByType(ob, eModifierType_Subsurf)) {
		/* is subsurf on? Lets use the verts on the limit surface then.
		 * = same amount of vertices as mesh, but vertices  moved to the
		 * subsurfed position, like for 'optimal'. */
		subsurf_calculate_limit_positions(mesh, verts);
		vertsfilled = 1;
	}

	/* transform verts to global space */
	for (i = 0; i < mesh->totvert; i++) {
		if (!vertsfilled)
			copy_v3_v3(verts[i], mesh->mvert[i].co);
		mul_m4_v3(ob->obmat, verts[i]);
	}

	/* compute the weights based on gathered vertices and bones */
	if (heat) {
		const char *error = NULL;

		heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip,
		                    root, tip, selected, &error);
		if (error) {
			BKE_report(reports, RPT_WARNING, error);
		}
	}
	else {
		envelope_bone_weighting(ob, mesh, verts, numbones, bonelist, dgrouplist,
		                        dgroupflip, root, tip, selected, mat4_to_scale(par->obmat));
	}

	/* only generated in some cases but can call anyway */
	ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');

	/* free the memory allocated */
	MEM_freeN(bonelist);
	MEM_freeN(dgrouplist);
	MEM_freeN(dgroupflip);
	MEM_freeN(root);
	MEM_freeN(tip);
	MEM_freeN(selected);
	MEM_freeN(verts);
}
Exemple #30
0
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *obedit = CTX_data_edit_object(C);
	Scene *scene = CTX_data_scene(C);
	RegionView3D *rv3d = CTX_wm_region_data(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float gridf, imat[3][3], bmat[3][3], vec[3];
	int a;

	gridf = rv3d->gridview;

	if (obedit) {
		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, 0);
		if (tvs.transverts_tot == 0)
			return OPERATOR_CANCELLED;

		copy_m3_m4(bmat, obedit->obmat);
		invert_m3_m3(imat, bmat);
		
		tv = tvs.transverts;
		for (a = 0; a < tvs.transverts_tot; a++, tv++) {
			copy_v3_v3(vec, tv->loc);
			mul_m3_v3(bmat, vec);
			add_v3_v3(vec, obedit->obmat[3]);
			vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
			vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
			vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
			sub_v3_v3(vec, obedit->obmat[3]);
			
			mul_m3_v3(imat, vec);
			copy_v3_v3(tv->loc, vec);
		}
		
		ED_transverts_update_obedit(&tvs, obedit);
		ED_transverts_free(&tvs);
	}
	else {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);

		CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
		{
			if (ob->mode & OB_MODE_POSE) {
				bPoseChannel *pchan;
				bArmature *arm = ob->data;
				
				invert_m4_m4(ob->imat, ob->obmat);
				
				for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
					if (pchan->bone->flag & BONE_SELECTED) {
						if (pchan->bone->layer & arm->layer) {
							if ((pchan->bone->flag & BONE_CONNECTED) == 0) {
								float nLoc[3];
								
								/* get nearest grid point to snap to */
								copy_v3_v3(nLoc, pchan->pose_mat[3]);
								/* We must operate in world space! */
								mul_m4_v3(ob->obmat, nLoc);
								vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
								vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
								vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
								/* Back in object space... */
								mul_m4_v3(ob->imat, vec);
								
								/* Get location of grid point in pose space. */
								BKE_armature_loc_pose_to_bone(pchan, vec, vec);
								
								/* adjust location */
								if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
									pchan->loc[0] = vec[0];
								if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
									pchan->loc[1] = vec[1];
								if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
									pchan->loc[2] = vec[2];

								/* auto-keyframing */
								ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
							}
							/* if the bone has a parent and is connected to the parent,
							 * don't do anything - will break chain unless we do auto-ik.
							 */
						}
					}
				}
				ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
				
				DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
			}
			else {
				vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf);
				vec[1] = -ob->obmat[3][1] + gridf * floorf(0.5f + ob->obmat[3][1] / gridf);
				vec[2] = -ob->obmat[3][2] + gridf * floorf(0.5f + ob->obmat[3][2] / gridf);
				
				if (ob->parent) {
					float originmat[3][3];
					BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);
					
					invert_m3_m3(imat, originmat);
					mul_m3_v3(imat, vec);
				}
				if ((ob->protectflag & OB_LOCK_LOCX) == 0)
					ob->loc[0] += vec[0];
				if ((ob->protectflag & OB_LOCK_LOCY) == 0)
					ob->loc[1] += vec[1];
				if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
					ob->loc[2] += vec[2];
				
				/* auto-keyframing */
				ED_autokeyframe_object(C, scene, ob, ks);

				DAG_id_tag_update(&ob->id, OB_RECALC_OB);
			}
		}
		CTX_DATA_END;
	}

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