Ticket #824: 824_selection_rings_21apr12.patch
File 824_selection_rings_21apr12.patch, 121.5 KB (added by , 12 years ago) |
---|
-
binaries/data/mods/public/shaders/arb/overlayline.fp
diff --git a/binaries/data/mods/public/shaders/arb/overlayline.fp b/binaries/data/mods/public/shaders/arb/overlayline.fp index fd78472..bde918c 100644
a b TEMP base; 4 4 TEMP mask; 5 5 TEMP color; 6 6 7 8 7 // Combine base texture and color, using mask texture 9 8 TEX base, fragment.texcoord[0], texture[0], 2D; 10 9 TEX mask, fragment.texcoord[0], texture[1], 2D; 11 LRP color.rgb, mask, objectColor, base; 10 #if USE_OBJECTCOLOR 11 LRP color.rgb, mask, objectColor, base; 12 #else 13 LRP color.rgb, mask, fragment.color, base; 14 #endif 12 15 13 #if defIGNORE_LOS16 #if IGNORE_LOS 14 17 MOV result.color.rgb, color; 15 18 #else 16 19 // Multiply RGB by LOS texture (alpha channel) … … LRP color.rgb, mask, objectColor, base; 19 22 MUL result.color.rgb, color, los.a; 20 23 #endif 21 24 22 // Use alpha from base texture, combined with the object color alpha. 23 // The latter is usually 1, so this basically comes down to base.a 24 MUL result.color.a, objectColor.a, base.a; 25 25 // Use alpha from base texture, combined with the object color/fragment alpha. 26 #if USE_OBJECTCOLOR 27 MUL result.color.a, objectColor.a, base.a; 28 #else 29 MUL result.color.a, fragment.color.a, base.a; 30 #endif 26 31 27 32 END -
binaries/data/mods/public/shaders/arb/overlayline.xml
diff --git a/binaries/data/mods/public/shaders/arb/overlayline.xml b/binaries/data/mods/public/shaders/arb/overlayline.xml index 07383bc..6dd0031 100644
a b 1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <program type="arb"> 3 3 4 <!-- This shader is used for rendering overlay lines (e.g. territory boundaries), and also for 5 rendering the unit selection ring quad overlays, since they are almost identical. The only 6 difference is that in unit selection ring mode, the uniform objectColor is ignored and instead 7 replaced by a color stream from the vertices. The USE_OBJECTCOLOR define is used to switch 8 between either mode. --> 9 4 10 <vertex file="arb/overlayline.vp"> 5 11 <stream name="pos"/> 6 12 <stream name="uv0"/> 13 <stream name="color" if="!USE_OBJECTCOLOR"/> 7 14 <uniform name="losTransform" loc="0" type="vec2"/> 8 15 </vertex> 9 16 … … 11 18 <uniform name="baseTex" loc="0" type="sampler2D"/> 12 19 <uniform name="maskTex" loc="1" type="sampler2D"/> 13 20 <uniform name="losTex" loc="2" type="sampler2D"/> 14 <uniform name="objectColor" loc="0" type="vec3" />21 <uniform name="objectColor" loc="0" type="vec3" if="USE_OBJECTCOLOR"/> 15 22 </fragment> 16 23 17 24 </program> -
binaries/data/mods/public/simulation/components/GuiInterface.js
diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js index 4be58ad..4d458dd 100644
a b GuiInterface.prototype.IsStanceSelected = function(player, data) 495 495 GuiInterface.prototype.SetSelectionHighlight = function(player, cmd) 496 496 { 497 497 var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); 498 499 498 var playerColours = {}; // cache of owner -> colour map 500 499 501 500 for each (var ent in cmd.entities) … … GuiInterface.prototype.SetSelectionHighlight = function(player, cmd) 504 503 if (!cmpSelectable) 505 504 continue; 506 505 507 if (cmd.alpha == 0)508 {509 cmpSelectable.SetSelectionHighlight({"r":0, "g":0, "b":0, "a":0});510 continue;511 }512 513 506 // Find the entity's owner's colour: 514 515 507 var owner = -1; 516 508 var cmpOwnership = Engine.QueryInterface(ent, IID_Ownership); 517 509 if (cmpOwnership) -
binaries/data/mods/public/simulation/templates/special/territory_block.xml
diff --git a/binaries/data/mods/public/simulation/templates/special/territory_block.xml b/binaries/data/mods/public/simulation/templates/special/territory_block.xml index 7774fb6..0ee7160 100644
a b 23 23 </Position> 24 24 <Selectable> 25 25 <EditorOnly/> 26 <Overlay> 27 <Texture> 28 <MainTexture>circle/128x128.png</MainTexture> 29 <MainTextureMask>circle/128x128_mask.png</MainTextureMask> 30 </Texture> 31 </Overlay> 26 32 </Selectable> 27 33 <TerritoryInfluence> 28 34 <OverrideCost>64</OverrideCost> -
binaries/data/mods/public/simulation/templates/special/territory_pull.xml
diff --git a/binaries/data/mods/public/simulation/templates/special/territory_pull.xml b/binaries/data/mods/public/simulation/templates/special/territory_pull.xml index bd8c4ac..2c2be00 100644
a b 23 23 </Position> 24 24 <Selectable> 25 25 <EditorOnly disable=""/> 26 <Overlay> 27 <Texture> 28 <MainTexture>circle/128x128.png</MainTexture> 29 <MainTextureMask>circle/128x128_mask.png</MainTextureMask> 30 </Texture> 31 </Overlay> 26 32 </Selectable> 27 33 <TerritoryInfluence> 28 34 <OverrideCost>0</OverrideCost> -
binaries/data/mods/public/simulation/templates/template_gaia_flora_bush_berry.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_flora_bush_berry.xml b/binaries/data/mods/public/simulation/templates/template_gaia_flora_bush_berry.xml index e979c8e..65fdcaf 100644
a b 18 18 </ResourceSupply> 19 19 <Selectable> 20 20 <EditorOnly disable=""/> 21 <Overlay> 22 <Texture> 23 <MainTexture>circle/128x128.png</MainTexture> 24 <MainTextureMask>circle/128x128_mask.png</MainTextureMask> 25 </Texture> 26 </Overlay> 21 27 </Selectable> 22 28 <Sound> 23 29 <SoundGroups> -
binaries/data/mods/public/simulation/templates/template_gaia_flora_tree.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_flora_tree.xml b/binaries/data/mods/public/simulation/templates/template_gaia_flora_tree.xml index ca3e80f..096c4e7 100644
a b 17 17 </ResourceSupply> 18 18 <Selectable> 19 19 <EditorOnly disable=""/> 20 <Overlay> 21 <Texture> 22 <MainTexture>circle/128x128.png</MainTexture> 23 <MainTextureMask>circle/128x128_mask.png</MainTextureMask> 24 </Texture> 25 </Overlay> 20 26 </Selectable> 21 27 <Sound> 22 28 <SoundGroups> -
binaries/data/mods/public/simulation/templates/template_gaia_geo_mineral.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_geo_mineral.xml b/binaries/data/mods/public/simulation/templates/template_gaia_geo_mineral.xml index f3a147a..0f17d2c 100644
a b 17 17 </ResourceSupply> 18 18 <Selectable> 19 19 <EditorOnly disable=""/> 20 <Overlay> 21 <Outline> 22 <LineTexture>outline_border.png</LineTexture> 23 <LineTextureMask>outline_border_mask.png</LineTextureMask> 24 <LineThickness>0.2</LineThickness> 25 </Outline> 26 </Overlay> 20 27 </Selectable> 21 28 <Sound> 22 29 <SoundGroups> -
binaries/data/mods/public/simulation/templates/template_gaia_geo_rock.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_geo_rock.xml b/binaries/data/mods/public/simulation/templates/template_gaia_geo_rock.xml index a954293..a247c15 100644
a b 17 17 </ResourceSupply> 18 18 <Selectable> 19 19 <EditorOnly disable=""/> 20 <Overlay> 21 <Texture> 22 <MainTexture>circle/128x128.png</MainTexture> 23 <MainTextureMask>circle/128x128_mask.png</MainTextureMask> 24 </Texture> 25 </Overlay> 20 26 </Selectable> 21 27 <Sound> 22 28 <SoundGroups> -
binaries/data/mods/public/simulation/templates/template_gaia_ruins.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_ruins.xml b/binaries/data/mods/public/simulation/templates/template_gaia_ruins.xml index f9ee70a..408ccb6 100644
a b 24 24 </ResourceSupply> 25 25 <Selectable> 26 26 <EditorOnly disable=""/> 27 <Overlay> 28 <Texture> 29 <MainTexture>circle/128x128.png</MainTexture> 30 <MainTextureMask>circle/128x128_mask.png</MainTextureMask> 31 </Texture> 32 </Overlay> 27 33 </Selectable> 28 34 <Sound> 29 35 <SoundGroups> -
binaries/data/mods/public/simulation/templates/template_gaia_treasure.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_treasure.xml b/binaries/data/mods/public/simulation/templates/template_gaia_treasure.xml index 15aea8a..4f11e37 100644
a b 29 29 </Sound> 30 30 <Selectable> 31 31 <EditorOnly disable=""/> 32 <Overlay> 33 <Texture> 34 <MainTexture>circle/128x128.png</MainTexture> 35 <MainTextureMask>circle/128x128_mask.png</MainTextureMask> 36 </Texture> 37 </Overlay> 32 38 </Selectable> 33 39 </Entity> -
binaries/data/mods/public/simulation/templates/template_structure.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_structure.xml b/binaries/data/mods/public/simulation/templates/template_structure.xml index d27bdd5..c7fdbd5 100644
a b 66 66 <LineCostClass>default</LineCostClass> 67 67 <LinePassabilityClass>default</LinePassabilityClass> 68 68 </RallyPointRenderer> 69 <Selectable> 70 <Overlay> 71 <Outline> 72 <LineTexture>outline_border.png</LineTexture> 73 <LineTextureMask>outline_border_mask.png</LineTextureMask> 74 <LineThickness>0.4</LineThickness> 75 </Outline> 76 </Overlay> 77 </Selectable> 69 78 <Sound> 70 79 <SoundGroups> 71 80 <select>interface/select/building/sel_universal.xml</select> -
binaries/data/mods/public/simulation/templates/template_unit.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_unit.xml b/binaries/data/mods/public/simulation/templates/template_unit.xml index d539d87..8afd0fc 100644
a b 80 80 <metal>20</metal> 81 81 </Capacities> 82 82 </ResourceGatherer> 83 <Selectable> 84 <Overlay> 85 <Texture> 86 <MainTexture>circle/128x128.png</MainTexture> 87 <MainTextureMask>circle/128x128_mask.png</MainTextureMask> 88 </Texture> 89 </Overlay> 90 </Selectable> 83 91 <StatusBars> 84 92 <BarWidth>2.0</BarWidth> 85 93 <BarHeight>0.333</BarHeight> -
binaries/data/mods/public/simulation/templates/template_unit_infantry.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_infantry.xml b/binaries/data/mods/public/simulation/templates/template_unit_infantry.xml index 736abae..afadec1 100644
a b 70 70 <metal.ore>1</metal.ore> 71 71 </Rates> 72 72 </ResourceGatherer> 73 <Selectable> 74 <Overlay> 75 <Texture> 76 <MainTexture>circle/128x128.png</MainTexture> 77 <MainTextureMask>circle/128x128_mask.png</MainTextureMask> 78 </Texture> 79 </Overlay> 80 </Selectable> 73 81 <Sound> 74 82 <SoundGroups> 75 83 <select>voice/hellenes/civ/civ_male_select.xml</select> -
source/graphics/ModelAbstract.h
diff --git a/binaries/system/ActorEditor.exe b/binaries/system/ActorEditor.exe deleted file mode 100644 index 15cdfc5..0000000 Binary files a/binaries/system/ActorEditor.exe and /dev/null differ diff --git a/source/graphics/ModelAbstract.h b/source/graphics/ModelAbstract.h index 1686847..60baec3 100644
a b public: 89 89 virtual void SetDirtyRec(int dirtyflags) = 0; 90 90 91 91 /// Returns world space bounds of this object and all child objects. 92 virtual const CBoundingBoxAligned GetWorldBoundsRec() { return GetWorldBounds(); } 92 virtual const CBoundingBoxAligned GetWorldBoundsRec() { return GetWorldBounds(); } // default implementation 93 93 94 94 /** 95 95 * Returns the world-space selection box of this model. Used primarily for hittesting against against a selection ray. The -
source/graphics/Overlay.h
diff --git a/source/graphics/Overlay.h b/source/graphics/Overlay.h index ce6f7c4..556c5bd 100644
a b 1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 20 20 21 21 #include "graphics/RenderableObject.h" 22 22 #include "graphics/Texture.h" 23 #include "maths/Vector2D.h" 23 24 #include "maths/Vector3D.h" 24 25 #include "ps/Overlay.h" // CColor (TODO: that file has nothing to do with overlays, it should be renamed) 26 #include "simulation2/components/ICmpFootprint.h" 25 27 26 28 class CTerrain; 27 29 … … struct SOverlayLine 35 37 36 38 CColor m_Color; 37 39 std::vector<float> m_Coords; // (x, y, z) vertex coordinate triples; shape is not automatically closed 38 u8 m_Thickness; // pixels40 u8 m_Thickness; // in pixels 39 41 40 /// Utility function; pushes three vertex coordinates at once onto the coordinates array41 42 void PushCoords(const float x, const float y, const float z) { m_Coords.push_back(x); m_Coords.push_back(y); m_Coords.push_back(z); } 42 /// Utility function; pushes a vertex location onto the coordinates array43 43 void PushCoords(const CVector3D& v) { PushCoords(v.X, v.Y, v.Z); } 44 44 }; 45 45 … … struct SOverlayTexturedLine 64 64 }; 65 65 66 66 SOverlayTexturedLine() 67 : m_Terrain(NULL), m_Thickness(1.0f), m_Closed(false), m_AlwaysVisible(false), m_StartCapType(LINECAP_FLAT), m_EndCapType(LINECAP_FLAT) 68 {} 67 : m_SimContext(NULL), m_Thickness(1.0f), m_Closed(false), m_AlwaysVisible(false), 68 m_StartCapType(LINECAP_FLAT), m_EndCapType(LINECAP_FLAT) 69 { } 69 70 70 CTerrain* m_Terrain;71 71 CTexturePtr m_TextureBase; 72 72 CTexturePtr m_TextureMask; 73 73 CColor m_Color; ///< Color to apply to the line texture … … struct SOverlayTexturedLine 79 79 LineCapType m_StartCapType; ///< LineCapType to be used at the start of the line 80 80 LineCapType m_EndCapType; ///< LineCapType to be used at the end of the line 81 81 82 const CSimContext* m_SimContext; /// Simulation context applicable for this overlay line; used to obtain terrain information 82 83 shared_ptr<CRenderData> m_RenderData; ///< Cached renderer data (shared_ptr so that copies/deletes are automatic) 83 84 84 85 /** … … struct SOverlayTexturedLine 86 87 * If the input string is unrecognized, a warning is issued and a default value is returned. 87 88 */ 88 89 static LineCapType StrToLineCapType(const std::wstring& str); 90 91 void PushCoords(const float x, const float z) { m_Coords.push_back(x); m_Coords.push_back(z); } 92 void PushCoords(const CVector2D& v) { PushCoords(v.X, v.Y); } 93 void PushCoords(const std::vector<CVector2D>& points) 94 { 95 for (size_t i = 0; i < points.size(); ++i) 96 PushCoords(points[i]); 97 } 89 98 }; 90 99 91 100 /** … … struct SOverlaySprite 99 108 float m_X0, m_Y0, m_X1, m_Y1; // billboard corner coordinates, relative to base position 100 109 }; 101 110 111 /** 112 * Rectangular single-quad terrain overlay, with world space coordinates. The vertices of the quad 113 * are not required to be coplanar; the quad is arbitrarily triangulated with no effort being made to 114 * find a best fit to the underlying terrain. 115 */ 116 struct SOverlayQuad 117 { 118 CTexturePtr m_Texture; 119 CTexturePtr m_TextureMask; 120 CVector3D m_Corners[4]; 121 CColor m_Color; 122 }; 123 102 124 // TODO: OverlayText 103 125 104 126 #endif // INCLUDED_GRAPHICS_OVERLAY -
source/graphics/RenderableObject.h
diff --git a/source/graphics/RenderableObject.h b/source/graphics/RenderableObject.h index c3784fd..cdc702a 100644
a b 1 /* Copyright (C) 20 09Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … class CRenderableObject 57 57 58 58 public: 59 59 // constructor 60 CRenderableObject() : m_RenderData(0), m_BoundsValid(false) { 60 CRenderableObject() : m_RenderData(0), m_BoundsValid(false) 61 { 61 62 m_Transform.SetIdentity(); 62 63 } 63 64 // destructor 64 65 virtual ~CRenderableObject() { delete m_RenderData; } 65 66 66 67 // set object transform 67 virtual void SetTransform(const CMatrix3D& transform) { 68 virtual void SetTransform(const CMatrix3D& transform) 69 { 68 70 if (m_Transform == transform) 69 71 return; 70 72 // store transform, calculate inverse … … public: 82 84 83 85 // mark some part of the renderdata as dirty, and requiring 84 86 // an update on next render 85 void SetDirty(u32 dirtyflags) { 86 if (m_RenderData) m_RenderData->m_UpdateFlags|=dirtyflags; 87 void SetDirty(u32 dirtyflags) 88 { 89 if (m_RenderData) 90 m_RenderData->m_UpdateFlags |= dirtyflags; 87 91 } 88 92 89 93 /** … … public: 98 102 virtual void CalcBounds() = 0; 99 103 100 104 /// Returns the world-space axis-aligned bounds of this object. 101 const CBoundingBoxAligned& GetWorldBounds() { 105 const CBoundingBoxAligned& GetWorldBounds() 106 { 102 107 RecalculateBoundsIfNecessary(); 103 108 return m_WorldBounds; 104 109 } … … public: 111 116 virtual void InvalidateBounds() { m_BoundsValid = false; } 112 117 113 118 // Set the object renderdata and free previous renderdata, if any. 114 void SetRenderData(CRenderData* renderdata) { 119 void SetRenderData(CRenderData* renderdata) 120 { 115 121 delete m_RenderData; 116 122 m_RenderData = renderdata; 117 123 } -
source/graphics/ShaderProgram.h
diff --git a/source/graphics/ShaderProgram.h b/source/graphics/ShaderProgram.h index 4f94da1..c024299 100644
a b public: 136 136 137 137 /** 138 138 * Returns bitset of STREAM_* value, indicating what vertex data streams the 139 * vertex shader needs .139 * vertex shader needs (e.g. position, color, UV, ...). 140 140 */ 141 141 int GetStreamFlags() const; 142 142 -
source/graphics/ShaderProgramFFP.cpp
diff --git a/source/graphics/ShaderProgramFFP.cpp b/source/graphics/ShaderProgramFFP.cpp index 7eb565c..de4f8d8 100644
a b class CShaderProgramFFP_OverlayLine : public CShaderProgramFFP 168 168 }; 169 169 170 170 bool m_IgnoreLos; 171 bool m_UseObjectColor; 171 172 172 173 public: 173 174 CShaderProgramFFP_OverlayLine(const CShaderDefines& defines) : 174 CShaderProgramFFP( STREAM_POS | STREAM_UV0 | STREAM_UV1)175 CShaderProgramFFP(0) // will be set manually in initializer below 175 176 { 176 177 SetUniformIndex("losTransform", ID_losTransform); 177 178 SetUniformIndex("objectColor", ID_objectColor); … … public: 182 183 SetUniformIndex("losTex", 2); 183 184 184 185 m_IgnoreLos = (defines.GetInt("IGNORE_LOS") != 0); 186 m_UseObjectColor = (defines.GetInt("USE_OBJECTCOLOR") != 0); 187 188 m_StreamFlags = STREAM_POS | STREAM_UV0 | STREAM_UV1; 189 if (!m_UseObjectColor) 190 m_StreamFlags |= STREAM_COLOR; 185 191 } 186 192 187 193 bool IsIgnoreLos() … … public: 219 225 virtual void Bind() 220 226 { 221 227 // RGB channels: 222 // Unit 0: Loadbase texture223 // Unit 1: Load mask texture; interpolate with objectColor & base228 // Unit 0: Sample base texture 229 // Unit 1: Sample mask texture; interpolate with [objectColor or vertexColor] and base, depending on USE_OBJECTCOLOR 224 230 // Unit 2: (Load LOS texture; multiply) if not #IGNORE_LOS, pass through otherwise 225 231 // Alpha channel: 226 // Unit 0: Loadbase texture232 // Unit 0: Sample base texture 227 233 // Unit 1: Multiply by objectColor 228 234 // Unit 2: Pass through 229 235 … … public: 231 237 glEnable(GL_TEXTURE_2D); 232 238 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 233 239 240 // Sample base texture RGB 234 241 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); 235 242 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); 236 243 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); 237 244 245 // Sample base texture Alpha 238 246 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); 239 247 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); 240 248 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); … … public: 244 252 pglActiveTextureARB(GL_TEXTURE1); 245 253 glEnable(GL_TEXTURE_2D); 246 254 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 247 // Uniform() sets GL_TEXTURE_ENV_COLOR248 255 249 // load mask texture; interpolate with objectColor and base; GL_INTERPOLATE takes 3 arguments: 250 // a0 * a2 + a1 * (1 - a2) 256 // RGB: interpolate component-wise between [objectColor or vertexColor] and base using mask: 257 // a0 * a2 + a1 * (1 - a2) 258 // Overridden implementation of Uniform() sets GL_TEXTURE_ENV_COLOR to objectColor, which 259 // is referenced as GL_CONSTANT (see spec) 251 260 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE); 252 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT);261 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, m_UseObjectColor ? GL_CONSTANT : GL_PRIMARY_COLOR); 253 262 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); 254 263 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS); 255 264 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); 256 265 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE); 257 266 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR); 258 267 268 // ALPHA: Multiply base alpha with [objectColor or vertexColor] alpha 259 269 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); 260 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_CONSTANT);270 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, m_UseObjectColor ? GL_CONSTANT : GL_PRIMARY_COLOR); 261 271 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); 262 272 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS); 263 273 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA); … … public: 278 288 } 279 289 else 280 290 { 281 // multiply RGBwith LoS texture alpha channel291 // Multiply RGB result up till now with LoS texture alpha channel 282 292 glEnable(GL_TEXTURE_GEN_S); 283 293 glEnable(GL_TEXTURE_GEN_T); 284 294 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); 285 295 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); 286 // Uniform() sets GL_OBJECT_PLANE values296 // Overridden implementation of Uniform() sets GL_OBJECT_PLANE values 287 297 288 298 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); 289 299 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS); -
new file source/maths/Ease.h
diff --git a/source/maths/Ease.h b/source/maths/Ease.h new file mode 100644 index 0000000..66e7859
- + 1 /* Copyright (C) 2012 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_EASE 19 #define INCLUDED_EASE 20 21 /** 22 * Straightforward C++ port of Robert Penner's easing equations 23 * http://www.robertpenner.com/easing/ 24 * 25 * Open source under the BSD License. 26 * Copyright (c) 2001 Robert Penner 27 * All rights reserved. 28 * http://www.robertpenner.com/easing_terms_of_use.html 29 */ 30 31 #include <math.h> 32 33 /** 34 * Generic easing functions. In each function, the parameters are: 35 * 36 * @param t Current time in seconds, as a float between 0 and d (inclusive). 37 * @param d Total duration of the ease, in seconds. Must be strictly positive. 38 * @param b Baseline value (at t = 0). 39 * @param c Delta from baseline value to reach the target value (at t = 1). I.e., target = b + c. 40 * 41 * Each function outputs the eased value between 'b' and 'b+c' at time 't'. 42 */ 43 class Ease 44 { 45 public: 46 static float QuadIn(float t, const float b, const float c, const float d) 47 { 48 t /= d; 49 return c*t*t + b; 50 } 51 52 static float QuadOut(float t, const float b, const float c, const float d) 53 { 54 t /= d; 55 return -c * t*(t-2) + b; 56 } 57 58 static float QuadInOut(float t, const float b, const float c, const float d) 59 { 60 t /= d/2; 61 if (t < 1) 62 return c/2*t*t + b; 63 --t; 64 return -c/2 * (t*(t-2) - 1) + b; 65 } 66 67 static float CubicIn(float t, const float b, const float c, const float d) 68 { 69 t /= d; 70 return c*t*t*t + b; 71 } 72 73 static float CubicOut(float t, const float b, const float c, const float d) 74 { 75 t = t/d - 1; 76 return c*(t*t*t + 1) + b; 77 } 78 79 static float CubicInOut(float t, const float b, const float c, const float d) 80 { 81 t /= d/2; 82 if (t < 1) 83 return c/2*t*t*t + b; 84 t -= 2; 85 return c/2*(t*t*t + 2) + b; 86 } 87 88 static float QuartIn(float t, const float b, const float c, const float d) 89 { 90 t /= d; 91 return c*t*t*t*t + b; 92 } 93 94 static float QuartOut(float t, const float b, const float c, const float d) 95 { 96 t = t/d - 1; 97 return -c*(t*t*t*t - 1) + b; 98 } 99 100 static float QuartInOut(float t, const float b, const float c, const float d) 101 { 102 t /= d/2; 103 if (t < 1) 104 return c/2*t*t*t*t + b; 105 t -= 2; 106 return -c/2 * (t*t*t*t - 2) + b; 107 } 108 109 static float QuintIn(float t, const float b, const float c, const float d) 110 { 111 t /= d; 112 return c*t*t*t*t*t + b; 113 } 114 115 static float QuintOut(float t, const float b, const float c, const float d) 116 { 117 t = t/d - 1; 118 return c*(t*t*t*t*t + 1) + b; 119 } 120 121 static float QuintInOut(float t, const float b, const float c, const float d) 122 { 123 t /= d/2; 124 if (t < 1) 125 return c/2*t*t*t*t*t + b; 126 t -= 2; 127 return c/2*(t*t*t*t*t + 2) + b; 128 } 129 }; 130 131 #endif // INCLUDED_EASE -
source/maths/FixedVector2D.h
diff --git a/source/maths/FixedVector2D.h b/source/maths/FixedVector2D.h index c58f66f..739469e 100644
a b public: 27 27 fixed X, Y; 28 28 29 29 CFixedVector2D() { } 30 31 30 CFixedVector2D(fixed X, fixed Y) : X(X), Y(Y) { } 32 31 33 32 /// Vector equality -
source/maths/MathUtil.h
diff --git a/source/maths/MathUtil.h b/source/maths/MathUtil.h index 741e57e..b00a70b 100644
a b 18 18 #ifndef INCLUDED_MATHUTIL 19 19 #define INCLUDED_MATHUTIL 20 20 21 #include <cmath> 22 21 23 #define DEGTORAD(a) ((a) * ((float)M_PI/180.0f)) 22 24 #define RADTODEG(a) ((a) * (180.0f/(float)M_PI)) 23 25 #define SQR(x) ((x) * (x)) -
source/maths/Vector2D.h
diff --git a/source/maths/Vector2D.h b/source/maths/Vector2D.h index 977584c..55787d8 100644
a b public: 121 121 Y /= mag; 122 122 } 123 123 124 CVector2D Normalized() 124 CVector2D Normalized() const 125 125 { 126 126 float mag = Length(); 127 127 return CVector2D(X / mag, Y / mag); … … public: 130 130 /** 131 131 * Returns a version of this vector rotated counterclockwise by @p angle radians. 132 132 */ 133 CVector2D Rotated(float angle) 133 CVector2D Rotated(float angle) const 134 134 { 135 135 float c = cosf(angle); 136 136 float s = sinf(angle); -
source/renderer/OverlayRenderer.cpp
diff --git a/source/renderer/OverlayRenderer.cpp b/source/renderer/OverlayRenderer.cpp index 0a30e7a..c22e8e8 100644
a b 1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 19 19 20 20 #include "OverlayRenderer.h" 21 21 22 #include "maths/MathUtil.h" 23 #include "maths/Quaternion.h" 24 #include "maths/Vector2D.h" 22 #include <boost/unordered_map.hpp> 25 23 #include "graphics/LOSTexture.h" 26 24 #include "graphics/Overlay.h" 27 25 #include "graphics/Terrain.h" 28 26 #include "graphics/TextureManager.h" 29 27 #include "lib/ogl.h" 28 #include "maths/MathUtil.h" 29 #include "maths/Quaternion.h" 30 30 #include "ps/Game.h" 31 31 #include "ps/Profile.h" 32 32 #include "renderer/Renderer.h" 33 #include "renderer/VertexArray.h" 33 34 #include "renderer/VertexBuffer.h" 34 35 #include "renderer/VertexBufferManager.h" 35 36 #include "simulation2/Simulation2.h" 36 37 #include "simulation2/components/ICmpWaterManager.h" 38 #include "simulation2/system/SimContext.h" 39 40 /** 41 * As a general TODO, some of the code here still uses g_VBMan manually. 42 * For consistency with other parts of the engine, it'd be nice to switch 43 * over to the cleaner and more readable VertexArray API. 44 */ 45 46 const float OverlayRenderer::OVERLAY_VOFFSET = 0.2f; 47 48 /** 49 * Key used to group quads into batches for more efficient rendering. Currently groups by the combination 50 * of the main texture and the texture mask, to minimize texture swapping during rendering. 51 */ 52 struct QuadBatchKey 53 { 54 QuadBatchKey (const CTexturePtr& texture, const CTexturePtr& textureMask) 55 : m_Texture(texture), m_TextureMask(textureMask) 56 { } 57 58 bool operator==(const QuadBatchKey& other) const 59 { 60 return (m_Texture == other.m_Texture && m_TextureMask == other.m_TextureMask); 61 } 62 63 CTexturePtr m_Texture; 64 CTexturePtr m_TextureMask; 65 }; 66 67 /** 68 * Holds information about a single quad rendering batch. 69 */ 70 class QuadBatchData : public CRenderData 71 { 72 public: 73 QuadBatchData() : m_IndicesBase(0) { } 74 75 /// Holds the quad overlay structures to be rendered during this batch. 76 /// Must be cleared after each frame. 77 std::vector<SOverlayQuad*> m_Quads; 78 /// Start index of this batch into the dedicated quad indices VertexArray (see OverlayInternals). 79 size_t m_IndicesBase; 80 }; 37 81 38 82 struct OverlayRendererInternals 39 83 { 84 typedef boost::unordered_map<QuadBatchKey, QuadBatchData> QuadBatchMap; 85 86 OverlayRendererInternals(); 87 ~OverlayRendererInternals(){ } 88 40 89 std::vector<SOverlayLine*> lines; 41 90 std::vector<SOverlayTexturedLine*> texlines; 42 91 std::vector<SOverlaySprite*> sprites; 92 std::vector<SOverlayQuad*> quads; 93 94 QuadBatchMap quadBatchMap; 95 96 // Dedicated vertex/index buffers for rendering all quads (to within the limits set by 97 // MAX_QUAD_OVERLAYS). 98 VertexArray quadVertices; 99 VertexArray::Attribute quadAttributePos; 100 VertexArray::Attribute quadAttributeColor; 101 VertexArray::Attribute quadAttributeUV; 102 VertexIndexArray quadIndices; 103 104 /// Maximum amount of quad overlays we support for rendering. This limit is set to be able to 105 /// render all quads from a single dedicated VB without having to reallocate it, which is much 106 /// faster in the typical case of rendering only a handful of quads. When modifying this value, 107 /// you must take care for the new amount of quads to fit in a single VBO (which is not likely 108 /// to be a problem). 109 static const size_t MAX_QUAD_OVERLAYS = 1024; 110 111 // Sets of commonly-(re)used shader defines. 112 CShaderDefines defsOverlayLineNormal; 113 CShaderDefines defsOverlayLineAlwaysVisible; 114 CShaderDefines defsQuadOverlay; 43 115 }; 44 116 117 OverlayRendererInternals::OverlayRendererInternals() 118 : quadVertices(GL_DYNAMIC_DRAW), quadIndices(GL_DYNAMIC_DRAW) 119 { 120 quadAttributePos.elems = 3; 121 quadAttributePos.type = GL_FLOAT; 122 quadVertices.AddAttribute(&quadAttributePos); 123 124 quadAttributeColor.elems = 4; 125 quadAttributeColor.type = GL_FLOAT; 126 quadVertices.AddAttribute(&quadAttributeColor); 127 128 quadAttributeUV.elems = 2; 129 quadAttributeUV.type = GL_SHORT; // don't use GL_UNSIGNED_SHORT here, TexCoordPointer won't accept it 130 quadVertices.AddAttribute(&quadAttributeUV); 131 132 quadVertices.SetNumVertices(MAX_QUAD_OVERLAYS * 4); 133 quadVertices.Layout(); // allocate backing store 134 135 quadIndices.SetNumVertices(MAX_QUAD_OVERLAYS * 6); 136 quadIndices.Layout(); // allocate backing store 137 138 // Since the quads in the vertex array are independent and always consist of exactly 4 vertices per quad, the 139 // indices are always the same; we can therefore fill in all the indices once and pretty much forget about 140 // them. We then also no longer need its backing store, since we never change any indices afterwards. 141 VertexArrayIterator<u16> index = quadIndices.GetIterator(); 142 for (size_t i = 0; i < MAX_QUAD_OVERLAYS; ++i) 143 { 144 *index++ = i*4 + 0; 145 *index++ = i*4 + 1; 146 *index++ = i*4 + 2; 147 *index++ = i*4 + 2; 148 *index++ = i*4 + 3; 149 *index++ = i*4 + 0; 150 } 151 quadIndices.Upload(); 152 quadIndices.FreeBackingStore(); 153 154 // Note that we're reusing the textured overlay line shader for the quad overlay rendering. This 155 // is because their code is almost identical; the only difference is that for the quad overlays 156 // we want to use a vertex color stream as opposed to an objectColor uniform. To this end, the 157 // shader has been set up to switch between the two behaviours based on the USE_OBJECTCOLOR define. 158 defsOverlayLineNormal.Add("USE_OBJECTCOLOR", "1"); 159 defsOverlayLineAlwaysVisible.Add("USE_OBJECTCOLOR", "1"); 160 defsOverlayLineAlwaysVisible.Add("IGNORE_LOS", "1"); 161 } 162 45 163 class CTexturedLineRData : public CRenderData 46 164 { 47 165 public: 48 CTexturedLineRData(SOverlayTexturedLine* line) : 49 m_Line(line), m_VB(NULL), m_VBIndices(NULL), m_Raise(.2f) 166 CTexturedLineRData(SOverlayTexturedLine* line) : m_Line(line), m_VB(NULL), m_VBIndices(NULL) 50 167 { } 51 168 52 169 ~CTexturedLineRData() … … public: 62 179 SVertex(CVector3D pos, float u, float v) : m_Position(pos) { m_UVs[0] = u; m_UVs[1] = v; } 63 180 CVector3D m_Position; 64 181 GLfloat m_UVs[2]; 65 float _padding[3]; // 5 floats up till now, so pad with another 3 floats to get a power of 2182 float _padding[3]; // get a pow2 struct size 66 183 }; 67 184 cassert(sizeof(SVertex) == 32); 68 185 … … public: 91 208 SOverlayTexturedLine* m_Line; 92 209 CVertexBuffer::VBChunk* m_VB; 93 210 CVertexBuffer::VBChunk* m_VBIndices; 94 95 float m_Raise; // small vertical offset of line from terrain to prevent visual glitches96 211 }; 97 212 213 static size_t hash_value(const QuadBatchKey& d) 214 { 215 size_t seed = 0; 216 boost::hash_combine(seed, d.m_Texture); 217 boost::hash_combine(seed, d.m_TextureMask); 218 return seed; 219 } 220 98 221 OverlayRenderer::OverlayRenderer() 99 222 { 100 223 m = new OverlayRendererInternals(); … … void OverlayRenderer::Submit(SOverlaySprite* overlay) 128 251 m->sprites.push_back(overlay); 129 252 } 130 253 254 void OverlayRenderer::Submit(SOverlayQuad* overlay) 255 { 256 m->quads.push_back(overlay); 257 } 258 131 259 void OverlayRenderer::EndFrame() 132 260 { 133 261 m->lines.clear(); 134 262 m->texlines.clear(); 135 263 m->sprites.clear(); 264 m->quads.clear(); 136 265 // this should leave the capacity unchanged, which is okay since it 137 266 // won't be very large or very variable 267 268 // Empty the batch rendering data structures, but keep their key mappings around for the next frames 269 for (OverlayRendererInternals::QuadBatchMap::iterator it = m->quadBatchMap.begin(); it != m->quadBatchMap.end(); it++) 270 { 271 it->second.m_Quads.clear(); 272 } 138 273 } 139 274 140 275 void OverlayRenderer::PrepareForRendering() … … void OverlayRenderer::PrepareForRendering() 157 292 // any of the parameters after first submitting the line. 158 293 } 159 294 } 295 296 // Group quad overlays by their texture/mask combination for efficient rendering 297 for (size_t i = 0; i < m->quads.size(); ++i) 298 { 299 SOverlayQuad* const quad = m->quads[i]; 300 301 QuadBatchKey textures(quad->m_Texture, quad->m_TextureMask); 302 QuadBatchData& batchRenderData = m->quadBatchMap[textures]; // will create entry if it doesn't already exist 303 304 // add overlay to list of quads 305 batchRenderData.m_Quads.push_back(quad); 306 } 307 308 const CVector3D vOffset(0, OVERLAY_VOFFSET, 0); 309 310 // Write quad overlay vertices/indices to VA backing store 311 VertexArrayIterator<CVector3D> vertexPos = m->quadAttributePos.GetIterator<CVector3D>(); 312 VertexArrayIterator<CVector4D> vertexColor = m->quadAttributeColor.GetIterator<CVector4D>(); 313 VertexArrayIterator<short[2]> vertexUV = m->quadAttributeUV.GetIterator<short[2]>(); 314 315 size_t indicesIdx = 0; 316 317 for (OverlayRendererInternals::QuadBatchMap::iterator it = m->quadBatchMap.begin(); it != m->quadBatchMap.end(); ++it) 318 { 319 QuadBatchData& batchRenderData = (it->second); 320 if (batchRenderData.m_Quads.empty()) 321 continue; 322 323 // Remember our current index into the (entire) indices array as our base offset for this batch 324 batchRenderData.m_IndicesBase = indicesIdx; 325 326 // points to the index where each iteration's vertices will be appended 327 for (size_t i = 0; i < batchRenderData.m_Quads.size(); i++) 328 { 329 const SOverlayQuad* quad = batchRenderData.m_Quads[i]; 330 331 // TODO: this is kind of ugly, the iterator should use a type that can have quad->m_Color assigned 332 // to it directly 333 const CVector4D quadColor(quad->m_Color.r, quad->m_Color.g, quad->m_Color.b, quad->m_Color.a); 334 335 *vertexPos++ = quad->m_Corners[0] + vOffset; 336 *vertexPos++ = quad->m_Corners[1] + vOffset; 337 *vertexPos++ = quad->m_Corners[2] + vOffset; 338 *vertexPos++ = quad->m_Corners[3] + vOffset; 339 340 (*vertexUV)[0] = 0; 341 (*vertexUV)[1] = 0; 342 ++vertexUV; 343 (*vertexUV)[0] = 0; 344 (*vertexUV)[1] = 1; 345 ++vertexUV; 346 (*vertexUV)[0] = 1; 347 (*vertexUV)[1] = 1; 348 ++vertexUV; 349 (*vertexUV)[0] = 1; 350 (*vertexUV)[1] = 0; 351 ++vertexUV; 352 353 *vertexColor++ = quadColor; 354 *vertexColor++ = quadColor; 355 *vertexColor++ = quadColor; 356 *vertexColor++ = quadColor; 357 358 indicesIdx += 6; 359 } 360 } 361 362 m->quadVertices.Upload(); 363 // don't free the backing store! we'll overwrite it on the next frame to save a reallocation. 160 364 } 161 365 162 366 void OverlayRenderer::RenderOverlaysBeforeWater() … … void OverlayRenderer::RenderOverlaysAfterWater() 196 400 { 197 401 PROFILE3_GPU("overlays (after)"); 198 402 403 RenderTexturedOverlayLines(); 404 RenderQuadOverlays(); 405 } 406 407 void OverlayRenderer::RenderTexturedOverlayLines() 408 { 199 409 #if CONFIG2_GLES 200 #warning TODO: implement OverlayRenderer::Render OverlaysAfterWaterfor GLES410 #warning TODO: implement OverlayRenderer::RenderTexturedOverlayLines for GLES 201 411 return; 202 412 #endif 413 if (m->texlines.empty()) 414 return; 203 415 204 416 ogl_WarnIfError(); 205 417 206 if (!m->texlines.empty()) 207 { 208 glEnable(GL_TEXTURE_2D); 209 glEnable(GL_BLEND); 210 glDepthMask(0); 211 212 const char* shaderName; 213 if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER) 214 shaderName = "arb/overlayline"; 215 else 216 shaderName = "fixed:overlayline"; 418 glEnable(GL_TEXTURE_2D); 419 glEnable(GL_BLEND); 420 glDepthMask(0); 217 421 218 CShaderDefines defAlwaysVisible; 219 defAlwaysVisible.Add("IGNORE_LOS", "1"); 422 const char* shaderName; 423 if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER) 424 shaderName = "arb/overlayline"; 425 else 426 shaderName = "fixed:overlayline"; 220 427 221 428 CLOSTexture& los = g_Renderer.GetScene().GetLOSTexture(); 222 429 223 224 CShaderProgramPtr shaderTexLineNormal(shaderManager.LoadProgram(shaderName, CShaderDefines()));225 CShaderProgramPtr shaderTexLineAlwaysVisible(shaderManager.LoadProgram(shaderName, defAlwaysVisible));430 CShaderManager& shaderManager = g_Renderer.GetShaderManager(); 431 CShaderProgramPtr shaderTexLineNormal(shaderManager.LoadProgram(shaderName, m->defsOverlayLineNormal)); 432 CShaderProgramPtr shaderTexLineAlwaysVisible(shaderManager.LoadProgram(shaderName, m->defsOverlayLineAlwaysVisible)); 226 433 227 434 // ---------------------------------------------------------------------------------------- 228 435 436 if (shaderTexLineNormal) 437 { 229 438 shaderTexLineNormal->Bind(); 230 439 shaderTexLineNormal->BindTexture("losTex", los.GetTexture()); 231 440 shaderTexLineNormal->Uniform("losTransform", los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f); … … void OverlayRenderer::RenderOverlaysAfterWater() 234 443 RenderTexturedOverlayLines(shaderTexLineNormal, false); 235 444 236 445 shaderTexLineNormal->Unbind(); 446 } 237 447 238 448 // ---------------------------------------------------------------------------------------- 239 449 450 if (shaderTexLineAlwaysVisible) 451 { 240 452 shaderTexLineAlwaysVisible->Bind(); 241 // TODO: losTex and losTransform are unused in the always visible shader, but I'm not sure if it's worthwhile messing 242 // with it just to remove these calls 453 // TODO: losTex and losTransform are unused in the always visible shader; see if these can be safely omitted 243 454 shaderTexLineAlwaysVisible->BindTexture("losTex", los.GetTexture()); 244 455 shaderTexLineAlwaysVisible->Uniform("losTransform", los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f); 245 456 … … void OverlayRenderer::RenderOverlaysAfterWater() 247 458 RenderTexturedOverlayLines(shaderTexLineAlwaysVisible, true); 248 459 249 460 shaderTexLineAlwaysVisible->Unbind(); 461 } 250 462 251 // TODO: the shader should probably be responsible for unbinding its textures 252 g_Renderer.BindTexture(1, 0); 253 g_Renderer.BindTexture(0, 0); 463 // ---------------------------------------------------------------------------------------- 254 464 255 CVertexBuffer::Unbind(); 465 // TODO: the shaders should probably be responsible for unbinding their textures 466 g_Renderer.BindTexture(1, 0); 467 g_Renderer.BindTexture(0, 0); 256 468 257 glDepthMask(1); 258 glDisable(GL_BLEND); 259 } 469 CVertexBuffer::Unbind(); 470 471 glDepthMask(1); 472 glDisable(GL_BLEND); 260 473 } 261 474 262 475 void OverlayRenderer::RenderTexturedOverlayLines(CShaderProgramPtr shaderTexLine, bool alwaysVisible) … … void OverlayRenderer::RenderTexturedOverlayLines(CShaderProgramPtr shaderTexLine 298 511 shaderTexLine->AssertPointersBound(); 299 512 glDrawElements(GL_TRIANGLES, rdata->m_VBIndices->m_Count, GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*rdata->m_VBIndices->m_Index); 300 513 514 g_Renderer.GetStats().m_DrawCalls++; 301 515 g_Renderer.GetStats().m_OverlayTris += rdata->m_VBIndices->m_Count/3; 302 516 } 303 517 } 304 518 519 void OverlayRenderer::RenderQuadOverlays() 520 { 521 if (m->quadBatchMap.empty()) 522 return; 523 524 ogl_WarnIfError(); 525 526 glEnable(GL_TEXTURE_2D); 527 glEnable(GL_BLEND); 528 glDepthMask(0); 529 530 const char* shaderName; 531 if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER) 532 shaderName = "arb/overlayline"; 533 else 534 shaderName = "fixed:overlayline"; 535 536 // TODO: create an FFP version of this shader? 537 538 CLOSTexture& los = g_Renderer.GetScene().GetLOSTexture(); 539 540 CShaderManager& shaderManager = g_Renderer.GetShaderManager(); 541 CShaderProgramPtr shader(shaderManager.LoadProgram(shaderName, m->defsQuadOverlay)); 542 543 // ---------------------------------------------------------------------------------------- 544 545 if (shader) 546 { 547 shader->Bind(); 548 shader->BindTexture("losTex", los.GetTexture()); 549 shader->Uniform("losTransform", los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f); 550 551 // Base offsets (in bytes) of the two backing stores relative to their owner VBO 552 // (the backing stores are chunks inside a larger, bound VBO) 553 u8* indexBase = m->quadIndices.Bind(); 554 u8* vertexBase = m->quadVertices.Bind(); 555 GLsizei indexStride = m->quadIndices.GetStride(); 556 GLsizei vertexStride = m->quadVertices.GetStride(); 557 558 for (OverlayRendererInternals::QuadBatchMap::iterator it = m->quadBatchMap.begin(); it != m->quadBatchMap.end(); it++) 559 { 560 QuadBatchData& batchRenderData = it->second; 561 const size_t batchNumQuads = batchRenderData.m_Quads.size(); 562 563 // Careful; some drivers don't like drawing calls with 0 stuff to draw. 564 // Also needed to ensure that batchRenderData.m_IndicesBase is valid (see PrepareForRendering). 565 if (batchNumQuads == 0) 566 continue; 567 568 const QuadBatchKey& maskPair = it->first; 569 570 shader->BindTexture("baseTex", maskPair.m_Texture->GetHandle()); 571 shader->BindTexture("maskTex", maskPair.m_TextureMask->GetHandle()); 572 573 int streamflags = shader->GetStreamFlags(); ogl_WarnIfError(); 574 575 if (streamflags & STREAM_POS) 576 shader->VertexPointer(m->quadAttributePos.elems, m->quadAttributePos.type, vertexStride, vertexBase + m->quadAttributePos.offset); 577 578 if (streamflags & STREAM_UV0) 579 shader->TexCoordPointer(GL_TEXTURE0, m->quadAttributeUV.elems, m->quadAttributeUV.type, vertexStride, vertexBase + m->quadAttributeUV.offset); 580 581 if (streamflags & STREAM_UV1) 582 shader->TexCoordPointer(GL_TEXTURE1, m->quadAttributeUV.elems, m->quadAttributeUV.type, vertexStride, vertexBase + m->quadAttributeUV.offset); 583 584 if (streamflags & STREAM_COLOR) 585 shader->ColorPointer(m->quadAttributeColor.elems, m->quadAttributeColor.type, vertexStride, vertexBase + m->quadAttributeColor.offset); 586 587 shader->AssertPointersBound(); 588 glDrawElements(GL_TRIANGLES, (GLsizei)(batchNumQuads * 6), GL_UNSIGNED_SHORT, indexBase + indexStride * batchRenderData.m_IndicesBase); 589 590 g_Renderer.GetStats().m_DrawCalls++; 591 g_Renderer.GetStats().m_OverlayTris += batchNumQuads*2; 592 } 593 594 shader->Unbind(); 595 } 596 597 // ---------------------------------------------------------------------------------------- 598 599 // TODO: the shader should probably be responsible for unbinding its textures 600 g_Renderer.BindTexture(1, 0); 601 g_Renderer.BindTexture(0, 0); 602 603 CVertexBuffer::Unbind(); 604 605 glDepthMask(1); 606 glDisable(GL_BLEND); 607 } 608 305 609 void OverlayRenderer::RenderForegroundOverlays(const CCamera& viewCamera) 306 610 { 307 611 PROFILE3_GPU("overlays (fg)"); … … void OverlayRenderer::RenderForegroundOverlays(const CCamera& viewCamera) 339 643 340 644 glVertexPointer(3, GL_FLOAT, sizeof(float)*3, &pos[0].X); 341 645 glDrawArrays(GL_QUADS, 0, (GLsizei)4); 646 647 g_Renderer.GetStats().m_DrawCalls++; 648 g_Renderer.GetStats().m_OverlayTris += 2; 342 649 } 343 650 344 651 glDisableClientState(GL_VERTEX_ARRAY); … … void CTexturedLineRData::Update() 363 670 m_VBIndices = NULL; 364 671 } 365 672 366 CTerrain* terrain = m_Line->m_Terrain; 367 CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); 673 if (!m_Line->m_SimContext) 674 { 675 debug_warn(L"[OverlayRenderer] No SimContext set for textured overlay line, cannot render (no terrain data)"); 676 return; 677 } 678 679 const CTerrain& terrain = m_Line->m_SimContext->GetTerrain(); 680 CmpPtr<ICmpWaterManager> cmpWaterManager(*m_Line->m_SimContext, SYSTEM_ENTITY); 368 681 369 682 float v = 0.f; 370 683 std::vector<SVertex> vertices; … … void CTexturedLineRData::Update() 400 713 // TODO: if we ever support more than one water level per map, recompute this per point 401 714 float w = cmpWaterManager->GetExactWaterLevel(p0.X, p0.Z); 402 715 403 p0.Y = terrain ->GetExactGroundLevel(p0.X, p0.Z);716 p0.Y = terrain.GetExactGroundLevel(p0.X, p0.Z); 404 717 if (p0.Y < w) 405 718 p0.Y = w; 406 719 407 p1.Y = terrain ->GetExactGroundLevel(p1.X, p1.Z);720 p1.Y = terrain.GetExactGroundLevel(p1.X, p1.Z); 408 721 if (p1.Y < w) 409 722 { 410 723 p1.Y = w; 411 724 p1floating = true; 412 725 } 413 726 414 p2.Y = terrain ->GetExactGroundLevel(p2.X, p2.Z);727 p2.Y = terrain.GetExactGroundLevel(p2.X, p2.Z); 415 728 if (p2.Y < w) 416 729 { 417 730 p2.Y = w; … … void CTexturedLineRData::Update() 428 741 if (p1floating) 429 742 norm = CVector3D(0, 1, 0); 430 743 else 431 norm = m_Line->m_Terrain->CalcExactNormal(p1.X, p1.Z);744 norm = terrain.CalcExactNormal(p1.X, p1.Z); 432 745 433 746 CVector3D b = ((p1 - p0).Normalized() + (p2 - p1).Normalized()).Cross(norm); 434 747 … … void CTexturedLineRData::Update() 447 760 // What the code below does is push the indices for a quad composed of two triangles in each iteration. The two triangles 448 761 // of each quad are indexed using the winding orders (BR, BL, TR) and (TR, BL, TR) (where BR is bottom-right of this 449 762 // iteration's quad, TR top-right etc). 450 SVertex vertex1(p1 + b + norm* m_Raise, 0.f, v);451 SVertex vertex2(p1 - b + norm* m_Raise, 1.f, v);763 SVertex vertex1(p1 + b + norm*OverlayRenderer::OVERLAY_VOFFSET, 0.f, v); 764 SVertex vertex2(p1 - b + norm*OverlayRenderer::OVERLAY_VOFFSET, 1.f, v); 452 765 vertices.push_back(vertex1); 453 766 vertices.push_back(vertex2); 454 767 … … void CTexturedLineRData::Update() 497 810 else 498 811 p2 = CVector3D(m_Line->m_Coords[((i+2) % n)*2], 0, m_Line->m_Coords[((i+2) % n)*2+1]); 499 812 500 p2.Y = terrain ->GetExactGroundLevel(p2.X, p2.Z);813 p2.Y = terrain.GetExactGroundLevel(p2.X, p2.Z); 501 814 if (p2.Y < w) 502 815 { 503 816 p2.Y = w; … … void CTexturedLineRData::Update() 540 853 541 854 for (unsigned i = 0; i < capIndices.size(); i++) 542 855 capIndices[i] += vertices.size(); 856 543 857 vertices.insert(vertices.end(), capVertices.begin(), capVertices.end()); 544 858 indices.insert(indices.end(), capIndices.begin(), capIndices.end()); 545 859 … … void CTexturedLineRData::Update() 560 874 561 875 for (unsigned i = 0; i < capIndices.size(); i++) 562 876 capIndices[i] += vertices.size(); 877 563 878 vertices.insert(vertices.end(), capVertices.begin(), capVertices.end()); 564 879 indices.insert(indices.end(), capIndices.begin(), capIndices.end()); 565 880 } … … void CTexturedLineRData::CreateLineCap(const CVector3D& corner1, const CVector3D 595 910 // That is to say, when viewed from the top, we will have something like 596 911 // . 597 912 // this: and not like this: /| 598 // ____./ |913 // ----+ / | 599 914 // | / . 600 915 // | / 601 // ____./916 // ----+ / 602 917 // 603 918 604 919 int roundCapPoints = 8; // amount of points to sample along the semicircle for rounded caps (including corner points) -
source/renderer/OverlayRenderer.h
diff --git a/source/renderer/OverlayRenderer.h b/source/renderer/OverlayRenderer.h index 6c1dfdc..a61656f 100644
a b 1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 23 23 struct SOverlayLine; 24 24 struct SOverlayTexturedLine; 25 25 struct SOverlaySprite; 26 struct SOverlayQuad; 26 27 class CCamera; 27 28 28 29 struct OverlayRendererInternals; … … public: 39 40 40 41 /** 41 42 * Add a line overlay for rendering in this frame. 43 * @param overlay Must be non-null. The pointed-to object must remain valid at least 44 * until the end of the frame. 42 45 */ 43 46 void Submit(SOverlayLine* overlay); 44 47 45 48 /** 46 49 * Add a textured line overlay for rendering in this frame. 50 * @param overlay Must be non-null. The pointed-to object must remain valid at least 51 * until the end of the frame. 47 52 */ 48 53 void Submit(SOverlayTexturedLine* overlay); 49 54 50 55 /** 51 56 * Add a sprite overlay for rendering in this frame. 57 * @param overlay Must be non-null. The pointed-to object must remain valid at least 58 * until the end of the frame. 52 59 */ 53 60 void Submit(SOverlaySprite* overlay); 54 61 55 62 /** 63 * Add a textured quad overlay for rendering in this frame. 64 * @param overlay Must be non-null. The pointed-to object must remain valid at least 65 * until the end of the frame. 66 */ 67 void Submit(SOverlayQuad* overlay); 68 69 /** 56 70 * Prepare internal data structures for rendering. 57 71 * Must be called after all Submit calls for a frame, and before 58 72 * any rendering calls. … … public: 85 99 */ 86 100 void RenderForegroundOverlays(const CCamera& viewCamera); 87 101 102 /// Small vertical offset of overlays from terrain to prevent visual glitches 103 static const float OVERLAY_VOFFSET; 104 88 105 private: 89 106 90 107 /** 91 * Helper method; renders those overlay lines currently registered in the internals (i.e. in m->texlines) for which the 92 * always visible flag equals @alwaysVisible. Used for batch rendering the overlay lines by their alwaysVisible status, 93 * because this requires a separate shader to be used. 108 * Helper method; renders all overlay lines currently registered in the internals. Batch- 109 * renders textured overlay lines batched according to their visibility status by delegating 110 * to RenderTexturedOverlayLines(CShaderProgramPtr, bool). 111 */ 112 void RenderTexturedOverlayLines(); 113 114 /** 115 * Helper method; renders those overlay lines currently registered in the internals (i.e. 116 * in m->texlines) for which the 'always visible' flag equals @p alwaysVisible. Used for 117 * batch rendering the overlay lines according to their alwaysVisible status, as this 118 * requires a separate shader to be used. 94 119 */ 95 120 void RenderTexturedOverlayLines(CShaderProgramPtr shader, bool alwaysVisible); 96 121 122 /** 123 * Helper method; batch-renders all registered quad overlays, batched by their texture for effiency. 124 */ 125 void RenderQuadOverlays(); 126 97 127 private: 98 128 OverlayRendererInternals* m; 99 129 }; -
source/renderer/Renderer.cpp
diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp index d743ef2..e66c1fa 100644
a b void CRenderer::Submit(SOverlaySprite* overlay) 1569 1569 m->overlayRenderer.Submit(overlay); 1570 1570 } 1571 1571 1572 void CRenderer::Submit(SOverlayQuad* overlay) 1573 { 1574 m->overlayRenderer.Submit(overlay); 1575 } 1576 1572 1577 void CRenderer::Submit(CModelDecal* decal) 1573 1578 { 1574 1579 m->terrainRenderer.Submit(decal); -
source/renderer/Renderer.h
diff --git a/source/renderer/Renderer.h b/source/renderer/Renderer.h index a6d1b2b..df82579 100644
a b protected: 316 316 void Submit(SOverlayLine* overlay); 317 317 void Submit(SOverlayTexturedLine* overlay); 318 318 void Submit(SOverlaySprite* overlay); 319 void Submit(SOverlayQuad* overlay); 319 320 void Submit(CModelDecal* decal); 320 321 void Submit(CParticleEmitter* emitter); 321 322 void SubmitNonRecursive(CModel* model); -
source/renderer/Scene.h
diff --git a/source/renderer/Scene.h b/source/renderer/Scene.h index 2018135..99c99f7 100644
a b class CTerritoryTexture; 39 39 struct SOverlayLine; 40 40 struct SOverlayTexturedLine; 41 41 struct SOverlaySprite; 42 struct SOverlayQuad; 42 43 43 44 class SceneCollector; 44 45 … … public: 104 105 virtual void Submit(SOverlaySprite* overlay) = 0; 105 106 106 107 /** 108 * Submit a textured quad overlay. 109 */ 110 virtual void Submit(SOverlayQuad* overlay) = 0; 111 112 /** 107 113 * Submit a terrain decal. 108 114 */ 109 115 virtual void Submit(CModelDecal* decal) = 0; -
source/renderer/VertexArray.cpp
diff --git a/source/renderer/VertexArray.cpp b/source/renderer/VertexArray.cpp index 6bf1fed..42d769b 100644
a b 22 22 #include "lib/sysdep/rtl.h" 23 23 #include "maths/Vector3D.h" 24 24 #include "maths/Vector4D.h" 25 #include "graphics/Color.h" 25 26 #include "graphics/SColor.h" 26 27 #include "renderer/VertexArray.h" 27 28 #include "renderer/VertexBuffer.h" … … void VertexArray::SetNumVertices(size_t num) 73 74 // Add vertex attributes like Position, Normal, UV 74 75 void VertexArray::AddAttribute(Attribute* attr) 75 76 { 76 ENSURE((attr->type == GL_FLOAT || attr->type == GL_UNSIGNED_SHORT || attr->type == GL_UNSIGNED_BYTE) && "Unsupported attribute type"); 77 ENSURE( 78 (attr->type == GL_FLOAT || attr->type == GL_SHORT || attr->type == GL_UNSIGNED_SHORT || attr->type == GL_UNSIGNED_BYTE) 79 && "Unsupported attribute type" 80 ); 77 81 ENSURE(attr->elems >= 1 && attr->elems <= 4); 78 82 79 83 attr->vertexArray = this; … … VertexArrayIterator<u16> VertexArray::Attribute::GetIterator<u16>() const 147 151 } 148 152 149 153 template<> 154 VertexArrayIterator<u16[2]> VertexArray::Attribute::GetIterator<u16[2]>() const 155 { 156 ENSURE(vertexArray); 157 ENSURE(type == GL_UNSIGNED_SHORT); 158 ENSURE(elems >= 2); 159 160 return vertexArray->MakeIterator<u16[2]>(this); 161 } 162 163 template<> 150 164 VertexArrayIterator<u8> VertexArray::Attribute::GetIterator<u8>() const 151 165 { 152 166 ENSURE(vertexArray); … … VertexArrayIterator<u8[4]> VertexArray::Attribute::GetIterator<u8[4]>() const 166 180 return vertexArray->MakeIterator<u8[4]>(this); 167 181 } 168 182 183 template<> 184 VertexArrayIterator<short> VertexArray::Attribute::GetIterator<short>() const 185 { 186 ENSURE(vertexArray); 187 ENSURE(type == GL_SHORT); 188 ENSURE(elems >= 1); 189 190 return vertexArray->MakeIterator<short>(this); 191 } 192 193 template<> 194 VertexArrayIterator<short[2]> VertexArray::Attribute::GetIterator<short[2]>() const 195 { 196 ENSURE(vertexArray); 197 ENSURE(type == GL_SHORT); 198 ENSURE(elems >= 2); 169 199 200 return vertexArray->MakeIterator<short[2]>(this); 201 } 170 202 171 203 static size_t RoundStride(size_t stride) 172 204 { … … void VertexArray::Layout() 206 238 case GL_UNSIGNED_BYTE: 207 239 attrSize = sizeof(GLubyte); 208 240 break; 241 case GL_SHORT: 242 attrSize = sizeof(GLshort); 243 break; 209 244 case GL_UNSIGNED_SHORT: 210 245 attrSize = sizeof(GLushort); 211 246 break; -
source/renderer/VertexArray.h
diff --git a/source/renderer/VertexArray.h b/source/renderer/VertexArray.h index 7cf6cfa..4960052 100644
a b 1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … class VertexArray 134 134 public: 135 135 struct Attribute 136 136 { 137 // Data type. Currently supported: GL_FLOAT, GL_ UNSIGNED_BYTE137 // Data type. Currently supported: GL_FLOAT, GL_SHORT, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE. 138 138 GLenum type; 139 139 // How many elements per vertex (e.g. 3 for RGB, 2 for UV) 140 140 GLuint elems; … … public: 146 146 147 147 Attribute() : type(0), elems(0), offset(0), vertexArray(0) { } 148 148 149 // Get an iterator for the given attribute that initially points at the first vertex. 150 // Supported types T: CVector3D, CVector4D, float[2], SColor3ub, SColor4ub 149 // Get an iterator over the backing store for the given attribute that 150 // initially points at the first vertex. 151 // Supported types T: CVector3D, CVector4D, float[2], SColor3ub, SColor4ub, 152 // u16, u16[2], u8, u8[4], short, short[2]. 151 153 // This function verifies at runtime that the requested type T matches 152 154 // the attribute definition passed to AddAttribute(). 153 155 template<typename T> … … public: 171 173 // attributes. 172 174 // All vertex data is lost when a vertex array is re-layouted. 173 175 void Layout(); 174 // (Re-)Upload the attributes of the vertex array. 176 // (Re-)Upload the attributes of the vertex array from the backing store to 177 // the underlying VBO object. 175 178 void Upload(); 176 179 // Bind this array, returns the base address for calls to glVertexPointer etc. 177 180 u8* Bind(); … … private: 204 207 * A VertexArray that is specialised to handle 16-bit array indices. 205 208 * Call Bind() and pass the return value to the indices parameter of 206 209 * glDrawElements/glDrawRangeElements/glMultiDrawElements. 207 * Use CVertexBuffer::Unbind() to unbind the array .210 * Use CVertexBuffer::Unbind() to unbind the array when done. 208 211 */ 209 212 class VertexIndexArray : public VertexArray 210 213 { 211 214 public: 212 215 VertexIndexArray(GLenum usage); 213 216 217 /// Gets the iterator over the (only) attribute in this array, i.e. a u16. 214 218 VertexArrayIterator<u16> GetIterator() const; 215 219 216 220 private: -
source/renderer/VertexBuffer.cpp
diff --git a/source/renderer/VertexBuffer.cpp b/source/renderer/VertexBuffer.cpp index bcbfebe..514d6eb 100644
a b CVertexBuffer::CVertexBuffer(size_t vertexSize, GLenum usage, GLenum target) 33 33 { 34 34 size_t size = MAX_VB_SIZE_BYTES; 35 35 36 if (target == GL_ARRAY_BUFFER) 36 if (target == GL_ARRAY_BUFFER) // vertex data buffer 37 37 { 38 38 // We want to store 16-bit indices to any vertex in a buffer, so the 39 // buffer must never be bigger than vertexSize*64K bytes 39 // buffer must never be bigger than vertexSize*64K bytes since we can 40 // address at most 64K of them with 16-bit indices 40 41 size = std::min(size, vertexSize*65536); 41 42 } 42 43 … … CVertexBuffer::CVertexBuffer(size_t vertexSize, GLenum usage, GLenum target) 54 55 } 55 56 56 57 // store max/free vertex counts 57 m_MaxVertices =m_FreeVertices=size/vertexSize;58 m_MaxVertices = m_FreeVertices = size/vertexSize; 58 59 59 60 // create sole free chunk 60 VBChunk* chunk =new VBChunk;61 chunk->m_Owner =this;62 chunk->m_Count =m_FreeVertices;63 chunk->m_Index =0;61 VBChunk* chunk = new VBChunk; 62 chunk->m_Owner = this; 63 chunk->m_Count = m_FreeVertices; 64 chunk->m_Index = 0; 64 65 m_FreeList.push_front(chunk); 65 66 } 66 67 … … CVertexBuffer::VBChunk* CVertexBuffer::Allocate(size_t vertexSize, size_t numVer 100 101 return 0; 101 102 102 103 // trawl free list looking for first free chunk with enough space 103 VBChunk* chunk =0;104 VBChunk* chunk = 0; 104 105 typedef std::list<VBChunk*>::iterator Iter; 105 for (Iter iter =m_FreeList.begin();iter!=m_FreeList.end();++iter) {106 if (numVertices <=(*iter)->m_Count) {107 chunk =*iter;106 for (Iter iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) { 107 if (numVertices <= (*iter)->m_Count) { 108 chunk = *iter; 108 109 // remove this chunk from the free list 109 110 m_FreeList.erase(iter); 110 111 m_FreeVertices -= chunk->m_Count; … … void CVertexBuffer::Release(VBChunk* chunk) 173 174 174 175 /////////////////////////////////////////////////////////////////////////////// 175 176 // UpdateChunkVertices: update vertex data for given chunk 176 void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk, void* data)177 void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk, void* data) 177 178 { 178 179 if (g_Renderer.m_Caps.m_VBO) 179 180 { -
source/renderer/VertexBuffer.h
diff --git a/source/renderer/VertexBuffer.h b/source/renderer/VertexBuffer.h index 816d83f..c426868 100644
a b 1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 33 33 // TODO: measure what influence this has on performance 34 34 #define MAX_VB_SIZE_BYTES (2*1024*1024) 35 35 36 /////////////////////////////////////////////////////////////////////////////// 37 // CVertexBuffer: encapsulation of ARB_vertex_buffer_object, also supplying 38 // some additional functionality for sharing buffers between multiple objects 36 /** 37 * CVertexBuffer: encapsulation of ARB_vertex_buffer_object, also supplying 38 * some additional functionality for sharing buffers between multiple objects 39 */ 39 40 class CVertexBuffer 40 41 { 41 42 public: 42 // VBChunk: describes a portion of this vertex buffer 43 44 /// VBChunk: describes a portion of this vertex buffer 43 45 struct VBChunk 44 46 { 45 // owningbuffer47 /// Owning (parent) vertex buffer 46 48 CVertexBuffer* m_Owner; 47 // start index of this chunk in owner49 /// Start index of this chunk in owner 48 50 size_t m_Index; 49 // number of vertices used by chunk51 /// Number of vertices used by chunk 50 52 size_t m_Count; 51 53 52 54 private: … … public: 62 64 CVertexBuffer(size_t vertexSize, GLenum usage, GLenum target); 63 65 ~CVertexBuffer(); 64 66 65 // bind to this buffer; return pointer to address required as parameter66 // to glVertexPointer ( + etc) calls67 /// Bind to this buffer; return pointer to address required as parameter 68 /// to glVertexPointer ( + etc) calls 67 69 u8* Bind(); 68 70 69 // get the address that Bind() will return, without actually binding71 /// Get the address that Bind() will return, without actually binding 70 72 u8* GetBindAddress(); 71 73 72 // unbind any currently-bound buffer, so glVertexPointer etc calls will not attempt to use it74 /// Unbind any currently-bound buffer, so glVertexPointer etc calls will not attempt to use it 73 75 static void Unbind(); 74 76 75 // update vertex data for given chunk77 /// Update vertex data for given chunk. Transfers the provided data to the actual OpenGL vertex buffer. 76 78 void UpdateChunkVertices(VBChunk* chunk, void* data); 77 79 78 80 size_t GetVertexSize() const { return m_VertexSize; } 79 80 81 size_t GetBytesReserved() const; 81 82 size_t GetBytesAllocated() const; 82 83 84 /// Returns true if this vertex buffer is compatible with the specified vertex type and intended usage. 83 85 bool CompatibleVertexType(size_t vertexSize, GLenum usage, GLenum target); 84 86 85 87 void DumpStatus(); … … public: 87 89 protected: 88 90 friend class CVertexBufferManager; // allow allocate only via CVertexBufferManager 89 91 90 // try to allocate a buffer of given number of vertices (each of given size),91 // and with the given type - return null if no free chunks available92 /// Try to allocate a buffer of given number of vertices (each of given size), 93 /// and with the given type - return null if no free chunks available 92 94 VBChunk* Allocate(size_t vertexSize, size_t numVertices, GLenum usage, GLenum target); 93 // return given chunk to this buffer95 /// Return given chunk to this buffer 94 96 void Release(VBChunk* chunk); 95 97 96 98 97 99 private: 98 // vertex size of this vertex buffer100 /// Vertex size of this vertex buffer 99 101 size_t m_VertexSize; 100 // number of vertices of above size in this buffer102 /// Number of vertices of above size in this buffer 101 103 size_t m_MaxVertices; 102 // list of free chunks in this buffer104 /// List of free chunks in this buffer 103 105 std::list<VBChunk*> m_FreeList; 104 // available free vertices - total of all free vertices in the free list106 /// Available free vertices - total of all free vertices in the free list 105 107 size_t m_FreeVertices; 106 // handle to the actual GL vertex buffer object108 /// Handle to the actual GL vertex buffer object 107 109 GLuint m_Handle; 108 // raw system memory for systems not supporting VBOs110 /// Raw system memory for systems not supporting VBOs 109 111 u8* m_SysMem; 110 // usage type of the buffer (GL_STATIC_DRAW etc)112 /// Usage type of the buffer (GL_STATIC_DRAW etc) 111 113 GLenum m_Usage; 112 // buffer target (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER)114 /// Buffer target (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER) 113 115 GLenum m_Target; 114 116 }; 115 117 -
source/renderer/VertexBufferManager.h
diff --git a/source/renderer/VertexBufferManager.h b/source/renderer/VertexBufferManager.h index b97c68d..4ccb02f 100644
a b 1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 30 30 class CVertexBufferManager 31 31 { 32 32 public: 33 // Explicit shutdown of the vertex buffer subsystem34 void Shutdown();35 33 36 34 /** 37 35 * Try to allocate a vertex buffer of the given size and type. … … public: 44 42 */ 45 43 CVertexBuffer::VBChunk* Allocate(size_t vertexSize, size_t numVertices, GLenum usage, GLenum target); 46 44 47 // return given chunk to its owner45 /// Returns the given @p chunk to its owning buffer 48 46 void Release(CVertexBuffer::VBChunk* chunk); 49 47 50 // returnlist of all buffers48 /// Returns a list of all buffers 51 49 const std::list<CVertexBuffer*>& GetBufferList() const { return m_Buffers; } 52 50 53 51 size_t GetBytesReserved(); 54 52 size_t GetBytesAllocated(); 55 53 54 /// Returns the maximum possible size of a single vertex buffer 55 size_t GetMaxBufferSize() const { return MAX_VB_SIZE_BYTES; } 56 57 /// Explicit shutdown of the vertex buffer subsystem; releases all currently-allocated buffers. 58 void Shutdown(); 59 56 60 private: 57 // list of all known vertex buffers61 /// List of all known vertex buffers 58 62 std::list<CVertexBuffer*> m_Buffers; 59 63 }; 60 64 -
source/simulation2/components/CCmpRallyPointRenderer.cpp
diff --git a/source/simulation2/components/CCmpRallyPointRenderer.cpp b/source/simulation2/components/CCmpRallyPointRenderer.cpp index dc16628..0a52b6f 100644
a b void CCmpRallyPointRenderer::ConstructOverlayLines() 610 610 // construct solid textured overlay line along a subset of the full path points from startPointIdx to endPointIdx 611 611 SOverlayTexturedLine overlayLine; 612 612 overlayLine.m_Thickness = m_LineThickness; 613 overlayLine.m_ Terrain = cmpTerrain->GetCTerrain();613 overlayLine.m_SimContext = &GetSimContext(); 614 614 overlayLine.m_TextureBase = m_Texture; 615 615 overlayLine.m_TextureMask = m_TextureMask; 616 616 overlayLine.m_Color = m_LineColor; … … void CCmpRallyPointRenderer::ConstructOverlayLines() 634 634 } 635 635 else 636 636 { 637 // construct dashed line from startPointIdx to endPointIdx ,add textured overlay lines for it to the render list637 // construct dashed line from startPointIdx to endPointIdx; add textured overlay lines for it to the render list 638 638 std::vector<CVector2D> straightLine; 639 639 straightLine.push_back(m_Path[segment.m_StartIndex]); 640 640 straightLine.push_back(m_Path[segment.m_EndIndex]); 641 641 642 // We always want to have the dashed lineend at either point with a full dash (i.e. not a cleared space), so that the dashed643 // area is visually obvious. Th at implies that we want at least So, let's do some calculations to see what size we should make644 // t he dashes and clears.642 // We always want to the dashed line to end at either point with a full dash (i.e. not a cleared space), so that the dashed 643 // area is visually obvious. This requires some calculations to see what size we should make the dashes and clears for them 644 // to fit exactly. 645 645 646 646 float maxDashSize = 3.f; 647 647 float maxClearSize = 3.f; … … void CCmpRallyPointRenderer::ConstructOverlayLines() 652 652 653 653 float distance = (m_Path[segment.m_StartIndex] - m_Path[segment.m_EndIndex]).Length(); // straight-line distance between the points 654 654 655 // see how many pairs (dash + clear) can fit into the distance unmodified. Then check the remaining distance; if it's not exactly656 // a dash size's worth ( and it likely won't be), then adjust the dash/clear sizes slightly so that it is.655 // See how many pairs (dash + clear) of unmodified size can fit into the distance. Then check the remaining distance; if it's not exactly 656 // a dash size's worth (which it probably won't be), then adjust the dash/clear sizes slightly so that it is. 657 657 int numFitUnmodified = floor(distance/(dashSize + clearSize)); 658 658 float remainderDistance = distance - (numFitUnmodified * (dashSize + clearSize)); 659 659 … … void CCmpRallyPointRenderer::ConstructOverlayLines() 682 682 SOverlayTexturedLine dashOverlay; 683 683 684 684 dashOverlay.m_Thickness = m_LineThickness; 685 dashOverlay.m_ Terrain = cmpTerrain->GetCTerrain();685 dashOverlay.m_SimContext = &GetSimContext(); 686 686 dashOverlay.m_TextureBase = m_Texture; 687 687 dashOverlay.m_TextureMask = m_TextureMask; 688 688 dashOverlay.m_Color = m_LineDashColor; … … void CCmpRallyPointRenderer::FixFootprintWaypoints(std::vector<CVector2D>& coord 767 767 { 768 768 case ICmpFootprint::SQUARE: 769 769 { 770 // in this case, footprintSize0 and 1 respectively indicate the (unrotated) size along the X and Z axes770 // in this case, footprintSize0 and 1 indicate the size along the X and Z axes, respectively. 771 771 772 772 // the building's footprint could be rotated any which way, so let's get the rotation around the Y axis 773 773 // and the rotated unit vectors in the X/Z plane of the shape's footprint … … void CCmpRallyPointRenderer::FixInvisibleWaypoints(std::vector<CVector2D>& coord 837 837 player_id_t currentPlayer = GetSimContext().GetCurrentDisplayedPlayer(); 838 838 CLosQuerier losQuerier(cmpRangeMgr->GetLosQuerier(currentPlayer)); 839 839 840 //for (std::vector<Waypoint>::iterator it = waypoints.begin(); it != waypoints.end();)841 840 for(std::vector<CVector2D>::iterator it = coords.begin(); it != coords.end();) 842 841 { 843 842 int i = (fixed::FromFloat(it->X) / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNearest(); -
source/simulation2/components/CCmpSelectable.cpp
diff --git a/source/simulation2/components/CCmpSelectable.cpp b/source/simulation2/components/CCmpSelectable.cpp index d23916f..b4b6460 100644
a b 20 20 #include "simulation2/system/Component.h" 21 21 #include "ICmpSelectable.h" 22 22 23 #include "ICmpPosition.h"24 #include "ICmpFootprint.h"25 #include "ICmpVisual.h"26 #include "simulation2/MessageTypes.h"27 #include "simulation2/helpers/Render.h"28 29 23 #include "graphics/Overlay.h" 24 #include "graphics/Terrain.h" 25 #include "graphics/TextureManager.h" 26 #include "maths/Ease.h" 30 27 #include "maths/MathUtil.h" 31 28 #include "maths/Matrix3D.h" 32 29 #include "maths/Vector3D.h" 30 #include "maths/Vector2D.h" 31 #include "ps/CLogger.h" 33 32 #include "renderer/Scene.h" 33 #include "renderer/Renderer.h" 34 #include "simulation2/MessageTypes.h" 35 #include "simulation2/components/ICmpPosition.h" 36 #include "simulation2/components/ICmpFootprint.h" 37 #include "simulation2/components/ICmpVisual.h" 38 #include "simulation2/components/ICmpTerrain.h" 39 #include "simulation2/components/ICmpOwnership.h" 40 #include "simulation2/components/ICmpPlayer.h" 41 #include "simulation2/components/ICmpPlayerManager.h" 42 #include "simulation2/components/ICmpWaterManager.h" 43 #include "simulation2/helpers/Render.h" 34 44 35 45 class CCmpSelectable : public ICmpSelectable 36 46 { … … public: 39 49 { 40 50 componentManager.SubscribeToMessageType(MT_Interpolate); 41 51 componentManager.SubscribeToMessageType(MT_RenderSubmit); 52 componentManager.SubscribeToMessageType(MT_OwnershipChanged); 53 componentManager.SubscribeToMessageType(MT_PositionChanged); 42 54 // TODO: it'd be nice if we didn't get these messages except in the rare 43 55 // cases where we're actually drawing a selection highlight 44 56 } 45 57 46 58 DEFAULT_COMPONENT_ALLOCATOR(Selectable) 47 59 48 SOverlayLine m_Overlay;49 SOverlayLine* m_DebugBoundingBoxOverlay;50 SOverlayLine* m_DebugSelectionBoxOverlay;51 bool m_EditorOnly;52 53 60 CCmpSelectable() 54 : m_DebugBoundingBoxOverlay(NULL), m_DebugSelectionBoxOverlay(NULL) 61 : m_DebugBoundingBoxOverlay(NULL), m_DebugSelectionBoxOverlay(NULL), 62 m_BuildingOverlay(NULL), m_UnitOverlay(NULL), 63 m_FadeBaselineAlpha(0.f), m_FadeDeltaAlpha(0.f), m_FadeProgress(0.f) 55 64 { 56 m_Overlay.m_Thickness = 2; 57 m_Overlay.m_Color = CColor(0, 0, 0, 0); 65 m_Color = CColor(0, 0, 0, m_FadeBaselineAlpha); 58 66 } 59 67 60 ~CCmpSelectable(){ 68 ~CCmpSelectable() 69 { 61 70 delete m_DebugBoundingBoxOverlay; 62 71 delete m_DebugSelectionBoxOverlay; 72 delete m_BuildingOverlay; 73 delete m_UnitOverlay; 63 74 } 64 75 65 76 static std::string GetSchema() … … public: 71 82 "<element name='EditorOnly' a:help='If this element is present, the entity is only selectable in Atlas'>" 72 83 "<empty/>" 73 84 "</element>" 74 "</optional>"; 85 "</optional>" 86 "<element name='Overlay' a:help='Specifies the type of overlay to be displayed when this entity is selected'>" 87 "<choice>" 88 "<element name='Texture' a:help='Displays a texture underneath the entity.'>" 89 "<element name='MainTexture' a:help='Texture to display underneath the entity. Filepath relative to art/textures/selection/.'><text/></element>" 90 "<element name='MainTextureMask' a:help='Mask texture that controls where to apply player color. Filepath relative to art/textures/selection/.'><text/></element>" 91 "</element>" 92 "<element name='Outline' a:help='Traces the outline of the entity with a line texture.'>" 93 "<element name='LineTexture' a:help='Texture to apply to the line. Filepath relative to art/textures/selection/.'><text/></element>" 94 "<element name='LineTextureMask' a:help='Texture that controls where to apply player color. Filepath relative to art/textures/selection/.'><text/></element>" 95 "<element name='LineThickness' a:help='Thickness of the line, in world units.'><ref name='positiveDecimal'/></element>" 96 "</element>" 97 "</choice>" 98 "</element>"; 75 99 } 76 100 77 101 virtual void Init(const CParamNode& paramNode) 78 102 { 79 103 m_EditorOnly = paramNode.GetChild("EditorOnly").IsOk(); 80 }81 104 82 virtual void Deinit() 83 { 105 const CParamNode& textureNode = paramNode.GetChild("Overlay").GetChild("Texture"); 106 const CParamNode& outlineNode = paramNode.GetChild("Overlay").GetChild("Outline"); 107 108 const char* textureBasePath = "art/textures/selection/"; 109 110 // Save some memory by using interned file paths in these descriptors (almost all actors and 111 // entities have this component, and many use the same textures). 112 if (textureNode.IsOk()) 113 { 114 // textured quad mode (dynamic, for units) 115 m_OverlayDescriptor.m_Type = ICmpSelectable::DYNAMIC_QUAD; 116 m_OverlayDescriptor.m_QuadTexture = CStrIntern(textureBasePath + textureNode.GetChild("MainTexture").ToUTF8()); 117 m_OverlayDescriptor.m_QuadTextureMask = CStrIntern(textureBasePath + textureNode.GetChild("MainTextureMask").ToUTF8()); 118 } 119 else if (outlineNode.IsOk()) 120 { 121 // textured outline mode (static, for buildings) 122 m_OverlayDescriptor.m_Type = ICmpSelectable::STATIC_OUTLINE; 123 m_OverlayDescriptor.m_LineTexture = CStrIntern(textureBasePath + outlineNode.GetChild("LineTexture").ToUTF8()); 124 m_OverlayDescriptor.m_LineTextureMask = CStrIntern(textureBasePath + outlineNode.GetChild("LineTextureMask").ToUTF8()); 125 m_OverlayDescriptor.m_LineThickness = outlineNode.GetChild("LineThickness").ToFloat(); 126 } 84 127 } 85 128 129 virtual void Deinit() { } 130 86 131 virtual void Serialize(ISerializer& UNUSED(serialize)) 87 132 { 88 133 // Nothing to do here (the overlay object is not worth saving, it'll get … … public: 95 140 Init(paramNode); 96 141 } 97 142 98 virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) 143 virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)); 144 145 virtual void SetSelectionHighlight(CColor color) 99 146 { 100 switch (msg.GetType()) 101 { 102 case MT_Interpolate: 147 m_Color.r = color.r; 148 m_Color.g = color.g; 149 m_Color.b = color.b; 150 151 // set up fading from the current value (as the baseline) to the target value 152 m_FadeBaselineAlpha = m_Color.a; 153 m_FadeDeltaAlpha = color.a - m_FadeBaselineAlpha; 154 m_FadeProgress = 0.f; 155 } 156 157 virtual bool IsEditorOnly() 158 { 159 return m_EditorOnly; 160 } 161 162 void RenderSubmit(SceneCollector& collector); 163 164 /** 165 * Called from RenderSubmit if using a static outline; responsible for ensuring that the static overlay 166 * is up-to-date before it is rendered. Has no effect unless the static overlay is explicitly marked as 167 * invalid first (see InvalidateStaticOverlay). 168 */ 169 void UpdateStaticOverlay(); 170 171 /** 172 * Called from the interpolation handler; responsible for ensuring the dynamic overlay (provided we're 173 * using one) is up-to-date and ready to be submitted to the next rendering run. 174 */ 175 void UpdateDynamicOverlay(float frameOffset); 176 177 /// Explicitly invalidates the static overlay. 178 void InvalidateStaticOverlay(); 179 180 private: 181 SOverlayDescriptor m_OverlayDescriptor; 182 SOverlayTexturedLine* m_BuildingOverlay; 183 SOverlayQuad* m_UnitOverlay; 184 185 SOverlayLine* m_DebugBoundingBoxOverlay; 186 SOverlayLine* m_DebugSelectionBoxOverlay; 187 188 bool m_EditorOnly; 189 190 /// Current selection overlay color. Alpha component is subject to fading. 191 CColor m_Color; 192 /// Baseline alpha value to start fading from. Constant during a single fade. 193 float m_FadeBaselineAlpha; 194 /// Delta between target and baseline alpha. Constant during a single fade. Can be positive or negative. 195 float m_FadeDeltaAlpha; 196 /// Linear time progress of the fade, between 0 and m_FadeDuration. 197 float m_FadeProgress; 198 /// Total duration of a single fade, in seconds. Assumed constant for now; feel free to change this into 199 /// a member variable if you need to adjust it per component. 200 static const float FADE_DURATION; 201 }; 202 203 const float CCmpSelectable::FADE_DURATION = 0.3f; 204 205 void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global)) 206 { 207 switch (msg.GetType()) 208 { 209 case MT_Interpolate: 103 210 { 104 if (m_Overlay.m_Color.a > 0) 211 const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg); 212 213 if (m_FadeDeltaAlpha != 0.f) 214 { 215 m_FadeProgress += msgData.frameTime; 216 if (m_FadeProgress >= FADE_DURATION) 217 { 218 const float targetAlpha = m_FadeBaselineAlpha + m_FadeDeltaAlpha; 219 220 // stop the fade 221 m_Color.a = targetAlpha; 222 m_FadeBaselineAlpha = targetAlpha; 223 m_FadeDeltaAlpha = 0.f; 224 m_FadeProgress = FADE_DURATION; // will need to be reset to start the next fade again 225 } 226 else 227 { 228 m_Color.a = Ease::QuartOut(m_FadeProgress, m_FadeBaselineAlpha, m_FadeDeltaAlpha, FADE_DURATION); 229 } 230 } 231 232 // update dynamic overlay only when visible 233 if (m_Color.a > 0) 105 234 { 106 float offset = static_cast<const CMessageInterpolate&> (msg).offset; 107 ConstructShape(offset); 235 UpdateDynamicOverlay(msgData.offset); 108 236 } 237 109 238 break; 110 239 } 111 case MT_RenderSubmit:240 case MT_OwnershipChanged: 112 241 { 113 if (m_Overlay.m_Color.a > 0) 114 { 115 const CMessageRenderSubmit& msgData = static_cast<const CMessageRenderSubmit&> (msg); 116 RenderSubmit(msgData.collector); 117 } 242 const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg); 243 244 // don't update color if there's no new owner (e.g. the unit died) 245 if (msgData.to == INVALID_PLAYER) 246 break; 247 248 // update the selection highlight color 249 CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); 250 if (!cmpPlayerManager) 251 break; 252 253 CmpPtr<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(msgData.to)); 254 if (!cmpPlayer) 255 break; 256 257 // Update the highlight color, while keeping the current alpha target value intact 258 // (i.e. baseline + delta), so that any ongoing fades simply continue with the new color. 259 CColor color = cmpPlayer->GetColour(); 260 SetSelectionHighlight(CColor(color.r, color.g, color.b, m_FadeBaselineAlpha + m_FadeDeltaAlpha)); 261 } 262 // fall-through 263 case MT_PositionChanged: 264 { 265 InvalidateStaticOverlay(); 118 266 break; 119 267 } 268 case MT_RenderSubmit: 269 { 270 const CMessageRenderSubmit& msgData = static_cast<const CMessageRenderSubmit&> (msg); 271 RenderSubmit(msgData.collector); 272 273 break; 120 274 } 121 275 } 276 } 122 277 123 virtual bool IsEditorOnly()124 125 return m_EditorOnly;126 278 void CCmpSelectable::InvalidateStaticOverlay() 279 { 280 SAFE_DELETE(m_BuildingOverlay); 281 } 127 282 128 virtual void SetSelectionHighlight(CColor color) 283 void CCmpSelectable::UpdateStaticOverlay() 284 { 285 // Static overlays are allocated once and not updated until they are explicitly deleted again 286 // (see InvalidateStaticOverlay). Since they are expected to change rarely (if ever) during 287 // normal gameplay, this saves us doing all the work below on each frame. 288 289 if (m_BuildingOverlay || m_OverlayDescriptor.m_Type != STATIC_OUTLINE) 290 return; 291 292 if (!CRenderer::IsInitialised()) 293 return; 294 295 entity_id_t entityId = GetEntityId(); 296 CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), entityId); 297 CmpPtr<ICmpFootprint> cmpFootprint(GetSimContext(), entityId); 298 if (!cmpFootprint || !cmpPosition || !cmpPosition->IsInWorld()) 299 return; 300 301 CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY); 302 if (!cmpTerrain) 303 return; // should never happen 304 305 // grab position/footprint data 306 CFixedVector2D position = cmpPosition->GetPosition2D(); 307 CFixedVector3D rotation = cmpPosition->GetRotation(); 308 309 ICmpFootprint::EShape fpShape; 310 entity_pos_t fpSize0_fixed, fpSize1_fixed, fpHeight_fixed; 311 cmpFootprint->GetShape(fpShape, fpSize0_fixed, fpSize1_fixed, fpHeight_fixed); 312 313 CTextureProperties texturePropsBase(m_OverlayDescriptor.m_LineTexture.c_str()); 314 texturePropsBase.SetWrap(GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE); 315 texturePropsBase.SetMaxAnisotropy(4.f); 316 317 CTextureProperties texturePropsMask(m_OverlayDescriptor.m_LineTextureMask.c_str()); 318 texturePropsMask.SetWrap(GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE); 319 texturePropsMask.SetMaxAnisotropy(4.f); 320 321 // ------------------------------------------------------------------------------------- 322 323 m_BuildingOverlay = new SOverlayTexturedLine; 324 m_BuildingOverlay->m_AlwaysVisible = false; 325 m_BuildingOverlay->m_Closed = true; 326 m_BuildingOverlay->m_SimContext = &GetSimContext(); 327 m_BuildingOverlay->m_Thickness = m_OverlayDescriptor.m_LineThickness; 328 m_BuildingOverlay->m_TextureBase = g_Renderer.GetTextureManager().CreateTexture(texturePropsBase); 329 m_BuildingOverlay->m_TextureMask = g_Renderer.GetTextureManager().CreateTexture(texturePropsMask); 330 331 CVector2D origin(position.X.ToFloat(), position.Y.ToFloat()); 332 333 switch (fpShape) 129 334 { 130 m_Overlay.m_Color = color; 335 case ICmpFootprint::SQUARE: 336 { 337 float s = sinf(-rotation.Y.ToFloat()); 338 float c = cosf(-rotation.Y.ToFloat()); 339 CVector2D unitX(c, s); 340 CVector2D unitZ(-s, c); 341 342 // add half the line thickness to the radius so that we get an 'outside' stroke of the footprint shape 343 const float halfSizeX = fpSize0_fixed.ToFloat()/2.f + m_BuildingOverlay->m_Thickness/2.f; 344 const float halfSizeZ = fpSize1_fixed.ToFloat()/2.f + m_BuildingOverlay->m_Thickness/2.f; 131 345 132 if (color.a == 0 && !m_Overlay.m_Coords.empty()) 346 std::vector<CVector2D> points; 347 points.push_back(CVector2D(origin + unitX * halfSizeX + unitZ *(-halfSizeZ))); 348 points.push_back(CVector2D(origin + unitX *(-halfSizeX) + unitZ *(-halfSizeZ))); 349 points.push_back(CVector2D(origin + unitX *(-halfSizeX) + unitZ * halfSizeZ)); 350 points.push_back(CVector2D(origin + unitX * halfSizeX + unitZ * halfSizeZ)); 351 352 SimRender::SubdividePoints(points, TERRAIN_TILE_SIZE/3.f, m_BuildingOverlay->m_Closed); 353 m_BuildingOverlay->PushCoords(points); 354 } 355 break; 356 case ICmpFootprint::CIRCLE: 133 357 { 134 // Delete the overlay data to save memory (we don't want hundreds of bytes 135 // times thousands of units when the selections are not being rendered any more) 136 std::vector<float> empty; 137 m_Overlay.m_Coords.swap(empty); 138 ENSURE(m_Overlay.m_Coords.capacity() == 0); 358 const float radius = fpSize0_fixed.ToFloat() + m_BuildingOverlay->m_Thickness/3.f; 359 if (radius > 0) // prevent catastrophic failure 360 { 361 float stepAngle; 362 unsigned numSteps; 363 SimRender::AngularStepFromChordLen(TERRAIN_TILE_SIZE/3.f, radius, stepAngle, numSteps); 364 365 for (unsigned i = 0; i < numSteps; i++) // '<' is sufficient because the line is closed automatically 366 { 367 float angle = i * stepAngle; 368 float px = origin.X + radius * sinf(angle); 369 float pz = origin.Y + radius * cosf(angle); 370 371 m_BuildingOverlay->PushCoords(px, pz); 372 } 373 } 139 374 } 375 break; 376 } 140 377 141 // TODO: it'd be nice to fade smoothly (but quickly) from transparent to solid 378 ENSURE(m_BuildingOverlay); 379 } 380 381 void CCmpSelectable::UpdateDynamicOverlay(float frameOffset) 382 { 383 // Dynamic overlay lines are allocated once and never deleted. Since they are expected to change frequently, 384 // they are assumed dirty on every call to this function, and we should therefore use this function more 385 // thoughtfully than calling it right before every frame render. 386 387 if (m_OverlayDescriptor.m_Type != DYNAMIC_QUAD) 388 return; 389 390 if (!CRenderer::IsInitialised()) 391 return; 392 393 entity_id_t entityId = GetEntityId(); 394 CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), entityId); 395 CmpPtr<ICmpFootprint> cmpFootprint(GetSimContext(), entityId); 396 if (!cmpFootprint || !cmpPosition || !cmpPosition->IsInWorld()) 397 return; 398 399 float rotY; 400 CVector2D position; 401 cmpPosition->GetInterpolatedPosition2D(frameOffset, position.X, position.Y, rotY); 402 403 CmpPtr<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY); 404 CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY); 405 ENSURE(cmpWaterManager && cmpTerrain); 406 407 CTerrain* terrain = cmpTerrain->GetCTerrain(); 408 ENSURE(terrain); 409 410 ICmpFootprint::EShape fpShape; 411 entity_pos_t fpSize0_fixed, fpSize1_fixed, fpHeight_fixed; 412 cmpFootprint->GetShape(fpShape, fpSize0_fixed, fpSize1_fixed, fpHeight_fixed); 413 414 // --------------------------------------------------------------------------------- 415 416 if (!m_UnitOverlay) 417 { 418 m_UnitOverlay = new SOverlayQuad; 419 420 // Assuming we don't need the capability of swapping textures on-demand. 421 CTextureProperties texturePropsBase(m_OverlayDescriptor.m_QuadTexture.c_str()); 422 texturePropsBase.SetWrap(GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE); 423 texturePropsBase.SetMaxAnisotropy(4.f); 424 425 CTextureProperties texturePropsMask(m_OverlayDescriptor.m_QuadTextureMask.c_str()); 426 texturePropsMask.SetWrap(GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE); 427 texturePropsMask.SetMaxAnisotropy(4.f); 428 429 m_UnitOverlay->m_Texture = g_Renderer.GetTextureManager().CreateTexture(texturePropsBase); 430 m_UnitOverlay->m_TextureMask = g_Renderer.GetTextureManager().CreateTexture(texturePropsMask); 142 431 } 143 432 144 void ConstructShape(float frameOffset) 433 m_UnitOverlay->m_Color = m_Color; 434 435 // TODO: some code duplication here :< would be nice to factor out getting the corner points of an 436 // entity based on its footprint sizes (and regardless of whether it's a circle or a square) 437 438 float s = sinf(-rotY); 439 float c = cosf(-rotY); 440 CVector2D unitX(c, s); 441 CVector2D unitZ(-s, c); 442 443 float halfSizeX = fpSize0_fixed.ToFloat(); 444 float halfSizeZ = fpSize1_fixed.ToFloat(); 445 if (fpShape == ICmpFootprint::SQUARE) 145 446 { 146 CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());147 if (!cmpPosition)148 return;447 halfSizeX /= 2.0f; 448 halfSizeZ /= 2.0f; 449 } 149 450 150 if (!cmpPosition->IsInWorld()) 151 return; 451 std::vector<CVector2D> points; 452 points.push_back(CVector2D(position + unitX *(-halfSizeX) + unitZ * halfSizeZ)); // top left 453 points.push_back(CVector2D(position + unitX *(-halfSizeX) + unitZ *(-halfSizeZ))); // bottom left 454 points.push_back(CVector2D(position + unitX * halfSizeX + unitZ *(-halfSizeZ))); // bottom right 455 points.push_back(CVector2D(position + unitX * halfSizeX + unitZ * halfSizeZ)); // top right 152 456 153 float x, z, rotY; 154 cmpPosition->GetInterpolatedPosition2D(frameOffset, x, z, rotY); 457 for (int i=0; i < 4; i++) 458 { 459 float quadY = std::max( 460 terrain->GetExactGroundLevel(points[i].X, points[i].Y), 461 cmpWaterManager->GetExactWaterLevel(points[i].X, points[i].Y) 462 ); 155 463 156 CmpPtr<ICmpFootprint> cmpFootprint(GetSimContext(), GetEntityId()); 157 if (!cmpFootprint) 158 { 159 // Default (this probably shouldn't happen) - just render an arbitrary-sized circle 160 SimRender::ConstructCircleOnGround(GetSimContext(), x, z, 2.f, m_Overlay, cmpPosition->IsFloating()); 161 } 162 else 464 m_UnitOverlay->m_Corners[i] = CVector3D(points[i].X, quadY, points[i].Y); 465 } 466 } 467 468 void CCmpSelectable::RenderSubmit(SceneCollector& collector) 469 { 470 // don't render selection overlay if it's not gonna be visible 471 if (m_Color.a > 0) 472 { 473 switch (m_OverlayDescriptor.m_Type) 163 474 { 164 ICmpFootprint::EShape shape; 165 entity_pos_t size0, size1, height; 166 cmpFootprint->GetShape(shape, size0, size1, height); 167 168 if (shape == ICmpFootprint::SQUARE) 169 SimRender::ConstructSquareOnGround(GetSimContext(), x, z, size0.ToFloat(), size1.ToFloat(), rotY, m_Overlay, cmpPosition->IsFloating()); 170 else 171 SimRender::ConstructCircleOnGround(GetSimContext(), x, z, size0.ToFloat(), m_Overlay, cmpPosition->IsFloating()); 475 case STATIC_OUTLINE: 476 { 477 UpdateStaticOverlay(); 478 m_BuildingOverlay->m_Color = m_Color; // done separately so alpha changes don't require a full update call 479 collector.Submit(m_BuildingOverlay); 480 } 481 break; 482 case DYNAMIC_QUAD: 483 { 484 if (m_UnitOverlay) 485 collector.Submit(m_UnitOverlay); 486 } 487 break; 488 default: 489 break; 172 490 } 173 491 } 174 492 175 void RenderSubmit(SceneCollector& collector) 493 // Render bounding box debug overlays if we have a positive target alpha value. This ensures 494 // that the debug overlays respond immediately to deselection without delay from fading out. 495 if (m_FadeBaselineAlpha + m_FadeDeltaAlpha > 0) 176 496 { 177 // (This is only called if a > 0)178 collector.Submit(&m_Overlay);179 180 497 if (ICmpSelectable::ms_EnableDebugOverlays) 181 498 { 182 499 // allocate debug overlays on-demand … … public: 205 522 if (m_DebugSelectionBoxOverlay) SAFE_DELETE(m_DebugSelectionBoxOverlay); 206 523 } 207 524 } 208 } ;525 } 209 526 210 527 REGISTER_COMPONENT_TYPE(Selectable) -
source/simulation2/components/CCmpTemplateManager.cpp
diff --git a/source/simulation2/components/CCmpTemplateManager.cpp b/source/simulation2/components/CCmpTemplateManager.cpp index 9061c5f..7b24af7 100644
a b void CCmpTemplateManager::ConstructTemplateActor(const std::string& actorName, C 377 377 378 378 // Initialise the actor's name and make it an Atlas selectable entity. 379 379 std::string name = utf8_from_wstring(CParamNode::EscapeXMLString(wstring_from_utf8(actorName))); 380 std::string xml = "<Entity><VisualActor><Actor>" + name + "</Actor></VisualActor><Selectable><EditorOnly/></Selectable></Entity>"; 380 std::string xml = "<Entity>" 381 "<VisualActor><Actor>" + name + "</Actor></VisualActor>" 382 "<Selectable>" 383 "<EditorOnly/>" 384 "<Overlay><Texture><MainTexture>actor.png</MainTexture><MainTextureMask>actor_mask.png</MainTextureMask></Texture></Overlay>" 385 "</Selectable>" 386 "</Entity>"; 387 381 388 CParamNode::LoadXMLString(out, xml.c_str()); 382 389 } 383 390 -
source/simulation2/components/CCmpTerritoryManager.cpp
diff --git a/source/simulation2/components/CCmpTerritoryManager.cpp b/source/simulation2/components/CCmpTerritoryManager.cpp index 4aa01bf..03c4fff 100644
a b void CCmpTerritoryManager::UpdateBoundaryLines() 620 620 texturePropsMask.SetMaxAnisotropy(2.f); 621 621 CTexturePtr textureMask = g_Renderer.GetTextureManager().CreateTexture(texturePropsMask); 622 622 623 CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);624 if (!cmpTerrain)625 return;626 CTerrain* terrain = cmpTerrain->GetCTerrain();627 628 623 CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); 629 624 if (!cmpPlayerManager) 630 625 return; … … void CCmpTerritoryManager::UpdateBoundaryLines() 642 637 m_BoundaryLines.push_back(SBoundaryLine()); 643 638 m_BoundaryLines.back().connected = boundaries[i].connected; 644 639 m_BoundaryLines.back().color = color; 645 m_BoundaryLines.back().overlay.m_ Terrain = terrain;640 m_BoundaryLines.back().overlay.m_SimContext = &GetSimContext(); 646 641 m_BoundaryLines.back().overlay.m_TextureBase = textureBase; 647 642 m_BoundaryLines.back().overlay.m_TextureMask = textureMask; 648 643 m_BoundaryLines.back().overlay.m_Color = color; … … void CCmpTerritoryManager::UpdateBoundaryLines() 650 645 m_BoundaryLines.back().overlay.m_Closed = true; 651 646 652 647 SimRender::SmoothPointsAverage(boundaries[i].points, m_BoundaryLines.back().overlay.m_Closed); 653 654 648 SimRender::InterpolatePointsRNS(boundaries[i].points, m_BoundaryLines.back().overlay.m_Closed, m_BorderSeparation); 655 649 656 650 std::vector<float>& points = m_BoundaryLines.back().overlay.m_Coords; -
source/simulation2/components/ICmpSelectable.h
diff --git a/source/simulation2/components/ICmpSelectable.h b/source/simulation2/components/ICmpSelectable.h index c7c8ec2..42f0026 100644
a b 18 18 #ifndef INCLUDED_ICMPSELECTABLE 19 19 #define INCLUDED_ICMPSELECTABLE 20 20 21 #include "ps/CStrIntern.h" 21 22 #include "simulation2/system/Interface.h" 22 23 23 24 struct CColor; … … struct CColor; 25 26 class ICmpSelectable : public IComponent 26 27 { 27 28 public: 29 30 enum EOverlayType { 31 /// A single textured quad overlay, intended for entities that move around much, like units (e.g. foot soldiers, etc). 32 DYNAMIC_QUAD, 33 /// A more complex textured line overlay, composed of several textured line segments. Intended for entities that do not 34 /// move often, such as buildings (structures). 35 STATIC_OUTLINE, 36 }; 37 38 struct SOverlayDescriptor 39 { 40 EOverlayType m_Type; 41 CStrIntern m_QuadTexture; 42 CStrIntern m_QuadTextureMask; 43 CStrIntern m_LineTexture; 44 CStrIntern m_LineTextureMask; 45 float m_LineThickness; 46 47 SOverlayDescriptor() : m_LineThickness(0) { } 48 }; 49 28 50 /** 29 51 * Returns true if the entity is only selectable in Atlas editor, e.g. a decorative visual actor. 30 52 */ -
source/simulation2/helpers/Geometry.cpp
diff --git a/source/simulation2/helpers/Geometry.cpp b/source/simulation2/helpers/Geometry.cpp index b357561..5b713f0 100644
a b 1 /* Copyright (C) 201 0Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … CFixedVector2D Geometry::GetHalfBoundingBox(CFixedVector2D u, CFixedVector2D v, 45 45 ); 46 46 } 47 47 48 float Geometry::ChordToCentralAngle(const float chordLength, const float radius) 49 { 50 return acosf(1.f - SQR(chordLength)/(2.f*SQR(radius))); // cfr. law of cosines 51 } 52 48 53 fixed Geometry::DistanceToSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize) 49 54 { 50 55 /* -
source/simulation2/helpers/Geometry.h
diff --git a/source/simulation2/helpers/Geometry.h b/source/simulation2/helpers/Geometry.h index cb925b7..e8af00e 100644
a b 1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 24 24 */ 25 25 26 26 #include "maths/Fixed.h" 27 #include "maths/MathUtil.h" 27 28 28 29 class CFixedVector2D; 29 30 … … CFixedVector2D GetHalfBoundingBox(CFixedVector2D u, CFixedVector2D v, CFixedVect 53 54 fixed DistanceToSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize); 54 55 55 56 /** 57 * Given a circle of radius @p radius, and a chord of length @p chordLength on this circle, computes the central angle formed by 58 * connecting the chord's endpoints to the center of the circle. 59 * 60 * @param radius Radius of the circle; must be strictly positive. 61 */ 62 float ChordToCentralAngle(const float chordLength, const float radius); 63 64 /** 56 65 * Find point closest to the given point on the edge of the given square or rectangle. 57 66 * 58 67 * @note Currently assumes the @p u and @p v vectors are perpendicular. -
source/simulation2/helpers/Render.cpp
diff --git a/source/simulation2/helpers/Render.cpp b/source/simulation2/helpers/Render.cpp index 450a28d..712a6d4 100644
a b 19 19 20 20 #include "Render.h" 21 21 22 #include "simulation2/Simulation2.h"23 #include "simulation2/components/ICmpTerrain.h"24 #include "simulation2/components/ICmpWaterManager.h"25 22 #include "graphics/Overlay.h" 26 23 #include "graphics/Terrain.h" 27 24 #include "maths/BoundingBoxAligned.h" 28 25 #include "maths/BoundingBoxOriented.h" 29 26 #include "maths/MathUtil.h" 27 #include "maths/Quaternion.h" 30 28 #include "maths/Vector2D.h" 31 29 #include "ps/Profile.h" 32 #include "maths/Quaternion.h" 30 #include "simulation2/Simulation2.h" 31 #include "simulation2/components/ICmpTerrain.h" 32 #include "simulation2/components/ICmpWaterManager.h" 33 #include "simulation2/helpers/Geometry.h" 33 34 34 35 void SimRender::ConstructLineOnGround(const CSimContext& context, const std::vector<float>& xz, 35 36 SOverlayLine& overlay, bool floating, float heightOffset) … … static CVector2D EvaluateSpline(float t, CVector2D a0, CVector2D a1, CVector2D a 343 344 return p + CVector2D(dp.Y*-offset, dp.X*offset); 344 345 } 345 346 346 void SimRender::InterpolatePointsRNS(std::vector<CVector2D>& points, bool closed, float offset, int segmentSamples )347 void SimRender::InterpolatePointsRNS(std::vector<CVector2D>& points, bool closed, float offset, int segmentSamples /* = 4 */) 347 348 { 348 349 PROFILE("InterpolatePointsRNS"); 349 350 ENSURE(segmentSamples > 0); … … void SimRender::InterpolatePointsRNS(std::vector<CVector2D>& points, bool closed 381 382 382 383 for (size_t i = 0; i < imax; ++i) 383 384 { 384 385 385 // Get the relevant points for this spline segment; each step interpolates the segment between p1 and p2; p0 and p3 are the points 386 386 // before p1 and after p2, respectively; they're needed to compute tangents and whatnot. 387 387 CVector2D p0; // normally points[(i-1+n)%n], but it's a bit more complicated due to open/closed paths -- see below … … void SimRender::ConstructDashedLine(const std::vector<CVector2D>& keyPoints, SDa 521 521 } 522 522 523 523 } 524 525 void SimRender::AngularStepFromChordLen(const float maxChordLength, const float radius, float& out_stepAngle, unsigned& out_numSteps) 526 { 527 float maxAngle = Geometry::ChordToCentralAngle(maxChordLength, radius); 528 out_numSteps = ceilf(float(2*M_PI)/maxAngle); 529 out_stepAngle = float(2*M_PI)/out_numSteps; 530 } 531 532 // TODO: this serves a similar purpose to SplitLine above, but is more general. Also, SplitLine seems to be implemented more 533 // efficiently, might be nice to take some cues from it 534 void SimRender::SubdividePoints(std::vector<CVector2D>& points, float maxSegmentLength, bool closed) 535 { 536 size_t numControlPoints = points.size(); 537 if (numControlPoints < 2) 538 return; 539 540 ENSURE(maxSegmentLength > 0); 541 542 size_t endIndex = numControlPoints; 543 if (!closed && numControlPoints > 2) 544 endIndex--; 545 546 std::vector<CVector2D> newPoints; 547 548 for (size_t i = 0; i < endIndex; i++) 549 { 550 const CVector2D& curPoint = points[i]; 551 const CVector2D& nextPoint = points[(i+1) % numControlPoints]; 552 const CVector2D line(nextPoint - curPoint); 553 CVector2D lineDirection = line.Normalized(); 554 555 // include control point i + a list of intermediate points between i and i + 1 (excluding i+1 itself) 556 newPoints.push_back(curPoint); 557 558 // calculate how many intermediate points are needed so that each segment is of length <= maxSegmentLength 559 float lineLength = line.Length(); 560 size_t numSegments = (size_t) ceilf(lineLength / maxSegmentLength); 561 float segmentLength = lineLength / numSegments; 562 563 for (size_t s = 1; s < numSegments; ++s) // start at one, we already included curPoint 564 { 565 newPoints.push_back(curPoint + lineDirection * (s * segmentLength)); 566 } 567 } 568 569 points.swap(newPoints); 570 } 571 No newline at end of file -
source/simulation2/helpers/Render.h
diff --git a/source/simulation2/helpers/Render.h b/source/simulation2/helpers/Render.h index 93e812d..6ed8be2 100644
a b 1 /* Copyright (C) 201 0Wildfire Games.1 /* Copyright (C) 2012 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … void ConstructLineOnGround(const CSimContext& context, const std::vector<float>& 76 76 * @param[in,out] overlay Updated overlay line representing this circle. 77 77 * @param[in] floating If true, the circle conforms to water as well. 78 78 * @param[in] heightOffset Height above terrain to offset the circle. 79 * @param heightOffset The vertical offset to apply to points, to raise the line off the terrain a bit. 79 80 */ 80 81 void ConstructCircleOnGround(const CSimContext& context, float x, float z, float radius, 81 82 SOverlayLine& overlay, … … void ConstructSquareOnGround(const CSimContext& context, float x, float z, float 96 97 bool floating, float heightOffset = 0.25f); 97 98 98 99 /** 99 * Constructs a solid outline of an arbitrarily-aligned bo x.100 * Constructs a solid outline of an arbitrarily-aligned bounding @p box. 100 101 * 101 102 * @param[in] box 102 103 * @param[in,out] overlayLine Updated overlay line representing the oriented box. … … void ConstructSquareOnGround(const CSimContext& context, float x, float z, float 104 105 void ConstructBoxOutline(const CBoundingBoxOriented& box, SOverlayLine& overlayLine); 105 106 106 107 /** 107 * Constructs a solid outline of an axis-aligned bounding box.108 * Constructs a solid outline of an axis-aligned bounding @p box. 108 109 * 109 110 * @param[in] bound 110 111 * @param[in,out] overlayLine Updated overlay line representing the AABB. 111 112 */ 112 void ConstructBoxOutline(const CBoundingBoxAligned& bo und, SOverlayLine& overlayLine);113 void ConstructBoxOutline(const CBoundingBoxAligned& box, SOverlayLine& overlayLine); 113 114 114 115 /** 115 116 * Constructs a simple gimbal outline with the given radius and center. … … void ConstructGimbal(const CVector3D& center, float radius, SOverlayLine& out, s 124 125 125 126 /** 126 127 * Constructs 3D axis marker overlay lines for the given coordinate system. 127 * The overlay lines are colored RGB for the XYZ axes, respectively.128 * The XYZ axes are colored RGB, respectively. 128 129 * 129 130 * @param[in] coordSystem Specifies the coordinate system. 130 131 * @param[out] outX,outY,outZ Constructed overlay lines for each axes. … … void InterpolatePointsRNS(std::vector<CVector2D>& points, bool closed, float off 162 163 * @param[in] dashLength Length of a single dash. Must be strictly positive. 163 164 * @param[in] blankLength Length of a single blank between dashes. Must be strictly positive. 164 165 */ 165 void ConstructDashedLine(const std::vector<CVector2D>& linePoints, SDashedLine& dashedLineOut, const float dashLength, const float blankLength); 166 void ConstructDashedLine(const std::vector<CVector2D>& linePoints, SDashedLine& dashedLineOut, 167 const float dashLength, const float blankLength); 168 169 /** 170 * Computes angular step parameters @p out_stepAngle and @p out_numSteps, given a @p maxChordLength on a circle of radius @p radius. 171 * The resulting values satisfy @p out_numSteps * @p out_stepAngle = 2*PI. 172 * 173 * This function is used to find the angular step parameters when drawing a circle outline approximated by several connected chords; 174 * it returns the step angle and number of steps such that the length of each resulting chord is less than or equal to @p maxChordLength. 175 * By stating that each chord cannot be longer than a particular length, a certain level of visual smoothness of the resulting circle 176 * outline can be guaranteed independently of the radius of the outline. 177 * 178 * @param radius Radius of the circle. Must be strictly positive. 179 * @param maxChordLength Desired maximum length of individual chords. Must be strictly positive. 180 */ 181 void AngularStepFromChordLen(const float maxChordLength, const float radius, float& out_stepAngle, unsigned& out_numSteps); 182 183 /** 184 * Subdivides a list of @p points into segments of maximum length @p maxSegmentLength that are of equal size between every two 185 * control points. The resulting subdivided list of points is written back to @p points. 186 * 187 * @param points The list of intermediate points to subdivide. 188 * @param maxSegmentLength The maximum length of a single segment after subdivision. Must be strictly positive. 189 * @param closed Should the provided list of points be treated as a closed shape? If true, the resulting list of points will include 190 * extra subdivided points between the last and the first point. 191 */ 192 void SubdividePoints(std::vector<CVector2D>& points, float maxSegmentLength, bool closed); 166 193 167 194 } // namespace 168 195 -
source/simulation2/system/ParamNode.cpp
diff --git a/source/simulation2/system/ParamNode.cpp b/source/simulation2/system/ParamNode.cpp index 4226a61..7cbf1bd 100644
a b const std::string CParamNode::ToUTF8() const 205 205 return utf8_from_wstring(m_Value); 206 206 } 207 207 208 const CStrIntern CParamNode::ToUTF8Intern() const 209 { 210 return CStrIntern(utf8_from_wstring(m_Value)); 211 } 212 208 213 int CParamNode::ToInt() const 209 214 { 210 215 int ret = 0; … … fixed CParamNode::ToFixed() const 219 224 return fixed::FromString(CStrW(m_Value)); 220 225 } 221 226 227 float CParamNode::ToFloat() const 228 { 229 float ret = 0; 230 std::wstringstream strm; 231 strm << m_Value; 232 strm >> ret; 233 return ret; 234 } 235 222 236 bool CParamNode::ToBool() const 223 237 { 224 238 if (m_Value == L"true") -
source/simulation2/system/ParamNode.h
diff --git a/source/simulation2/system/ParamNode.h b/source/simulation2/system/ParamNode.h index 16e9b40..7caffbd 100644
a b 20 20 21 21 #include "lib/file/vfs/vfs_path.h" 22 22 #include "maths/Fixed.h" 23 #include "ps/CStrIntern.h" 23 24 #include "ps/Errors.h" 24 25 #include "scriptinterface/ScriptVal.h" 25 26 … … public: 169 170 const std::string ToUTF8() const; 170 171 171 172 /** 173 * Returns the content of this node as an internalized 8-bit string. Should only be used for 174 * predictably small and frequently-used strings. 175 */ 176 const CStrIntern ToUTF8Intern() const; 177 178 /** 172 179 * Parses the content of this node as an integer 173 180 */ 174 181 int ToInt() const; … … public: 179 186 fixed ToFixed() const; 180 187 181 188 /** 189 * Parses the content of this node as a floating-point number 190 */ 191 float ToFloat() const; 192 193 /** 182 194 * Parses the content of this node as a boolean ("true" == true, anything else == false) 183 195 */ 184 196 bool ToBool() const; -
source/simulation2/tests/test_CmpTemplateManager.h
diff --git a/source/simulation2/tests/test_CmpTemplateManager.h b/source/simulation2/tests/test_CmpTemplateManager.h index d087929..0c3a0e5 100644
a b public: 78 78 const CParamNode* actor = tempMan->LoadTemplate(ent2, "actor|example1", -1); 79 79 TS_ASSERT(actor != NULL); 80 80 TS_ASSERT_WSTR_EQUALS(actor->ToXML(), 81 L"<Selectable><EditorOnly></EditorOnly></Selectable><VisualActor><Actor>example1</Actor><SilhouetteDisplay>false</SilhouetteDisplay><SilhouetteOccluder>false</SilhouetteOccluder></VisualActor>"); 81 L"<Selectable><EditorOnly></EditorOnly><Overlay><Texture><MainTexture>actor.png</MainTexture><MainTextureMask>actor_mask.png</MainTextureMask></Texture></Overlay></Selectable>" 82 L"<VisualActor><Actor>example1</Actor><SilhouetteDisplay>false</SilhouetteDisplay><SilhouetteOccluder>false</SilhouetteOccluder></VisualActor>"); 82 83 83 84 const CParamNode* preview = tempMan->LoadTemplate(ent2, "preview|unit", -1); 84 85 TS_ASSERT(preview != NULL); -
new file source/tools/selectiontexgen/selectiontexgen.py
diff --git a/source/tools/selectiontexgen/selectiontexgen.py b/source/tools/selectiontexgen/selectiontexgen.py new file mode 100644 index 0000000..cfd6611
- + 1 """ 2 Generates basic square and circle selection overlay textures by parsing all the entity XML files and reading 3 their Footprint components. 4 5 For usage, invoke this script with --help. 6 """ 7 8 # This script uses PyCairo for plotting, since PIL (Python Imaging Library) is absolutely horrible. On Linux, 9 # this should be merely a matter of installing a package (e.g. 'python-cairo' for Debian/Ubuntu), but on Windows 10 # it's kind of tricky and requires some Google-fu. Fortunately, I have saved the working instructions below: 11 # 12 # Grab a Win32 binary from http://ftp.gnome.org/pub/GNOME/binaries/win32/pycairo/1.8/ and install PyCairo using 13 # the installer. The installer extracts the necessary files into Lib\site-packages\cairo within the folder where 14 # Python is installed. There are some extra DLLs which are required to make Cairo work, so we have to get these 15 # as well. 16 # 17 # Head to http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ and get the binary versions of Cairo 18 # (cairo_1.8.10-3_win32.zip at the time of writing), Fontconfig (fontconfig_2.8.0-2_win32.zip), Freetype 19 # (freetype_2.4.4-1_win32.zip), Expat (expat_2.0.1-1_win32.zip), libpng (libpng_1.4.3-1_win32.zip) and zlib 20 # (zlib_1.2.5-2_win32.zip). Version numbers may vary, so be adaptive! Each ZIP file will contain a bin subfolder 21 # with a DLL file in it. Put the following DLLs in Lib\site-packages\cairo within your Python installation: 22 # 23 # freetype6.dll (from freetype_2.4.4-1_win32.zip) 24 # libcairo-2.dll (from cairo_1.8.10-3_win32.zip) 25 # libexpat-1.dll (from expat_2.0.1-1_win32.zip) 26 # libfontconfig-1.dll (from fontconfig_2.8.0-2_win32.zip) 27 # libpng14-14.dll (from libpng_1.4.3-1_win32.zip) 28 # zlib1.dll (from zlib_1.2.5-2_win32.zip). 29 # 30 # Should be all set now. 31 32 import optparse 33 import sys, os 34 import math 35 import operator 36 import cairo # Requires PyCairo (see notes above) 37 from os.path import * 38 from xml.dom import minidom 39 40 def geqPow2(x): 41 """Returns the smallest power of two that's equal to or greater than x""" 42 return int(2**math.ceil(math.log(x, 2))) 43 44 def generateSelectionTexture(shape, textureW, textureH, outerStrokeW, innerStrokeW, outputDir): 45 46 outputBasename = "%dx%d" % (textureW, textureH) 47 48 # size of the image canvas containing the texture (may be larger to ensure power-of-two dimensions) 49 canvasW = geqPow2(textureW) 50 canvasH = geqPow2(textureH) 51 52 # draw texture 53 texture = cairo.ImageSurface(cairo.FORMAT_ARGB32, canvasW, canvasH) 54 textureMask = cairo.ImageSurface(cairo.FORMAT_RGB24, canvasW, canvasH) 55 56 ctxTexture = cairo.Context(texture) 57 ctxTextureMask = cairo.Context(textureMask) 58 59 # fill entire image with transparent pixels 60 ctxTexture.set_source_rgba(1.0, 1.0, 1.0, 0.0) # transparent 61 ctxTexture.rectangle(0, 0, textureW, textureH) 62 ctxTexture.fill() # fill current path 63 64 ctxTextureMask.set_source_rgb(0.0, 0.0, 0.0) # black 65 ctxTextureMask.rectangle(0, 0, canvasW, canvasH) # (!) 66 ctxTextureMask.fill() 67 68 pasteX = (canvasW - textureW)//2 # integer division, floored result 69 pasteY = (canvasH - textureH)//2 # integer division, floored result 70 ctxTexture.translate(pasteX, pasteY) # translate all drawing so that the result is centered 71 ctxTextureMask.translate(pasteX, pasteY) 72 73 # outer stroke width should always be >= inner stroke width, but let's play it safe 74 maxStrokeW = max(outerStrokeW, innerStrokeW) 75 76 if shape == "square": 77 78 rectW = textureW 79 rectH = textureH 80 81 # draw texture (4px white outline, then overlay a 2px black outline) 82 ctxTexture.rectangle(maxStrokeW/2, maxStrokeW/2, rectW - maxStrokeW, rectH - maxStrokeW) 83 ctxTexture.set_line_width(outerStrokeW) 84 ctxTexture.set_source_rgba(1.0, 1.0, 1.0, 1.0) # white 85 ctxTexture.stroke_preserve() # stroke and maintain path 86 ctxTexture.set_line_width(innerStrokeW) 87 ctxTexture.set_source_rgba(0.0, 0.0, 0.0, 1.0) # black 88 ctxTexture.stroke() # stroke and clear path 89 90 # draw mask (2px white) 91 ctxTextureMask.rectangle(maxStrokeW/2, maxStrokeW/2, rectW - maxStrokeW, rectH - maxStrokeW) 92 ctxTextureMask.set_line_width(innerStrokeW) 93 ctxTextureMask.set_source_rgb(1.0, 1.0, 1.0) 94 ctxTextureMask.stroke() 95 96 elif shape == "circle": 97 98 centerX = textureW//2 99 centerY = textureH//2 100 radius = textureW//2 - maxStrokeW/2 # allow for the strokes to fit 101 102 # draw texture 103 ctxTexture.arc(centerX, centerY, radius, 0, 2*math.pi) 104 ctxTexture.set_line_width(outerStrokeW) 105 ctxTexture.set_source_rgba(1.0, 1.0, 1.0, 1.0) # white 106 ctxTexture.stroke_preserve() # stroke and maintain path 107 ctxTexture.set_line_width(innerStrokeW) 108 ctxTexture.set_source_rgba(0.0, 0.0, 0.0, 1.0) # black 109 ctxTexture.stroke() 110 111 # draw mask 112 ctxTextureMask.arc(centerX, centerY, radius, 0, 2*math.pi) 113 ctxTextureMask.set_line_width(innerStrokeW) 114 ctxTextureMask.set_source_rgb(1.0, 1.0, 1.0) 115 ctxTextureMask.stroke() 116 117 finalOutputDir = outputDir + "/" + shape 118 if not isdir(finalOutputDir): 119 os.makedirs(finalOutputDir) 120 121 print "Generating " + os.path.normcase(finalOutputDir + "/" + outputBasename + ".png") 122 123 texture.write_to_png(finalOutputDir + "/" + outputBasename + ".png") 124 textureMask.write_to_png(finalOutputDir + "/" + outputBasename + "_mask.png") 125 126 127 def generateSelectionTextures(xmlTemplateDir, outputDir, outerStrokeScale, innerStrokeScale, snapSizes = False): 128 129 # recursively list XML files 130 xmlFiles = [] 131 132 for dir, subdirs, basenames in os.walk(xmlTemplateDir): 133 for basename in basenames: 134 filename = join(dir, basename) 135 if filename[-4:] == ".xml": 136 xmlFiles.append(filename) 137 138 textureTypesRaw = set() # set of (type, w, h) tuples (so we can eliminate duplicates) 139 140 # parse the XML files, and look for <Footprint> nodes that are a child of <Entity> and 141 # that do not have the disable attribute defined 142 for xmlFile in xmlFiles: 143 xmlDoc = minidom.parse(xmlFile) 144 rootNode = xmlDoc.childNodes[0] 145 146 # we're only interested in entity templates 147 if not rootNode.nodeName == "Entity": 148 continue 149 150 # check if this entity has a footprint definition 151 rootChildNodes = [n for n in rootNode.childNodes if n.localName is not None] # remove whitespace text nodes 152 footprintNodes = filter(lambda x: x.localName == "Footprint", rootChildNodes) 153 if not len(footprintNodes) == 1: 154 continue 155 156 footprintNode = footprintNodes[0] 157 if footprintNode.hasAttribute("disable"): 158 continue 159 160 # parse the footprint declaration 161 # Footprints can either have either one of these children: 162 # <Circle radius="xx.x" /> 163 # <Square width="xx.x" depth="xx.x"/> 164 # There's also a <Height> node, but we don't care about it here. 165 166 squareNodes = footprintNode.getElementsByTagName("Square") 167 circleNodes = footprintNode.getElementsByTagName("Circle") 168 169 numSquareNodes = len(squareNodes) 170 numCircleNodes = len(circleNodes) 171 172 if not (numSquareNodes + numCircleNodes == 1): 173 print "Invalid Footprint definition: insufficient or too many Square and/or Circle definitions in %s" % xmlFile 174 175 texShape = None 176 texW = None # in world-space units 177 texH = None # in world-space units 178 179 if numSquareNodes == 1: 180 texShape = "square" 181 texW = float(squareNodes[0].getAttribute("width")) 182 texH = float(squareNodes[0].getAttribute("depth")) 183 184 elif numCircleNodes == 1: 185 texShape = "circle" 186 texW = float(circleNodes[0].getAttribute("radius")) 187 texH = texW 188 189 textureTypesRaw.add((texShape, texW, texH)) 190 191 # endfor xmlFiles 192 193 print "Found: %d footprints (%d square, %d circle)" % ( 194 len(textureTypesRaw), 195 len([x for x in textureTypesRaw if x[0] == "square"]), 196 len([x for x in textureTypesRaw if x[0] == "circle"]) 197 ) 198 199 textureTypes = set() 200 201 for type, w, h in textureTypesRaw: 202 if snapSizes: 203 # "snap" texture sizes to close-enough neighbours that will still look good enough so we can get away with fewer 204 # actual textures than there are unique footprint outlines 205 w = 1*math.ceil(w/1) # round up to the nearest world-space unit 206 h = 1*math.ceil(h/1) # round up to the nearest world-space unit 207 208 textureTypes.add((type, w, h)) 209 210 if snapSizes: 211 print "Reduced: %d footprints (%d square, %d circle)" % ( 212 len(textureTypes), 213 len([x for x in textureTypes if x[0] == "square"]), 214 len([x for x in textureTypes if x[0] == "circle"]) 215 ) 216 217 # create list from texture types set (so we can sort and have prettier output) 218 textureTypes = sorted(list(textureTypes), key=operator.itemgetter(0,1,2)) # sort by the first tuple element, then by the second, then the third 219 220 # ------------------------------------------------------------------------------------ 221 # compute the size of the actual texture we want to generate (in px) 222 223 scale = 8 # world-space-units-to-pixels scale 224 for type, w, h in textureTypes: 225 226 # if we have a circle, update the w and h so that they're the full width and height of the texture 227 # and not just the radius 228 if type == "circle": 229 assert w == h 230 w *= 2 231 h *= 2 232 233 w = int(math.ceil(w*scale)) 234 h = int(math.ceil(h*scale)) 235 236 # apply a minimum size for really small textures 237 w = max(24, w) 238 h = max(24, h) 239 240 generateSelectionTexture(type, w, h, w/outerStrokeScale, innerStrokeScale * (w/outerStrokeScale), outputDir) 241 242 243 if __name__ == "__main__": 244 245 parser = optparse.OptionParser(usage="Usage: %prog [filenames]") 246 247 parser.add_option("--template-dir", type="str", default=None, help="Path to simulation template XML definition folder. Will be searched recursively for templates containing Footprint definitions. If not specified and this script is run from its directory, it will be automatically determined.") 248 parser.add_option("--output-dir", type="str", default=".", help="Output directory. Will be created if it does not already exist. Defaults to the current directory.") 249 parser.add_option("--oss", "--outer-stroke-scale", type="float", default=12.0, dest="outer_stroke_scale", metavar="SCALE", help="Width of the outer (white) stroke, as a divisor of each generated texture's width. Defaults to 12. Larger values produce thinner overall outlines.") 250 parser.add_option("--iss", "--inner-stroke-scale", type="float", default=0.5, dest="inner_stroke_scale", metavar="PERCENTAGE", help="Width of the inner (black) stroke, as a percentage of the outer stroke's calculated width. Must be between 0 and 1. Higher values produce thinner black/player color strokes inside the surrounding outer white stroke. Defaults to 0.5.") 251 252 (options, args) = parser.parse_args() 253 254 templateDir = options.template_dir 255 if templateDir is None: 256 257 scriptDir = dirname(abspath(__file__)) 258 259 # 'autodetect' location if run from its own dir 260 if normcase(scriptDir).replace('\\', '/').endswith("source/tools/selectiontexgen"): 261 templateDir = "../../../binaries/data/mods/public/simulation/templates" 262 else: 263 print "No template dir specified; use the --template-dir command line argument." 264 sys.exit() 265 266 # check if the template dir exists 267 templateDir = abspath(templateDir) 268 if not isdir(templateDir): 269 print "No such template directory: %s" % templateDir 270 sys.exit() 271 272 # check if the output dir exists, create it if needed 273 outputDir = abspath(options.output_dir) 274 print outputDir 275 if not isdir(outputDir): 276 print "Creating output directory: %s" % outputDir 277 os.makedirs(outputDir) 278 279 print "Template directory:\t%s" % templateDir 280 print "Output directory: \t%s" % outputDir 281 print "------------------------------------------------" 282 283 generateSelectionTextures( 284 templateDir, 285 outputDir, 286 max(0.0, options.outer_stroke_scale), 287 min(1.0, max(0.0, options.inner_stroke_scale)), 288 ) 289 No newline at end of file