Beispiel #1
0
void Editor::Right()
{
	if (mode == ROTATE_VIEW)
		addRot(0, 1.5F, 0);
	if (mode == MOVE_OBJECT) {
		if (Object3DS::selected != NULL)
			Object3DS::selected->transform.position.x += moveStep;
	}
	if (mode == ROTATE_OBJECT) {
		if (Object3DS::selected != NULL)
			Object3DS::selected->transform.rotation.z += rotStep;
	}
}
Beispiel #2
0
void Editor::Backward()
{
	if (mode == ROTATE_VIEW)
		addRot(-1.5F, 0, 0);
	if (mode == MOVE_VIEW)
		addPos(0, 0, 0.8f);
	if (mode == MOVE_OBJECT) {
		if (Object3DS::selected != NULL)
			Object3DS::selected->transform.position.z += moveStep;
	}

	if (mode == ROTATE_OBJECT) {
		if (Object3DS::selected != NULL)
			Object3DS::selected->transform.rotation.x += rotStep;
	}
}
bool UAnimExporterITP::ExportText(const FExportObjectInnerContext* Context, UObject* Object, const TCHAR* Type, FOutputDevice& Ar, FFeedbackContext* Warn, uint32 PortFlags /*= 0*/)
{
	UAnimSequence* AnimSeq = CastChecked<UAnimSequence>(Object);

	USkeleton* Skeleton = AnimSeq->GetSkeleton();
	const FReferenceSkeleton& RefSkeleton = Skeleton->GetReferenceSkeleton();
	USkeletalMesh* SkelMesh = Skeleton->GetPreviewMesh();
	if (AnimSeq->SequenceLength == 0.f)
	{
		// something is wrong
		return false;
	}

	const float FrameRate = AnimSeq->NumFrames / AnimSeq->SequenceLength;

	// Open another archive
	FArchive* File = IFileManager::Get().CreateFileWriter(*UExporter::CurrentFilename);

	// Let's try the header...
	File->Logf(TEXT("{"));
	File->Logf(TEXT("\t\"metadata\":{"));
	File->Logf(TEXT("\t\t\"type\":\"itpanim\","));
	File->Logf(TEXT("\t\t\"version\":2"));
	File->Logf(TEXT("\t},"));

	File->Logf(TEXT("\t\"sequence\":{"));
	File->Logf(TEXT("\t\t\"frames\":%d,"), AnimSeq->NumFrames);
	File->Logf(TEXT("\t\t\"length\":%f,"), AnimSeq->SequenceLength);
	File->Logf(TEXT("\t\t\"bonecount\":%d,"), RefSkeleton.GetNum());
	File->Logf(TEXT("\t\t\"tracks\":["));

	bool firstOutput = false;

	for (int32 BoneIndex = 0; BoneIndex < RefSkeleton.GetNum(); ++BoneIndex)
	{
		//int32 BoneTreeIndex = Skeleton->GetSkeletonBoneIndexFromMeshBoneIndex(SkelMesh, BoneIndex);
		int32 BoneTrackIndex = Skeleton->GetAnimationTrackIndex(BoneIndex, AnimSeq);
		
		if (BoneTrackIndex == INDEX_NONE)
		{
			// If this sequence does not have a track for the current bone, then skip it
			continue;
		}
	
		if (firstOutput)
		{
			File->Logf(TEXT("\t\t\t},"));
		}

		firstOutput = true;

		File->Logf(TEXT("\t\t\t{"));
		File->Logf(TEXT("\t\t\t\t\"bone\":%d,"), BoneIndex);
		File->Logf(TEXT("\t\t\t\t\"transforms\":["));
		float AnimTime = 0.0f;
		float AnimEndTime = AnimSeq->SequenceLength;
		// Subtracts 1 because NumFrames includes an initial pose for 0.0 second
		double TimePerKey = (AnimSeq->SequenceLength / (AnimSeq->NumFrames - 1));
		const float AnimTimeIncrement = TimePerKey;

		bool bLastKey = false;
		// Step through each frame and add the bone's transformation data
		while (!bLastKey)
		{
			const TArray<FBoneNode>& BoneTree = Skeleton->GetBoneTree();

			FTransform BoneAtom;
			AnimSeq->GetBoneTransform(BoneAtom, BoneTrackIndex, AnimTime, true);

			bLastKey = AnimTime >= AnimEndTime;

			File->Logf(TEXT("\t\t\t\t\t{"));

			FQuat rot = BoneAtom.GetRotation();
			// For the root bone, we need to fix-up the rotation because Unreal exports
			// animations with Y-forward for some reason (maybe because Maya?)
			if (BoneIndex == 0)
			{
				FQuat addRot(FVector(0.0f, 0.0f, 1.0f), -1.57f);
				rot = addRot * rot;
			}
			File->Logf(TEXT("\t\t\t\t\t\t\"rot\":[%f,%f,%f,%f],"), rot.X, rot.Y, rot.Z, rot.W);
			FVector trans = BoneAtom.GetTranslation();

			// Sanjay: If it's skeleton retargeting, change the translation to be from the ref pose skeleton
			if (BoneTree[BoneIndex].TranslationRetargetingMode == EBoneTranslationRetargetingMode::Skeleton)
			{
				const FTransform& BoneTransform = RefSkeleton.GetRefBonePose()[BoneIndex];
				trans = BoneTransform.GetTranslation();
			}

			File->Logf(TEXT("\t\t\t\t\t\t\"trans\":[%f,%f,%f]"), trans.X, trans.Y, trans.Z);

			if (!bLastKey)
			{
				File->Logf(TEXT("\t\t\t\t\t},"));
			}
			else
			{
				File->Logf(TEXT("\t\t\t\t\t}"));
			}
			

			AnimTime += AnimTimeIncrement;
		}

		File->Logf(TEXT("\t\t\t\t]"), BoneIndex);
	}

	File->Logf(TEXT("\t\t\t}"));
	File->Logf(TEXT("\t\t]"));
	File->Logf(TEXT("\t}"));

 	File->Logf(TEXT("}"));
 	delete File;

	return true;
}
	/************************************************************************
	  CMinPack minimzation:
	*************************************************************************/
	void SkeletonFitting::updateCMP(Joint* joint)
	{
		// TODO: use same minimization method also with MT_CMINPACK_CCD, just exchange the function

		if (!joint) {
			WARN << "joint invalid" << ENDL;	// should never happen
			return;
		}
		
		// TODO: implement simple steepest descent method using the same functions
		const int i = 0;
		
		// if this is the root joint, also update the position
		if (!joint->getPrevJoint()) {
			const double tol = 0.000001;
			const double factor = 0.01;
			const double eps = 0.00001;
			const int iterFac = 50;

			cv::Point3d addPos(0, 0, 0);
			double addSize = 0;
			
			if (i == 0) {
				minimize(&Payload(joint, 0), funcPos, 1, 1, &addPos.x, tol, iterFac, factor, eps);
				minimize(&Payload(joint, 1), funcPos, 1, 1, &addPos.y, tol, iterFac, factor, eps);
				minimize(&Payload(joint, 2), funcPos, 1, 1, &addPos.z, tol, iterFac, factor, eps);

				if (m_minimizeSize)
					minimize(&Payload(joint, 2), funcSize, 1, 1, &addSize, tol, iterFac, factor, eps);
			}
			else {
				/*minimizeSteepestDesc(&Payload(joint, 0), funcPos, 1, 1, &addPos.x);
				minimizeSteepestDesc(&Payload(joint, 1), funcPos, 1, 1, &addPos.y);
				minimizeSteepestDesc(&Payload(joint, 2), funcPos, 1, 1, &addPos.z);
				
				if (m_minimizeSize)
					minimizeSteepestDesc(&Payload(joint, 2), funcSize, 1, 1, &addSize);*/
			}
		
			joint->addPos3d(addPos);
			joint->addBoneSize(addSize);
			joint->updateForward(false);	// changing position doesn't need constraint checking
		}
		
		// update joint angles
		const double tol = 0.001;
		const int iterFac = 50;
		double factor = 100;
		double eps = 0.001;

		switch (joint->getClass()) {
		case JC_BALLANDSOCKET:
			{
				// update ball and socket joints
				JointBallAndSocket* jointBAS = (JointBallAndSocket*)joint;

				// update angles
				cv::Point3d addRot(0, 0, 0);
			
				if (i == 0) {
					minimize(&Payload(joint, 0), funcBAS, 1, 1, &addRot.x, tol, iterFac, factor, eps);
					minimize(&Payload(joint, 1), funcBAS, 1, 1, &addRot.y, tol, iterFac, factor, eps);
					minimize(&Payload(joint, 2), funcBAS, 1, 1, &addRot.z, tol, iterFac, factor, eps);
				}
				else {
					//minimizeSteepestDesc(&Payload(joint, 0), funcBAS, 1, 1, &addRot.x);
					//minimizeSteepestDesc(&Payload(joint, 1), funcBAS, 1, 1, &addRot.y);
					//minimizeSteepestDesc(&Payload(joint, 2), funcBAS, 1, 1, &addRot.z);
				}


				jointBAS->addOrientation(addRot);
				jointBAS->updateForward(true);

				break;
			}
		case JC_HINGE:
			{
				// update hinge joints
				JointHinge* jointHinge = (JointHinge*)joint;
				
				// update angles
				double addAngle = 0;
				
				if (i == 0) {
					minimize(&Payload(joint, 0), funcHinge, 1, 1, &addAngle, tol, iterFac, factor, eps);
				}
				else {
					//minimizeSteepestDesc(&Payload(joint, 0), funcHinge, 1, 1, &addAngle);
				}

				jointHinge->addAngle(addAngle);
				jointHinge->updateForward(true);

				break;
			}
		case JC_ENDCONNECTOR:
			// no need to update end connector joints, their position is only
			// affected by their subordinate joints
			break;
		case JC_CONNECTOR:
			// does also not need to be updated
			break;
		default:
			WARN << "unknown joint type: " << (int)joint->getClass() << ENDL;
			break;
		}
		
		// if this is not the root joint, update the next previous joint
		if (joint->getPrevJoint())
			updateCMP(joint->getPrevJoint());
	}