Esempio n. 1
0
void env_rotate_scene(Render *re, float mat[4][4], int do_rotate)
{
	GroupObject *go;
	ObjectRen *obr;
	ObjectInstanceRen *obi;
	LampRen *lar = NULL;
	HaloRen *har = NULL;
	float imat[3][3], mat_inverse[4][4], smat[4][4], tmat[4][4], cmat[3][3], tmpmat[4][4];
	int a;
	
	if (do_rotate == 0) {
		invert_m4_m4(tmat, mat);
		copy_m3_m4(imat, tmat);
		
		copy_m4_m4(mat_inverse, mat);
	}
	else {
		copy_m4_m4(tmat, mat);
		copy_m3_m4(imat, mat);
		
		invert_m4_m4(mat_inverse, tmat);
	}

	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);
			mul_m4_m4m4(obi->mat, tmat, tmpmat);
		}
		else if (do_rotate == 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 (do_rotate == 0)
			obi->flag &= ~R_ENV_TRANSFORMED;
		else {
			obi->flag |= R_ENV_TRANSFORMED;
			copy_m4_m4(obi->imat, mat_inverse);
		}
	}
	

	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);
		}

		/* imat_ren is needed for correct texture coordinates */
		mul_m4_m4m4(obr->ob->imat_ren, re->viewmat, obr->ob->obmat);
		invert_m4(obr->ob->imat_ren);
	}
/* v3d and rv3d are allowed to be NULL */
void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
{
	Object *obedit = scene->obedit; // XXX get from context
	bArmature *arm = obedit->data;
	float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
	EditBone    *bone;

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

	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, 0);
	
	/* Create a bone */
	bone = ED_armature_edit_bone_add(arm, "Bone");

	arm->act_edbone = bone;

	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
}
Esempio n. 3
0
/**
 * \param ray_distance  Distance to the hit point
 * \param r_location  Location of the hit point
 * \param r_normal  Normal of the hit surface, transformed to always face the camera
 */
