Ticket #2264: terrainModifier.4.diff
File terrainModifier.4.diff, 45.5 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/simulation/components/TerrainModifier.js
1 function TerrainModifier() {}; 2 3 /* 4 * A component to calculate the height of different vertices for a height changing entity 5 */ 6 TerrainModifier.prototype.Schema = 7 "<element name='Type'>" + 8 "<choice>" + 9 "<value>flatten</value>" + 10 "<value>slopeWall</value>" + 11 "</choice>" + 12 "</element>"; 13 14 TerrainModifier.prototype.GetType = function() 15 { 16 return this.template.Type; 17 }; 18 19 /** 20 * All queried vertices will be in a relative square around this entity, 21 * with as size the value from this method. 22 */ 23 TerrainModifier.prototype.GetBBox = function() 24 { 25 if (this.bBox != undefined) 26 return this.bBox; 27 28 if (!this.footprint) 29 { 30 var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint); 31 this.footprint = cmpFootprint.GetShape(); 32 } 33 if (this.footprint.type == "square") 34 var max = Math.max(this.footprint.width, this.footprint.depth) + 6; 35 else 36 var max = this.footprint.radius * 2 + 6; 37 if (this.GetType() == "flatten") 38 this.bBox = max 39 else 40 this.bBox = Math.max(max, 100); 41 return this.bBox; 42 }; 43 44 /** 45 * Calculate the new height for the relative point 46 * the oldHeight for that point, and the default entity height are given to save CPU time 47 * 48 * Note that the entity height will change when vertices near the centre 49 * are modified in height 50 */ 51 TerrainModifier.prototype.GetNewHeight = function(point, oldHeight, entHeight) 52 { 53 var r = {"height": oldHeight, "weight":0}; 54 switch (this.GetType()) 55 { 56 case "flatten": 57 var w = 0; 58 var fp = this.footprint; 59 // get the max distance from the footprint 60 if (fp.type == "square") 61 w = Math.max(Math.abs(point.x) - fp.width/2, Math.abs(point.y) - fp.depth/2); 62 else 63 w = Math.sqrt(Math.pow(point.x,2) + Math.pow(point.y,2)) - fp.radius; 64 65 // convert to a weight, where w == 1 is inside the footprint, 66 // and w == 0 is far away from the footprint 67 // TODO: turn '6' into a variable, it's the cutoff from which point nothing is changed 68 w = Math.max(Math.min(1 - w/6, 1), 0); 69 r = {"height": (1 - w)*oldHeight + w*entHeight, "weight": w}; 70 break; 71 72 case "slopeWall": 73 if (point.y <= 0 ) 74 { 75 if (point.y > -8 && Math.abs(point.x) < 4) 76 r.weight = 10; 77 break; 78 } 79 var l = 50;// TODO put in variable, and bind with the bbox 80 var newHeight = this.footprint.height*(Math.atan(-7*point.y/l + 3.5) + 1.4)/2.6; 81 if (Math.abs(point.x) > this.footprint.width/2) 82 { 83 var mult = 1/(Math.abs(point.x) - this.footprint.width/2 + 2); 84 r.weight = mult/10; 85 r.height = mult*newHeight + oldHeight; 86 } 87 else 88 { 89 r.weight = (l-Math.abs(point.y))/l; 90 r.height = newHeight + (entHeight*(l - point.y) + oldHeight*point.y)/l; 91 } 92 break; 93 default: 94 warn("unknown terrain modifier type"); 95 break; 96 } 97 return {"x": r.height, "y": r.weight} 98 }; 99 100 TerrainModifier.prototype.OnPositionChanged = function(msg) 101 { 102 var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain); 103 cmpTerrain.MakeVisualTerrainDirty(this.entity, this.bBox); 104 }; 105 106 TerrainModifier.prototype.OnDestroy = function(msg) 107 { 108 var bBox = this.bBox; 109 this.bBox = 0; // disable terrain modifying capabilities of this entity 110 var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain); 111 cmpTerrain.MakeVisualTerrainDirty(this.entity, bBox); 112 }; 113 114 Engine.RegisterComponentType(IID_TerrainModifier, "TerrainModifier", TerrainModifier); 115 -
binaries/data/mods/public/simulation/templates/structures/brit_wall_gate.xml
11 11 <Square width="38.5" depth="9.0"/> 12 12 <Height>9.0</Height> 13 13 </Footprint> 14 <Health> 15 <Max>1500</Max> 16 </Health> 14 17 <Identity> 15 18 <Civ>brit</Civ> 16 19 <SpecificName>Dor</SpecificName> -
binaries/data/mods/public/simulation/templates/structures/brit_wall_long.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_long"> 3 <Armour> 4 <Crush>20</Crush> 5 </Armour> 3 6 <Footprint> 4 <Square width="38.5" depth=" 8.5"/>7 <Square width="38.5" depth="12.5"/> 5 8 <Height>9.0</Height> 6 9 </Footprint> 7 10 <Identity> … … 11 14 <History>The Romans called this wall 'Murus Gallicus'. Translated, it means 'Gaulish wall'. It was extremely resistant to assault by battering ram. Julius Caesar described a type of wood and stone wall, known as a Murus Gallicus, in his account of the Gallic Wars. These walls were made of a stone wall filled with rubble, with wooden logs inside for stability. Caesar noted how the flexibility of the wood added to the strength of the fort in case of battering ram attack.</History> 12 15 </Identity> 13 16 <Obstruction> 14 <Static width="37.0" depth=" 7.0"/>17 <Static width="37.0" depth="10.0"/> 15 18 </Obstruction> 19 <TerrainModifier> 20 <Type> 21 slopeWall 22 </Type> 23 </TerrainModifier> 16 24 <VisualActor> 17 25 <Actor>structures/celts/wall_long.xml</Actor> 18 26 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/brit_wall_medium.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_medium"> 3 <Armour> 4 <Crush>20</Crush> 5 </Armour> 3 6 <Footprint> 4 <Square width="26.5" depth=" 8.5"/>7 <Square width="26.5" depth="12.5"/> 5 8 <Height>9.0</Height> 6 9 </Footprint> 7 10 <Health> … … 14 17 <History>The Romans called this wall 'Murus Gallicus'. Translated, it means 'Gaulish wall'. It was extremely resistant to assault by battering ram. Julius Caesar described a type of wood and stone wall, known as a Murus Gallicus, in his account of the Gallic Wars. These walls were made of a stone wall filled with rubble, with wooden logs inside for stability. Caesar noted how the flexibility of the wood added to the strength of the fort in case of battering ram attack.</History> 15 18 </Identity> 16 19 <Obstruction> 17 <Static width="25.0" depth=" 7.0"/>20 <Static width="25.0" depth="10.0"/> 18 21 </Obstruction> 22 <TerrainModifier> 23 <Type> 24 slopeWall 25 </Type> 26 </TerrainModifier> 19 27 <VisualActor> 20 28 <Actor>structures/celts/wall_medium.xml</Actor> 21 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/brit_wall_short.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_short"> 3 <Armour> 4 <Crush>20</Crush> 5 </Armour> 3 6 <Footprint> 4 <Square width="14.5" depth=" 8.5"/>7 <Square width="14.5" depth="12.5"/> 5 8 <Height>9.0</Height> 6 9 </Footprint> 7 10 <Health> … … 14 17 <History>The Romans called this wall 'Murus Gallicus'. Translated, it means 'Gaulish wall'. It was extremely resistant to assault by battering ram. Julius Caesar described a type of wood and stone wall, known as a Murus Gallicus, in his account of the Gallic Wars. These walls were made of a stone wall filled with rubble, with wooden logs inside for stability. Caesar noted how the flexibility of the wood added to the strength of the fort in case of battering ram attack.</History> 15 18 </Identity> 16 19 <Obstruction> 17 <Static width="13.0" depth=" 7.0"/>20 <Static width="13.0" depth="10.0"/> 18 21 </Obstruction> 22 <TerrainModifier> 23 <Type> 24 slopeWall 25 </Type> 26 </TerrainModifier> 19 27 <VisualActor> 20 28 <Actor>structures/celts/wall_short.xml</Actor> 21 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/brit_wall_tower.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_tower"> 3 3 <Attack disable=""/> 4 <Armour> 5 <Crush>20</Crush> 6 </Armour> 4 7 <Footprint> 5 <Square width="10.0" depth="1 0.0"/>6 <Height> 20.0</Height>8 <Square width="10.0" depth="13.0"/> 9 <Height>9.0</Height> 7 10 </Footprint> 8 11 <GarrisonHolder disable=""/> 9 12 <Identity> … … 13 16 <Tooltip>Does not shoot or garrison.</Tooltip> 14 17 </Identity> 15 18 <Obstruction> 16 <Static width="9.0" depth=" 9.0"/>19 <Static width="9.0" depth="12.0"/> 17 20 </Obstruction> 21 <TerrainModifier> 22 <Type> 23 slopeWall 24 </Type> 25 </TerrainModifier> 18 26 <RallyPoint disable=""/> 19 27 <VisualActor> 20 28 <Actor>structures/celts/wall_tower.xml</Actor> -
binaries/data/mods/public/simulation/templates/structures/celt_wall_gate.xml
11 11 <Square width="38.5" depth="9.0"/> 12 12 <Height>9.0</Height> 13 13 </Footprint> 14 <Health> 15 <Max>1500</Max> 16 </Health> 14 17 <Identity> 15 18 <Civ>celt</Civ> 16 19 <SpecificName>Gate</SpecificName> -
binaries/data/mods/public/simulation/templates/structures/celt_wall_long.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_long"> 3 <Armour> 4 <Crush>20</Crush> 5 </Armour> 3 6 <Footprint> 4 <Square width="38.5" depth=" 8.5"/>7 <Square width="38.5" depth="12.5"/> 5 8 <Height>9.0</Height> 6 9 </Footprint> 7 10 <Identity> … … 11 14 <History>The Romans called this wall 'Murus Gallicus'. Translated, it means 'Gaulish wall'. It was extremely resistant to assault by battering ram. Julius Caesar described a type of wood and stone wall, known as a Murus Gallicus, in his account of the Gallic Wars. These walls were made of a stone wall filled with rubble, with wooden logs inside for stability. Caesar noted how the flexibility of the wood added to the strength of the fort in case of battering ram attack.</History> 12 15 </Identity> 13 16 <Obstruction> 14 <Static width="37.0" depth=" 7.0"/>17 <Static width="37.0" depth="10.0"/> 15 18 </Obstruction> 19 <TerrainModifier> 20 <Type> 21 slopeWall 22 </Type> 23 </TerrainModifier> 16 24 <VisualActor> 17 25 <Actor>structures/celts/wall_long.xml</Actor> 18 26 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/celt_wall_medium.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_medium"> 3 <Armour> 4 <Crush>20</Crush> 5 </Armour> 3 6 <Footprint> 4 <Square width="26.5" depth=" 8.5"/>7 <Square width="26.5" depth="12.5"/> 5 8 <Height>9.0</Height> 6 9 </Footprint> 7 10 <Health> … … 14 17 <History>The Romans called this wall 'Murus Gallicus'. Translated, it means 'Gaulish wall'. It was extremely resistant to assault by battering ram. Julius Caesar described a type of wood and stone wall, known as a Murus Gallicus, in his account of the Gallic Wars. These walls were made of a stone wall filled with rubble, with wooden logs inside for stability. Caesar noted how the flexibility of the wood added to the strength of the fort in case of battering ram attack.</History> 15 18 </Identity> 16 19 <Obstruction> 17 <Static width="25.0" depth=" 7.0"/>20 <Static width="25.0" depth="10.0"/> 18 21 </Obstruction> 22 <TerrainModifier> 23 <Type> 24 slopeWall 25 </Type> 26 </TerrainModifier> 19 27 <VisualActor> 20 28 <Actor>structures/celts/wall_medium.xml</Actor> 21 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/celt_wall_short.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_short"> 3 <Armour> 4 <Crush>20</Crush> 5 </Armour> 3 6 <Footprint> 4 <Square width="14.5" depth=" 8.5"/>7 <Square width="14.5" depth="12.5"/> 5 8 <Height>9.0</Height> 6 9 </Footprint> 7 10 <Health> … … 14 17 <History>The Romans called this wall 'Murus Gallicus'. Translated, it means 'Gaulish wall'. It was extremely resistant to assault by battering ram. Julius Caesar described a type of wood and stone wall, known as a Murus Gallicus, in his account of the Gallic Wars. These walls were made of a stone wall filled with rubble, with wooden logs inside for stability. Caesar noted how the flexibility of the wood added to the strength of the fort in case of battering ram attack.</History> 15 18 </Identity> 16 19 <Obstruction> 17 <Static width="13.0" depth=" 7.0"/>20 <Static width="13.0" depth="10.0"/> 18 21 </Obstruction> 22 <TerrainModifier> 23 <Type> 24 slopeWall 25 </Type> 26 </TerrainModifier> 19 27 <VisualActor> 20 28 <Actor>structures/celts/wall_short.xml</Actor> 21 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/celt_wall_tower.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_tower"> 3 3 <Attack disable=""/> 4 <Armour> 5 <Crush>20</Crush> 6 </Armour> 4 7 <Footprint> 5 <Square width="10.0" depth="1 0.0"/>6 <Height> 20.0</Height>8 <Square width="10.0" depth="13.0"/> 9 <Height>9.0</Height> 7 10 </Footprint> 8 11 <GarrisonHolder disable=""/> 9 12 <Identity> … … 13 16 <Tooltip>Does not shoot or garrison.</Tooltip> 14 17 </Identity> 15 18 <Obstruction> 16 <Static width="9.0" depth=" 9.0"/>19 <Static width="9.0" depth="12.0"/> 17 20 </Obstruction> 18 21 <RallyPoint disable=""/> 22 <TerrainModifier> 23 <Type> 24 slopeWall 25 </Type> 26 </TerrainModifier> 19 27 <VisualActor> 20 28 <Actor>structures/celts/wall_tower.xml</Actor> 21 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/gaul_wall_gate.xml
11 11 <Square width="38.5" depth="9.0"/> 12 12 <Height>9.0</Height> 13 13 </Footprint> 14 <Health> 15 <Max>1500</Max> 16 </Health> 14 17 <Identity> 15 18 <Civ>gaul</Civ> 16 19 <SpecificName>Duro</SpecificName> -
binaries/data/mods/public/simulation/templates/structures/gaul_wall_long.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_long"> 3 <Armour> 4 <Crush>20</Crush> 5 </Armour> 3 6 <Footprint> 4 <Square width="38.5" depth=" 8.5"/>7 <Square width="38.5" depth="12.5"/> 5 8 <Height>9.0</Height> 6 9 </Footprint> 7 10 <Identity> … … 11 14 <History>The Romans called this wall 'Murus Gallicus'. Translated, it means 'Gaulish wall'. It was extremely resistant to assault by battering ram. Julius Caesar described a type of wood and stone wall, known as a Murus Gallicus, in his account of the Gallic Wars. These walls were made of a stone wall filled with rubble, with wooden logs inside for stability. Caesar noted how the flexibility of the wood added to the strength of the fort in case of battering ram attack.</History> 12 15 </Identity> 13 16 <Obstruction> 14 <Static width="37.0" depth=" 7.0"/>17 <Static width="37.0" depth="10.0"/> 15 18 </Obstruction> 19 <TerrainModifier> 20 <Type> 21 slopeWall 22 </Type> 23 </TerrainModifier> 16 24 <VisualActor> 17 25 <Actor>structures/celts/wall_long.xml</Actor> 18 26 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/gaul_wall_medium.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_medium"> 3 <Armour> 4 <Crush>20</Crush> 5 </Armour> 3 6 <Footprint> 4 <Square width="26.5" depth=" 8.5"/>7 <Square width="26.5" depth="12.5"/> 5 8 <Height>9.0</Height> 6 9 </Footprint> 7 10 <Health> … … 14 17 <History>The Romans called this wall 'Murus Gallicus'. Translated, it means 'Gaulish wall'. It was extremely resistant to assault by battering ram. Julius Caesar described a type of wood and stone wall, known as a Murus Gallicus, in his account of the Gallic Wars. These walls were made of a stone wall filled with rubble, with wooden logs inside for stability. Caesar noted how the flexibility of the wood added to the strength of the fort in case of battering ram attack.</History> 15 18 </Identity> 16 19 <Obstruction> 17 <Static width="25.0" depth=" 7.0"/>20 <Static width="25.0" depth="10.0"/> 18 21 </Obstruction> 22 <TerrainModifier> 23 <Type> 24 slopeWall 25 </Type> 26 </TerrainModifier> 19 27 <VisualActor> 20 28 <Actor>structures/celts/wall_medium.xml</Actor> 21 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/gaul_wall_short.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_short"> 3 <Armour> 4 <Crush>20</Crush> 5 </Armour> 3 6 <Footprint> 4 <Square width="14.5" depth=" 8.5"/>7 <Square width="14.5" depth="12.5"/> 5 8 <Height>9.0</Height> 6 9 </Footprint> 7 10 <Health> … … 14 17 <History>The Romans called this wall 'Murus Gallicus'. Translated, it means 'Gaulish wall'. It was extremely resistant to assault by battering ram. Julius Caesar described a type of wood and stone wall, known as a Murus Gallicus, in his account of the Gallic Wars. These walls were made of a stone wall filled with rubble, with wooden logs inside for stability. Caesar noted how the flexibility of the wood added to the strength of the fort in case of battering ram attack.</History> 15 18 </Identity> 16 19 <Obstruction> 17 <Static width="13.0" depth=" 7.0"/>20 <Static width="13.0" depth="10.0"/> 18 21 </Obstruction> 22 <TerrainModifier> 23 <Type> 24 slopeWall 25 </Type> 26 </TerrainModifier> 19 27 <VisualActor> 20 28 <Actor>structures/celts/wall_short.xml</Actor> 21 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/gaul_wall_tower.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_structure_defense_wall_tower"> 3 3 <Attack disable=""/> 4 <Armour> 5 <Crush>20</Crush> 6 </Armour> 4 7 <Footprint> 5 <Square width="10.0" depth="1 0.0"/>6 <Height> 20.0</Height>8 <Square width="10.0" depth="13.0"/> 9 <Height>9.0</Height> 7 10 </Footprint> 8 11 <GarrisonHolder disable=""/> 9 12 <Identity> … … 13 16 <Tooltip>Does not shoot or garrison.</Tooltip> 14 17 </Identity> 15 18 <Obstruction> 16 <Static width="9.0" depth=" 9.0"/>19 <Static width="9.0" depth="12.0"/> 17 20 </Obstruction> 21 <TerrainModifier> 22 <Type> 23 slopeWall 24 </Type> 25 </TerrainModifier> 18 26 <RallyPoint disable=""/> 19 27 <VisualActor> 20 28 <Actor>structures/celts/wall_tower.xml</Actor> -
binaries/data/mods/public/simulation/templates/structures/iber_house.xml
19 19 <Radius>16</Radius> 20 20 <Weight>65536</Weight> 21 21 </TerritoryInfluence> 22 <TerrainModifier> 23 <Type> 24 flatten 25 </Type> 26 </TerrainModifier> 22 27 <VisualActor> 23 28 <Actor>structures/iberians/house.xml</Actor> 24 29 <FoundationActor>structures/fndn_2x2.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/template_structure_defense_wall.xml
48 48 <Radius>20</Radius> 49 49 <Weight>65536</Weight> 50 50 </TerritoryInfluence> 51 <TerrainModifier disable=""/> 51 52 <Vision> 52 53 <Range>20</Range> 53 54 </Vision> -
binaries/data/mods/public/simulation/templates/template_structure_defense_wall_long.xml
10 10 <SpawnEntityOnDeath>rubble/rubble_stone_wall_long</SpawnEntityOnDeath> 11 11 </Health> 12 12 <Identity> 13 <Classes datatype="tokens">LongWall</Classes> 14 <Tooltip>Long wall segments can be converted to gates.</Tooltip> 15 </Identity> 16 </Entity> 13 <Classes datatype="tokens">LongWall</Classes> 14 <Tooltip>Long wall segments can be converted to gates.</Tooltip> 15 </Identity> 16 </Entity> -
binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml
85 85 <StatusBars> 86 86 <HeightOffset>20.0</HeightOffset> 87 87 </StatusBars> 88 <TerrainModifier disable=""/> 88 89 <TerritoryInfluence> 89 90 <Root>false</Root> 90 91 <Radius>20</Radius> -
binaries/data/mods/public/simulation/templates/template_structure_military_dock.xml
53 53 </SoundGroups> 54 54 </Sound> 55 55 <TerritoryDecay disable=""/> 56 <TerrainModifier disable=""/> 56 57 <ProductionQueue> 57 58 <BatchTimeModifier>0.8</BatchTimeModifier> 58 59 <Entities datatype="tokens"> -
source/graphics/MapReader.cpp
218 218 // - data: map size, heightmap, list of textures used by map, texture tile assignments 219 219 int CMapReader::UnpackTerrain() 220 220 { 221 printf("start unpackTerrain\n"); 221 222 // yield after this time is reached. balances increased progress bar 222 223 // smoothness vs. slowing down loading. 223 224 const double end_time = timer_Time() + 200e-3; … … 260 261 261 262 // reset generator state. 262 263 cur_terrain_tex = 0; 264 printf("stop unpackTerrain\n"); 263 265 264 266 return 0; 265 267 } … … 267 269 // ApplyData: take all the input data, and rebuild the scene from it 268 270 int CMapReader::ApplyData() 269 271 { 272 printf("start ApplyData\n"); 270 273 if (m_PatchesPerSide == 0) 271 274 { 272 275 // we'll probably crash when trying to use this map later … … 330 333 CmpPtr<ICmpTerrain> cmpTerrain(*pSimContext, SYSTEM_ENTITY); 331 334 if (cmpTerrain) 332 335 cmpTerrain->ReloadTerrain(); 336 printf("stop ApplyData\n"); 333 337 334 338 return 0; 335 339 } -
source/graphics/Terrain.cpp
40 40 /////////////////////////////////////////////////////////////////////////////// 41 41 // CTerrain constructor 42 42 CTerrain::CTerrain() 43 : m_ Heightmap(0), m_Patches(0), m_MapSize(0), m_MapSizePatches(0),43 : m_VisualHeightmap(0), m_OrigHeightmap(0), m_Patches(0), m_MapSize(0), m_MapSizePatches(0), 44 44 m_BaseColour(255, 255, 255, 255) 45 45 { 46 46 } … … 59 59 { 60 60 m_HeightMipmap.ReleaseData(); 61 61 62 delete[] m_Heightmap; 62 delete[] m_VisualHeightmap; 63 delete[] m_OrigHeightmap; 63 64 delete[] m_Patches; 64 65 } 65 66 … … 76 77 m_MapSize = patchesPerSide*PATCH_SIZE+1; 77 78 m_MapSizePatches = patchesPerSide; 78 79 // allocate data for new terrain 79 m_Heightmap = new u16[m_MapSize*m_MapSize]; 80 m_VisualHeightmap = new u16[m_MapSize*m_MapSize]; 81 m_OrigHeightmap = new u16[m_MapSize*m_MapSize]; 82 m_Heightmap = m_VisualHeightmap; 80 83 m_Patches = new CPatch[m_MapSizePatches*m_MapSizePatches]; 81 84 82 85 // given a heightmap? … … 83 86 if (data) 84 87 { 85 88 // yes; keep a copy of it 86 memcpy(m_Heightmap, data, m_MapSize*m_MapSize*sizeof(u16)); 89 memcpy(m_OrigHeightmap, data, m_MapSize*m_MapSize*sizeof(u16)); 90 memcpy(m_VisualHeightmap, data, m_MapSize*m_MapSize*sizeof(u16)); 87 91 } 88 92 else 89 93 { 90 94 // build a flat terrain 91 memset(m_Heightmap, 0, m_MapSize*m_MapSize*sizeof(u16)); 95 memset(m_OrigHeightmap, 0, m_MapSize*m_MapSize*sizeof(u16)); 96 memset(m_VisualHeightmap, 0, m_MapSize*m_MapSize*sizeof(u16)); 92 97 } 93 98 94 99 // setup patch parents, indices etc … … 95 100 InitialisePatches(); 96 101 97 102 // initialise mipmap 98 m_HeightMipmap.Initialize(m_MapSize, m_ Heightmap);103 m_HeightMipmap.Initialize(m_MapSize, m_VisualHeightmap); 99 104 100 105 return true; 101 106 } 102 107 103 108 /////////////////////////////////////////////////////////////////////////////// 109 // Switch between querying the original height map or the visual height map 110 // For most purposes, querying the visual height map is best as it confirms what the player sees 111 void CTerrain::WorkOnOrigHeightMap(bool f) 112 { 113 if (f) 114 m_Heightmap = m_OrigHeightmap; 115 else 116 m_Heightmap = m_VisualHeightmap; 117 } 104 118 119 ////////////////////////////////////////////////////////////////////////////// 120 // Get the 8-bit movement class used in the pathfinder 105 121 CStr8 CTerrain::GetMovementClass(ssize_t i, ssize_t j) const 106 122 { 107 123 CMiniPatch* tile = GetTile(i, j); … … 460 476 461 477 // allocate data for new terrain 462 478 ssize_t newMapSize=size*PATCH_SIZE+1; 463 u16* newHeightmap=new u16[newMapSize*newMapSize]; 479 u16* newOrigHeightmap=new u16[newMapSize*newMapSize]; 480 u16* newVisualHeightmap=new u16[newMapSize*newMapSize]; 464 481 CPatch* newPatches=new CPatch[size*size]; 465 482 466 483 if (size>m_MapSizePatches) { 467 484 // new map is bigger than old one - zero the heightmap so we don't get uninitialised 468 485 // height data along the expanded edges 469 memset(newHeightmap,0,newMapSize*newMapSize*sizeof(u16)); 486 memset(newOrigHeightmap,0,newMapSize*newMapSize*sizeof(u16)); 487 memset(newVisualHeightmap,0,newMapSize*newMapSize*sizeof(u16)); 470 488 } 471 489 472 490 // now copy over rows of data 473 u16* src=m_Heightmap; 474 u16* dst=newHeightmap; 491 u16* src1=m_VisualHeightmap; 492 u16* src2=m_OrigHeightmap; 493 u16* dst1=newVisualHeightmap; 494 u16* dst2=newOrigHeightmap; 475 495 ssize_t copysize=std::min(newMapSize, m_MapSize); 476 496 for (ssize_t j=0;j<copysize;j++) { 477 memcpy(dst,src,copysize*sizeof(u16)); 478 dst+=copysize; 479 src+=m_MapSize; 497 memcpy(dst1,src1,copysize*sizeof(u16)); 498 memcpy(dst2,src2,copysize*sizeof(u16)); 499 dst1+=copysize; 500 dst2+=copysize; 501 src1+=m_MapSize; 502 src2+=m_MapSize; 480 503 if (newMapSize>m_MapSize) { 481 504 // extend the last height to the end of the row 482 505 for (size_t i=0;i<newMapSize-(size_t)m_MapSize;i++) { 483 *dst++=*(src-1); 506 *dst1++=*(src1-1); 507 *dst2++=*(src2-1); 484 508 } 485 509 } 486 510 } … … 488 512 489 513 if (newMapSize>m_MapSize) { 490 514 // copy over heights of the last row to any remaining rows 491 src=newHeightmap+((m_MapSize-1)*newMapSize); 492 dst=src+newMapSize; 515 src1=newVisualHeightmap+((m_MapSize-1)*newMapSize); 516 src2=newOrigHeightmap+((m_MapSize-1)*newMapSize); 517 dst1=src1+newMapSize; 518 dst2=src2+newMapSize; 493 519 for (ssize_t i=0;i<newMapSize-m_MapSize;i++) { 494 memcpy(dst,src,newMapSize*sizeof(u16)); 495 dst+=newMapSize; 520 memcpy(dst1,src1,newMapSize*sizeof(u16)); 521 memcpy(dst2,src2,newMapSize*sizeof(u16)); 522 dst1+=newMapSize; 523 dst2+=newMapSize; 496 524 } 497 525 } 498 526 … … 543 571 ReleaseData(); 544 572 545 573 // store new data 546 m_Heightmap=newHeightmap; 574 m_VisualHeightmap=newVisualHeightmap; 575 m_OrigHeightmap=newOrigHeightmap; 576 m_Heightmap=newVisualHeightmap; 547 577 m_Patches=newPatches; 548 578 m_MapSize=(ssize_t)newMapSize; 549 579 m_MapSizePatches=(ssize_t)size; … … 575 605 void CTerrain::SetHeightMap(u16* heightmap) 576 606 { 577 607 // keep a copy of the given heightmap 578 memcpy(m_Heightmap, heightmap, m_MapSize*m_MapSize*sizeof(u16)); 608 memcpy(m_VisualHeightmap, heightmap, m_MapSize*m_MapSize*sizeof(u16)); 609 memcpy(m_OrigHeightmap, heightmap, m_MapSize*m_MapSize*sizeof(u16)); 579 610 580 611 // recalculate patch bounds, invalidate vertices 581 612 for (ssize_t j = 0; j < m_MapSizePatches; j++) -
source/graphics/Terrain.h
101 101 void SetHeightMap(u16* heightmap); 102 102 // return a pointer to the heightmap 103 103 u16* GetHeightMap() const { return m_Heightmap; } 104 u16* GetVisualHeightMap() const { return m_VisualHeightmap; } 105 u16* GetOrigHeightMap() const { return m_OrigHeightmap; } 104 106 107 void WorkOnOrigHeightMap(bool f); 108 105 109 // get patch at given coordinates, expressed in patch-space; return 0 if 106 110 // coordinates represent patch off the edge of the map 107 111 CPatch* GetPatch(ssize_t i, ssize_t j) const; … … 169 173 CPatch* m_Patches; 170 174 // 16-bit heightmap data 171 175 u16* m_Heightmap; 176 u16* m_VisualHeightmap; 177 u16* m_OrigHeightmap; 172 178 // base colour (usually white) 173 179 SColor4ub m_BaseColour; 174 180 // heightmap mipmap -
source/simulation2/TypeList.h
148 148 INTERFACE(Terrain) 149 149 COMPONENT(Terrain) 150 150 151 INTERFACE(TerrainModifier) 152 COMPONENT(TerrainModifierScripted) 153 151 154 INTERFACE(TerritoryInfluence) 152 155 COMPONENT(TerritoryInfluence) 153 156 -
source/simulation2/components/CCmpTerrain.cpp
20 20 #include "simulation2/system/Component.h" 21 21 #include "ICmpTerrain.h" 22 22 23 #include "ICmpTerrainModifier.h" 23 24 #include "ICmpObstructionManager.h" 24 25 #include "ICmpRangeManager.h" 26 #include "ICmpPosition.h" 25 27 #include "simulation2/MessageTypes.h" 28 #include "simulation2/helpers/Geometry.h" 26 29 27 30 #include "graphics/Terrain.h" 28 31 #include "renderer/Renderer.h" 29 32 #include "renderer/WaterManager.h" 33 #include "graphics/Patch.h" 34 #include "maths/MathUtil.h" 30 35 #include "maths/Vector3D.h" 31 36 32 37 class CCmpTerrain : public ICmpTerrain … … 68 73 return m_Terrain->GetVerticesPerSide() != 0; 69 74 } 70 75 76 77 virtual u16* GetSimHeightMap() 78 { 79 return m_Terrain->GetOrigHeightMap(); 80 } 81 82 virtual void MakeVisualTerrainDirty(entity_id_t ent, fixed bBox) 83 { 84 if (m_Terrain->GetPatchesPerSide()) 85 RecalculateVisualHeightmap(ent, bBox); 86 } 87 71 88 virtual CFixedVector3D CalcNormal(entity_pos_t x, entity_pos_t z) 72 89 { 73 90 CFixedVector3D normal; … … 83 100 virtual entity_pos_t GetGroundLevel(entity_pos_t x, entity_pos_t z) 84 101 { 85 102 // TODO: this can crash if the terrain heightmap isn't initialised yet 86 87 103 return m_Terrain->GetExactGroundLevelFixed(x, z); 88 104 } 89 105 … … 102 118 virtual u16 GetVerticesPerSide() 103 119 { 104 120 ssize_t vertices = m_Terrain->GetVerticesPerSide(); 105 ENSURE(1 < =vertices && vertices <= 65535);121 ENSURE(1 < vertices && vertices <= 65535); 106 122 return (u16)vertices; 107 123 } 108 124 … … 111 127 return m_Terrain; 112 128 } 113 129 130 struct IterateHeightmapAverage 131 { 132 u16* resultHeightmap; 133 int pitch; 134 135 // weighted sum of the wanted heights 136 fixed* avgHeightmap; 137 // sum of the weights 138 fixed* sumWeightmap; 139 140 void operator()(int i, int j, fixed weight, fixed newHeight) 141 { 142 if (weight > fixed::Zero()) 143 { 144 fixed sumWeight = sumWeightmap[i+j*pitch] + weight; 145 // avoid overflows by dividing before multiplying 146 avgHeightmap[i+j*pitch] = (avgHeightmap[i+j*pitch]/sumWeight).Multiply(sumWeightmap[i+j*pitch]) + (newHeight/sumWeight).Multiply(weight); 147 148 sumWeightmap[i+j*pitch] = sumWeight; 149 int h = HEIGHT_UNITS_PER_METRE*avgHeightmap[i+j*pitch].ToInt_RoundToNearest(); 150 resultHeightmap[i + j*pitch] = Clamp(h, 0, 65535); 151 } 152 } 153 }; 154 155 template<typename T> 156 void IterateHeightmap(T& callback, CFixedVector2D pos, fixed angle, entity_id_t ent, int iMin, int jMin, int iMax, int jMax) 157 { 158 CmpPtr<ICmpTerrainModifier> CCmpTerrainModifier(GetSimContext(), ent); 159 // get the bbox, multiply by sqrt(2)/2 (rounded up) to get half the size and take 160 // account of possible rotations 161 fixed BBoxSize = CCmpTerrainModifier->GetBBox()/2; 162 fixed maxBBoxSize = BBoxSize*142/100; 163 int numVerts = GetVerticesPerSide(); 164 165 int i0 = ((pos.X - maxBBoxSize) / TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(); 166 int i1 = ((pos.X + maxBBoxSize) / TERRAIN_TILE_SIZE).ToInt_RoundToInfinity(); 167 int j0 = ((pos.Y - maxBBoxSize) / TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(); 168 int j1 = ((pos.Y + maxBBoxSize) / TERRAIN_TILE_SIZE).ToInt_RoundToInfinity(); 169 i0 = Clamp(i0, iMin, numVerts); 170 i1 = Clamp(i1, 0, iMax); 171 j0 = Clamp(j0, jMin, numVerts); 172 j1 = Clamp(j1, 0, jMax); 173 174 fixed entHeight = m_Terrain->GetExactGroundLevelFixed(pos.X, pos.Y); 175 for (int j = j0; j <= j1; ++j) 176 { 177 for (int i = i0; i <= i1; ++i) 178 { 179 CFixedVector2D pt = CFixedVector2D(fixed::FromInt(i*TERRAIN_TILE_SIZE), fixed::FromInt(j*TERRAIN_TILE_SIZE)) - CFixedVector2D(pos.X, pos.Y); 180 pt = pt.Rotate(-angle); 181 if (pt.X.Absolute() > BBoxSize || pt.Y.Absolute() > BBoxSize) 182 continue; 183 fixed oldHeight = m_Terrain->GetVertexGroundLevelFixed(i, j); 184 fixed newHeight, weight; 185 CCmpTerrainModifier->GetNewHeight(pt, oldHeight, entHeight, newHeight, weight); 186 callback(i, j, weight, newHeight); 187 } 188 } 189 MakeDirty(i0, j0, i1, j1); 190 } 191 192 void RecalculateVisualHeightmap(entity_id_t ent, fixed bBox) 193 { 194 u16* origHeightmap = m_Terrain->GetOrigHeightMap(); 195 u16* visualHeightmap = m_Terrain->GetVisualHeightMap(); 196 m_Terrain->WorkOnOrigHeightMap(true); 197 int pitch = GetVerticesPerSide(); 198 199 IterateHeightmapAverage callback; 200 callback.resultHeightmap = visualHeightmap; 201 callback.pitch = pitch; 202 std::vector<fixed> avgHeightmap(pitch * pitch, fixed::Zero()); 203 callback.avgHeightmap = &avgHeightmap[0]; 204 std::vector<fixed> sumWeightmap(pitch * pitch, fixed::Zero()); 205 callback.sumWeightmap = &sumWeightmap[0]; 206 207 int iMin, jMin, iMax, jMax; 208 iMin = jMin = 0; 209 iMax = jMax = GetVerticesPerSide(); 210 // TODO Halp, why does it CRASHSSSHSSHS? 211 /*if (ent != INVALID_ENTITY) 212 { 213 CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), ent); 214 if (cmpPosition && cmpPosition->IsInWorld()) 215 { 216 CFixedVector2D posMin, posMax; 217 posMin = cmpPosition->GetPosition2D(); 218 posMax = cmpPosition->GetPreviousPosition2D(); 219 if (posMin.X > posMax.X) 220 { 221 fixed c = posMax.X; 222 posMax.X = posMin.X; 223 posMin.X = c; 224 } 225 if (posMin.Y > posMax.Y) 226 { 227 fixed c = posMax.Y; 228 posMax.Y = posMin.Y; 229 posMin.Y = c; 230 } 231 232 fixed maxBBoxSize = bBox*142/200; 233 int numVerts = GetVerticesPerSide(); 234 235 iMin = ((posMin.X - maxBBoxSize) / TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(); 236 iMax = ((posMax.X + maxBBoxSize) / TERRAIN_TILE_SIZE).ToInt_RoundToInfinity() + 1; 237 jMin = ((posMin.Y - maxBBoxSize) / TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(); 238 jMax = ((posMax.Y + maxBBoxSize) / TERRAIN_TILE_SIZE).ToInt_RoundToInfinity() + 1; 239 iMin = Clamp(iMin, 0, numVerts); 240 iMax = Clamp(iMax, 0, numVerts); 241 jMin = Clamp(jMin, 0, numVerts); 242 jMax = Clamp(jMax, 0, numVerts); 243 } 244 } 245 // reset the visual heightmap for the found region 246 for (int j = jMin; j < jMax; ++j) 247 for (int i = iMin; i < iMax; ++i) 248 visualHeightmap[i + j*pitch] = origHeightmap[i + j*pitch]; 249 */ 250 memcpy(visualHeightmap, origHeightmap, pitch*pitch*sizeof(u16)); 251 252 // recalculate the visual heightmap by iterating over all entities with the 253 // TerrainModifier component 254 CComponentManager::InterfaceList ents = GetSimContext().GetComponentManager().GetEntitiesWithInterface(IID_TerrainModifier); 255 for (CComponentManager::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it) 256 { 257 CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), it->first); 258 if (cmpPosition && cmpPosition->IsInWorld()) 259 { 260 CFixedVector2D pos = cmpPosition->GetPosition2D(); 261 fixed angle = cmpPosition->GetRotation().Y; 262 263 IterateHeightmap(callback, pos, angle, it->first, iMin, jMin, iMax, jMax); 264 } 265 } 266 267 m_Terrain->WorkOnOrigHeightMap(false); 268 m_Terrain->MakeDirty(RENDERDATA_UPDATE_VERTICES); 269 } 270 114 271 virtual void ReloadTerrain() 115 272 { 116 273 // TODO: should refactor this code to be nicer 117 118 274 u16 tiles = GetTilesPerSide(); 119 275 u16 vertices = GetVerticesPerSide(); 120 276 … … 138 294 if (CRenderer::IsInitialised()) 139 295 g_Renderer.GetWaterManager()->SetMapSize(vertices); 140 296 141 MakeDirty(0, 0, tiles+1, tiles+1); 297 MakeDirty(0, 0, tiles + 1, tiles + 1); 298 MakeVisualTerrainDirty(INVALID_ENTITY, fixed::Zero()); 142 299 } 143 300 144 301 virtual void MakeDirty(i32 i0, i32 j0, i32 i1, i32 j1) -
source/simulation2/components/ICmpTerrain.cpp
25 25 DEFINE_INTERFACE_METHOD_2("GetGroundLevel", entity_pos_t, ICmpTerrain, GetGroundLevel, entity_pos_t, entity_pos_t) 26 26 DEFINE_INTERFACE_METHOD_2("CalcNormal", CFixedVector3D, ICmpTerrain, CalcNormal, entity_pos_t, entity_pos_t) 27 27 DEFINE_INTERFACE_METHOD_0("GetTilesPerSide", u16, ICmpTerrain, GetTilesPerSide) 28 DEFINE_INTERFACE_METHOD_2("MakeVisualTerrainDirty", void, ICmpTerrain, MakeVisualTerrainDirty, entity_id_t, fixed) 28 29 END_INTERFACE_WRAPPER(Terrain) -
source/simulation2/components/ICmpTerrain.h
32 32 public: 33 33 virtual bool IsLoaded() = 0; 34 34 35 virtual u16* GetSimHeightMap() = 0; 36 37 virtual void MakeVisualTerrainDirty(entity_id_t ent, entity_pos_t bBox) = 0; 38 35 39 virtual CFixedVector3D CalcNormal(entity_pos_t x, entity_pos_t z) = 0; 36 40 37 41 virtual CVector3D CalcExactNormal(float x, float z) = 0; -
source/simulation2/components/ICmpTerrainModifier.cpp
1 /* Copyright (C) 2013 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 20 #include "ICmpTerrainModifier.h" 21 22 #include "simulation2/system/InterfaceScripted.h" 23 #include "simulation2/scripting/ScriptComponent.h" 24 25 BEGIN_INTERFACE_WRAPPER(TerrainModifier) 26 END_INTERFACE_WRAPPER(TerrainModifier) 27 28 29 class CCmpTerrainModifierScripted : public ICmpTerrainModifier 30 { 31 public: 32 DEFAULT_SCRIPT_WRAPPER(TerrainModifierScripted) 33 34 virtual fixed GetBBox() 35 { 36 return m_Script.Call<fixed>("GetBBox"); 37 } 38 39 virtual void GetNewHeight(CFixedVector2D relPt, fixed oldHeight, fixed entHeight, fixed& newHeight, fixed& weight) 40 { 41 // TODO Use std::vector<float> instead??? 42 CFixedVector2D v = m_Script.Call<CFixedVector2D>("GetNewHeight", relPt, oldHeight, entHeight); 43 newHeight = v.X; 44 weight = v.Y; 45 } 46 }; 47 48 REGISTER_COMPONENT_SCRIPT_WRAPPER(TerrainModifierScripted) 49 -
source/simulation2/components/ICmpTerrainModifier.h
1 /* Copyright (C) 2013 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef INCLUDED_ICMPTERRAINMODIFIER 19 #define INCLUDED_ICMPTERRAINMODIFIER 20 21 #include "simulation2/system/Interface.h" 22 23 #include "simulation2/helpers/Position.h" 24 #include "maths/FixedVector2D.h" 25 26 class ICmpTerrainModifier : public IComponent 27 { 28 public: 29 30 /** 31 * the BBox size of vertices that certainly need to be queried 32 * other vertices outside the BBox can also be queried, but shouldn't influence the terrain 33 */ 34 virtual fixed GetBBox() = 0; 35 36 37 virtual void GetNewHeight(CFixedVector2D relPt, fixed oldHeight, fixed entHeight, fixed& newHeight, fixed& weight) = 0; 38 39 DECLARE_INTERFACE_TYPE(TerrainModifier) 40 }; 41 42 #endif // INCLUDED_ICMPTERRAINMODIFIER -
source/simulation2/system/ComponentTest.h
229 229 virtual void ReloadTerrain() 230 230 { 231 231 } 232 233 virtual void MakeVisualTerrainDirty(entity_id_t UNUSED(ent), entity_pos_t UNUSED(bBox)) 234 { 235 } 236 237 virtual u16* GetSimHeightMap() 238 { 239 return NULL; 240 } 232 241 }; -
source/tools/atlas/GameInterface/Handlers/ElevationHandlers.cpp
41 41 void Init() 42 42 { 43 43 m_Heightmap = g_Game->GetWorld()->GetTerrain()->GetHeightMap(); 44 CmpPtr<ICmpTerrain> cmpTerrain(*g_Game->GetSimulation2(), SYSTEM_ENTITY); 45 if (cmpTerrain) 46 m_SimHeightmap = cmpTerrain->GetSimHeightMap(); 44 47 m_VertsPerSide = g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide(); 45 48 } 46 49 … … 90 93 void setNew(ssize_t x, ssize_t y, const u16& val) 91 94 { 92 95 m_Heightmap[y*m_VertsPerSide + x] = val; 96 if (m_SimHeightmap) 97 m_SimHeightmap[y*m_VertsPerSide + x] = val; 93 98 } 94 99 95 100 u16* m_Heightmap; 101 u16* m_SimHeightmap; 96 102 ssize_t m_VertsPerSide; 97 103 }; 98 104