void FrameDeform(ArmatureFrameView out, ArmatureFrameConstView from, ArmatureFrameConstView deformation)
	{
		auto n = std::min(from.size(), deformation.size());
		assert(out.size() >= n);
		for (size_t i = 0; i < n; i++)
		{
			auto& lt = out[i];
			lt.LocalTransform() = from[i].LocalTransform();
			lt.LocalTransform() *= deformation[i].LocalTransform();
		}
	}
	void FrameTransformMatrix(XMFLOAT4X4* pOut, ArmatureFrameConstView from, ArmatureFrameConstView to, size_t numOut)
	{
		using namespace std;
		size_t n = min(from.size(), to.size());
		if (numOut > 0)
			n = min(n, numOut);
		for (int i = 0; i < n; ++i)
		{
			XMMATRIX mat = Bone::TransformMatrix(from[i], to[i]);
			//mat = XMMatrixTranspose(mat);
			XMStoreFloat4x4(pOut + i, mat);
		}
	}
	void FrameDifference(ArmatureFrameView out, ArmatureFrameConstView from, ArmatureFrameConstView to)
	{
		auto n = std::min(from.size(), to.size());
		assert(out.size() >= n);
		for (size_t i = 0; i < n; i++)
		{
			auto& lt = out[i];
			lt.LocalTransform() = from[i].LocalTransform();
			lt.LocalTransform().Inverse();
			lt.LocalTransform() *= to[i].LocalTransform();

			lt.GlobalTransform() = from[i].GlobalTransform();
			lt.GlobalTransform().Inverse();
			lt.GlobalTransform() *= to[i].GlobalTransform();
		}
	}
float CharacterController::UpdateTargetCharacter(ArmatureFrameConstView frame, ArmatureFrameConstView lastframe, double deltaTime) const
{
	auto bidning = m_pBinding.get();

	if (bidning == nullptr)
		return 0;

	if (try_lock(m_bindMutex))
	{
		std::lock_guard<mutex> guard(m_bindMutex,adopt_lock);
		auto& cframe = m_charaFrame;
		ArmatureFrame f(frame), lf(lastframe);
		auto& sarm = bidning->SourceArmature();
		if (g_IngnoreInputRootRotation)
		{
			RemoveFrameRootTransform(f, sarm);
			RemoveFrameRootTransform(lf, sarm);
		}

		// Linear interpolation between frames
		if (deltaTime > g_MaxiumTimeDelta)
		{
			//! This code pass is buggy!
			ArmatureFrame tf(frame.size()), ltf(lastframe);

			int subStep = (int)ceil(deltaTime / g_MaxiumTimeDelta);
			auto dt = deltaTime / subStep;

			for (int iter = 0; iter < subStep; iter++)
			{
				auto t = (iter + 1)*(1.0 / (subStep));
				FrameLerp(tf, lf, f, t, sarm);

				cout << "sub step [" << iter << ']' << endl;
				bidning->Transform(cframe, tf, ltf, dt);

				ltf = tf;
			}
		}
		else
		{
			bidning->Transform(cframe, f, lf, deltaTime);
		}
		m_pCharacter->MapCurrentFrameForUpdate() = m_charaFrame;
		m_pCharacter->ReleaseCurrentFrameFrorUpdate();
	}

	float l = 100;
	for (auto& bone : frame)
	{
		if (bone.GblTranslation.y < l)
			l = bone.GblTranslation.y;
	}

	using namespace DirectX;

	auto& bone = frame[0];
	//auto pos = frame[0].GblTranslation - MapRefPos + CMapRefPos;

	SychronizeRootDisplacement(bone);

	return 1.0;
}
ArmatureFrame::ArmatureFrame(const ArmatureFrameConstView &frameView)
	: BaseType(frameView.begin(), frameView.end())
{
}