예제 #1
0
/* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */
static void poselib_backup_posecopy(tPoseLib_PreviewData *pld)
{
	bActionGroup *agrp;
	bPoseChannel *pchan;
	
	/* for each posechannel that has an actionchannel in */
	for (agrp = pld->act->groups.first; agrp; agrp = agrp->next) {
		/* try to find posechannel */
		pchan = BKE_pose_channel_find_name(pld->pose, agrp->name);
		
		/* backup data if available */
		if (pchan) {
			tPoseLib_Backup *plb;
			
			/* store backup */
			plb = MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup");
			
			plb->pchan = pchan;
			memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel));
			
			if (pchan->prop)
				plb->oldprops = IDP_CopyProperty(pchan->prop);
			
			BLI_addtail(&pld->backups, plb);
			
			/* mark as being affected */
			if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))
				pld->selcount++;
			pld->totcount++;
		}
	}
}
예제 #2
0
/* Returns total selected vgroups,
 * wpi.defbase_sel is assumed malloc'd, all values are set */
bool *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
{
	bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__);
	bDeformGroup *defgroup;
	unsigned int i;
	Object *armob = BKE_object_pose_armature_get(ob);
	(*r_dg_flags_sel_tot) = 0;

	if (armob) {
		bPose *pose = armob->pose;
		for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) {
			bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name);
			if (pchan && (pchan->bone->flag & BONE_SELECTED)) {
				dg_selection[i] = TRUE;
				(*r_dg_flags_sel_tot) += 1;
			}
			else {
				dg_selection[i] = FALSE;
			}
		}
	}
	else {
		memset(dg_selection, FALSE, sizeof(*dg_selection) * defbase_tot);
	}

	return dg_selection;
}
static int buttons_context_path_pose_bone(ButsContextPath *path)
{
	PointerRNA *ptr = &path->ptr[path->len - 1];

	/* if we already have a (pinned) PoseBone, we're done */
	if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
		return 1;
	}

	/* if we have an armature, get the active bone */
	if (buttons_context_path_object(path)) {
		Object *ob = path->ptr[path->len - 1].data;
		bArmature *arm = ob->data; /* path->ptr[path->len-1].data - works too */

		if (ob->type != OB_ARMATURE || arm->edbo) {
			return 0;
		}
		else {
			if (arm->act_bone) {
				bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, arm->act_bone->name);
				if (pchan) {
					RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &path->ptr[path->len]);
					path->len++;
					return 1;
				}
			}
		}
	}

	/* no path to a bone possible */
	return 0;
}
예제 #4
0
/* calculate difference matrix */
void ED_gpencil_parent_location(bGPDlayer *gpl, float diff_mat[4][4])
{
	Object *ob = gpl->parent;

	if (ob == NULL) {
		unit_m4(diff_mat);
		return;
	}
	else {
		if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
			mul_m4_m4m4(diff_mat, ob->obmat, gpl->inverse);
			return;
		}
		else if (gpl->partype == PARBONE) {
			bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, gpl->parsubstr);
			if (pchan) {
				float tmp_mat[4][4];
				mul_m4_m4m4(tmp_mat, ob->obmat, pchan->pose_mat);
				mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
			}
			else {
				mul_m4_m4m4(diff_mat, ob->obmat, gpl->inverse); /* if bone not found use object (armature) */
			}
			return;
		}
		else {
			unit_m4(diff_mat); /* not defined type */
		}
	}
}
void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
{
	bArmature *arm = (bArmature *)ob_arm->data;
	int flag = arm->flag;
	std::vector<float> fra;
	//char prefix[256];

	FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
	while (fcu) {
		std::string bone_name = getObjectBoneName(ob_arm, fcu);
		int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
		if (val == 0) break;
		fcu = fcu->next;
	}

	if (!(fcu)) return; 
	bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
	if (!pchan)
		return;

	find_frames(ob_arm, fra);

	if (flag & ARM_RESTPOS) {
		arm->flag &= ~ARM_RESTPOS;
		BKE_pose_where_is(scene, ob_arm);
	}

	if (fra.size()) {
		dae_baked_animation(fra, ob_arm, bone);
	}

	if (flag & ARM_RESTPOS) 
		arm->flag = flag;
	BKE_pose_where_is(scene, ob_arm);
}
예제 #6
0
/* perform syncing updates for Action Groups */
static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGroup **active_agrp)
{
	bActionGroup *agrp = (bActionGroup *)ale->data;
	ID *owner_id = ale->id;
	
	/* major priority is selection status
	 * so we need both a group and an owner
	 */
	if (ELEM(NULL, agrp, owner_id))
		return;
		
	/* for standard Objects, check if group is the name of some bone */
	if (GS(owner_id->name) == ID_OB) {
		Object *ob = (Object *)owner_id;
		
		/* check if there are bones, and whether the name matches any 
		 * NOTE: this feature will only really work if groups by default contain the F-Curves for a single bone
		 */
		if (ob->pose) {
			bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
			bArmature *arm = ob->data;
			
			if (pchan) {
				bActionGroup *bgrp;
				
				/* if one matches, sync the selection status */
				if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))
					agrp->flag |= AGRP_SELECTED;
				else
					agrp->flag &= ~AGRP_SELECTED;
					
				/* also sync active group status */
				if ((ob == ac->obact) && (pchan->bone == arm->act_bone)) {
					/* if no previous F-Curve has active flag, then we're the first and only one to get it */
					if (*active_agrp == NULL) {
						agrp->flag |= AGRP_ACTIVE;
						*active_agrp = agrp;
					}
					else {
						/* someone else has already taken it - set as not active */
						agrp->flag &= ~AGRP_ACTIVE;
					}
				}
				else {
					/* this can't possibly be active now */
					agrp->flag &= ~AGRP_ACTIVE;
				}
				
				/* sync group colors */
				bgrp = (bActionGroup *)BLI_findlink(&ob->pose->agroups, (pchan->agrp_index - 1));
				if (bgrp) {
					agrp->customCol = bgrp->customCol;
					action_group_colors_sync(agrp, bgrp);
				}
			}
		}
	}
}
예제 #7
0
/* Applies the appropriate stored pose from the pose-library to the current pose
 *	- assumes that a valid object, with a poselib has been supplied
 *	- gets the string to print in the header
 *  - this code is based on the code for extract_pose_from_action in blenkernel/action.c
 */
