1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-03 00:59:47 +02:00

Added TextureAtlas, broke rendering

This commit is contained in:
Daniel Evans 2013-09-11 11:10:42 +00:00
parent 2796ba5e25
commit 206b3979e8
11 changed files with 238 additions and 26 deletions

View File

@ -9,3 +9,5 @@ add_subdirectory(viewer)
add_subdirectory(framework2)
add_subdirectory(analyzer)
add_subdirectory(tests)

View File

@ -422,9 +422,6 @@ void GTARenderer::renderNamedFrame(Model* model, const glm::mat4 &matrix, const
culled++;
continue;
}
else {
rendered++;
}
renderGeometry(model, g, matrix);
break;
@ -452,8 +449,8 @@ void GTARenderer::renderGeometry(Model* model, size_t g, const glm::mat4& modelM
glEnableVertexAttribArray(normalAttrib);
glEnableVertexAttribArray(colourAttrib);
for(size_t sg = 0; sg < model->geometries[g].subgeom.size(); ++sg)
{
for(size_t sg = 0; sg <1 && sg < model->geometries[g].subgeom.size(); ++sg)
{
if (model->geometries[g].materials.size() > model->geometries[g].subgeom[sg].material) {
Model::Material& mat = model->geometries[g].materials[model->geometries[g].subgeom[sg].material];
@ -487,25 +484,24 @@ void GTARenderer::renderGeometry(Model* model, size_t g, const glm::mat4& modelM
glUniform1f(uniMatAmbient, mat.ambientIntensity);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->geometries[g].subgeom[sg].EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->geometries[g].EBO);
glDrawElements((model->geometries[g].facetype == Model::Triangles ? GL_TRIANGLES : GL_TRIANGLE_STRIP), model->geometries[g].subgeom[sg].indices.size(), GL_UNSIGNED_INT, NULL);
rendered++;
glDrawElements((model->geometries[g].facetype == Model::Triangles ? GL_TRIANGLES : GL_TRIANGLE_STRIP), model->geometries[g].indicesCount, GL_UNSIGNED_INT, NULL);
}
}
void GTARenderer::renderModel(Model* model, const glm::mat4& modelMatrix, GTAObject* object, Animator *animator)
{
for (size_t a = 0; a < model->atomics.size(); a++)
for (size_t a = 0; a < model->atomics.size(); a++)
{
size_t g = model->atomics[a].geometry;
RW::BSGeometryBounds& bounds = model->geometries[g].geometryBounds;
if(! camera.frustum.intersects(bounds.center + glm::vec3(modelMatrix[3]), bounds.radius)) {
culled++;
continue;
}
else {
rendered++;
}
}
int32_t fi = model->atomics[a].frame;
if( object && object->type() == GTAObject::Vehicle ) {

View File

@ -183,7 +183,7 @@ Model* LoaderDFF::loadFromMemory(char *data)
{
auto meshplg = extsec.readSubStructure<RW::BSBinMeshPLG>(0);
geometryStruct.subgeom.resize(meshplg.numsplits);
geometryStruct.facetype = static_cast<Model::FaceType>(meshplg.facetype);
geometryStruct.facetype = static_cast<Model::FaceType>(meshplg.facetype);
size_t meshplgI = sizeof(RW::BSBinMeshPLG);
for(size_t i = 0; i < meshplg.numsplits; ++i)
{
@ -230,10 +230,13 @@ Model* LoaderDFF::loadFromMemory(char *data)
// OpenGL buffer stuff
glGenBuffers(1, &geometryStruct.VBO);
glGenBuffers(1, &geometryStruct.EBO);
size_t Ecount = 0;
for(size_t i = 0; i < geometryStruct.subgeom.size(); ++i)
{
glGenBuffers(1, &(geometryStruct.subgeom[i].EBO));
Ecount += geometryStruct.subgeom[i].indices.size();
//glGenBuffers(1, &(geometryStruct.subgeom[i].EBO));
}
geometryStruct.indicesCount = Ecount;
size_t buffsize = (geometryStruct.vertices.size() * sizeof(float) * 3)
+ (geometryStruct.texcoords.size() * sizeof(float) * 2)
@ -293,23 +296,33 @@ Model* LoaderDFF::loadFromMemory(char *data)
indicies[i + 2] = tri.third;
i += 3;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometryStruct.EBO);
/*glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometryStruct.EBO);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
sizeof(indicies),
indicies,
GL_STATIC_DRAW
);
for(size_t i = 0; i < geometryStruct.subgeom.size(); ++i)
);*/
// Allocate complete EBO buffer.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometryStruct.EBO);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
sizeof(uint32_t) * geometryStruct.indicesCount,
nullptr,
GL_STATIC_DRAW);
// Upload each subgeometry chunk.
size_t subOffset = 0;
for(size_t i = 0; i < geometryStruct.subgeom.size(); ++i)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometryStruct.subgeom[i].EBO);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
sizeof(uint32_t) * geometryStruct.subgeom[i].indices.size(),
&(geometryStruct.subgeom[i].indices[0]),
GL_STATIC_DRAW
);
glBufferSubData(
GL_ELEMENT_ARRAY_BUFFER,
subOffset,
sizeof(uint32_t) * geometryStruct.subgeom[i].indices.size(),
&(geometryStruct.subgeom[i].indices[0]));
subOffset += sizeof(uint32_t) * geometryStruct.subgeom[i].indices.size();
}
geometryStruct.clumpNum = clumpID;

View File

@ -0,0 +1,58 @@
#include <renderwure/render/TextureAtlas.hpp>
#include <algorithm>
TextureAtlas::TextureAtlas(size_t w, size_t h)
: width(w), height(h), textureName(0), X(0), Y(0), rowHeight(0)
{
glGenTextures(1, &textureName);
glBindTexture(GL_TEXTURE_2D, textureName);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA,
width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, nullptr
);
}
TextureAtlas::~TextureAtlas()
{
glDeleteTextures(1, &textureName);
}
void TextureAtlas::packTexture(uint8_t *data, size_t w, size_t h, float &s, float &t, float &sX, float &sY)
{
// Ignore null pointer data for testing purposes.
if( data != nullptr )
{
glBindTexture(GL_TEXTURE_2D, textureName);
glTexSubImage2D(GL_TEXTURE_2D, 0, X, Y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
s = X/(float)width;
t = Y/(float)height;
sX = w/(float)width;
sY = h/(float)height;
rowHeight = std::max(rowHeight, h);
X += w;
if( X >= width ) {
Y += rowHeight;
X = rowHeight = 0;
}
}
bool TextureAtlas::canPack(size_t *w, size_t *h, size_t n) const
{
size_t rwHeight = rowHeight;
size_t lX = X, lY = Y;
for(size_t i = 0; i < n; ++i) {
lX += (w[i]);
rwHeight = std::max(rwHeight, h[i]);
if(lX >= width) {
lY += rwHeight;
lX = rwHeight = 0;
}
}
if(lX <= width && lY <= height) {
return true;
}
return false;
}

View File

@ -37,6 +37,8 @@ bool TextureLoader::loadFromMemory(char *data)
auto texNative = rootSection.readStructure<RW::BSTextureNative>();
GLuint texture = 0;
std::cout << texNative.width << "x" << texNative.height << std::endl;
if(texNative.platform != 8)
{

View File

@ -35,7 +35,7 @@ public:
};
struct SubGeometry {
GLuint EBO;
//GLuint EBO;
size_t material;
std::vector<uint32_t> indices;
};
@ -56,6 +56,7 @@ public:
std::vector<glm::vec4> colours;
std::vector<RW::BSTVector3> vertices;
std::vector<RW::BSTVector3> normals;
uint32_t indicesCount;
std::vector<Material> materials;
std::vector<SubGeometry> subgeom;

View File

@ -0,0 +1,43 @@
#pragma once
#ifndef _TEXTURE_ATLAS_HPP_
#define _TEXTURE_ATLAS_HPP_
#include <GL/gl.h>
class TextureAtlas
{
/**
* @brief width Width of the backing texture.
*/
size_t width;
/**
* @brief height Height of the backing texture.
*/
size_t height;
GLuint textureName;
size_t X; // X edge of latest texture.
size_t Y; // Y of current row.
size_t rowHeight; // Maximum texture height for the current row.
public:
TextureAtlas(size_t w, size_t h);
~TextureAtlas();
void packTexture(uint8_t* data, size_t w, size_t h, float& s, float& t, float& sX, float& sY);
/**
* @brief canPack Returns true if enough space remains in the atlas
* for the given texture sizes to be packed.
* @param w
* @param h
* @param n
* @return True on success, false on failure.
*/
bool canPack(size_t* w, size_t* h, size_t n) const;
};
#endif

16
tests/CMakeLists.txt Normal file
View File

@ -0,0 +1,16 @@
FILE(GLOB TEST_SOURCES "*.cpp")
ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK)
add_executable(run_tests ${TEST_SOURCES})
include_directories(include)
include_directories(${PROJECT_SOURCE_DIR}/engine/include)
find_package(Boost COMPONENTS unit_test_framework REQUIRED)
include_directories(../framework2/include)
target_link_libraries(run_tests renderware sfml-window sfml-system GL ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
add_test(UnitTests run_tests)

21
tests/main.cpp Normal file
View File

@ -0,0 +1,21 @@
#define BOOST_TEST_MODULE gtfw
#include <boost/test/included/unit_test.hpp>
#include <SFML/Window.hpp>
// Many tests require OpenGL be functional, seems like a reasonable solution.
class GlobalFixture
{
public:
sf::Window wnd;
GlobalFixture() {
wnd.create(sf::VideoMode(640, 360), "Testing");
}
~GlobalFixture() {
wnd.close();
}
};
BOOST_GLOBAL_FIXTURE(GlobalFixture)

56
tests/test_atlas.cpp Normal file
View File

@ -0,0 +1,56 @@
#include <boost/test/unit_test.hpp>
#include <renderwure/render/TextureAtlas.hpp>
BOOST_AUTO_TEST_SUITE(TextureAtlasTests)
BOOST_AUTO_TEST_CASE(atlas_fill_test)
{
TextureAtlas atlas(16, 16);
size_t dim = 16;
BOOST_CHECK( atlas.canPack(&dim, &dim, 1) );
float s, t, w, h;
atlas.packTexture(nullptr, dim, dim, s, t, w, h);
BOOST_CHECK( s == 0.f );
BOOST_CHECK( t == 0.f );
BOOST_CHECK( w == 1.f );
BOOST_CHECK( h == 1.f );
BOOST_CHECK( atlas.canPack(&dim, &dim, 1) == false );
}
BOOST_AUTO_TEST_CASE(atlas_pack_test)
{
TextureAtlas atlas(4, 4);
size_t dim = 1;
uint8_t pixels[] = { 0xFF, 0x00, 0x00, 0xFF,
0x00, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0xFF };
float s, t, w, h;
atlas.packTexture(pixels+0, dim, dim, s, t, w, h);
BOOST_CHECK( s == 0.f && t == 0.f && w == 0.25f && h == 0.25f );
atlas.packTexture(pixels+4, dim, dim, s, t, w, h);
BOOST_CHECK( s == 0.25f && t == 0.f && w == 0.25f && h == 0.25f );
atlas.packTexture(pixels+8, dim, dim, s, t, w, h);
BOOST_CHECK( s == 0.5f && t == 0.f && w == 0.25f && h == 0.25f );
atlas.packTexture(pixels+12, dim, dim, s, t, w, h);
BOOST_CHECK( s == 0.75f && t == 0.f && w == 0.25f && h == 0.25f );
BOOST_CHECK( atlas.canPack(&dim, &dim, 1) == true );
uint8_t outPixels[4*4*4];
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, outPixels);
for(size_t p = 0; p < 16; ++p) {
BOOST_CHECK(outPixels[p] == pixels[p]);
}
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -121,6 +121,10 @@ void init(std::string gtapath)
debugDrawer->setShaderProgram(gta->renderer.worldProgram);
debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
gta->dynamicsWorld->setDebugDrawer(debugDrawer);
std::cout << "Loaded "
<< gta->gameData.models.size() << " models, "
<< gta->gameData.textureLoader.textures.size() << " textures" << std::endl;
}
void update(float dt)