static bool walk_ray_cast(bContext *C, RegionView3D *rv3d, WalkInfo *walk, float r_location[3], float r_normal[3], float *ray_distance)
{
	float dummy_dist_px = 0;
	float ray_normal[3] = {0, 0, 1}; /* forward */
	float ray_start[3];
	float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */
	bool ret;

	*ray_distance = TRANSFORM_DIST_MAX_RAY;

	copy_v3_v3(ray_start, rv3d->viewinv[3]);
	copy_m3_m4(mat, rv3d->viewinv);

	mul_m3_v3(mat, ray_normal);

	mul_v3_fl(ray_normal, -1);
	normalize_v3(ray_normal);

	ret = snapObjectsRayEx(CTX_data_scene(C), NULL, NULL, NULL, NULL, SCE_SNAP_MODE_FACE,
	                       NULL, NULL,
	                       ray_start, ray_normal, ray_distance,
	                       NULL, &dummy_dist_px, r_location, r_normal, SNAP_ALL);


	/* dot is positive if both rays are facing the same direction */
	if (dot_v3v3(ray_normal, r_normal) > 0) {
		copy_v3_fl3(r_normal, -r_normal[0], -r_normal[1], -r_normal[2]);
	}

	/* artifically scale the distance to the scene size */
	*ray_distance /= walk->grid;

	return ret;
}
static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
	Main *bmain = CTX_data_main(C);
	float *v1, *v3;
	float mat[3][3];

	CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
	{
		if (ob->parent) {
			/* vectors pointed to by v1 and v3 will get modified */
			v1 = ob->loc;
			v3 = ob->parentinv[3];
			
			copy_m3_m4(mat, ob->parentinv);
			negate_v3_v3(v3, v1);
			mul_m3_v3(mat, v3);
		}

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

	DAG_ids_flush_update(bmain, 0);
	
	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	
	return OPERATOR_FINISHED;
}
Esempio n. 5
0
void setLocalConstraint(TransInfo *t, int mode, const char text[]) {
	if (t->flag & T_EDIT) {
		float obmat[3][3];
		copy_m3_m4(obmat, t->scene->obedit->obmat);
		normalize_m3(obmat);
		setConstraint(t, obmat, mode, text);
	}
	else {
		if (t->total == 1) {
			setConstraint(t, t->data->axismtx, mode, text);
		}
		else {
			strncpy(t->con.text + 1, text, 48);
			copy_m3_m3(t->con.mtx, t->data->axismtx);
			t->con.mode = mode;
			getConstraintMatrix(t);

			startConstraint(t);

			t->con.drawExtra = drawObjectConstraint;
			t->con.applyVec = applyObjectConstraintVec;
			t->con.applySize = applyObjectConstraintSize;
			t->con.applyRot = applyObjectConstraintRot;
			t->redraw = 1;
		}
	}
}
Esempio n. 6
0
/* returns standard diameter */
static float new_primitive_matrix(bContext *C, float *loc, float *rot, float primmat[][4])
{
	Object *obedit = CTX_data_edit_object(C);
	View3D *v3d = CTX_wm_view3d(C);
	float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
	
	unit_m4(primmat);

	eul_to_mat3(rmat, rot);
	invert_m3(rmat);
	
	/* inverse transform for initial rotation and object */
	copy_m3_m4(mat, obedit->obmat);
	mul_m3_m3m3(cmat, rmat, mat);
	invert_m3_m3(imat, cmat);
	copy_m4_m3(primmat, imat);

	/* center */
	copy_v3_v3(primmat[3], loc);
	sub_v3_v3(primmat[3], obedit->obmat[3]);
	invert_m3_m3(imat, mat);
	mul_m3_v3(imat, primmat[3]);

	return v3d ? v3d->grid : 1.0f;
}
Esempio n. 7
0
static int object_hook_recenter_exec(bContext *C, wmOperator *op)
{
	PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
	int num= RNA_enum_get(op->ptr, "modifier");
	Object *ob=NULL;
	HookModifierData *hmd=NULL;
	Scene *scene = CTX_data_scene(C);
	float bmat[3][3], imat[3][3];
	
	if (ptr.data) {		/* if modifier context is available, use that */
		ob = ptr.id.data;
		hmd= ptr.data;
	} 
	else {			/* use the provided property */
		ob = CTX_data_edit_object(C);
		hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
	}
	if (!ob || !hmd) {
		BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
		return OPERATOR_CANCELLED;
	}
	
	/* recenter functionality */
	copy_m3_m4(bmat, ob->obmat);
	invert_m3_m3(imat, bmat);
	
	sub_v3_v3v3(hmd->cent, scene->cursor, ob->obmat[3]);
	mul_m3_v3(imat, hmd->cent);
	
	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
	
	return OPERATOR_FINISHED;
}
Esempio n. 8
0
void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4])
{
	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);
		
		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;
	}
}
Esempio n. 9
0
bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
{
	const Mesh *me;
	const MPoly *mp;
	const MLoop *ml;
	const MVert *mvert;
	int a, b;
	bool ok = false;
	float vec[3], bmat[3][3];

	me = BKE_mesh_from_object(ob);
	if (!me || !me->mloopuv) {
		return ok;
	}
	
	copy_m3_m4(bmat, ob->obmat);

	mvert = me->mvert;
	mp = me->mpoly;
	for (a = me->totpoly; a > 0; a--, mp++) {
		if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL))
			continue;

		ml = me->mloop + mp->totloop;
		for (b = 0; b < mp->totloop; b++, ml++) {
			mul_v3_m3v3(vec, bmat, mvert[ml->v].co);
			add_v3_v3v3(vec, vec, ob->obmat[3]);
			minmax_v3v3_v3(r_min, r_max, vec);
		}

		ok = true;
	}

	return ok;
}
Esempio n. 10
0
static void rigid_orthogonalize_R(float R[][3])
{
	HMatrix M, Q, S;

	copy_m4_m3(M, R);
	polar_decomp(M, Q, S);
	copy_m3_m4(R, Q);
}
Esempio n. 11
0
static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd)
{
	invert_m4_m4(ob->imat, ob->obmat);
	mult_m4_m4m4(cd->objectspace, ob->imat, par->obmat);
	invert_m4_m4(cd->curvespace, cd->objectspace);
	copy_m3_m4(cd->objectspace3, cd->objectspace);
	cd->no_rot_axis = 0;
}
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;
}
Esempio n. 13
0
void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4])
{
	float mat3[3][3];

	copy_m3_m4(mat3, mat);
	/* We want normalized matrix here, to be consistent with ebone_to_mat. */
	BLI_ASSERT_UNIT_M3(mat3);

	sub_v3_v3(ebone->tail, ebone->head);
	copy_v3_v3(ebone->head, mat[3]);
	add_v3_v3(ebone->tail, mat[3]);
	ED_armature_ebone_from_mat3(ebone, mat3);
}
Esempio n. 14
0
static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
{
	float angle, start[3], end[3];

	sub_v3_v3v3(start, p1, t->center_global);
	sub_v3_v3v3(end,   p2, t->center_global);
		
	// Angle around a constraint axis (error prone, will need debug)
	if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
		float axis[3], tmp[3];
		
		t->con.applyRot(t, NULL, axis, NULL);

		project_v3_v3v3(tmp, end, axis);
		sub_v3_v3v3(end, end, tmp);
		
		project_v3_v3v3(tmp, start, axis);
		sub_v3_v3v3(start, start, tmp);
		
		normalize_v3(end);
		normalize_v3(start);
		
		cross_v3_v3v3(tmp, start, end);
		
		if (dot_v3v3(tmp, axis) < 0.0f)
			angle = -acosf(dot_v3v3(start, end));
		else
			angle = acosf(dot_v3v3(start, end));
	}
	else {
		float mtx[3][3];
		
		copy_m3_m4(mtx, t->viewmat);

		mul_m3_v3(mtx, end);
		mul_m3_v3(mtx, start);
		
		angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]);
	}
	
	if (angle > (float)M_PI) {
		angle = angle - 2 * (float)M_PI;
	}
	else if (angle < -((float)M_PI)) {
		angle = 2.0f * (float)M_PI + angle;
	}
	
	return angle;
}
Esempio n. 15
0
static void camera_frame_fit_data_init(
        const Scene *scene, const Object *ob,
        CameraParams *params, CameraViewFrameData *data)
{
	float camera_rotmat_transposed_inversed[4][4];
	unsigned int i;

	/* setup parameters */
	BKE_camera_params_init(params);
	BKE_camera_params_from_object(params, ob);

	/* compute matrix, viewplane, .. */
	if (scene) {
		BKE_camera_params_compute_viewplane(params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
	}
	else {
		BKE_camera_params_compute_viewplane(params, 1, 1, 1.0f, 1.0f);
	}
	BKE_camera_params_compute_matrix(params);

	/* initialize callback data */
	copy_m3_m4(data->camera_rotmat, (float (*)[4])ob->obmat);
	normalize_m3(data->camera_rotmat);
	/* To transform a plane which is in its homogeneous representation (4d vector),
	 * we need the inverse of the transpose of the transform matrix... */
	copy_m4_m3(camera_rotmat_transposed_inversed, data->camera_rotmat);
	transpose_m4(camera_rotmat_transposed_inversed);
	invert_m4(camera_rotmat_transposed_inversed);

	/* Extract frustum planes from projection matrix. */
	planes_from_projmat(params->winmat,
	                    /*   left              right                 top              bottom        near  far */
	                    data->plane_tx[2], data->plane_tx[0], data->plane_tx[3], data->plane_tx[1], NULL, NULL);

	/* Rotate planes and get normals from them */
	for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
		mul_m4_v4(camera_rotmat_transposed_inversed, data->plane_tx[i]);
		normalize_v3_v3(data->normal_tx[i], data->plane_tx[i]);
	}

	copy_v4_fl(data->dist_vals_sq, FLT_MAX);
	data->tot = 0;
	data->is_ortho = params->is_ortho;
	if (params->is_ortho) {
		/* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
		negate_v3_v3(data->camera_no, data->camera_rotmat[2]);
		data->dist_to_cam = FLT_MAX;
	}
}
Esempio n. 16
0
static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
{
	float bmat[4][4];
	float tmat[3][3];
	
	rv3d->view = RV3D_VIEW_USER; /* don't show the grid */
	
	copy_m4_m4(bmat, ob->obmat);
	normalize_m4(bmat);
	invert_m4_m4(rv3d->viewmat, bmat);
	
	/* view quat calculation, needed for add object */
	copy_m3_m4(tmat, rv3d->viewmat);
	mat3_to_quat(rv3d->viewquat, tmat);
}
Esempio n. 17
0
static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd, int dloc)
{
	invert_m4_m4(ob->imat, ob->obmat);
	mul_m4_m4m4(cd->objectspace, par->obmat, ob->imat);
	invert_m4_m4(cd->curvespace, cd->objectspace);
	copy_m3_m4(cd->objectspace3, cd->objectspace);
	
	// offset vector for 'no smear'
	if(dloc) {
		invert_m4_m4(par->imat, par->obmat);
		mul_v3_m4v3(cd->dloc, par->imat, ob->obmat[3]);
	}
	else {
		cd->dloc[0]=cd->dloc[1]=cd->dloc[2]= 0.0f;
	}
	
	cd->no_rot_axis= 0;
}
Esempio n. 18
0
void ED_armature_apply_transform(Object *ob, float mat[4][4])
{
	EditBone *ebone;
	bArmature *arm = ob->data;
	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);
	
	/* Put the armature into editmode */
	ED_armature_to_edit(ob);
	
	/* Do the rotations */
	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
		float delta[3], tmat[3][3];
		
		/* find the current bone's roll matrix */
		sub_v3_v3v3(delta, ebone->tail, ebone->head);
		vec_roll_to_mat3(delta, ebone->roll, 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 transfiormed roll back */
		mat3_to_vec_roll(tmat, NULL, &ebone->roll);
		
		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;
	}
	
	/* Turn the list into an armature */
	ED_armature_from_edit(ob);
	ED_armature_edit_free(ob);
}
Esempio n. 19
0
static void obmat_to_viewmat(View3D *v3d, RegionView3D *rv3d, Object *ob, short smooth)
{
	float bmat[4][4];
	float tmat[3][3];
	
	rv3d->view = RV3D_VIEW_USER; /* don't show the grid */
	
	copy_m4_m4(bmat, ob->obmat);
	normalize_m4(bmat);
	invert_m4_m4(rv3d->viewmat, bmat);
	
	/* view quat calculation, needed for add object */
	copy_m3_m4(tmat, rv3d->viewmat);
	if (smooth) {
		float new_quat[4];
		if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
			/* were from a camera view */
			
			float orig_ofs[3];
			float orig_dist = rv3d->dist;
			float orig_lens = v3d->lens;
			copy_v3_v3(orig_ofs, rv3d->ofs);
			
			/* Switch from camera view */
			mat3_to_quat(new_quat, tmat);
			
			rv3d->persp = RV3D_PERSP;
			rv3d->dist = 0.0;
			
			ED_view3d_from_object(v3d->camera, rv3d->ofs, NULL, NULL, &v3d->lens);
			view3d_smooth_view(NULL, NULL, NULL, NULL, NULL, orig_ofs, new_quat, &orig_dist, &orig_lens); /* XXX */

			rv3d->persp = RV3D_CAMOB; /* just to be polite, not needed */
			
		}
		else {
			mat3_to_quat(new_quat, tmat);
			view3d_smooth_view(NULL, NULL, NULL, NULL, NULL, NULL, new_quat, NULL, NULL); /* XXX */
		}
	}
	else {
		mat3_to_quat(rv3d->viewquat, tmat);
	}
}
Esempio n. 20
0
/* also sets restposition in armature (arm_mat) */
static void fix_bonelist_roll(ListBase *bonelist, ListBase *editbonelist)
{
	Bone *curBone;
	EditBone *ebone;
	float premat[3][3];
	float postmat[3][3];
	float difmat[3][3];
	float imat[3][3];
	
	for (curBone = bonelist->first; curBone; curBone = curBone->next) {
		/* sets local matrix and arm_mat (restpos) */
		BKE_armature_where_is_bone(curBone, curBone->parent);
		
		/* Find the associated editbone */
		for (ebone = editbonelist->first; ebone; ebone = ebone->next)
			if (ebone->temp.bone == curBone)
				break;
		
		if (ebone) {
			/* Get the ebone premat */
			ED_armature_ebone_to_mat3(ebone, premat);
			
			/* Get the bone postmat */
			copy_m3_m4(postmat, curBone->arm_mat);
			
			invert_m3_m3(imat, premat);
			mul_m3_m3m3(difmat, imat, postmat);
#if 0
			printf("Bone %s\n", curBone->name);
			print_m4("premat", premat);
			print_m4("postmat", postmat);
			print_m4("difmat", difmat);
			printf("Roll = %f\n",  RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
#endif
			curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
			
			/* and set restposition again */
			BKE_armature_where_is_bone(curBone, curBone->parent);
		}
		fix_bonelist_roll(&curBone->childbase, editbonelist);
	}
}
Esempio n. 21
0
static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk)
{
#define WALK_ROTATE_FAC 2.2f /* more is faster */
#define WALK_TOP_LIMIT DEG2RADF(85.0f)
#define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f)
#define WALK_MOVE_SPEED base_speed
#define WALK_BOOST_FACTOR ((void)0, walk->speed_factor)

	/* walk mode - Ctrl+Shift+F
	 * a walk loop where the user can move move the view as if they are in a walk game
	 */
	RegionView3D *rv3d = walk->rv3d;
	ARegion *ar = walk->ar;

	float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */
	float dvec[3] = {0.0f, 0.0f, 0.0f}; /* this is the direction that's added to the view offset per redraw */

	/* Camera Uprighting variables */
	float upvec[3] = {0.0f, 0.0f, 0.0f}; /* stores the view's up vector */

	int moffset[2]; /* mouse offset from the views center */
	float tmp_quat[4]; /* used for rotating the view */

#ifdef NDOF_WALK_DEBUG
	{
		static unsigned int iteration = 1;
		printf("walk timer %d\n", iteration++);
	}
#endif

	{
		/* mouse offset from the center */
		copy_v2_v2_int(moffset, walk->moffset);

		/* apply moffset so we can re-accumulate */
		walk->moffset[0] = 0;
		walk->moffset[1] = 0;

		/* revert mouse */
		if (walk->is_reversed) {
			moffset[1] = -moffset[1];
		}

		/* Should we redraw? */
		if ((walk->active_directions) ||
		    moffset[0] || moffset[1] ||
		    walk->teleport.state == WALK_TELEPORT_STATE_ON ||
		    walk->gravity_state != WALK_GRAVITY_STATE_OFF)
		{
			float dvec_tmp[3];

			/* time how fast it takes for us to redraw,
			 * this is so simple scenes don't walk too fast */
			double time_current;
			float time_redraw;
#ifdef NDOF_WALK_DRAW_TOOMUCH
			walk->redraw = 1;
#endif
			time_current = PIL_check_seconds_timer();
			time_redraw = (float)(time_current - walk->time_lastdraw);

			walk->time_lastdraw = time_current;

			/* base speed in m/s */
			walk->speed = WALK_MOVE_SPEED;

			if (walk->is_fast) {
				walk->speed *= WALK_BOOST_FACTOR;
			}
			else if (walk->is_slow) {
				walk->speed *= 1.0f / WALK_BOOST_FACTOR;
			}

			copy_m3_m4(mat, rv3d->viewinv);

			{
				/* rotate about the X axis- look up/down */
				if (moffset[1]) {
					float angle;
					float y;

					/* relative offset */
					y = (float) moffset[1] / ar->winy;

					/* speed factor */
					y *= WALK_ROTATE_FAC;

					/* user adjustement factor */
					y *= walk->mouse_speed;

					/* clamp the angle limits */
					/* it ranges from 90.0f to -90.0f */
					angle = -asinf(rv3d->viewmat[2][2]);

					if (angle > WALK_TOP_LIMIT && y > 0.0f)
						y = 0.0f;

					else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f)
						y = 0.0f;

					copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
					mul_m3_v3(mat, upvec);
					/* Rotate about the relative up vec */
					axis_angle_to_quat(tmp_quat, upvec, -y);
					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
				}

				/* rotate about the Y axis- look left/right */
				if (moffset[0]) {
					float x;

					/* if we're upside down invert the moffset */
					copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
					mul_m3_v3(mat, upvec);

					if (upvec[2] < 0.0f)
						moffset[0] = -moffset[0];

					/* relative offset */
					x = (float) moffset[0] / ar->winx;

					/* speed factor */
					x *= WALK_ROTATE_FAC;

					/* user adjustement factor */
					x *= walk->mouse_speed;

					copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);

					/* Rotate about the relative up vec */
					axis_angle_normalized_to_quat(tmp_quat, upvec, x);
					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
				}
			}

			/* WASD - 'move' translation code */
			if ((walk->active_directions) &&
			    (walk->gravity_state == WALK_GRAVITY_STATE_OFF))
			{

				short direction;
				zero_v3(dvec);

				if ((walk->active_directions & WALK_BIT_FORWARD) ||
				    (walk->active_directions & WALK_BIT_BACKWARD))
				{

					direction = 0;

					if ((walk->active_directions & WALK_BIT_FORWARD))
						direction += 1;

					if ((walk->active_directions & WALK_BIT_BACKWARD))
						direction -= 1;

					copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
					mul_m3_v3(mat, dvec_tmp);

					if (walk->navigation_mode == WALK_MODE_GRAVITY) {
						dvec_tmp[2] = 0.0f;
					}

					normalize_v3(dvec_tmp);
					add_v3_v3(dvec, dvec_tmp);

				}

				if ((walk->active_directions & WALK_BIT_LEFT) ||
				    (walk->active_directions & WALK_BIT_RIGHT))
				{

					direction = 0;

					if ((walk->active_directions & WALK_BIT_LEFT))
						direction += 1;

					if ((walk->active_directions & WALK_BIT_RIGHT))
						direction -= 1;

					dvec_tmp[0] = direction * rv3d->viewinv[0][0];
					dvec_tmp[1] = direction * rv3d->viewinv[0][1];
					dvec_tmp[2] = 0.0f;

					normalize_v3(dvec_tmp);
					add_v3_v3(dvec, dvec_tmp);

				}

				if ((walk->active_directions & WALK_BIT_UP) ||
				    (walk->active_directions & WALK_BIT_DOWN))
				{

					if (walk->navigation_mode == WALK_MODE_FREE) {

						direction = 0;

						if ((walk->active_directions & WALK_BIT_UP))
							direction -= 1;

						if ((walk->active_directions & WALK_BIT_DOWN))
							direction = 1;

						copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
						add_v3_v3(dvec, dvec_tmp);
					}
				}

				/* apply movement */
				mul_v3_fl(dvec, walk->speed * time_redraw);
			}

			/* stick to the floor */
			if (walk->navigation_mode == WALK_MODE_GRAVITY &&
			    ELEM(walk->gravity_state,
			         WALK_GRAVITY_STATE_OFF,
			         WALK_GRAVITY_STATE_START))
			{

				bool ret;
				float ray_distance;
				float difference = -100.0f;
				float fall_distance;

				ret = walk_floor_distance_get(C, rv3d, walk, dvec, &ray_distance);

				if (ret) {
					difference = walk->view_height - ray_distance;
				}

				/* the distance we would fall naturally smoothly enough that we
				 * can manually drop the object without activating gravity */
				fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR;

				if (fabsf(difference) < fall_distance) {
					/* slope/stairs */
					dvec[2] -= difference;

					/* in case we switched from FREE to GRAVITY too close to the ground */
					if (walk->gravity_state == WALK_GRAVITY_STATE_START)
						walk->gravity_state = WALK_GRAVITY_STATE_OFF;
				}
				else {
					/* hijack the teleport variables */
					walk->teleport.initial_time = PIL_check_seconds_timer();
					walk->gravity_state = WALK_GRAVITY_STATE_ON;
					walk->teleport.duration = 0.0f;

					copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
					copy_v2_v2(walk->teleport.direction, dvec);

				}
			}

			/* Falling or jumping) */
			if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) {
				float t;
				float z_cur, z_new;
				bool ret;
				float ray_distance, difference = -100.0f;

				/* delta time */
				t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);

				/* keep moving if we were moving */
				copy_v2_v2(dvec, walk->teleport.direction);

				z_cur = walk->rv3d->viewinv[3][2];
				z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid;

				/* jump */
				z_new += t * walk->speed_jump * walk->grid;

				/* duration is the jump duration */
				if (t > walk->teleport.duration) {

					/* check to see if we are landing */
					ret = walk_floor_distance_get(C, rv3d, walk, dvec, &ray_distance);

					if (ret) {
						difference = walk->view_height - ray_distance;
					}

					if (difference > 0.0f) {
						/* quit falling, lands at "view_height" from the floor */
						dvec[2] -= difference;
						walk->gravity_state = WALK_GRAVITY_STATE_OFF;
						walk->speed_jump = 0.0f;
					}
					else {
						/* keep falling */
						dvec[2] = z_cur - z_new;
					}
				}
				else {
					/* keep going up (jump) */
					dvec[2] = z_cur - z_new;
				}
			}

			/* Teleport */
			else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) {
				float t; /* factor */
				float new_loc[3];
				float cur_loc[3];

				/* linear interpolation */
				t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
				t /= walk->teleport.duration;

				/* clamp so we don't go past our limit */
				if (t >= 1.0f) {
					t = 1.0f;
					walk->teleport.state = WALK_TELEPORT_STATE_OFF;
					walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode);
				}

				mul_v3_v3fl(new_loc, walk->teleport.direction, t);
				add_v3_v3(new_loc, walk->teleport.origin);

				copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]);
				sub_v3_v3v3(dvec, cur_loc, new_loc);
			}

			if (rv3d->persp == RV3D_CAMOB) {
				Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
				if (lock_ob->protectflag & OB_LOCK_LOCX) dvec[0] = 0.0f;
				if (lock_ob->protectflag & OB_LOCK_LOCY) dvec[1] = 0.0f;
				if (lock_ob->protectflag & OB_LOCK_LOCZ) dvec[2] = 0.0f;
			}

			/* scale the movement to the scene size */
			mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
			add_v3_v3(rv3d->ofs, dvec_tmp);

			if (rv3d->persp == RV3D_CAMOB) {
				const bool do_rotate = (moffset[0] || moffset[1]);
				const bool do_translate = (walk->speed != 0.0f);
				walkMoveCamera(C, walk, do_rotate, do_translate);
			}
		}
		else {
			/* we're not redrawing but we need to update the time else the view will jump */
			walk->time_lastdraw = PIL_check_seconds_timer();
		}
		/* end drawing */
		copy_v3_v3(walk->dvec_prev, dvec);
	}

	return OPERATOR_FINISHED;
