Introduced VertexArray object to handle terrain vertex data

This will be used later with opengl vertex arrays
This commit is contained in:
Michaël Lemaire 2013-12-23 17:24:05 +01:00 committed by Michael Lemaire
parent ac5c0fd584
commit f97823604e
8 changed files with 291 additions and 21 deletions

View file

@ -8,6 +8,7 @@
#include "CameraDefinition.h" #include "CameraDefinition.h"
#include "OpenGLRenderer.h" #include "OpenGLRenderer.h"
#include "TerrainRenderer.h" #include "TerrainRenderer.h"
#include "VertexArray.h"
ExplorerChunkTerrain::ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height): ExplorerChunkTerrain::ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height):
_renderer(renderer) _renderer(renderer)
@ -33,8 +34,11 @@ ExplorerChunkTerrain::ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, d
_water_height = water_height; _water_height = water_height;
_overwater = false; _overwater = false;
_tessellation_max_size = 32; tessellation_count = 33;
_tessellation = new double[(_tessellation_max_size + 1) * (_tessellation_max_size + 1)]; tessellated = new VertexArray<TerrainVertex>();
tessellated->setGridSize(tessellation_count);
tessellated->setAutoGridIndices(tessellation_count);
_tessellation_max_size = tessellation_count - 1;
_tessellation_current_size = 0; _tessellation_current_size = 0;
_tessellation_step = _size / (double) _tessellation_max_size; _tessellation_step = _size / (double) _tessellation_max_size;
@ -49,7 +53,7 @@ ExplorerChunkTerrain::~ExplorerChunkTerrain()
delete _color_profile; delete _color_profile;
delete _texture; delete _texture;
delete texture; delete texture;
delete [] _tessellation; delete tessellated;
_lock_data.unlock(); _lock_data.unlock();
} }
@ -116,24 +120,39 @@ bool ExplorerChunkTerrain::onMaintainEvent()
int new_tessellation_size = _tessellation_current_size ? _tessellation_current_size * 4 : 2; 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 old_tessellation_inc = _tessellation_current_size ? _tessellation_max_size / _tessellation_current_size : 1;
int new_tessellation_inc = _tessellation_max_size / new_tessellation_size; 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 j = 0; j <= _tessellation_max_size; j += new_tessellation_inc)
{ {
for (int i = 0; i <= _tessellation_max_size; i += 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) 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) if (height >= _water_height)
{ {
_overwater = true; _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(); _lock_data.lock();
_tessellation_current_size = new_tessellation_size; _tessellation_current_size = new_tessellation_size;
tessellated->setAutoGridIndices(tessellation_count, new_tessellation_inc);
_lock_data.unlock(); _lock_data.unlock();
if (_tessellation_current_size < 4 && _tessellation_current_size < _tessellation_max_size) if (_tessellation_current_size < 4 && _tessellation_current_size < _tessellation_max_size)
@ -216,7 +235,6 @@ void ExplorerChunkTerrain::render(OpenGLFunctions* functions)
{ {
_lock_data.lock(); _lock_data.lock();
int tessellation_size = _tessellation_current_size; int tessellation_size = _tessellation_current_size;
double tsize = 1.0 / (double) _tessellation_max_size;
_lock_data.unlock(); _lock_data.unlock();
if (tessellation_size <= 1 or not _overwater) if (tessellation_size <= 1 or not _overwater)
@ -224,19 +242,17 @@ void ExplorerChunkTerrain::render(OpenGLFunctions* functions)
return; return;
} }
int tessellation_inc = _tessellation_max_size / (double) tessellation_size; _lock_data.lock(); // TEMP
for (int j = 0; j < _tessellation_max_size; j += tessellation_inc) int n = tessellated->getIndexCount();
functions->glBegin(GL_TRIANGLES);
for (int i = 0; i < n; i++)
{ {
functions->glBegin(GL_QUAD_STRIP); TerrainVertex v = tessellated->getVertexByIndex(i);
for (int i = 0; i <= _tessellation_max_size; i += tessellation_inc) functions->glTexCoord2d(v.uv[0], v.uv[1]);
{ functions->glVertex3d(v.location[0], v.location[1], v.location[2]);
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();
} }
functions->glEnd();
_lock_data.unlock(); // TEMP
} }
} }

View file

@ -12,6 +12,13 @@ namespace opengl {
class OPENGLSHARED_EXPORT ExplorerChunkTerrain class OPENGLSHARED_EXPORT ExplorerChunkTerrain
{ {
public:
typedef struct
{
float location[3];
float uv[2];
} TerrainVertex;
public: public:
ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height); ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height);
~ExplorerChunkTerrain(); ~ExplorerChunkTerrain();
@ -41,7 +48,8 @@ private:
double _water_height; double _water_height;
bool _overwater; bool _overwater;
double* _tessellation; int tessellation_count;
VertexArray<TerrainVertex> *tessellated;
int _tessellation_max_size; int _tessellation_max_size;
int _tessellation_current_size; int _tessellation_current_size;
double _tessellation_step; double _tessellation_step;

View file

@ -0,0 +1 @@
#include "VertexArray.h"

View file

@ -0,0 +1,135 @@
#ifndef VERTEXARRAY_H
#define VERTEXARRAY_H
#include "opengl_global.h"
#include <cassert>
namespace paysages {
namespace opengl {
/*!
* Wrapper for OpenGL vertex arrays.
*/
template <typename Vertex> 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

View file

@ -23,7 +23,8 @@ SOURCES += \
OpenGLWater.cpp \ OpenGLWater.cpp \
OpenGLSharedState.cpp \ OpenGLSharedState.cpp \
OpenGLVariable.cpp \ OpenGLVariable.cpp \
OpenGLTerrain.cpp OpenGLTerrain.cpp \
VertexArray.cpp
HEADERS +=\ HEADERS +=\
opengl_global.h \ opengl_global.h \
@ -36,7 +37,8 @@ HEADERS +=\
OpenGLWater.h \ OpenGLWater.h \
OpenGLSharedState.h \ OpenGLSharedState.h \
OpenGLVariable.h \ OpenGLVariable.h \
OpenGLTerrain.h OpenGLTerrain.h \
VertexArray.h
unix:!symbian { unix:!symbian {
maemo5 { maemo5 {

View file

@ -22,6 +22,7 @@ namespace opengl {
class OpenGLWater; class OpenGLWater;
class OpenGLTerrain; class OpenGLTerrain;
class ExplorerChunkTerrain; class ExplorerChunkTerrain;
template <typename Vertex> class VertexArray;
} }
} }
using namespace paysages::opengl; using namespace paysages::opengl;

View file

@ -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<TestVertex> 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<TestVertex> 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<TestVertex> 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));
}

View file

@ -17,7 +17,8 @@ SOURCES += main.cpp \
Bruneton_Test.cpp \ Bruneton_Test.cpp \
Camera_Test.cpp \ Camera_Test.cpp \
Clouds_Test.cpp \ Clouds_Test.cpp \
FluidMediumManager_Test.cpp FluidMediumManager_Test.cpp \
VertexArray_Test.cpp
HEADERS += \ HEADERS += \
BaseTestCase.h 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 else:unix: LIBS += -L$$OUT_PWD/../render/software/ -lpaysages_render_software
INCLUDEPATH += $$PWD/../render/software INCLUDEPATH += $$PWD/../render/software
DEPENDPATH += $$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