public Quaternion GetLastRotationForChannel(string channelName) { Quaternion previousRotation = Quaternion.identity; if (this.previousClip != null) { IAnimationChannel previousChannel = this.previousClip.GetAnimationChannel(channelName); if (previousChannel != null && previousChannel is RotationChannel) { RotationChannel previousRotationChannel = previousChannel as RotationChannel; previousRotation = previousRotationChannel.GetPreviousRotation(); } } else { //If we dont have a previous clip to extract a rotation from we use the initial transform for this channel. if (this.animationTransforms.ContainsKey(channelName)) { BoneTransform boneTransform = this.animationTransforms[channelName] as BoneTransform; previousRotation = boneTransform.GetInitialRotation(); } } return(previousRotation); }
void Start() { var rigged = Node.GetComponent <Animator>(); if (rigged) { head = rigged.BoneController.GetBone("頭"); head.FollowAnimation = false; } //create head ray collision object headBox = new SphereShape(0.35f); var rbInfo = new RigidBodyConstructionInfo(0, new DefaultMotionState(Matrix4.Identity.Convert()), headBox, BulletSharp.Math.Vector3.Zero); headBody = new RigidBody(rbInfo); CoreEngine.pEngine.World.AddRigidBody(headBody, (int)CollisionFilleters.Look, (int)CollisionFilleters.Look); //headBody.CollisionFlags |= CollisionFlags.KinematicObject; headBody.UserObject = new Action <SceneNode>(triggerSwitch); headBody.UserIndex = 1; targetAngle = new Vector2(thetaDef, phiDef); angle = targetAngle; angSpeed = Vector2.Zero; audio = Node.AddComponent <AudioSource>(); PrepareExpressions(rigged); PrepareSpeech(); }
void CreateBaseChannels() { this.baseChannels = new List <IAnimationChannel>(); for (int i = 0; i < this.transformLookup.Count; i++) { TransformBase transform = this.transformLookup[i]; if (transform is MorphTransform) { //A small list of keyframes, used to sample values. List <float> keys = new List <float>(5) { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; MorphChannel morphChannel = new MorphChannel(transform.GetName(), keys, false, false, false, false, FRAMERATE); this.baseChannels.Add(morphChannel); } else if (transform is BoneTransform) { BoneTransform boneTransform = transform as BoneTransform; //Sample initial rotation value. Vector3 angle = boneTransform.GetInitialRotation().eulerAngles; List <Vector3> keys = new List <Vector3>(5) { angle, angle, angle, angle, angle }; RotationChannel rotationChannel = new RotationChannel(boneTransform.GetName(), keys, false, false, false, false, FRAMERATE); this.baseChannels.Add(rotationChannel); } } }
private void LoadPoseOld(List <string> lines) { Armature armature = selectedItem.Model.Armature; DataSet dataSet = dataSetDict[selectedItem]; if (lines.Count != armature.Bones.Length) { MessageBox.Show(this, "Incompatible armatures (bones do not match).", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } int boneID = 0; foreach (string line in lines) { string[] tokens = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length == 3) { BoneTransform boneTransform = dataSet.boneTransforms[boneID]; boneTransform.rotX = int.Parse(tokens[0]); boneTransform.rotY = int.Parse(tokens[1]); boneTransform.rotZ = int.Parse(tokens[2]); boneTransform.moveX = 0; boneTransform.moveY = 0; boneTransform.moveZ = 0; } boneID++; } foreach (Armature.Bone bone in armature.Bones) { BoneTransform boneRotation = dataSet.boneTransforms[bone.id]; ApplyTransformToBone(bone, boneRotation); } }
void FindBoneTransforms() { string[] optionalBones = { "Mid_Head_Jnt_03", "L_LowEyelid_Jnt_00", "R_LowEyelid_Jnt_00", "L_UpEyelid_Jnt_00", "R_UpEyelid_Jnt_00", "L_Eyeball_Jnt_00", "R_Eyeball_Jnt_00" }; Dictionary <string, Transform> mappedTransforms = new Dictionary <string, Transform>(); TransformHelp.FindChildrenRecursive(this.transform, optionalBones, mappedTransforms); //Avoid using enumerators when iterating foreach (KeyValuePair <string, Transform> pair in mappedTransforms) { BoneTransform boneTransform = new BoneTransform(pair.Key, pair.Value, pair.Value.localRotation); if (!this.animationTransforms.ContainsKey(pair.Key)) { this.animationTransforms.Add(pair.Key, boneTransform); } } }
private void LoadPoseNew(List <string> lines) { Armature armature = selectedItem.Model.Armature; Dictionary <string, BoneTransform> boneTransforms = new Dictionary <string, BoneTransform>(); foreach (string line in lines) { string[] tokens1 = line.Split(':'); if (tokens1.Length == 2) { string boneName = tokens1[0].Trim(); Armature.Bone bone = armature.GetBone(boneName); if (bone != null) { string[] tokens2 = tokens1[1].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (tokens2.Length == 3 || tokens2.Length == 6) { BoneTransform boneTransform = new BoneTransform(); boneTransform.rotX = float.Parse(tokens2[0]); boneTransform.rotY = float.Parse(tokens2[1]); boneTransform.rotZ = float.Parse(tokens2[2]); if (tokens2.Length == 6) { boneTransform.moveX = float.Parse(tokens2[3]); boneTransform.moveY = float.Parse(tokens2[4]); boneTransform.moveZ = float.Parse(tokens2[5]); } else { boneTransform.moveX = 0; boneTransform.moveY = 0; boneTransform.moveZ = 0; } boneTransforms[boneName] = boneTransform; } } } } ICollection <string> boneNames = boneTransforms.Keys; PoseFilterDialog dialog = new PoseFilterDialog(game, "Load pose", "Select bones to load:", boneNames, true); if (dialog.ShowDialog(this) != DialogResult.OK) { return; } DataSet dataSet = dataSetDict[selectedItem]; foreach (string boneName in boneNames) { if (dialog.IsBoneSelected(boneName)) { Armature.Bone bone = armature.GetBone(boneName); BoneTransform boneTransform = boneTransforms[boneName]; dataSet.boneTransforms[bone.id] = boneTransform; ApplyTransformToBone(bone, boneTransform); } } }
/// <summary> /// Prepare references /// </summary> void InitialSetup() { eyesBone = anim.BoneController.GetBone("両目"); eyesBone.FollowAnimation = false; morphes = mesh.Morphes; EyeLocationX = 0; EyeLocationY = 0; DefaultExpression = new NPCExpression("Def"); }
public static void DrawAvatarBone(BoneTransform bone, Vector3 direction) { if (bone.transform == null) { return; } Debug.DrawRay(bone.transform.position, bone.targetRotation * direction * bone.length, Color.cyan); }
public static void Main() { const int N = 10000; const long SecondInTicks = 10000000; var vertices = new Vertex[N]; var influences = new Influence[N]; for (int i = 0; i < N; i++) { vertices[i] = new Vertex { Position = new CalVector4(1, 2, 3), Normal = new CalVector4(0, 0, 1) }; influences[i] = new Influence { BoneId = 0, Weight = 1.0f, LastInfluenceForThisVertex = true }; } var boneTransforms = new BoneTransform[] { new BoneTransform() }; var output = new CalVector4[N * 2]; for (int i = 0; i < 100; i++) { long verticesSkinned = 0; long started = DateTime.UtcNow.Ticks; while (DateTime.UtcNow.Ticks < (started + SecondInTicks)) { CalculateVerticesAndNormals( boneTransforms, N, vertices, influences, output ); verticesSkinned += N; } long elapsed = DateTime.UtcNow.Ticks - started; Console.WriteLine( "Skinned vertices per second: {0}", (verticesSkinned * SecondInTicks) / elapsed ); } }
public void PopulateChildren() { if (!RootNode) { return; } _preRootNode = RootNode; _childNodes = RootNode.GetComponentsInChildren <Transform>(); _previousTransforms = new BoneTransform[_childNodes.Length]; for (var i = 0; i < _childNodes.Length; i++) { var childNode = _childNodes[i]; _previousTransforms[i] = new BoneTransform(childNode, childNode.localPosition); } }
public void AddScaled(ref BoneTransform mutate, float s) { mutate.RowX.X += RowX.X * s; mutate.RowX.Y += RowX.Y * s; mutate.RowX.Z += RowX.Z * s; mutate.RowX.W += RowX.W * s; mutate.RowY.X += RowY.X * s; mutate.RowY.Y += RowY.Y * s; mutate.RowY.Z += RowY.Z * s; mutate.RowY.W += RowY.W * s; mutate.RowZ.X += RowZ.X * s; mutate.RowZ.Y += RowZ.Y * s; mutate.RowZ.Z += RowZ.Z * s; mutate.RowZ.W += RowZ.W * s; }
public void Scale(out BoneTransform result, float s) { result.RowX.X = RowX.X * s; result.RowX.Y = RowX.Y * s; result.RowX.Z = RowX.Z * s; result.RowX.W = RowX.W * s; result.RowY.X = RowY.X * s; result.RowY.Y = RowY.Y * s; result.RowY.Z = RowY.Z * s; result.RowY.W = RowY.W * s; result.RowZ.X = RowZ.X * s; result.RowZ.Y = RowZ.Y * s; result.RowZ.Z = RowZ.Z * s; result.RowZ.W = RowZ.W * s; }
public void ReadFromFile(MemoryStream reader, bool isBigEndian) { int numBones = reader.ReadInt32(isBigEndian); byte numLods = reader.ReadByte8(); //index infos boneIndexInfos = new BoneIndexInfo[numLods]; for (int i = 0; i != boneIndexInfos.Length; i++) { boneIndexInfos[i].NumIDs = reader.ReadInt32(isBigEndian); boneIndexInfos[i].NumMaterials = reader.ReadInt32(isBigEndian); } //bounds for all bones together? bounds = BoundingBoxExtenders.ReadFromFile(reader, isBigEndian); //Bone Transforms boneTransforms = new BoneTransform[numBones]; for (int i = 0; i != boneTransforms.Length; i++) { boneTransforms[i] = new BoneTransform(); boneTransforms[i].ReadFromFile(reader, isBigEndian); } for (int i = 0; i != boneIndexInfos.Length; i++) { boneIndexInfos[i].BonesPerPool = reader.ReadBytes(8); //IDs.. boneIndexInfos[i].IDs = reader.ReadBytes(boneIndexInfos[i].NumIDs); //Material blendings.. boneIndexInfos[i].MatBlends = new ushort[boneIndexInfos[i].NumMaterials]; boneIndexInfos[i].BonesSlot = new byte[boneIndexInfos[i].NumMaterials]; boneIndexInfos[i].NumWeightsPerVertex = new int[boneIndexInfos[i].NumMaterials]; for (int x = 0; x != boneIndexInfos[i].NumMaterials; x++) { boneIndexInfos[i].MatBlends[x] = reader.ReadUInt16(isBigEndian); ushort value = boneIndexInfos[i].MatBlends[x]; boneIndexInfos[i].BonesSlot[x] = (byte)(value & 0xFF); boneIndexInfos[i].NumWeightsPerVertex[x] = (value >> 8); } } }
private void SavePose(string filename) { Armature armature = selectedItem.Model.Armature; List <string> boneNames = new List <string>(); foreach (Armature.Bone bone in armature.Bones) { if (!bone.name.StartsWith("unused")) { boneNames.Add(bone.name); } } PoseFilterDialog dialog = new PoseFilterDialog(game, "Save pose", "Select bones to save:", boneNames, true); if (dialog.ShowDialog(this) != DialogResult.OK) { return; } try { DataSet dataSet = dataSetDict[selectedItem]; StreamWriter file = new StreamWriter(filename); foreach (Armature.Bone bone in armature.Bones) { if (!dialog.IsBoneSelected(bone.name)) { continue; } BoneTransform boneTransform = dataSet.boneTransforms[bone.id]; file.WriteLine("{0}: {1} {2} {3} {4} {5} {6}", bone.name, boneTransform.rotX, boneTransform.rotY, boneTransform.rotZ, boneTransform.moveX, boneTransform.moveY, boneTransform.moveZ); } file.Close(); } catch (Exception ex) { MessageBox.Show(this, "Could not save the pose file.\n" + ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } }
private void MirrorPose() { if (selectedItem == null) { return; } Armature armature = selectedItem.Model.Armature; List <string> labels = new List <string>(); foreach (Armature.Bone bone in armature.Bones) { int origSide; string mirroredName = GetMirroredBoneName(bone.name, out origSide); if (mirroredName != null && origSide < 0 && armature.GetBone(mirroredName) != null) { labels.Add("L: " + bone.name); } } foreach (Armature.Bone bone in armature.Bones) { int origSide; string mirroredName = GetMirroredBoneName(bone.name, out origSide); if (mirroredName != null && origSide > 0 && armature.GetBone(mirroredName) != null) { labels.Add("R: " + bone.name); } } PoseFilterDialog dialog = new PoseFilterDialog(game, "Mirror (copy) pose left/right", "Select bones to mirror pose from:", labels, false); if (dialog.ShowDialog(this) != DialogResult.OK) { return; } DataSet dataSet = dataSetDict[selectedItem]; foreach (string label in labels) { if (!dialog.IsBoneSelected(label)) { continue; } string boneNameFrom = label.Substring(3); Armature.Bone boneFrom = armature.GetBone(boneNameFrom); BoneTransform boneTransformFrom = dataSet.boneTransforms[boneFrom.id]; string boneNameTo = GetMirroredBoneName(boneNameFrom); Armature.Bone boneTo = armature.GetBone(boneNameTo); BoneTransform boneTransformTo = dataSet.boneTransforms[boneTo.id]; boneTransformTo.moveX = -boneTransformFrom.moveX; boneTransformTo.moveY = +boneTransformFrom.moveY; boneTransformTo.moveZ = +boneTransformFrom.moveZ; boneTransformTo.rotX = +boneTransformFrom.rotX; boneTransformTo.rotY = -boneTransformFrom.rotY; boneTransformTo.rotZ = -boneTransformFrom.rotZ; ApplyTransformToBone(boneTo, boneTransformTo); } }
private void FlipPose() { if (selectedItem == null) { return; } Armature armature = selectedItem.Model.Armature; List <string> labels = new List <string>(); Dictionary <string, string> labelsToBoneNames = new Dictionary <string, string>(); foreach (Armature.Bone bone in armature.Bones) { int origSide; string flippedName = GetFlippedBoneName(bone.name, out origSide); if (flippedName != null && origSide < 0 && armature.GetBone(flippedName) != null) { string combinedName = GetCombinedBoneName(bone.name); labels.Add(combinedName); labelsToBoneNames[combinedName] = bone.name; } } PoseFilterDialog dialog = new PoseFilterDialog(game, "Flip (swap) pose left/right", "Select bone pairs whose pose to flip:", labels, false); if (dialog.ShowDialog(this) != DialogResult.OK) { return; } DataSet dataSet = dataSetDict[selectedItem]; foreach (string label in labels) { if (!dialog.IsBoneSelected(label)) { continue; } string boneName1 = labelsToBoneNames[label]; Armature.Bone bone1 = armature.GetBone(boneName1); BoneTransform boneTransform1 = dataSet.boneTransforms[bone1.id]; string boneName2 = GetFlippedBoneName(boneName1); Armature.Bone bone2 = armature.GetBone(boneName2); BoneTransform boneTransform2 = dataSet.boneTransforms[bone2.id]; float moveX1 = boneTransform1.moveX; float moveY1 = boneTransform1.moveY; float moveZ1 = boneTransform1.moveZ; float rotX1 = boneTransform1.rotX; float rotY1 = boneTransform1.rotY; float rotZ1 = boneTransform1.rotZ; float moveX2 = boneTransform2.moveX; float moveY2 = boneTransform2.moveY; float moveZ2 = boneTransform2.moveZ; float rotX2 = boneTransform2.rotX; float rotY2 = boneTransform2.rotY; float rotZ2 = boneTransform2.rotZ; boneTransform2.moveX = -moveX1; boneTransform2.moveY = +moveY1; boneTransform2.moveZ = +moveZ1; boneTransform2.rotX = +rotX1; boneTransform2.rotY = -rotY1; boneTransform2.rotZ = -rotZ1; boneTransform1.moveX = -moveX2; boneTransform1.moveY = +moveY2; boneTransform1.moveZ = +moveZ2; boneTransform1.rotX = +rotX2; boneTransform1.rotY = -rotY2; boneTransform1.rotZ = -rotZ2; ApplyTransformToBone(bone1, boneTransform1); ApplyTransformToBone(bone2, boneTransform2); } }
private void SaveScene(string filename) { BinaryWriter file; try { file = new BinaryWriter(new FileStream(filename, FileMode.Create)); } catch (Exception) { MessageBox.Show(this, "Could not save scene.", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // file format version file.Write((ushort)1); // major file.Write((ushort)11); // minor // items file.Write(items.Count); foreach (Item item in items) { // type file.Write(item.Type.ToString()); // directory name file.Write(item.DirName); // visibility file.Write(item.Model.IsVisible); // scale file.Write(item.Model.Armature.WorldScale.X); file.Write(item.Model.Armature.WorldScale.Y); file.Write(item.Model.Armature.WorldScale.Z); // pose Armature armature = item.Model.Armature; DataSet dataSet = dataSetDict[item]; foreach (Armature.Bone bone in armature.Bones) { BoneTransform boneTransform = dataSet.boneTransforms[bone.id]; file.Write(boneTransform.rotX); file.Write(boneTransform.rotY); file.Write(boneTransform.rotZ); file.Write(boneTransform.moveX); file.Write(boneTransform.moveY); file.Write(boneTransform.moveZ); } // position Vector3 position = armature.WorldTranslation; file.Write(position.X); file.Write(position.Y); file.Write(position.Z); // accessories ExportModelParams(file, item.Model); // glow colors file.Write(item.ColorGlowLeft.X); file.Write(item.ColorGlowLeft.Y); file.Write(item.ColorGlowLeft.Z); file.Write(item.ColorGlowRight.X); file.Write(item.ColorGlowRight.Y); file.Write(item.ColorGlowRight.Z); } // camera CameraTurnTable camera = game.Camera; file.Write(camera.FieldOfViewHorizontal); file.Write(camera.Target.X); file.Write(camera.Target.Y); file.Write(camera.Target.Z); file.Write(camera.Distance); file.Write(camera.RotationHorizontal); file.Write(camera.RotationVertical); // light 1 Vector3 light1Dir = game.Light1Direction; file.Write(light1Dir.X); file.Write(light1Dir.Y); file.Write(light1Dir.Z); file.Write(game.Light1Intensity); Color light1Color = game.Light1Color; file.Write(light1Color.R); file.Write(light1Color.G); file.Write(light1Color.B); file.Write(game.Light1ShadowDepth); // light 2 Vector3 light2Dir = game.Light2Direction; file.Write(light2Dir.X); file.Write(light2Dir.Y); file.Write(light2Dir.Z); file.Write(game.Light2Intensity); Color light2Color = game.Light2Color; file.Write(light2Color.R); file.Write(light2Color.G); file.Write(light2Color.B); file.Write(game.Light2ShadowDepth); // light 3 Vector3 light3Dir = game.Light3Direction; file.Write(light3Dir.X); file.Write(light3Dir.Y); file.Write(light3Dir.Z); file.Write(game.Light3Intensity); Color light3Color = game.Light3Color; file.Write(light3Color.R); file.Write(light3Color.G); file.Write(light3Color.B); file.Write(game.Light3ShadowDepth); // post-processing params file.Write(game.PostProcessBrightness); file.Write(game.PostProcessGamma); file.Write(game.PostProcessContrast); file.Write(game.PostProcessSaturation); // ground texture file.Write(game.DisplayGround); file.Write("data\\ground.png"); // background color file.Write(game.BackgroundColor.R); file.Write(game.BackgroundColor.G); file.Write(game.BackgroundColor.B); // background image file.Write(""); // skydome file.Write(game.DisplaySkyDome); file.Write(ItemType.SkyDome_Thailand_Sea.ToString()); file.Write(game.SkyDomeRotation); file.Write(game.SkyDomeElevation); // canvas size file.Write(game.GameForm.WindowState == FormWindowState.Maximized); file.Write(game.GameForm.ClientSize.Width); file.Write(game.GameForm.ClientSize.Height); file.Close(); }
/// <summary> /// Формирует измененные позиции вершин (ключ словаря - индекс в переданном массиве vertices, значение - новая позиция и нормаль этой вершины) на основании переданного массива вершин, /// скелета (список костей) к которому эти вершины привязаны а также набора трансформаций с этими костями. /// То есть по сути формирует состояние вершин модели при изменении костей (как при скелетной анимации) /// </summary> public static Dictionary <int, Vertex> BakeBlendShape(Vec3 objectPosition, WowVertex[] vertices, WowBone[] bones, WowVrcFileData.BlendshapeData.BoneData[] blendShapeBoneChanges, float scale) { var vertexPositions = vertices .Select(x => new Vec3(x.Position.X + objectPosition.X, x.Position.Y + objectPosition.Y, x.Position.Z + objectPosition.Z)) .ToArray(); // Создаем оригинальные/трансформированные кости и просчитываем локальные матрицы для них var originalBones = new BoneTransform[bones.Length]; var blenshapeBones = new BoneTransform[bones.Length]; for (int boneIdx = 0; boneIdx < bones.Length; boneIdx++) { if (bones[boneIdx] == null) { continue; } originalBones[boneIdx] = new BoneTransform(); blenshapeBones[boneIdx] = new BoneTransform(); originalBones[boneIdx].SetLocalDataFromWowBone(bones[boneIdx]); var blendshapeChange = blendShapeBoneChanges.FirstOrDefault(x => x.Name == bones[boneIdx].GetName()); if (blendshapeChange != null) { blenshapeBones[boneIdx].SetLocalDataFromBlendshapeBone(bones[boneIdx], blendshapeChange, scale); } else { blenshapeBones[boneIdx].SetLocalDataFromWowBone(bones[boneIdx]); } } // Прописываем иерархию для оригинальных/трансформированных костей for (int boneIdx = 0; boneIdx < bones.Length; boneIdx++) { if (bones[boneIdx] == null) { continue; } if (bones[boneIdx].ParentBone != null) { originalBones[boneIdx].Parent = originalBones[bones[boneIdx].ParentBone.Index]; blenshapeBones[boneIdx].Parent = blenshapeBones[bones[boneIdx].ParentBone.Index]; } } // Считаем глобальные матрицы разницы между оригинальной и blendshape костью для каждой из костей в исходном массиве костей // В случае если изменений в кости (с учетом родительской иерархии) не было, матрица изменений кости будет равна (или приблизительно равна) identity var blendshapeDifferenceMatricesPerBone = new Mat4[bones.Length]; for (int boneIdx = 0; boneIdx < bones.Length; boneIdx++) { if (originalBones[boneIdx] == null) { continue; } blendshapeDifferenceMatricesPerBone[boneIdx] = Mat4.Multiply(blenshapeBones[boneIdx].GetGlobalMatrix(), Mat4.Invert(originalBones[boneIdx].GetGlobalMatrix())); } // Меняем заданные вершины в соответствии с просчитанными матрицами изменений. // Если значение вершины изменилось в результате примененных трансформаций (то есть если на вершину влияла хотя бы одна кость, матрица изменений которой не identity) // то добавляем эту вершину в словарь измененных вершин, который далее возвращаем var changedVertices = new Dictionary <int, Vertex>(); for (int vertexIdx = 0; vertexIdx < vertices.Length; vertexIdx++) { var vertex = vertices[vertexIdx]; var vertexPosition = vertexPositions[vertexIdx]; var changedVertexPos = new Vec3(); var changedVertexNormal = new Vec3(); for (int boneInVertexIdx = 0; boneInVertexIdx < 4; boneInVertexIdx++) { var boneIdx = vertex.BoneIndexes[boneInVertexIdx]; if (boneIdx < 0 || bones[boneIdx] == null) { continue; } var boneWeight = vertex.BoneWeights[boneInVertexIdx]; var positionFromBone = Vec3.TransformMat4(vertexPosition, blendshapeDifferenceMatricesPerBone[boneIdx]); changedVertexPos.X += positionFromBone.X * boneWeight; changedVertexPos.Y += positionFromBone.Y * boneWeight; changedVertexPos.Z += positionFromBone.Z * boneWeight; // Незнаю в чем дело, но если используется scale в нормалях то результат не соответствует скинингу из юнити. При чем непонятно где правильно сделано, как тут или как там var normalFromBone = Vec3.TransformMat4(vertex.Normal, Mat4.Transpose(Mat4.Invert(blendshapeDifferenceMatricesPerBone[boneIdx]))); changedVertexNormal.X += normalFromBone.X * boneWeight; changedVertexNormal.Y += normalFromBone.Y * boneWeight; changedVertexNormal.Z += normalFromBone.Z * boneWeight; } changedVertexNormal = Vec3.Normalize(changedVertexNormal); if (!Vec3.AreNearlyEqual(changedVertexPos, vertexPosition)) { changedVertices.Add(vertexIdx, new Vertex() { Position = new Vec3(changedVertexPos.X - objectPosition.X, changedVertexPos.Y - objectPosition.Y, changedVertexPos.Z - objectPosition.Z), Normal = changedVertexNormal }); } } return(changedVertices); }
public static SkeletonFormat Read(List <ChunkTable.ChunkDataEntry> chunkList) { var genericSkeleton = new SkeletonFormat(); Header header = null; List <BoneInfo> boneInfos = new List <BoneInfo>(); List <BoneTransform> boneTransforms = new List <BoneTransform>(); List <uint> boneIndices = new List <uint>(); List <BoneHash> boneHashes = new List <BoneHash>(); for (int i = 0; i < chunkList.Count; i++) { if (chunkList[i].ChunkType == ChunkDataType.SkeletonHeader) { header = chunkList[i].ReadStruct <Header>(); } } for (int i = 0; i < chunkList.Count; i++) { var chunk = chunkList[i]; Console.WriteLine($"SKELETON {chunk.ChunkType}"); switch (chunk.ChunkType) { case ChunkDataType.SkeletonBoneInfo: boneInfos = chunk.ReadStructs <BoneInfo>(header.BoneCount); break; case ChunkDataType.SkeletonBoneTransform: boneTransforms = chunk.ReadStructs <BoneTransform>(header.BoneCount); break; case ChunkDataType.SkeletonBoneIndexList: // boneIndices = chunk.ReadPrimitive<uint>(header.BoneIndexListCount); break; case ChunkDataType.SkeletonBoneHashList: boneHashes = chunk.ReadStructs <BoneHash>(header.BoneCount); break; } } for (int i = 0; i < boneInfos.Count; i++) { var info = boneInfos[i]; var transform = boneTransforms[i]; string name = Hashing.HashNames.ContainsKey(info.Hash) ? Hashing.HashNames[info.Hash] : info.Hash.ToString(); if (transform == null) { transform = new BoneTransform(); } genericSkeleton.Bones.Add(new STBone(genericSkeleton) { Name = name, ParentIndex = info.ParentIndex, Position = (new OpenTK.Vector3( transform.TranslationX, transform.TranslationY, transform.TranslationZ) * (info.ParentIndex != -1 ? (32 * ModelWrapper.PreviewScale) : 1)), Rotation = new OpenTK.Quaternion( transform.QuaternionX, transform.QuaternionY, transform.QuaternionZ, transform.QuaternionW) * (info.ParentIndex == -1 ? Quaternion.FromEulerAngles(-1.5708F, 0, 0) : Quaternion.Identity), }); Console.WriteLine($"BONE {transform.ScaleX} {transform.ScaleY} {transform.ScaleZ}"); } for (int i = 0; i < boneHashes.Count; i++) { genericSkeleton.BoneHashToID.Add(boneHashes[i].Hash, (int)boneHashes[i].Index); Console.WriteLine($"BONEINDEXLIST {boneHashes[i].Hash} {boneHashes[i].Index}"); } genericSkeleton.Reset(); return(genericSkeleton); }
private bool LoadItems(BinaryReader file, ushort versionMajor, ushort versionMinor, bool loadScene) { // items int itemCount = file.ReadInt32(); for (int itemID = 0; itemID < itemCount; itemID++) { // create item string itemTypeName = file.ReadString(); string dirName; if (versionMajor >= 1 && versionMinor >= 5) { dirName = file.ReadString(); } else { dirName = itemTypeName.ToLower(); } bool isVisible = file.ReadBoolean(); Vector3 itemScale; if (versionMajor >= 1 && versionMinor >= 8) { float itemScaleX = file.ReadSingle(); float itemScaleY = file.ReadSingle(); float itemScaleZ = file.ReadSingle(); itemScale = new Vector3(itemScaleX, itemScaleY, itemScaleZ); } else { float itemScaleXYZ = file.ReadSingle(); itemScale = new Vector3(itemScaleXYZ, itemScaleXYZ, itemScaleXYZ); } ItemType itemType = ParseItemType(itemTypeName); Item item = ItemFactory.GetItem(game, itemType); if (!dirName.ToLower().StartsWith("data\\")) { dirName = "data\\" + dirName; } if (!item.LoadAndInitModel(itemType, dirName)) { return(false); } item.Model.IsVisible = isVisible; if (loadScene) { AddItem(item); } // pose Armature armature = item.Model.Armature; foreach (Armature.Bone bone in armature.Bones) { float rotX = file.ReadSingle(); float rotY = file.ReadSingle(); float rotZ = file.ReadSingle(); float moveX = 0; float moveY = 0; float moveZ = 0; if (versionMajor >= 1 && versionMinor >= 3) { moveX = file.ReadSingle(); moveY = file.ReadSingle(); moveZ = file.ReadSingle(); } if (loadScene) { DataSet dataSet = dataSetDict[item]; BoneTransform boneTransform = dataSet.boneTransforms[bone.id]; boneTransform.rotX = rotX; boneTransform.rotY = rotY; boneTransform.rotZ = rotZ; boneTransform.moveX = moveX; boneTransform.moveY = moveY; boneTransform.moveZ = moveZ; ApplyTransformToBone(bone, boneTransform); } } // position Vector3 position = new Vector3(); position.X = file.ReadSingle(); position.Y = file.ReadSingle(); position.Z = file.ReadSingle(); if (loadScene) { armature.WorldScale = itemScale; HandleScaleChangedInGUI(itemScale); armature.WorldTranslation = position; HandleHeightChanged(position.Y); } // accessories ImportModelParams(file, loadScene ? item.Model : null); if (loadScene) { UpdateAccessoriesCheckboxes(item.Model); } // glow colors if (versionMajor >= 1 && versionMinor >= 11) { float r, g, b; r = file.ReadSingle(); g = file.ReadSingle(); b = file.ReadSingle(); item.ColorGlowLeft = new Vector4(r, g, b, 1); r = file.ReadSingle(); g = file.ReadSingle(); b = file.ReadSingle(); item.ColorGlowRight = new Vector4(r, g, b, 1); } } return(true); }
public static void CalculateVerticesAndNormals( BoneTransform[] boneTransforms, int vertexCount, Vertex[] vertices, Influence[] influences, CalVector4[] output ) { Debug.Assert(output.Length == vertices.Length * 2); BoneTransform totalTransform; for ( int sourceVertex = 0, sourceInfluence = 0, outputVertex = 0; sourceVertex < vertices.Length; sourceVertex++, sourceInfluence++, outputVertex += 2 ) { var influence = influences[sourceInfluence]; boneTransforms[influence.BoneId].Scale( out totalTransform, influence.Weight ); while (!influence.LastInfluenceForThisVertex) { sourceInfluence += 1; influence = influences[sourceInfluence]; boneTransforms[influence.BoneId].AddScaled( ref totalTransform, influence.Weight ); } totalTransform.TransformPoint( out output[outputVertex], ref vertices[sourceVertex].Position ); totalTransform.TransformVector( out output[outputVertex + 1], ref vertices[sourceVertex].Normal ); } }
public override void Bind(TransformBase animationTransform) { this.boneTransform = animationTransform as BoneTransform; }