#undef WALK_ROTATE_FAC
#undef WALK_ZUP_CORRECT_FAC
#undef WALK_ZUP_CORRECT_ACCEL
#undef WALK_SMOOTH_FAC
#undef WALK_TOP_LIMIT
#undef WALK_BOTTOM_LIMIT
#undef WALK_MOVE_SPEED
#undef WALK_BOOST_FACTOR
}
Esempio n. 22
0
static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Object *inst_ob)
{
	FaceDupliData *fdd = userdata;
	MPoly *mpoly = fdd->mpoly, *mp;
	MLoop *mloop = fdd->mloop;
	MVert *mvert = fdd->mvert;
	float (*orco)[3] = fdd->orco;
	MLoopUV *mloopuv = fdd->mloopuv;
	int a, totface = fdd->totface;
	bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
	float child_imat[4][4];
	DupliObject *dob;

	invert_m4_m4(inst_ob->imat, inst_ob->obmat);
	/* relative transform from parent to child space */
	mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat);

	for (a = 0, mp = mpoly; a < totface; a++, mp++) {
		MLoop *loopstart = mloop + mp->loopstart;
		float space_mat[4][4], obmat[4][4];

		if (UNLIKELY(mp->totloop < 3))
			continue;

		/* obmat is transform to face */
		get_dupliface_transform(mp, loopstart, mvert, fdd->use_scale, ctx->object->dupfacesca, obmat);
		/* make offset relative to inst_ob using relative child transform */
		mul_mat3_m4_v3(child_imat, obmat[3]);

		/* XXX ugly hack to ensure same behavior as in master
		 * this should not be needed, parentinv is not consistent
		 * outside of parenting.
		 */
		{
			float imat[3][3];
			copy_m3_m4(imat, inst_ob->parentinv);
			mul_m4_m3m4(obmat, imat, obmat);
		}

		/* apply obmat _after_ the local face transform */
		mul_m4_m4m4(obmat, inst_ob->obmat, obmat);

		/* space matrix is constructed by removing obmat transform,
		 * this yields the worldspace transform for recursive duplis
		 */
		mul_m4_m4m4(space_mat, obmat, inst_ob->imat);

		dob = make_dupli(ctx, inst_ob, obmat, a, false, false);
		if (use_texcoords) {
			float w = 1.0f / (float)mp->totloop;

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

			if (mloopuv) {
				int j;
				for (j = 0; j < mp->totloop; j++) {
					madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w);
				}
			}
		}

		/* recursion */
		make_recursive_duplis(ctx, inst_ob, space_mat, a, false);
	}
}
Esempio n. 23
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;
}
Esempio n. 24
0
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
{
	Object *obedit = CTX_data_edit_object(C);
	Scene *scene = CTX_data_scene(C);
	View3D *v3d = CTX_wm_view3d(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float bmat[3][3], vec[3], min[3], max[3], centroid[3];
	int count, a;

	count = 0;
	INIT_MINMAX(min, max);
	zero_v3(centroid);

	if (obedit) {

		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);

		if (tvs.transverts_tot == 0) {
			return false;
		}

		copy_m3_m4(bmat, obedit->obmat);
		
		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]);
			add_v3_v3(centroid, vec);
			minmax_v3v3_v3(min, max, vec);
		}
		
		if (v3d->around == V3D_AROUND_CENTER_MEAN) {
			mul_v3_fl(centroid, 1.0f / (float)tvs.transverts_tot);
			copy_v3_v3(cursor, centroid);
		}
		else {
			mid_v3_v3v3(cursor, min, max);
		}

		ED_transverts_free(&tvs);
	}
	else {
		Object *obact = CTX_data_active_object(C);
		
		if (obact && (obact->mode & OB_MODE_POSE)) {
			bArmature *arm = obact->data;
			bPoseChannel *pchan;
			for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
				if (arm->layer & pchan->bone->layer) {
					if (pchan->bone->flag & BONE_SELECTED) {
						copy_v3_v3(vec, pchan->pose_head);
						mul_m4_v3(obact->obmat, vec);
						add_v3_v3(centroid, vec);
						minmax_v3v3_v3(min, max, vec);
						count++;
					}
				}
			}
		}
		else {
			CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
			{
				copy_v3_v3(vec, ob->obmat[3]);

				/* special case for camera -- snap to bundles */
				if (ob->type == OB_CAMERA) {
					/* snap to bundles should happen only when bundles are visible */
					if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
						bundle_midpoint(scene, ob, vec);
					}
				}

				add_v3_v3(centroid, vec);
				minmax_v3v3_v3(min, max, vec);
				count++;
			}
			CTX_DATA_END;
		}

		if (count == 0) {
			return false;
		}

		if (v3d->around == V3D_AROUND_CENTER_MEAN) {
			mul_v3_fl(centroid, 1.0f / (float)count);
			copy_v3_v3(cursor, centroid);
		}
		else {
			mid_v3_v3v3(cursor, min, max);
		}
	}
