public virtual void Update()
        {
            base.begin_update();

            if (MeshSource == null)
            {
                throw new Exception("MeshVertexDisplacementOp: must set valid MeshSource to compute!");
            }
            if (DisplacementSource == null)
            {
                throw new Exception("MeshVertexDisplacementOp: must set valid DisplacementSource to compute!");
            }

            DMesh3 meshIn = MeshSource.GetDMeshUnsafe();
            IVectorDisplacement displace = DisplacementSource.GetDisplacement();

            if (displace.Count != 0 && displace.Count != meshIn.MaxVertexID)
            {
                throw new Exception("MeshVertexDisplacementOp: inconsistent counts " + displace.Count.ToString() + " != " + meshIn.MaxVertexID.ToString());
            }

            DMesh3 mesh = new DMesh3(meshIn, MeshHints.None);

            //if (!mesh.HasVertexNormals)
            //    MeshNormals.QuickCompute(mesh);
            if (displace.Count > 0)
            {
                gParallel.ForEach(mesh.VertexIndices(), (vid) => {
                    Vector3d dv = displace.GetDisplacementForIndex(vid);

                    //Vector3f n = mesh.GetVertexNormal(vid);
                    Vector3d v = mesh.GetVertex(vid);

                    v += dv;

                    mesh.SetVertex(vid, v);
                });

                if (enable_heat_map)
                {
                    // compute max displace len
                    ColorMap map = new ColorMap();
                    map.AddPoint(0, Colorf.CornflowerBlue);
                    float d = (float)HeatMapMaxDistance;
                    map.AddPoint(d, Colorf.Orange);
                    map.AddPoint(2 * d, Colorf.VideoYellow);
                    map.AddPoint(4 * d, Colorf.VideoRed);
                    map.AddPoint(-d, Colorf.VideoMagenta);

                    float max_displace = d;
                    gParallel.ForEach(mesh.VertexIndices(), (vid) => {
                        Vector3f dv = (Vector3f)displace.GetDisplacementForIndex(vid);

                        Vector3f n = mesh.GetVertexNormal(vid);
                        float sign = n.Dot(dv) > 0 ? 1 : -1;

                        Colorf c = map.Linear(dv.Length * sign);

                        Colorf existing_c   = mesh.GetVertexColor(vid);
                        float preserve__max = max_displace / 2;
                        float t             = MathUtil.Clamp(dv.Length / preserve__max, 0.0f, 1.0f);
                        c = (1.0f - t) * existing_c + (t) * c;

                        mesh.SetVertexColor(vid, c);

                        //float t = MathUtil.Clamp(dv.Length / max_displace, -1.0f, 1.0f);
                        //mesh.SetVertexColor(vid, t * Colorf.Orange);
                    });
                }
            }

            MeshNormals.QuickCompute(mesh);

            DisplacedMesh = mesh;
            base.complete_update();
        }