Skip to content
This repository
Browse code

Merge branch 'master' into new-ui

Conflicts:
	src/Pi.cpp
	src/vector2.h
  • Loading branch information...
commit d937d4a448b6e499707ed4699bcf3e68dc99dd11 2 parents 96994b8 + dc15e45
Robert Norris robn authored

Showing 103 changed files with 4,631 additions and 234 deletions. Show diff stats Hide diff stats

  1. +5 0 AUTHORS.txt
  2. +13 0 Changelog.txt
  3. +2 1  configure.ac
  4. +1 1  contrib/Makefile.am
  5. +2 0  contrib/vcacheopt/Makefile.am
  6. +507 0 contrib/vcacheopt/vcacheopt.h
  7. BIN  data/icons/object_planet_medium_gas_giant.png
  8. +4 0 data/lang/English.txt
  9. +9 5 data/lang/Polski.txt
  10. +28 0 data/lang/Spanish.txt
  11. +3 0  data/systems/00_sol.lua
  12. +1 0  data/ui/MainMenu.lua
  13. +43 35 src/GameMenuView.cpp
  14. +5 1 src/GameMenuView.h
  15. +116 61 src/GeoSphere.cpp
  16. +2 0  src/LangStrings.inc.h
  17. +19 13 src/LmrModel.cpp
  18. +1 1  src/LuaConsole.cpp
  19. +33 15 src/Pi.cpp
  20. +6 0 src/Pi.h
  21. +2 2 src/ShipAICmd.cpp
  22. +8 8 src/Space.cpp
  23. +1 0  src/SpaceStation.cpp
  24. +15 15 src/SystemInfoView.cpp
  25. +12 8 src/View.cpp
  26. +1 3 src/WorldView.cpp
  27. +0 5 src/WorldView.h
  28. +24 0 src/galaxy/CustomSystem.cpp
  29. +2 0  src/galaxy/CustomSystem.h
  30. +19 3 src/galaxy/StarSystem.cpp
  31. +4 0 src/galaxy/StarSystem.h
  32. +1 1  src/graphics/Renderer.h
  33. +1 1  src/graphics/RendererLegacy.h
  34. +2 0  src/gui/GuiFixed.cpp
  35. +1 1  src/gui/GuiImage.cpp
  36. +1 0  src/gui/GuiWidget.cpp
  37. +0 2  src/libs.h
  38. +5 5 src/terrain/TerrainColorGGJupiter.cpp
  39. +5 5 src/terrain/TerrainColorGGNeptune.cpp
  40. +5 4 src/terrain/TerrainColorGGNeptune2.cpp
  41. +7 7 src/terrain/TerrainColorGGSaturn.cpp
  42. +1 1  src/terrain/TerrainColorGGSaturn2.cpp
  43. +4 4 src/terrain/TerrainColorGGUranus.cpp
  44. +1 1  src/ui/Align.cpp
  45. +1 1  src/ui/Background.cpp
  46. +1 1  src/ui/Box.cpp
  47. +2 2 src/ui/Context.h
  48. +2 2 src/ui/DropDown.cpp
  49. +1 1  src/ui/FloatContainer.h
  50. +1 1  src/ui/Label.cpp
  51. +1 1  src/ui/List.cpp
  52. +2 2 src/ui/MultiLineText.cpp
  53. +1 1  src/ui/Scroller.cpp
  54. +1 1  src/ui/Single.cpp
  55. +1 1  src/ui/TextLayout.cpp
  56. +3 3 src/ui/Widget.cpp
  57. +2 2 src/ui/Widget.h
  58. +4 4 src/vector2.h
  59. +2 2 src/vector3.h
  60. BIN  win32/lib/libogg_static_vc2012_debug.lib
  61. BIN  win32/lib/libogg_static_vc2012_debug.pdb
  62. BIN  win32/lib/libogg_static_vc2012_release.lib
  63. BIN  win32/lib/libvorbis_static_vc2012_debug.lib
  64. BIN  win32/lib/libvorbis_static_vc2012_release.lib
  65. BIN  win32/lib/libvorbisfile_static_vc2012_debug.lib
  66. BIN  win32/lib/libvorbisfile_static_vc2012_release.lib
  67. BIN  win32/lib/sigc-vc2012-2_2_8.dll
  68. BIN  win32/lib/sigc-vc2012-2_2_8.lib
  69. BIN  win32/lib/sigc-vc2012-d-2_2_8.dll
  70. BIN  win32/lib/sigc-vc2012-d-2_2_8.lib
  71. BIN  win32/lib/sigc-vc2012-d-2_2_8.pdb
  72. +8 0 win32/vc2008/pioneer-msvc-9.0.vcproj
  73. +1 0  win32/vc2010/pioneer.vcxproj
  74. +3 0  win32/vc2010/pioneer.vcxproj.filters
  75. +25 0 win32/vc2012/Debug.props
  76. +33 0 win32/vc2012/PreRelease.props
  77. +30 0 win32/vc2012/Release.props
  78. +106 0 win32/vc2012/collider/collider.vcxproj
  79. +28 0 win32/vc2012/collider/collider.vcxproj.filters
  80. +14 0 win32/vc2012/common.props
  81. +106 0 win32/vc2012/galaxy/galaxy.vcxproj
  82. +28 0 win32/vc2012/galaxy/galaxy.vcxproj.filters
  83. +139 0 win32/vc2012/graphics/graphics.vcxproj
  84. +92 0 win32/vc2012/graphics/graphics.vcxproj.filters
  85. +153 0 win32/vc2012/gui/gui.vcxproj
  86. +75 0 win32/vc2012/gui/gui.vcxproj.filters
  87. +100 0 win32/vc2012/jenkins/jenkins.vcxproj
  88. +18 0 win32/vc2012/jenkins/jenkins.vcxproj.filters
  89. +180 0 win32/vc2012/lua.vcxproj
  90. +183 0 win32/vc2012/lua.vcxproj.filters
  91. +126 0 win32/vc2012/miniz.vcxproj
  92. +18 0 win32/vc2012/miniz.vcxproj.filters
  93. +184 0 win32/vc2012/modelviewer.vcxproj
  94. +180 0 win32/vc2012/modelviewer.vcxproj.filters
  95. +99 0 win32/vc2012/perlintest.vcxproj
  96. +36 0 win32/vc2012/perlintest.vcxproj.filters
  97. +123 0 win32/vc2012/pioneer.sln
  98. +399 0 win32/vc2012/pioneer.vcxproj
  99. +839 0 win32/vc2012/pioneer.vcxproj.filters
  100. +152 0 win32/vc2012/terrain/terrain.vcxproj
  101. +74 0 win32/vc2012/terrain/terrain.vcxproj.filters
  102. +105 0 win32/vc2012/text/text.vcxproj
  103. +27 0 win32/vc2012/text/text.vcxproj.filters
5 AUTHORS.txt
@@ -23,6 +23,7 @@ The Pioneer team, past and present, as at 14 September 2012 (alpha 26):
23 23 John Jordan
24 24 Kimmo Kotajärvi
25 25 Konrad Mruk
  26 + Krzysztof Niedźwiecki