static void poselib_apply_pose(tPoseLib_PreviewData *pld)
{
	PointerRNA *ptr = &pld->rna_ptr;
	bArmature *arm = pld->arm;
	bPose *pose = pld->pose;
	bPoseChannel *pchan;
	bAction *act = pld->act;
	bActionGroup *agrp;
	
	KeyframeEditData ked = {{NULL}};
	KeyframeEditFunc group_ok_cb;
	int frame = 1;
	
	/* get the frame */
	if (pld->marker)
		frame = pld->marker->frame;
	else
		return;
	
	
	/* init settings for testing groups for keyframes */
	group_ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
	ked.f1 = ((float)frame) - 0.5f;
	ked.f2 = ((float)frame) + 0.5f;
	
	
	/* start applying - only those channels which have a key at this point in time! */
	for (agrp = act->groups.first; agrp; agrp = agrp->next) {
		/* check if group has any keyframes */
		if (ANIM_animchanneldata_keyframes_loop(&ked, NULL, agrp, ALE_GROUP, NULL, group_ok_cb, NULL)) {
			/* has keyframe on this frame, so try to get a PoseChannel with this name */
			pchan = BKE_pose_channel_find_name(pose, agrp->name);
			
			if (pchan) {
				short ok = 0;
				
				/* check if this bone should get any animation applied */
				if (pld->selcount == 0) {
					/* if no bones are selected, then any bone is ok */
					ok = 1;
				}
				else if (pchan->bone) {
					/* only ok if bone is visible and selected */
					if ((pchan->bone->flag & BONE_SELECTED) &&
					    (pchan->bone->flag & BONE_HIDDEN_P) == 0 &&
					    (pchan->bone->layer & arm->layer))
					{
						ok = 1;
					}
				}
				
				if (ok) 
					animsys_evaluate_action_group(ptr, act, agrp, NULL, (float)frame);
			}
		}
	}
}
예제 #8
0
void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
{
	if (ob->pose == NULL) {
		return;
	}

	BKE_pose_channels_hash_free(ob->pose);
	BKE_pose_channels_hash_make(ob->pose);

	GHash *name_map = BLI_ghash_str_new(__func__);

	for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) {
		EditBone *ebone_dst = ebone_src->temp.ebone;
		if (!ebone_dst) {
			ebone_dst = ED_armature_bone_get_mirrored(editbones, ebone_src);
		}
		if (ebone_dst) {
			BLI_ghash_insert(name_map, ebone_src->name, ebone_dst->name);
		}
	}

	for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) {
		EditBone *ebone_dst = ebone_src->temp.ebone;
		if (ebone_dst) {
			bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name);
			if (pchan_src) {
				bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name);
				if (pchan_dst) {
					if (pchan_src->custom_tx) {
						pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx);
					}
					if (pchan_src->bbone_prev) {
						pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev);
					}
					if (pchan_src->bbone_next) {
						pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next);
					}
				}
			}
		}
	}

	BLI_ghash_free(name_map, NULL, NULL);
}
예제 #9
0
static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonename)
{
	bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename);
	if (pchan) {
		mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
	}
	else {
		copy_m4_m4(mat, ob->obmat);
	}
}
예제 #10
0
파일: action.c 프로젝트: UPBGE/blender
/**
 * \see #ED_armature_bone_get_mirrored (edit-mode, matching function)
 */
