public void LateUpdate()
        {
//			if (mpb==null) {
//				mpb = new MaterialPropertyBlock ();
//				mpb.AddColor("_Color",color);
//			}

            if (mesh != null)
            {
                //if the sim changes data topology
                if (this.particleNumCache != sim.numberOfParticles() || this.stringNumCache != sim.numberOfSprings())
                {
                    //Debug.Log(this.particleNumCache);
                    //Debug.Log(sim.numberOfParticles());
                    mesh.Clear();
                    CreateMesh();
                    this.particleNumCache = sim.numberOfParticles();
                    this.stringNumCache   = sim.numberOfSprings();
                }
                else
                {
                    if (sim.numberOfParticles() > 2)
                    {
                        if (Application.isPlaying)
                        {
                            mesh.vertices = sim.getVerticesNonAlloc();
                        }
                        else
                        {
                            mesh.vertices = sim.getVertices();
                        }
                        mesh.RecalculateBounds();
                    }
                    //
                    else
                    {
                    }
                }
            }
            else
            {
                mesh = new Mesh();
                CreateMesh();
                this.meshFilter.sharedMesh = this.mesh;
                this.particleNumCache      = sim.numberOfParticles();
                this.stringNumCache        = sim.numberOfSprings();
            }

            if (color != colorCache)
            {
                SetColor(color);
                colorCache = color;
            }
        }
        //called by editor script to set up data
        public void MeshLineRender_Ctor()
        {
            this.sim = this.GetComponent <IFormLayer>().GetSimulation;
            this.particleNumCache = sim.numberOfParticles();
            this.stringNumCache   = sim.numberOfSprings();

            meshRenderer = this.GetComponent <MeshRenderer>();
            if (meshRenderer == null)
            {
                meshRenderer = this.gameObject.AddComponent <MeshRenderer>();
            }
            meshRenderer.receiveShadows       = false;
            meshRenderer.shadowCastingMode    = UnityEngine.Rendering.ShadowCastingMode.Off;
            meshRenderer.useLightProbes       = false;
            meshRenderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;
            meshRenderer.sharedMaterial       = Mtl;
            meshRenderer.hideFlags            = HideFlags.HideInInspector;

            mpb = new MaterialPropertyBlock();
            meshRenderer.GetPropertyBlock(mpb);
            mpb.SetColor("_Color", color);
            meshRenderer.SetPropertyBlock(mpb);
            colorCache = color;

            if (mesh == null)
            {
                mesh = new Mesh();
                CreateMesh();
                this.particleNumCache = sim.numberOfParticles();
                this.stringNumCache   = sim.numberOfSprings();
            }

            meshFilter = this.GetComponent <MeshFilter>();
            if (meshFilter == null)
            {
                meshFilter = this.gameObject.AddComponent <MeshFilter>();
            }
            meshFilter.sharedMesh = mesh;
            meshFilter.hideFlags  = HideFlags.HideInInspector;
        }
        public SimBuffer_Spring(Simulation sim, Vector2[] particleUV, int width, int height)
        {
            this.sim = sim;
            rt       = new RenderTexture[sim.maxSpringConvergenceID];
            int parNum = sim.numberOfParticles();

            ID_SpringParamRT  = Shader.PropertyToID("_SpringParamRT");
            ID_SpringConstant = Shader.PropertyToID("_SpringConstant");
            ID_PositionRT     = Shader.PropertyToID("_PositionRT");

            //rg = the other end point's uv, b = restlength, a = state
            Color[]   tempColor = new Color[width * height];
            Texture2D tempTex   = new Texture2D(width, height, TextureFormat.RGBAFloat, false, false);

            for (int i = 0; i < sim.maxSpringConvergenceID; i++)
            {
                //init rt
                rt[i] = new RenderTexture(width, height, 0, RTFormat.ARGB);
                rt[i].Create();

                //prepare temp color
                for (int k = 0; k < width * height; k++)
                {
                    if (k < parNum)
                    {
                        Vector2 uv = particleUV[k];
                        tempColor[k] = new Color(uv.x, uv.y, 1f, (sim.getParticle(k).IsFree) ? 1f : 0f);
                    }
                    else
                    {
                        tempColor[k] = new Color(0f, 0f, 1f, 0f);
                    }
                }

                //get info
                for (int j = 0; j < sim.numberOfSprings(); j++)
                {
                    Spring2D sp = sim.getSpring(j);
                    if (sp.convergenceGroupID == i + 1)
                    {
                        int a = sim.getParticleIndex(sp.ParticleA);
                        int b = sim.getParticleIndex(sp.ParticleB);
                        tempColor[a].r = particleUV[b].x;
                        tempColor[a].g = particleUV[b].y;
                        tempColor[a].b = sp.restLength2;
                        tempColor[a].a = (sp.ParticleA.IsFree) ? 1f : 0f;
                        tempColor[b].r = particleUV[a].x;
                        tempColor[b].g = particleUV[a].y;
                        tempColor[b].b = sp.restLength2;
                        tempColor[b].a = (sp.ParticleB.IsFree) ? 1f : 0f;
                    }
                }

                //blit
                tempTex.SetPixels(tempColor);
                tempTex.Apply();
                Graphics.Blit(tempTex, rt[i]);
            }

            Extension.ObjDestroy(tempTex);

            //mpb
            mpb = new MaterialPropertyBlock[sim.maxSpringConvergenceID];
            for (int i = 0; i < sim.maxSpringConvergenceID; i++)
            {
                mpb[i] = new MaterialPropertyBlock();
                mpb[i].SetTexture(ID_SpringParamRT, rt[i]);
                mpb[i].SetFloat(ID_SpringConstant, sim.Settings.springConstant);
            }

            //tempRT
            tempRT = new RenderTexture[sim.maxSpringConvergenceID - 1];
        }