26 27 Lee Reilly
27 28 Lars Westerhoff
28 29 Leonardo Manna
@@ -75,6 +76,10 @@ Pioneer includes the following third-party software:
75 76
76 77 lookup3.c, by Bob Jenkins, May 2006, Public Domain.
77 78
  79 + vcacheopt.h
  80 + Copyright (C) 2009, Michael Georgoulpoulos
  81 + Licensed under the MIT licence (see the license block in the file)
  82 +
78 83 Pioneer also makes use of these fine projects. Thanks a lot!
79 84
80 85 SDL
13 Changelog.txt
... ... @@ -1,14 +1,27 @@
1 1 Alpha 27
2 2
  3 + * New features
  4 + * The settings screen is now acessible from the main menu (#1187, #1512)
  5 +
3 6 * Minor changes and tweaks
4 7 * Smooth zoom animation in World, System, Sector and Galactic views (#1170)
  8 + * Earth start location has returned to Los Angeles (in daytime now) (#1506)
  9 +
  10 + * Fixes
  11 + * Avoid icons in some ternary systems overlapping each other (#1510, #1511)
  12 + * Fix overlapping text for long system descriptions (#1494, #1498)
  13 + * Fix crash in SystemInfoView from leaking widget references (#1526, #1493)
5 14
6 15 * Script changes
7 16 * EventQueue, which was deprecated in alpha 26, has been removed (#1485)
  17 + * Orbital phase (season) and rotational phase (time) can now be set in custom
  18 + systems with :rotational_phase_at_start and :orbital_phase_at_start (#1506)
8 19
9 20 * Internal changes
10 21 * Terrain generation thread now sleeps until being signalled (#1169)
11 22 * New C++ wrappers for Lua table manipulation and value persistence (#1438)
  23 + * Terrain patches are now rendered more efficiently (#1507)
  24 + * Many minor cleanups identified by valgrind (#1524)
12 25
13 26 Alpha 26
14 27
3  configure.ac
@@ -5,7 +5,7 @@ dnl Setup
5 5 dnl ###########################################################################
6 6 AC_PREREQ(2.59)
7 7
8   -AC_INIT([pioneer], [alpha-27-dev], [pioneer@pioneerspacesim.net])
  8 +AC_INIT([pioneer], [alpha-27-dev], [pioneer-dev@pioneerspacesim.net])
9 9 dnl AC_CONFIG_HEADERS([config.h])
10 10
11 11 AC_DEFUN([MXE_SETUP], [
@@ -299,6 +299,7 @@ AC_CONFIG_FILES([
299 299 contrib/lua/Makefile
300 300 contrib/miniz/Makefile
301 301 contrib/jenkins/Makefile
  302 + contrib/vcacheopt/Makefile
302 303 osx/Makefile
303 304 win32/Makefile])
304 305 AC_OUTPUT
2  contrib/Makefile.am
... ... @@ -1 +1 @@
1   -SUBDIRS = lua miniz jenkins
  1 +SUBDIRS = lua miniz jenkins vcacheopt
2  contrib/vcacheopt/Makefile.am
... ... @@ -0,0 +1,2 @@
  1 +# Process this file with automake to produce Makefile.in
  2 +noinst_HEADERS = vcacheopt.h
507 contrib/vcacheopt/vcacheopt.h
... ... @@ -0,0 +1,507 @@
  1 +/*
  2 + * vcacheopt.h - Vertex Cache Optimizer
  3 + * Copyright 2009 Michael Georgoulpoulos <mgeorgoulopoulos at gmail>
  4 + *
  5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  6 + * of this software and associated documentation files (the "Software"), to deal
  7 + * in the Software without restriction, including without limitation the rights
  8 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9 + * copies of the Software, and to permit persons to whom the Software is
  10 + * furnished to do so, subject to the following conditions:
  11 + *
  12 + * The above copyright notice and this permission notice shall be included in
  13 + * all copies or substantial portions of the Software.
  14 + *
  15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21 + * THE SOFTWARE.
  22 + */
  23 +
  24 +#ifndef _VCACHEOPT_H_
  25 +#define _VCACHEOPT_H_
  26 +
  27 +#include <vector>
  28 +#include <cmath>
  29 +#include <cassert>
  30 +#include <climits>
  31 +
  32 +template <typename T, int ERR_VAL>
  33 +class TVertexCacheData
  34 +{
  35 +public:
  36 + int position_in_cache;
  37 + float current_score;
  38 + int total_valence; // toatl number of triangles using this vertex
  39 + int remaining_valence; // number of triangles using it but not yet rendered
  40 + std::vector<T> tri_indices; // indices to the indices that use this vertex
  41 + bool calculated; // was the score calculated during this iteration?
  42 +
  43 +
  44 + T FindTriangle(const T tri) const
  45 + {
  46 + for (size_t i=0; i<tri_indices.size(); ++i) {
  47 + if (tri_indices[i] == tri)
  48 + return i;
  49 + }
  50 + return ERR_VAL;
  51 + }
  52 +
  53 + void MoveTriangleToEnd(const T tri)
  54 + {
  55 + T t_ind = FindTriangle(tri);
  56 + assert(t_ind >= 0);
  57 + tri_indices.erase(tri_indices.begin() + t_ind, tri_indices.begin() + t_ind + 1);
  58 + tri_indices.push_back(tri);
  59 + }
  60 +
  61 + TVertexCacheData()
  62 + {
  63 + position_in_cache = -1;
  64 + current_score = 0.0f;
  65 + total_valence = 0;
  66 + remaining_valence = 0;
  67 + }
  68 +};
  69 +typedef TVertexCacheData<int, INT_MAX > VertexCacheDataInt;
  70 +typedef TVertexCacheData<unsigned short, USHRT_MAX > VertexCacheDataUShort;
  71 +
  72 +template <typename T, int ERR_VAL>
  73 +class TTriangleCacheData
  74 +{
  75 +public:
  76 + bool rendered; // has the triangle been added to the draw list yet?
  77 + bool calculated; // was the score calculated during this iteration?
  78 + float current_score; // sum of the score of its vertices
  79 + T verts[3]; // indices to the triangle's vertices
  80 +
  81 + TTriangleCacheData() : rendered(false), calculated(false), current_score(0.0f) {
  82 + verts[0] = verts[1] = verts[2] = ERR_VAL;
  83 + }
  84 +};
  85 +typedef TTriangleCacheData<int, INT_MAX > TriangleCacheDataInt;
  86 +typedef TTriangleCacheData<unsigned short, USHRT_MAX > TriangleCacheDataUShort;
  87 +
  88 +template <typename T, int N, int ERR_VAL>
  89 +class TVertexCache
  90 +{
  91 +protected:
  92 + T cache[N];
  93 + int misses; // cache miss count
  94 +
  95 + T FindVertex(const T v) const
  96 + {
  97 + for (int i=0; i<(N-1); ++i) {
  98 + if (cache[i] == v) return i;
  99 + }
  100 +
  101 + return ERR_VAL;
  102 + }
  103 +
  104 + void RemoveVertex(const int stack_index)
  105 + {
  106 + for (int i=stack_index; i<(N-1); ++i) {
  107 + cache[i] = cache[i+1];
  108 + }
  109 + }
  110 +
  111 +public:
  112 + // the vertex will be placed on top
  113 + // if the vertex didn't exist previewsly in
  114 + // the cache, then miss count is incermented
  115 + void AddVertex(const int v)
  116 + {
  117 + int w = FindVertex(v);
  118 + if (w >= 0) {
  119 + // remove the vertex from the cache (to reinsert it later on the top)
  120 + RemoveVertex(w);
  121 + } else {
  122 + // the vertex was not found in the cache - increment misses
  123 + ++misses;
  124 + }
  125 +
  126 + // shift all vertices down (to make room for the new top vertex)
  127 + for (int i=(N-1); i>0; --i) {
  128 + cache[i] = cache[i-1];
  129 + }
  130 +
  131 + // add the new vertex on top
  132 + cache[0] = v;
  133 + }
  134 +
  135 + void Clear()
  136 + {
  137 + for (int i=0; i<N; ++i) cache[i] = ERR_VAL;
  138 + misses = 0;
  139 + }
  140 +
  141 + TVertexCache()
  142 + {
  143 + Clear();
  144 + }
  145 +
  146 + int GetCacheMissCount() const
  147 + {
  148 + return misses;
  149 + }
  150 +
  151 + T GetCachedVertex(int which) const
  152 + {
  153 + return cache[which];
  154 + }
  155 +
  156 + int GetCacheMissCount(int *inds, int tri_count)
  157 + {
  158 + Clear();
  159 +
  160 + for (int i=0; i<3*tri_count; i++)
  161 + {
  162 + AddVertex(inds[i]);
  163 + }
  164 +
  165 + return misses;
  166 + }
  167 +};
  168 +typedef TVertexCache<int, 40, INT_MAX > VertexCacheInt;
  169 +typedef TVertexCache<unsigned short, 40, USHRT_MAX > VertexCacheUShort;
  170 +
  171 +template <typename T, int N, int ERR_VAL>
  172 +class TVertexCacheOptimizer
  173 +{
  174 +public:
  175 + // CalculateVertexScore constants
  176 + float CacheDecayPower;
  177 + float LastTriScore;
  178 + float ValenceBoostScale;
  179 + float ValenceBoostPower;
  180 +
  181 + enum Result
  182 + {
  183 + Success = 0,
  184 + Fail_BadIndex,
  185 + Fail_NoVerts
  186 + };
  187 +
  188 + static bool Failed(Result r)
  189 + {
  190 + return r != Success;
  191 + }
  192 +
  193 +protected:
  194 + std::vector<TVertexCacheData<T, ERR_VAL > > verts;
  195 + std::vector<TTriangleCacheData<T, ERR_VAL > > tris;
  196 + std::vector<T> inds;
  197 + int best_tri; // the next triangle to add to the render list
  198 + TVertexCache<T, N, ERR_VAL > vertex_cache;
  199 + std::vector<T> draw_list;
  200 +
  201 + float CalculateVertexScore(const int vertex)
  202 + {
  203 + TVertexCacheData<T, ERR_VAL > *v = &verts[vertex];
  204 + if (v->remaining_valence <= 0) {
  205 + // No tri needs this vertex!
  206 + return -1.0f;
  207 + }
  208 +
  209 + float ret = 0.0f;
  210 + if (v->position_in_cache < 0) {
  211 + // Vertex is not in FIFO cache - no score.
  212 + } else {
  213 + if (v->position_in_cache < 3) {
  214 + // This vertex was used in the last triangle,
  215 + // so it has a fixed score, whichever of the three
  216 + // it's in. Otherwise, you can get very different
  217 + // answers depending on whether you add
  218 + // the triangle 1,2,3 or 3,1,2 - which is silly.
  219 + ret = LastTriScore;
  220 + } else {
  221 + // Points for being high in the cache.
  222 + const float Scaler = 1.0f / (32 - 3);
  223 + ret = 1.0f - (v->position_in_cache - 3) * Scaler;
  224 + ret = powf(ret, CacheDecayPower);
  225 + }
  226 + }
  227 +
  228 + // Bonus points for having a low number of tris still to
  229 + // use the vert, so we get rid of lone verts quickly.
  230 + float valence_boost = powf((float)v->remaining_valence, -ValenceBoostPower);
  231 + ret += ValenceBoostScale * valence_boost;
  232 +
  233 + return ret;
  234 + }
  235 +
  236 + // returns the index of the triangle with the highest score
  237 + // (or -1, if there aren't any active triangles)
  238 + int FullScoreRecalculation()
  239 + {
  240 + // calculate score for all vertices
  241 + for (size_t i=0; i<verts.size(); ++i) {
  242 + verts[i].current_score = CalculateVertexScore(i);
  243 + }
  244 +
  245 + // calculate scores for all active triangles
  246 + float max_score;
  247 + int max_score_tri = -1;
  248 + bool first_time = true;
  249 + for (int i=0; i<(int)tris.size(); ++i) {
  250 + if (tris[i].rendered) continue;
  251 + // sum the score of all the triangle's vertices
  252 + float sc = verts[tris[i].verts[0]].current_score +
  253 + verts[tris[i].verts[1]].current_score +
  254 + verts[tris[i].verts[2]].current_score;
  255 +
  256 + tris[i].current_score = sc;
  257 +
  258 + if (first_time || sc > max_score) {
  259 + first_time = false;
  260 + max_score = sc;
  261 + max_score_tri = i;
  262 + }
  263 + }
  264 +
  265 + return max_score_tri;
  266 + }
  267 +
  268 + Result InitialPass()
  269 + {
  270 + for (size_t i=0; i<inds.size(); ++i)
  271 + {
  272 + int index = inds[i];
  273 + if (ERR_VAL==index || index >= (int)verts.size()) return Fail_BadIndex;
  274 +
  275 + verts[index].total_valence++;
  276 + verts[index].remaining_valence++;
  277 +
  278 + verts[index].tri_indices.push_back(i/3);
  279 + }
  280 +
  281 + best_tri = FullScoreRecalculation();
  282 +
  283 + return Success;
  284 + }
  285 +
  286 + Result Init(T *inds, const int tri_count, const int vertex_count)
  287 + {
  288 + // clear the draw list
  289 + draw_list.clear();
  290 +
  291 + // allocate and initialize vertices and triangles
  292 + verts.clear();
  293 + for (int i=0; i<vertex_count; ++i) verts.push_back( TVertexCacheData<T, ERR_VAL >() );
  294 +
  295 + tris.clear();
  296 + for (int i=0; i<tri_count; ++i) {
  297 + TTriangleCacheData<T, ERR_VAL > dat;
  298 + for (int j=0; j<3; ++j) {
  299 + dat.verts[j] = inds[i * 3 + j];
  300 + }
  301 + tris.push_back(dat);
  302 + }
  303 +
  304 + // copy the indices
  305 + this->inds.clear();
  306 + for (int i=0; i<tri_count * 3; ++i) this->inds.push_back(inds[i]);
  307 +
  308 + vertex_cache.Clear();
  309 + best_tri = -1;
  310 +
  311 + return InitialPass();
  312 + }
  313 +
  314 + void AddTriangleToDrawList(const int tri)
  315 + {
  316 + // reset all cache positions
  317 + for (int i=0; i<32; ++i) {
  318 + int ind = vertex_cache.GetCachedVertex(i);
  319 + if (ERR_VAL==ind) continue;
  320 + verts[ind].position_in_cache = -1;
  321 + }
  322 +
  323 + TTriangleCacheData<T, ERR_VAL > *t = &tris[tri];
  324 + if (t->rendered) return; // triangle is already in the draw list
  325 +
  326 + for (int i=0; i<3; ++i) {
  327 + // add all triangle vertices to the cache
  328 + vertex_cache.AddVertex(t->verts[i]);
  329 +
  330 + TVertexCacheData<T, ERR_VAL > *v = &verts[t->verts[i]];
  331 +
  332 + // decrease remaining velence
  333 + v->remaining_valence--;
  334 +
  335 + // move the added triangle to the end of the vertex's
  336 + // triangle index list, so that the first 'remaining_valence'
  337 + // triangles in the list are the active ones
  338 + v->MoveTriangleToEnd(tri);
  339 + }
  340 +
  341 + draw_list.push_back(tri);
  342 +
  343 + t->rendered = true;
  344 +
  345 + // update all vertex cache positions
  346 + for (int i=0; i<32; ++i) {
  347 + T ind = vertex_cache.GetCachedVertex(i);
  348 + if (ERR_VAL==ind) continue;
  349 + verts[ind].position_in_cache = i;
  350 + }
  351 +
  352 + }
  353 +
  354 + // Optimization: to avoid duplicate calculations durind the same iteration,
  355 + // both vertices and triangles have a 'calculated' flag. This flag
  356 + // must be cleared at the beginning of the iteration to all *active* triangles
  357 + // that have one or more of their vertices currently cached, and all their
  358 + // other vertices.
  359 + // If there aren't any active triangles in the cache, the function returns
  360 + // false and full recalculation is performed.
  361 + bool CleanCalculationFlags()
  362 + {
  363 + bool ret = false;
  364 + for (int i=0; i<32; i++) {
  365 + T vert = vertex_cache.GetCachedVertex(i);
  366 + if (ERR_VAL==vert) continue;
  367 +
  368 + TVertexCacheData<T, ERR_VAL > *v = &verts[vert];
  369 +
  370 + for (int j=0; j<v->remaining_valence; j++) {
  371 + TTriangleCacheData<T, ERR_VAL > *t = &tris[v->tri_indices[j]];
  372 +
  373 + // we actually found a triangle to process
  374 + ret = true;
  375 +
  376 + // clear triangle flag
  377 + t->calculated = false;
  378 +
  379 + // clear vertex flags
  380 + for (int tri_vert=0; tri_vert<3; tri_vert++) {
  381 + verts[t->verts[tri_vert]].calculated = false;
  382 + }
  383 + }
  384 + }
  385 +
  386 + return ret;
  387 + }
  388 +
  389 + void TriangleScoreRecalculation(const int tri)
  390 + {
  391 + TTriangleCacheData<T, ERR_VAL > *t = &tris[tri];
  392 +
  393 + // calculate vertex scores
  394 + float sum = 0.0f;
  395 + for (int i=0; i<3; i++) {
  396 + TVertexCacheData<T, ERR_VAL > *v = &verts[t->verts[i]];
  397 + float sc = v->current_score;
  398 + if (!v->calculated) {
  399 + sc = CalculateVertexScore(t->verts[i]);
  400 + }
  401 + v->current_score = sc;
  402 + v->calculated = true;
  403 + sum += sc;
  404 + }
  405 +
  406 + t->current_score = sum;
  407 + t->calculated = true;
  408 + }
  409 +
  410 + int PartialScoreRecalculation()
  411 + {
  412 + // iterate through all the vertices of the cache
  413 + bool first_time = true;
  414 + float max_score;
  415 + int max_score_tri = -1;
  416 + for (int i=0; i<32; i++) {
  417 + int vert = vertex_cache.GetCachedVertex(i);
  418 + if (ERR_VAL==vert) continue;
  419 +
  420 + TVertexCacheData<T, ERR_VAL > *v = &verts[vert];
  421 +
  422 + // iterate through all *active* triangles of this vertex
  423 + for (int j=0; j<v->remaining_valence; j++) {
  424 + int tri = v->tri_indices[j];
  425 + TTriangleCacheData<T, ERR_VAL > *t = &tris[tri];
  426 + if (!t->calculated) {
  427 + // calculate triangle score
  428 + TriangleScoreRecalculation(tri);
  429 + }
  430 +
  431 + float sc = t->current_score;
  432 +
  433 + // we actually found a triangle to process
  434 + if (first_time || sc > max_score) {
  435 + first_time = false;
  436 + max_score = sc;
  437 + max_score_tri = tri;
  438 + }
  439 + }
  440 + }
  441 +
  442 + return max_score_tri;
  443 + }
  444 +
  445 + // returns true while there are more steps to take
  446 + // false when optimization is complete
  447 + bool Iterate()
  448 + {
  449 + if (draw_list.size() == tris.size()) return false;
  450 +
  451 + // add the selected triangle to the draw list
  452 + AddTriangleToDrawList(best_tri);
  453 +
  454 + // recalculate vertex and triangle scores and
  455 + // select the best triangle for the next iteration
  456 + if (CleanCalculationFlags()) {
  457 + best_tri = PartialScoreRecalculation();
  458 + } else {
  459 + best_tri = FullScoreRecalculation();
  460 + }
  461 +
  462 + return true;
  463 + }
  464 +
  465 +public:
  466 + TVertexCacheOptimizer()
  467 + {
  468 + // initialize constants
  469 + CacheDecayPower = 1.5f;
  470 + LastTriScore = 0.75f;
  471 + ValenceBoostScale = 2.0f;
  472 + ValenceBoostPower = 0.5f;
  473 +
  474 + best_tri = 0;
  475 + }
  476 +
  477 + // stores new indices in place
  478 + Result Optimize(T *inds, int tri_count)
  479 + {
  480 + // find vertex count
  481 + int max_vert = -1;
  482 + for (int i=0; i<tri_count * 3; i++) {
  483 + if (inds[i] > max_vert) max_vert = inds[i];
  484 + }
  485 +
  486 + if (max_vert == -1) return Fail_NoVerts;
  487 +
  488 + Result res = Init(inds, tri_count, max_vert + 1);
  489 + if (res) return res;
  490 +
  491 + // iterate until Iterate returns false
  492 + while (Iterate());
  493 +
  494 + // rewrite optimized index list
  495 + for (size_t i=0; i<draw_list.size(); i++) {
  496 + inds[3 * i + 0] = tris[draw_list[i]].verts[0];
  497 + inds[3 * i + 1] = tris[draw_list[i]].verts[1];
  498 + inds[3 * i + 2] = tris[draw_list[i]].verts[2];
  499 + }
  500 +
  501 + return Success;
  502 + }
  503 +};
  504 +typedef TVertexCacheOptimizer<int, 40, INT_MAX > VertexCacheOptimizerInt;
  505 +typedef TVertexCacheOptimizer<unsigned short, 40, USHRT_MAX > VertexCacheOptimizerUShort;
  506 +
  507 +#endif // ndef _VCACHEOPT_H_
BIN  data/icons/object_planet_medium_gas_giant.png
4 data/lang/English.txt
@@ -214,6 +214,8 @@ LOAD_A_GAME
214 214 [L] Load a game
215 215 EXIT_THIS_GAME
216 216 Exit this game
  217 +RETURN_TO_MENU
  218 + Return to menu
217 219 WINDOW_OR_FULLSCREEN
218 220 Windowed or fullscreen (restart to apply)
219 221 FULL_SCREEN
@@ -620,6 +622,8 @@ MM_START_NEW_GAME_DEBUG
620 622 New game starting on debug point
621 623 MM_LOAD_SAVED_GAME
622 624 Load a saved game
  625 +MM_SETTINGS
  626 + Settings
623 627 MM_QUIT
624 628 Quit
625 629 SCREENSHOT_FILENAME_TEMPLATE
14 data/lang/Polski.txt
@@ -28,9 +28,9 @@ VID_LINK_ESTABLISHED
28 28 VID_CONNECTING
29 29 Łączenie...
30 30 BOUGHT_1T_OF
31   - Kupiłeś 1t: %commodity.
  31 + Kupiono 1t: %commodity.
32 32 SOLD_1T_OF
33   - Sprzedałeś 1t: %commodity.
  33 + Sprzedano 1t: %commodity.
34 34 WELCOME_TO_MARKET
35 35 Stacja %station. Witamy w sklepie.
36 36 GO_BACK
@@ -214,6 +214,8 @@ LOAD_A_GAME
214 214 [L] Wczytaj grę
215 215 EXIT_THIS_GAME
216 216 Wyjdź z gry
  217 +RETURN_TO_MENU
  218 + Powrót do menu
217 219 WINDOW_OR_FULLSCREEN
218 220 Okno lub pełny ekran (wymagany restart)
219 221 FULL_SCREEN
@@ -620,6 +622,8 @@ MM_START_NEW_GAME_DEBUG
620 622 Nowa gra: rozpocznij z debug point
621 623 MM_LOAD_SAVED_GAME
622 624 Wczytaj grę
  625 +MM_SETTINGS
  626 + Opcje
623 627 MM_QUIT
624 628 Wyjdź
625 629 SCREENSHOT_FILENAME_TEMPLATE
@@ -687,7 +691,7 @@ SOCIAL_DEMOCRACY
687 691 CORPORATE_SYSTEM
688 692 System korporacyjny
689 693 MILITARY_DICTATORSHIP
690   - Dyktatora wojskowa
  694 + Dyktatura wojskowa
691 695 COMMUNIST
692 696 Komunizm
693 697 PLUTOCRATIC_DICTATORSHIP
@@ -1155,9 +1159,9 @@ NAVIGATION_TARGETS_IN_THIS_SYSTEM
1155 1159 YOU_NO_MONEY
1156 1160 Nie masz pieniędzy.
1157 1161 FINE_PAID_N_BUT_N_REMAINING
1158   - Zapłaciłeś %paid kary, lecz wciąż jesteś winien %fine.
  1162 + Zapłacono %paid kary, nadal masz %fine do uregulowania.
1159 1163 FINE_PAID_N
1160   - Przelałeś na konto policji %fine.
  1164 + Przelano na konto policji %fine.
1161 1165 SET_HYPERSPACE_DESTINATION_TO
1162 1166 "Ustawiono cel skoku na %system"
1163 1167 NO_TARGET_SELECTED
28 data/lang/Spanish.txt
@@ -214,6 +214,8 @@ LOAD_A_GAME
214 214 [L] Cargar un Juego
215 215 EXIT_THIS_GAME
216 216 Abandonar el Juego
  217 +RETURN_TO_MENU
  218 + Volver a menu
217 219 WINDOW_OR_FULLSCREEN
218 220 Ventana o Pantalla completa (Reiniciar para aplicar)
219 221 FULL_SCREEN
@@ -620,6 +622,8 @@ MM_START_NEW_GAME_DEBUG
620 622 Comenzar Juego Nuevo en punto de depuración
621 623 MM_LOAD_SAVED_GAME
622 624 Cargar un juego
  625 +MM_SETTINGS
  626 + Ajustes
623 627 MM_QUIT
624 628 Salir
625 629 SCREENSHOT_FILENAME_TEMPLATE
@@ -1200,3 +1204,27 @@ X_PASSENGER_CABINS
1200 1204 %quantity cabinas de pasajeros ocupadas
1201 1205 CABINS
1202 1206 Cabinas
  1207 +MONTH_JAN
  1208 + Ene
  1209 +MONTH_FEB
  1210 + Feb
  1211 +MONTH_MAR
  1212 + Mar
  1213 +MONTH_APR
  1214 + Abr
  1215 +MONTH_MAY
  1216 + May
  1217 +MONTH_JUN
  1218 + Jun
  1219 +MONTH_JUL
  1220 + Jul
  1221 +MONTH_AUG
  1222 + Ago
  1223 +MONTH_SEP
  1224 + Sep
  1225 +MONTH_OCT
  1226 + Oct
  1227 +MONTH_NOV
  1228 + Nov
  1229 +MONTH_DEC
  1230 + Dic
3  data/systems/00_sol.lua
@@ -51,6 +51,7 @@ local earth = CustomSystemBody:new('Earth', 'PLANET_TERRESTRIAL')
51 51 :eccentricity(f(167,10000))
52 52 :rotation_period(f(1,1))
53 53 :axial_tilt(fixed.deg2rad(f(2344,100)))
  54 + :rotational_phase_at_start(fixed.deg2rad(f(170,1)))
54 55 :height_map('earth.hmap',0)
55 56 :metallicity(f(1,2))
56 57 :volcanicity(f(1,10))
@@ -96,6 +97,8 @@ local moon = {
96 97 :inclination(math.deg2rad(5.145))
97 98 :rotation_period(f(273,10))
98 99 :axial_tilt(fixed.deg2rad(f(668,100)))
  100 + :orbital_phase_at_start(fixed.deg2rad(f(0,1)))
  101 + :rotational_phase_at_start(fixed.deg2rad(f(0,1)))
99 102 :volcanicity(f(0,1)),
100 103 {
101 104 CustomSystemBody:new('Tranquility Base', 'STARPORT_SURFACE')
1  data/ui/MainMenu.lua
@@ -38,6 +38,7 @@ local buttonDefs = {
38 38 { l.MM_START_NEW_GAME_LAVE, function () Game.StartGame(SystemPath.New(-2,1,90,0,2)) setupPlayerCobra() end },
39 39 { l.MM_START_NEW_GAME_DEBUG, function () Game.StartGame(SystemPath.New(-1,9,-22,0,5)) setupPlayerEagle() addDebugEnemy() end },
40 40 { l.MM_LOAD_SAVED_GAME, function () ui:SetInnerWidget(ui.templates.FileDialog({ title = "Load game...", path = "savefiles" })) end },
  41 + { l.MM_SETTINGS, function () print("settings") end },
41 42 { l.MM_QUIT, function () print("quit") end },
42 43 }
43 44
78 src/GameMenuView.cpp
@@ -165,8 +165,6 @@ GameMenuView::~GameMenuView()
165 165
166 166 GameMenuView::GameMenuView(): View()
167 167 {
168   - m_subview = 0;
169   -
170 168 Gui::Tabbed *tabs = new Gui::Tabbed();
171 169 Add(tabs, 0, 0);
172 170
@@ -180,22 +178,26 @@ GameMenuView::GameMenuView(): View()
180 178 m_rightRegion2->Add(l, 10, 0);
181 179
182 180 {
183   - Gui::LabelButton *b;
184 181 Gui::Box *hbox = new Gui::HBox();
185 182 hbox->SetSpacing(5.0f);
186 183 mainTab->Add(hbox, 20, 30);
187   - b = new Gui::LabelButton(new Gui::Label(Lang::SAVE_THE_GAME));
188   - b->SetShortcut(SDLK_s, KMOD_NONE);
189   - b->onClick.connect(sigc::mem_fun(this, &GameMenuView::OpenSaveDialog));
190   - hbox->PackEnd(b);
191   - b = new Gui::LabelButton(new Gui::Label(Lang::LOAD_A_GAME));
192   - b->onClick.connect(sigc::mem_fun(this, &GameMenuView::OpenLoadDialog));
193   - b->SetShortcut(SDLK_l, KMOD_NONE);
194   - hbox->PackEnd(b);
195   - b = new Gui::LabelButton(new Gui::Label(Lang::EXIT_THIS_GAME));
196   - b->onClick.connect(sigc::mem_fun(this, &GameMenuView::HideAll));
197   - b->onClick.connect(sigc::ptr_fun(&Pi::EndGame));
198   - hbox->PackEnd(b);
  184 +
  185 + m_saveButton = new Gui::LabelButton(new Gui::Label(Lang::SAVE_THE_GAME));
  186 + m_saveButton->SetShortcut(SDLK_s, KMOD_NONE);
  187 + m_saveButton->onClick.connect(sigc::mem_fun(this, &GameMenuView::OpenSaveDialog));
  188 + hbox->PackEnd(m_saveButton);
  189 + m_loadButton = new Gui::LabelButton(new Gui::Label(Lang::LOAD_A_GAME));
  190 + m_loadButton->onClick.connect(sigc::mem_fun(this, &GameMenuView::OpenLoadDialog));
  191 + m_loadButton->SetShortcut(SDLK_l, KMOD_NONE);
  192 + hbox->PackEnd(m_loadButton);
  193 + m_exitButton = new Gui::LabelButton(new Gui::Label(Lang::EXIT_THIS_GAME));
  194 + m_exitButton->onClick.connect(sigc::mem_fun(this, &GameMenuView::HideAll));
  195 + m_exitButton->onClick.connect(sigc::ptr_fun(&Pi::EndGame));
  196 + hbox->PackEnd(m_exitButton);
  197 +
  198 + m_menuButton = new Gui::LabelButton(new Gui::Label(Lang::RETURN_TO_MENU));
  199 + m_menuButton->onClick.connect(sigc::bind(sigc::ptr_fun(&Pi::SetView), static_cast<View*>(0)));
  200 + mainTab->Add(m_menuButton, 20, 30);
199 201 }
200 202
201 203 Gui::Box *vbox = new Gui::VBox();
@@ -600,8 +602,7 @@ void GameMenuView::OnToggleMouseYInvert(Gui::ToggleButton *b, bool state)
600 602 void GameMenuView::OnToggleNavTunnel(Gui::ToggleButton *b, bool state) {
601 603 Pi::config->SetInt("DisplayNavTunnel", (state ? 1 : 0));
602 604 Pi::config->Save();
603   - if (Pi::game && Pi::worldView)
604   - Pi::worldView->SetNavTunnelDisplayed(state);
  605 + Pi::SetNavTunnelDisplayed(state);
605 606 }
606 607
607 608 void GameMenuView::HideAll()
@@ -641,24 +642,31 @@ void GameMenuView::OpenLoadDialog()
641 642 }
642 643 }
643 644
644   -void GameMenuView::OnSwitchTo() {
645   - m_changedDetailLevel = false;
646   - if (m_subview) {
647   - delete m_subview;
648   - m_subview = 0;
  645 +void GameMenuView::ShowAll() {
  646 + View::ShowAll();
  647 + if (Pi::game) {
  648 + m_saveButton->Show();
  649 + m_loadButton->Show();
  650 + m_exitButton->Show();
  651 + m_menuButton->Hide();
649 652 }
650   - // don't want to switch to this view if game not running
651   - if (!Pi::game) {
652   - Pi::SetView(Pi::worldView);
653   - } else {
654   - m_planetDetailGroup->SetSelected(Pi::detail.planets);
655   - m_planetTextureGroup->SetSelected(Pi::detail.textures);
656   - m_planetFractalGroup->SetSelected(Pi::detail.fracmult);
657   - m_cityDetailGroup->SetSelected(Pi::detail.cities);
658   - m_toggleShaders->SetPressed(Pi::config->Int("DisableShaders") == 0);
659   - m_toggleFullscreen->SetPressed(Pi::config->Int("StartFullscreen") != 0);
660   - m_toggleJoystick->SetPressed(Pi::IsJoystickEnabled());
661   - m_toggleMouseYInvert->SetPressed(Pi::IsMouseYInvert());
662   - m_toggleNavTunnel->SetPressed(Pi::worldView->IsNavTunnelDisplayed());
  653 + else {
  654 + m_saveButton->Hide();
  655 + m_loadButton->Hide();
  656 + m_exitButton->Hide();
  657 + m_menuButton->Show();
663 658 }
664 659 }
  660 +
  661 +void GameMenuView::OnSwitchTo() {
  662 + m_changedDetailLevel = false;
  663 + m_planetDetailGroup->SetSelected(Pi::detail.planets);
  664 + m_planetTextureGroup->SetSelected(Pi::detail.textures);
  665 + m_planetFractalGroup->SetSelected(Pi::detail.fracmult);
  666 + m_cityDetailGroup->SetSelected(Pi::detail.cities);
  667 + m_toggleShaders->SetPressed(Pi::config->Int("DisableShaders") == 0);
  668 + m_toggleFullscreen->SetPressed(Pi::config->Int("StartFullscreen") != 0);
  669 + m_toggleJoystick->SetPressed(Pi::IsJoystickEnabled());
  670 + m_toggleMouseYInvert->SetPressed(Pi::IsMouseYInvert());
  671 + m_toggleNavTunnel->SetPressed(Pi::IsNavTunnelDisplayed());
  672 +}
6 src/GameMenuView.h
@@ -60,6 +60,7 @@ class GameMenuView: public View {
60 60 virtual void Update() {}
61 61 virtual void Draw3D() {}
62 62 virtual void OnSwitchTo();
  63 + virtual void ShowAll();
63 64 virtual void HideAll();
64 65 void OpenLoadDialog();
65 66 void OpenSaveDialog();
@@ -79,7 +80,10 @@ class GameMenuView: public View {
79 80 void OnToggleMouseYInvert(Gui::ToggleButton *b, bool state);
80 81 void OnToggleNavTunnel(Gui::ToggleButton *b, bool state);
81 82 bool m_changedDetailLevel;
82   - View *m_subview;
  83 + Gui::Button *m_saveButton;
  84 + Gui::Button *m_loadButton;
  85 + Gui::Button *m_exitButton;
  86 + Gui::Button *m_menuButton;
83 87 VolumeControl *m_masterVolume;
84 88 VolumeControl *m_sfxVolume;
85 89 VolumeControl *m_musicVolume;
177 src/GeoSphere.cpp
@@ -9,6 +9,7 @@
9 9 #include "graphics/Graphics.h"
10 10 #include "graphics/VertexArray.h"
11 11 #include "graphics/gl2/GeoSphereMaterial.h"
  12 +#include "vcacheopt/vcacheopt.h"
12 13 #include <deque>
13 14 #include <algorithm>
14 15
@@ -38,9 +39,8 @@ struct VBOVertex
38 39 };
39 40 #pragma pack()
40 41
41   -// for glDrawRangeElements
42   -static int s_loMinIdx[4], s_loMaxIdx[4];
43   -static int s_hiMinIdx[4], s_hiMaxIdx[4];
  42 +// hold the 16 possible terrain edge connections
  43 +const int NUM_INDEX_LISTS = 16;
44 44
45 45 class GeoPatchContext : public RefCounted {
46 46 public:
@@ -54,15 +54,19 @@ class GeoPatchContext : public RefCounted {
54 54 inline int IDX_VBO_LO_OFFSET(int i) const { return i*sizeof(unsigned short)*3*(edgeLen/2); }
55 55 inline int IDX_VBO_HI_OFFSET(int i) const { return (i*sizeof(unsigned short)*VBO_COUNT_HI_EDGE())+IDX_VBO_LO_OFFSET(4); }
56 56 inline int IDX_VBO_MAIN_OFFSET() const { return IDX_VBO_HI_OFFSET(4); }
  57 + inline int IDX_VBO_COUNT_ALL_IDX() const { return ((edgeLen-1)*(edgeLen-1))*2*3; }
57 58
58 59 inline int NUMVERTICES() const { return edgeLen*edgeLen; }
59 60
60 61 double frac;
61 62
62   - unsigned short *midIndices;
63   - unsigned short *loEdgeIndices[4];
64   - unsigned short *hiEdgeIndices[4];
  63 + ScopedArray<unsigned short> midIndices;
  64 + ScopedArray<unsigned short> loEdgeIndices[4];
  65 + ScopedArray<unsigned short> hiEdgeIndices[4];
65 66 GLuint indices_vbo;
  67 + GLuint indices_list[NUM_INDEX_LISTS];
  68 + GLuint indices_tri_count;
  69 + GLuint indices_tri_counts[NUM_INDEX_LISTS];
66 70 VBOVertex *vbotemp;
67 71
68 72 GeoPatchContext(int _edgeLen) : edgeLen(_edgeLen) {
@@ -79,30 +83,76 @@ class GeoPatchContext : public RefCounted {
79 83 }
80 84
81 85 void Cleanup() {
82   - delete [] midIndices;
  86 + midIndices.Reset();
83 87 for (int i=0; i<4; i++) {
84   - delete [] loEdgeIndices[i];
85   - delete [] hiEdgeIndices[i];
  88 + loEdgeIndices[i].Reset();
  89 + hiEdgeIndices[i].Reset();
86 90 }
87 91 if (indices_vbo) {
88   - glDeleteBuffersARB(1, &indices_vbo);
  92 + indices_vbo = 0;
  93 + }
  94 + for (int i=0; i<NUM_INDEX_LISTS; i++) {
  95 + if (indices_list[i]) {
  96 + glDeleteBuffersARB(1, &indices_list[i]);
  97 + }
89 98 }
90 99 delete [] vbotemp;
91 100 }
92 101
  102 + void updateIndexBufferId(const GLuint edge_hi_flags) {
  103 + assert(edge_hi_flags < GLuint(NUM_INDEX_LISTS));
  104 + indices_vbo = indices_list[edge_hi_flags];
  105 + indices_tri_count = indices_tri_counts[edge_hi_flags];
  106 + }
  107 +
  108 + int getIndices(std::vector<unsigned short> &pl, const unsigned int edge_hi_flags)
  109 + {
  110 + // calculate how many tri's there are
  111 + int tri_count = (VBO_COUNT_MID_IDX() / 3);
  112 + for( int i=0; i<4; ++i ) {
  113 + if( edge_hi_flags & (1 << i) ) {
  114 + tri_count += (VBO_COUNT_HI_EDGE() / 3);
  115 + } else {
  116 + tri_count += (VBO_COUNT_LO_EDGE() / 3);
  117 + }
  118 + }
  119 +
  120 + // pre-allocate enough space
  121 + pl.reserve(tri_count);
  122 +
  123 + // add all of the middle indices
  124 + for(int i=0; i<VBO_COUNT_MID_IDX(); ++i) {
  125 + pl.push_back(midIndices[i]);
  126 + }
  127 + // selectively add the HI or LO detail indices
  128 + for (int i=0; i<4; i++) {
  129 + if( edge_hi_flags & (1 << i) ) {
  130 + for(int j=0; j<VBO_COUNT_HI_EDGE(); ++j) {
  131 + pl.push_back(hiEdgeIndices[i][j]);
  132 + }
  133 + } else {
  134 + for(int j=0; j<VBO_COUNT_LO_EDGE(); ++j) {
  135 + pl.push_back(loEdgeIndices[i][j]);
  136 + }
  137 + }
  138 + }
  139 +
  140 + return tri_count;
  141 + }
  142 +
93 143 void Init() {
94 144 frac = 1.0 / double(edgeLen-1);
95 145
96 146 vbotemp = new VBOVertex[NUMVERTICES()];
97 147
98 148 unsigned short *idx;
99   - midIndices = new unsigned short[VBO_COUNT_MID_IDX()];
  149 + midIndices.Reset(new unsigned short[VBO_COUNT_MID_IDX()]);
100 150 for (int i=0; i<4; i++) {
101   - loEdgeIndices[i] = new unsigned short[VBO_COUNT_LO_EDGE()];
102   - hiEdgeIndices[i] = new unsigned short[VBO_COUNT_HI_EDGE()];
  151 + loEdgeIndices[i].Reset(new unsigned short[VBO_COUNT_LO_EDGE()]);
  152 + hiEdgeIndices[i].Reset(new unsigned short[VBO_COUNT_HI_EDGE()]);
103 153 }
104 154 /* also want vtx indices for tris not touching edge of patch */
105   - idx = midIndices;
  155 + idx = midIndices.Get();
106 156 for (int x=1; x<edgeLen-2; x++) {
107 157 for (int y=1; y<edgeLen-2; y++) {
108 158 idx[0] = x + edgeLen*y;
@@ -164,14 +214,14 @@ class GeoPatchContext : public RefCounted {
164 214 }
165 215 // full detail edge triangles
166 216 {
167   - idx = hiEdgeIndices[0];
  217 + idx = hiEdgeIndices[0].Get();
168 218 for (int x=0; x<edgeLen-1; x+=2) {
169 219 idx[0] = x; idx[1] = x+1; idx[2] = x+1 + edgeLen;
170 220 idx+=3;
171 221 idx[0] = x+1; idx[1] = x+2; idx[2] = x+1 + edgeLen;
172 222 idx+=3;
173 223 }
174   - idx = hiEdgeIndices[1];
  224 + idx = hiEdgeIndices[1].Get();
175 225 for (int y=0; y<edgeLen-1; y+=2) {
176 226 idx[0] = edgeLen-1 + y*edgeLen;
177 227 idx[1] = edgeLen-1 + (y+1)*edgeLen;
@@ -182,7 +232,7 @@ class GeoPatchContext : public RefCounted {
182 232 idx[2] = edgeLen-2 + (y+1)*edgeLen;
183 233 idx+=3;
184 234 }
185   - idx = hiEdgeIndices[2];
  235 + idx = hiEdgeIndices[2].Get();
186 236 for (int x=0; x<edgeLen-1; x+=2) {
187 237 idx[0] = x + (edgeLen-1)*edgeLen;
188 238 idx[1] = x+1 + (edgeLen-2)*edgeLen;
@@ -193,7 +243,7 @@ class GeoPatchContext : public RefCounted {
193 243 idx[2] = x+1 + (edgeLen-1)*edgeLen;
194 244 idx+=3;
195 245 }
196   - idx = hiEdgeIndices[3];
  246 + idx = hiEdgeIndices[3].Get();
197 247 for (int y=0; y<edgeLen-1; y+=2) {
198 248 idx[0] = y*edgeLen;
199 249 idx[1] = 1 + (y+1)*edgeLen;
@@ -209,28 +259,28 @@ class GeoPatchContext : public RefCounted {
209 259 // neighbour of equal or greater detail -- they reduce
210 260 // their edge complexity by 1 division
211 261 {
212   - idx = loEdgeIndices[0];
  262 + idx = loEdgeIndices[0].Get();
213 263 for (int x=0; x<edgeLen-2; x+=2) {
214 264 idx[0] = x;
215 265 idx[1] = x+2;
216 266 idx[2] = x+1+edgeLen;
217 267 idx += 3;
218 268 }
219   - idx = loEdgeIndices[1];
  269 + idx = loEdgeIndices[1].Get();
220 270 for (int y=0; y<edgeLen-2; y+=2) {
221 271 idx[0] = (edgeLen-1) + y*edgeLen;
222 272 idx[1] = (edgeLen-1) + (y+2)*edgeLen;
223 273 idx[2] = (edgeLen-2) + (y+1)*edgeLen;
224 274 idx += 3;
225 275 }
226   - idx = loEdgeIndices[2];
  276 + idx = loEdgeIndices[2].Get();
227 277 for (int x=0; x<edgeLen-2; x+=2) {
228 278 idx[0] = x+edgeLen*(edgeLen-1);
229 279 idx[2] = x+2+edgeLen*(edgeLen-1);
230 280 idx[1] = x+1+edgeLen*(edgeLen-2);
231 281 idx += 3;
232 282 }
233   - idx = loEdgeIndices[3];
  283 + idx = loEdgeIndices[3].Get();
234 284 for (int y=0; y<edgeLen-2; y+=2) {
235 285 idx[0] = y*edgeLen;
236 286 idx[2] = (y+2)*edgeLen;
@@ -238,41 +288,42 @@ class GeoPatchContext : public RefCounted {
238 288 idx += 3;
239 289 }
240 290 }
241   - // find min/max indices
242   - for (int i=0; i<4; i++) {
243   - s_loMinIdx[i] = s_hiMinIdx[i] = 1<<30;
244   - s_loMaxIdx[i] = s_hiMaxIdx[i] = 0;
245   - for (int j=0; j<3*(edgeLen/2); j++) {
246   - if (loEdgeIndices[i][j] < s_loMinIdx[i]) s_loMinIdx[i] = loEdgeIndices[i][j];
247   - if (loEdgeIndices[i][j] > s_loMaxIdx[i]) s_loMaxIdx[i] = loEdgeIndices[i][j];
248   - }
249   - for (int j=0; j<VBO_COUNT_HI_EDGE(); j++) {
250   - if (hiEdgeIndices[i][j] < s_hiMinIdx[i]) s_hiMinIdx[i] = hiEdgeIndices[i][j];
251   - if (hiEdgeIndices[i][j] > s_hiMaxIdx[i]) s_hiMaxIdx[i] = hiEdgeIndices[i][j];
252   - }
253   - //printf("%d:\nLo %d:%d\nHi: %d:%d\n", i, s_loMinIdx[i], s_loMaxIdx[i], s_hiMinIdx[i], s_hiMaxIdx[i]);
  291 +
  292 + // these will hold the optimised indices
  293 + std::vector<unsigned short> pl_short[NUM_INDEX_LISTS];
  294 + // populate the N indices lists from the arrays built during InitTerrainIndices()
  295 + for( int i=0; i<NUM_INDEX_LISTS; ++i ) {
  296 + const unsigned int edge_hi_flags = i;
  297 + indices_tri_counts[i] = getIndices(pl_short[i], edge_hi_flags);
254 298 }
255 299
256   - glGenBuffersARB(1, &indices_vbo);
257   - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, indices_vbo);
258   - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, IDX_VBO_MAIN_OFFSET() + sizeof(unsigned short)*VBO_COUNT_MID_IDX(), 0, GL_STATIC_DRAW);
259   - for (int i=0; i<4; i++) {
260   - glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER,
261   - IDX_VBO_LO_OFFSET(i),
262   - sizeof(unsigned short)*3*(edgeLen/2),
263   - loEdgeIndices[i]);
  300 + // iterate over each index list and optimize it
  301 + for( int i=0; i<NUM_INDEX_LISTS; ++i ) {
  302 + int tri_count = indices_tri_counts[i];
  303 + VertexCacheOptimizerUShort vco;
  304 + VertexCacheOptimizerUShort::Result res = vco.Optimize(&pl_short[i][0], tri_count);
  305 + assert(0 == res);
264 306 }
265   - for (int i=0; i<4; i++) {
266   - glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER,
267   - IDX_VBO_HI_OFFSET(i),
268   - sizeof(unsigned short)*VBO_COUNT_HI_EDGE(),
269   - hiEdgeIndices[i]);
  307 +
  308 + // everything should be hunky-dory for setting up as OpenGL index buffers now.
  309 + for( int i=0; i<NUM_INDEX_LISTS; ++i ) {
  310 + glGenBuffersARB(1, &indices_list[i]);
  311 + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, indices_list[i]);
  312 + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*indices_tri_counts[i]*3, &(pl_short[i][0]), GL_STATIC_DRAW);
  313 + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
  314 + }
  315 +
  316 + // default it to the last entry which uses the hi-res borders
  317 + indices_vbo = indices_list[NUM_INDEX_LISTS-1];
  318 + indices_tri_count = indices_tri_counts[NUM_INDEX_LISTS-1];
  319 +
  320 + if (midIndices) {
  321 + midIndices.Reset();
  322 + for (int i=0; i<4; i++) {
  323 + loEdgeIndices[i].Reset();
  324 + hiEdgeIndices[i].Reset();
  325 + }