Exemplo n.º 1
0
    IEnumerator DecreaseTerrain(float contactTime, float[,] heightMapPrimitive, int[,] heightMapPrimitiveBool, int x, int z)
    {
        // 1. Apply frame-per-frame deformation ("displacement")
        for (int zi = -gridSensorSize; zi <= gridSensorSize; zi++)
        {
            for (int xi = -gridSensorSize; xi <= gridSensorSize; xi++)
            {
                // Calculate each cell position wrt World and Heightmap - Left Foot
                Vector3 rayGridPrimitive      = new Vector3(x + xi, terrain.Get(x + xi, z + zi), z + zi);
                Vector3 rayGridWorldPrimitive = terrain.Grid2World(rayGridPrimitive);

                // Create each ray for the grid (wrt World) - Left
                RaycastHit primitiveHit;
                Ray        upRayPrimitive = new Ray(rayGridWorldPrimitive, Vector3.up);

                // If hits the Left Foot, increase counter and add cell to be affected
                if (PrimitiveCollider.Raycast(upRayPrimitive, out primitiveHit, rayPrimitiveDistanceUp))
                {
                    // Cell contacting directly
                    heightMapPrimitiveBool[zi + gridSensorSize, xi + gridSensorSize] = 2;
                    heightMapPrimitive[zi + gridSensorSize, xi + gridSensorSize]     = terrain.Get(rayGridPrimitive.x, rayGridPrimitive.z) - (displacement);
                }
                else
                {
                    // No contact
                    heightMapPrimitiveBool[zi + gridSensorSize, xi + gridSensorSize] = 0;
                    heightMapPrimitive[zi + gridSensorSize, xi + gridSensorSize]     = terrain.Get(rayGridPrimitive.x, rayGridPrimitive.z);
                }
            }
        }

        // 2. Pre-filter Gaussian filter
        if (applyPreFilterPrimitive)
        {
            heightMapPrimitive = FilterBufferPrimitive(heightMapPrimitive, heightMapPrimitiveBool);
        }

        // 3. Save terrain
        if (applyNewTerrainModification)
        {
            for (int zi = -gridSensorSize; zi <= gridSensorSize; zi++)
            {
                for (int xi = -gridSensorSize; xi <= gridSensorSize; xi++)
                {
                    Vector3 rayGridPrimitive = new Vector3(x + xi, terrain.Get(x + xi, z + zi), z + zi);
                    terrain.Set(rayGridPrimitive.x, rayGridPrimitive.z, heightMapPrimitive[zi + gridSensorSize, xi + gridSensorSize]);
                }
            }
        }

        yield return(null);
    }
