public void AddBlendShapesToMesh(Mesh mesh) { Dictionary <string, BlendShape> map = new Dictionary <string, BlendShape>(); foreach (var x in BlendShapes) { BlendShape bs = null; if (!map.TryGetValue(x.Name, out bs)) { bs = new BlendShape(); bs.Positions = Positions.ToArray(); bs.Normals = Normals.ToArray(); bs.Tangents = Tangents.Select(y => (Vector3)y).ToArray(); bs.Name = x.Name; bs.FrameWeight = x.FrameWeight; map.Add(x.Name, bs); } var j = x.VertexOffset; for (int i = 0; i < x.Positions.Length; ++i, ++j) { bs.Positions[j] = x.Positions[i]; bs.Normals[j] = x.Normals[i]; bs.Tangents[j] = x.Tangents[i]; } } foreach (var kv in map) { //Debug.LogFormat("AddBlendShapeFrame: {0}", kv.Key); mesh.AddBlendShapeFrame(kv.Key, kv.Value.FrameWeight, kv.Value.Positions, kv.Value.Normals, kv.Value.Tangents); } }
void BuildBlendShapes() { _blendShapes = new BlendShape[attributeMeshes.Length]; for (int i = 0; i < attributeMeshes.Length; i++) { if (attributeMeshes [i] == null) { continue; } _blendShapes[i] = new BlendShape(); Vector3[] attributeMeshVertices = attributeMeshes[i].vertices; Vector3[] attributeMeshNormals = attributeMeshes[i].normals; Vector3[] workMeshVertices = _workingMesh.vertices; Vector3[] workMeshNormals = _workingMesh.normals; List <BlendShapeVertex> vertices = new List <BlendShapeVertex>(_workingMesh.vertexCount); for (int j = 0; j < _workingMesh.vertexCount; j++) { if (workMeshVertices[j] != attributeMeshVertices[j]) { BlendShapeVertex blendShapeVertex = new BlendShapeVertex(); blendShapeVertex.originalIndex = j; blendShapeVertex.position = attributeMeshVertices[j] - workMeshVertices[j]; // blendShapeVertex.normal = attributeMeshNormals[j] - workMeshNormals[j]; vertices.Add(blendShapeVertex); } } _blendShapes[i].vertices = vertices.ToArray(); } }
public static BlendShapeManager FromGltf(this VrmBlendShapeMaster master, List <MeshGroup> meshes, List <Material> materials, List <Node> nodes) { var manager = new BlendShapeManager(); manager.BlendShapeList.AddRange(master.blendShapeGroups.Select(x => { var expression = new BlendShape(x.presetName.FromGltf(), x.name, x.isBinary); expression.BlendShapeValues.AddRange( x.binds.Select(y => { var group = meshes[y.mesh]; var node = nodes.First(z => z.MeshGroup == group); var blendShapeName = group.Meshes[0].MorphTargets[y.index].Name; var value = new BlendShapeBindValue(node, blendShapeName, y.weight); return(value); })); expression.MaterialValues.AddRange( x.materialValues.Select(y => { var material = materials.First(z => z.Name == y.materialName); var target = new Vector4(y.targetValue[0], y.targetValue[1], y.targetValue[2], y.targetValue[3]); var value = new MaterialBindValue(material, y.propertyName, target); return(value); })); return(expression); })); return(manager); }
public void SetMorph() { if (_blendShapes == null) { return; } Vector3[] morphedVertices = neutral.vertices; Vector3[] morphedNormals = neutral.normals; for (int j = 0; j < attributeMeshes.Length; j++) { if (attributeMeshes [j] == null) { continue; } if (!Mathf.Approximately(attributeProgress[j], 0)) { BlendShape shape = _blendShapes[j]; for (int i = 0; i < shape.vertices.Length; i++) { morphedVertices[shape.vertices[i].originalIndex] += shape.vertices[i].position * attributeProgress[j] * eOffset; //morphedNormals[shape.vertices[i].originalIndex] += shape.vertices[i].normal * attributeProgress[j]; } } } _workingMesh.vertices = morphedVertices; _workingMesh.normals = morphedNormals; _workingMesh.RecalculateBounds(); }
void BuildBlendShapes() { ConfigNode keyNode = null; if (!String.IsNullOrEmpty(keyNodeString)) { keyNode = ConfigNode.Parse(keyNodeString).nodes[0]; } int keyCount = 0; if (keyNode != null) { keyCount = keyNode.values.Count; } int index = 0; for (int i = 0; i < keyCount; i++) { var value = keyNode.values[i]; if (!blendShapeDict.ContainsKey(value.name)) { var bs = new BlendShape(value.name, index++, shapeMesh); blendShapeDict[value.name] = bs; blendShapeList.Add(bs); } } while (index < shapeMesh.sharedMesh.blendShapeCount) { var bs = new BlendShape(index.ToString(), index++, shapeMesh); blendShapeList.Add(bs); } }
public BlendShapeContainer(BlendShape blendShape) { shapeName = blendShape.ShapeName; frames = new BlendShapeFrameContainer[blendShape.Frames.Length]; for (int i = 0; i < frames.Length; i++) { frames[i] = new BlendShapeFrameContainer(blendShape.Frames[i]); } }
public void ChangeBlendShapeValue(string blendShapeName, float value) { if (!BlendShapesList.ContainsKey(blendShapeName)) { Debug.LogError(blendShapeName + "不存在"); return; } BlendShape blendshape = BlendShapesList[blendShapeName]; value = Mathf.Clamp(value, -100, 100); skm.SetBlendShapeWeight(blendshape.Index, value); }
public static BlendShapeManager FromGltf(this VrmBlendShapeMaster master, List <MeshGroup> meshes, List <Material> materials, List <Node> nodes) { var manager = new BlendShapeManager(); manager.BlendShapeList.AddRange(master.blendShapeGroups.Select(x => { var expression = new BlendShape(x.presetName.FromGltf(), x.name, x.isBinary); expression.BlendShapeValues.AddRange( x.binds.Select(y => { var group = meshes[y.mesh]; var node = nodes.First(z => z.MeshGroup == group); var blendShapeName = group.Meshes[0].MorphTargets[y.index].Name; var value = new BlendShapeBindValue(node, blendShapeName, y.weight); return(value); })); /// VRM-0.X の MaterialBindValue を VRM-1.0 仕様に変換する foreach (var y in x.materialValues) { var material = materials.First(z => z.Name == y.materialName); if (y.propertyName.EndsWith("_ST")) { expression.UVScaleOffsetValues.Add(new UVScaleOffsetValue(material, new Vector2(y.targetValue[0], y.targetValue[1]), new Vector2(y.targetValue[2], y.targetValue[3]))); } else if (y.propertyName.EndsWith("_ST_S")) { expression.UVScaleOffsetValues.Add(new UVScaleOffsetValue(material, new Vector2(y.targetValue[0], 1), new Vector2(y.targetValue[2], 0))); } else if (y.propertyName.EndsWith("_ST_T")) { expression.UVScaleOffsetValues.Add(new UVScaleOffsetValue(material, new Vector2(1, y.targetValue[1]), new Vector2(0, y.targetValue[3]))); } else { var bindType = material.GetBindType(y.propertyName); var target = new Vector4(y.targetValue[0], y.targetValue[1], y.targetValue[2], y.targetValue[3]); expression.MaterialValues.Add(new MaterialBindValue(material, bindType, target)); } } return(expression); })); return(manager); }
void BuildBlendShapes() { blendShape = new BlendShape(); blendShape.vertices = new BlendShapeVertex[workingMesh.vertexCount]; for ( int j = 0; j < workingMesh.vertexCount; j++) { BlendShapeVertex blendShapeVertex = new BlendShapeVertex(); blendShapeVertex.originalIndex = j; blendShapeVertex.position = attributeMesh.vertices[j] - workingMesh.vertices[j]; blendShapeVertex.normal = attributeMesh.normals[j] - workingMesh.normals[j]; blendShape.vertices[j] = blendShapeVertex; } }
void BuildBlendShapes() { blendShapes = new BlendShape[attributes.Length]; //For each attribute figure out which vertices are affected, then store their info in the blend shape object. for (int i = 0; i < attributes.Length; i++) { //Populate blendShapes array with new blend shapes blendShapes[i] = new BlendShape(); /** TODO: Make this a little more stylish! * UGLY hack to compensate the lack of dynamic arrays in C#. Feel free to improve! */ int blendShapeCounter = 0; for (int j = 0; j < workingMesh.vertexCount; j++) { if (workingMesh.vertices[j] != attributeMeshes[i].vertices[j]) { blendShapeCounter++; } } blendShapes[i].vertices = new BlendShapeVertex[blendShapeCounter]; blendShapeCounter = 0; for (int j = 0; j < workingMesh.vertexCount; j++) { //If the vertex is affected, populate a blend shape vertex with that info if (workingMesh.vertices[j] != attributeMeshes[i].vertices[j]) { //Create a blend shape vertex and populate its data. BlendShapeVertex blendShapeVertex = new BlendShapeVertex(); blendShapeVertex.originalIndex = j; blendShapeVertex.position = attributeMeshes[i].vertices[j] - workingMesh.vertices[j]; blendShapeVertex.normal = attributeMeshes[i].normals[j] - workingMesh.normals[j]; //Add new blend shape vertex to blendShape object. blendShapes[i].vertices[blendShapeCounter] = blendShapeVertex; blendShapeCounter++; } } //Convert blendShapes.vertices to builtin array //blendShapes[i].vertices = blendShapes[i].vertices.ToBuiltin(BlendShapeVertex); } }
public static BlendShapeManager FromGltf(this VrmProtobuf.BlendShape master, List <MeshGroup> meshes, List <Material> materials) { var manager = new BlendShapeManager(); manager.BlendShapeList.AddRange(master.BlendShapeGroups.Select(x => { var expression = new BlendShape((VrmLib.BlendShapePreset)x.Preset, x.Name, x.IsBinary.HasValue && x.IsBinary.Value); expression.BlendShapeValues.AddRange( x.Binds.Select(y => { var group = meshes[y.Mesh]; var blendShapeName = group.Meshes[0].MorphTargets[y.Index].Name; var value = new BlendShapeBindValue(group, blendShapeName, y.Weight); return(value); })); expression.MaterialValues.AddRange( x.MaterialValues.Select(y => { var material = materials[y.Material]; Vector4 target = default; if (y.TargetValue.Count > 0) { target.X = y.TargetValue[0]; } if (y.TargetValue.Count > 1) { target.Y = y.TargetValue[1]; } if (y.TargetValue.Count > 2) { target.Z = y.TargetValue[2]; } if (y.TargetValue.Count > 3) { target.W = y.TargetValue[3]; } var value = new MaterialBindValue(material, EnumUtil.Parse <MaterialBindType>(y.Type.ToString()), target); return(value); })); return(expression); })); return(manager); }
public void ChangeBlendShapeValue(string blendShapeName, float value) { if (!blendShapeDatabase.ContainsKey(blendShapeName)) { Debug.LogError("BlendShape " + blendShapeName + " doesn't exist."); return; } value = Mathf.Clamp(value, -100.0f, 100.0f); BlendShape blendShape = blendShapeDatabase [blendShapeName]; if (value >= 0) { if (blendShape.positiveIndex == -1) { return; } smr.SetBlendShapeWeight(blendShape.positiveIndex, value); if (blendShape.negativeIndex == -1) { return; } smr.SetBlendShapeWeight(blendShape.negativeIndex, 0); } else { if (blendShape.negativeIndex == -1) { return; } smr.SetBlendShapeWeight(blendShape.negativeIndex, -value); if (blendShape.positiveIndex == -1) { return; } smr.SetBlendShapeWeight(blendShape.positiveIndex, 0); } }
static void SaveVerts(){ GameObject target = Selection.activeGameObject; Mesh targetMesh = target.GetComponent<MeshFilter>().mesh; BlendShape blndShape = new BlendShape(); blndShape.verticies = targetMesh.vertices; blndShape.uvs = targetMesh.uv; blndShape.triangles = targetMesh.triangles; StreamWriter sw = new StreamWriter(Application.dataPath + "/AppData/" + target.name.ToString() + ".xml"); XmlSerializer xml = new XmlSerializer(typeof(BlendShape)); xml.Serialize(sw,blndShape); sw.Close(); AssetDatabase.Refresh(); }
/// <summary> /// Constructor that takes in a target skinned mesh renderer with verts and creates a blend shape object from it. This blend shape will then be assigned to the mesh /// </summary> /// <param name="originalSmr">Original untouched mesh</param> /// <param name="blendShapeName">Desired name of the blend shape, should be unique</param> /// <param name="newSmr">The smr containing the target mesh shape</param> public BlendShapeController(Mesh originalSmrMesh, SkinnedMeshRenderer newSmr, string blendShapeName) { if (!blendShape.isInitilized) { var maxShapeSize = 100f; //Create blend shape deltas from both meshes blendShape = new BlendShape(); blendShape.name = blendShapeName; blendShape.weight = maxShapeSize; //Get delta diffs of the two meshes for the blend shape blendShape.verticies = GetV3Deltas(originalSmrMesh.vertices, newSmr.sharedMesh.vertices); blendShape.normals = GetV3Deltas(originalSmrMesh.normals, newSmr.sharedMesh.normals); blendShape.tangents = GetV3Deltas(ConvertV4ToV3(originalSmrMesh.tangents), ConvertV4ToV3(newSmr.sharedMesh.tangents)); } AddBlendShapeToMesh(newSmr); }
static void SaveVerts() { GameObject target = Selection.activeGameObject; Mesh targetMesh = target.GetComponent <MeshFilter>().mesh; BlendShape blndShape = new BlendShape(); blndShape.verticies = targetMesh.vertices; blndShape.uvs = targetMesh.uv; blndShape.triangles = targetMesh.triangles; StreamWriter sw = new StreamWriter(Application.dataPath + "/AppData/" + target.name.ToString() + ".xml"); XmlSerializer xml = new XmlSerializer(typeof(BlendShape)); xml.Serialize(sw, blndShape); sw.Close(); AssetDatabase.Refresh(); }
IEnumerator animShoot() { canShoot = false; LoadEffect.SetActive(false); float time = 0; while (time < shootTime) { time += Time.deltaTime; if (BlendShape) { BlendShape.SetBlendShapeWeight(0, 100f - time / shootTime * 100f); } yield return(null); } if (BlendShape) { BlendShape.SetBlendShapeWeight(0, 0f); } StartCoroutine(getReady()); }
IEnumerator getReady() { float time = 0; while (time < loadTime) { time += Time.deltaTime; if (BlendShape) { BlendShape.SetBlendShapeWeight(0, time / loadTime * 100f); } WinchWheel.Rotate(WinchWheelRotationAxis * 400f * Time.deltaTime, Space.Self); yield return(null); } if (BlendShape) { BlendShape.SetBlendShapeWeight(0, 100f); } projectileAnim.SetActive(true); canShoot = true; }
IEnumerator getReady() { canShoot = false; LoadEffect.SetActive(true); float time = 0; while (time < loadTime) { time += Time.deltaTime; if (BlendShape) { BlendShape.SetBlendShapeWeight(0, time / loadTime * 100f); } yield return(null); } if (BlendShape) { BlendShape.SetBlendShapeWeight(0, 100f); } canShoot = true; }
public static VrmProtobuf.BlendShapeGroup ToGltf(this BlendShape x, List <MeshGroup> meshes, List <Material> materials) { var g = new VrmProtobuf.BlendShapeGroup { Preset = (VrmProtobuf.BlendShapeGroup.Types.BlendShapePreset)x.Preset, Name = x.Name, IsBinary = x.IsBinary, IgnoreBlink = x.IgnoreBlink, IgnoreLookAt = x.IgnoreLookAt, IgnoreMouth = x.IgnoreMouth, }; foreach (var y in x.BlendShapeValues) { g.Binds.Add(y.ToGltf(meshes)); } foreach (var y in x.MaterialValues) { g.MaterialValues.Add(y.ToGltf(materials)); } return(g); }
public void ChangeBlendShapeValue(string blendShapeName, float value) { if (!BlendShapeDatabase.ContainsKey(blendShapeName)) { Debug.LogError(blendShapeName + "不存在"); return; } BlendShape blendshape = BlendShapeDatabase[blendShapeName]; value = Mathf.Clamp(value, -100, 100); if (value > 0) { if (blendshape.postiveIndex == -1) { return; } skm.SetBlendShapeWeight(blendshape.postiveIndex, value); if (blendshape.negativeIndex == -1) { return; } skm.SetBlendShapeWeight(blendshape.negativeIndex, 0); } else { if (blendshape.negativeIndex == -1) { return; } skm.SetBlendShapeWeight(blendshape.negativeIndex, -value); if (blendshape.postiveIndex == -1) { return; } skm.SetBlendShapeWeight(blendshape.postiveIndex, 0); } }
private bool ShapeEnabled(BlendShape shape) { var shapeGroup = shape.Group; // shape group that this belongs to is disabled? if (UIController.StorableIsGroupEnabled.ContainsKey(shapeGroup)) { if (UIController.StorableIsGroupEnabled[shapeGroup].val == false) { return(false); } } // is the multiplier 0? if (UIController.StorableBlendShapeStrength.ContainsKey(shape.Id)) { if (UIController.StorableBlendShapeStrength[shape.Id].val == 0) { return(false); } } return(true); }
public override void Load(Utility utility) { base.Load(utility); Flags = utility.ReadU32(); utility.LoadIndirect(() => { BoundingBox = GfxBoundingBox.Load(utility); }); PositionOffset = Vector3.Read(utility); SubMeshes = utility.LoadIndirectObjList(() => GfxSubMesh.Load(utility)).ToList(); BaseAddress = utility.ReadU32(); VertexBuffers = utility.LoadIndirectObjList(() => VertexBuffer.Load(utility)).ToList(); utility.LoadIndirect(() => { BlendShape = BlendShape.Load(utility); }); }
/// <summary> /// Initialize /// </summary> void OnEnable() { blendShape = (BlendShape)target; }
public void ShouldApplyBlendShapes() { var mesh = new Mesh(); mesh.vertices = new Vector3[2]; var frameWeights = new float[] { 0.2f, 0.48f }; var deltaVertices = new Vector3[][] { new Vector3[] { new Vector3(15f, 13.7f, 8889.91f), new Vector3(761.717f, -76.225f, 889.1f) }, new Vector3[] { new Vector3(-15f, 13.7f, -8889.91f), new Vector3(761.717f, 76.225f, -889.1f) } }; var deltaNormals = new Vector3[][] { new Vector3[] { deltaVertices[0][0].normalized, deltaVertices[0][1].normalized }, new Vector3[] { deltaVertices[1][0].normalized, deltaVertices[1][1].normalized } }; var deltaTangents = new Vector3[][] { new Vector3[] { Vector3.Cross(deltaNormals[0][0], Vector3.forward).normalized, Vector3.Cross(deltaNormals[0][1], Vector3.forward).normalized, }, new Vector3[] { Vector3.Cross(deltaNormals[1][0], Vector3.forward).normalized, Vector3.Cross(deltaNormals[1][1], Vector3.forward).normalized } }; var blendShape = new BlendShape { ShapeName = "test", Frames = new BlendShapeFrame[] { new BlendShapeFrame(frameWeights[0], deltaVertices[0], deltaNormals[0], deltaTangents[0]), new BlendShapeFrame(frameWeights[1], deltaVertices[1], deltaNormals[1], deltaTangents[1]) } }; var blendShapes = new BlendShape[] { blendShape }; MeshUtils.ApplyMeshBlendShapes(mesh, blendShapes); Assert.AreEqual(1, mesh.blendShapeCount); Assert.AreEqual(blendShape.ShapeName, mesh.GetBlendShapeName(0)); Assert.AreEqual(blendShape.Frames.Length, mesh.GetBlendShapeFrameCount(0)); for (int i = 0; i < blendShape.Frames.Length; i++) { var frame = blendShape.Frames[i]; Assert.AreEqual(frame.FrameWeight, mesh.GetBlendShapeFrameWeight(0, i)); var resultVertices = new Vector3[2]; var resultNormals = new Vector3[2]; var resultTangents = new Vector3[2]; mesh.GetBlendShapeFrameVertices(0, i, resultVertices, resultNormals, resultTangents); Assert.AreEqual(frame.DeltaVertices, resultVertices); Assert.AreEqual(frame.DeltaNormals, resultNormals); Assert.AreEqual(frame.DeltaTangents, resultTangents); } }
public void ShouldCreateMesh() { var vertices = new Vector3[] { new Vector3(15f, 13.7f, 8889.91f), new Vector3(761.717f, -76.225f, 889.1f), new Vector3(-15f, 13.7f, -8889.91f), new Vector3(761.717f, 76.225f, -889.1f) }; var indices = new int[][] { new int[] { 0, 1, 2, 3, 1, 0 }, new int[] { 3, 1, 0, 2, 1, 0 } }; var normals = new Vector3[] { vertices[0].normalized, vertices[1].normalized, vertices[2].normalized, vertices[3].normalized }; var tangents = new Vector4[] { Vector3.Cross(normals[0], Vector3.forward).normalized, Vector3.Cross(normals[1], Vector3.forward).normalized, Vector3.Cross(normals[2], Vector3.forward).normalized, Vector3.Cross(normals[3], Vector3.forward).normalized }; var colors = new Color[] { Color.red, Color.blue, Color.yellow, Color.magenta }; var boneWeights = new BoneWeight[] { new BoneWeight { boneIndex0 = 0, boneIndex1 = 1, boneIndex2 = 2, boneIndex3 = 3, weight0 = 0.1f, weight1 = 0.2f, weight2 = 0.3f, weight3 = 0.4f }, new BoneWeight { boneIndex0 = 0, boneIndex1 = 1, boneIndex2 = 2, boneIndex3 = 3, weight0 = 0.5f, weight1 = 0.6f, weight2 = 0.7f, weight3 = 0.8f }, new BoneWeight { boneIndex0 = 3, boneIndex1 = 2, boneIndex2 = 1, boneIndex3 = 0, weight0 = 0.1f, weight1 = 0.2f, weight2 = 0.3f, weight3 = 0.4f }, new BoneWeight { boneIndex0 = 3, boneIndex1 = 2, boneIndex2 = 1, boneIndex3 = 0, weight0 = 0.5f, weight1 = 0.6f, weight2 = 0.7f, weight3 = 0.8f } }; var uvs2D = new List <Vector2>[] { new List <Vector2> { new Vector2(0f, 1f), new Vector2(0.1f, 1.1f), new Vector2(0.2f, 1.2f), new Vector2(0.3f, 1.3f) }, null, null, new List <Vector2> { new Vector2(1.1f, 2.1f), new Vector2(1.2f, 2.2f), new Vector2(1.3f, 2.3f), new Vector2(1.4f, 2.4f) } }; var uvs3D = new List <Vector3>[] { null, new List <Vector3> { new Vector3(0f, 1f, 2f), new Vector3(0.1f, 1.1f, 2.1f), new Vector3(0.2f, 1.2f, 2.2f), new Vector3(0.3f, 1.3f, 2.3f) }, null, null }; var uvs4D = new List <Vector4>[] { null, null, new List <Vector4> { new Vector4(0f, 1f, 2f, 3f), new Vector4(0.1f, 1.1f, 2.1f, 3.1f), new Vector4(0.2f, 1.2f, 2.2f, 3.2f), new Vector4(0.3f, 1.3f, 2.3f, 3.3f) }, null }; var bindposes = new Matrix4x4[] { Matrix4x4.identity, Matrix4x4.Rotate(Quaternion.Euler(13.4f, 91.1f, -17.9f)), Matrix4x4.Rotate(Quaternion.Euler(-74.9f, 2.817f, 41.99f)), Matrix4x4.Rotate(Quaternion.Euler(14.55f, 23.69f, -73.82f)) }; var blendShapes = new BlendShape[0]; var mesh = MeshUtils.CreateMesh(vertices, indices, normals, tangents, colors, boneWeights, uvs2D, uvs3D, uvs4D, bindposes, blendShapes); Assert.IsNotNull(mesh); Assert.AreEqual(vertices, mesh.vertices); for (int i = 0; i < indices.Length; i++) { Assert.AreEqual(indices[i], mesh.GetIndices(i)); } Assert.AreEqual(normals, mesh.normals); Assert.AreEqual(tangents, mesh.tangents); Assert.AreEqual(colors, mesh.colors); Assert.AreEqual(boneWeights, mesh.boneWeights); var resultUV2D = new List <Vector2>(); mesh.GetUVs(0, resultUV2D); Assert.AreEqual(uvs2D[0], resultUV2D.ToArray()); var resultUV3D = new List <Vector3>(); mesh.GetUVs(1, resultUV3D); Assert.AreEqual(uvs3D[1], resultUV3D.ToArray()); var resultUV4D = new List <Vector4>(); mesh.GetUVs(2, resultUV4D); Assert.AreEqual(uvs4D[2], resultUV4D.ToArray()); resultUV2D.Clear(); mesh.GetUVs(3, resultUV2D); Assert.AreEqual(uvs2D[3], resultUV2D.ToArray()); Assert.AreEqual(bindposes, mesh.bindposes); }
/// <summary> /// Initialize /// </summary> void OnEnable() { blendShape = (BlendShape) target; }
/// <summary> /// Constructor overload that just takes a saved blendshape and sets it to the correct mesh /// </summary> /// <param name="smr">The current active mesh</param> /// <param name="_blendShape">The blendshape we loaded from character card</param> public BlendShapeController(SkinnedMeshRenderer smr, BlendShape _blendShape) { blendShape = _blendShape; AddBlendShapeToMesh(smr); }
public override void OnInspectorGUI() { base.OnInspectorGUI(); EditorGUILayout.Space(); var characterCustomization = (CharacterCustomization)target; if (characterCustomization.target == null) { EditorGUILayout.LabelField("请给target赋值!"); return; } //是否换了新的skm if (!characterCustomization.DoesTargetMatchSkm()) { characterCustomization.ClearDatabase(); } if (characterCustomization.GetNumber() <= 0) { characterCustomization.Initialize(); } string[] blendshapeNames = characterCustomization.GetBlendshapeNames(); if (blendshapeNames.Length <= 0) { EditorGUILayout.LabelField("taget没有blendshape"); characterCustomization.ClearDatabase(); return; } EditorGUILayout.LabelField("请创建一个滑动条~", EditorStyles.boldLabel); selectIndex = EditorGUILayout.Popup("blendShapeName", selectIndex, blendshapeNames); if (GUILayout.Button("创建滑动条")) { if (canvas == null) { canvas = GameObject.FindObjectOfType <Canvas>(); } if (canvas == null) { throw new System.Exception("场景中没有canvas ,请创建!"); } GameObject sliderGo = Instantiate(Resources.Load("slider", typeof(GameObject))) as GameObject; var BShapeSlider = sliderGo.GetComponent <BlendShapeSlider>(); //改名字 //改父物体 //大小 BShapeSlider.BlendShapeName = blendshapeNames[selectIndex]; BShapeSlider.name = blendshapeNames[selectIndex]; BShapeSlider.transform.parent = canvas.transform; BShapeSlider.GetComponent <RectTransform>().sizeDelta = new Vector2(140f, 25f); BShapeSlider.GetComponentInChildren <Text>().text = blendshapeNames[selectIndex]; //获取BlendShape BlendShape blendShape = characterCustomization.GetBlendShape(blendshapeNames[selectIndex]); //获取slider Slider slider = sliderGo.GetComponent <Slider>(); if (blendShape.negativeIndex == -1) { slider.minValue = 0; } if (blendShape.postiveIndex == -1) { slider.maxValue = 0; } slider.value = 0; Debug.Log(blendshapeNames[selectIndex] + "slider 创建完成!"); } }
public MeshData(GLTFMesh gltfMesh, GLTFAccessor.ImportResult[] accessors) { name = gltfMesh.name; if (gltfMesh.primitives.Count == 0) { Debug.LogWarning("0 primitives in mesh"); } else { for (int i = 0; i < gltfMesh.primitives.Count; i++) { GLTFPrimitive primitive = gltfMesh.primitives[i]; int vertStartIndex = verts.Count; submeshVertexStart.Add(vertStartIndex); // Verts - (Z points backwards in GLTF) if (primitive.attributes.POSITION.HasValue) { IEnumerable <Vector3> newVerts = accessors[primitive.attributes.POSITION.Value].ReadVec3().Select(v => { v.z = -v.z; return(v); }); verts.AddRange(newVerts); } int vertCount = verts.Count; // Tris - (Invert all triangles. Instead of flipping each triangle, just flip the entire array. Much easier) if (primitive.indices.HasValue) { submeshTris.Add(new List <int>(accessors[primitive.indices.Value].ReadInt().Reverse().Select(x => x + vertStartIndex))); } /// Normals - (Z points backwards in GLTF) if (primitive.attributes.NORMAL.HasValue) { normals.AddRange(accessors[primitive.attributes.NORMAL.Value].ReadVec3().Select(v => { v.z = -v.z; return(v); })); } // Tangents - (Z points backwards in GLTF) if (primitive.attributes.TANGENT.HasValue) { tangents.AddRange(accessors[primitive.attributes.TANGENT.Value].ReadVec4().Select(v => { v.z = -v.z; v.w = -v.w; return(v); })); } // Vertex colors if (primitive.attributes.COLOR_0.HasValue) { colors.AddRange(accessors[primitive.attributes.COLOR_0.Value].ReadColor()); } // Weights if (primitive.attributes.WEIGHTS_0.HasValue && primitive.attributes.JOINTS_0.HasValue) { Vector4[] weights0 = accessors[primitive.attributes.WEIGHTS_0.Value].ReadVec4(); Vector4[] joints0 = accessors[primitive.attributes.JOINTS_0.Value].ReadVec4(); if (joints0.Length == weights0.Length) { BoneWeight[] boneWeights = new BoneWeight[weights0.Length]; for (int k = 0; k < boneWeights.Length; k++) { NormalizeWeights(ref weights0[k]); boneWeights[k].weight0 = weights0[k].x; boneWeights[k].weight1 = weights0[k].y; boneWeights[k].weight2 = weights0[k].z; boneWeights[k].weight3 = weights0[k].w; boneWeights[k].boneIndex0 = Mathf.RoundToInt(joints0[k].x); boneWeights[k].boneIndex1 = Mathf.RoundToInt(joints0[k].y); boneWeights[k].boneIndex2 = Mathf.RoundToInt(joints0[k].z); boneWeights[k].boneIndex3 = Mathf.RoundToInt(joints0[k].w); } if (weights == null) { weights = new List <BoneWeight>(new BoneWeight[vertCount - boneWeights.Length]); } weights.AddRange(boneWeights); } else { Debug.LogWarning("WEIGHTS_0 and JOINTS_0 not same length. Skipped"); } } else { if (weights != null) { weights.AddRange(new BoneWeight[vertCount - weights.Count]); } } // UVs ReadUVs(ref uv1, accessors, primitive.attributes.TEXCOORD_0, vertCount); ReadUVs(ref uv2, accessors, primitive.attributes.TEXCOORD_1, vertCount); ReadUVs(ref uv3, accessors, primitive.attributes.TEXCOORD_2, vertCount); ReadUVs(ref uv4, accessors, primitive.attributes.TEXCOORD_3, vertCount); ReadUVs(ref uv5, accessors, primitive.attributes.TEXCOORD_4, vertCount); ReadUVs(ref uv6, accessors, primitive.attributes.TEXCOORD_5, vertCount); ReadUVs(ref uv7, accessors, primitive.attributes.TEXCOORD_6, vertCount); ReadUVs(ref uv8, accessors, primitive.attributes.TEXCOORD_7, vertCount); } bool hasTargetNames = gltfMesh.extras != null && gltfMesh.extras.targetNames != null; if (hasTargetNames) { if (gltfMesh.primitives.All(x => x.targets.Count != gltfMesh.extras.targetNames.Length)) { Debug.LogWarning("Morph target names found in mesh " + name + " but array length does not match primitive morph target array length"); hasTargetNames = false; } } // Read blend shapes after knowing final vertex count int finalVertCount = verts.Count; for (int i = 0; i < gltfMesh.primitives.Count; i++) { GLTFPrimitive primitive = gltfMesh.primitives[i]; if (primitive.targets != null) { for (int k = 0; k < primitive.targets.Count; k++) { BlendShape blendShape = new BlendShape(); blendShape.pos = GetMorphWeights(primitive.targets[k].POSITION, submeshVertexStart[i], finalVertCount, accessors); blendShape.norm = GetMorphWeights(primitive.targets[k].NORMAL, submeshVertexStart[i], finalVertCount, accessors); blendShape.tan = GetMorphWeights(primitive.targets[k].TANGENT, submeshVertexStart[i], finalVertCount, accessors); if (hasTargetNames) { blendShape.name = gltfMesh.extras.targetNames[k]; } else { blendShape.name = "morph-" + blendShapes.Count; } blendShapes.Add(blendShape); } } } } }
public bool Equals(BlendShape obj) { return(obj != null && obj.Id == this.Id); }
public BlendShapeReceivedEventArgs(BlendShape shape, float value) { Shape = shape; Value = value; }
public MeshData(GLTFMesh gltfMesh, GLTFAccessor.ImportResult[] accessors, GLTFBufferView.ImportResult[] bufferViews) { name = gltfMesh.name; if (gltfMesh.primitives.Count == 0) { Debug.LogWarning("0 primitives in mesh"); } else { for (int i = 0; i < gltfMesh.primitives.Count; i++) { GLTFPrimitive primitive = gltfMesh.primitives[i]; // Load draco mesh if (primitive.extensions != null && primitive.extensions.KHR_draco_mesh_compression != null) { GLTFPrimitive.DracoMeshCompression draco = primitive.extensions.KHR_draco_mesh_compression; GLTFBufferView.ImportResult bufferView = bufferViews[draco.bufferView]; GLTFUtilityDracoLoader loader = new GLTFUtilityDracoLoader(); byte[] buffer = new byte[bufferView.byteLength]; bufferView.stream.Seek(bufferView.byteOffset, System.IO.SeekOrigin.Begin); bufferView.stream.Read(buffer, 0, bufferView.byteLength); GLTFUtilityDracoLoader.MeshAttributes attribs = new GLTFUtilityDracoLoader.MeshAttributes( primitive.extensions.KHR_draco_mesh_compression.attributes.POSITION ?? -1, primitive.extensions.KHR_draco_mesh_compression.attributes.NORMAL ?? -1, primitive.extensions.KHR_draco_mesh_compression.attributes.TEXCOORD_0 ?? -1, primitive.extensions.KHR_draco_mesh_compression.attributes.JOINTS_0 ?? -1, primitive.extensions.KHR_draco_mesh_compression.attributes.WEIGHTS_0 ?? -1, primitive.extensions.KHR_draco_mesh_compression.attributes.COLOR_0 ?? -1 ); //Mesh mesh = loader.LoadMesh(buffer, attribs); GLTFUtilityDracoLoader.AsyncMesh asyncMesh = loader.LoadMesh(buffer, attribs); if (asyncMesh == null) { Debug.LogWarning("Draco mesh couldn't be loaded"); } submeshTrisMode.Add(primitive.mode); // Tris int vertCount = verts.Count(); submeshTris.Add(asyncMesh.tris.Reverse().Select(x => x + vertCount).ToList()); verts.AddRange(asyncMesh.verts.Select(x => new Vector3(-x.x, x.y, x.z))); normals.AddRange(asyncMesh.norms.Select(v => { v.x = -v.x; return(v); })); //tangents.AddRange(asyncMesh.tangents.Select(v => { v.y = -v.y; v.z = -v.z; return v; })); // Weights if (asyncMesh.boneWeights != null) { if (weights == null) { weights = new List <BoneWeight>(); } weights.AddRange(asyncMesh.boneWeights); } // BlendShapes not supported yet /* for (int k = 0; k < mesh.blendShapeCount; k++) { * int frameCount = mesh.GetBlendShapeFrameCount(k); * BlendShape blendShape = new BlendShape(); * blendShape.pos = new Vector3[frameCount]; * blendShape.norm = new Vector3[frameCount]; * blendShape.tan = new Vector3[frameCount]; * for (int o = 0; o < frameCount; o++) { * mesh.GetBlendShapeFrameVertices(k, o, blendShape.pos, blendShape.norm, blendShape.tan); * } * blendShapes.Add(blendShape); * } */ // UVs if (asyncMesh.uv != null) { if (uv1 == null) { uv1 = new List <Vector2>(); } uv1.AddRange(asyncMesh.uv.Select(x => new Vector2(x.x, -x.y))); } } // Load normal mesh else { int vertStartIndex = verts.Count; submeshVertexStart.Add(vertStartIndex); // Verts - (X points left in GLTF) if (primitive.attributes.POSITION.HasValue) { IEnumerable <Vector3> newVerts = accessors[primitive.attributes.POSITION.Value].ReadVec3().Select(v => { v.x = -v.x; return(v); }); verts.AddRange(newVerts); } int vertCount = verts.Count; // Tris - (Invert all triangles. Instead of flipping each triangle, just flip the entire array. Much easier) if (primitive.indices.HasValue) { submeshTris.Add(new List <int>(accessors[primitive.indices.Value].ReadInt().Reverse().Select(x => x + vertStartIndex))); submeshTrisMode.Add(primitive.mode); } /// Normals - (X points left in GLTF) if (primitive.attributes.NORMAL.HasValue) { normals.AddRange(accessors[primitive.attributes.NORMAL.Value].ReadVec3().Select(v => { v.x = -v.x; return(v); })); } // Tangents - (X points left in GLTF) if (primitive.attributes.TANGENT.HasValue) { tangents.AddRange(accessors[primitive.attributes.TANGENT.Value].ReadVec4().Select(v => { v.y = -v.y; v.z = -v.z; return(v); })); } // Vertex colors if (primitive.attributes.COLOR_0.HasValue) { colors.AddRange(accessors[primitive.attributes.COLOR_0.Value].ReadColor()); } // Weights if (primitive.attributes.WEIGHTS_0.HasValue && primitive.attributes.JOINTS_0.HasValue) { Vector4[] weights0 = accessors[primitive.attributes.WEIGHTS_0.Value].ReadVec4(); Vector4[] joints0 = accessors[primitive.attributes.JOINTS_0.Value].ReadVec4(); if (joints0.Length == weights0.Length) { BoneWeight[] boneWeights = new BoneWeight[weights0.Length]; for (int k = 0; k < boneWeights.Length; k++) { NormalizeWeights(ref weights0[k]); boneWeights[k].weight0 = weights0[k].x; boneWeights[k].weight1 = weights0[k].y; boneWeights[k].weight2 = weights0[k].z; boneWeights[k].weight3 = weights0[k].w; boneWeights[k].boneIndex0 = Mathf.RoundToInt(joints0[k].x); boneWeights[k].boneIndex1 = Mathf.RoundToInt(joints0[k].y); boneWeights[k].boneIndex2 = Mathf.RoundToInt(joints0[k].z); boneWeights[k].boneIndex3 = Mathf.RoundToInt(joints0[k].w); } if (weights == null) { weights = new List <BoneWeight>(new BoneWeight[vertCount - boneWeights.Length]); } weights.AddRange(boneWeights); } else { Debug.LogWarning("WEIGHTS_0 and JOINTS_0 not same length. Skipped"); } } else { if (weights != null) { weights.AddRange(new BoneWeight[vertCount - weights.Count]); } } // UVs ReadUVs(ref uv1, accessors, primitive.attributes.TEXCOORD_0, vertCount); ReadUVs(ref uv2, accessors, primitive.attributes.TEXCOORD_1, vertCount); ReadUVs(ref uv3, accessors, primitive.attributes.TEXCOORD_2, vertCount); ReadUVs(ref uv4, accessors, primitive.attributes.TEXCOORD_3, vertCount); ReadUVs(ref uv5, accessors, primitive.attributes.TEXCOORD_4, vertCount); ReadUVs(ref uv6, accessors, primitive.attributes.TEXCOORD_5, vertCount); ReadUVs(ref uv7, accessors, primitive.attributes.TEXCOORD_6, vertCount); ReadUVs(ref uv8, accessors, primitive.attributes.TEXCOORD_7, vertCount); } } bool hasTargetNames = gltfMesh.extras != null && gltfMesh.extras.targetNames != null; if (hasTargetNames) { if (gltfMesh.primitives.All(x => x.targets.Count != gltfMesh.extras.targetNames.Length)) { Debug.LogWarning("Morph target names found in mesh " + name + " but array length does not match primitive morph target array length"); hasTargetNames = false; } } // Read blend shapes after knowing final vertex count int finalVertCount = verts.Count; for (int i = 0; i < gltfMesh.primitives.Count; i++) { GLTFPrimitive primitive = gltfMesh.primitives[i]; if (primitive.targets != null) { for (int k = 0; k < primitive.targets.Count; k++) { BlendShape blendShape = new BlendShape(); blendShape.pos = GetMorphWeights(primitive.targets[k].POSITION, submeshVertexStart[i], finalVertCount, accessors); blendShape.norm = GetMorphWeights(primitive.targets[k].NORMAL, submeshVertexStart[i], finalVertCount, accessors); blendShape.tan = GetMorphWeights(primitive.targets[k].TANGENT, submeshVertexStart[i], finalVertCount, accessors); if (hasTargetNames) { blendShape.name = gltfMesh.extras.targetNames[k]; } else { blendShape.name = "morph-" + blendShapes.Count; } blendShapes.Add(blendShape); } } } } }
/// <summary> /// Hook up the BlendShape data /// </summary> /// <param name="go"> /// A <see cref="GameObject"/> /// </param> public virtual void OnPostprocessModel(GameObject go) { // early out if no blend shape data were found if (baseShapePairs.Count < 1) { return; } // process each blend shape data object foreach (GameObject indexMap in baseShapePairs.Keys) { // grab the container for the new BlendShape component from the HashTable Transform blendContainer = TransformHelpers.GetTransformInHierarchy(go.transform, baseShapePairs[indexMap] as string); // if no match is found, try to find a skin with the mesh Component[] skins = go.GetComponentsInChildren <SkinnedMeshRenderer>(); foreach (SkinnedMeshRenderer skin in skins) { if (skin.sharedMesh.name == baseShapePairs[indexMap] as string) { blendContainer = skin.transform; } } // if no match was found, then assume it is the root if (blendContainer == null || blendContainer.GetComponent <Renderer>() == null) { blendContainer = go.transform; } // add the blendShape component if it does not yet exist BlendShape blendShapeNode = blendContainer.gameObject.AddComponent <BlendShape>(); blendShapeNode.meshRenderer = blendShapeNode.GetComponent <Renderer>(); // grab the base mesh to map target indices and the ArrayList of target models Mesh taggedBaseMesh = indexMap.GetComponent <MeshFilter>().sharedMesh; ArrayList targetModels = targetMeshes[indexMap.name] as ArrayList; // grab the seamless base mesh GameObject seamlessBaseModel = seamlessShapePairs[indexMap.name] as GameObject; blendShapeNode.seamlessBaseMesh = seamlessBaseModel.GetComponent <MeshFilter>().sharedMesh; // create the index map between the seamless base mesh and the actual base mesh Mesh outMesh; if (blendShapeNode.GetComponent <MeshFilter>() == null) { outMesh = blendShapeNode.GetComponent <SkinnedMeshRenderer>().sharedMesh; } else { outMesh = blendShapeNode.GetComponent <MeshFilter>().sharedMesh; } blendShapeNode.indexMap = new int[outMesh.vertexCount]; for (int i = 0; i < taggedBaseMesh.colors.Length; i++) { // point indices on the seamless mesh should be identical to tag values blendShapeNode.indexMap[i] = ColorToTag(taggedBaseMesh.colors[i]); } // create BlendShapeTargets from the target models blendShapeNode.targets = new BlendShape.Target[targetModels.Count]; for (int i = 0; i < targetModels.Count; i++) { // create the new BlendShapeTarget GameObject targetModel = targetModels[i] as GameObject; Mesh targetMesh = targetModel.GetComponent <MeshFilter>().sharedMesh; BlendShape.Target target = new BlendShape.Target(); target.name = targetMesh.name.Substring(targetMesh.name.LastIndexOf("__blendShapeTarget__") + 20); // store the indices and deltaPosition values for the target ArrayList vertices = new ArrayList(); ArrayList deltaPos = new ArrayList(); for (int j = 0; j < targetMesh.vertexCount; j++) { int tag = ColorToTag(targetMesh.colors[j]); Vector3 compareTo = blendShapeNode.seamlessBaseMesh.vertices[tag]; // simply use tag since it should be identical to point index on seamless mesh // early out if the threshold test is not satisfied if ((targetMesh.vertices[j] - compareTo).sqrMagnitude < sqrMagThreshold) { continue; } vertices.Add(tag); deltaPos.Add(targetMesh.vertices[j] - compareTo); } target.vertices = new int[vertices.Count]; for (int j = 0; j < target.vertices.Length; j++) { target.vertices[j] = (int)vertices[j]; } target.deltaPositions = new Vector3[deltaPos.Count]; for (int j = 0; j < target.deltaPositions.Length; j++) { target.deltaPositions[j] = (Vector3)deltaPos[j]; } // copy the target to the BlendShape component blendShapeNode.targets[i] = target; // remove the target's assets GameObject.DestroyImmediate(targetMesh, true); GameObject.DestroyImmediate(targetModel, true); } // remove the tagged base mesh assets GameObject.DestroyImmediate(taggedBaseMesh, true); GameObject.DestroyImmediate(indexMap, true); // remove the seamless base mesh GameObject GameObject.DestroyImmediate(seamlessBaseModel, true); } }
void BuildBlendShapes() { blendShapes = new BlendShape[attributes.Length]; //For each attribute figure out which vertices are affected, then store their info in the blend shape object. for (int i = 0; i < attributes.Length; i++) { //Populate blendShapes array with new blend shapes blendShapes[i] = new BlendShape(); /** TODO: Make this a little more stylish! * UGLY hack to compensate the lack of dynamic arrays in C#. Feel free to improve! */ int blendShapeCounter = 0; for (int j = 0; j < workingMesh.vertexCount; j++) { if (workingMesh.vertices[j] != attributeMeshes[i].vertices[j]) { blendShapeCounter++; } } blendShapes[i].vertices = new BlendShapeVertex[blendShapeCounter]; blendShapeCounter = 0; for (int j = 0; j < workingMesh.vertexCount; j++) { //If the vertex is affected, populate a blend shape vertex with that info if (workingMesh.vertices[j] != attributeMeshes[i].vertices[j]) { //Create a blend shape vertex and populate its data. BlendShapeVertex blendShapeVertex = new BlendShapeVertex(); blendShapeVertex.originalIndex = j; blendShapeVertex.position = attributeMeshes[i].vertices[j] - workingMesh.vertices[j]; blendShapeVertex.normal = attributeMeshes[i].normals[j] - workingMesh.normals[j]; //Add new blend shape vertex to blendShape object. blendShapes[i].vertices[blendShapeCounter]=blendShapeVertex; blendShapeCounter++; } } //Convert blendShapes.vertices to builtin array //blendShapes[i].vertices = blendShapes[i].vertices.ToBuiltin(BlendShapeVertex); } }