Esempio n. 25
0
static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
{
	Scene *scene = CTX_data_scene(C);
	Object *obedit = CTX_data_edit_object(C);
	Object *obact = CTX_data_active_object(C);
	View3D *v3d = CTX_wm_view3d(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float imat[3][3], bmat[3][3];
	float center_global[3];
	float offset_global[3];
	int a;

	if (use_offset) {
		if ((v3d && v3d->around == V3D_AROUND_ACTIVE) &&
		    snap_calc_active_center(C, true, center_global))
		{
			/* pass */
		}
		else {
			snap_curs_to_sel_ex(C, center_global);
		}
		sub_v3_v3v3(offset_global, snap_target_global, center_global);
	}

	if (obedit) {
		float snap_target_local[3];
		
		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);
		
		/* get the cursor in object space */
		sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
		mul_m3_v3(imat, snap_target_local);

		if (use_offset) {
			float offset_local[3];

			mul_v3_m3v3(offset_local, imat, offset_global);

			tv = tvs.transverts;
			for (a = 0; a < tvs.transverts_tot; a++, tv++) {
				add_v3_v3(tv->loc, offset_local);
			}
		}
		else {
			tv = tvs.transverts;
			for (a = 0; a < tvs.transverts_tot; a++, tv++) {
				copy_v3_v3(tv->loc, snap_target_local);
			}
		}
		
		ED_transverts_update_obedit(&tvs, obedit);
		ED_transverts_free(&tvs);
	}
	else if (obact && (obact->mode & OB_MODE_POSE)) {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);

		bPoseChannel *pchan;
		bArmature *arm = obact->data;
		float snap_target_local[3];

		invert_m4_m4(obact->imat, obact->obmat);
		mul_v3_m4v3(snap_target_local, obact->imat, snap_target_global);

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			if ((pchan->bone->flag & BONE_SELECTED) &&
			    (PBONE_VISIBLE(arm, pchan->bone)) &&
			    /* if the bone has a parent and is connected to the parent,
			     * don't do anything - will break chain unless we do auto-ik.
			     */
			    (pchan->bone->flag & BONE_CONNECTED) == 0)
			{
				pchan->bone->flag |= BONE_TRANSFORM;
			}
			else {
				pchan->bone->flag &= ~BONE_TRANSFORM;
			}
		}

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			if ((pchan->bone->flag & BONE_TRANSFORM) &&
			    /* check that our parents not transformed (if we have one) */
			    ((pchan->bone->parent &&
			      BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0))
			{
				/* Get position in pchan (pose) space. */
				float cursor_pose[3];

				if (use_offset) {
					mul_v3_m4v3(cursor_pose, obact->obmat, pchan->pose_mat[3]);
					add_v3_v3(cursor_pose, offset_global);

					mul_m4_v3(obact->imat, cursor_pose);
					BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
				}
				else {
					BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose);
				}

				/* copy new position */
				if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
					pchan->loc[0] = cursor_pose[0];
				if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
					pchan->loc[1] = cursor_pose[1];
				if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
					pchan->loc[2] = cursor_pose[2];

				/* auto-keyframing */
				ED_autokeyframe_pchan(C, scene, obact, pchan, ks);
			}
		}

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			pchan->bone->flag &= ~BONE_TRANSFORM;
		}

		obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);

		DAG_id_tag_update(&obact->id, OB_RECALC_DATA);
	}
	else {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
		Main *bmain = CTX_data_main(C);

		ListBase ctx_data_list;
		CollectionPointerLink *ctx_ob;
		Object *ob;

		CTX_data_selected_editable_objects(C, &ctx_data_list);

		/* reset flags */
		for (ob = bmain->object.first; ob; ob = ob->id.next) {
			ob->flag &= ~OB_DONE;
		}

		/* tag objects we're transforming */
		for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
			ob = ctx_ob->ptr.data;
			ob->flag |= OB_DONE;
		}

		for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
			ob = ctx_ob->ptr.data;

			if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {

				float cursor_parent[3];  /* parent-relative */

				if (use_offset) {
					add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
				}
				else {
					copy_v3_v3(cursor_parent, snap_target_global);
				}

				sub_v3_v3(cursor_parent, ob->obmat[3]);

				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, cursor_parent);
				}
				if ((ob->protectflag & OB_LOCK_LOCX) == 0)
					ob->loc[0] += cursor_parent[0];
				if ((ob->protectflag & OB_LOCK_LOCY) == 0)
					ob->loc[1] += cursor_parent[1];
				if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
					ob->loc[2] += cursor_parent[2];

				/* auto-keyframing */
				ED_autokeyframe_object(C, scene, ob, ks);

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

		BLI_freelistN(&ctx_data_list);
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	
	return OPERATOR_FINISHED;
}
Esempio n. 26
0
/* only valid for perspective cameras */
int camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3])
{
	float shift[2];
	float plane_tx[4][3];
	float rot_obmat[3][3];
	const float zero[3]= {0,0,0};
	CameraViewFrameData data_cb;

	unsigned int i;

	camera_view_frame(scene, camera_ob->data, data_cb.frame_tx);

	copy_m3_m4(rot_obmat, camera_ob->obmat);
	normalize_m3(rot_obmat);

	for (i= 0; i < 4; i++) {
		/* normalize so Z is always 1.0f*/
		mul_v3_fl(data_cb.frame_tx[i], 1.0f/data_cb.frame_tx[i][2]);
	}

	/* get the shift back out of the frame */
	shift[0]= (data_cb.frame_tx[0][0] +
	           data_cb.frame_tx[1][0] +
	           data_cb.frame_tx[2][0] +
	           data_cb.frame_tx[3][0]) / 4.0f;
	shift[1]= (data_cb.frame_tx[0][1] +
	           data_cb.frame_tx[1][1] +
	           data_cb.frame_tx[2][1] +
	           data_cb.frame_tx[3][1]) / 4.0f;

	for (i= 0; i < 4; i++) {
		mul_m3_v3(rot_obmat, data_cb.frame_tx[i]);
	}

	for (i= 0; i < 4; i++) {
		normal_tri_v3(data_cb.normal_tx[i],
		              zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]);
	}

	/* initialize callback data */
	data_cb.dist_vals[0]=
	data_cb.dist_vals[1]=
	data_cb.dist_vals[2]=
	data_cb.dist_vals[3]= FLT_MAX;
	data_cb.tot= 0;
	/* run callback on all visible points */
	BKE_scene_foreach_display_point(scene, v3d, BA_SELECT,
	                                camera_to_frame_view_cb, &data_cb);

	if (data_cb.tot <= 1) {
		return FALSE;
	}
	else {
		float plane_isect_1[3], plane_isect_1_no[3], plane_isect_1_other[3];
		float plane_isect_2[3], plane_isect_2_no[3], plane_isect_2_other[3];

		float plane_isect_pt_1[3], plane_isect_pt_2[3];

		/* apply the dist-from-plane's to the transformed plane points */
		for (i= 0; i < 4; i++) {
			mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], data_cb.dist_vals[i]);
		}

		isect_plane_plane_v3(plane_isect_1, plane_isect_1_no,
		                     plane_tx[0], data_cb.normal_tx[0],
		                     plane_tx[2], data_cb.normal_tx[2]);
		isect_plane_plane_v3(plane_isect_2, plane_isect_2_no,
		                     plane_tx[1], data_cb.normal_tx[1],
		                     plane_tx[3], data_cb.normal_tx[3]);

		add_v3_v3v3(plane_isect_1_other, plane_isect_1, plane_isect_1_no);
		add_v3_v3v3(plane_isect_2_other, plane_isect_2, plane_isect_2_no);

		if (isect_line_line_v3(plane_isect_1, plane_isect_1_other,
		                       plane_isect_2, plane_isect_2_other,
		                       plane_isect_pt_1, plane_isect_pt_2) == 0)
		{
			return FALSE;
		}
		else {
			float cam_plane_no[3]= {0.0f, 0.0f, -1.0f};
			float plane_isect_delta[3];
			float plane_isect_delta_len;

			mul_m3_v3(rot_obmat, cam_plane_no);

			sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1);
			plane_isect_delta_len= len_v3(plane_isect_delta);

			if (dot_v3v3(plane_isect_delta, cam_plane_no) > 0.0f) {
				copy_v3_v3(r_co, plane_isect_pt_1);

				/* offset shift */
				normalize_v3(plane_isect_1_no);
				madd_v3_v3fl(r_co, plane_isect_1_no, shift[1] * -plane_isect_delta_len);
			}
			else {
				copy_v3_v3(r_co, plane_isect_pt_2);

				/* offset shift */
				normalize_v3(plane_isect_2_no);
				madd_v3_v3fl(r_co, plane_isect_2_no, shift[0] * -plane_isect_delta_len);
			}


			return TRUE;
		}
	}
}
Esempio n. 27
0
static int armature_calc_roll_exec(bContext *C, wmOperator *op) 
{
	Object *ob = CTX_data_edit_object(C);
	const short type = RNA_enum_get(op->ptr, "type");
	const short axis_only = RNA_boolean_get(op->ptr, "axis_only");
	const short axis_flip = RNA_boolean_get(op->ptr, "axis_flip");

	float imat[3][3];

	bArmature *arm = ob->data;
	EditBone *ebone;

	copy_m3_m4(imat, ob->obmat);
	invert_m3(imat);

	if (type == CALC_ROLL_CURSOR) { /* Cursor */
		Scene *scene = CTX_data_scene(C);
		View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
		float cursor_local[3];
		const float   *cursor = give_cursor(scene, v3d);
		
		
		copy_v3_v3(cursor_local, cursor);
		mul_m3_v3(imat, cursor_local);
		
		/* cursor */
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
				float cursor_rel[3];
				sub_v3_v3v3(cursor_rel, cursor_local, ebone->head);
				if (axis_flip) negate_v3(cursor_rel);
				ebone->roll = ED_rollBoneToVector(ebone, cursor_rel, axis_only);
			}
		}
	}
	else {
		float vec[3] = {0.0f, 0.0f, 0.0f};
		if (type == CALC_ROLL_VIEW) { /* View */
			RegionView3D *rv3d = CTX_wm_region_view3d(C);
			if (rv3d == NULL) {
				BKE_report(op->reports, RPT_ERROR, "No region view3d available");
				return OPERATOR_CANCELLED;
			}
			
			copy_v3_v3(vec, rv3d->viewinv[2]);
			mul_m3_v3(imat, vec);
		}
		else if (type == CALC_ROLL_ACTIVE) {
			float mat[3][3], nor[3];
			ebone = (EditBone *)arm->act_edbone;
			if (ebone == NULL) {
				BKE_report(op->reports, RPT_ERROR, "No active bone set");
				return OPERATOR_CANCELLED;
			}
			
			sub_v3_v3v3(nor, ebone->tail, ebone->head);
			vec_roll_to_mat3(nor, ebone->roll, mat);
			copy_v3_v3(vec, mat[2]);
		}
		else { /* Axis */
			assert(type >= 0 && type <= 5);
			if (type < 3) vec[type] = 1.0f;
			else vec[type - 2] = -1.0f;
			mul_m3_v3(imat, vec);
		}
		
		if (axis_flip) negate_v3(vec);
		
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
				/* roll func is a callback which assumes that all is well */
				ebone->roll = ED_rollBoneToVector(ebone, vec, axis_only);
			}
		}
	}
	
	if (arm->flag & ARM_MIRROR_EDIT) {
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
				EditBone *ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, ebone);
				if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
					ebone->roll = -ebone_mirr->roll;
				}
			}
		}
	}
	
	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
	
	return OPERATOR_FINISHED;
}
/* the ctrl-click method */
static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
{
	View3D *v3d;
	bArmature *arm;
	EditBone *ebone, *newbone, *flipbone;
	float mat[3][3], imat[3][3];
	const float *curs;
	int a, to_root = 0;
	Object *obedit;
	Scene *scene;

	scene = CTX_data_scene(C);
	v3d = CTX_wm_view3d(C);
	obedit = CTX_data_edit_object(C);
	arm = obedit->data;
	
	/* find the active or selected bone */
	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
		if (EBONE_VISIBLE(arm, ebone)) {
			if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone)
				break;
		}
	}
	
	if (ebone == NULL) {
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (EBONE_VISIBLE(arm, ebone)) {
				if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone)
					break;
			}
		}
		if (ebone == NULL) 
			return OPERATOR_CANCELLED;
		
		to_root = 1;
	}
	
	ED_armature_deselect_all(obedit);
	
	/* we re-use code for mirror editing... */
	flipbone = NULL;
	if (arm->flag & ARM_MIRROR_EDIT)
		flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);

	for (a = 0; a < 2; a++) {
		if (a == 1) {
			if (flipbone == NULL)
				break;
			else {
				SWAP(EditBone *, flipbone, ebone);
			}
		}
		
		newbone = ED_armature_edit_bone_add(arm, ebone->name);
		arm->act_edbone = newbone;
		
		if (to_root) {
			copy_v3_v3(newbone->head, ebone->head);
			newbone->rad_head = ebone->rad_tail;
			newbone->parent = ebone->parent;
		}
		else {
			copy_v3_v3(newbone->head, ebone->tail);
			newbone->rad_head = ebone->rad_tail;
			newbone->parent = ebone;
			newbone->flag |= BONE_CONNECTED;
		}
		
		curs = ED_view3d_cursor3d_get(scene, v3d);
		copy_v3_v3(newbone->tail, curs);
		sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
		
		if (a == 1)
			newbone->tail[0] = -newbone->tail[0];
		
		copy_m3_m4(mat, obedit->obmat);
		invert_m3_m3(imat, mat);
		mul_m3_v3(imat, newbone->tail);
		
		newbone->length = len_v3v3(newbone->head, newbone->tail);
		newbone->rad_tail = newbone->length * 0.05f;
		newbone->dist = newbone->length * 0.25f;
		
	}
	
	ED_armature_sync_selection(arm->edbo);

	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
	
	return OPERATOR_FINISHED;
}
Esempio n. 29
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *derivedData,
                                  ModifierApplyFlag flag)
{
	DerivedMesh *dm = derivedData;
	DerivedMesh *result;
	ScrewModifierData *ltmd = (ScrewModifierData *) md;
	const int useRenderParams = flag & MOD_APPLY_RENDER;
	
	int *origindex;
	int mpoly_index = 0;
	unsigned int step;
	unsigned int i, j;
	unsigned int i1, i2;
	unsigned int step_tot = useRenderParams ? ltmd->render_steps : ltmd->steps;
	const bool do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0;

	const int quad_ord[4] = {
	    do_flip ? 3 : 0,
	    do_flip ? 2 : 1,
	    do_flip ? 1 : 2,
	    do_flip ? 0 : 3,
	};
	const int quad_ord_ofs[4] = {
	    do_flip ? 2 : 0,
	    do_flip ? 1 : 1,
	    do_flip ? 0 : 2,
	    do_flip ? 3 : 3,
	};

	unsigned int maxVerts = 0, maxEdges = 0, maxPolys = 0;
	const unsigned int totvert = (unsigned int)dm->getNumVerts(dm);
	const unsigned int totedge = (unsigned int)dm->getNumEdges(dm);
	const unsigned int totpoly = (unsigned int)dm->getNumPolys(dm);

	unsigned int *edge_poly_map = NULL;  /* orig edge to orig poly */
	unsigned int *vert_loop_map = NULL;  /* orig vert to orig loop */

	/* UV Coords */
	const unsigned int mloopuv_layers_tot = (unsigned int)CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV);
	MLoopUV **mloopuv_layers = BLI_array_alloca(mloopuv_layers, mloopuv_layers_tot);
	float uv_u_scale;
	float uv_v_minmax[2] = {FLT_MAX, -FLT_MAX};
	float uv_v_range_inv;
	float uv_axis_plane[4];

	char axis_char = 'X';
	bool close;
	float angle = ltmd->angle;
	float screw_ofs = ltmd->screw_ofs;
	float axis_vec[3] = {0.0f, 0.0f, 0.0f};
	float tmp_vec1[3], tmp_vec2[3]; 
	float mat3[3][3];
	float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */
	float mtx_tx_inv[4][4]; /* inverted */
	float mtx_tmp_a[4][4];
	
	unsigned int vc_tot_linked = 0;
	short other_axis_1, other_axis_2;
	const float *tmpf1, *tmpf2;

	unsigned int edge_offset;
	
	MPoly *mpoly_orig, *mpoly_new, *mp_new;
	MLoop *mloop_orig, *mloop_new, *ml_new;
	MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new;
	MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base;

	ScrewVertConnect *vc, *vc_tmp, *vert_connect = NULL;

	const char mpoly_flag = (ltmd->flag & MOD_SCREW_SMOOTH_SHADING) ? ME_SMOOTH : 0;

	/* don't do anything? */
	if (!totvert)
		return CDDM_from_template(dm, 0, 0, 0, 0, 0);

	switch (ltmd->axis) {
		case 0:
			other_axis_1 = 1;
			other_axis_2 = 2;
			break;
		case 1:
			other_axis_1 = 0;
			other_axis_2 = 2;
			break;
		default: /* 2, use default to quiet warnings */
			other_axis_1 = 0;
			other_axis_2 = 1;
			break;
	}

	axis_vec[ltmd->axis] = 1.0f;

	if (ltmd->ob_axis) {
		/* calc the matrix relative to the axis object */
		invert_m4_m4(mtx_tmp_a, ob->obmat);
		copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat);
		mul_m4_m4m4(mtx_tx, mtx_tmp_a, mtx_tx_inv);

		/* calc the axis vec */
		mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */
		normalize_v3(axis_vec);

		/* screw */
		if (ltmd->flag & MOD_SCREW_OBJECT_OFFSET) {
			/* find the offset along this axis relative to this objects matrix */
			float totlen = len_v3(mtx_tx[3]);

			if (totlen != 0.0f) {
				float zero[3] = {0.0f, 0.0f, 0.0f};
				float cp[3];
				screw_ofs = closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec);
			}
			else {
				screw_ofs = 0.0f;
			}
		}

		/* angle */

