Ticket #21: 21.2.patch

File 21.2.patch, 7.6 KB (added by thomas, 12 years ago)
  • binaries/data/mods/public/simulation/components/Foundation.js

     
    119119    this.buildMultiplier = Math.pow(this.numRecentBuilders, 0.7) / this.numRecentBuilders;
    120120}
    121121
     122Foundation.prototype.FlattenBuildingArea = function()
     123{
     124        var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
     125        var pos = cmpPosition.GetPosition();
     126        var rot = cmpPosition.GetRotation();
     127   
     128        var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint);
     129        var shape = cmpFootprint.GetShape();
     130        var width, depth = 0;
     131   
     132        if (shape.type == "square")
     133        {
     134            width = shape.width;
     135            depth = shape.depth;
     136    }
     137        else if (shape.type == "circle")
     138        {
     139            width = depth = shape.radius * 2;
     140    }
     141   
     142        var xm = pos.x + width / 2 * Math.sin(rot.y);
     143        var zm = pos.z + depth / 2 * Math.sin(rot.y);
     144
     145        var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
     146        var height = cmpTerrain.GetGroundLevel(xm, zm);
     147   
     148        cmpTerrain.SetGroundLevelRegion(height, pos.x, pos.z, width, depth, rot.y);
     149}
     150
    122151/**
    123152 * Perform some number of seconds of construction work.
    124153 * Returns true if the construction is completed.
     
    177206        }
    178207
    179208        this.committed = true;
     209
     210            // Now that we're committed, flatten ground under foundation
     211            this.FlattenBuildingArea();
    180212    }
    181213
    182214    // Calculate the amount of progress that will be added (where 1.0 = completion)
  • source/graphics/Terrain.cpp

     
    423423    // in handling triangulation properly
    424424}
    425425
     426void CTerrain::SetExactGroundLevelFixed(fixed new_y, fixed x, fixed z)
     427{
     428    // Clamp to size-2 so we can use the tiles (xi,zi)-(xi+1,zi+1)
     429    const ssize_t xi = clamp((ssize_t)(x / (int)TERRAIN_TILE_SIZE).ToInt_RoundToZero(), (ssize_t)0, m_MapSize-2);
     430    const ssize_t zi = clamp((ssize_t)(z / (int)TERRAIN_TILE_SIZE).ToInt_RoundToZero(), (ssize_t)0, m_MapSize-2);
     431
     432    m_Heightmap[zi*m_MapSize + xi] = new_y.ToInt_RoundToZero() / HEIGHT_SCALE;
     433    m_Heightmap[(zi+1)*m_MapSize + xi] = new_y.ToInt_RoundToZero() / HEIGHT_SCALE;
     434    m_Heightmap[zi*m_MapSize + (xi+1)] = new_y.ToInt_RoundToZero() / HEIGHT_SCALE;
     435    m_Heightmap[(zi+1)*m_MapSize + (xi+1)] = new_y.ToInt_RoundToZero() / HEIGHT_SCALE;
     436}
     437
    426438bool CTerrain::GetTriangulationDir(ssize_t i, ssize_t j) const
    427439{
    428440    // Clamp to size-2 so we can use the tiles (i,j)-(i+1,j+1)
  • source/graphics/Terrain.h

     
    8585    fixed GetVertexGroundLevelFixed(ssize_t i, ssize_t j) const;
    8686    float GetExactGroundLevel(float x, float z) const;
    8787    fixed GetExactGroundLevelFixed(fixed x, fixed z) const;
     88    void SetExactGroundLevelFixed(fixed new_y, fixed x, fixed z);
    8889    float GetFilteredGroundLevel(float x, float z, float radius) const;
    8990
    9091    // get the approximate slope (0 = horizontal, 0.5 = 30 degrees, 1.0 = 45 degrees, etc)
  • source/simulation2/components/CCmpTerrain.cpp

     
    2525#include "simulation2/MessageTypes.h"
    2626
    2727#include "graphics/Terrain.h"
     28#include "graphics/RenderableObject.h"
    2829
    2930class CCmpTerrain : public ICmpTerrain
    3031{
     
    7980        return m_Terrain->GetExactGroundLevelFixed(x, z);
    8081    }
    8182
     83    virtual void SetGroundLevelRegion(entity_pos_t new_y, entity_pos_t x, entity_pos_t z, fixed width, fixed depth, fixed y_rot)
     84    {
     85        // Initialize dirty region to the center of the given region (coordinates in tile space)
     86        ssize_t xi = x.ToInt_RoundToZero();
     87        ssize_t zi = z.ToInt_RoundToZero();
     88
     89        ssize_t x_min = xi, z_min = zi, x_max = xi + 1, z_max = zi + 1;
     90
     91        // Loop through every integral point in the region
     92        // This treats the region as a grid of points with a cell size of 1
     93        for(fixed i = fixed::FromInt(-1); i < width + fixed::FromInt(1); i += fixed::FromInt(1))
     94        {
     95            for(fixed j = fixed::FromInt(-1); j < width + fixed::FromInt(1); j += fixed::FromInt(1))
     96            {
     97                // Create a vector corresponding to the top left corner of the region
     98                CFixedVector2D v(width / -2 + i, depth / -2 + j);
     99                // Rotate that vector by the rotation of the region
     100                v = v.Rotate(y_rot);
     101
     102                fixed height = new_y;
     103
     104                // Smooth elevation on surrounding tiles by averaging
     105                if(i < fixed::FromInt(0) || i > width || j < fixed::FromInt(0) || j > depth)
     106                {
     107                    fixed current_height = m_Terrain->GetExactGroundLevelFixed(v.X + x, v.Y + z);
     108                    height = (current_height + new_y) / 2;
     109                }
     110
     111                m_Terrain->SetExactGroundLevelFixed(height, v.X + x, v.Y + z);
     112
     113                // Calculate if the current point lies outside known dirty region, converting to tile space
     114                ssize_t x_low = (v.X + x).ToInt_RoundToZero() / TERRAIN_TILE_SIZE;
     115                ssize_t x_high = (v.X + x).ToInt_RoundToInfinity() / TERRAIN_TILE_SIZE;
     116                ssize_t z_low = (v.Y + z).ToInt_RoundToZero() / TERRAIN_TILE_SIZE;
     117                ssize_t z_high = (v.Y + z).ToInt_RoundToInfinity() / TERRAIN_TILE_SIZE;
     118
     119                if(x_low < x_min)
     120                {
     121                    x_min = x_low;
     122                }
     123                else if(x_high > x_max)
     124                {
     125                    x_max = x_high;
     126                }
     127
     128                if(z_low < z_min)
     129                {
     130                    z_min = z_low;
     131                }
     132                else if(z_high > z_max)
     133                {
     134                    z_max = z_high;
     135                }
     136            }
     137        }
     138
     139        // Allow changes to be displayed
     140        // As noted in Terrain.h, this needs to include adjacent tiles that blend in to this one
     141        m_Terrain->MakeDirty(x_min - 1, z_min - 1, x_max + 2, z_max + 2, RENDERDATA_UPDATE_VERTICES);
     142
     143        // Alert any components that are interested that the terrain changes
     144        CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
     145        if (cmpTerrain)
     146            cmpTerrain->MakeDirty(x_min, z_min, x_max, z_max);
     147
     148    }
     149
    82150    virtual float GetExactGroundLevel(float x, float z)
    83151    {
    84152        return m_Terrain->GetExactGroundLevel(x, z);
  • source/simulation2/components/ICmpTerrain.cpp

     
    2323
    2424BEGIN_INTERFACE_WRAPPER(Terrain)
    2525DEFINE_INTERFACE_METHOD_2("GetGroundLevel", entity_pos_t, ICmpTerrain, GetGroundLevel, entity_pos_t, entity_pos_t)
     26DEFINE_INTERFACE_METHOD_6("SetGroundLevelRegion", void, ICmpTerrain, SetGroundLevelRegion, entity_pos_t, entity_pos_t, entity_pos_t, fixed, fixed, fixed)
    2627DEFINE_INTERFACE_METHOD_2("CalcNormal", CFixedVector3D, ICmpTerrain, CalcNormal, entity_pos_t, entity_pos_t)
    2728END_INTERFACE_WRAPPER(Terrain)
  • source/simulation2/components/ICmpTerrain.h

     
    3535
    3636    virtual entity_pos_t GetGroundLevel(entity_pos_t x, entity_pos_t z) = 0;
    3737
     38    virtual void SetGroundLevelRegion(entity_pos_t new_y, entity_pos_t x, entity_pos_t z, fixed width, fixed depth, fixed y_rot) = 0;
     39
    3840    virtual float GetExactGroundLevel(float x, float z) = 0;
    3941
    4042    /**