private static float GetMaskValue(BrushPoint point, CritterModuleCoreGenome.MaskData maskData)
    {
        float outValue = 0f;
        float inValue  = 0f;

        // MASK COORDINATE SPACES:
        if (maskData.coordinateTypeID == CritterModuleCoreGenome.MaskCoordinateType.Lengthwise)
        {
            inValue = Mathf.Abs(point.initCoordsNormalized.y - maskData.origin) / maskData.cycleDistance;
        }
        if (maskData.coordinateTypeID == CritterModuleCoreGenome.MaskCoordinateType.Polygonize)
        {
            //find 2 closest edges
            float pointFaceCoord = point.uv.x * (float)maskData.numPolyEdges;

            float dist0 = pointFaceCoord % 1f;
            float dist1 = 1f - dist0;

            float dist = Mathf.Max(dist0, dist1) / maskData.cycleDistance;

            inValue = dist;
        }

        /*if(maskData.coordinateTypeID == CritterModuleCoreGenome.MaskCoordinateType.SingleAxis) {
         *
         *  float dot = Vector2.Dot(new Vector2(point.initCoordsNormalized.x, point.initCoordsNormalized.z).normalized, maskData.axisDir.normalized);  // *** IF I CHANGE coordinate Axes this needs to change!! ***
         *
         *  inValue = (dot * 0.5f + 0.5f) / maskData.cycleDistance;
         * }*/
        //inValue = Mathf.Clamp01(inValue); // *** ??? avoid discontinuities?
        // FUNCTION TYPES:
        if (maskData.functionTypeID == CritterModuleCoreGenome.MaskFunctionType.Linear)
        {
            outValue = Mathf.Clamp01(1f - inValue);
        }
        if (maskData.functionTypeID == CritterModuleCoreGenome.MaskFunctionType.Sin)
        {
            outValue = Mathf.Sin(inValue) * Mathf.PI;
        }
        if (maskData.functionTypeID == CritterModuleCoreGenome.MaskFunctionType.Cos)
        {
            outValue = Mathf.Cos(inValue) * Mathf.PI;
        }

        return(outValue);
    }
    /// <summary>
    /// COORDINATES FOR CREATURES:
    /// Positive Y = forward, creature head
    /// X Axis = Creature width;
    /// Negative Z = world UP!  note that this is flipped
    /// </summary>

    private static void ProcessBrushPointBaseBody(ref BrushPoint point, AgentGenome genome)
    {
        CritterModuleCoreGenome gene = genome.bodyGenome.coreGenome; // for readability

        float segmentsSummedCritterLength = gene.mouthLength + gene.headLength + gene.bodyLength + gene.tailLength;
        float bindPoseY = point.initCoordsNormalized.y * segmentsSummedCritterLength;

        float widthMultiplier;
        float heightMultiplier;
        // simplify round:
        float frontCapLerpAmount = Mathf.Clamp01(point.initCoordsNormalized.y - gene.creatureFrontTaperSize) / gene.creatureFrontTaperSize;
        float backCapLerpAmount  = Mathf.Clamp01((1f - point.initCoordsNormalized.y) - gene.creatureFrontTaperSize) / gene.creatureBackTaperSize;
        float circularizeAmount  = Mathf.Max(frontCapLerpAmount, backCapLerpAmount);
        /// **** FIX THIS!! ***  circle coords depend on taper distance?
        float pointCircleCoord       = point.initCoordsNormalized.y * 2f - 1f;               // get normalized coords 0 to 1 to sample circle
        float circleSize             = Mathf.Sqrt(1f - pointCircleCoord * pointCircleCoord); // pythagorean theorem
        float circleWidthMultiplier  = Mathf.Lerp(1f, circleSize, circularizeAmount) * 0.5f; // *0.5 for radius vs. diameter
        float circleHeightMultiplier = Mathf.Lerp(1f, circleSize, circularizeAmount) * 0.5f;

        if (bindPoseY > gene.tailLength)
        {
            if (bindPoseY > gene.bodyLength + gene.tailLength)
            {
                if (bindPoseY > gene.headLength + gene.bodyLength + gene.tailLength)
                {
                    // this point is in the MOUTH Section:
                    float subSectionCoords01 = (bindPoseY - gene.tailLength - gene.bodyLength - gene.headLength) / gene.mouthLength;
                    //float mouthTipBlendLerpAmount = Mathf.Clamp01((gene.mouthEndCapTaperSize * 0.5f - (1f - subSectionCoords01)) / (gene.mouthEndCapTaperSize * 0.5f));
                    float headBlendLerpAmount = Mathf.Clamp01((gene.mouthToHeadTransitionSize * 0.5f - (subSectionCoords01)) / (gene.mouthToHeadTransitionSize * 0.5f)) * 0.5f;

                    float headSectionWidth  = gene.bodyBackWidth;
                    float mouthSectionWidth = Mathf.Lerp(gene.mouthBackWidth, gene.mouthFrontWidth, subSectionCoords01);
                    widthMultiplier = Mathf.Lerp(mouthSectionWidth, headSectionWidth, headBlendLerpAmount);
                    //widthMultiplier = Mathf.Lerp(mult, widthMultiplier, headBlendLerpAmount);
                    //widthMultiplier = Mathf.Lerp(widthMultiplier, 0f, Mathf.Pow(mouthTipBlendLerpAmount, 1f));
                    //widthMultiplier = widthMultiplier * gene.mouthLength;

                    float headSectionHeight  = gene.bodyBackHeight;
                    float mouthSectionHeight = Mathf.Lerp(gene.mouthBackHeight, gene.mouthFrontHeight, subSectionCoords01);
                    heightMultiplier = Mathf.Lerp(mouthSectionHeight, headSectionHeight, headBlendLerpAmount);
                    //heightMultiplier = Mathf.Lerp(heightMultiplier, 0f, Mathf.Pow(mouthTipBlendLerpAmount, 1f));
                    //heightMultiplier = heightMultiplier * gene.mouthLength;

                    if (bindPoseY > segmentsSummedCritterLength)
                    {
                        Debug.LogError($"bindPoseY is {bindPoseY}, which is longer than the creature {segmentsSummedCritterLength}!");
                    }
                }
                else
                {
                    // this point is in the HEAD Section:
                    float subSectionCoords01   = (bindPoseY - gene.tailLength - gene.bodyLength) / gene.headLength;
                    float bodyBlendLerpAmount  = Mathf.Clamp01((gene.headToBodyTransitionSize * 0.5f - subSectionCoords01) / (gene.headToBodyTransitionSize * 0.5f)) * 0.5f;
                    float mouthBlendLerpAmount = Mathf.Clamp01((gene.mouthToHeadTransitionSize * 0.5f - (1f - subSectionCoords01)) / (gene.mouthToHeadTransitionSize * 0.5f)) * 0.5f;

                    float bodySectionWidth  = gene.bodyFrontWidth;
                    float headSectionWidth  = Mathf.Lerp(gene.headBackWidth, gene.headFrontWidth, subSectionCoords01);
                    float mouthSectionWidth = gene.mouthBackWidth;
                    widthMultiplier = Mathf.Lerp(headSectionWidth, bodySectionWidth, bodyBlendLerpAmount);
                    widthMultiplier = Mathf.Lerp(widthMultiplier, mouthSectionWidth, mouthBlendLerpAmount);
                    //widthMultiplier = widthMultiplier * gene.headLength;

                    float bodySectionHeight  = gene.bodyFrontHeight;
                    float headSectionHeight  = Mathf.Lerp(gene.headBackHeight, gene.headFrontHeight, subSectionCoords01);
                    float mouthSectionHeight = gene.mouthBackHeight;
                    heightMultiplier = Mathf.Lerp(headSectionHeight, bodySectionHeight, bodyBlendLerpAmount);
                    heightMultiplier = Mathf.Lerp(heightMultiplier, mouthSectionHeight, mouthBlendLerpAmount);
                    //heightMultiplier = heightMultiplier * gene.headLength;
                }
            }
            else
            {
                // this point is in the BODY Section:
                float subSectionCoords01  = (bindPoseY - gene.tailLength) / gene.bodyLength;
                float tailBlendLerpAmount = Mathf.Clamp01((gene.bodyToTailTransitionSize * 0.5f - subSectionCoords01) / (gene.bodyToTailTransitionSize * 0.5f)) * 0.5f;
                float headBlendLerpAmount = Mathf.Clamp01((gene.headToBodyTransitionSize * 0.5f - (1f - subSectionCoords01)) / (gene.headToBodyTransitionSize * 0.5f)) * 0.5f;

                float tailSectionWidth = gene.tailFrontWidth;
                float bodySectionWidth = Mathf.Lerp(gene.bodyBackWidth, gene.bodyFrontWidth, subSectionCoords01);
                float headSectionWidth = gene.headBackWidth;
                widthMultiplier = Mathf.Lerp(bodySectionWidth, tailSectionWidth, tailBlendLerpAmount);
                widthMultiplier = Mathf.Lerp(widthMultiplier, headSectionWidth, headBlendLerpAmount);
                //widthMultiplier = widthMultiplier * gene.bodyLength;

                float tailSectionHeight = gene.tailFrontHeight;
                float bodySectionHeight = Mathf.Lerp(gene.bodyBackHeight, gene.bodyFrontHeight, subSectionCoords01);
                float headSectionHeight = gene.headBackHeight;
                heightMultiplier = Mathf.Lerp(bodySectionHeight, tailSectionHeight, tailBlendLerpAmount);
                heightMultiplier = Mathf.Lerp(heightMultiplier, headSectionHeight, headBlendLerpAmount);
                //heightMultiplier = heightMultiplier * gene.bodyLength;
            }
        }
        else
        {
            // this point is in the TAIL Section:
            float subSectionCoords01  = bindPoseY / gene.tailLength; // divide by zero if no tail?
            float bodyBlendLerpAmount = Mathf.Clamp01((gene.bodyToTailTransitionSize * 0.5f - (1f - subSectionCoords01)) / (gene.bodyToTailTransitionSize * 0.5f)) * 0.5f;
            //float tailTipBlendLerpAmount = Mathf.Clamp01((gene.tailEndCapTaperSize - subSectionCoords01) / (gene.tailEndCapTaperSize));

            float tailSectionWidth = Mathf.Lerp(gene.tailBackWidth, gene.tailFrontWidth, subSectionCoords01);
            float bodySectionWidth = gene.bodyBackWidth;
            widthMultiplier = Mathf.Lerp(tailSectionWidth, bodySectionWidth, bodyBlendLerpAmount);
            //widthMultiplier = Mathf.Lerp(widthMultiplier, 0f, tailTipBlendLerpAmount);
            //widthMultiplier = widthMultiplier * gene.tailLength;

            float tailSectionHeight = Mathf.Lerp(gene.tailBackHeight, gene.tailFrontHeight, subSectionCoords01);
            float bodySectionHeight = gene.bodyBackHeight;
            heightMultiplier = Mathf.Lerp(tailSectionHeight, bodySectionHeight, bodyBlendLerpAmount);
            //heightMultiplier = Mathf.Lerp(heightMultiplier, 0f, tailTipBlendLerpAmount);
            //heightMultiplier = heightMultiplier * gene.tailLength;
        }

        //Vector2 crossSectionScale = new Vector2(widthMultiplier, heightMultiplier);
        //float crossSectionWidth =

        // Now Body Modifiers are processed:
        float radiusMult = 0f;

        for (int i = 0; i < gene.shapeModifiersList.Count; i++)
        {
            CritterModuleCoreGenome.ShapeModifierData modifierData = gene.shapeModifiersList[i];
            if (modifierData.modifierTypeID == CritterModuleCoreGenome.ShapeModifierType.Extrude)    // extrude
            // Find extrude amount:
            {
                float maskValue = 1f;

                for (int j = 0; j < gene.shapeModifiersList[i].maskIndicesList.Count; j++)
                {
                    int maskIndex = gene.shapeModifiersList[i].maskIndicesList[j];
                    CritterModuleCoreGenome.MaskData maskData = gene.masksList[maskIndex];

                    float rawMaskValue = GetMaskValue(point, maskData);

                    // taper distance?:
                    float taperMask = 1f - Mathf.Clamp01(Mathf.Abs(point.initCoordsNormalized.y - maskData.origin) / modifierData.taperDistance);

                    maskValue *= rawMaskValue * taperMask;
                }
                radiusMult += maskValue * modifierData.amplitude;
                // OLD:
                //float radiusMult = maskValue * modifierData.amplitude + 1f;
                //widthMultiplier *= radiusMult;
                //heightMultiplier *= radiusMult;
            }
        }
        radiusMult        = Mathf.Min(Mathf.Max(radiusMult + 1f, 0.5f), 1.5f);
        widthMultiplier  *= radiusMult;
        heightMultiplier *= radiusMult;


        widthMultiplier  *= circleWidthMultiplier; // this includes * 0.5f from earlier to account for radius vs diameter
        heightMultiplier *= circleHeightMultiplier;

        // simplify round:

        /*
         * float pointCircleCoord = point.initCoordsNormalized.y * 2f - 1f; // get normalized coords 0 to 1 to sample circle
         * float circleWidthMultiplier = Mathf.Sqrt(1f - pointCircleCoord * pointCircleCoord);  // pythagorean theorem
         *
         * float frontCapLerpAmount = Mathf.Clamp01(point.initCoordsNormalized.y - gene.creatureFrontTaperSize) * 2f;
         * float backCapLerpAmount = Mathf.Clamp01((1f - point.initCoordsNormalized.y) - gene.creatureFrontTaperSize) * 2f;
         * float circularizeAmount = Mathf.Max(frontCapLerpAmount, backCapLerpAmount);
         *
         * widthMultiplier = Mathf.Lerp(widthMultiplier, circleWidthMultiplier, circularizeAmount) * 0.5f;  // *0.5 for radius vs. diameter
         * heightMultiplier = Mathf.Lerp(heightMultiplier, circleWidthMultiplier, circularizeAmount) * 0.5f;
         */

        float finalCreatureLength    = segmentsSummedCritterLength * gene.creatureBaseLength;
        float finalCreatureThickness = gene.creatureAspectRatio * finalCreatureLength;

        point.bindPos = new Vector3(point.initCoordsNormalized.x * widthMultiplier * finalCreatureThickness, point.initCoordsNormalized.y * finalCreatureLength - finalCreatureLength * 0.5f, point.initCoordsNormalized.z * heightMultiplier * finalCreatureThickness);
    }