#if 0   /* cant incluide this, not predictable enough, though quite fun. */
		if (ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
			float mtx3_tx[3][3];
			copy_m3_m4(mtx3_tx, mtx_tx);

			float vec[3] = {0, 1, 0};
			float cross1[3];
			float cross2[3];
			cross_v3_v3v3(cross1, vec, axis_vec);

			mul_v3_m3v3(cross2, mtx3_tx, cross1);
			{
				float c1[3];
				float c2[3];
				float axis_tmp[3];

				cross_v3_v3v3(c1, cross2, axis_vec);
				cross_v3_v3v3(c2, axis_vec, c1);


				angle = angle_v3v3(cross1, c2);

				cross_v3_v3v3(axis_tmp, cross1, c2);
				normalize_v3(axis_tmp);

				if (len_v3v3(axis_tmp, axis_vec) > 1.0f)
					angle = -angle;

			}
		}
#endif
	}
	else {
		/* exis char is used by i_rotate*/
		axis_char = (char)(axis_char + ltmd->axis); /* 'X' + axis */

		/* useful to be able to use the axis vec in some cases still */
		zero_v3(axis_vec);
		axis_vec[ltmd->axis] = 1.0f;
	}

	/* apply the multiplier */
	angle *= (float)ltmd->iter;
	screw_ofs *= (float)ltmd->iter;
	uv_u_scale = 1.0f / (float)(step_tot);

	/* multiplying the steps is a bit tricky, this works best */
	step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);

	/* will the screw be closed?
	 * Note! smaller then FLT_EPSILON * 100 gives problems with float precision so its never closed. */
	if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) &&
	    fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f))
	{
		close = 1;
		step_tot--;
		if (step_tot < 3) step_tot = 3;
	
		maxVerts = totvert  * step_tot;   /* -1 because we're joining back up */
		maxEdges = (totvert * step_tot) + /* these are the edges between new verts */
		           (totedge * step_tot);  /* -1 because vert edges join */
		maxPolys = totedge * step_tot;

		screw_ofs = 0.0f;
	}
	else {
		close = 0;
		if (step_tot < 3) step_tot = 3;

		maxVerts =  totvert  * step_tot; /* -1 because we're joining back up */
		maxEdges =  (totvert * (step_tot - 1)) + /* these are the edges between new verts */
		           (totedge * step_tot);  /* -1 because vert edges join */
		maxPolys =  totedge * (step_tot - 1);
	}

	if ((ltmd->flag & MOD_SCREW_UV_STRETCH_U) == 0) {
		uv_u_scale = (uv_u_scale / (float)ltmd->iter) * (angle / ((float)M_PI * 2.0f));
	}
	
	result = CDDM_from_template(dm, (int)maxVerts, (int)maxEdges, 0, (int)maxPolys * 4, (int)maxPolys);
	
	/* copy verts from mesh */
	mvert_orig =    dm->getVertArray(dm);
	medge_orig =    dm->getEdgeArray(dm);
	
	mvert_new =     result->getVertArray(result);
	mpoly_new =     result->getPolyArray(result);
	mloop_new =     result->getLoopArray(result);
	medge_new =     result->getEdgeArray(result);

	if (!CustomData_has_layer(&result->polyData, CD_ORIGINDEX)) {
		CustomData_add_layer(&result->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, (int)maxPolys);
	}

	origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);

	DM_copy_vert_data(dm, result, 0, 0, (int)totvert); /* copy first otherwise this overwrites our own vertex normals */

	if (mloopuv_layers_tot) {
		float zero_co[3] = {0};
		plane_from_point_normal_v3(uv_axis_plane, zero_co, axis_vec);
	}

	if (mloopuv_layers_tot) {
		unsigned int uv_lay;
		for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) {
			mloopuv_layers[uv_lay] = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, (int)uv_lay);
		}

		if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) {
			for (i = 0, mv_orig = mvert_orig; i < totvert; i++, mv_orig++) {
				const float v = dist_squared_to_plane_v3(mv_orig->co, uv_axis_plane);
				uv_v_minmax[0] = min_ff(v, uv_v_minmax[0]);
				uv_v_minmax[1] = max_ff(v, uv_v_minmax[1]);
			}
			uv_v_minmax[0] = sqrtf_signed(uv_v_minmax[0]);
			uv_v_minmax[1] = sqrtf_signed(uv_v_minmax[1]);
		}

		uv_v_range_inv = uv_v_minmax[1] - uv_v_minmax[0];
		uv_v_range_inv = uv_v_range_inv ? 1.0f / uv_v_range_inv : 0.0f;
	}

	/* Set the locations of the first set of verts */
	
	mv_new = mvert_new;
	mv_orig = mvert_orig;
	
	/* Copy the first set of edges */
	med_orig = medge_orig;
	med_new = medge_new;
	for (i = 0; i < totedge; i++, med_orig++, med_new++) {
		med_new->v1 = med_orig->v1;
		med_new->v2 = med_orig->v2;
		med_new->crease = med_orig->crease;
		med_new->flag = med_orig->flag &  ~ME_LOOSEEDGE;
	}
	
	/* build polygon -> edge map */
	if (totpoly) {
		MPoly *mp_orig;

		mpoly_orig = dm->getPolyArray(dm);
		mloop_orig = dm->getLoopArray(dm);
		edge_poly_map = MEM_mallocN(sizeof(*edge_poly_map) * totedge, __func__);
		memset(edge_poly_map, 0xff, sizeof(*edge_poly_map) * totedge);

		vert_loop_map = MEM_mallocN(sizeof(*vert_loop_map) * totvert, __func__);
		memset(vert_loop_map, 0xff, sizeof(*vert_loop_map) * totvert);

		for (i = 0, mp_orig = mpoly_orig; i < totpoly; i++, mp_orig++) {
			unsigned int loopstart = (unsigned int)mp_orig->loopstart;
			unsigned int loopend = loopstart + (unsigned int)mp_orig->totloop;

			MLoop *ml_orig = &mloop_orig[loopstart];
			unsigned int k;
			for (k = loopstart; k < loopend; k++, ml_orig++) {
				edge_poly_map[ml_orig->e] = i;
				vert_loop_map[ml_orig->v] = k;

				/* also order edges based on faces */
				if (medge_new[ml_orig->e].v1 != ml_orig->v) {
					SWAP(unsigned int, medge_new[ml_orig->e].v1, medge_new[ml_orig->e].v2);
				}
			}
		}
	}
