diff --git a/src/engine/include/models/mesh.hpp b/src/engine/include/models/mesh.hpp index 1155a0b..d4c1c47 100644 --- a/src/engine/include/models/mesh.hpp +++ b/src/engine/include/models/mesh.hpp @@ -54,8 +54,23 @@ public: u8 isMd2Loaded, isObjLoaded, isDffLoaded, isSpecInitialized; clutbuffer_t clut; lod_t lod; + u32 id; MeshTexture *textures; + /** Array of materials. Size of getMaterialsCount() */ + MeshMaterial *getMaterials() const { return obj->frames[0].getMaterials(); }; + + const u32 &getMaterialsCount() const { return obj->frames[0].getMaterialsCount(); }; + + /** Returns material, which is a mesh "subgroup". */ + MeshMaterial &getMaterial(const u32 &i) const { return obj->frames[0].getMaterial(i); }; + + /** + * Returns material, which is a mesh "subgroup". + * NULL if not found. + */ + MeshMaterial *getMaterialById(const u32 &t_id) const { return obj->frames[0].getMaterialById(t_id); } + private: void setupLodAndClut(); void setDefaultWrapSettings(texwrap_t &t_wrapSettings); diff --git a/src/engine/include/models/mesh_frame.hpp b/src/engine/include/models/mesh_frame.hpp index 5c548d2..e5c525a 100644 --- a/src/engine/include/models/mesh_frame.hpp +++ b/src/engine/include/models/mesh_frame.hpp @@ -11,6 +11,7 @@ #ifndef _TYRA_MESH_FRAME_ #define _TYRA_MESH_FRAME_ +#include #include #include "math/point.hpp" #include "math/vector3.hpp" @@ -50,6 +51,18 @@ public: /** Returns material, which is a mesh "subgroup". */ MeshMaterial &getMaterial(const u32 &i) const { return materials[i]; }; + /** + * Returns material, which is a mesh "subgroup". + * NULL if not found. + */ + MeshMaterial *getMaterialById(const u32 &t_id) const + { + for (u32 i = 0; i < materialsCount; i++) + if (materials[i].getId() == t_id) + return &materials[i]; + return NULL; + } + /** Array of vertices. Size of getVertexCount() */ Vector3 *getVertices() const { return vertices; }; diff --git a/src/engine/include/models/mesh_texture.hpp b/src/engine/include/models/mesh_texture.hpp index fc4a8a4..f23e649 100644 --- a/src/engine/include/models/mesh_texture.hpp +++ b/src/engine/include/models/mesh_texture.hpp @@ -106,15 +106,23 @@ public: // ---- /** Assign texture to mesh and mesh material */ - void addLink(u32 t_meshId, u32 t_materialId); + void addLink(const u32 &t_meshId, const u32 &t_materialId); /** Remove mesh and mesh material assignment */ - void removeLink(u32 t_meshId, u32 t_materialId); + void removeLink(const u32 &t_meshId, const u32 &t_materialId); const u8 &isNameSet() const { return _isNameSet; }; const u8 &isSizeSet() const { return _isSizeSet; }; + const u8 isLinkedWith(const u32 &t_meshId, const u32 &t_materialId) const + { + for (u32 i = 0; i < texLinkCount; i++) + if (texLinks[i].materialId == t_materialId && texLinks[i].meshId == t_meshId) + return true; + return false; + }; + private: void setDefaultWrapSettings(); texwrap_t wrapSettings; diff --git a/src/engine/include/modules/renderer.hpp b/src/engine/include/modules/renderer.hpp index 16d8b5e..e5eda51 100644 --- a/src/engine/include/modules/renderer.hpp +++ b/src/engine/include/modules/renderer.hpp @@ -59,7 +59,7 @@ public: TextureRepository *getTextureRepository() { return &textureRepo; }; private: - void changeTexture(Mesh *t_mesh, u8 t_textureIndex); + void changeTexture(Mesh *t_mesh, u32 t_materialId); u32 lastTextureId; texbuffer_t textureBuffer; u8 isTextureVRAMAllocated; diff --git a/src/engine/include/modules/texture_repository.hpp b/src/engine/include/modules/texture_repository.hpp index 621df96..025bb51 100644 --- a/src/engine/include/modules/texture_repository.hpp +++ b/src/engine/include/modules/texture_repository.hpp @@ -14,6 +14,8 @@ #include #include #include "../models/mesh.hpp" +#include "../models/mesh_frame.hpp" +#include "../loaders/bmp_loader.hpp" /** Class responsible for intializing draw env, textures and buffers */ class TextureRepository @@ -23,7 +25,64 @@ public: TextureRepository(); ~TextureRepository(); + // ---- + // Getters + // ---- + + /** Returns all repository textures. */ + MeshTexture **getAll() const { return textures; } + + const u32 &getTexturesCount() const { return texturesCount; }; + + /** + * Returns single texture. + * NULL if not found. + */ + MeshTexture *getByMesh(const u32 &t_meshId, const u32 &t_materialId) + { + for (u32 i = 0; i < texturesCount; i++) + if (textures[i]->isLinkedWith(t_meshId, t_materialId)) + return textures[i]; + return NULL; + } + + /** + * Returns single texture. + * NULL if not found. + */ + MeshTexture *getByTextureId(const u32 &t_id) const + { + for (u32 i = 0; i < texturesCount; i++) + if (t_id == textures[i]->getId()) + return textures[i]; + return NULL; + } + + // ---- + // Setters + // ---- + + // ---- + // Other + // ---- + + /** Add single unlinked texture to repository. */ + MeshTexture *add(char *t_subfolder, char *t_name); + + /** Add linked textures in given subpath for mesh material names. */ + void addByMesh(char *t_path, Mesh &mesh); + + /** + * Remove texture from repository. + * Texture is NOT destructed. + */ + void remove(u32 textureId); + private: + void increaseArray(u32 newLength); + u32 texturesCount; + MeshTexture **textures; + BmpLoader loader; }; #endif diff --git a/src/engine/loaders/bmp_loader.cpp b/src/engine/loaders/bmp_loader.cpp index c225b8f..acbf705 100644 --- a/src/engine/loaders/bmp_loader.cpp +++ b/src/engine/loaders/bmp_loader.cpp @@ -32,7 +32,7 @@ BmpLoader::~BmpLoader() {} */ void BmpLoader::load(MeshTexture &o_texture, char *t_subfolder, char *t_name, char *t_extension) { - o_texture.setName(t_name); + char *t_path_part = String::createConcatenated(t_subfolder, t_name); char *t_path = String::createConcatenated(t_path_part, t_extension); delete[] t_path_part; diff --git a/src/engine/models/mesh.cpp b/src/engine/models/mesh.cpp index e2d229d..89a14a2 100644 --- a/src/engine/models/mesh.cpp +++ b/src/engine/models/mesh.cpp @@ -17,6 +17,7 @@ #include "../include/models/mesh_texture.hpp" #include "../include/utils/debug.hpp" #include "../include/utils/string.hpp" +#include // ---- // Constructors/Destructors @@ -31,6 +32,7 @@ Mesh::Mesh() isObjLoaded = false; isDffLoaded = false; isSpecInitialized = false; + id = rand() % 1000000; scale = 1.0F; } @@ -110,7 +112,6 @@ void Mesh::loadObj(char *t_subfolder, char *t_objFile, Vector3 &t_initPos, float setVerticesReference(obj->getFacesCount(), obj->frames[0].getVertices()); setDefaultColor(); isObjLoaded = true; - loadTextures(t_subfolder, ".bmp"); } void Mesh::setObj(Vector3 &t_initPos, ObjModel *t_objModel) @@ -171,12 +172,6 @@ void Mesh::loadTextures(char *t_subfolder, char *t_extension) BmpLoader bmpLoader = BmpLoader(); if (isObjLoaded) { - textures = new MeshTexture[obj->frames[0].getMaterialsCount()]; - for (u8 i = 0; i < obj->frames[0].getMaterialsCount(); i++) - { - bmpLoader.load(textures[i], t_subfolder, obj->frames[0].getMaterial(i).getName(), t_extension); - // setDefaultWrapSettings(spec->textures[i].wrapSettings); - } } else if (isMd2Loaded) { diff --git a/src/engine/models/mesh_material.cpp b/src/engine/models/mesh_material.cpp index fa68c86..d6396f3 100644 --- a/src/engine/models/mesh_material.cpp +++ b/src/engine/models/mesh_material.cpp @@ -19,7 +19,7 @@ MeshMaterial::MeshMaterial() { - id = rand() % 100000; + id = rand() % 1000000; facesCount = 0; _isNameSet = false; _areFacesAllocated = false; diff --git a/src/engine/models/mesh_texture.cpp b/src/engine/models/mesh_texture.cpp index f3cb6b3..5e57af4 100644 --- a/src/engine/models/mesh_texture.cpp +++ b/src/engine/models/mesh_texture.cpp @@ -20,7 +20,7 @@ MeshTexture::MeshTexture() { - id = rand() % 100000; + id = rand() % 1000000; texLinkCount = 0; _isSizeSet = false; _isNameSet = false; @@ -81,30 +81,33 @@ void MeshTexture::setWrapSettings(const WrapSettings t_horizontal, const WrapSet wrapSettings.vertical = t_vertical; } -void MeshTexture::addLink(u32 t_meshId, u32 t_materialId) +void MeshTexture::addLink(const u32 &t_meshId, const u32 &t_materialId) { TextureLink *savedLinks = texLinks; - texLinks = new TextureLink[++texLinkCount]; - for (u32 i = 0; i < texLinkCount - 1; i++) + texLinks = new TextureLink[texLinkCount + 1]; + for (u32 i = 0; i < texLinkCount; i++) { texLinks[i].materialId = savedLinks[i].materialId; texLinks[i].meshId = savedLinks[i].meshId; } - delete[] savedLinks; + if (texLinkCount != 0) + delete[] savedLinks; + texLinkCount++; texLinks[texLinkCount - 1].materialId = t_materialId; texLinks[texLinkCount - 1].meshId = t_meshId; } -void MeshTexture::removeLink(u32 t_meshId, u32 t_materialId) +void MeshTexture::removeLink(const u32 &t_meshId, const u32 &t_materialId) { TextureLink *savedLinks = texLinks; - texLinks = new TextureLink[--texLinkCount]; + texLinks = new TextureLink[texLinkCount - 1]; u32 savedCount = 0; - for (u32 i = 0; i < texLinkCount + 1; i++) + for (u32 i = 0; i < texLinkCount; i++) if (savedLinks[i].materialId != t_materialId && savedLinks[i].meshId != t_meshId) { texLinks[savedCount++].materialId = savedLinks[i].materialId; texLinks[savedCount++].meshId = savedLinks[i].meshId; } delete[] savedLinks; + texLinkCount--; } diff --git a/src/engine/modules/renderer.cpp b/src/engine/modules/renderer.cpp index 258fd29..ca6988f 100644 --- a/src/engine/modules/renderer.cpp +++ b/src/engine/modules/renderer.cpp @@ -81,15 +81,21 @@ void Renderer::deallocateTextureBuffer() } } -void Renderer::changeTexture(Mesh *t_mesh, u8 t_textureIndex) +void Renderer::changeTexture(Mesh *t_mesh, u32 t_materialId) { - if (t_mesh->textures[t_textureIndex].getId() != lastTextureId) + MeshTexture *tex = textureRepo.getByMesh(t_mesh->id, t_materialId); + if (tex != NULL) { - lastTextureId = t_mesh->textures[t_textureIndex].getId(); - deallocateTextureBuffer(); - allocateTextureBuffer(t_mesh->textures[t_textureIndex].getWidth(), t_mesh->textures[t_textureIndex].getHeight()); - GifSender::sendTexture(t_mesh->textures[t_textureIndex], &textureBuffer); + if (tex->getId() != lastTextureId) + { + lastTextureId = tex->getId(); + deallocateTextureBuffer(); + allocateTextureBuffer(tex->getWidth(), tex->getHeight()); + GifSender::sendTexture(*tex, &textureBuffer); + } } + else + PRINT_ERR("Texture was not found in texture repository!"); } /** Initializes drawing environment (1st app packet) */ @@ -208,9 +214,9 @@ void Renderer::draw(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount) if (t_mesh->isObjLoaded) { t_mesh->obj->animate(); - for (u32 i = 0; i < t_mesh->obj->frames[0].getMaterialsCount(); i++) + for (u32 i = 0; i < t_mesh->getMaterialsCount(); i++) { - changeTexture(t_mesh, i); + changeTexture(t_mesh, t_mesh->getMaterial(i).getId()); vertCount = t_mesh->getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition); vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer); } diff --git a/src/engine/modules/texture_repository.cpp b/src/engine/modules/texture_repository.cpp index 9cfe457..447f00f 100644 --- a/src/engine/modules/texture_repository.cpp +++ b/src/engine/modules/texture_repository.cpp @@ -18,7 +18,7 @@ TextureRepository::TextureRepository() { PRINT_LOG("Initializing texture repository"); - + texturesCount = 0; PRINT_LOG("Texture repository initialized!"); } @@ -27,3 +27,59 @@ TextureRepository::~TextureRepository() {} // ---- // Methods // ---- + +MeshTexture *TextureRepository::add(char *t_subfolder, char *t_name) +{ + increaseArray(texturesCount + 1); + // texturesCount is updated + loader.load(*textures[texturesCount - 1], t_subfolder, t_name, ".bmp"); + return textures[texturesCount - 1]; +} + +void TextureRepository::addByMesh(char *t_path, Mesh &mesh) +{ +#define MATERIAL mesh.getMaterial(i) + u32 newLength = texturesCount + mesh.getMaterialsCount(); + increaseArray(newLength); + for (u8 i = newLength - mesh.getMaterialsCount(); i < newLength; i++) + { + textures[i] = new MeshTexture(); + loader.load(*textures[i], t_path, MATERIAL.getName(), ".bmp"); + textures[i]->setName(mesh.getMaterial(i).getName()); + textures[i]->addLink(mesh.id, MATERIAL.getId()); + } +} + +/** + * Remove texture from repository. + * Texture is not destructed. + */ +void TextureRepository::remove(u32 t_textureId) +{ + MeshTexture **savedTextures = textures; + textures = new MeshTexture *[texturesCount - 1]; + u32 savedCount = 0; + for (u32 i = 0; i < texturesCount; i++) + if (savedTextures[i]->getId() != t_textureId) + textures[savedCount++] = savedTextures[i]; + delete[] savedTextures; + texturesCount--; +} + +/** + * Resize textures array. + * texturesCount variable is updated. + * Classes are NOT instantiated. + */ +void TextureRepository::increaseArray(u32 newLength) +{ + MeshTexture **savedTextures = textures; + textures = new MeshTexture *[newLength]; + if (texturesCount) + { + for (u32 i = 0; i < texturesCount; i++) + textures[i] = savedTextures[i]; + delete[] savedTextures; + } + texturesCount = newLength; +} diff --git a/src/samples/ari/ari.cpp b/src/samples/ari/ari.cpp index 288ab78..846c07a 100644 --- a/src/samples/ari/ari.cpp +++ b/src/samples/ari/ari.cpp @@ -93,6 +93,8 @@ void Ari::onInit() test = new Mesh(); Vector3 testpos = Vector3(0.0F, 10.0F, 0.0F); test->loadObj("objanim/", "untitled", testpos, 10.0F, 2); + texRepo->addByMesh("objanim/", *test); + // MeshTexture **textures = texRepo->getAll(); test->playAnimation(0, 1); test->shouldBeBackfaceCulled = true; // test->shouldBeFrustumCulled = true;