public void OnDrawGizmosSelected()
    {
        if (debugDisplayMappedBoneGizmos)
        {
            Gizmos.color = Color.blue;
            for (int i = 0; i < bone2idxMap.Length; i++)
            {
                if (bone2idxMap[i].bone != null)
                {
                    BoneAndNode bn = bone2idxMap[i];
                    Gizmos.color = Color.blue;
                    Gizmos.DrawWireSphere(bn.bone.transform.position, .1f);
                }
            }
        }

        if (debugDisplayMappedAnchors)
        {
            Gizmos.color = Color.blue;
            for (int i = 0; i < anchors.Length; i++)
            {
                for (int j = 0; j < anchors[i].anchorNodeIndexes.Count; j++)
                {
                    Vector3 pos = transform.TransformPoint(anchors[i].anchorPosition[j]);
                    Gizmos.DrawWireSphere(pos, .1f);
                }
            }
        }
    }
    public void LateUpdate()
    {
        if (isInWorld)
        {
            //Read the positions of the bones from the physics simulation
            DumpDataFromBullet();

            //Update bone positions and orientaion based on bullet data
            for (int i = 0; i < bone2idxMap.Length; i++)
            {
                BoneAndNode bn = bone2idxMap[i];
                bn.bone.position = verts[bn.nodeIdx];

                //To update the orientation we need to see how the normal and one vertex moved
                //todo check magnitude and loop over edges if first doesn't work
                Vector3 edgeXnorm = Vector3.Cross(verts[bn.edges[0].nodeIdx] - verts[bn.nodeIdx], norms[bn.nodeIdx]);
                edgeXnorm.Normalize();

                Quaternion q = WahbasSolution(bn.bindNormal, bn.edges[0].bindEdgeXnorm, norms[bn.nodeIdx], edgeXnorm);

                bone2idxMap[i].bone.rotation = q * bn.bindBoneRotation;
            }

            if (debugDisplaySimulatedMesh)
            {
                if (myMesh == null)
                {
                    myMesh = Instantiate(physicsSimMesh.sharedMesh);
                    MeshFilter mf = physicsSimMesh.GetComponent <MeshFilter>();
                    mf.sharedMesh = myMesh;
                }

                if (localVerts == null || localVerts.Length != verts.Length)
                {
                    localVerts = new Vector3[verts.Length];
                    localNorms = new Vector3[norms.Length];
                }

                for (int i = 0; i < verts.Length; i++)
                {
                    localVerts[i] = physicsSimMesh.transform.InverseTransformPoint(verts[i]) + debugSimMeshOffset;
                    localNorms[i] = physicsSimMesh.transform.InverseTransformDirection(norms[i]);
                }

                myMesh.vertices = localVerts;
                myMesh.normals  = localNorms;
                myMesh.RecalculateBounds();
            }
        }
    }
    public void OnDrawGizmosSelected()
    {
        /*
         * for (int i = 0; i < bone2idxMap.Length; i++)
         * {
         *  if (i == 1 && verts != null && verts.Length > 0)
         *  {
         *      Gizmos.color = Color.magenta;
         *      for (int j = 0; j < bone2idxMap[i].edges.Length; j++)
         *      {
         *          Gizmos.DrawLine(verts[bone2idxMap[i].nodeIdx], verts[bone2idxMap[i].edges[j].nodeIdx]);
         *          Gizmos.color = Gizmos.color * .75f;
         *      }
         *  }
         * }
         */
        if (debugDisplayMappedBoneGizmos)
        {
            Gizmos.color = Color.blue;
            for (int i = 0; i < bone2idxMap.Length; i++)
            {
                if (bone2idxMap[i].bone != null)
                {
                    BoneAndNode bn = bone2idxMap[i];
                    Gizmos.color = Color.blue;
                    Gizmos.DrawWireSphere(bn.bone.transform.position, .1f);

                    /*
                     * Gizmos.DrawRay(bone2idxMap[i].bone.position, bone2idxMap[i].bindNormal);
                     * Gizmos.color = Color.magenta * .6f;
                     * Gizmos.DrawRay(bone2idxMap[i].bone.position, bone2idxMap[i].edges[0].bindEdgeXnorm);
                     * Gizmos.color = Color.green;
                     * Gizmos.DrawRay(bone2idxMap[i].bone.position, norms[bone2idxMap[i].nodeIdx]);
                     * Vector3 edgeXnorm = Vector3.Cross(verts[bn.edges[0].nodeIdx] - verts[bn.nodeIdx], norms[bn.nodeIdx]);
                     * edgeXnorm.Normalize();
                     * Gizmos.color = Color.green * .6f;
                     * Gizmos.DrawRay(bone2idxMap[i].bone.position, edgeXnorm);
                     */
                    /*
                     * Gizmos.color = Color.red;
                     * Gizmos.DrawRay(bone2idxMap[i].bone.position, bone2idxMap[i].bone.right);
                     * Gizmos.color = Color.green;
                     * Gizmos.DrawRay(bone2idxMap[i].bone.position, bone2idxMap[i].bone.up);
                     * Gizmos.color = Color.blue;
                     * Gizmos.DrawRay(bone2idxMap[i].bone.position, bone2idxMap[i].bone.forward);
                     *
                     * Gizmos.color = Color.red * .6f;
                     * Gizmos.DrawRay(bone2idxMap[i].bone.position, bone2idxMap[i].bindBoneRotation * Vector3.forward);
                     * Gizmos.color = Color.green * .6f; ;
                     * Gizmos.DrawRay(bone2idxMap[i].bone.position, bone2idxMap[i].bindBoneRotation * Vector3.up);
                     * Gizmos.color = Color.blue * .6f;
                     * Gizmos.DrawRay(bone2idxMap[i].bone.position, bone2idxMap[i].bindBoneRotation * Vector3.right);
                     */
                }
            }
        }
        if (debugDisplayMappedAnchors)
        {
            Gizmos.color = Color.blue;
            for (int i = 0; i < anchors.Length; i++)
            {
                for (int j = 0; j < anchors[i].anchorNodeIndexes.Count; j++)
                {
                    Vector3 pos = transform.TransformPoint(anchors[i].anchorPosition[j]);
                    Gizmos.DrawWireSphere(pos, .1f);
                }
            }
        }
    }
    // Use this for initialization
    public void BindBonesToSoftBodyAndNodesToAnchors()
    {
        if (transform.localScale != Vector3.one)
        {
            Debug.LogError("The scale must be 1,1,1");
            return;
        }

        if (skinnedMesh == null)
        {
            Debug.LogError("The Skinned Mesh field has not been assigned.");
            return;
        }

        physicsSimMesh = GetComponent <MeshFilter>();
        if (physicsSimMesh == null)
        {
            Debug.LogError("Must be attached to an object with a MeshRenderer");
            return;
        }

        if (physicsSimMesh == null)
        {
            Debug.LogError("must add the physics sim mesh bone");
            return;
        }

        for (int i = 0; i < anchors.Length; i++)
        {
            BAnchor a = anchors[i];
            if (a.colRangeTo <= a.colRangeFrom)
            {
                Debug.LogError("Error with Anchor row " + i + " ColRangeTo must be greater than colRangeFrom.");
            }
            for (int j = i + 1; j < anchors.Length; j++)
            {
                BAnchor b = anchors[j];
                if (b.colRangeFrom >= a.colRangeTo && b.colRangeTo >= a.colRangeTo)
                {
                    //good
                }
                else if (b.colRangeFrom <= a.colRangeFrom && b.colRangeTo <= a.colRangeFrom)
                {
                    //good
                }
                else
                {
                    Debug.LogErrorFormat("The color ranges of Anchors {0} and {1} overlap", i, j);
                }
            }
        }
        //get bones and mesh verts
        //compare these in world space to see which ones line up
        //TODO why does other mesh shape work better than this one.
        Transform[] bones = skinnedMesh.bones;
        Mesh        m     = physicsSimMesh.sharedMesh;

        Vector3[] verts     = m.vertices;
        Vector3[] norms     = m.normals;
        Color[]   cols      = m.colors;
        int[]     triangles = m.triangles;
        if (cols.Length != verts.Length)
        {
            Debug.LogError("The physics sim mesh had no colors. Colors are needed to identify the anchor bones.");
        }
        //check for duplicate verts
        int numDuplicated = 0;

        for (int i = 0; i < verts.Length; i++)
        {
            for (int j = i + 1; j < verts.Length; j++)
            {
                if (verts[i] == verts[j])
                {
                    numDuplicated++;
                }
            }
        }
        if (numDuplicated > 0)
        {
            Debug.LogError("The physics sim mesh has " + numDuplicated + " duplicated vertices. Check that the mesh does not have hard edges and that there are no UVs.");
        }

        List <BoneAndNode> foundMatches = new List <BoneAndNode>();

        for (int i = 0; i < verts.Length; i++)
        {
            for (int j = 0; j < bones.Length; j++)
            {
                Vector3 worldSpaceVert = physicsSimMesh.transform.TransformPoint(verts[i]);
                Vector3 worldSpaceBone = bones[j].position;
                if (Vector3.Distance(worldSpaceBone, worldSpaceVert) < radius)
                {
                    //Debug.Log("found a bone that is aligned with a vertex " + bones[j]);
                    BoneAndNode ban = new BoneAndNode();
                    ban.bone    = bones[j];
                    ban.nodeIdx = i;
                    foundMatches.Add(ban);
                }
            }
        }
        bone2idxMap = foundMatches.ToArray();
        for (int i = 0; i < bone2idxMap.Length; i++)
        {
            int         idx   = bone2idxMap[i].nodeIdx;
            List <Edge> edges = new List <Edge>();
            for (int j = 0; j < triangles.Length; j += 3)
            {
                if (triangles[j] == idx)
                {
                    _addEdges(idx, triangles[j + 1], triangles[j + 2], edges, norms, verts);
                }
                else if (triangles[j + 1] == idx)
                {
                    _addEdges(idx, triangles[j], triangles[j + 2], edges, norms, verts);
                }
                else if (triangles[j + 2] == idx)
                {
                    _addEdges(idx, triangles[j], triangles[j + 1], edges, norms, verts);
                }
            }
            edges.Sort();
            bone2idxMap[i].edges = edges.ToArray();
        }
        // clear old values
        for (int j = 0; j < anchors.Length; j++)
        {
            anchors[j].anchorNodeIndexes.Clear();
            anchors[j].anchorNodeStrength.Clear();
            anchors[j].anchorPosition.Clear();
        }

        int numAnchorNodes = 0;

        for (int i = 0; i < cols.Length; i++)
        {
            for (int j = 0; j < anchors.Length; j++)
            {
                if (cols[i].g > anchors[j].colRangeFrom &&
                    cols[i].g < anchors[j].colRangeTo)
                {
                    anchors[j].anchorNodeIndexes.Add(i);
                    anchors[j].anchorNodeStrength.Add(cols[i].r);
                    anchors[j].anchorPosition.Add(verts[i]);
                    numAnchorNodes++;
                }
            }
        }

        SoftBody sb = (SoftBody)m_collisionObject;

        Debug.LogFormat("Done binding bones to nodes and nodes to anchors. Found: {0} bones and {1} anchor nodes.", bone2idxMap.Length, numAnchorNodes);
    }