Exemplo n.º 2
0
    /// <summary>
    /// Method that takes the IK positions for each feet and apply displacement to ground.
    /// </summary>
    /// <param name="xLeft"></param>
    /// <param name="zLeft"></param>
    /// <param name="xRight"></param>
    /// <param name="zRight"></param>
    public override void DrawFootprint(int x, int z)
    {
        //=============//

        // Reset counter hits
        counterHitsPrimitive = 0;

        // Clear cells to be affected
        //cellsAffected.Clear();

        // Primitive
        float[,] heightMapPrimitive   = new float[2 * gridSensorSize + 1, 2 * gridSensorSize + 1];
        int[,] heightMapPrimitiveBool = new int[2 * gridSensorSize + 1, 2 * gridSensorSize + 1];

        // Warning: Supossing that terrain is squared!
        if (printTerrainInformation)
        {
            Debug.Log("[INFO] Length Terrain - X: " + terrain.TerrainSize().x);
            Debug.Log("[INFO] Length Terrain - Z: " + terrain.TerrainSize().z);
            Debug.Log("[INFO] Number of heightmap cells: " + (terrain.GridSize().x - 1));
            Debug.Log("[INFO] Lenght of one cell - X: " + (terrain.TerrainSize().x / (terrain.GridSize().x - 1)));
            Debug.Log("[INFO] Lenght of one cell - Z: " + (terrain.TerrainSize().z / (terrain.GridSize().z - 1)));
            Debug.Log("[INFO] Area of one cell: " + (terrain.TerrainSize().x / (terrain.GridSize().x - 1)) * (terrain.TerrainSize().z / (terrain.GridSize().z - 1)));
        }

        // Calculate area per cell outside the loop
        lenghtCellX = terrain.TerrainSize().x / (terrain.GridSize().x - 1);
        lenghtCellZ = terrain.TerrainSize().z / (terrain.GridSize().z - 1);
        areaCell    = lenghtCellX * lenghtCellZ;

        //=============//

        // 2D iteration for primitive
        // It counts the number of hits, save the classified cell in a list and debug ray-casting
        for (int zi = -gridSensorSize; zi <= gridSensorSize; zi++)
        {
            for (int xi = -gridSensorSize; xi <= gridSensorSize; xi++)
            {
                // Calculate each cell position wrt World and Heightmap - Primitive
                Vector3 rayGridPrimitive      = new Vector3(x + xi, terrain.Get(x + xi, z + zi) - offset, z + zi);
                Vector3 rayGridWorldPrimitive = terrain.Grid2World(rayGridPrimitive);

                // Create each ray for the grid (wrt World) - Primitive
                RaycastHit primitiveHit;
                Ray        upRayPrimitive = new Ray(rayGridWorldPrimitive, Vector3.up);

                // If hits the Left Foot, increase counter and add cell to be affected
                if (PrimitiveCollider.Raycast(upRayPrimitive, out primitiveHit, rayPrimitiveDistanceUp))
                {
                    counterHitsPrimitive++;

                    if (showGridDebug)
                    {
                        Debug.DrawRay(rayGridWorldPrimitive, Vector3.up * rayPrimitiveDistanceUp, Color.blue);
                    }
                }
                else
                {
                    //cellsNotAffected.Add(rayGridLeft);

                    if (showGridDebug)
                    {
                        Debug.DrawRay(rayGridWorldPrimitive, Vector3.up * rayPrimitiveDistanceUp, Color.red);
                    }
                }
            }
        }

        //=============//

        // 1. TotalForce gives the total force applicable (gravity + reaction impulse)
        //Debug.Log("Total Force now: " + TotalForce);

        // 2. Total Contact Area in Frame.
        // TODO: Keep always larger area - (?)
        oldAreaTotal = ((counterHitsPrimitive) * areaCell);
        if (oldAreaTotal >= areaTotal)
        {
            areaTotal = ((counterHitsPrimitive) * areaCell);
        }

        // 3. Calculate Pressure applicable per Frame - no contact, no pressure.
        if (counterHitsPrimitive == 0)
        {
            pressure = 0f;
        }
        else
        {
            pressure = (TotalForce) / areaTotal;
        }

        // Plot
        //pressurePlot = pressure;

        //=============//

        // 4. Given those cells, and pressure, which should be the decrement in the terrain?
        // The decrement will depend entirely on the pressure and time.

        // A. Test - Interpolated Value
        //float normalizedValuePressure = Mathf.InverseLerp(0, 2000, pressure);
        //heightCellDisplacement = Mathf.Lerp(0f, 0.1f, normalizedValuePressure);

        // B. Test - Constant Value
        //heightCellDisplacement = 0.015f;

        // C. Young Modulus to calculate maximum displacement for a equivalent rod of cross-section "areaTotal" and length "originalLength"
        // We keep the maximum displacement caused - (?)
        oldHeightCellDisplacementYoung = pressure * (originalLength / (youngModulus));
        if (oldHeightCellDisplacementYoung >= heightCellDisplacementYoung)
        {
            heightCellDisplacementYoung = pressure * (originalLength / youngModulus);
        }

        // Then, if the previous displacement is the total deformation, we need to calculate the small step
        // that we do per frame until we reach the given "ContactTime".
        displacement = (Time.deltaTime * (float)heightCellDisplacementYoung) / ContactTime;
        //Debug.Log("For the pressure " + pressure + " we have a displacement/cell of " + displacement);

        // Plot
        //displacementPlot = (float)heightCellDisplacementYoung;

        //=============//

        //if (printFootprintsInformation)
        //{
        //    Debug.Log("[INFO] Counter Hits Left: " + counterHitsLeft);
        //    Debug.Log("[INFO] Counter Hits Right: " + counterHitsRight);
        //    Debug.Log("[INFO] Total Contact Area: " + areaTotal);
        //    Debug.Log("[INFO] Current Force: " + Force);
        //    Debug.Log("[INFO] Pressure/Cell NOW: " + pressure);
        //    Debug.Log("[INFO] Min Pressure: " + minPressure);
        //    Debug.Log("[INFO] Max Pressure: " + maxPressure);
        //}

        //if (printDeformationInformation)
        //{
        //    Debug.Log("normalizedValuePressure: " + normalizedValuePressure);
        //    Debug.Log("heightCellDisplacement: " + heightCellDisplacement);
        //}

        //=============//

        // 2D iteration Deformation
        // Once we have the displacement based on the weight, we saved the actual result of applying it to the terrain
        if (counterHitsPrimitive != 0)
        {
            // Once we touch the ground, clock starts. It will deform the terrain during delta_t.
            // TODO: We need to reset times for the steps example later on.
            timePassed += Time.deltaTime;
            if (timePassed <= ContactTime)
            {
                StartCoroutine(DecreaseTerrain(ContactTime, heightMapPrimitive, heightMapPrimitiveBool, x, z));
            }
        }
    }