bPoseChannel *BKE_pose_channel_get_mirrored(const bPose *pose, const char *name)
{
	char name_flip[MAXBONENAME];

	BKE_deform_flip_side_name(name_flip, name, false);

	if (!STREQ(name_flip, name)) {
		return BKE_pose_channel_find_name(pose, name_flip);
	}

	return NULL;
}
bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix)
{
	bPoseChannel *pchan;

	ApplyPose();
	pchan = BKE_pose_channel_find_name(m_objArma->pose, bone->name);
	if (pchan)
		matrix.setValue(&pchan->pose_mat[0][0]);
	RestorePose();

	return (pchan != NULL);
}
예제 #12
0
static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	bArmature *arm = (bArmature *)ob->data;
	bConstraint *con;
	int found = 0;
	
	CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
	{
		if (pchan->bone->flag & BONE_SELECTED) {
			for (con = pchan->constraints.first; con; con = con->next) {
				bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
				ListBase targets = {NULL, NULL};
				bConstraintTarget *ct;
				
				if (cti && cti->get_constraint_targets) {
					cti->get_constraint_targets(con, &targets);
					
					for (ct = targets.first; ct; ct = ct->next) {
						if ((ct->tar == ob) && (ct->subtarget[0])) {
							bPoseChannel *pchanc = BKE_pose_channel_find_name(ob->pose, ct->subtarget);
							if ((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) {
								pchanc->bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
								found = 1;
							}
						}
					}
					
					if (cti->flush_constraint_targets)
						cti->flush_constraint_targets(con, &targets, 1);
				}
			}
		}
	}
	CTX_DATA_END;
	
	if (!found)
		return OPERATOR_CANCELLED;
	
	/* updates */
	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
	
	if (arm->flag & ARM_HAS_VIZ_DEPS) {
		/* mask modifier ('armature' mode), etc. */
		DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	}
	
	return OPERATOR_FINISHED;
}
예제 #13
0
void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
{
	bPoseChannel *parchan = NULL;
	bPose *pose = ob_arm->pose;

	pchan = BKE_pose_channel_find_name(pose, bone->name);

	if (!pchan)
		return;

	parchan = pchan->parent;

	enable_fcurves(ob_arm->adt->action, bone->name);

	std::vector<float>::iterator it;
	for (it = frames.begin(); it != frames.end(); it++) {
		float mat[4][4], ipar[4][4];

		float ctime = BKE_scene_frame_get_from_ctime(scene, *it);


		BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
		BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);

		// compute bone local mat
		if (bone->parent) {
			invert_m4_m4(ipar, parchan->pose_mat);
			mult_m4_m4m4(mat, ipar, pchan->pose_mat);
		}
		else
			copy_m4_m4(mat, pchan->pose_mat);

		switch (type) {
			case 0:
				mat4_to_eul(v, mat);
				break;
			case 1:
				mat4_to_size(v, mat);
				break;
			case 2:
				copy_v3_v3(v, mat[3]);
				break;
		}

		v += 3;
	}

	enable_fcurves(ob_arm->adt->action, NULL);
}
예제 #14
0
/**
 * Allocate a new pose on the heap, and copy the src pose and it's channels
 * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL.
 *
 * \param dst  Should be freed already, makes entire duplicate.
 */
void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
{
	bPose *outPose;
	bPoseChannel *pchan;
	ListBase listb;

	if (!src) {
		*dst = NULL;
		return;
	}
	
	outPose = MEM_callocN(sizeof(bPose), "pose");
	
	BLI_duplicatelist(&outPose->chanbase, &src->chanbase);

	outPose->iksolver = src->iksolver;
	outPose->ikdata = NULL;
	outPose->ikparam = MEM_dupallocN(src->ikparam);
	outPose->avs = src->avs;
	
	for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) {

		if (pchan->custom) {
			id_us_plus(&pchan->custom->id);
		}

		/* warning, O(n2) here, but it's a rarely used feature. */
		if (pchan->custom_tx) {
			pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name);
		}

		if (copy_constraints) {
			BKE_constraints_copy(&listb, &pchan->constraints, true);  // BKE_constraints_copy NULLs listb
			pchan->constraints = listb;
			pchan->mpath = NULL; /* motion paths should not get copied yet... */
		}
		
		if (pchan->prop) {
			pchan->prop = IDP_CopyProperty(pchan->prop);
		}
	}

	/* for now, duplicate Bone Groups too when doing this */
	if (copy_constraints) {
		BLI_duplicatelist(&outPose->agroups, &src->agroups);
	}
	
	*dst = outPose;
}
예제 #15
0
/**
 * Helper function for #postEditBoneDuplicate,
 * return the destination pchan from the original.
 */
