private bool AddBlendShape( string targetShapeName, string sourceShapeName, float magnitudeScale, float yScale, bool keepLeft, bool keepRight, bool keepUpward, bool keepDownward, ScaleNormalization scaleNormalization, int onlyIncludeThisSubmesh, int onlyExcludeThisSubmesh) { if (mesh.GetBlendShapeIndex(targetShapeName) >= 0) { // Blend shape already exists. Don't try to add it again. return(false); } Vector3[] deltaVertices = new Vector3[mesh.vertexCount]; Vector3[] deltaNormals = new Vector3[mesh.vertexCount]; Vector3[] deltaTangents = new Vector3[mesh.vertexCount]; // Find the source shape index. int shapeIndex = FindShapeIndex(sourceShapeName); if (shapeIndex < 0) { // Failed to find the source shape. return(false); } // Copy across the keyframes in the blendshape (most have 1 keyframe). int frameCount = mesh.GetBlendShapeFrameCount(shapeIndex); for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float frameWeight = mesh.GetBlendShapeFrameWeight(shapeIndex, frameIndex); mesh.GetBlendShapeFrameVertices(shapeIndex, frameIndex, deltaVertices, deltaNormals, deltaTangents); AdjustBlendShape(deltaVertices, deltaNormals, deltaTangents, magnitudeScale, yScale, keepLeft, keepRight, keepUpward, keepDownward, scaleNormalization, onlyIncludeThisSubmesh, onlyExcludeThisSubmesh); mesh.AddBlendShapeFrame(targetShapeName, frameWeight, deltaVertices, deltaNormals, deltaTangents); } return(true); }
private void AdjustBlendShape( Vector3[] deltaVertices, Vector3[] deltaNormals, Vector3[] deltaTangents, float magnitudeScale, float yScale, bool keepLeft, bool keepRight, bool keepUpward, bool keepDownward, ScaleNormalization scaleNormalization, int onlyIncludeThisSubmesh, int onlyExcludeThisSubmesh) { Vector3[] vertices = mesh.vertices; Bounds bounds = mesh.bounds; float minX = bounds.center.x - bounds.extents.x; float maxX = bounds.center.x + bounds.extents.x; for (int i = 0; i < mesh.vertexCount; i++) { Vector3 v = vertices[i]; Debug.Log("v=" + V3ToString(v) + " dv=" + V3ToString(deltaVertices[i])); bool zeroIt = false; if (v.x > 0.0f && !keepRight) { zeroIt = true; Debug.Log("ZA"); } if (v.x < 0.0f && !keepLeft) { zeroIt = true; Debug.Log("ZB"); } if (deltaVertices[i].y > 0.0f && !keepUpward) { zeroIt = true; Debug.Log("ZC"); } if (deltaVertices[i].y < 0.0f && !keepDownward) { zeroIt = true; Debug.Log("ZD"); } if (zeroIt) { deltaVertices[i] = Vector3.zero; deltaNormals[i] = Vector3.zero; deltaTangents[i] = Vector3.zero; } else { Debug.Log("KEEP"); // Adjust the scaling factor based on position on face. float scaleFactor = magnitudeScale; switch (scaleNormalization) { case ScaleNormalization.LeftToRight: { float localScale = (v.x - minX) / (maxX - minX); Debug.Log("1.v.x=" + v.x + ", minX=" + minX + ", maxX=" + maxX + ", lscale=" + localScale); if (localScale < 0.0f) { localScale = 0.0f; } if (localScale > 1.0f) { localScale = 1.0f; } scaleFactor *= localScale; break; } case ScaleNormalization.RightToLeft: { float localScale = (v.x - minX) / (maxX - minX); Debug.Log("2.v.x=" + v.x + ", minX=" + minX + ", maxX=" + maxX + ", lscale=" + localScale); if (localScale < 0.0f) { localScale = 0.0f; } if (localScale > 1.0f) { localScale = 1.0f; } scaleFactor *= (1.0f - localScale); break; } case ScaleNormalization.ZeroAtCenter: { float localScale = v.x / (maxX / 4.0f); Debug.Log("localScale = " + localScale); Debug.Log("2.v.x=" + v.x + ", minX=" + minX + ", maxX=" + maxX + ", lscale=" + localScale); if (localScale < 0.0f) { localScale = -localScale; } if (localScale > 1.0f) { localScale = 1.0f; } Debug.Log("final localScale = " + localScale); scaleFactor *= localScale; Debug.Log("scaleFactor= " + scaleFactor); break; } } // Multiply in magnitude scale. deltaVertices[i] *= scaleFactor; deltaNormals[i] *= scaleFactor; deltaTangents[i] *= scaleFactor; // Multiple in Y scale (e.g. scale = -1 to invert) deltaVertices[i].y *= yScale; deltaNormals[i].y *= yScale; deltaTangents[i].y *= yScale; } } if (onlyIncludeThisSubmesh >= 0) { // Set everything to zero not in requested submesh UnityEngine.Rendering.SubMeshDescriptor smd = mesh.GetSubMesh(onlyIncludeThisSubmesh); for (int i = 0; i < smd.firstVertex; i++) { deltaVertices[i] = Vector3.zero; deltaNormals[i] = Vector3.zero; deltaTangents[i] = Vector3.zero; } for (int i = smd.firstVertex + smd.vertexCount; i < mesh.vertexCount; i++) { deltaVertices[i] = Vector3.zero; deltaNormals[i] = Vector3.zero; deltaTangents[i] = Vector3.zero; } } if (onlyExcludeThisSubmesh >= 0) { // Set everything to zero in requested submesh UnityEngine.Rendering.SubMeshDescriptor smd = mesh.GetSubMesh(onlyExcludeThisSubmesh); for (int i = smd.firstVertex; i < smd.firstVertex + smd.vertexCount; i++) { deltaVertices[i] = Vector3.zero; deltaNormals[i] = Vector3.zero; deltaTangents[i] = Vector3.zero; } } }