public void BuildMesh(ref TrainerCritterBrushstrokeManager trainerCritterBrushstrokeManagerRef)
    {
        float startTime = Time.realtimeSinceStartup;

        // NOISE VOLUME!
        RenderTexture DensityVolume = new RenderTexture(16, 16, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.sRGB);

        DensityVolume.volumeDepth       = 16;
        DensityVolume.isVolume          = true;
        DensityVolume.enableRandomWrite = true;
        DensityVolume.filterMode        = FilterMode.Bilinear;
        DensityVolume.wrapMode          = TextureWrapMode.Repeat;
        DensityVolume.Create();
        int mgen_id = CShaderSimplex.FindKernel("FillEmpty");

        // uses renderTexture rather than StructuredBuffer?
        CShaderSimplex.SetTexture(mgen_id, "Result", DensityVolume); // Links RenderTexture to the "Result" RWTexture in the compute shader?
        CShaderSimplex.Dispatch(mgen_id, 1, 1, 16);                  // run computeShader "FillEmpty" with 1 x 1 x 31 threadGroups?
        mgen_id = CShaderSimplex.FindKernel("Simplex3d");
        CShaderSimplex.SetTexture(mgen_id, "Result", DensityVolume);
        CShaderSimplex.Dispatch(mgen_id, 1, 1, 16);  // Fill shared RenderTexture with GPU simplex Noise

        ComputeBuffer cBufferSegmentTransform = new ComputeBuffer(critterSegmentTransforms.Length, sizeof(float) * (3 + 3 + 4));

        cBufferSegmentTransform.SetData(critterSegmentTransforms);
        int kernelID = CShaderBuildMC.FindKernel("CSMain");

        CShaderBuildMC.SetBuffer(kernelID, "segmentTransformBuffer", cBufferSegmentTransform);
        CShaderBuildMC.SetTexture(kernelID, "noise_volume", DensityVolume);  // Noise 3D texture

        // Figure out how many chunks are needed:
        int numChunksX = Mathf.CeilToInt(GlobalBoundingBoxDimensions.x / (cellResolution * 8f));
        int numChunksY = Mathf.CeilToInt(GlobalBoundingBoxDimensions.y / (cellResolution * 8f));
        int numChunksZ = Mathf.CeilToInt(GlobalBoundingBoxDimensions.z / (cellResolution * 8f));
        //Debug.Log("numChunks: (" + numChunksX.ToString() + ", " + numChunksY.ToString() + ", " + numChunksZ.ToString() + ")");

        int totalNumChunks = numChunksX * numChunksY * numChunksZ;

        Poly[][] PolyArrayArray = new Poly[totalNumChunks][];  // This will hold the mesh data from the chunks calculated on the GPU
        int[]    numPolysArray  = new int[totalNumChunks];
        int      totalNumPolys  = 0;

        // Get each chunk!
        int chunkIndex = 0;

        for (int x = 0; x < numChunksX; x++)
        {
            for (int y = 0; y < numChunksY; y++)
            {
                for (int z = 0; z < numChunksZ; z++)
                {
                    // Figure out chunk offset amount:
                    Vector3 chunkOffset = new Vector3(cellResolution * 8f * x, cellResolution * 8f * y, cellResolution * 8f * z) + GlobalBoundingBoxOffset - (GlobalBoundingBoxDimensions / 2f);

                    int[]         numPolys       = new int[1];
                    ComputeBuffer cBufferNumPoly = new ComputeBuffer(1, sizeof(int));
                    cBufferNumPoly.SetData(numPolys);

                    int id = CShaderBuildMC.FindKernel("CSMain");
                    CShaderBuildMC.SetInt("_CalcNumPolys", 1); // only calculate how many tris so I can correctly size the poly buffer
                    CShaderBuildMC.SetFloat("_GlobalOffsetX", chunkOffset.x);
                    CShaderBuildMC.SetFloat("_GlobalOffsetY", chunkOffset.y);
                    CShaderBuildMC.SetFloat("_GlobalOffsetZ", chunkOffset.z);
                    CShaderBuildMC.SetFloat("_CellSize", cellResolution);
                    CShaderBuildMC.SetVector("_ColorPrimary", colorPrimary);
                    CShaderBuildMC.SetVector("_ColorSecondary", colorSecondary);
                    CShaderBuildMC.SetFloat("_ColorNoiseScale", colorNoiseScale);
                    CShaderBuildMC.SetFloat("_ColorSmlAmplitude", colorSmlAmplitude);
                    CShaderBuildMC.SetFloat("_ColorMedAmplitude", colorMedAmplitude);
                    CShaderBuildMC.SetFloat("_ColorLrgAmplitude", colorLrgAmplitude);
                    CShaderBuildMC.SetFloat("_ColorContrast", colorContrast);
                    CShaderBuildMC.SetFloat("_ColorThreshold", colorThreshold);
                    CShaderBuildMC.SetVector("_SkinNoiseScale", skinNoiseScale);
                    CShaderBuildMC.SetFloat("_SkinNoiseAmplitude", skinNoiseAmplitude);
                    CShaderBuildMC.SetVector("_SkinLocalTaper", skinLocalTaper);
                    CShaderBuildMC.SetVector("_SkinLocalSinFreq", skinLocalSinFreq);
                    CShaderBuildMC.SetVector("_SkinLocalSinAmp", skinLocalSinAmp);
                    // Local Segment-space modifications, sin, taper, etc.

                    CShaderBuildMC.SetBuffer(id, "numPolyBuffer", cBufferNumPoly);
                    CShaderBuildMC.Dispatch(id, 1, 1, 1); // calc num polys
                    cBufferNumPoly.GetData(numPolys);     // get numPolys
                    //Debug.Log("Chunk: " + (z + (numChunksZ * y) + (numChunksZ * numChunksY * x)).ToString() + ", cBufferNumPoly.GetData(numPolys): " + numPolys[0].ToString() + ", chunkOffset: " + chunkOffset.ToString());
                    totalNumPolys            += numPolys[0];
                    numPolysArray[chunkIndex] = numPolys[0];

                    if (numPolys[0] > 0)     // only do this if there was at least 1 triangle in the test pass
                    {
                        Poly[]        polyArray     = new Poly[numPolys[0]];
                        int           cBufferStride = sizeof(float) * (18 + 9 + 6) + sizeof(int) * (6);
                        ComputeBuffer cBuffer       = new ComputeBuffer(numPolys[0], cBufferStride); // 18 floats x 4 bytes/float = 72   + COLORS! 9 x 4 = 36  = 108   + BONES! 6x4 = 24 + 6 xint...
                        cBuffer.SetData(polyArray);

                        CShaderBuildMC.SetBuffer(id, "buffer", cBuffer);
                        CShaderBuildMC.SetInt("_CalcNumPolys", 0); // Actually calc tris
                        CShaderBuildMC.Dispatch(id, 1, 1, 1);
                        cBuffer.GetData(polyArray);                // return data from GPU

                        PolyArrayArray[chunkIndex] = polyArray;
                        cBuffer.Dispose();
                    }

                    cBufferNumPoly.Dispose();

                    chunkIndex++;
                }
            }
        }

        // OLD: // CritterDecorationsTest.decorationStruct[] points = new CritterDecorationsTest.decorationStruct[totalNumPolys];
        critterPointsDataArray = new TrainerRenderManager.strokeStruct[totalNumPolys];  // first try brushstrokes

        //Construct mesh using received data
        int vindex   = 0;
        int decindex = 0;

        // Why same number of tris as vertices?  == // because all triangles have duplicate verts - no shared vertices?
        Vector3[]    vertices = new Vector3[totalNumPolys * 3];
        Color[]      colors   = new Color[totalNumPolys * 3];
        int[]        tris     = new int[totalNumPolys * 3];
        Vector2[]    uvs      = new Vector2[totalNumPolys * 3];
        Vector3[]    normals  = new Vector3[totalNumPolys * 3];
        BoneWeight[] weights  = new BoneWeight[totalNumPolys * 3];

        //Parse triangles
        for (int i = 0; i < PolyArrayArray.Length; i++)
        {
            if (numPolysArray[i] > 0)    // only do this if there was at least 1 triangle in the test pass
            {
                for (int ix = 0; ix < numPolysArray[i]; ix++)
                {
                    Vector3 vPos;
                    Vector3 vOffset = new Vector3(0, 0, 0);   //???  offsets all vertices by this amount, but why 30??
                                                              //A1,A2,A3
                    vPos                       = new Vector3(PolyArrayArray[i][ix].A1, PolyArrayArray[i][ix].A2, PolyArrayArray[i][ix].A3) + vOffset;
                    vertices[vindex]           = vPos * _Scale;
                    normals[vindex]            = new Vector3(PolyArrayArray[i][ix].NA1, PolyArrayArray[i][ix].NA2, PolyArrayArray[i][ix].NA3);
                    tris[vindex]               = vindex;
                    uvs[vindex]                = new Vector2(vertices[vindex].z, vertices[vindex].x);
                    colors[vindex]             = new Color(PolyArrayArray[i][ix].CAR, PolyArrayArray[i][ix].CAG, PolyArrayArray[i][ix].CAB, 1.0f);
                    weights[vindex].boneIndex0 = PolyArrayArray[i][ix].BoneIndexA0;
                    weights[vindex].boneIndex1 = PolyArrayArray[i][ix].BoneIndexA1;
                    weights[vindex].weight0    = PolyArrayArray[i][ix].BoneWeightA0;
                    weights[vindex].weight1    = PolyArrayArray[i][ix].BoneWeightA1;

                    critterPointsDataArray[decindex].pos    = vPos;
                    critterPointsDataArray[decindex].col    = new Vector3(colors[vindex].r, colors[vindex].g, colors[vindex].b);
                    critterPointsDataArray[decindex].normal = normals[vindex];
                    //critterPointsDataArray[decindex].tangent = ;  // Tangent is calculated during initial Skinning (when determining weights)
                    critterPointsDataArray[decindex].prevPos    = vPos;
                    critterPointsDataArray[decindex].dimensions = new Vector2(1f, 1f);
                    critterPointsDataArray[decindex].brushType  = 0; // default
                    // OLD:
                    //points[decindex].pos = vPos;
                    //points[decindex].normal = normals[vindex];
                    //points[decindex].color = new Vector3(colors[vindex].r, colors[vindex].g, colors[vindex].b);

                    decindex++;
                    vindex++;

                    //B1,B2,B3
                    vPos                       = new Vector3(PolyArrayArray[i][ix].B1, PolyArrayArray[i][ix].B2, PolyArrayArray[i][ix].B3) + vOffset;
                    vertices[vindex]           = vPos * _Scale;
                    normals[vindex]            = new Vector3(PolyArrayArray[i][ix].NB1, PolyArrayArray[i][ix].NB2, PolyArrayArray[i][ix].NB3);
                    tris[vindex]               = vindex;
                    uvs[vindex]                = new Vector2(vertices[vindex].z, vertices[vindex].x);
                    colors[vindex]             = new Color(PolyArrayArray[i][ix].CBR, PolyArrayArray[i][ix].CBG, PolyArrayArray[i][ix].CBB, 1.0f);
                    weights[vindex].boneIndex0 = PolyArrayArray[i][ix].BoneIndexB0;
                    weights[vindex].boneIndex1 = PolyArrayArray[i][ix].BoneIndexB1;
                    weights[vindex].weight0    = PolyArrayArray[i][ix].BoneWeightB0;
                    weights[vindex].weight1    = PolyArrayArray[i][ix].BoneWeightB1;

                    vindex++;

                    //C1,C2,C3
                    vPos                       = new Vector3(PolyArrayArray[i][ix].C1, PolyArrayArray[i][ix].C2, PolyArrayArray[i][ix].C3) + vOffset;
                    vertices[vindex]           = vPos * _Scale;
                    normals[vindex]            = new Vector3(PolyArrayArray[i][ix].NC1, PolyArrayArray[i][ix].NC2, PolyArrayArray[i][ix].NC3);
                    tris[vindex]               = vindex;
                    uvs[vindex]                = new Vector2(vertices[vindex].z, vertices[vindex].x);
                    colors[vindex]             = new Color(PolyArrayArray[i][ix].CCR, PolyArrayArray[i][ix].CCG, PolyArrayArray[i][ix].CCB, 1.0f);
                    weights[vindex].boneIndex0 = PolyArrayArray[i][ix].BoneIndexC0;
                    weights[vindex].boneIndex1 = PolyArrayArray[i][ix].BoneIndexC1;
                    weights[vindex].weight0    = PolyArrayArray[i][ix].BoneWeightC0;
                    weights[vindex].weight1    = PolyArrayArray[i][ix].BoneWeightC1;

                    vindex++;
                }
            }
        }

        //We have got all data and are ready to setup a new mesh!
        if (critterMesh == null)
        {
            critterMesh = new Mesh();
        }
        else
        {
            critterMesh.Clear();
        }
        //Mesh newMesh = new Mesh();
        critterMesh.vertices  = vertices;
        critterMesh.uv        = uvs;     //Unwrapping.GeneratePerTriangleUV(NewMesh);
        critterMesh.triangles = tris;
        critterMesh.normals   = normals; //NewMesh.RecalculateNormals();
        critterMesh.colors    = colors;
        critterMesh.Optimize();

        // Set up SKINNING!!!:
        Transform[] bones     = new Transform[critter.critterSegmentList.Count];
        Matrix4x4[] bindPoses = new Matrix4x4[critter.critterSegmentList.Count];
        // Try just using existing critter's GameObjects/Transforms:
        for (int seg = 0; seg < critter.critterSegmentList.Count; seg++)
        {
            bones[seg]     = critter.critterSegmentList[seg].transform;
            bindPoses[seg] = bones[seg].worldToLocalMatrix * transform.localToWorldMatrix;  // ?????????????????
            // the bind pose is the inverse of inverse transformation matrix of the bone, when the bone is in the bind pose .... unhelpful ....
        }
        critterMesh.boneWeights = weights;
        critterMesh.bindposes   = bindPoses;
        SkinnedMeshRenderer skinnedMeshRenderer = this.GetComponent <SkinnedMeshRenderer>();

        skinnedMeshRenderer.bones             = bones;
        skinnedMeshRenderer.sharedMesh        = critterMesh;
        skinnedMeshRenderer.enabled           = true;
        skinnedMeshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;

        cBufferSegmentTransform.Release();


        trainerCritterBrushstrokeManagerRef.TurnOn(critterPointsDataArray);  // Initializes Buffers for Brushstroke
        //critterPointsBuffer = new ComputeBuffer(critterPointsDataArray.Length, sizeof(float) * 3);
        //critterPointsBuffer.SetData(critterPointsDataArray);
        //Debug.Log("BuildMesh count: " + critterPointsDataArray.Length.ToString() + ", 0: " + critterPointsDataArray[0].pos.ToString() + ", 500: " + critterPointsDataArray[500].pos.ToString());
        // OLD: //critterDecorationsTest.TurnOn(points);

        float calcTime = Time.realtimeSinceStartup - startTime;

        //Debug.Log("MeshCreated! " + calcTime.ToString());

        HideSegmentCubes();
    }
    public void BuildMesh(ref TrainerCritterBrushstrokeManager trainerCritterBrushstrokeManagerRef) {
        float startTime = Time.realtimeSinceStartup;

        // NOISE VOLUME!
        RenderTexture DensityVolume = new RenderTexture(16, 16, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.sRGB);
        DensityVolume.volumeDepth = 16;
        DensityVolume.isVolume = true;
        DensityVolume.enableRandomWrite = true;
        DensityVolume.filterMode = FilterMode.Bilinear;
        DensityVolume.wrapMode = TextureWrapMode.Repeat;
        DensityVolume.Create();
        int mgen_id = CShaderSimplex.FindKernel("FillEmpty");
        // uses renderTexture rather than StructuredBuffer?
        CShaderSimplex.SetTexture(mgen_id, "Result", DensityVolume);  // Links RenderTexture to the "Result" RWTexture in the compute shader?	
        CShaderSimplex.Dispatch(mgen_id, 1, 1, 16);  // run computeShader "FillEmpty" with 1 x 1 x 31 threadGroups?      
        mgen_id = CShaderSimplex.FindKernel("Simplex3d");
        CShaderSimplex.SetTexture(mgen_id, "Result", DensityVolume);
        CShaderSimplex.Dispatch(mgen_id, 1, 1, 16);  // Fill shared RenderTexture with GPU simplex Noise
        
        ComputeBuffer cBufferSegmentTransform = new ComputeBuffer(critterSegmentTransforms.Length, sizeof(float) * (3 + 3 + 4));
        cBufferSegmentTransform.SetData(critterSegmentTransforms);
        int kernelID = CShaderBuildMC.FindKernel("CSMain");
        CShaderBuildMC.SetBuffer(kernelID, "segmentTransformBuffer", cBufferSegmentTransform);
        CShaderBuildMC.SetTexture(kernelID, "noise_volume", DensityVolume);  // Noise 3D texture
        
        // Figure out how many chunks are needed:
        int numChunksX = Mathf.CeilToInt(GlobalBoundingBoxDimensions.x / (cellResolution * 8f));
        int numChunksY = Mathf.CeilToInt(GlobalBoundingBoxDimensions.y / (cellResolution * 8f));
        int numChunksZ = Mathf.CeilToInt(GlobalBoundingBoxDimensions.z / (cellResolution * 8f));
        //Debug.Log("numChunks: (" + numChunksX.ToString() + ", " + numChunksY.ToString() + ", " + numChunksZ.ToString() + ")");

        int totalNumChunks = numChunksX * numChunksY * numChunksZ;
        Poly[][] PolyArrayArray = new Poly[totalNumChunks][];  // This will hold the mesh data from the chunks calculated on the GPU
        int[] numPolysArray = new int[totalNumChunks];
        int totalNumPolys = 0;

        // Get each chunk!
        int chunkIndex = 0;
        for (int x = 0; x < numChunksX; x++) {
            for (int y = 0; y < numChunksY; y++) {
                for (int z = 0; z < numChunksZ; z++) {
                    // Figure out chunk offset amount:
                    Vector3 chunkOffset = new Vector3(cellResolution * 8f * x, cellResolution * 8f * y, cellResolution * 8f * z) + GlobalBoundingBoxOffset - (GlobalBoundingBoxDimensions / 2f);

                    int[] numPolys = new int[1];
                    ComputeBuffer cBufferNumPoly = new ComputeBuffer(1, sizeof(int));
                    cBufferNumPoly.SetData(numPolys);

                    int id = CShaderBuildMC.FindKernel("CSMain");
                    CShaderBuildMC.SetInt("_CalcNumPolys", 1); // only calculate how many tris so I can correctly size the poly buffer
                    CShaderBuildMC.SetFloat("_GlobalOffsetX", chunkOffset.x);
                    CShaderBuildMC.SetFloat("_GlobalOffsetY", chunkOffset.y);
                    CShaderBuildMC.SetFloat("_GlobalOffsetZ", chunkOffset.z);
                    CShaderBuildMC.SetFloat("_CellSize", cellResolution);
                    CShaderBuildMC.SetVector("_ColorPrimary", colorPrimary);
                    CShaderBuildMC.SetVector("_ColorSecondary", colorSecondary);
                    CShaderBuildMC.SetFloat("_ColorNoiseScale", colorNoiseScale);
                    CShaderBuildMC.SetFloat("_ColorSmlAmplitude", colorSmlAmplitude);
                    CShaderBuildMC.SetFloat("_ColorMedAmplitude", colorMedAmplitude);
                    CShaderBuildMC.SetFloat("_ColorLrgAmplitude", colorLrgAmplitude);
                    CShaderBuildMC.SetFloat("_ColorContrast", colorContrast);
                    CShaderBuildMC.SetFloat("_ColorThreshold", colorThreshold);
                    CShaderBuildMC.SetVector("_SkinNoiseScale", skinNoiseScale);
                    CShaderBuildMC.SetFloat("_SkinNoiseAmplitude", skinNoiseAmplitude);
                    CShaderBuildMC.SetVector("_SkinLocalTaper", skinLocalTaper);
                    CShaderBuildMC.SetVector("_SkinLocalSinFreq", skinLocalSinFreq);
                    CShaderBuildMC.SetVector("_SkinLocalSinAmp", skinLocalSinAmp);
                    // Local Segment-space modifications, sin, taper, etc.

                    CShaderBuildMC.SetBuffer(id, "numPolyBuffer", cBufferNumPoly);
                    CShaderBuildMC.Dispatch(id, 1, 1, 1);  // calc num polys      
                    cBufferNumPoly.GetData(numPolys);  // get numPolys
                    //Debug.Log("Chunk: " + (z + (numChunksZ * y) + (numChunksZ * numChunksY * x)).ToString() + ", cBufferNumPoly.GetData(numPolys): " + numPolys[0].ToString() + ", chunkOffset: " + chunkOffset.ToString());
                    totalNumPolys += numPolys[0];
                    numPolysArray[chunkIndex] = numPolys[0];

                    if (numPolys[0] > 0) {   // only do this if there was at least 1 triangle in the test pass
                        Poly[] polyArray = new Poly[numPolys[0]];
                        int cBufferStride = sizeof(float) * (18 + 9 + 6) + sizeof(int) * (6);
                        ComputeBuffer cBuffer = new ComputeBuffer(numPolys[0], cBufferStride);  // 18 floats x 4 bytes/float = 72   + COLORS! 9 x 4 = 36  = 108   + BONES! 6x4 = 24 + 6 xint...
                        cBuffer.SetData(polyArray);

                        CShaderBuildMC.SetBuffer(id, "buffer", cBuffer);
                        CShaderBuildMC.SetInt("_CalcNumPolys", 0);  // Actually calc tris        
                        CShaderBuildMC.Dispatch(id, 1, 1, 1);
                        cBuffer.GetData(polyArray);  // return data from GPU

                        PolyArrayArray[chunkIndex] = polyArray;
                        cBuffer.Dispose();
                    }

                    cBufferNumPoly.Dispose();

                    chunkIndex++;
                }
            }
        }

        // OLD: // CritterDecorationsTest.decorationStruct[] points = new CritterDecorationsTest.decorationStruct[totalNumPolys];
        critterPointsDataArray = new TrainerRenderManager.strokeStruct[totalNumPolys];  // first try brushstrokes
        
        //Construct mesh using received data 
        int vindex = 0;
        int decindex = 0;
        // Why same number of tris as vertices?  == // because all triangles have duplicate verts - no shared vertices?
        Vector3[] vertices = new Vector3[totalNumPolys * 3];
        Color[] colors = new Color[totalNumPolys * 3];
        int[] tris = new int[totalNumPolys * 3];
        Vector2[] uvs = new Vector2[totalNumPolys * 3];
        Vector3[] normals = new Vector3[totalNumPolys * 3];
        BoneWeight[] weights = new BoneWeight[totalNumPolys * 3];

        //Parse triangles
        for (int i = 0; i < PolyArrayArray.Length; i++) {
            if (numPolysArray[i] > 0) {  // only do this if there was at least 1 triangle in the test pass
                for (int ix = 0; ix < numPolysArray[i]; ix++) {

                    Vector3 vPos;
                    Vector3 vOffset = new Vector3(0, 0, 0);   //???  offsets all vertices by this amount, but why 30?? 
                                                              //A1,A2,A3
                    vPos = new Vector3(PolyArrayArray[i][ix].A1, PolyArrayArray[i][ix].A2, PolyArrayArray[i][ix].A3) + vOffset;
                    vertices[vindex] = vPos * _Scale;
                    normals[vindex] = new Vector3(PolyArrayArray[i][ix].NA1, PolyArrayArray[i][ix].NA2, PolyArrayArray[i][ix].NA3);
                    tris[vindex] = vindex;
                    uvs[vindex] = new Vector2(vertices[vindex].z, vertices[vindex].x);
                    colors[vindex] = new Color(PolyArrayArray[i][ix].CAR, PolyArrayArray[i][ix].CAG, PolyArrayArray[i][ix].CAB, 1.0f);
                    weights[vindex].boneIndex0 = PolyArrayArray[i][ix].BoneIndexA0;
                    weights[vindex].boneIndex1 = PolyArrayArray[i][ix].BoneIndexA1;
                    weights[vindex].weight0 = PolyArrayArray[i][ix].BoneWeightA0;
                    weights[vindex].weight1 = PolyArrayArray[i][ix].BoneWeightA1;

                    critterPointsDataArray[decindex].pos = vPos;
                    critterPointsDataArray[decindex].col = new Vector3(colors[vindex].r, colors[vindex].g, colors[vindex].b);
                    critterPointsDataArray[decindex].normal = normals[vindex];
                    //critterPointsDataArray[decindex].tangent = ;  // Tangent is calculated during initial Skinning (when determining weights)
                    critterPointsDataArray[decindex].prevPos = vPos;
                    critterPointsDataArray[decindex].dimensions = new Vector2(1f,1f);
                    critterPointsDataArray[decindex].brushType = 0;  // default
                    // OLD:
                    //points[decindex].pos = vPos;
                    //points[decindex].normal = normals[vindex];
                    //points[decindex].color = new Vector3(colors[vindex].r, colors[vindex].g, colors[vindex].b);

                    decindex++;
                    vindex++;

                    //B1,B2,B3
                    vPos = new Vector3(PolyArrayArray[i][ix].B1, PolyArrayArray[i][ix].B2, PolyArrayArray[i][ix].B3) + vOffset;
                    vertices[vindex] = vPos * _Scale;
                    normals[vindex] = new Vector3(PolyArrayArray[i][ix].NB1, PolyArrayArray[i][ix].NB2, PolyArrayArray[i][ix].NB3);
                    tris[vindex] = vindex;
                    uvs[vindex] = new Vector2(vertices[vindex].z, vertices[vindex].x);
                    colors[vindex] = new Color(PolyArrayArray[i][ix].CBR, PolyArrayArray[i][ix].CBG, PolyArrayArray[i][ix].CBB, 1.0f);
                    weights[vindex].boneIndex0 = PolyArrayArray[i][ix].BoneIndexB0;
                    weights[vindex].boneIndex1 = PolyArrayArray[i][ix].BoneIndexB1;
                    weights[vindex].weight0 = PolyArrayArray[i][ix].BoneWeightB0;
                    weights[vindex].weight1 = PolyArrayArray[i][ix].BoneWeightB1;

                    vindex++;

                    //C1,C2,C3
                    vPos = new Vector3(PolyArrayArray[i][ix].C1, PolyArrayArray[i][ix].C2, PolyArrayArray[i][ix].C3) + vOffset;
                    vertices[vindex] = vPos * _Scale;
                    normals[vindex] = new Vector3(PolyArrayArray[i][ix].NC1, PolyArrayArray[i][ix].NC2, PolyArrayArray[i][ix].NC3);
                    tris[vindex] = vindex;
                    uvs[vindex] = new Vector2(vertices[vindex].z, vertices[vindex].x);
                    colors[vindex] = new Color(PolyArrayArray[i][ix].CCR, PolyArrayArray[i][ix].CCG, PolyArrayArray[i][ix].CCB, 1.0f);
                    weights[vindex].boneIndex0 = PolyArrayArray[i][ix].BoneIndexC0;
                    weights[vindex].boneIndex1 = PolyArrayArray[i][ix].BoneIndexC1;
                    weights[vindex].weight0 = PolyArrayArray[i][ix].BoneWeightC0;
                    weights[vindex].weight1 = PolyArrayArray[i][ix].BoneWeightC1;

                    vindex++;
                }
            }
        }

        //We have got all data and are ready to setup a new mesh!
        if(critterMesh == null) {
            critterMesh = new Mesh();
        }
        else {
            critterMesh.Clear();
        }
        //Mesh newMesh = new Mesh();
        critterMesh.vertices = vertices;
        critterMesh.uv = uvs; //Unwrapping.GeneratePerTriangleUV(NewMesh);
        critterMesh.triangles = tris;
        critterMesh.normals = normals; //NewMesh.RecalculateNormals();
        critterMesh.colors = colors;
        critterMesh.Optimize();

        // Set up SKINNING!!!:
        Transform[] bones = new Transform[critter.critterSegmentList.Count];
        Matrix4x4[] bindPoses = new Matrix4x4[critter.critterSegmentList.Count];
        // Try just using existing critter's GameObjects/Transforms:
        for (int seg = 0; seg < critter.critterSegmentList.Count; seg++) {
            bones[seg] = critter.critterSegmentList[seg].transform;
            bindPoses[seg] = bones[seg].worldToLocalMatrix * transform.localToWorldMatrix;  // ?????????????????  
            // the bind pose is the inverse of inverse transformation matrix of the bone, when the bone is in the bind pose .... unhelpful ....
        }
        critterMesh.boneWeights = weights;
        critterMesh.bindposes = bindPoses;
        SkinnedMeshRenderer skinnedMeshRenderer = this.GetComponent<SkinnedMeshRenderer>();
        skinnedMeshRenderer.bones = bones;
        skinnedMeshRenderer.sharedMesh = critterMesh;
        skinnedMeshRenderer.enabled = true;
        skinnedMeshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;

        cBufferSegmentTransform.Release();


        trainerCritterBrushstrokeManagerRef.TurnOn(critterPointsDataArray);  // Initializes Buffers for Brushstroke
        //critterPointsBuffer = new ComputeBuffer(critterPointsDataArray.Length, sizeof(float) * 3);
        //critterPointsBuffer.SetData(critterPointsDataArray);
        //Debug.Log("BuildMesh count: " + critterPointsDataArray.Length.ToString() + ", 0: " + critterPointsDataArray[0].pos.ToString() + ", 500: " + critterPointsDataArray[500].pos.ToString());
        // OLD: //critterDecorationsTest.TurnOn(points);

        float calcTime = Time.realtimeSinceStartup - startTime;
        //Debug.Log("MeshCreated! " + calcTime.ToString());

        HideSegmentCubes();
    }