static bPoseChannel *pchan_duplicate_map(const bPose *pose, GHash *name_map, bPoseChannel *pchan_src)
{
	bPoseChannel *pchan_dst = NULL;
	const char *name_src = pchan_src->name;
	const char *name_dst = BLI_ghash_lookup(name_map, name_src);
	if (name_dst) {
		pchan_dst = BKE_pose_channel_find_name(pose, name_dst);
	}

	if (pchan_dst == NULL) {
		pchan_dst = pchan_src;
	}

	return pchan_dst;
}
static int bone_skinnable_cb(Object *ob, Bone *bone, void *datap)
{
	/* Bones that are deforming
	 * are regarded to be "skinnable" and are eligible for
	 * auto-skinning.
	 *
	 * This function performs 2 functions:
	 *
	 *   a) It returns 1 if the bone is skinnable.
	 *      If we loop over all bones with this 
	 *      function, we can count the number of
	 *      skinnable bones.
	 *   b) If the pointer data is non null,
	 *      it is treated like a handle to a
	 *      bone pointer -- the bone pointer
	 *      is set to point at this bone, and
	 *      the pointer the handle points to
	 *      is incremented to point to the
	 *      next member of an array of pointers
	 *      to bones. This way we can loop using
	 *      this function to construct an array of
	 *      pointers to bones that point to all
	 *      skinnable bones.
	 */
	Bone ***hbone;
	int a, segments;
	struct { Object *armob; void *list; int heat; } *data = datap;

	if (!(ob->mode & OB_MODE_WEIGHT_PAINT) || !(bone->flag & BONE_HIDDEN_P)) {
		if (!(bone->flag & BONE_NO_DEFORM)) {
			if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
				segments = bone->segments;
			else
				segments = 1;
			
			if (data->list != NULL) {
				hbone = (Bone ***) &data->list;
				
				for (a = 0; a < segments; a++) {
					**hbone = bone;
					++*hbone;
				}
			}
			return segments;
		}
	}
	return 0;
}
예제 #17
0
파일: action.c 프로젝트: UPBGE/blender
/* both poses should be in sync */
bool BKE_pose_copy_result(bPose *to, bPose *from)
{
	bPoseChannel *pchanto, *pchanfrom;
	
	if (to == NULL || from == NULL) {
		printf("Pose copy error, pose to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */
		return false;
	}

	if (to == from) {
		printf("BKE_pose_copy_result source and target are the same\n");
		return false;
	}


	for (pchanfrom = from->chanbase.first; pchanfrom; pchanfrom = pchanfrom->next) {
		pchanto = BKE_pose_channel_find_name(to, pchanfrom->name);
		if (pchanto) {
			copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat);
			copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat);
			
			/* used for local constraints */
			copy_v3_v3(pchanto->loc, pchanfrom->loc);
			copy_qt_qt(pchanto->quat, pchanfrom->quat);
			copy_v3_v3(pchanto->eul, pchanfrom->eul);
			copy_v3_v3(pchanto->size, pchanfrom->size);
			
			copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head);
			copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail);
			
			pchanto->roll1 = pchanfrom->roll1;
			pchanto->roll2 = pchanfrom->roll2;
			pchanto->curveInX = pchanfrom->curveInX;
			pchanto->curveInY = pchanfrom->curveInY;
			pchanto->curveOutX = pchanfrom->curveOutX;
			pchanto->curveOutY = pchanfrom->curveOutY;
			pchanto->scaleIn = pchanfrom->scaleIn;
			pchanto->scaleOut = pchanfrom->scaleOut;
			
			pchanto->rotmode = pchanfrom->rotmode;
			pchanto->flag = pchanfrom->flag;
			pchanto->protectflag = pchanfrom->protectflag;
			pchanto->bboneflag = pchanfrom->bboneflag;
		}
	}
	return true;
}
예제 #18
0
/* Auto-keys/tags bones affected by the pose used from the poselib */
static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData *pld)
{
	bPose *pose = pld->pose;
	bPoseChannel *pchan;
	bAction *act = pld->act;
	bActionGroup *agrp;
	
	KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
	ListBase dsources = {NULL, NULL};
	short autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id);
	
	/* start tagging/keying */
	for (agrp = act->groups.first; agrp; agrp = agrp->next) {
		/* only for selected bones unless there aren't any selected, in which case all are included  */
		pchan = BKE_pose_channel_find_name(pose, agrp->name);
		
		if (pchan) {
			if ((pld->selcount == 0) || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) {
				if (autokey) {
					/* add datasource override for the PoseChannel, to be used later */
					ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan); 
					
					/* clear any unkeyed tags */
					if (pchan->bone)
						pchan->bone->flag &= ~BONE_UNKEYED;
				}
				else {
					/* add unkeyed tags */
					if (pchan->bone)
						pchan->bone->flag |= BONE_UNKEYED;
				}
			}
		}
	}
	
	/* perform actual auto-keying now */
	if (autokey) {
		/* insert keyframes for all relevant bones in one go */
		ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
		BLI_freelistN(&dsources);
	}
	
	/* send notifiers for this */
	WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
