private static Material CreateMaterial(IMeshSampler sampler, VertexTex vtex,
                                               Texture2D posTex = null, Texture2D normTex = null, Renderer renderer = null)
        {
            Material mat = new Material(Shader.Find(ShaderConst.SHADER_NAME));

            if (renderer != null && renderer.sharedMaterial != null)
            {
                mat.mainTexture = renderer.sharedMaterial.mainTexture;
            }
            if (posTex != null)
            {
                mat.SetTexture(ShaderConst.SHADER_ANIM_TEX, posTex);
            }
            mat.SetVector(ShaderConst.SHADER_SCALE, vtex.scale);
            mat.SetVector(ShaderConst.SHADER_OFFSET, vtex.offset);
            mat.SetVector(ShaderConst.SHADER_ANIM_END, new Vector4(sampler.Length, vtex.verticesList.Count - 1, 0f, 0f));
            mat.SetFloat(ShaderConst.SHADER_FPS, FPS);
            if (normTex != null)
            {
                mat.SetTexture(ShaderConst.SHADER_NORM_TEX, normTex);
            }
            return(mat);
        }
        public VertexTex(IMeshSampler sample)
        {
            verticesList = new List <Vector3[]> ();
            normalsList  = new List <Vector3[]> ();
            for (float t = 0; t < (sample.Length + DT); t += DT)
            {
                var combinedMesh = sample.Sample(t);
                verticesList.Add(combinedMesh.vertices);
                normalsList.Add(combinedMesh.normals);
            }

            var firstVertices = verticesList[0];
            var firstVertex   = firstVertices[0];
            var vertexCount   = firstVertices.Length;

            frameEnd = vertexCount - 1;

            var minX = firstVertex.x;
            var minY = firstVertex.y;
            var minZ = firstVertex.z;
            var maxX = firstVertex.x;
            var maxY = firstVertex.y;
            var maxZ = firstVertex.z;

            foreach (var vertices in verticesList)
            {
                for (var i = 0; i < vertices.Length; i++)
                {
                    var v = vertices [i];
                    minX = Mathf.Min(minX, v.x);
                    minY = Mathf.Min(minY, v.y);
                    minZ = Mathf.Min(minZ, v.z);
                    maxX = Mathf.Max(maxX, v.x);
                    maxY = Mathf.Max(maxY, v.y);
                    maxZ = Mathf.Max(maxZ, v.z);
                }
            }
            scale  = new Vector4(maxX - minX, maxY - minY, maxZ - minZ, 1f);
            offset = new Vector4(minX, minY, minZ, 1f);
            Debug.LogFormat("Scale={0} Offset={1}", scale, offset);

            var texWidth  = LargerInPow2(vertexCount);
            var texHeight = LargerInPow2(verticesList.Count * 2);

            Debug.Log(string.Format("tex({0}x{1}), nVertices={2} nFrames={3}", texWidth, texHeight, vertexCount, verticesList.Count));

            positionTex            = new Texture2D(texWidth, texHeight, TextureFormat.RGB24, false, true);
            positionTex.filterMode = ANIM_TEX_FILTER;
            positionTex.wrapMode   = TextureWrapMode.Clamp;

            normalTex            = new Texture2D(texWidth, texHeight, TextureFormat.RGB24, false, true);
            normalTex.filterMode = ANIM_TEX_FILTER;
            normalTex.wrapMode   = TextureWrapMode.Clamp;

            uv2 = new Vector2[vertexCount];
            var texSize       = new Vector2(1f / texWidth, 1f / texHeight);
            var halfTexOffset = 0.5f * texSize;

            for (int i = 0; i < uv2.Length; i++)
            {
                uv2 [i] = new Vector2((float)i * texSize.x, 0f) + halfTexOffset;
            }
            for (int y = 0; y < verticesList.Count; y++)
            {
                Vector3[] vertices = verticesList [y];
                Vector3[] normals  = normalsList [y];
                for (int x = 0; x < vertices.Length; x++)
                {
                    var   pos = Normalize(vertices [x], offset, scale);
                    Color c0, c1;
                    Encode(pos, out c0, out c1);
                    positionTex.SetPixel(x, y, c0);
                    positionTex.SetPixel(x, y + (texHeight >> 1), c1);

                    var normal = 0.5f * (normals [x].normalized + Vector3.one);
                    Encode(normal, out c0, out c1);
                    normalTex.SetPixel(x, y, c0);
                    normalTex.SetPixel(x, y + (texHeight >> 1), c1);
                }
            }
            positionTex.Apply();
            normalTex.Apply();
        }