- Timestamp:
- 07/30/11 02:56:45 (13 years ago)
- Location:
- ps/trunk
- Files:
-
- 9 added
- 28 edited
-
binaries/data/mods/_test.sim/simulation/data/territorymanager.xml (added)
-
binaries/data/mods/public/art/textures/misc (added)
-
binaries/data/mods/public/art/textures/misc/territory_border.png (added)
-
binaries/data/mods/public/art/textures/misc/territory_border_mask.png (added)
-
binaries/data/mods/public/art/textures/misc/textures.xml (added)
-
binaries/data/mods/public/shaders/overlayline.fp (added)
-
binaries/data/mods/public/shaders/overlayline.vp (added)
-
binaries/data/mods/public/shaders/overlayline.xml (added)
-
binaries/data/mods/public/shaders/terrain_base.xml (modified) (2 diffs)
-
binaries/data/mods/public/shaders/terrain_blend.xml (modified) (2 diffs)
-
binaries/data/mods/public/shaders/terrain_common.fp (modified) (1 diff)
-
binaries/data/mods/public/shaders/terrain_common.vp (modified) (2 diffs)
-
binaries/data/mods/public/shaders/terrain_decal.xml (modified) (2 diffs)
-
binaries/data/mods/public/simulation/data/pathfinder.xml (modified) (1 diff)
-
binaries/data/mods/public/simulation/data/territorymanager.xml (added)
-
source/graphics/Overlay.h (modified) (3 diffs)
-
source/graphics/Terrain.cpp (modified) (3 diffs)
-
source/graphics/Terrain.h (modified) (1 diff)
-
source/graphics/TextureManager.cpp (modified) (3 diffs)
-
source/graphics/TextureManager.h (modified) (3 diffs)
-
source/lib/res/graphics/ogl_tex.cpp (modified) (5 diffs)
-
source/lib/res/graphics/ogl_tex.h (modified) (1 diff)
-
source/maths/Noise.cpp (modified) (2 diffs)
-
source/maths/Noise.h (modified) (1 diff)
-
source/maths/Vector2D.h (modified) (2 diffs)
-
source/renderer/OverlayRenderer.cpp (modified) (6 diffs)
-
source/renderer/OverlayRenderer.h (modified) (3 diffs)
-
source/renderer/Renderer.cpp (modified) (7 diffs)
-
source/renderer/Renderer.h (modified) (2 diffs)
-
source/renderer/Scene.h (modified) (2 diffs)
-
source/renderer/VertexBuffer.cpp (modified) (6 diffs)
-
source/renderer/VertexBuffer.h (modified) (2 diffs)
-
source/renderer/VertexBufferManager.cpp (modified) (3 diffs)
-
source/renderer/VertexBufferManager.h (modified) (1 diff)
-
source/simulation2/components/CCmpTerritoryManager.cpp (modified) (12 diffs)
-
source/simulation2/helpers/Render.cpp (modified) (7 diffs)
-
source/simulation2/helpers/Render.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
ps/trunk/binaries/data/mods/public/shaders/terrain_base.xml
r9889 r9929 6 6 <uniform name="losTransform" loc="1" type="vec2"/> 7 7 <uniform name="shadowTransform" loc="2" type="mat4"/> 8 <uniform name="territoryTransform" loc="6" type="vec2"/>9 8 </vertex> 10 9 … … 13 12 <uniform name="shadowTex" loc="2" type="sampler2DShadow"/> 14 13 <uniform name="losTex" loc="3" type="sampler2D"/> 15 <uniform name="territoryTex" loc="4" type="sampler2D"/>16 14 17 15 <uniform name="ambient" loc="0" type="vec3"/> -
ps/trunk/binaries/data/mods/public/shaders/terrain_blend.xml
r9889 r9929 8 8 <uniform name="losTransform" loc="1" type="vec2"/> 9 9 <uniform name="shadowTransform" loc="2" type="mat4"/> 10 <uniform name="territoryTransform" loc="6" type="vec2"/>11 10 </vertex> 12 11 … … 16 15 <uniform name="shadowTex" loc="2" type="sampler2DShadow"/> 17 16 <uniform name="losTex" loc="3" type="sampler2D"/> 18 <uniform name="territoryTex" loc="4" type="sampler2D"/>19 17 20 18 <uniform name="ambient" loc="0" type="vec3"/> -
ps/trunk/binaries/data/mods/public/shaders/terrain_common.fp
r9889 r9929 82 82 #endif 83 83 84 // Blend with the territory boundary texture85 TEX tex, fragment.texcoord[4], texture[4], 2D;86 LRP color.rgb, tex.a, tex, color;87 88 84 // Multiply everything by the LOS texture 89 85 TEX tex.a, fragment.texcoord[3], texture[3], 2D; -
ps/trunk/binaries/data/mods/public/shaders/terrain_common.vp
r9889 r9929 3 3 PARAM losTransform = program.local[1]; 4 4 PARAM shadowTransform[4] = { program.local[2..5] }; 5 PARAM territoryTransform = program.local[6];6 5 7 6 TEMP lighting; … … 40 39 41 40 MAD result.texcoord[3], position.xzzz, losTransform.x, losTransform.y; 42 MAD result.texcoord[4], position.xzzz, territoryTransform.x, territoryTransform.y;43 41 44 42 END -
ps/trunk/binaries/data/mods/public/shaders/terrain_decal.xml
r9889 r9929 8 8 <uniform name="losTransform" loc="1" type="vec2"/> 9 9 <uniform name="shadowTransform" loc="2" type="mat4"/> 10 <uniform name="territoryTransform" loc="6" type="vec2"/>11 10 </vertex> 12 11 … … 15 14 <uniform name="shadowTex" loc="2" type="sampler2DShadow"/> 16 15 <uniform name="losTex" loc="3" type="sampler2D"/> 17 <uniform name="territoryTex" loc="4" type="sampler2D"/>18 16 19 17 <uniform name="ambient" loc="0" type="vec3"/> -
ps/trunk/binaries/data/mods/public/simulation/data/pathfinder.xml
r9666 r9929 8 8 9 9 <!-- Unit pathfinding classes: --> 10 <unrestricted/> 10 11 <default> 11 12 <MaxWaterDepth>2</MaxWaterDepth> -
ps/trunk/source/graphics/Overlay.h
r8241 r9929 1 /* Copyright (C) 201 0Wildfire Games.1 /* Copyright (C) 2011 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * … … 19 19 #define INCLUDED_GRAPHICS_OVERLAY 20 20 21 #include "graphics/RenderableObject.h" 21 22 #include "graphics/Texture.h" 22 23 #include "maths/Vector3D.h" 23 24 #include "ps/Overlay.h" // CColor (TODO: that file has nothing to do with overlays, it should be renamed) 25 26 class CTerrain; 24 27 25 28 /** … … 34 37 std::vector<float> m_Coords; // (x, y, z) vertex coordinate triples; shape is not automatically closed 35 38 u8 m_Thickness; // pixels 39 }; 40 41 /** 42 * Textured line overlay, with world-space coordinates, rendered in the world 43 * onto the terrain. Designed for territory borders. 44 */ 45 struct SOverlayTexturedLine 46 { 47 SOverlayTexturedLine() : m_Terrain(NULL), m_Thickness(1.0f) { } 48 49 CTerrain* m_Terrain; 50 CTexturePtr m_TextureBase; 51 CTexturePtr m_TextureMask; 52 CColor m_Color; 53 std::vector<float> m_Coords; // (x, z) vertex coordinate pairs; y is computed automatically; shape is automatically closed 54 float m_Thickness; // world-space units 55 56 shared_ptr<CRenderData> m_RenderData; // cached renderer data (shared_ptr so that copies/deletes are automatic) 36 57 }; 37 58 -
ps/trunk/source/graphics/Terrain.cpp
r9055 r9929 224 224 } 225 225 226 CVector3D CTerrain::CalcExactNormal(float x, float z) const 227 { 228 // Clamp to size-2 so we can use the tiles (xi,zi)-(xi+1,zi+1) 229 const ssize_t xi = clamp((ssize_t)floor(x/CELL_SIZE), (ssize_t)0, m_MapSize-2); 230 const ssize_t zi = clamp((ssize_t)floor(z/CELL_SIZE), (ssize_t)0, m_MapSize-2); 231 232 const float xf = clamp(x/CELL_SIZE-xi, 0.0f, 1.0f); 233 const float zf = clamp(z/CELL_SIZE-zi, 0.0f, 1.0f); 234 235 float h00 = m_Heightmap[zi*m_MapSize + xi]; 236 float h01 = m_Heightmap[(zi+1)*m_MapSize + xi]; 237 float h10 = m_Heightmap[zi*m_MapSize + (xi+1)]; 238 float h11 = m_Heightmap[(zi+1)*m_MapSize + (xi+1)]; 239 240 // Determine which terrain triangle this point is on, 241 // then compute the normal of that triangle's plane 242 243 if (GetTriangulationDir(xi, zi)) 244 { 245 if (xf + zf <= 1.f) 246 { 247 // Lower-left triangle (don't use h11) 248 return -CVector3D(CELL_SIZE, (h10-h00)*HEIGHT_SCALE, 0).Cross(CVector3D(0, (h01-h00)*HEIGHT_SCALE, CELL_SIZE)).Normalized(); 249 } 250 else 251 { 252 // Upper-right triangle (don't use h00) 253 return -CVector3D(CELL_SIZE, (h11-h01)*HEIGHT_SCALE, 0).Cross(CVector3D(0, (h11-h10)*HEIGHT_SCALE, CELL_SIZE)).Normalized(); 254 } 255 } 256 else 257 { 258 if (xf <= zf) 259 { 260 // Upper-left triangle (don't use h10) 261 return -CVector3D(CELL_SIZE, (h11-h01)*HEIGHT_SCALE, 0).Cross(CVector3D(0, (h01-h00)*HEIGHT_SCALE, CELL_SIZE)).Normalized(); 262 } 263 else 264 { 265 // Lower-right triangle (don't use h01) 266 return -CVector3D(CELL_SIZE, (h10-h00)*HEIGHT_SCALE, 0).Cross(CVector3D(0, (h11-h10)*HEIGHT_SCALE, CELL_SIZE)).Normalized(); 267 } 268 } 269 } 270 226 271 /////////////////////////////////////////////////////////////////////////////// 227 272 // GetPatch: return the patch at (i,j) in patch space, or null if the patch is … … 299 344 float h10 = m_Heightmap[zi*m_MapSize + (xi+1)]; 300 345 float h11 = m_Heightmap[(zi+1)*m_MapSize + (xi+1)]; 301 // Linearly interpolate 302 return (HEIGHT_SCALE * ( 303 (1 - zf) * ((1 - xf) * h00 + xf * h10) 304 + zf * ((1 - xf) * h01 + xf * h11))); 346 347 // Determine which terrain triangle this point is on, 348 // then compute the linearly-interpolated height on that triangle's plane 349 350 if (GetTriangulationDir(xi, zi)) 351 { 352 if (xf + zf <= 1.f) 353 { 354 // Lower-left triangle (don't use h11) 355 return HEIGHT_SCALE * (h00 + (h10-h00)*xf + (h01-h00)*zf); 356 } 357 else 358 { 359 // Upper-right triangle (don't use h00) 360 return HEIGHT_SCALE * (h11 + (h01-h11)*(1-xf) + (h10-h11)*(1-zf)); 361 } 362 } 363 else 364 { 365 if (xf <= zf) 366 { 367 // Upper-left triangle (don't use h10) 368 return HEIGHT_SCALE * (h00 + (h11-h01)*xf + (h01-h00)*zf); 369 } 370 else 371 { 372 // Lower-right triangle (don't use h01) 373 return HEIGHT_SCALE * (h00 + (h10-h00)*xf + (h11-h10)*zf); 374 } 375 } 305 376 } 306 377 … … 329 400 return ((one - zf).Multiply(xf1 * h00 + xf0 * h10) 330 401 + zf.Multiply(xf1 * h01 + xf0 * h11)) / (int)(HEIGHT_UNITS_PER_METRE / 2); 402 403 // TODO: This should probably be more like GetExactGroundLevel() 404 // in handling triangulation properly 331 405 } 332 406 -
ps/trunk/source/graphics/Terrain.h
r9055 r9929 127 127 void CalcNormalFixed(ssize_t i, ssize_t j, CFixedVector3D& normal) const; 128 128 129 CVector3D CalcExactNormal(float x, float z) const; 130 129 131 // flatten out an area of terrain (specified in world space coords); return 130 132 // the average height of the flattened area -
ps/trunk/source/graphics/TextureManager.cpp
r9410 r9929 45 45 boost::hash_combine(seed, a.m_Path); 46 46 boost::hash_combine(seed, a.m_Filter); 47 boost::hash_combine(seed, a.m_Wrap); 47 boost::hash_combine(seed, a.m_WrapS); 48 boost::hash_combine(seed, a.m_WrapT); 48 49 boost::hash_combine(seed, a.m_Aniso); 49 50 return seed; … … 62 63 { 63 64 return a.m_Path == b.m_Path && a.m_Filter == b.m_Filter 64 && a.m_Wrap == b.m_Wrap && a.m_Aniso == b.m_Aniso; 65 && a.m_WrapS == b.m_WrapS && a.m_WrapT == b.m_WrapT 66 && a.m_Aniso == b.m_Aniso; 65 67 } 66 68 bool operator()(CTexturePtr const& a, CTexturePtr const& b) const … … 187 189 188 190 // Set GL upload properties 189 (void)ogl_tex_set_wrap(h, texture->m_Properties.m_Wrap );191 (void)ogl_tex_set_wrap(h, texture->m_Properties.m_WrapS, texture->m_Properties.m_WrapT); 190 192 (void)ogl_tex_set_anisotropy(h, texture->m_Properties.m_Aniso); 191 193 -
ps/trunk/source/graphics/TextureManager.h
r9123 r9929 130 130 */ 131 131 explicit CTextureProperties(const VfsPath& path) : 132 m_Path(path), m_Filter(GL_LINEAR_MIPMAP_LINEAR), m_Wrap(GL_REPEAT), m_Aniso(1.0f) 132 m_Path(path), m_Filter(GL_LINEAR_MIPMAP_LINEAR), 133 m_WrapS(GL_REPEAT), m_WrapT(GL_REPEAT), m_Aniso(1.0f) 133 134 { 134 135 } … … 142 143 * Set wrapping mode (typically GL_REPEAT, GL_CLAMP_TO_EDGE, etc). 143 144 */ 144 void SetWrap(GLint wrap) { m_Wrap = wrap; } 145 void SetWrap(GLint wrap) { m_WrapS = wrap; m_WrapT = wrap; } 146 147 /** 148 * Set wrapping mode (typically GL_REPEAT, GL_CLAMP_TO_EDGE, etc), 149 * separately for S and T. 150 */ 151 void SetWrap(GLint wrap_s, GLint wrap_t) { m_WrapS = wrap_s; m_WrapT = wrap_t; } 145 152 146 153 /** … … 169 176 VfsPath m_Path; 170 177 GLint m_Filter; 171 GLint m_Wrap; 178 GLint m_WrapS; 179 GLint m_WrapT; 172 180 float m_Aniso; 173 181 }; -
ps/trunk/source/lib/res/graphics/ogl_tex.cpp
r9546 r9929 276 276 GLint filter; 277 277 // .. wrap mode 278 // note: to simplify things, we assume that apps will never want to 279 // set S/T modes independently. it that becomes necessary, 280 // it's easy to add. 281 GLint wrap; 278 GLint wrap_s; 279 GLint wrap_t; 282 280 // .. anisotropy 283 281 // note: ignored unless EXT_texture_filter_anisotropic is supported. … … 290 288 { 291 289 ots->filter = default_filter; 292 ots->wrap = GL_REPEAT; 290 ots->wrap_s = GL_REPEAT; 291 ots->wrap_t = GL_REPEAT; 293 292 ots->anisotropy = 1.0f; 294 293 } … … 306 305 307 306 // wrap 308 const GLint wrap = ots->wrap; 309 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); 310 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); 307 const GLint wrap_s = ots->wrap_s; 308 const GLint wrap_t = ots->wrap_t; 309 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s); 310 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t); 311 311 // .. only CLAMP and REPEAT are guaranteed to be available. 312 312 // if we're using one of the others, we squelch the error that 313 313 // may have resulted if this GL implementation is old. 314 if( wrap != GL_CLAMP && wrap != GL_REPEAT)314 if((wrap_s != GL_CLAMP && wrap_s != GL_REPEAT) || (wrap_t != GL_CLAMP && wrap_t != GL_REPEAT)) 315 315 ogl_SquelchError(GL_INVALID_ENUM); 316 316 … … 482 482 if(!filter_valid(ot->state.filter)) 483 483 WARN_RETURN(ERR::_14); 484 if(!wrap_valid(ot->state.wrap ))484 if(!wrap_valid(ot->state.wrap_s)) 485 485 WARN_RETURN(ERR::_15); 486 if(!wrap_valid(ot->state.wrap_t)) 487 WARN_RETURN(ERR::_16); 486 488 487 489 // misc 488 490 if(!q_flags_valid(ot->q_flags)) 489 WARN_RETURN(ERR::_1 6);491 WARN_RETURN(ERR::_17); 490 492 if(ot->tmu >= 128) // unexpected that there will ever be this many 491 WARN_RETURN(ERR::_1 7);493 WARN_RETURN(ERR::_18); 492 494 if(ot->flags > OT_ALL_FLAGS) 493 WARN_RETURN(ERR::_1 8);495 WARN_RETURN(ERR::_19); 494 496 // .. note: don't check ot->fmt and ot->int_fmt - they aren't set 495 497 // until during ogl_tex_upload. … … 621 623 // override default wrap mode (GL_REPEAT) for this texture. 622 624 // must be called before uploading (raises a warning if called afterwards). 623 // wrap is as defined by OpenGL and applies to both S and T coordinates 624 // (rationale: see OglTexState). 625 Status ogl_tex_set_wrap(Handle ht, GLint wrap) 625 // wrap is as defined by OpenGL. 626 Status ogl_tex_set_wrap(Handle ht, GLint wrap_s, GLint wrap_t) 626 627 { 627 628 H_DEREF(ht, OglTex, ot); 628 629 629 if(!wrap_valid(wrap ))630 if(!wrap_valid(wrap_s)) 630 631 WARN_RETURN(ERR::INVALID_PARAM); 631 632 632 if(ot->state.wrap != wrap) 633 if(!wrap_valid(wrap_t)) 634 WARN_RETURN(ERR::INVALID_PARAM); 635 636 if(ot->state.wrap_s != wrap_s || ot->state.wrap_t != wrap_t) 633 637 { 634 638 warn_if_uploaded(ht, ot); 635 ot->state.wrap = wrap; 639 ot->state.wrap_s = wrap_s; 640 ot->state.wrap_t = wrap_t; 636 641 } 637 642 return INFO::OK; -
ps/trunk/source/lib/res/graphics/ogl_tex.h
r9410 r9929 290 290 * 291 291 * @param ht Texture handle 292 * @param wrap OpenGL wrap mode (for both S and T coordinates)293 * (rationale: see {@link OglTexState})292 * @param wrap_s OpenGL wrap mode for S coordinates 293 * @param wrap_t OpenGL wrap mode for T coordinates 294 294 * @return Status 295 295 * 296 296 * Must be called before uploading (raises a warning if called afterwards). 297 297 */ 298 extern Status ogl_tex_set_wrap(Handle ht, GLint wrap );298 extern Status ogl_tex_set_wrap(Handle ht, GLint wrap_s, GLint wrap_t); 299 299 300 300 /** -
ps/trunk/source/maths/Noise.cpp
r9905 r9929 49 49 { 50 50 freq = f; 51 grads = new CVector2D _Maths*[freq];51 grads = new CVector2D*[freq]; 52 52 for(int i=0; i<freq; i++) 53 53 { 54 grads[i] = new CVector2D _Maths[freq];54 grads[i] = new CVector2D[freq]; 55 55 for(int j=0; j<freq; j++) 56 56 { 57 57 float a = randFloat() * 2 * (float)M_PI; 58 grads[i][j] = CVector2D _Maths(cos(a), sin(a));58 grads[i][j] = CVector2D(cos(a), sin(a)); 59 59 } 60 60 } … … 87 87 int iy1 = (iy+1) % freq; 88 88 89 float s = grads[ix][iy].Dot(CVector2D _Maths(fx, fy));90 float t = grads[ix1][iy].Dot(CVector2D _Maths(fx-1, fy));91 float u = grads[ix][iy1].Dot(CVector2D _Maths(fx, fy-1));92 float v = grads[ix1][iy1].Dot(CVector2D _Maths(fx-1, fy-1));89 float s = grads[ix][iy].Dot(CVector2D(fx, fy)); 90 float t = grads[ix1][iy].Dot(CVector2D(fx-1, fy)); 91 float u = grads[ix][iy1].Dot(CVector2D(fx, fy-1)); 92 float v = grads[ix1][iy1].Dot(CVector2D(fx-1, fy-1)); 93 93 94 94 float ex = easeCurve(fx); -
ps/trunk/source/maths/Noise.h
r6832 r9929 37 37 38 38 /// freq*freq random gradient vectors in the unit cube 39 CVector2D _Maths** grads;39 CVector2D** grads; 40 40 public: 41 41 Noise2D(int freq); -
ps/trunk/source/maths/Vector2D.h
r7326 r9929 1 /* Copyright (C) 20 09Wildfire Games.1 /* Copyright (C) 2011 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * … … 28 28 29 29 /////////////////////////////////////////////////////////////////////////////// 30 // CVector2D _Maths:31 class CVector2D _Maths30 // CVector2D: 31 class CVector2D 32 32 { 33 33 public: 34 CVector2D_Maths() {} 35 CVector2D_Maths(float x,float y) { X=x; Y=y; } 36 CVector2D_Maths(const CVector2D_Maths& p) { X=p.X; Y=p.Y; } 34 CVector2D() {} 35 CVector2D(float x, float y) : X(x), Y(y) {} 37 36 38 operator float*() { 37 operator float*() 38 { 39 39 return &X; 40 40 } 41 41 42 operator const float*() const { 42 operator const float*() const 43 { 43 44 return &X; 44 45 } 45 46 46 CVector2D_Maths operator-() const { 47 return CVector2D_Maths(-X, -Y); 47 CVector2D operator-() const 48 { 49 return CVector2D(-X, -Y); 48 50 } 49 51 50 CVector2D_Maths operator+(const CVector2D_Maths& t) const { 51 return CVector2D_Maths(X+t.X, Y+t.Y); 52 CVector2D operator+(const CVector2D& t) const 53 { 54 return CVector2D(X + t.X, Y + t.Y); 52 55 } 53 56 54 CVector2D_Maths operator-(const CVector2D_Maths& t) const { 55 return CVector2D_Maths(X-t.X, Y-t.Y); 57 CVector2D operator-(const CVector2D& t) const 58 { 59 return CVector2D(X - t.X, Y - t.Y); 56 60 } 57 61 58 CVector2D_Maths operator*(float f) const { 59 return CVector2D_Maths(X*f, Y*f); 62 CVector2D operator*(float f) const 63 { 64 return CVector2D(X * f, Y * f); 60 65 } 61 66 62 CVector2D_Maths operator/(float f) const { 63 float inv=1.0f/f; 64 return CVector2D_Maths(X*inv, Y*inv); 67 CVector2D operator/(float f) const 68 { 69 float inv = 1.0f / f; 70 return CVector2D(X * inv, Y * inv); 65 71 } 66 72 67 CVector2D_Maths& operator+=(const CVector2D_Maths& t) { 68 X+=t.X; Y+=t.Y; 69 return *this; 73 CVector2D& operator+=(const CVector2D& t) 74 { 75 X += t.X; 76 Y += t.Y; 77 return *this; 70 78 } 71 79 72 CVector2D_Maths& operator-=(const CVector2D_Maths& t) { 73 X-=t.X; Y-=t.Y; 74 return *this; 80 CVector2D& operator-=(const CVector2D& t) 81 { 82 X -= t.X; 83 Y -= t.Y; 84 return *this; 75 85 } 76 86 77 CVector2D_Maths& operator*=(float f) { 78 X*=f; Y*=f; 79 return *this; 87 CVector2D& operator*=(float f) 88 { 89 X *= f; 90 Y *= f; 91 return *this; 80 92 } 81 93 82 CVector2D_Maths& operator/=(float f) { 83 float invf=1.0f/f; 84 X*=invf; Y*=invf; 85 return *this; 94 CVector2D& operator/=(float f) 95 { 96 float invf = 1.0f / f; 97 X *= invf; 98 Y *= invf; 99 return *this; 86 100 } 87 101 88 float Dot(const CVector2D_Maths& a) const { 89 return X*a.X + Y*a.Y; 102 float Dot(const CVector2D& a) const 103 { 104 return X * a.X + Y * a.Y; 90 105 } 91 106 92 float LengthSquared() const { 93 return Dot(*this); 107 float LengthSquared() const 108 { 109 return Dot(*this); 94 110 } 95 111 96 float Length() const { 97 return (float) sqrt(LengthSquared()); 112 float Length() const 113 { 114 return (float)sqrt(LengthSquared()); 98 115 } 99 116 100 void Normalize() { 101 float mag=Length(); 102 X/=mag; Y/=mag; 117 void Normalize() 118 { 119 float mag = Length(); 120 X /= mag; 121 Y /= mag; 122 } 123 124 CVector2D Normalized() 125 { 126 float mag = Length(); 127 return CVector2D(X / mag, Y / mag); 103 128 } 104 129 -
ps/trunk/source/renderer/OverlayRenderer.cpp
r9362 r9929 20 20 #include "OverlayRenderer.h" 21 21 22 #include "graphics/LOSTexture.h" 22 23 #include "graphics/Overlay.h" 24 #include "graphics/ShaderManager.h" 25 #include "graphics/Terrain.h" 23 26 #include "graphics/TextureManager.h" 24 27 #include "lib/ogl.h" 28 #include "ps/Game.h" 29 #include "ps/Profile.h" 25 30 #include "renderer/Renderer.h" 31 #include "renderer/VertexBuffer.h" 32 #include "renderer/VertexBufferManager.h" 33 #include "simulation2/Simulation2.h" 34 #include "simulation2/components/ICmpWaterManager.h" 26 35 27 36 struct OverlayRendererInternals 28 37 { 29 38 std::vector<SOverlayLine*> lines; 39 std::vector<SOverlayTexturedLine*> texlines; 30 40 std::vector<SOverlaySprite*> sprites; 31 41 }; 32 42 43 class CTexturedLineRData : public CRenderData 44 { 45 public: 46 CTexturedLineRData(SOverlayTexturedLine* line) : 47 m_Line(line), m_VB(NULL), m_VBIndices(NULL) 48 { 49 } 50 51 ~CTexturedLineRData() 52 { 53 if (m_VB) 54 g_VBMan.Release(m_VB); 55 if (m_VBIndices) 56 g_VBMan.Release(m_VBIndices); 57 } 58 59 struct SVertex 60 { 61 SVertex(CVector3D pos, short u, short v) : m_Position(pos) { m_UVs[0] = u; m_UVs[1] = v; } 62 CVector3D m_Position; 63 GLshort m_UVs[2]; 64 }; 65 cassert(sizeof(SVertex) == 16); 66 67 void Update(); 68 69 SOverlayTexturedLine* m_Line; 70 71 CVertexBuffer::VBChunk* m_VB; 72 CVertexBuffer::VBChunk* m_VBIndices; 73 }; 74 33 75 OverlayRenderer::OverlayRenderer() 34 76 { … … 41 83 } 42 84 43 void OverlayRenderer::Submit(SOverlayLine* overlay) 44 { 45 m->lines.push_back(overlay); 85 void OverlayRenderer::Submit(SOverlayLine* line) 86 { 87 ENSURE(line->m_Coords.size() % 3 == 0); 88 89 m->lines.push_back(line); 90 } 91 92 void OverlayRenderer::Submit(SOverlayTexturedLine* line) 93 { 94 // Simplify the rest of the code by guaranteeing non-empty lines 95 if (line->m_Coords.empty()) 96 return; 97 98 ENSURE(line->m_Coords.size() % 2 == 0); 99 100 m->texlines.push_back(line); 46 101 } 47 102 … … 54 109 { 55 110 m->lines.clear(); 111 m->texlines.clear(); 56 112 m->sprites.clear(); 57 113 // this should leave the capacity unchanged, which is okay since it … … 61 117 void OverlayRenderer::PrepareForRendering() 62 118 { 119 PROFILE("prepare overlays"); 120 63 121 // This is where we should do something like sort the overlays by 64 122 // colour/sprite/etc for more efficient rendering 65 } 66 67 void OverlayRenderer::RenderOverlays() 68 { 123 124 for (size_t i = 0; i < m->texlines.size(); ++i) 125 { 126 SOverlayTexturedLine* line = m->texlines[i]; 127 if (!line->m_RenderData) 128 { 129 line->m_RenderData = shared_ptr<CRenderData>(new CTexturedLineRData(line)); 130 static_cast<CTexturedLineRData*>(line->m_RenderData.get())->Update(); 131 // We assume the overlay line will get replaced by the caller 132 // if terrain changes, so we don't need to detect that here and 133 // call Update again. Also we assume the caller won't change 134 // any of the parameters after first submitting the line. 135 } 136 } 137 } 138 139 void OverlayRenderer::RenderOverlaysBeforeWater() 140 { 141 PROFILE("render overlays (before water)"); 142 69 143 glDisable(GL_TEXTURE_2D); 70 144 glEnable(GL_BLEND); … … 91 165 } 92 166 167 void OverlayRenderer::RenderOverlaysAfterWater() 168 { 169 PROFILE("render overlays (after water)"); 170 171 // Only supported in shader modes 172 // (TODO: should support in non-shader too) 173 if (g_Renderer.GetRenderPath() != CRenderer::RP_SHADER) 174 return; 175 176 if (!m->texlines.empty()) 177 { 178 glEnable(GL_TEXTURE_2D); 179 glEnable(GL_BLEND); 180 glDepthMask(0); 181 182 glEnableClientState(GL_VERTEX_ARRAY); 183 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 184 185 CShaderManager& shaderManager = g_Renderer.GetShaderManager(); 186 CShaderProgramPtr shaderTexLine(shaderManager.LoadProgram("overlayline", std::map<CStr, CStr>())); 187 188 shaderTexLine->Bind(); 189 190 CLOSTexture& los = g_Renderer.GetScene().GetLOSTexture(); 191 shaderTexLine->BindTexture("losTex", los.GetTexture()); 192 shaderTexLine->Uniform("losTransform", los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f); 193 194 for (size_t i = 0; i < m->texlines.size(); ++i) 195 { 196 SOverlayTexturedLine* line = m->texlines[i]; 197 if (!line->m_RenderData) 198 continue; 199 200 shaderTexLine->BindTexture("baseTex", line->m_TextureBase->GetHandle()); 201 shaderTexLine->BindTexture("maskTex", line->m_TextureMask->GetHandle()); 202 shaderTexLine->Uniform("objectColor", line->m_Color); 203 204 CTexturedLineRData* rdata = static_cast<CTexturedLineRData*>(line->m_RenderData.get()); 205 206 GLsizei stride = sizeof(CTexturedLineRData::SVertex); 207 CTexturedLineRData::SVertex* base = reinterpret_cast<CTexturedLineRData::SVertex*>(rdata->m_VB->m_Owner->Bind()); 208 209 glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]); 210 glTexCoordPointer(2, GL_SHORT, stride, &base->m_UVs[0]); 211 212 u8* indexBase = rdata->m_VBIndices->m_Owner->Bind(); 213 glDrawElements(GL_QUAD_STRIP, rdata->m_VBIndices->m_Count, GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*rdata->m_VBIndices->m_Index); 214 215 g_Renderer.GetStats().m_OverlayTris += rdata->m_VBIndices->m_Count - 2; 216 } 217 218 shaderTexLine->Unbind(); 219 220 // TODO: the shader should probably be responsible for unbinding its textures 221 g_Renderer.BindTexture(1, 0); 222 g_Renderer.BindTexture(0, 0); 223 224 CVertexBuffer::Unbind(); 225 glDisableClientState(GL_VERTEX_ARRAY); 226 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 227 228 glDepthMask(1); 229 glDisable(GL_BLEND); 230 } 231 } 232 93 233 void OverlayRenderer::RenderForegroundOverlays(const CCamera& viewCamera) 94 234 { 235 PROFILE("render overlays (fg)"); 236 95 237 glEnable(GL_TEXTURE_2D); 96 238 glEnable(GL_BLEND); … … 133 275 glDisable(GL_TEXTURE_2D); 134 276 } 277 278 void CTexturedLineRData::Update() 279 { 280 if (m_VB) 281 { 282 g_VBMan.Release(m_VB); 283 m_VB = NULL; 284 } 285 286 if (m_VBIndices) 287 { 288 g_VBMan.Release(m_VBIndices); 289 m_VBIndices = NULL; 290 } 291 292 CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); 293 294 std::vector<SVertex> vertices; 295 std::vector<u16> indices; 296 297 short v = 0; 298 299 size_t n = m_Line->m_Coords.size() / 2; 300 ENSURE(n >= 1); 301 302 CTerrain* terrain = m_Line->m_Terrain; 303 304 // TODO: this assumes paths are closed loops; probably should extend this to 305 // handle non-closed paths too 306 307 // In each iteration, p1 is the position of vertex i, p0 is i-1, p2 is i+1. 308 // To avoid slightly expensive terrain computations we cycle these around and 309 // recompute p2 at the end of each iteration. 310 CVector3D p0 = CVector3D(m_Line->m_Coords[(n-1)*2], 0, m_Line->m_Coords[(n-1)*2+1]); 311 CVector3D p1 = CVector3D(m_Line->m_Coords[0], 0, m_Line->m_Coords[1]); 312 CVector3D p2 = CVector3D(m_Line->m_Coords[(1 % n)*2], 0, m_Line->m_Coords[(1 % n)*2+1]); 313 bool p1floating = false; 314 bool p2floating = false; 315 316 // Compute terrain heights, clamped to the water height (and remember whether 317 // each point was floating on water, for normal computation later) 318 319 // TODO: if we ever support more than one water level per map, recompute this per point 320 float w = cmpWaterManager->GetExactWaterLevel(p0.X, p0.Z); 321 322 p0.Y = terrain->GetExactGroundLevel(p0.X, p0.Z); 323 if (p0.Y < w) 324 p0.Y = w; 325 326 p1.Y = terrain->GetExactGroundLevel(p1.X, p1.Z); 327 if (p1.Y < w) 328 { 329 p1.Y = w; 330 p1floating = true; 331 } 332 333 p2.Y = terrain->GetExactGroundLevel(p2.X, p2.Z); 334 if (p2.Y < w) 335 { 336 p2.Y = w; 337 p2floating = true; 338 } 339 340 for (size_t i = 0; i < n; ++i) 341 { 342 // For vertex i, compute bisector of lines (i-1)..(i) and (i)..(i+1) 343 // perpendicular to terrain normal 344 345 // Normal is vertical if on water, else computed from terrain 346 CVector3D norm; 347 if (p1floating) 348 norm = CVector3D(0, 1, 0); 349 else 350 norm = m_Line->m_Terrain->CalcExactNormal(p1.X, p1.Z); 351 352 CVector3D b = ((p1 - p0).Normalized() + (p2 - p1).Normalized()).Cross(norm); 353 354 // Adjust bisector length to match the line thickness, along the line's width 355 float l = b.Dot((p2 - p1).Normalized().Cross(norm)); 356 if (fabs(l) > 0.000001f) // avoid unlikely divide-by-zero 357 b *= m_Line->m_Thickness / l; 358 359 // Raise off the terrain a little bit 360 const float raised = 0.2f; 361 362 vertices.push_back(SVertex(p1 + b + norm*raised, 0, v)); 363 indices.push_back(vertices.size() - 1); 364 365 vertices.push_back(SVertex(p1 - b + norm*raised, 1, v)); 366 indices.push_back(vertices.size() - 1); 367 368 // Alternate V coordinate for debugging 369 v = 1 - v; 370 371 // Cycle the p's and compute the new p2 372 p0 = p1; 373 p1 = p2; 374 p1floating = p2floating; 375 p2 = CVector3D(m_Line->m_Coords[((i+2) % n)*2], 0, m_Line->m_Coords[((i+2) % n)*2+1]); 376 p2.Y = terrain->GetExactGroundLevel(p2.X, p2.Z); 377 if (p2.Y < w) 378 { 379 p2.Y = w; 380 p2floating = true; 381 } 382 else 383 p2floating = false; 384 } 385 386 // Close the path 387 indices.push_back(0); 388 indices.push_back(1); 389 390 m_VB = g_VBMan.Allocate(sizeof(SVertex), vertices.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER); 391 m_VB->m_Owner->UpdateChunkVertices(m_VB, &vertices[0]); 392 393 // Update the indices to include the base offset of the vertex data 394 for (size_t k = 0; k < indices.size(); ++k) 395 indices[k] += m_VB->m_Index; 396 397 m_VBIndices = g_VBMan.Allocate(sizeof(u16), indices.size(), GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER); 398 m_VBIndices->m_Owner->UpdateChunkVertices(m_VBIndices, &indices[0]); 399 } -
ps/trunk/source/renderer/OverlayRenderer.h
r8241 r9929 20 20 21 21 struct SOverlayLine; 22 struct SOverlayTexturedLine; 22 23 struct SOverlaySprite; 23 24 class CCamera; … … 41 42 42 43 /** 44 * Add a textured line overlay for rendering in this frame. 45 */ 46 void Submit(SOverlayTexturedLine* overlay); 47 48 /** 43 49 * Add a sprite overlay for rendering in this frame. 44 50 */ … … 59 65 /** 60 66 * Render all the submitted overlays that are embedded in the world 61 * (i.e. rendered behind other objects, underwater, etc). 67 * (i.e. rendered behind other objects in the normal 3D way) 68 * and should be drawn before water (i.e. may be visible under the water) 62 69 */ 63 void RenderOverlays(); 70 void RenderOverlaysBeforeWater(); 71 72 /** 73 * Render all the submitted overlays that are embedded in the world 74 * (i.e. rendered behind other objects in the normal 3D way) 75 * and should be drawn after water (i.e. may be visible on top of the water) 76 */ 77 void RenderOverlaysAfterWater(); 64 78 65 79 /** -
ps/trunk/source/renderer/Renderer.cpp
r9847 r9929 107 107 Row_WaterTris, 108 108 Row_ModelTris, 109 Row_OverlayTris, 109 110 Row_BlendSplats, 110 111 Row_Particles, … … 174 175 return "# model tris"; 175 176 sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_ModelTris); 177 return buf; 178 179 case Row_OverlayTris: 180 if (col == 0) 181 return "# overlay tris"; 182 sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_OverlayTris); 176 183 return buf; 177 184 … … 1574 1581 ogl_WarnIfError(); 1575 1582 1576 // render other debug-related overlays before water (so they can be displayed when underwater) 1577 PROFILE_START("render overlays"); 1578 m->overlayRenderer.RenderOverlays(); 1579 PROFILE_END("render overlays"); 1583 // render other debug-related overlays before water (so they can be seen when underwater) 1584 m->overlayRenderer.RenderOverlaysBeforeWater(); 1580 1585 ogl_WarnIfError(); 1581 1586 … … 1604 1609 } 1605 1610 1611 // render some other overlays after water (so they can be displayed on top of water) 1612 m->overlayRenderer.RenderOverlaysAfterWater(); 1613 ogl_WarnIfError(); 1614 1606 1615 // particles are transparent so render after water 1607 1616 RenderParticles(); … … 1623 1632 1624 1633 // render overlays that should appear on top of all other objects 1625 PROFILE_START("render fg overlays");1626 1634 m->overlayRenderer.RenderForegroundOverlays(m_ViewCamera); 1627 PROFILE_END("render fg overlays");1628 1635 ogl_WarnIfError(); 1629 1636 } … … 1719 1726 1720 1727 void CRenderer::Submit(SOverlayLine* overlay) 1728 { 1729 m->overlayRenderer.Submit(overlay); 1730 } 1731 1732 void CRenderer::Submit(SOverlayTexturedLine* overlay) 1721 1733 { 1722 1734 m->overlayRenderer.Submit(overlay); … … 1933 1945 m_hCompositeAlphaMap = ogl_tex_wrap(&t, g_VFS, key); 1934 1946 (void)ogl_tex_set_filter(m_hCompositeAlphaMap, GL_LINEAR); 1935 (void)ogl_tex_set_wrap (m_hCompositeAlphaMap, GL_CLAMP_TO_EDGE );1947 (void)ogl_tex_set_wrap (m_hCompositeAlphaMap, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); 1936 1948 int ret = ogl_tex_upload(m_hCompositeAlphaMap, 0, 0, GL_INTENSITY); 1937 1949 -
ps/trunk/source/renderer/Renderer.h
r9827 r9929 117 117 // number of (non-transparent) model triangles drawn 118 118 size_t m_ModelTris; 119 // number of overlay triangles drawn 120 size_t m_OverlayTris; 119 121 // number of splat passes for alphamapping 120 122 size_t m_BlendSplats; … … 335 337 void Submit(CPatch* patch); 336 338 void Submit(SOverlayLine* overlay); 339 void Submit(SOverlayTexturedLine* overlay); 337 340 void Submit(SOverlaySprite* overlay); 338 341 void Submit(CModelDecal* decal); -
ps/trunk/source/renderer/Scene.h
r9889 r9929 38 38 class CTerritoryTexture; 39 39 struct SOverlayLine; 40 struct SOverlayTexturedLine; 40 41 struct SOverlaySprite; 41 42 … … 94 95 95 96 /** 97 * Submit a textured line overlay. 98 */ 99 virtual void Submit(SOverlayTexturedLine* overlay) = 0; 100 101 /** 96 102 * Submit a sprite overlay. 97 103 */ -
ps/trunk/source/renderer/VertexBuffer.cpp
r9362 r9929 29 29 #include "ps/CLogger.h" 30 30 31 ///////////////////////////////////////////////////////////////////////////////32 // CVertexBuffer constructor33 31 CVertexBuffer::CVertexBuffer(size_t vertexSize, GLenum usage, GLenum target) 34 32 : m_VertexSize(vertexSize), m_Handle(0), m_SysMem(0), m_Usage(usage), m_Target(target) … … 67 65 } 68 66 69 ///////////////////////////////////////////////////////////////////////////////70 // CVertexBuffer destructor71 67 CVertexBuffer::~CVertexBuffer() 72 68 { … … 74 70 pglDeleteBuffersARB(1, &m_Handle); 75 71 76 if (m_SysMem) 77 delete[] m_SysMem; 78 79 // janwas 2004-06-14: release freelist 72 delete[] m_SysMem; 73 80 74 typedef std::list<VBChunk*>::iterator Iter; 81 75 for (Iter iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) 82 76 delete *iter; 77 } 78 79 80 bool CVertexBuffer::CompatibleVertexType(size_t vertexSize, GLenum usage, GLenum target) 81 { 82 if (usage != m_Usage || target != m_Target || vertexSize != m_VertexSize) 83 return false; 84 85 return true; 83 86 } 84 87 … … 90 93 { 91 94 // check this is the right kind of buffer 92 if ( usage != m_Usage || target != m_Target || vertexSize != m_VertexSize)95 if (!CompatibleVertexType(vertexSize, usage, target)) 93 96 return 0; 94 97 … … 139 142 void CVertexBuffer::Release(VBChunk* chunk) 140 143 { 141 // add to free list 142 // TODO, RC - need to merge available chunks where possible to avoid 143 // excessive fragmentation of vertex buffer space 144 // Update total free count before potentially modifying this chunk's count 145 m_FreeVertices += chunk->m_Count; 146 147 typedef std::list<VBChunk*>::iterator Iter; 148 149 // Coalesce with any free-list items that are adjacent to this chunk; 150 // merge the found chunk with the new one, and remove the old one 151 // from the list, and repeat until no more are found 152 bool coalesced; 153 do 154 { 155 coalesced = false; 156 for (Iter iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) 157 { 158 if ((*iter)->m_Index == chunk->m_Index + chunk->m_Count 159 || (*iter)->m_Index + (*iter)->m_Count == chunk->m_Index) 160 { 161 chunk->m_Index = std::min(chunk->m_Index, (*iter)->m_Index); 162 chunk->m_Count += (*iter)->m_Count; 163 m_FreeList.erase(iter); 164 coalesced = true; 165 break; 166 } 167 } 168 } 169 while (coalesced); 170 144 171 m_FreeList.push_front(chunk); 145 m_FreeVertices += chunk->m_Count;146 172 } 147 173 … … 206 232 return (m_MaxVertices - m_FreeVertices) * m_VertexSize; 207 233 } 234 235 void CVertexBuffer::DumpStatus() 236 { 237 debug_printf(L"freeverts = %d\n", m_FreeVertices); 238 239 size_t maxSize = 0; 240 typedef std::list<VBChunk*>::iterator Iter; 241 for (Iter iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) 242 { 243 debug_printf(L"free chunk %p: size=%d\n", *iter, (*iter)->m_Count); 244 maxSize = std::max((*iter)->m_Count, maxSize); 245 } 246 debug_printf(L"max size = %d\n", maxSize); 247 } -
ps/trunk/source/renderer/VertexBuffer.h
r9053 r9929 46 46 // number of vertices used by chunk 47 47 size_t m_Count; 48 49 private: 50 // Only CVertexBuffer can construct/delete these 51 // (Other people should use g_VBMan.Allocate, g_VBMan.Release) 52 friend class CVertexBuffer; 53 VBChunk() {} 54 ~VBChunk() {} 48 55 }; 49 56 … … 70 77 size_t GetBytesReserved() const; 71 78 size_t GetBytesAllocated() const; 79 80 bool CompatibleVertexType(size_t vertexSize, GLenum usage, GLenum target); 81 82 void DumpStatus(); 72 83 73 84 protected: -
ps/trunk/source/renderer/VertexBufferManager.cpp
r9362 r9929 27 27 #include "ps/CLogger.h" 28 28 29 #define DUMP_VB_STATS 0 // for debugging 30 29 31 CVertexBufferManager g_VBMan; 30 31 // janwas 2004-06-14: added dtor32 33 CVertexBufferManager::~CVertexBufferManager()34 {35 }36 32 37 33 /////////////////////////////////////////////////////////////////////////////// … … 62 58 // TODO, RC - run some sanity checks on allocation request 63 59 60 typedef std::list<CVertexBuffer*>::iterator Iter; 61 62 #if DUMP_VB_STATS 63 debug_printf(L"\n============================\n# allocate vsize=%d nverts=%d\n\n", vertexSize, numVertices); 64 for (Iter iter = m_Buffers.begin(); iter != m_Buffers.end(); ++iter) { 65 CVertexBuffer* buffer = *iter; 66 if (buffer->CompatibleVertexType(vertexSize, usage, target)) 67 { 68 debug_printf(L"%p\n", buffer); 69 buffer->DumpStatus(); 70 } 71 } 72 #endif 73 64 74 // iterate through all existing buffers testing for one that'll 65 75 // satisfy the allocation 66 typedef std::list<CVertexBuffer*>::iterator Iter;67 76 for (Iter iter = m_Buffers.begin(); iter != m_Buffers.end(); ++iter) { 68 77 CVertexBuffer* buffer = *iter; … … 90 99 { 91 100 ENSURE(chunk); 101 #if DUMP_VB_STATS 102 debug_printf(L"\n============================\n# release %p nverts=%d\n\n", chunk, chunk->m_Count); 103 #endif 92 104 chunk->m_Owner->Release(chunk); 93 105 } -
ps/trunk/source/renderer/VertexBufferManager.h
r9052 r9929 31 31 { 32 32 public: 33 CVertexBufferManager() {}34 ~CVertexBufferManager();35 36 33 // Explicit shutdown of the vertex buffer subsystem 37 34 void Shutdown(); -
ps/trunk/source/simulation2/components/CCmpTerritoryManager.cpp
r9906 r9929 21 21 #include "ICmpTerritoryManager.h" 22 22 23 #include "graphics/Overlay.h" 23 24 #include "graphics/Terrain.h" 25 #include "graphics/TextureManager.h" 24 26 #include "maths/MathUtil.h" 27 #include "maths/Vector2D.h" 25 28 #include "ps/Overlay.h" 29 #include "renderer/Renderer.h" 30 #include "renderer/Scene.h" 26 31 #include "renderer/TerrainOverlay.h" 27 32 #include "simulation2/MessageTypes.h" … … 30 35 #include "simulation2/components/ICmpOwnership.h" 31 36 #include "simulation2/components/ICmpPathfinder.h" 37 #include "simulation2/components/ICmpPlayer.h" 38 #include "simulation2/components/ICmpPlayerManager.h" 32 39 #include "simulation2/components/ICmpPosition.h" 33 40 #include "simulation2/components/ICmpSettlement.h" … … 37 44 #include "simulation2/helpers/Grid.h" 38 45 #include "simulation2/helpers/PriorityQueue.h" 46 #include "simulation2/helpers/Render.h" 39 47 40 48 class CCmpTerritoryManager; … … 59 67 componentManager.SubscribeGloballyToMessageType(MT_PositionChanged); 60 68 componentManager.SubscribeToMessageType(MT_TerrainChanged); 69 componentManager.SubscribeToMessageType(MT_RenderSubmit); 61 70 } 62 71 … … 67 76 return "<a:component type='system'/><empty/>"; 68 77 } 78 79 u8 m_ImpassableCost; 80 float m_BorderThickness; 81 float m_BorderSeparation; 69 82 70 83 Grid<u8>* m_Territories; 71 84 TerritoryOverlay* m_DebugOverlay; 85 std::vector<SOverlayTexturedLine> m_BoundaryLines; 86 bool m_BoundaryLinesDirty; 72 87 73 88 virtual void Init(const CParamNode& UNUSED(paramNode)) … … 76 91 m_DebugOverlay = NULL; 77 92 // m_DebugOverlay = new TerritoryOverlay(*this); 93 m_BoundaryLinesDirty = true; 78 94 79 95 m_DirtyID = 1; 96 97 CParamNode externalParamNode; 98 CParamNode::LoadXML(externalParamNode, L"simulation/data/territorymanager.xml"); 99 100 m_ImpassableCost = externalParamNode.GetChild("TerritoryManager").GetChild("ImpassableCost").ToInt(); 101 m_BorderThickness = externalParamNode.GetChild("TerritoryManager").GetChild("BorderThickness").ToFixed().ToFloat(); 102 m_BorderSeparation = externalParamNode.GetChild("TerritoryManager").GetChild("BorderSeparation").ToFixed().ToFloat(); 80 103 } 81 104 … … 117 140 break; 118 141 } 142 case MT_RenderSubmit: 143 { 144 const CMessageRenderSubmit& msgData = static_cast<const CMessageRenderSubmit&> (msg); 145 RenderSubmit(msgData.collector); 146 break; 147 } 119 148 } 120 149 } … … 149 178 SAFE_DELETE(m_Territories); 150 179 ++m_DirtyID; 180 m_BoundaryLinesDirty = true; 151 181 } 152 182 … … 170 200 */ 171 201 void RasteriseInfluences(CComponentManager::InterfaceList& infls, Grid<u8>& grid); 202 203 struct TerritoryBoundary 204 { 205 player_id_t owner; 206 std::vector<CVector2D> points; 207 }; 208 209 std::vector<TerritoryBoundary> ComputeBoundaries(); 210 211 void UpdateBoundaryLines(); 212 213 void RenderSubmit(SceneCollector& collector); 172 214 }; 173 215 … … 253 295 254 296 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); 255 ICmpPathfinder::pass_class_t passClass = cmpPathfinder->GetPassabilityClass("default"); 297 ICmpPathfinder::pass_class_t passClassUnrestricted = cmpPathfinder->GetPassabilityClass("unrestricted"); 298 ICmpPathfinder::pass_class_t passClassDefault = cmpPathfinder->GetPassabilityClass("default"); 256 299 const Grid<u16>& passGrid = cmpPathfinder->GetPassabilityGrid(); 257 300 for (u32 j = 0; j < tilesH; ++j) … … 259 302 for (u32 i = 0; i < tilesW; ++i) 260 303 { 304 u8 g = passGrid.get(i, j); 261 305 u8 cost; 262 if (passGrid.get(i, j) & passClass) 263 cost = 4; // TODO: should come from some XML file 306 if (g & passClassUnrestricted) 307 cost = 255; // off the world; use maximum cost 308 else if (g & passClassDefault) 309 cost = m_ImpassableCost; 264 310 else 265 311 cost = 1; … … 426 472 } 427 473 474 std::vector<CCmpTerritoryManager::TerritoryBoundary> CCmpTerritoryManager::ComputeBoundaries() 475 { 476 PROFILE("ComputeBoundaries"); 477 478 std::vector<CCmpTerritoryManager::TerritoryBoundary> boundaries; 479 480 CalculateTerritories(); 481 482 // Copy the territories grid so we can mess with it 483 Grid<u8> grid (*m_Territories); 484 485 // Some constants for the border walk 486 CVector2D edgeOffsets[] = { 487 CVector2D(0.5f, 0.0f), 488 CVector2D(1.0f, 0.5f), 489 CVector2D(0.5f, 1.0f), 490 CVector2D(0.0f, 0.5f) 491 }; 492 493 // Try to find an assigned tile 494 for (int j = 0; j < grid.m_H; ++j) 495 { 496 for (int i = 0; i < grid.m_W; ++i) 497 { 498 u8 owner = grid.get(i, j); 499 if (owner) 500 { 501 // Found the first tile (which must be the lowest j value of any non-zero tile); 502 // start at the bottom edge of it and chase anticlockwise around the border until 503 // we reach the starting point again 504 505 boundaries.push_back(TerritoryBoundary()); 506 boundaries.back().owner = owner; 507 std::vector<CVector2D>& points = boundaries.back().points; 508 509 int dir = 0; // 0 == bottom edge of tile, 1 == right, 2 == top, 3 == left 510 511 int cdir = dir; 512 int ci = i, cj = j; 513 514 while (true) 515 { 516 points.push_back((CVector2D(ci, cj) + edgeOffsets[cdir]) * CELL_SIZE); 517 518 // Given that we're on an edge on a continuous boundary and aiming anticlockwise, 519 // we can either carry on straight or turn left or turn right, so examine each 520 // of the three possible cases (depending on initial direction): 521 switch (cdir) 522 { 523 case 0: 524 if (ci < grid.m_W-1 && cj > 0 && grid.get(ci+1, cj-1) == owner) 525 { 526 ++ci; 527 --cj; 528 cdir = 3; 529 } 530 else if (ci < grid.m_W-1 && grid.get(ci+1, cj) == owner) 531 ++ci; 532 else 533 cdir = 1; 534 break; 535 case 1: 536 if (ci < grid.m_W-1 && cj < grid.m_H-1 && grid.get(ci+1, cj+1) == owner) 537 { 538 ++ci; 539 ++cj; 540 cdir = 0; 541 } 542 else if (cj < grid.m_H-1 && grid.get(ci, cj+1) == owner) 543 ++cj; 544 else 545 cdir = 2; 546 break; 547 case 2: 548 if (ci > 0 && cj < grid.m_H-1 && grid.get(ci-1, cj+1) == owner) 549 { 550 --ci; 551 ++cj; 552 cdir = 1; 553 } 554 else if (ci > 0 && grid.get(ci-1, cj) == owner) 555 --ci; 556 else 557 cdir = 3; 558 break; 559 case 3: 560 if (ci > 0 && cj > 0 && grid.get(ci-1, cj-1) == owner) 561 { 562 --ci; 563 --cj; 564 cdir = 2; 565 } 566 else if (cj > 0 && grid.get(ci, cj-1) == owner) 567 --cj; 568 else 569 cdir = 0; 570 break; 571 } 572 573 // Stop when we've reached the starting point again 574 if (ci == i && cj == j && cdir == dir) 575 break; 576 } 577 578 // Zero out this whole territory with a simple flood fill, so we don't 579 // process it a second time 580 std::vector<std::pair<int, int> > tileStack; 581 582 #define ZERO_AND_PUSH(i, j) STMT(grid.set(i, j, 0); tileStack.push_back(std::make_pair(i, j)); ) 583 584 ZERO_AND_PUSH(i, j); 585 while (!tileStack.empty()) 586 { 587 int ti = tileStack.back().first; 588 int tj = tileStack.back().second; 589 tileStack.pop_back(); 590 591 if (ti > 0 && grid.get(ti-1, tj) == owner) 592 ZERO_AND_PUSH(ti-1, tj); 593 if (ti < grid.m_W-1 && grid.get(ti+1, tj) == owner) 594 ZERO_AND_PUSH(ti+1, tj); 595 if (tj > 0 && grid.get(ti, tj-1) == owner) 596 ZERO_AND_PUSH(ti, tj-1); 597 if (tj < grid.m_H-1 && grid.get(ti, tj+1) == owner) 598 ZERO_AND_PUSH(ti, tj+1); 599 600 if (ti > 0 && tj > 0 && grid.get(ti-1, tj-1) == owner) 601 ZERO_AND_PUSH(ti-1, tj-1); 602 if (ti > 0 && tj < grid.m_H-1 && grid.get(ti-1, tj+1) == owner) 603 ZERO_AND_PUSH(ti-1, tj+1); 604 if (ti < grid.m_W-1 && tj > 0 && grid.get(ti+1, tj-1) == owner) 605 ZERO_AND_PUSH(ti+1, tj-1); 606 if (ti < grid.m_W-1 && tj < grid.m_H-1 && grid.get(ti+1, tj+1) == owner) 607 ZERO_AND_PUSH(ti+1, tj+1); 608 } 609 610 #undef ZERO_AND_PUSH 611 } 612 } 613 } 614 615 return boundaries; 616 } 617 618 void CCmpTerritoryManager::UpdateBoundaryLines() 619 { 620 PROFILE("update boundary lines"); 621 622 m_BoundaryLines.clear(); 623 624 std::vector<CCmpTerritoryManager::TerritoryBoundary> boundaries = ComputeBoundaries(); 625 626 CTextureProperties texturePropsBase("art/textures/misc/territory_border.png"); 627 texturePropsBase.SetWrap(GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE); 628 texturePropsBase.SetMaxAnisotropy(2.f); 629 CTexturePtr textureBase = g_Renderer.GetTextureManager().CreateTexture(texturePropsBase); 630 631 CTextureProperties texturePropsMask("art/textures/misc/territory_border_mask.png"); 632 texturePropsMask.SetWrap(GL_CLAMP_TO_BORDER, GL_CLAMP_TO_EDGE); 633 texturePropsMask.SetMaxAnisotropy(2.f); 634 CTexturePtr textureMask = g_Renderer.GetTextureManager().CreateTexture(texturePropsMask); 635 636 CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY); 637 if (cmpTerrain.null()) 638 return; 639 CTerrain* terrain = cmpTerrain->GetCTerrain(); 640 641 CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); 642 if (cmpPlayerManager.null()) 643 return; 644 645 for (size_t i = 0; i < boundaries.size(); ++i) 646 { 647 if (boundaries[i].points.empty()) 648 continue; 649 650 CColor color(1, 0, 1, 1); 651 CmpPtr<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(boundaries[i].owner)); 652 if (!cmpPlayer.null()) 653 color = cmpPlayer->GetColour(); 654 655 m_BoundaryLines.push_back(SOverlayTexturedLine()); 656 m_BoundaryLines.back().m_Terrain = terrain; 657 m_BoundaryLines.back().m_TextureBase = textureBase; 658 m_BoundaryLines.back().m_TextureMask = textureMask; 659 m_BoundaryLines.back().m_Color = color; 660 m_BoundaryLines.back().m_Thickness = m_BorderThickness; 661 662 SimRender::SmoothPointsAverage(boundaries[i].points, true); 663 664 SimRender::InterpolatePointsRNS(boundaries[i].points, true, m_BorderSeparation); 665 666 std::vector<float>& points = m_BoundaryLines.back().m_Coords; 667 for (size_t j = 0; j < boundaries[i].points.size(); ++j) 668 { 669 points.push_back(boundaries[i].points[j].X); 670 points.push_back(boundaries[i].points[j].Y); 671 } 672 } 673 } 674 675 void CCmpTerritoryManager::RenderSubmit(SceneCollector& collector) 676 { 677 if (m_BoundaryLinesDirty) 678 { 679 UpdateBoundaryLines(); 680 m_BoundaryLinesDirty = false; 681 } 682 683 for (size_t i = 0; i < m_BoundaryLines.size(); ++i) 684 collector.Submit(&m_BoundaryLines[i]); 685 } 686 428 687 429 688 void TerritoryOverlay::StartRender() -
ps/trunk/source/simulation2/helpers/Render.cpp
r7817 r9929 26 26 #include "graphics/Terrain.h" 27 27 #include "maths/MathUtil.h" 28 29 static const float RENDER_HEIGHT_DELTA = 0.25f; // distance above terrain 30 31 void SimRender::ConstructLineOnGround(const CSimContext& context, std::vector<float> xz, 32 SOverlayLine& overlay, bool floating) 33 { 28 #include "maths/Vector2D.h" 29 #include "ps/Profile.h" 30 31 void SimRender::ConstructLineOnGround(const CSimContext& context, const std::vector<float>& xz, 32 SOverlayLine& overlay, bool floating, float heightOffset) 33 { 34 PROFILE("ConstructLineOnGround"); 35 34 36 overlay.m_Coords.clear(); 35 37 … … 55 57 float px = xz[i]; 56 58 float pz = xz[i+1]; 57 float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + RENDER_HEIGHT_DELTA;59 float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + heightOffset; 58 60 overlay.m_Coords.push_back(px); 59 61 overlay.m_Coords.push_back(py); … … 63 65 64 66 void SimRender::ConstructCircleOnGround(const CSimContext& context, float x, float z, float radius, 65 SOverlayLine& overlay, bool floating )67 SOverlayLine& overlay, bool floating, float heightOffset) 66 68 { 67 69 overlay.m_Coords.clear(); … … 89 91 float px = x + radius * sin(a); 90 92 float pz = z + radius * cos(a); 91 float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + RENDER_HEIGHT_DELTA;93 float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + heightOffset; 92 94 overlay.m_Coords.push_back(px); 93 95 overlay.m_Coords.push_back(py); … … 114 116 115 117 void SimRender::ConstructSquareOnGround(const CSimContext& context, float x, float z, float w, float h, float a, 116 SOverlayLine& overlay, bool floating )118 SOverlayLine& overlay, bool floating, float heightOffset) 117 119 { 118 120 overlay.m_Coords.clear(); … … 151 153 float px = coords[i].first; 152 154 float pz = coords[i].second; 153 float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + RENDER_HEIGHT_DELTA;155 float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + heightOffset; 154 156 overlay.m_Coords.push_back(px); 155 157 overlay.m_Coords.push_back(py); … … 157 159 } 158 160 } 161 162 void SimRender::SmoothPointsAverage(std::vector<CVector2D>& points, bool closed) 163 { 164 PROFILE("SmoothPointsAverage"); 165 166 size_t n = points.size(); 167 if (n < 2) 168 return; // avoid out-of-bounds array accesses, and leave the points unchanged 169 170 std::vector<CVector2D> newPoints; 171 newPoints.resize(points.size()); 172 173 // Handle the end points appropriately 174 if (closed) 175 { 176 newPoints[0] = (points[n-1] + points[0] + points[1]) / 3.f; 177 newPoints[n-1] = (points[n-2] + points[n-1] + points[0]) / 3.f; 178 } 179 else 180 { 181 newPoints[0] = points[0]; 182 newPoints[n-1] = points[n-1]; 183 } 184 185 // Average all the intermediate points 186 for (size_t i = 1; i < n-1; ++i) 187 newPoints[i] = (points[i-1] + points[i] + points[i+1]) / 3.f; 188 189 points.swap(newPoints); 190 } 191 192 static CVector2D EvaluateSpline(float t, CVector2D a0, CVector2D a1, CVector2D a2, CVector2D a3, float offset) 193 { 194 // Compute position on spline 195 CVector2D p = a0*(t*t*t) + a1*(t*t) + a2*t + a3; 196 197 // Compute unit-vector direction of spline 198 CVector2D dp = (a0*(3*t*t) + a1*(2*t) + a2).Normalized(); 199 200 // Offset position perpendicularly 201 return p + CVector2D(dp.Y*-offset, dp.X*offset); 202 } 203 204 void SimRender::InterpolatePointsRNS(std::vector<CVector2D>& points, bool closed, float offset) 205 { 206 PROFILE("InterpolatePointsRNS"); 207 208 std::vector<CVector2D> newPoints; 209 210 // (This does some redundant computations for adjacent vertices, 211 // but it's fairly fast (<1ms typically) so we don't worry about it yet) 212 213 // TODO: Instead of doing a fixed number of line segments between each 214 // control point, it should probably be somewhat adaptive to get a nicer 215 // curve with fewer points 216 217 size_t n = points.size(); 218 if (n < 1) 219 return; // can't do anything unless we have two points 220 221 size_t imax = closed ? n : n-1; // TODO: we probably need to do a bit more to handle non-closed paths 222 223 newPoints.reserve(imax*4); 224 225 for (size_t i = 0; i < imax; ++i) 226 { 227 // Get the relevant points for this spline segment 228 CVector2D p0 = points[(i-1+n)%n]; 229 CVector2D p1 = points[i]; 230 CVector2D p2 = points[(i+1)%n]; 231 CVector2D p3 = points[(i+2)%n]; 232 233 // Do the RNS computation (based on GPG4 "Nonuniform Splines") 234 float l1 = (p2 - p1).Length(); // length of spline segment (i)..(i+1) 235 CVector2D s0 = (p1 - p0).Normalized(); // unit vector of spline segment (i-1)..(i) 236 CVector2D s1 = (p2 - p1).Normalized(); // unit vector of spline segment (i)..(i+1) 237 CVector2D s2 = (p3 - p2).Normalized(); // unit vector of spline segment (i+1)..(i+2) 238 CVector2D v1 = (s0 + s1).Normalized() * l1; // spline velocity at i 239 CVector2D v2 = (s1 + s2).Normalized() * l1; // spline velocity at i+1 240 241 // Compute standard cubic spline parameters 242 CVector2D a0 = p1*2 + p2*-2 + v1 + v2; 243 CVector2D a1 = p1*-3 + p2*3 + v1*-2 + v2*-1; 244 CVector2D a2 = v1; 245 CVector2D a3 = p1; 246 247 // Interpolate at various points 248 newPoints.push_back(EvaluateSpline(0.f, a0, a1, a2, a3, offset)); 249 newPoints.push_back(EvaluateSpline(1.f/4.f, a0, a1, a2, a3, offset)); 250 newPoints.push_back(EvaluateSpline(2.f/4.f, a0, a1, a2, a3, offset)); 251 newPoints.push_back(EvaluateSpline(3.f/4.f, a0, a1, a2, a3, offset)); 252 } 253 254 points.swap(newPoints); 255 } -
ps/trunk/source/simulation2/helpers/Render.h
r7655 r9929 25 25 26 26 class CSimContext; 27 class CVector2D; 27 28 struct SOverlayLine; 28 29 … … 34 35 * flattened on the terrain (or on the water if @p floating). 35 36 */ 36 void ConstructLineOnGround(const CSimContext& context, std::vector<float> xz, SOverlayLine& overlay, bool floating); 37 void ConstructLineOnGround(const CSimContext& context, const std::vector<float>& xz, 38 SOverlayLine& overlay, 39 bool floating, float heightOffset = 0.25f); 37 40 38 41 /** 39 42 * Updates @p overlay so that it represents the given circle, flattened on the terrain. 40 43 */ 41 void ConstructCircleOnGround(const CSimContext& context, float x, float z, float radius, SOverlayLine& overlay, bool floating); 44 void ConstructCircleOnGround(const CSimContext& context, float x, float z, float radius, 45 SOverlayLine& overlay, 46 bool floating, float heightOffset = 0.25f); 42 47 43 48 /** … … 45 50 * @p x and @p z are position of center, @p w and @p h are size of rectangle, @p a is clockwise angle. 46 51 */ 47 void ConstructSquareOnGround(const CSimContext& context, float x, float z, float w, float h, float a, SOverlayLine& overlay, bool floating); 52 void ConstructSquareOnGround(const CSimContext& context, float x, float z, float w, float h, float a, 53 SOverlayLine& overlay, 54 bool floating, float heightOffset = 0.25f); 55 56 /** 57 * Updates @p points so each point is averaged with its neighbours, resulting in 58 * a somewhat smoother curve, assuming the points are roughly equally spaced. 59 * If @p closed then the points are treated as a closed path (the last is connected 60 * to the first). 61 */ 62 void SmoothPointsAverage(std::vector<CVector2D>& points, bool closed); 63 64 /** 65 * Updates @p points to include intermediate points interpolating between the original 66 * control points, using a rounded nonuniform spline. 67 * The points are also shifted by @p offset in a direction 90 degrees clockwise from 68 * the direction of the curve. 69 * If @p closed then the points are treated as a closed path (the last is connected 70 * to the first). 71 */ 72 void InterpolatePointsRNS(std::vector<CVector2D>& points, bool closed, float offset); 48 73 49 74 } // namespace
Note:
See TracChangeset
for help on using the changeset viewer.