예제 #19
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]);
		}
	}
}
void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
{
	bArmature *arm = (bArmature *)ob_arm->data;
	int flag = arm->flag;
	std::vector<float> fra;
	//char prefix[256];

	//Check if there is a fcurve in the armature for the bone in param
	//when baking this check is not needed, solve every bone for every frame.
	/*FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;

	while (fcu) {
		std::string bone_name = getObjectBoneName(ob_arm, fcu);
		int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
		if (val == 0) break;
		fcu = fcu->next;
	}

	if (!(fcu)) return;*/ 

	bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
	if (!pchan)
		return;

	//every inserted keyframe of bones.	
	find_frames(ob_arm, fra);

	if (flag & ARM_RESTPOS) {
		arm->flag &= ~ARM_RESTPOS;
		BKE_pose_where_is(scene, ob_arm);
	}

	if (fra.size()) {
		dae_baked_animation(fra, ob_arm, bone);
	}

	if (flag & ARM_RESTPOS) 
		arm->flag = flag;
	BKE_pose_where_is(scene, ob_arm);
}
예제 #21
0
/* 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);
			}
		}
	}
}
예제 #22
0
파일: action.c 프로젝트: UPBGE/blender
/* only for real IK, not for auto-IK */
static bool pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan, int level)
{
	bConstraint *con;
	Bone *bone;
	
	/* No need to check if constraint is active (has influence),
	 * since all constraints with CONSTRAINT_IK_AUTO are active */
	for (con = pchan->constraints.first; con; con = con->next) {
		if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
			bKinematicConstraint *data = con->data;
			if ((data->rootbone == 0) || (data->rootbone > level)) {
				if ((data->flag & CONSTRAINT_IK_AUTO) == 0)
					return true;
			}
		}
	}
	for (bone = pchan->bone->childbase.first; bone; bone = bone->next) {
		pchan = BKE_pose_channel_find_name(ob->pose, bone->name);
		if (pchan && pose_channel_in_IK_chain(ob, pchan, level + 1))
			return true;
	}
	return false;
}
Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def)
{
	bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name);
	return pchan ? pchan->bone : NULL;
}
예제 #24
0
/* seems messy, but thats what you get with not using pointers but channel names :) */
void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *newnamep)
{
	Object *ob;
	char newname[MAXBONENAME];
	char oldname[MAXBONENAME];
	
	/* names better differ! */
	if (strncmp(oldnamep, newnamep, MAXBONENAME)) {
		
		/* we alter newname string... so make copy */
		BLI_strncpy(newname, newnamep, MAXBONENAME);
		/* we use oldname for search... so make copy */
		BLI_strncpy(oldname, oldnamep, MAXBONENAME);
		
		/* now check if we're in editmode, we need to find the unique name */
		if (arm->edbo) {
			EditBone *eBone = ED_armature_bone_find_name(arm->edbo, oldname);
			
			if (eBone) {
				unique_editbone_name(arm->edbo, newname, NULL);
				BLI_strncpy(eBone->name, newname, MAXBONENAME);
			}
			else {
				return;
			}
		}
		else {
			Bone *bone = BKE_armature_find_bone_name(arm, oldname);
			
			if (bone) {
				unique_bone_name(arm, newname);
				BLI_strncpy(bone->name, newname, MAXBONENAME);
			}
			else {
				return;
			}
		}
		
		/* do entire dbase - objects */
		for (ob = G.main->object.first; ob; ob = ob->id.next) {
			ModifierData *md;
			
			/* we have the object using the armature */
			if (arm == ob->data) {
				Object *cob;
				
				/* Rename the pose channel, if it exists */
				if (ob->pose) {
					bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname);
					if (pchan) {
						GHash *gh = ob->pose->chanhash;

						/* remove the old hash entry, and replace with the new name */
						if (gh) {
							BLI_assert(BLI_ghash_haskey(gh, pchan->name));
							BLI_ghash_remove(gh, pchan->name, NULL, NULL);
						}

						BLI_strncpy(pchan->name, newname, MAXBONENAME);

						if (gh) {
							BLI_ghash_insert(gh, pchan->name, pchan);
						}
					}

					BLI_assert(BKE_pose_channels_is_valid(ob->pose) == true);
				}
				
				/* Update any object constraints to use the new bone name */
				for (cob = G.main->object.first; cob; cob = cob->id.next) {
					if (cob->constraints.first)
						constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
					if (cob->pose) {
						bPoseChannel *pchan;
						for (pchan = cob->pose->chanbase.first; pchan; pchan = pchan->next) {
							constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname);
						}
					}
				}
			}
			
			/* See if an object is parented to this armature */
			if (ob->parent && (ob->parent->data == arm)) {
				if (ob->partype == PARBONE) {
					/* bone name in object */
					if (!strcmp(ob->parsubstr, oldname))
						BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
				}
			}
			
			if (modifiers_usesArmature(ob, arm)) {
				bDeformGroup *dg = defgroup_find_name(ob, oldname);
				if (dg) {
					BLI_strncpy(dg->name, newname, MAXBONENAME);
				}
			}
			
			/* fix modifiers that might be using this name */
			for (md = ob->modifiers.first; md; md = md->next) {
				switch (md->type) {
					case eModifierType_Hook:
					{
						HookModifierData *hmd = (HookModifierData *)md;

						if (hmd->object && (hmd->object->data == arm)) {
							if (STREQ(hmd->subtarget, oldname))
								BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
						}
						break;
					}
					case eModifierType_UVWarp:
					{
						UVWarpModifierData *umd = (UVWarpModifierData *)md;

						if (umd->object_src && (umd->object_src->data == arm)) {
							if (STREQ(umd->bone_src, oldname))
								BLI_strncpy(umd->bone_src, newname, MAXBONENAME);
						}
						if (umd->object_dst && (umd->object_dst->data == arm)) {
							if (STREQ(umd->bone_dst, oldname))
								BLI_strncpy(umd->bone_dst, newname, MAXBONENAME);
						}
						break;
					}
					default:
						break;
				}
			}
		}
		
		/* Fix all animdata that may refer to this bone - we can't just do the ones attached to objects, since
		 * other ID-blocks may have drivers referring to this bone [#29822]
		 */
		{
			
			BKE_all_animdata_fix_paths_rename(&arm->id, "pose.bones", oldname, newname);
		}
		
		/* correct view locking */
		{
			bScreen *screen;
			for (screen = G.main->screen.first; screen; screen = screen->id.next) {
				ScrArea *sa;
				/* add regions */
				for (sa = screen->areabase.first; sa; sa = sa->next) {
					SpaceLink *sl;
					for (sl = sa->spacedata.first; sl; sl = sl->next) {
						if (sl->spacetype == SPACE_VIEW3D) {
							View3D *v3d = (View3D *)sl;
							if (v3d->ob_centre && v3d->ob_centre->data == arm) {
								if (!strcmp(v3d->ob_centre_bone, oldname)) {
									BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
								}
							}
						}
					}
				}
			}
		}
	}
}
예제 #25
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *derivedData,
                                  ModifierApplyFlag UNUSED(flag))
{
	MaskModifierData *mmd = (MaskModifierData *)md;
	DerivedMesh *dm = derivedData, *result = NULL;
	GHash *vertHash = NULL, *edgeHash, *polyHash;
	GHashIterator *hashIter;
	MDeformVert *dvert = NULL, *dv;
	int numPolys = 0, numLoops = 0, numEdges = 0, numVerts = 0;
	int maxVerts, maxEdges, maxPolys;
	int i;

	MPoly *mpoly;
	MLoop *mloop;

	MPoly *mpoly_new;
	MLoop *mloop_new;
	MEdge *medge_new;
	MVert *mvert_new;


	int *loop_mapping;

	/* Overview of Method:
	 *	1. Get the vertices that are in the vertexgroup of interest 
	 *	2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices
	 *	3. Make a new mesh containing only the mapping data
	 */
	
	/* get original number of verts, edges, and faces */
	maxVerts = dm->getNumVerts(dm);
	maxEdges = dm->getNumEdges(dm);
	maxPolys = dm->getNumPolys(dm);
	
	/* check if we can just return the original mesh 
	 *	- must have verts and therefore verts assigned to vgroups to do anything useful
	 */
	if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) ||
	    (maxVerts == 0) || (ob->defbase.first == NULL) )
	{
		return derivedData;
	}
	
	/* if mode is to use selected armature bones, aggregate the bone groups */
	if (mmd->mode == MOD_MASK_MODE_ARM) { /* --- using selected bones --- */
		Object *oba = mmd->ob_arm;
		bPoseChannel *pchan;
		bDeformGroup *def;
		char *bone_select_array;
		int bone_select_tot = 0;
		const int defbase_tot = BLI_countlist(&ob->defbase);
		
		/* check that there is armature object with bones to use, otherwise return original mesh */
		if (ELEM3(NULL, oba, oba->pose, ob->defbase.first))
			return derivedData;
		
		/* determine whether each vertexgroup is associated with a selected bone or not 
		 * - each cell is a boolean saying whether bone corresponding to the ith group is selected
		 * - groups that don't match a bone are treated as not existing (along with the corresponding ungrouped verts)
		 */
		bone_select_array = MEM_mallocN(defbase_tot * sizeof(char), "mask array");
		
		for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
			pchan = BKE_pose_channel_find_name(oba->pose, def->name);
			if (pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
				bone_select_array[i] = TRUE;
				bone_select_tot++;
			}
			else {
				bone_select_array[i] = FALSE;
			}
		}
		
		/* if no dverts (i.e. no data for vertex groups exists), we've got an
		 * inconsistent situation, so free hashes and return oirginal mesh
		 */
		dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
		if (dvert == NULL) {
			MEM_freeN(bone_select_array);
			return derivedData;
		}
		
		/* verthash gives mapping from original vertex indices to the new indices (including selected matches only)
		 * key = oldindex, value = newindex
		 */
		vertHash = BLI_ghash_int_new("mask vert gh");
		
		/* add vertices which exist in vertexgroups into vertHash for filtering 
		 * - dv = for each vertex, what vertexgroups does it belong to
		 * - dw = weight that vertex was assigned to a vertexgroup it belongs to
		 */
		for (i = 0, dv = dvert; i < maxVerts; i++, dv++) {
			MDeformWeight *dw = dv->dw;
			short found = 0;
			int j;
			
			/* check the groups that vertex is assigned to, and see if it was any use */
			for (j = 0; j < dv->totweight; j++, dw++) {
				if (dw->def_nr < defbase_tot) {
					if (bone_select_array[dw->def_nr]) {
						if (dw->weight != 0.0f) {
							found = TRUE;
							break;
						}
					}
				}
			}
			
			/* check if include vert in vertHash */
			if (mmd->flag & MOD_MASK_INV) {
				/* if this vert is in the vgroup, don't include it in vertHash */
				if (found) continue;
			}
			else {
				/* if this vert isn't in the vgroup, don't include it in vertHash */
				if (!found) continue;
			}
			
			/* add to ghash for verts (numVerts acts as counter for mapping) */
			BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
			numVerts++;
		}
		
		/* free temp hashes */
		MEM_freeN(bone_select_array);
	}
	else {  /* --- Using Nominated VertexGroup only --- */
		int defgrp_index = defgroup_name_index(ob, mmd->vgroup);
		
		/* get dverts */
		if (defgrp_index != -1)
			dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
			
		/* if no vgroup (i.e. dverts) found, return the initial mesh */
		if ((defgrp_index == -1) || (dvert == NULL))
			return dm;
			
		/* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
		vertHash = BLI_ghash_int_new("mask vert2 bh");
		
		/* add vertices which exist in vertexgroup into ghash for filtering */
		for (i = 0, dv = dvert; i < maxVerts; i++, dv++) {
			const int weight_set = defvert_find_weight(dv, defgrp_index) != 0.0f;
			
			/* check if include vert in vertHash */
			if (mmd->flag & MOD_MASK_INV) {
				/* if this vert is in the vgroup, don't include it in vertHash */
				if (weight_set) continue;
			}
			else {
				/* if this vert isn't in the vgroup, don't include it in vertHash */
				if (!weight_set) continue;
			}
			
			/* add to ghash for verts (numVerts acts as counter for mapping) */
			BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
			numVerts++;
		}
	}

	/* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
	edgeHash = BLI_ghash_int_new("mask ed2 gh");
	polyHash = BLI_ghash_int_new("mask fa2 gh");
	
	mpoly = dm->getPolyArray(dm);
	mloop = dm->getLoopArray(dm);

	loop_mapping = MEM_callocN(sizeof(int) * maxPolys, "mask loopmap"); /* overalloc, assume all polys are seen */

	/* loop over edges and faces, and do the same thing to 
	 * ensure that they only reference existing verts 
	 */
	for (i = 0; i < maxEdges; i++) {
		MEdge me;
		dm->getEdge(dm, i, &me);
		
		/* only add if both verts will be in new mesh */
		if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) &&
		    BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
		{
			BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges));
			numEdges++;
		}
	}
	for (i = 0; i < maxPolys; i++) {
		MPoly *mp = &mpoly[i];
		MLoop *ml = mloop + mp->loopstart;
		int ok = TRUE;
		int j;
		
		for (j = 0; j < mp->totloop; j++, ml++) {
			if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v))) {
				ok = FALSE;
				break;
			}
		}
		
		/* all verts must be available */
		if (ok) {
			BLI_ghash_insert(polyHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numPolys));
			loop_mapping[numPolys] = numLoops;
			numPolys++;
			numLoops += mp->totloop;
		}
	}
	
	
	/* now we know the number of verts, edges and faces, 
	 * we can create the new (reduced) mesh
	 */
	result = CDDM_from_template(dm, numVerts, numEdges, 0, numLoops, numPolys);
	
	mpoly_new = CDDM_get_polys(result);
	mloop_new = CDDM_get_loops(result);
	medge_new = CDDM_get_edges(result);
	mvert_new = CDDM_get_verts(result);
	
	/* using ghash-iterators, map data into new mesh */
	/* vertices */
	for (hashIter = BLI_ghashIterator_new(vertHash);
	     !BLI_ghashIterator_isDone(hashIter);
	     BLI_ghashIterator_step(hashIter) )
	{
		MVert source;
		MVert *dest;
		int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
		int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
		
		dm->getVert(dm, oldIndex, &source);
		dest = &mvert_new[newIndex];
		
		DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
		*dest = source;
	}
	BLI_ghashIterator_free(hashIter);
		
	/* edges */
	for (hashIter = BLI_ghashIterator_new(edgeHash);
	     !BLI_ghashIterator_isDone(hashIter);
	     BLI_ghashIterator_step(hashIter))
	{
		MEdge source;
		MEdge *dest;
		int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
		int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
		
		dm->getEdge(dm, oldIndex, &source);
		dest = &medge_new[newIndex];
		
		source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
		source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
		
		DM_copy_edge_data(dm, result, oldIndex, newIndex, 1);
		*dest = source;
	}
	BLI_ghashIterator_free(hashIter);
	
	/* faces */
	for (hashIter = BLI_ghashIterator_new(polyHash);
	     !BLI_ghashIterator_isDone(hashIter);
	     BLI_ghashIterator_step(hashIter) )
	{
		int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
		int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
		MPoly *source = &mpoly[oldIndex];
		MPoly *dest = &mpoly_new[newIndex];
		int oldLoopIndex = source->loopstart;
		int newLoopIndex = loop_mapping[newIndex];
		MLoop *source_loop = &mloop[oldLoopIndex];
		MLoop *dest_loop = &mloop_new[newLoopIndex];
		
		DM_copy_poly_data(dm, result, oldIndex, newIndex, 1);
		DM_copy_loop_data(dm, result, oldLoopIndex, newLoopIndex, source->totloop);

		*dest = *source;
		dest->loopstart = newLoopIndex;
		for (i = 0; i < source->totloop; i++) {
			dest_loop[i].v = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source_loop[i].v)));
			dest_loop[i].e = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(source_loop[i].e)));
		}
	}

	BLI_ghashIterator_free(hashIter);

	MEM_freeN(loop_mapping);

	/* why is this needed? - campbell */
	/* recalculate normals */
	CDDM_calc_normals(result);
	
	/* free hashes */
	BLI_ghash_free(vertHash, NULL, NULL);
	BLI_ghash_free(edgeHash, NULL, NULL);
	BLI_ghash_free(polyHash, NULL, NULL);

	/* return the new mesh */
	return result;
}
예제 #26
0
PyObject* BL_ActionActuator::PyGetChannel(PyObject* value)
{
	PyErr_SetString(PyExc_NotImplementedError, "BL_ActionActuator.getChannel() no longer works, please use BL_ArmatureObject.channels instead");
	return NULL;
#if 0 // XXX To be removed in a later version (first removed in 2.64)
	const char *string= _PyUnicode_AsString(value);

	if (GetParent()->GetGameObjectType() != SCA_IObject::OBJ_ARMATURE)
	{
		PyErr_SetString(PyExc_NotImplementedError, "actuator.getChannel(): Only armatures support channels");
		return NULL;
	}
	
	if (!string) {
		PyErr_SetString(PyExc_TypeError, "expected a single string");
		return NULL;
	}
	
	bPoseChannel *pchan;
	
	if (m_userpose==NULL && m_pose==NULL) {
		BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
		obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
	}
	
	// BKE_pose_channel_find_name accounts for NULL pose, run on both in case one exists but
	// the channel doesnt
	if (		!(pchan=BKE_pose_channel_find_name(m_userpose, string)) &&
			!(pchan=BKE_pose_channel_find_name(m_pose, string))  )
	{
		PyErr_SetString(PyExc_ValueError, "channel doesnt exist");
		return NULL;
	}

	PyObject *ret = PyTuple_New(3);
	
	PyObject *list = PyList_New(3); 
	PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->loc[0]));
	PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->loc[1]));
	PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->loc[2]));
	PyTuple_SET_ITEM(ret, 0, list);
	
	list = PyList_New(3);
	PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->size[0]));
	PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->size[1]));
	PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->size[2]));
	PyTuple_SET_ITEM(ret, 1, list);
	
	list = PyList_New(4);
	PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->quat[0]));
	PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->quat[1]));
	PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->quat[2]));
	PyList_SET_ITEM(list, 3, PyFloat_FromDouble(pchan->quat[3]));
	PyTuple_SET_ITEM(ret, 2, list);

	return ret;
