void RandomizeFigter(Poser fighter) { int pantsIndex = Random.Range(0, pants.Length + 1); if (pantsIndex < pants.Length) { fighter.pantsSprites = pants[pantsIndex]; fighter.pantsSpriteRenderer.color = clothesColors[Random.Range(0, clothesColors.Length)]; } int topIndex = Random.Range(0, tops.Length + 1); if (topIndex < tops.Length) { fighter.shirtSprites = tops[topIndex]; fighter.shirtSpriteRenderer.color = clothesColors[Random.Range(0, clothesColors.Length)]; } int hairIndex = Random.Range(0, hair.Length + 1); if (hairIndex < hair.Length) { fighter.hairSprites = hair[hairIndex]; fighter.hairSpriteRenderer.color = hairColors[Random.Range(0, hairColors.Length)]; } fighter.manSpriteRenderer.color = skinColors[Random.Range(0, skinColors.Length)]; }
IEnumerator Record() { records = new List <Pose> (recordCount); isRecording = true; recordBeginTime = Time.time; Poser poser = currentShelf.CurrentPoser(); UpdateInfoText(INFO_TEXT_NOW_RECORDING); for (int i = 0; i < recordCount; i++) { if (isRecording == false || records == null) { recordBeginTime = 0; yield break; } records.Add(poser.GetCurrentPose()); yield return(new WaitForSeconds(recordInterval)); } isRecording = false; poser.DisconnectFromRigidbody(); poser.Highlighted = Highlightable.HighlightDegree.Pale; poser.EditEnabled = false; UpdateInfoText(INFO_TEXT_RECORDING_DONE); EnqueueCommentText(COMMENT_TEXT_RECORDING_DONE_BY_TIMER); }
IEnumerator OnSaveButtonPicked() { if (state != State.Edit) { yield break; } UpdateInfoText(INFO_TEXT_RECORDING_DONE); EnqueueCommentText(COMMENT_TEXT_RECORDING_DONE_BY_BUTTON); isRecording = false; saveEditingButton.SwellAndDisable(); cancelEditingButton.enabled = false; doneEditingButton.enabled = true; Poser poser = currentShelf.CurrentPoser(); poser.Highlighted = Highlightable.HighlightDegree.Pale; poser.EditEnabled = false; yield return(StartCoroutine(FadeOutVignette())); state = State.TypeTextInfo; yield return(StartCoroutine(FadeInTitleAuthorTextField())); }
IEnumerator OnEditButtonPicked() { if (state != State.Show) { yield break; } state = State.Edit; UpdateInfoText(INFO_TEXT_NEW_RECORDING); EnqueueCommentText(COMMENT_TEXT_ENCOURAGE_PICK_A_PART); editButton.SwellAndDisable(); cancelEditingButton.enabled = true; StartCoroutine(FadeInVignette()); yield return(new WaitForSeconds(0.5f)); Poser poser = currentShelf.CurrentPoser(); poser.EditEnabled = true; poser.Highlighted = Highlightable.HighlightDegree.Full; yield return(new WaitForSeconds(.25f)); poser.Highlighted = Highlightable.HighlightDegree.None; isWaitingFirstPick = true; pickedAnyPart = false; StartCoroutine(WaitFirstPickAndRecord()); }
IEnumerator OnCancelButtonPicked() { if (state != State.Edit) { yield break; } pickedAnyPart = false; isWaitingFirstPick = false; isRecording = false; records = null; cancelEditingButton.SwellAndDisable(); editButton.enabled = true; saveEditingButton.enabled = false; yield return(StartCoroutine(FadeOutVignette())); state = State.Show; Poser poser = currentShelf.CurrentPoser(); poser.ApplyPose(Pose.DefaultPose(), 1); poser.Highlighted = Highlightable.HighlightDegree.Pale; poser.EditEnabled = false; UpdateGalleryInfoAndComment(skipComment: true); }
public void InsertPresetBeforeLast(Preset preset) { presets.InsertBeforeLast(preset); Poser lastSlot = slots [(SlotsNum / 2) + 1]; lastSlot.ApplyPreset(presets.Get(presets.Count - 1)); }
void CreateSlots() { for (int i = 0; i < SlotsNum; i++) { Transform puppet = (Transform)Instantiate(puppetPrefab, GetSlotPosition(i), Quaternion.identity); Poser poser = puppet.gameObject.GetComponent <Poser>(); slots.Add(poser); } }
private void DoGenerate(MmdModel model, MmdMotion motion, string savePath, float frameStepLength, float timeAfterMotionFinish, float physicsStepLength) { try { _status = GenerateStatus.Preparing; if (physicsStepLength > frameStepLength) { physicsStepLength = frameStepLength; } var poser = new Poser(model); var motionPlayer = new MotionPlayer(motion, poser); var physicsReactor = new BulletPyhsicsReactor(); var totalTimeLength = motion.Length / 30.0 + timeAfterMotionFinish; var totalStepCount = (int)(totalTimeLength / frameStepLength) + 1; var playPos = 0.0; var maxSubSteps = (int)(frameStepLength / physicsStepLength) + 1; using (var fileStream = new FileStream(savePath, FileMode.Create)) { using (var bufferedStream = new BufferedStream(fileStream)) { using (var binaryWriter = new BinaryWriter(bufferedStream)) { WriteHeader(binaryWriter, model, totalStepCount + 1, frameStepLength); _status = GenerateStatus.CalculatingFrames; _totalFrames = totalStepCount + 1; _calculatedFrames = 0; physicsReactor.AddPoser(poser); motionPlayer.SeekFrame(0); poser.PrePhysicsPosing(); physicsReactor.Reset(); poser.PostPhysicsPosing(); WritePose(binaryWriter, poser); _calculatedFrames = 1; for (var i = 0; i < totalStepCount; ++i) { playPos += frameStepLength; motionPlayer.SeekTime(playPos); poser.PrePhysicsPosing(); physicsReactor.React(frameStepLength, maxSubSteps, physicsStepLength); poser.PostPhysicsPosing(); WritePose(binaryWriter, poser); _calculatedFrames = i + 2; } } } } _status = GenerateStatus.Finished; } catch (Exception e) { _status = GenerateStatus.Failed; Debug.LogException(e); } }
private static void WritePose(BinaryWriter writer, Poser poser) { var bonePoseImages = BonePosePreCalculator.GetBonePoseImage(poser); foreach (var bonePose in bonePoseImages) { WriteVector3(writer, bonePose.Position); WriteVector3(writer, bonePose.Rotation.eulerAngles); } }
public ActorBehavior(ControllerManager controllerManager, ActorModel model, InverterParameters inverterParameters) { this.model = model; poser = new Poser(model.MainDefinition); ikAnimator = new InverseKinematicsAnimator(controllerManager, model.MainDefinition, inverterParameters); proceduralAnimator = new StandardProceduralAnimator(model.MainDefinition, model.Behavior); dragHandle = new DragHandle(controllerManager, InitialSettings.InitialTransform); model.PoseReset += ikAnimator.Reset; }
void ApplyPresetsToSlots() { for (int i = 0; i < SlotsNum; i++) { Poser poser = slots[i]; int indexRelativeToDataSource = i - (SlotsNum / 2) + index; Preset preset = presets.Get(indexRelativeToDataSource); poser.ApplyPreset(preset); } }
public PoserMotionState(Poser poser, MmdRigidBody body, Matrix bodyTransform) { _poser = poser; _passive = body.Type == MmdRigidBody.RigidBodyType.RigidTypeKinematic; _strict = body.Type == MmdRigidBody.RigidBodyType.RigidTypePhysicsStrict; _ghost = body.Type == MmdRigidBody.RigidBodyType.RigidTypePhysicsGhost; _target = GetPoserBoneImage(poser, body.AssociatedBoneIndex); _bodyTransform = bodyTransform; _bodyTransformInv = Matrix.Invert(bodyTransform); Reset(); }
private void DoLoadModel(string filePath) { Debug.LogFormat("start load model {0}", filePath); _model = ModelReader.LoadMmdModel(filePath, _modelReadConfig); Release(); var directoryInfo = new FileInfo(filePath).Directory; if (directoryInfo == null) { throw new MmdFileParseException(filePath + " does not belong to any directory."); } var relativePath = directoryInfo.FullName; _materialLoader = new MaterialLoader(new TextureLoader(relativePath, DefaultMaxTextureSize)); var vertCount = _model.Vertices.Length; if (vertCount <= 65535) { var mesh = new Mesh { vertices = new Vector3[vertCount], normals = new Vector3[vertCount] }; var triangleCount = _model.TriangleIndexes.Length / 3; var triangles = _model.TriangleIndexes; FillSubMesh(mesh, triangleCount, triangles); var uv = ExtratUv(_model.Vertices); var uvVec = new Vector2[vertCount]; Utils.MmdUvToUnityUv(uv, uvVec); mesh.uv = uvVec; mesh.boneWeights = _model.Vertices.Select(x => ConvertBoneWeight(x.SkinningOperator)).ToArray(); ReleasePreviousMeshes(); Mesh = mesh; mesh.RecalculateBounds(); _partIndexes = null; } else { var triangleCount = _model.TriangleIndexes.Length / 3; var triangles = _model.TriangleIndexes; var uv = ExtratUv(_model.Vertices); ; var uvVec = new Vector2[vertCount]; Utils.MmdUvToUnityUv(uv, uvVec); FillPartMeshes(triangleCount, triangles, uv); } _poser = new Poser(_model); _physicsReactor = new BulletPyhsicsReactor(); _physicsReactor.AddPoser(_poser); InitMesh(); Debug.LogFormat("load model finished {0}", filePath); }
void BeginPlayCenterSlotIfAnimated() { Preset centerPreset = currentShelf.CurrentPreset(); if (centerPreset.Type == Preset.PresetType.Animated) { Poser centerPoser = currentShelf.CurrentPoser(); List <Pose> motion = centerPreset.Motion; StartCoroutine(centerPoser.BeginMotion(motion, recordInterval / PLAYBACK_SPEED)); isPlaying = true; playBeginTime = Time.time; } }
void OnDoneButtonPicked() { if (state != State.TypeTextInfo) { return; } state = State.Show; if (displayingTitle.Equals(TITLE_PLACEHOLDER)) { displayingTitle = "무제"; } if (displayingAuthor.Equals(AUTHOR_PLACEHOLDER)) { displayingAuthor = "익명"; } titleStyle.normal.background = null; authorStyle.normal.background = null; doneEditingButton.SwellAndDisable(); Poser poser = currentShelf.CurrentPoser(); poser.EditEnabled = true; poser.Highlighted = Highlightable.HighlightDegree.None; poser.EditEnabled = false; Preset lastPreset = currentShelf.LastPreset(); int fileIndexToSave = 0; if (lastPreset != null) { fileIndexToSave = lastPreset.FileIndex + 1; } List <Pose> motion = records; records = null; Preset preset = new Preset(motion, displayingTitle, displayingAuthor, fileIndexToSave); currentShelf.InsertPresetBeforeLast(preset); BeginPlayCenterSlotIfAnimated(); UpdateGalleryInfoAndComment(skipComment: true); StartCoroutine(SavePresetAsFile(preset, fileIndexToSave)); audio.PlayOneShot(audioSaveSuccess); }
private static void SeedFavoritesJson(string outputDirectory) { var poser = new Poser("Favorites", String.Empty); poser.AddPack(new PoserPack("Favorites")); var outputFile = outputDirectory + Resources.FavoritesJsonName; // only write if a favorites file is not present if (!File.Exists(outputFile)) { Program.Log.Write("Creating new " + outputFile); File.WriteAllText(outputFile, poser.ToPapyrusUtilJson()); } }
private void SetPoseToPoser(MmdPose pose, Poser poser) { var nameToIndex = BuildBoneNameToIndexDictionary(poser.Model); foreach (var entry in pose.BonePoses) { var name = entry.Key; var bonePose = entry.Value; int index; if (!nameToIndex.TryGetValue(name, out index)) { continue; } poser.SetBonePose(index, bonePose); } }
public BonePosePreCalculator(MmdPose pose, Poser poser, BulletPyhsicsReactor physicsReactor, double stepLength, double startTimePos, int frameCacheSize, bool autoStepLength) { _poseMode = true; _poser = poser; _physicsReactor = physicsReactor; _stepLength = stepLength; _bonePoseImagesStore = new BlockingQueue <BonePoseFrame>(frameCacheSize); _timePos = startTimePos; _autoStepLength = autoStepLength; poser.ResetPosing(); SetPoseToPoser(pose, _poser); _poser.PrePhysicsPosing(); _physicsReactor.Reset(); _poser.PostPhysicsPosing(); var image = GetBonePoseImage(_poser); _bonePoseImagesStore.Enqueue(new BonePoseFrame(startTimePos, image)); }
public BonePosePreCalculator(Poser poser, BulletPyhsicsReactor physicsReactor, MotionPlayer motionPlayer, double stepLength, double startTimePos, int frameCacheSize, bool autoStepLength) { _poseMode = false; _poser = poser; _physicsReactor = physicsReactor; _motionPlayer = motionPlayer; _stepLength = stepLength; _bonePoseImagesStore = new BlockingQueue <BonePoseFrame>(frameCacheSize); _timePos = startTimePos; _autoStepLength = autoStepLength; _motionPlayer.SeekTime(startTimePos); _poser.PrePhysicsPosing(); _physicsReactor.Reset(); _poser.PostPhysicsPosing(); var image = GetBonePoseImage(_poser); _bonePoseImagesStore.Enqueue(new BonePoseFrame(startTimePos, image)); }
public BonePosePreCalculator(BonePoseCalculatorWorker worker, MmdPose pose, Poser poser, BulletPyhsicsReactor physicsReactor, float stepLength, float startTimePos, int frameCacheSize, bool autoStepLength) { _poseMode = true; _poser = poser; _physicsReactor = physicsReactor; _stepLength = stepLength; _bonePoseImagesStore = new SynchronizedQueue <BonePoseFrame>(); _timePos = startTimePos; _autoStepLength = autoStepLength; _frameCacheSize = frameCacheSize; poser.ResetPosing(); SetPoseToPoser(pose, _poser); _poser.PrePhysicsPosing(); _physicsReactor.Reset(); _poser.PostPhysicsPosing(); var image = GetBonePoseImage(_poser); _bonePoseImagesStore.Enqueue(new BonePoseFrame(startTimePos, image)); _worker = worker; }
public static BonePoseImage[] GetBonePoseImage(Poser poser) { var boneCount = poser.BoneImages.Length; var ret = new BonePoseImage[boneCount]; var model = poser.Model; var poserBoneImages = poser.BoneImages; for (var i = 0; i < boneCount; ++i) { var poserBoneImage = poserBoneImages[i]; var position = poserBoneImage.SkinningMatrix.MultiplyPoint3x4(model.Bones[i].Position); var rotation = poserBoneImage.SkinningMatrix.ExtractRotation(); ret[i] = new BonePoseImage { Position = position, Rotation = rotation }; } return(ret); }
void Start() { // Find some components. ik = GetComponent <FullBodyBipedIK>(); poserLeftHand = ik.references.leftHand.GetComponent <Poser>(); poserRightHand = ik.references.rightHand.GetComponent <Poser>(); ik.solver.OnPostUpdate += AfterFBBIK; lastWeight = weight; SetHandedness(handedness); // Remember some default positions defaultWeaponsAnchorLocalPosition = weaponsAnchor.localPosition; weaponsPivotLocalPosition = weaponsPivot.localPosition; pivotRelativePosition = pivotMotionTarget.InverseTransformPoint(weaponsPivot.position); cameraPosition = TargetsCameraPosition(); lastCharacterPosition = characterController.position; }
public override void RemovePoser(Poser poser) { if (!_rigidBodies.ContainsKey(poser)) { return; } var constraints = _constraints[poser]; var rigidBodies = _rigidBodies[poser]; foreach (var constraint in constraints) { _world.RemoveConstraint(constraint); } foreach (var rigidBody in rigidBodies) { _world.RemoveRigidBody(rigidBody); } _constraints.Remove(poser); _rigidBodies.Remove(poser); _motionStates.Remove(poser); }
private void FavoritesToFnisListToolStripMenuItemClick(object sender, EventArgs e) { // warn to scare curious users var dialogResult = MessageBox.Show( Resources.CommonString_ScareMessage, Resources.CommonString_Warning, MessageBoxButtons.YesNo); if (dialogResult == DialogResult.No) { return; } // start logging Program.Log.Write("\nGenerate FNIS List from Favorites: " + DateTime.Now.ToString("u")); // locate favorites var favoritesJsonFilePath = this.skyrimDirectory + Resources.PoserHotkeysDataPath + Resources.FavoritesJsonName; if (!File.Exists(favoritesJsonFilePath)) { var errorMessage = "Unable to locate favorites at " + favoritesJsonFilePath; MessageBox.Show(errorMessage, Resources.CommonString_Error, MessageBoxButtons.OK); Program.Log.Write(errorMessage); return; } // deserialize favorites var favoritesJsonData = File.ReadAllText(favoritesJsonFilePath); var favorites = JsonUtilFavorites.Deserialize(favoritesJsonData); // setup output paths var fnisOutputDirectory = this.skyrimDirectory + Resources.AnimationsDataPath + "PoserHotkeys\\"; var fnisOutputFilePath = fnisOutputDirectory + "FNIS_PoserHotkeys_List.txt"; var jsonOutputDirectory = this.skyrimDirectory + Resources.PoserHotkeysDataPath; // ensure output directory exists if (!Directory.Exists(fnisOutputDirectory)) { Program.Log.Write("Creating directory: " + fnisOutputDirectory); Directory.CreateDirectory(fnisOutputDirectory); } // generate data var fnisLines = new ConcurrentBag<string>(); using (var pleaseWaitMessage = new FormPleaseWaitMessage()) { pleaseWaitMessage.Show(this); pleaseWaitMessage.Update(); try { // read fnis animation defintions var availablePosers = this.checkedListBoxPosers.Items.OfType<Poser>(); var posersList = availablePosers as IList<Poser> ?? availablePosers.ToList(); Parallel.ForEach( posersList, poser => { poser.PopulateAnimationEventDictionary(); }); Program.Log.Write("FNIS AnimationEvent dictionaries populated."); Program.Log.Write("Attempting to match " + favorites.stringList.favorites.Count + " favorites."); // compile line matches Parallel.ForEach( favorites.stringList.favorites, favorite => { Parallel.ForEach( this.posers, poser => { if (poser.FnisLines.ContainsKey(favorite)) { fnisLines.Add(poser.FnisLines[favorite]); } }); }); Program.Log.Write("Successfully matched " + fnisLines.Count + " favorites."); // write results to file Program.Log.Write("Overwritting " + fnisOutputFilePath); File.WriteAllLines(fnisOutputFilePath, fnisLines); // generate json for favorites var favoritesPoser = new Poser(Resources.FavoritesPoserName, fnisOutputDirectory); favoritesPoser.PopulatePacks(false); WriteJson(new List<Poser> { favoritesPoser }, jsonOutputDirectory); } catch (Exception exception) { Program.Log.Write("Fatal Error: " + exception.Message); throw; } pleaseWaitMessage.Close(); } // show summary var summaryMessage = String.Format( $"Generated {fnisLines.Count} animation events." + $"\n\nWrote FNIS data to:\n{fnisOutputFilePath}" + $"\n\nWrote json data to:\n{jsonOutputDirectory + Resources.FavoritesPoserName}.json" + "\n\nYou may now run FNIS Generator for Modders."); MessageBox.Show(summaryMessage, Resources.CommonString_Summary, MessageBoxButtons.OK); this.buttonQuit.Select(); }
public bool Flip(bool toLeft = true, float speedMultiplier = 1) { int desiredIndex = (toLeft? index + 1 : index - 1); if (0 > desiredIndex || desiredIndex >= presets.Count) { return(false); } Poser currentPoser = CurrentPoser(); Preset currentPreset = CurrentPreset(); if (currentPreset.Pose != null) { currentPoser.StopMotion(); currentPoser.ApplyPose(currentPreset.Pose, FLIP_DURATION / speedMultiplier / 2); } index = desiredIndex; int tweenSlotBeginIndex = 0; int tweenSlotEndIndex = 0; int lastSlotIndex = SlotsNum - 1; if (toLeft) { tweenSlotBeginIndex = 1; tweenSlotEndIndex = lastSlotIndex; } else { tweenSlotBeginIndex = 0; tweenSlotEndIndex = lastSlotIndex - 1; } for (int i = tweenSlotBeginIndex; i <= tweenSlotEndIndex; i++) { int newIndex = i + (toLeft? -1 : +1); Vector3 newPosition = GetSlotPosition(newIndex); LTDescr tween = LeanTween.moveLocal(slots[i].gameObject, newPosition, FLIP_DURATION / speedMultiplier).setEase(LeanTweenType.easeInOutCubic); if (i == CenterSlot) { tween.setOnComplete(OnCenterSlotFlipComplete); } } int poppingSlotIndex = (toLeft? 0 : lastSlotIndex); Poser reusedSlot = slots[poppingSlotIndex]; slots.RemoveAt(poppingSlotIndex); int halfSlotsNum = SlotsNum / 2; int endPointPresetIndex = index + (toLeft? halfSlotsNum : -halfSlotsNum); reusedSlot.ApplyPreset(presets.Get(endPointPresetIndex)); int pushingSlotIndex = (toLeft? lastSlotIndex : 0); slots.Insert(pushingSlotIndex, reusedSlot); reusedSlot.transform.localPosition = GetSlotPosition(pushingSlotIndex); return(true); }
public override void AddPoser(Poser poser) { var model = poser.Model; if (_rigidBodies.ContainsKey(poser)) { return; } poser.ResetPosing(); var motionStates = new List <PoserMotionState>(); _motionStates.Add(poser, motionStates); var rigidBodies = new List <RigidBody>(); _rigidBodies.Add(poser, rigidBodies); var constraints = new List <Generic6DofSpringConstraint>(); _constraints.Add(poser, constraints); foreach (var body in model.Rigidbodies) { var bodyDimension = body.Dimemsions; CollisionShape btShape = null; var btMass = 0.0f; var btLocalInertia = new Vector3(0.0f, 0.0f, 0.0f); switch (body.Shape) { case MmdRigidBody.RigidBodyShape.RigidShapeSphere: btShape = new SphereShape(bodyDimension.x); break; case MmdRigidBody.RigidBodyShape.RigidShapeBox: btShape = new BoxShape(new Vector3(bodyDimension.x, bodyDimension.y, bodyDimension.z)); break; case MmdRigidBody.RigidBodyShape.RigidShapeCapsule: btShape = new CapsuleShape(bodyDimension.x, bodyDimension.y); break; default: throw new ArgumentOutOfRangeException(); } if (body.Type != MmdRigidBody.RigidBodyType.RigidTypeKinematic) { btMass = body.Mass; btShape.CalculateLocalInertia(btMass, out btLocalInertia); } var bodyTransform = MathUtil.QuaternionToMatrix4X4(MathUtil.YxzToQuaternion(body.Rotation)); MathUtil.SetTransToMatrix4X4(body.Position, ref bodyTransform); var btBodyTransform = new Matrix(); MathUtil.UnityMatrixToBulletMatrix(bodyTransform, ref btBodyTransform); var btMotionState = new PoserMotionState(poser, body, btBodyTransform); var btInfo = new RigidBodyConstructionInfo(btMass, btMotionState, btShape, btLocalInertia) { LinearDamping = body.TranslateDamp, AngularDamping = body.RotateDamp, Restitution = body.Restitution, Friction = body.Friction }; var btRigidBody = new RigidBody(btInfo) { ActivationState = ActivationState.DisableDeactivation }; if (body.Type == MmdRigidBody.RigidBodyType.RigidTypeKinematic) { btRigidBody.CollisionFlags = btRigidBody.CollisionFlags | CollisionFlags.KinematicObject; } _world.AddRigidBody(btRigidBody, (short)(1 << body.CollisionGroup), (short)body.CollisionMask); #if MMD_PHYSICS_DEBUG CreateUnityCollisionObjectProxy(btRigidBody, body.Name); #endif motionStates.Add(btMotionState); rigidBodies.Add(btRigidBody); } foreach (var constraint in model.Constraints) { var btBody1 = rigidBodies[constraint.AssociatedRigidBodyIndex[0]]; var btBody2 = rigidBodies[constraint.AssociatedRigidBodyIndex[1]]; var positionLowLimit = constraint.PositionLowLimit; var positionHiLimit = constraint.PositionHiLimit; var rotationLoLimit = constraint.RotationLowLimit; var rotationHiLimit = constraint.RotationHiLimit; var constraintTransform = MathUtil.QuaternionToMatrix4X4(MathUtil.YxzToQuaternion(constraint.Rotation)); MathUtil.SetTransToMatrix4X4(constraint.Position, ref constraintTransform); var btConstraintTransform = new Matrix(); MathUtil.UnityMatrixToBulletMatrix(constraintTransform, ref btConstraintTransform); var btLocalizationTransform1 = btConstraintTransform * Matrix.Invert(btBody1.WorldTransform); //TODO 验证这个和mmdlib里算出来的是否一样 var btLocalizationTransform2 = btConstraintTransform * Matrix.Invert(btBody2.WorldTransform); var btConstraint = new Generic6DofSpringConstraint(btBody1, btBody2, btLocalizationTransform1, btLocalizationTransform2, true) { LinearLowerLimit = new Vector3(positionLowLimit.x, positionLowLimit.y, positionLowLimit.z), LinearUpperLimit = new Vector3(positionHiLimit.x, positionHiLimit.y, positionHiLimit.z), AngularLowerLimit = new Vector3(rotationLoLimit.x, rotationLoLimit.y, rotationLoLimit.z), AngularUpperLimit = new Vector3(rotationHiLimit.x, rotationHiLimit.y, rotationHiLimit.z) }; for (var j = 0; j < 3; ++j) { btConstraint.SetStiffness(j, constraint.SpringTranslate[j]); btConstraint.EnableSpring(j, true); btConstraint.SetStiffness(j + 3, constraint.SpringRotate[j]); btConstraint.EnableSpring(j + 3, true); } _world.AddConstraint(btConstraint); constraints.Add(btConstraint); } }
public static BoneImage GetPoserBoneImage(Poser poser, int index) { return(index >= poser.BoneImages.Length ? NullBoneImage : poser.BoneImages[index]); }