Esempio n. 1
0
    // ******************************************************************************************
    //                          FIELD SOLVING FUNCTIONS
    // ******************************************************************************************
    private void computeDensityField(CC_Unit ccu)
    {
        // grab properties of the CC Unit
        var footprint = ccu.GetFootprint().Rotate(-ccu.Rotation());
        var anchor    = ccu.Position();

        // compute the footprint's half-dimensions
        var xHalf = footprint.GetLength(0) / 2f;
        var yHalf = footprint.GetLength(1) / 2f;

        // translate the anchor so it's centered about our unit
        anchor -= new Vector2(xHalf, yHalf);
        // finally, perform bilinear interpolation of the footprint at our anchor
        var footprintInterp = footprint.BilinearInterpolation(anchor);

        // offsets - floor produces smoothest interpolated position stamps
        var xOffset = Mathf.FloorToInt(anchor.x);
        var yOffset = Mathf.FloorToInt(anchor.y);

        // scan the grid, stamping the footprint onto the tile
        for (int x = 0; x < footprintInterp.GetLength(0); x++)
        {
            for (int y = 0; y < footprintInterp.GetLength(1); y++)
            {
                // get the rho value
                float rho = footprintInterp[x, y];
                // only perform storage functions if there is a density value
                if (rho > 0)
                {
                    var xIndex = x + xOffset;
                    var yIndex = y + yOffset;
                    // add rho to the in-place density
                    addDataToPoint_rho(xIndex, yIndex, rho);
                }
            }
        }
    }
Esempio n. 2
0
    // **********************************************************************
    //      Predictive velocity fields
    // **********************************************************************
    private void applyPredictiveVelocity(CC_Unit ccu)
    {
        // TODO: Only apply predictive velocity to continuous segments, ie.
        //      if a portion of this predictive path is blocked by impassable
        //      terrain, we should not apply predictive velocity beyond that
        //      point

        // fetch unit properties
        var speed = ccu.Speed();

        // compute values
        var distance  = (int)Math.Ceiling(speed * CCValues.S.v_predictiveSeconds);
        var footprint = ccu.GetFootprint();
        var height    = footprint.GetLength(1);

        // (1) create a rect with Length = predictive distance, Height = Unit footprint height
        //var footprintEnd = (int)Math.Floor(footprint.GetLength(0) / 2f);
        var footprintEnd = Mathf.FloorToInt(ccu.Falloff() + ccu.SizeX - 1);
        var predictive   = new float[footprintEnd + distance, height];

        // (2) build half of the footprint into the predictive rect
        for (int i = 0; i < footprintEnd; i++)
        {
            for (int k = 0; k < height; k++)
            {
                predictive[i, k] = footprint[i, k];
            }
        }

        // (3a) record the "vertical slice" of the unit footprint
        var slice = new float[height];

        for (int i = 0; i < slice.Length; i++)
        {
            slice[i] = footprint[footprintEnd, i];
        }

        // (3b) scale the vertical slice along the length of the rect
        // determine falloff rates
        var start = (CCValues.S.f_rhoMax + CCValues.S.f_rhoMin) / 2;
        var end   = 0f; // CCValues.S.f_rhoMin / 4f;
        // track iteration
        int c = 0;

        for (int i = footprintEnd; i < predictive.GetLength(0); i++)
        {
            // taper from <start> down to <end>
            var scalar = (end - start) / distance * c + start;
            c++;
            for (int k = 0; k < height; k++)
            {
                // build the predictive velocity rect in front of the footprint
                predictive[i, k] = slice[k] * scalar;
            }
        }

        // (4) rotate the rect
        var yEuler = ccu.Rotation();
        // Unity y-euler rotations start at +z (+y in 2D) and move CW.
        // Academic rotations are described as CCW from the +x axis, which is what
        // many of our derivations are based, so we convert here.
        var degrees = Mathf.Repeat(90 - yEuler, 360);
        var radians = degrees * Mathf.Deg2Rad;
        var rotated = predictive.Rotate(degrees);

        // (5) determine anchor position - do this by taking the "perfect" center
        //     and applying the same translations/rotations that our rotate process
        //     applies
        //   (i) declare unit location in original footprint center
        var unitOffset = new Vector2(footprint.GetLength(0) / 2f, height / 2f);

        //   (ii) translate by predictive velocity half-shape to center on (0,0)
        unitOffset += new Vector2(-predictive.GetLength(0) / 2f, -height / 2f);
        //   (iii) rotate the point about (0,0) by our unit's rotation
        unitOffset = unitOffset.Rotate(radians);
        //   (iv) translate back by rotated shape half-space
        unitOffset += new Vector2(rotated.GetLength(0) / 2f, rotated.GetLength(1) / 2f);

        // finally, translate the anchor to be positioned on the unit
        var anchor = ccu.Position() - unitOffset;

        // (6) inteprolate the final result
        var final = rotated.BilinearInterpolation(anchor);

        // offsets - floor produces smoothest interpolated position stamps
        var xOffset = Mathf.FloorToInt(anchor.x);
        var yOffset = Mathf.FloorToInt(anchor.y);

        // (7) add the density and velocity along the length of the path,
        // scaling each by the value of the rect
        var direction = new Vector2(1, 0).Rotate(radians);
        var velocity  = direction * speed;

        for (int x = 0; x < final.GetLength(0); x++)
        {
            for (int y = 0; y < final.GetLength(1); y++)
            {
                var xIndex = x + xOffset;
                var yIndex = y + yOffset;
                // add rho and velocity to existing data
                addDataToPoint_rho(xIndex, yIndex, final[x, y]);
                addDataToPoint_vAve(xIndex, yIndex, final[x, y] * velocity);
            }
        }
    }