#if 0
	return Py_BuildValue("([fff][fff][ffff])",
		pchan->loc[0], pchan->loc[1], pchan->loc[2],
		pchan->size[0], pchan->size[1], pchan->size[2],
		pchan->quat[0], pchan->quat[1], pchan->quat[2], pchan->quat[3] );
#endif
#endif
}
std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
{
	std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;

	int totjoint = 0;
	for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
		if (is_bone_defgroup(ob_arm, def))
			totjoint++;
	}

	COLLADASW::FloatSourceF source(mSW);
	source.setId(source_id);
	source.setArrayId(source_id + ARRAY_ID_SUFFIX);
	source.setAccessorCount(totjoint); //BLI_listbase_count(defbase));
	source.setAccessorStride(16);
	
	source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
	COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
	param.push_back("TRANSFORM");

	source.prepareToAppendValues();

	bPose *pose = ob_arm->pose;
	bArmature *arm = (bArmature *)ob_arm->data;

	int flag = arm->flag;

	// put armature in rest position
	if (!(arm->flag & ARM_RESTPOS)) {
		arm->flag |= ARM_RESTPOS;
		BKE_pose_where_is(scene, ob_arm);
	}

	for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
		if (is_bone_defgroup(ob_arm, def)) {
			bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name);

			float mat[4][4];
			float world[4][4];
			float inv_bind_mat[4][4];

			
			// SL/OPEN_SIM COMPATIBILITY
			if (export_settings->open_sim) {
				// Only translations, no rotation vs armature
				float temp[4][4];
				unit_m4(temp);
				copy_v3_v3(temp[3], pchan->bone->arm_mat[3]);
				mul_m4_m4m4(world, ob_arm->obmat, temp);

				// Add Maya restpose matrix (if defined as properties)
				float restpose_mat[4][4];
				create_restpose_mat(pchan->bone, restpose_mat);
				mul_m4_m4m4(world, world, restpose_mat);

			}
			else {
				// make world-space matrix, arm_mat is armature-space
				mul_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat);
			}


			invert_m4_m4(mat, world);
			converter.mat4_to_dae(inv_bind_mat, mat);

			source.appendValues(inv_bind_mat);
		}
	}

	// back from rest positon
	if (!(flag & ARM_RESTPOS)) {
		arm->flag = flag;
		BKE_pose_where_is(scene, ob_arm);
	}

	source.finish();

	return source_id;
}
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);
}
static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap) 
{
	/* Bones that are deforming
	 * are regarded to be "skinnable" and are eligible for
	 * auto-skinning.
	 *
	 * This function performs 2 functions:
	 *
	 *   a) If the bone is skinnable, it creates 
	 *      a vertex group for ob that has
	 *      the name of the skinnable bone
	 *      (if one doesn't exist already).
	 *   b) If the pointer data is non null,
	 *      it is treated like a handle to a
	 *      bDeformGroup pointer -- the 
	 *      bDeformGroup pointer is set to point
	 *      to the deform group with the bone's
	 *      name, and the pointer the handle 
	 *      points to is incremented to point to the
	 *      next member of an array of pointers
	 *      to bDeformGroups. This way we can loop using
	 *      this function to construct an array of
	 *      pointers to bDeformGroups, all with names
	 *      of skinnable bones.
	 */
	bDeformGroup ***hgroup, *defgroup = NULL;
	int a, segments;
	struct { Object *armob; void *list; int heat; } *data = datap;
	int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
	bArmature *arm = data->armob->data;

	if (!wpmode || !(bone->flag & BONE_HIDDEN_P)) {
		if (!(bone->flag & BONE_NO_DEFORM)) {
			if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
				segments = bone->segments;
			else
				segments = 1;
			
			if (!wpmode || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
				if (!(defgroup = defgroup_find_name(ob, bone->name))) {
					defgroup = BKE_object_defgroup_add_name(ob, bone->name);
				}
				else if (defgroup->flag & DG_LOCK_WEIGHT) {
					/* In case vgroup already exists and is locked, do not modify it here. See T43814. */
					defgroup = NULL;
				}
			}
			
			if (data->list != NULL) {
				hgroup = (bDeformGroup ***) &data->list;
				
				for (a = 0; a < segments; a++) {
					**hgroup = defgroup;
					++*hgroup;
				}
			}
			return segments;
		}
	}
	return 0;
}
예제 #30
0
파일: action.c 프로젝트: UPBGE/blender
/**
 * Allocate a new pose on the heap, and copy the src pose and it's channels
 * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL.
 *
 * \param dst  Should be freed already, makes entire duplicate.
 */
