From f97823604e959370d9908547c1ab371a424b0cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Mon, 23 Dec 2013 17:24:05 +0100 Subject: [PATCH] Introduced VertexArray object to handle terrain vertex data This will be used later with opengl vertex arrays --- src/render/opengl/ExplorerChunkTerrain.cpp | 50 +++++--- src/render/opengl/ExplorerChunkTerrain.h | 10 +- src/render/opengl/VertexArray.cpp | 1 + src/render/opengl/VertexArray.h | 135 +++++++++++++++++++++ src/render/opengl/opengl.pro | 6 +- src/render/opengl/opengl_global.h | 1 + src/tests/VertexArray_Test.cpp | 100 +++++++++++++++ src/tests/tests.pro | 9 +- 8 files changed, 291 insertions(+), 21 deletions(-) create mode 100644 src/render/opengl/VertexArray.cpp create mode 100644 src/render/opengl/VertexArray.h create mode 100644 src/tests/VertexArray_Test.cpp diff --git a/src/render/opengl/ExplorerChunkTerrain.cpp b/src/render/opengl/ExplorerChunkTerrain.cpp index 4fd3acb..5d5fd90 100644 --- a/src/render/opengl/ExplorerChunkTerrain.cpp +++ b/src/render/opengl/ExplorerChunkTerrain.cpp @@ -8,6 +8,7 @@ #include "CameraDefinition.h" #include "OpenGLRenderer.h" #include "TerrainRenderer.h" +#include "VertexArray.h" ExplorerChunkTerrain::ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height): _renderer(renderer) @@ -33,8 +34,11 @@ ExplorerChunkTerrain::ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, d _water_height = water_height; _overwater = false; - _tessellation_max_size = 32; - _tessellation = new double[(_tessellation_max_size + 1) * (_tessellation_max_size + 1)]; + tessellation_count = 33; + tessellated = new VertexArray(); + tessellated->setGridSize(tessellation_count); + tessellated->setAutoGridIndices(tessellation_count); + _tessellation_max_size = tessellation_count - 1; _tessellation_current_size = 0; _tessellation_step = _size / (double) _tessellation_max_size; @@ -49,7 +53,7 @@ ExplorerChunkTerrain::~ExplorerChunkTerrain() delete _color_profile; delete _texture; delete texture; - delete [] _tessellation; + delete tessellated; _lock_data.unlock(); } @@ -116,24 +120,39 @@ bool ExplorerChunkTerrain::onMaintainEvent() int new_tessellation_size = _tessellation_current_size ? _tessellation_current_size * 4 : 2; int old_tessellation_inc = _tessellation_current_size ? _tessellation_max_size / _tessellation_current_size : 1; int new_tessellation_inc = _tessellation_max_size / new_tessellation_size; + float internal_step = 1.0f / (float)_tessellation_max_size; for (int j = 0; j <= _tessellation_max_size; j += new_tessellation_inc) { for (int i = 0; i <= _tessellation_max_size; i += new_tessellation_inc) { if (_tessellation_current_size == 0 || i % old_tessellation_inc != 0 || j % old_tessellation_inc != 0) { - double height = _renderer->getTerrainRenderer()->getHeight(_startx + _tessellation_step * (double) i, _startz + _tessellation_step * (double) j, 1); + double x = _startx + _tessellation_step * (float)i; + double z = _startz + _tessellation_step * (float)j; + + double height = _renderer->getTerrainRenderer()->getHeight(x, z, 1); if (height >= _water_height) { _overwater = true; } - _tessellation[j * (_tessellation_max_size + 1) + i] = height; + + TerrainVertex v; + + v.uv[0] = internal_step * (float)i; + v.uv[1] = internal_step * (float)j; + + v.location[0] = x; + v.location[1] = height; + v.location[2] = z; + + tessellated->setGridVertex(tessellation_count, i, j, v); } } } _lock_data.lock(); _tessellation_current_size = new_tessellation_size; + tessellated->setAutoGridIndices(tessellation_count, new_tessellation_inc); _lock_data.unlock(); if (_tessellation_current_size < 4 && _tessellation_current_size < _tessellation_max_size) @@ -216,7 +235,6 @@ void ExplorerChunkTerrain::render(OpenGLFunctions* functions) { _lock_data.lock(); int tessellation_size = _tessellation_current_size; - double tsize = 1.0 / (double) _tessellation_max_size; _lock_data.unlock(); if (tessellation_size <= 1 or not _overwater) @@ -224,19 +242,17 @@ void ExplorerChunkTerrain::render(OpenGLFunctions* functions) return; } - int tessellation_inc = _tessellation_max_size / (double) tessellation_size; - for (int j = 0; j < _tessellation_max_size; j += tessellation_inc) + _lock_data.lock(); // TEMP + int n = tessellated->getIndexCount(); + functions->glBegin(GL_TRIANGLES); + for (int i = 0; i < n; i++) { - functions->glBegin(GL_QUAD_STRIP); - for (int i = 0; i <= _tessellation_max_size; i += tessellation_inc) - { - functions->glTexCoord2d(tsize * (double) i, tsize * (double) j); - functions->glVertex3d(_startx + _tessellation_step * (double) i, _tessellation[j * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double) j); - functions->glTexCoord2d(tsize * (double) i, tsize * (double) (j + tessellation_inc)); - functions->glVertex3d(_startx + _tessellation_step * (double) i, _tessellation[(j + tessellation_inc) * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double) (j + tessellation_inc)); - } - functions->glEnd(); + TerrainVertex v = tessellated->getVertexByIndex(i); + functions->glTexCoord2d(v.uv[0], v.uv[1]); + functions->glVertex3d(v.location[0], v.location[1], v.location[2]); } + functions->glEnd(); + _lock_data.unlock(); // TEMP } } diff --git a/src/render/opengl/ExplorerChunkTerrain.h b/src/render/opengl/ExplorerChunkTerrain.h index 2c7c911..1de8355 100644 --- a/src/render/opengl/ExplorerChunkTerrain.h +++ b/src/render/opengl/ExplorerChunkTerrain.h @@ -12,6 +12,13 @@ namespace opengl { class OPENGLSHARED_EXPORT ExplorerChunkTerrain { +public: + typedef struct + { + float location[3]; + float uv[2]; + } TerrainVertex; + public: ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height); ~ExplorerChunkTerrain(); @@ -41,7 +48,8 @@ private: double _water_height; bool _overwater; - double* _tessellation; + int tessellation_count; + VertexArray *tessellated; int _tessellation_max_size; int _tessellation_current_size; double _tessellation_step; diff --git a/src/render/opengl/VertexArray.cpp b/src/render/opengl/VertexArray.cpp new file mode 100644 index 0000000..96d7d79 --- /dev/null +++ b/src/render/opengl/VertexArray.cpp @@ -0,0 +1 @@ +#include "VertexArray.h" diff --git a/src/render/opengl/VertexArray.h b/src/render/opengl/VertexArray.h new file mode 100644 index 0000000..ffc289f --- /dev/null +++ b/src/render/opengl/VertexArray.h @@ -0,0 +1,135 @@ +#ifndef VERTEXARRAY_H +#define VERTEXARRAY_H + +#include "opengl_global.h" + +#include + +namespace paysages { +namespace opengl { + +/*! + * Wrapper for OpenGL vertex arrays. + */ +template class VertexArray +{ +public: + VertexArray() + { + ready = false; + changed = false; + vertex_count = 1; + vertices = new Vertex[1]; + index_count = 1; + indices = new int[1]; + } + + ~VertexArray() + { + delete[] vertices; + delete[] indices; + } + + inline int getVertexCount() {return vertex_count;} + inline int getIndexCount() {return index_count;} + inline bool isReady() {return ready;} + inline bool isChanged() {return changed;} + + void setVertexCount(int count) + { + assert(count > 0 and count <= 16384); + + delete[] vertices; + vertices = new Vertex[count]; + + vertex_count = count; + } + + void setGridSize(int edge_vertex_count) + { + assert(edge_vertex_count >= 2); + + setVertexCount(edge_vertex_count * edge_vertex_count); + } + + void setVertex(int position, const Vertex &vertex) + { + assert(position >= 0 and position < vertex_count); + + vertices[position] = vertex; + + changed = true; + } + + void setGridVertex(int edge_vertex_count, int x, int y, const Vertex &vertex) + { + setVertex(y * edge_vertex_count + x, vertex); + } + + void setAutoGridIndices(int edge_vertex_count, int stride=1) + { + assert(stride >= 1); + + delete[] indices; + int cell_count = edge_vertex_count - 1; + + index_count = (cell_count / stride) * (cell_count / stride) * 6; + indices = new int[index_count]; + + int idx = 0; + for (int y = 0; y < cell_count; y += stride) + { + for (int x = 0; x < cell_count; x += stride) + { + int base = y * edge_vertex_count + x; + indices[idx++] = base; + indices[idx++] = base + edge_vertex_count * stride; + indices[idx++] = base + stride; + indices[idx++] = base + stride; + indices[idx++] = base + edge_vertex_count * stride; + indices[idx++] = base + edge_vertex_count * stride + stride; + } + } + } + + Vertex getVertex(int position) + { + assert(position >= 0 and position < vertex_count); + + return vertices[position]; + } + + Vertex getVertexByIndex(int index) + { + assert(index >= 0 and index < index_count); + + return getVertex(indices[index]); + } + + Vertex getGridVertex(int edge_vertex_count, int x, int y) + { + return getVertex(y * edge_vertex_count + x); + } + + int getIndex(int position) + { + assert(position >= 0 and position < index_count); + + return indices[position]; + } + +private: + bool ready; + bool changed; + + int vertex_count; + Vertex* vertices; + + int index_count; + int* indices; +}; + +} +} + +#endif // VERTEXARRAY_H diff --git a/src/render/opengl/opengl.pro b/src/render/opengl/opengl.pro index fce63a4..47594ae 100644 --- a/src/render/opengl/opengl.pro +++ b/src/render/opengl/opengl.pro @@ -23,7 +23,8 @@ SOURCES += \ OpenGLWater.cpp \ OpenGLSharedState.cpp \ OpenGLVariable.cpp \ - OpenGLTerrain.cpp + OpenGLTerrain.cpp \ + VertexArray.cpp HEADERS +=\ opengl_global.h \ @@ -36,7 +37,8 @@ HEADERS +=\ OpenGLWater.h \ OpenGLSharedState.h \ OpenGLVariable.h \ - OpenGLTerrain.h + OpenGLTerrain.h \ + VertexArray.h unix:!symbian { maemo5 { diff --git a/src/render/opengl/opengl_global.h b/src/render/opengl/opengl_global.h index 9496f54..1150545 100644 --- a/src/render/opengl/opengl_global.h +++ b/src/render/opengl/opengl_global.h @@ -22,6 +22,7 @@ namespace opengl { class OpenGLWater; class OpenGLTerrain; class ExplorerChunkTerrain; + template class VertexArray; } } using namespace paysages::opengl; diff --git a/src/tests/VertexArray_Test.cpp b/src/tests/VertexArray_Test.cpp new file mode 100644 index 0000000..1b29e6d --- /dev/null +++ b/src/tests/VertexArray_Test.cpp @@ -0,0 +1,100 @@ +#include "BaseTestCase.h" + +#include "VertexArray.h" + +class TestVertex +{ +public: + float uv[2]; + int loc[3]; + + bool operator==(const TestVertex &other) const + { + return other.uv[0] == uv[0] + and other.uv[1] == uv[1] + and other.loc[0] == loc[0] + and other.loc[1] == loc[1] + and other.loc[2] == loc[2]; + } +}; + +TEST(VertexArray, grid) +{ + VertexArray array; + + array.setGridSize(3); + + ASSERT_EQ(9, array.getVertexCount()); + + TestVertex v1 = {{0.1, 0.2}, {1, 2, 3}}; + TestVertex vgot; + + array.setGridVertex(3, 1, 2, v1); + vgot = array.getGridVertex(3, 1, 2); + EXPECT_EQ(v1, vgot); + vgot = array.getVertex(7); + EXPECT_EQ(v1, vgot); +} + +TEST(VertexArray, gridIndices) +{ + VertexArray array; + + array.setGridSize(3); + + array.setAutoGridIndices(3); + ASSERT_EQ(24, array.getIndexCount()); + + EXPECT_EQ(0, array.getIndex(0)); + EXPECT_EQ(3, array.getIndex(1)); + EXPECT_EQ(1, array.getIndex(2)); + + EXPECT_EQ(1, array.getIndex(3)); + EXPECT_EQ(3, array.getIndex(4)); + EXPECT_EQ(4, array.getIndex(5)); + + EXPECT_EQ(1, array.getIndex(6)); + EXPECT_EQ(4, array.getIndex(7)); + EXPECT_EQ(2, array.getIndex(8)); + + EXPECT_EQ(2, array.getIndex(9)); + EXPECT_EQ(4, array.getIndex(10)); + EXPECT_EQ(5, array.getIndex(11)); + + EXPECT_EQ(3, array.getIndex(12)); + EXPECT_EQ(6, array.getIndex(13)); + EXPECT_EQ(4, array.getIndex(14)); +} + +TEST(VertexArray, gridIndicesStride) +{ + VertexArray array; + + array.setGridSize(5); + + array.setAutoGridIndices(5, 1); + ASSERT_EQ(96, array.getIndexCount()); + + array.setAutoGridIndices(5, 2); + ASSERT_EQ(24, array.getIndexCount()); + + EXPECT_EQ(0, array.getIndex(0)); + EXPECT_EQ(10, array.getIndex(1)); + EXPECT_EQ(2, array.getIndex(2)); + + EXPECT_EQ(2, array.getIndex(3)); + EXPECT_EQ(10, array.getIndex(4)); + EXPECT_EQ(12, array.getIndex(5)); + + EXPECT_EQ(2, array.getIndex(6)); + EXPECT_EQ(12, array.getIndex(7)); + EXPECT_EQ(4, array.getIndex(8)); + + EXPECT_EQ(4, array.getIndex(9)); + EXPECT_EQ(12, array.getIndex(10)); + EXPECT_EQ(14, array.getIndex(11)); + + EXPECT_EQ(10, array.getIndex(12)); + EXPECT_EQ(20, array.getIndex(13)); + EXPECT_EQ(12, array.getIndex(14)); +} diff --git a/src/tests/tests.pro b/src/tests/tests.pro index 3fc8679..2e638f3 100644 --- a/src/tests/tests.pro +++ b/src/tests/tests.pro @@ -17,7 +17,8 @@ SOURCES += main.cpp \ Bruneton_Test.cpp \ Camera_Test.cpp \ Clouds_Test.cpp \ - FluidMediumManager_Test.cpp + FluidMediumManager_Test.cpp \ + VertexArray_Test.cpp HEADERS += \ BaseTestCase.h @@ -51,3 +52,9 @@ else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../render/software/ else:unix: LIBS += -L$$OUT_PWD/../render/software/ -lpaysages_render_software INCLUDEPATH += $$PWD/../render/software DEPENDPATH += $$PWD/../render/software + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../render/opengl/release/ -lpaysages_render_opengl +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../render/opengl/debug/ -lpaysages_render_opengl +else:unix: LIBS += -L$$OUT_PWD/../render/opengl/ -lpaysages_render_opengl +INCLUDEPATH += $$PWD/../render/opengl +DEPENDPATH += $$PWD/../render/opengl