Exemple #1
0
            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();
        }
    }
Exemple #3
0
        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();
    }
Exemple #5
0
        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);
            }
        }
Exemple #6
0
 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);
        }
    }
Exemple #11
0
        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;
    }
Exemple #19
0
        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);
        }
Exemple #20
0
    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);
        }
    }
Exemple #21
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);
            });
        }
Exemple #23
0
 /// <summary>
 /// Initialize
 /// </summary>
 void OnEnable()
 {
     blendShape = (BlendShape)target;
 }
Exemple #24
0
        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);
            }
        }
Exemple #25
0
        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);
        }
Exemple #26
0
	/// <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 创建完成!");
        }
    }
Exemple #29
0
                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);
 }
Exemple #31
0
 public BlendShapeReceivedEventArgs(BlendShape shape, float value)
 {
     Shape = shape;
     Value = value;
 }
Exemple #32
0
                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);
                                }
                            }
                        }
                    }
                }
Exemple #33
0
    /// <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);
        }
    }