void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
{
	bPose *outPose;
	bPoseChannel *pchan;
	ListBase listb;

	if (!src) {
		*dst = NULL;
		return;
	}
	
	outPose = MEM_callocN(sizeof(bPose), "pose");
	
	BLI_duplicatelist(&outPose->chanbase, &src->chanbase);
	
	/* Rebuild ghash here too, so that name lookups below won't be too bad...
	 * BUT this will have the penalty that the ghash will be built twice
	 * if BKE_pose_rebuild() gets called after this...
	 */
	if (outPose->chanbase.first != outPose->chanbase.last) {
		outPose->chanhash = NULL;
		BKE_pose_channels_hash_make(outPose);
	}
	
	outPose->iksolver = src->iksolver;
	outPose->ikdata = NULL;
	outPose->ikparam = MEM_dupallocN(src->ikparam);
	outPose->avs = src->avs;
	
	for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) {

		if (pchan->custom) {
			id_us_plus(&pchan->custom->id);
		}

		/* warning, O(n2) here, if done without the hash, but these are rarely used features. */
		if (pchan->custom_tx) {
			pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name);
		}
		if (pchan->bbone_prev) {
			pchan->bbone_prev = BKE_pose_channel_find_name(outPose, pchan->bbone_prev->name);
		}
		if (pchan->bbone_next) {
			pchan->bbone_next = BKE_pose_channel_find_name(outPose, pchan->bbone_next->name);
		}

		if (copy_constraints) {
			BKE_constraints_copy(&listb, &pchan->constraints, true);  // BKE_constraints_copy NULLs listb
			pchan->constraints = listb;
			pchan->mpath = NULL; /* motion paths should not get copied yet... */
		}
		
		if (pchan->prop) {
			pchan->prop = IDP_CopyProperty(pchan->prop);
		}
	}

	/* for now, duplicate Bone Groups too when doing this */
	if (copy_constraints) {
		BLI_duplicatelist(&outPose->agroups, &src->agroups);
	}
	
	*dst = outPose;
}