mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-15 06:52:34 +02:00
Added TextureAtlas, broke rendering
This commit is contained in:
parent
2796ba5e25
commit
206b3979e8
@ -9,3 +9,5 @@ add_subdirectory(viewer)
|
||||
|
||||
add_subdirectory(framework2)
|
||||
add_subdirectory(analyzer)
|
||||
|
||||
add_subdirectory(tests)
|
||||
|
@ -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 ) {
|
||||
|
@ -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;
|
||||
|
58
framework2/TextureAtlas.cpp
Normal file
58
framework2/TextureAtlas.cpp
Normal 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;
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
43
framework2/include/renderwure/render/TextureAtlas.hpp
Normal file
43
framework2/include/renderwure/render/TextureAtlas.hpp
Normal 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
16
tests/CMakeLists.txt
Normal 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
21
tests/main.cpp
Normal 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
56
tests/test_atlas.cpp
Normal 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()
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user