internal IKPose GetIkPose(PmdModel pmdModel) { var ikPose = new IKPose(); var normalPose = ikPose.NormalPose; var endEffectorGoals = ikPose.EndEffectorGoals; var assignableBoneTypes = new[] { Bone.BONE_ROTATE, Bone.BONE_ROTATE_TRANSLATE, Bone.BONE_IK_ROTATION_INFLUENCED, Bone.BONE_IK_TARGET }; JointChange jointChange; for (int boneIndex = 0; boneIndex < pmdModel.Bones.Count; boneIndex++) { var bone = pmdModel.Bones.ElementAt(boneIndex); if (assignableBoneTypes.Contains(bone.BoneType)) { try { jointChange = GetRightHandedJointChange(bone.Name); } catch (KeyNotFoundException) { continue; } normalPose.SetJointChange(bone.Name, jointChange); } else if (bone.BoneType == Bone.BONE_ROTATION_INFLUENCED) { var source_bone = pmdModel.Bones.ElementAt(bone.IkBoneIndex); try { jointChange = GetRightHandedJointChange(source_bone.Name); } catch (KeyNotFoundException) { continue; } normalPose.SetJointChange(bone.Name, jointChange); } else if (bone.BoneType == Bone.BONE_IK) { var ikChain = pmdModel.GetIkChainByIkBoneIndex(boneIndex); var endEffectorBone = pmdModel.Bones.ElementAt(ikChain.EndEffectorIndex); var newPosition = pmdModel.GetMorphedWorldPosition(boneIndex, this); endEffectorGoals.SetEndEffectorPosition(endEffectorBone.Name, newPosition); } } return(ikPose); }
/// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); Font.Initialze(GraphicsDevice, Content); miku = Content.Load <PmdModel>("Models/miku"); miku.Initialize(GraphicsDevice, Content); anim = Content.Load <VmdAnimation>("Anims/Lamb"); miku.SetAnim(anim); anim.AnimationSpeed = 0.1f; //bone helper #if WINDOWS helper = new BoneHelper(GraphicsDevice, Content); #endif // TODO: use this.Content to load your game content here }
public PoseAnimation GetIkLessPoseAnimation(PmdModel pmdModel, Func <double, bool> progressHook) { var curves = GetBoneCurves(); var ikArmature = pmdModel.GetIkArmature(); var ikPose = new IKPose(); var pose = new Pose(); var iterators = new Dictionary <string, IEnumerator <ControlPoint <JointChange> > >(); foreach (var item in curves) { var boneName = item.Key; var curve = item.Value; iterators[boneName] = curve.GetControlPointIterator(); } var frames = new Dictionary <string, ControlPoint <JointChange> >(); foreach (var item in iterators) { var boneName = item.Key; var iterator = item.Value; if (iterator.MoveNext()) { frames[boneName] = iterator.Current; } } var ikJointCurves = new Dictionary <string, Polyline <JointChange> >(); foreach (var ikJoint in ikArmature.GetIkJoints()) { ikJointCurves[ikJoint.Name] = new Polyline_JointChange(); } while (frames.Count > 0) { var earliestTime = 1e20f; foreach (var item in frames) { var boneName = item.Key; var frame = item.Value; if (frame.Time < earliestTime) { earliestTime = frame.Time; } } var vpd_pose = GetVpdPose(curves, pmdModel, earliestTime); pose = pmdModel.GetIkLessPose(vpd_pose); foreach (var item in ikJointCurves) { var ikJointName = item.Key; var curve = item.Value; curve.SetControlPoint(earliestTime, pose.GetJointChange(ikJointName)); } var boneNamesWithEarliestTime = new List <string>(); foreach (var item in frames) { var boneName = item.Key; var frame = item.Value; if (Math.Abs(frame.Time - earliestTime) < 0.0001) { boneNamesWithEarliestTime.Add(boneName); } } foreach (var boneName in boneNamesWithEarliestTime) { var iterator = iterators[boneName]; if (iterator.MoveNext()) { frames[boneName] = iterator.Current; } else { frames.Remove(boneName); } } if (progressHook != null) { var continuing = progressHook(earliestTime); if (!continuing) { return(null); } } } var poseAnimation = new PoseAnimation(); curves = new Dictionary <string, Polyline <JointChange> >(); foreach (var boneFrame in boneFrames) { if (!curves.ContainsKey(boneFrame.BoneName)) { curves[boneFrame.BoneName] = new Polyline_JointChange(); } var position = new Vector3D(boneFrame.Position.X, boneFrame.Position.Y, -boneFrame.Position.Z); // var z_flip_matrix = matrix4x4.scale(1, 1, -1); var orientation = new Quaternion(boneFrame.Orientation.X, boneFrame.Orientation.Y, -boneFrame.Orientation.Z, -boneFrame.Orientation.W); curves[boneFrame.BoneName].SetControlPoint(boneFrame.FrameNumber, new JointChange(position, orientation)); } foreach (var item in curves) { var boneName = item.Key; var curve = item.Value; if (pmdModel.BonesByName.ContainsKey(boneName)) { var bone = pmdModel.GetBoneByName(boneName); if (bone.BoneType != Bone.BONE_IK) { poseAnimation.SetJointCurve(boneName, curve); } } } foreach (var item in ikJointCurves) { var boneName = item.Key; var ikJointCurve = item.Value; poseAnimation.SetJointCurve(boneName, ikJointCurve); } foreach (var bone in pmdModel.Bones) { if (bone.BoneType == Bone.BONE_ROTATION_INFLUENCED) { var sourceBone = pmdModel.Bones.ElementAt(bone.IkBoneIndex); var boneCurve = new Polyline_JointChange(); if (curves.ContainsKey(sourceBone.Name)) { var sourceCurve = curves[sourceBone.Name]; foreach (var controlPoint in sourceCurve.GetControlPoints()) { var time = controlPoint.Time; var jc = controlPoint.Value; boneCurve.SetControlPoint(time, new JointChange(new Vector3D(0, 0, 0), jc.Orientation)); } } poseAnimation.SetJointCurve(bone.Name, boneCurve); } } poseAnimation.UpdateRange(); return(poseAnimation); }
private VpdPose GetVpdPose(Dictionary <string, Polyline <JointChange> > curves, PmdModel pmdModel, float time) { var vpdPose = new VpdPose(); foreach (var item in curves) { var boneName = item.Key; var curve = item.Value; var jointChange = curve.Evaluate(time); vpdPose.SetJointChange(boneName, jointChange); } return(vpdPose); }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) { this.Exit(); } // TODO: Add your update logic here //update view if (g_bRotateCamera) { g_time += gameTime.ElapsedGameTime.Milliseconds * 0.001f; CameraPos = new Vector3(g_fDistanceToMiku * (float)Math.Cos(g_time), height, g_fDistanceToMiku * (float)Math.Sin(g_time)); View = Matrix.CreateLookAt(CameraPos, new Vector3(0, height - 5, 0), new Vector3(0, 1, 0)); } miku.Update(gameTime); #region Control //control region KeyboardState currentState = Keyboard.GetState(); MouseState currentMouseState = Mouse.GetState(); if (currentState.IsKeyDown(Keys.C) && lastKeyState.IsKeyUp(Keys.C)) { miku = Content.Load <PmdModel>("Models/model_1"); miku.Initialize(GraphicsDevice, Content); anim = Content.Load <VmdAnimation>("Anims/Lamb"); miku.SetAnim(anim); anim.AnimationSpeed = 0.1f; } if (currentState.IsKeyDown(Keys.V) && lastKeyState.IsKeyUp(Keys.V)) { miku = Content.Load <PmdModel>("Models/miku"); miku.Initialize(GraphicsDevice, Content); anim = Content.Load <VmdAnimation>("Anims/Lamb"); miku.SetAnim(anim); anim.AnimationSpeed = 0.1f; } if (currentState.IsKeyDown(Keys.Space) && lastKeyState.IsKeyUp(Keys.Space)) { bShowAllBone = !bShowAllBone; } if (currentState.IsKeyDown(Keys.Enter) && lastKeyState.IsKeyUp(Keys.Enter)) { g_bRotateCamera = !g_bRotateCamera; } if (currentState.IsKeyDown(Keys.P) && lastKeyState.IsKeyUp(Keys.P)) { miku.Pause = !miku.Pause; } if (currentState.IsKeyDown(Keys.I) && lastKeyState.IsKeyUp(Keys.I)) { miku.PauseBoneUpdate = !miku.PauseBoneUpdate; } //show ik bone if (currentState.IsKeyDown(Keys.K) && lastKeyState.IsKeyUp(Keys.K)) { bShowIkBone = !bShowIkBone; } if (currentState.IsKeyDown(Keys.Up) && lastKeyState.IsKeyUp(Keys.Up)) { showBoneIndex = (showBoneIndex + 1) % miku.BoneCount; } else if (currentState.IsKeyDown(Keys.Down) && lastKeyState.IsKeyUp(Keys.Down)) { showBoneIndex = (showBoneIndex - 1 + miku.BoneCount) % miku.BoneCount; } if (currentState.IsKeyDown(Keys.Left)) { showBoneIndex = (showBoneIndex + 1) % miku.BoneCount; } else if (currentState.IsKeyDown(Keys.Right)) { showBoneIndex = (showBoneIndex - 1 + miku.BoneCount) % miku.BoneCount; } Vector3 forward = Vector3.Cross(CameraUp, CameraRight); forward.Normalize(); if (currentState.IsKeyDown(Keys.W) || currentState.IsKeyDown(Keys.A) || currentState.IsKeyDown(Keys.D) || currentState.IsKeyDown(Keys.S)) { Vector3 moveMent = Vector3.Zero; if (currentState.IsKeyDown(Keys.W)) { moveMent = forward; } else if (currentState.IsKeyDown(Keys.S)) { moveMent = -forward; } if (currentState.IsKeyDown(Keys.A)) { moveMent = -CameraRight; } else if (currentState.IsKeyDown(Keys.D)) { moveMent = CameraRight; } moveMent *= 0.05f; CameraPos += moveMent; CameraTarget += moveMent; View = Matrix.CreateLookAt(CameraPos, CameraTarget, CameraUp); } if ((lastMouseState.LeftButton == ButtonState.Pressed) && (lastMouseState.X != currentMouseState.X || lastMouseState.Y != currentMouseState.Y)) { float xMove = lastMouseState.X - currentMouseState.X; float yMove = lastMouseState.Y - currentMouseState.Y; CameraTarget += 0.05f * (-xMove * CameraRight + yMove * CameraUp); forward = CameraTarget - CameraPos; forward.Normalize(); CameraRight = Vector3.Cross(forward, CameraUp); CameraRight.Normalize(); CameraUp = Vector3.Cross(CameraRight, forward); CameraUp.Normalize(); //CameraUp = new Vector3(0, 1, 0); View = Matrix.CreateLookAt(CameraPos, CameraTarget, CameraUp); } if (currentState.IsKeyDown(Keys.Escape) && lastKeyState.IsKeyUp(Keys.Escape)) { bShowMiku = !bShowMiku; } //show single chain if (currentState.IsKeyDown(Keys.F1) && lastKeyState.IsKeyUp(Keys.F1)) { bShowSingleIkChain = !bShowSingleIkChain; } if (currentState.IsKeyDown(Keys.PageDown) && lastKeyState.IsKeyUp(Keys.PageDown)) { showSingleChainIndex = (showSingleChainIndex - 1 + miku.IK_Chains.IKChainCount) % miku.IK_Chains.IKChainCount; } if (currentState.IsKeyDown(Keys.PageUp) && lastKeyState.IsKeyUp(Keys.PageUp)) { showSingleChainIndex = (showSingleChainIndex + 1) % miku.IK_Chains.IKChainCount; } lastKeyState = currentState; lastMouseState = currentMouseState; Font.DrawMessage(showBoneIndex.ToString(), 20, 20); #endregion base.Update(gameTime); }