Esempio n. 30
0
/* called from within the core BKE_pose_where_is loop, all animsystems and constraints
 * were executed & assigned. Now as last we do an IK pass */
static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
{
	float R_parmat[3][3], identity[3][3];
	float iR_parmat[3][3];
	float R_bonemat[3][3];
	float goalrot[3][3], goalpos[3];
	float rootmat[4][4], imat[4][4];
	float goal[4][4], goalinv[4][4];
	float irest_basis[3][3], full_basis[3][3];
	float end_pose[4][4], world_pose[4][4];
	float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch = NULL;
	float resultinf = 0.0f;
	int a, flag, hasstretch = 0, resultblend = 0;
	bPoseChannel *pchan;
	IK_Segment *seg, *parent, **iktree, *iktarget;
	IK_Solver *solver;
	PoseTarget *target;
	bKinematicConstraint *data, *poleangledata = NULL;
	Bone *bone;

	if (tree->totchannel == 0)
		return;

	iktree = MEM_mallocN(sizeof(void *) * tree->totchannel, "ik tree");

	for (a = 0; a < tree->totchannel; a++) {
		pchan = tree->pchan[a];
		bone = pchan->bone;

		/* set DoF flag */
		flag = 0;
		if (!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP))
			flag |= IK_XDOF;
		if (!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP))
			flag |= IK_YDOF;
		if (!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP))
			flag |= IK_ZDOF;

		if (tree->stretch && (pchan->ikstretch > 0.0f)) {
			flag |= IK_TRANS_YDOF;
			hasstretch = 1;
		}

		seg = iktree[a] = IK_CreateSegment(flag);

		/* find parent */
		if (a == 0)
			parent = NULL;
		else
			parent = iktree[tree->parent[a]];

		IK_SetParent(seg, parent);

		/* get the matrix that transforms from prevbone into this bone */
		copy_m3_m4(R_bonemat, pchan->pose_mat);

		/* gather transformations for this IK segment */

		if (pchan->parent)
			copy_m3_m4(R_parmat, pchan->parent->pose_mat);
		else
			unit_m3(R_parmat);

		/* bone offset */
		if (pchan->parent && (a > 0))
			sub_v3_v3v3(start, pchan->pose_head, pchan->parent->pose_tail);
		else
			/* only root bone (a = 0) has no parent */
			start[0] = start[1] = start[2] = 0.0f;

		/* change length based on bone size */
		length = bone->length * len_v3(R_bonemat[1]);

		/* compute rest basis and its inverse */
		copy_m3_m3(rest_basis, bone->bone_mat);
		copy_m3_m3(irest_basis, bone->bone_mat);
		transpose_m3(irest_basis);

		/* compute basis with rest_basis removed */
		invert_m3_m3(iR_parmat, R_parmat);
		mul_m3_m3m3(full_basis, iR_parmat, R_bonemat);
		mul_m3_m3m3(basis, irest_basis, full_basis);

		/* basis must be pure rotation */
		normalize_m3(basis);

		/* transform offset into local bone space */
		normalize_m3(iR_parmat);
		mul_m3_v3(iR_parmat, start);

		IK_SetTransform(seg, start, rest_basis, basis, length);

		if (pchan->ikflag & BONE_IK_XLIMIT)
			IK_SetLimit(seg, IK_X, pchan->limitmin[0], pchan->limitmax[0]);
		if (pchan->ikflag & BONE_IK_YLIMIT)
			IK_SetLimit(seg, IK_Y, pchan->limitmin[1], pchan->limitmax[1]);
		if (pchan->ikflag & BONE_IK_ZLIMIT)
			IK_SetLimit(seg, IK_Z, pchan->limitmin[2], pchan->limitmax[2]);

		IK_SetStiffness(seg, IK_X, pchan->stiffness[0]);
		IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]);
		IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]);

		if (tree->stretch && (pchan->ikstretch > 0.0f)) {
			const float ikstretch = pchan->ikstretch * pchan->ikstretch;
			/* this function does its own clamping */
			IK_SetStiffness(seg, IK_TRANS_Y, 1.0f - ikstretch);
			IK_SetLimit(seg, IK_TRANS_Y, IK_STRETCH_STIFF_MIN, IK_STRETCH_STIFF_MAX);
		}
	}

	solver = IK_CreateSolver(iktree[0]);

	/* set solver goals */

	/* first set the goal inverse transform, assuming the root of tree was done ok! */
	pchan = tree->pchan[0];
	if (pchan->parent) {
		/* transform goal by parent mat, so this rotation is not part of the
		 * segment's basis. otherwise rotation limits do not work on the
		 * local transform of the segment itself. */
		copy_m4_m4(rootmat, pchan->parent->pose_mat);
		/* However, we do not want to get (i.e. reverse) parent's scale, as it generates [#31008]
		 * kind of nasty bugs... */
		normalize_m4(rootmat);
	}
	else
		unit_m4(rootmat);
	copy_v3_v3(rootmat[3], pchan->pose_head);

	mul_m4_m4m4(imat, ob->obmat, rootmat);
	invert_m4_m4(goalinv, imat);

	for (target = tree->targets.first; target; target = target->next) {
		float polepos[3];
		int poleconstrain = 0;

		data = (bKinematicConstraint *)target->con->data;

		/* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
		 * strictly speaking, it is a posechannel)
		 */
		BKE_constraint_target_matrix_get(scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);

		/* and set and transform goal */
		mul_m4_m4m4(goal, goalinv, rootmat);

		copy_v3_v3(goalpos, goal[3]);
		copy_m3_m4(goalrot, goal);
		normalize_m3(goalrot);

		/* same for pole vector target */
		if (data->poletar) {
			BKE_constraint_target_matrix_get(scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);

			if (data->flag & CONSTRAINT_IK_SETANGLE) {
				/* don't solve IK when we are setting the pole angle */
				break;
			}
			else {
				mul_m4_m4m4(goal, goalinv, rootmat);
				copy_v3_v3(polepos, goal[3]);
				poleconstrain = 1;

				/* for pole targets, we blend the result of the ik solver
				 * instead of the target position, otherwise we can't get
				 * a smooth transition */
				resultblend = 1;
				resultinf = target->con->enforce;

				if (data->flag & CONSTRAINT_IK_GETANGLE) {
					poleangledata = data;
					data->flag &= ~CONSTRAINT_IK_GETANGLE;
				}
			}
		}

		/* do we need blending? */
		if (!resultblend && target->con->enforce != 1.0f) {
			float q1[4], q2[4], q[4];
			float fac = target->con->enforce;
			float mfac = 1.0f - fac;

			pchan = tree->pchan[target->tip];

			/* end effector in world space */
			copy_m4_m4(end_pose, pchan->pose_mat);
			copy_v3_v3(end_pose[3], pchan->pose_tail);
			mul_serie_m4(world_pose, goalinv, ob->obmat, end_pose, NULL, NULL, NULL, NULL, NULL);

			/* blend position */
			goalpos[0] = fac * goalpos[0] + mfac * world_pose[3][0];
			goalpos[1] = fac * goalpos[1] + mfac * world_pose[3][1];
			goalpos[2] = fac * goalpos[2] + mfac * world_pose[3][2];

			/* blend rotation */
			mat3_to_quat(q1, goalrot);
			mat4_to_quat(q2, world_pose);
			interp_qt_qtqt(q, q1, q2, mfac);
			quat_to_mat3(goalrot, q);
		}

		iktarget = iktree[target->tip];

		if ((data->flag & CONSTRAINT_IK_POS) && data->weight != 0.0f) {
			if (poleconstrain)
				IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos,
				                                 polepos, data->poleangle, (poleangledata == data));
			IK_SolverAddGoal(solver, iktarget, goalpos, data->weight);
		}
		if ((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0f))
			if ((data->flag & CONSTRAINT_IK_AUTO) == 0)
				IK_SolverAddGoalOrientation(solver, iktarget, goalrot,
				                            data->orientweight);
	}

	/* solve */
	IK_Solve(solver, 0.0f, tree->iterations);

	if (poleangledata)
		poleangledata->poleangle = IK_SolverGetPoleAngle(solver);

	IK_FreeSolver(solver);

	/* gather basis changes */
	tree->basis_change = MEM_mallocN(sizeof(float[3][3]) * tree->totchannel, "ik basis change");
	if (hasstretch)
		ikstretch = MEM_mallocN(sizeof(float) * tree->totchannel, "ik stretch");

	for (a = 0; a < tree->totchannel; a++) {
		IK_GetBasisChange(iktree[a], tree->basis_change[a]);

		if (hasstretch) {
			/* have to compensate for scaling received from parent */
			float parentstretch, stretch;

			pchan = tree->pchan[a];
			parentstretch = (tree->parent[a] >= 0) ? ikstretch[tree->parent[a]] : 1.0f;

			if (tree->stretch && (pchan->ikstretch > 0.0f)) {
				float trans[3], length;

				IK_GetTranslationChange(iktree[a], trans);
				length = pchan->bone->length * len_v3(pchan->pose_mat[1]);

				ikstretch[a] = (length == 0.0f) ? 1.0f : (trans[1] + length) / length;
			}
			else
				ikstretch[a] = 1.0;

			stretch = (parentstretch == 0.0f) ? 1.0f : ikstretch[a] / parentstretch;

			mul_v3_fl(tree->basis_change[a][0], stretch);
			mul_v3_fl(tree->basis_change[a][1], stretch);
			mul_v3_fl(tree->basis_change[a][2], stretch);
		}

		if (resultblend && resultinf != 1.0f) {
			unit_m3(identity);
			blend_m3_m3m3(tree->basis_change[a], identity,
			              tree->basis_change[a], resultinf);
		}

		IK_FreeSegment(iktree[a]);
	}

	MEM_freeN(iktree);
	if (ikstretch) MEM_freeN(ikstretch);
}