diff --git a/src/engine/include/models/mesh.hpp b/src/engine/include/models/mesh.hpp index 94541c0..1155a0b 100644 --- a/src/engine/include/models/mesh.hpp +++ b/src/engine/include/models/mesh.hpp @@ -54,7 +54,7 @@ public: u8 isMd2Loaded, isObjLoaded, isDffLoaded, isSpecInitialized; clutbuffer_t clut; lod_t lod; - MeshTexture **textures; + MeshTexture *textures; private: void setupLodAndClut(); diff --git a/src/engine/include/models/mesh_texture.hpp b/src/engine/include/models/mesh_texture.hpp index bf1b751..fc4a8a4 100644 --- a/src/engine/include/models/mesh_texture.hpp +++ b/src/engine/include/models/mesh_texture.hpp @@ -14,12 +14,12 @@ #include #include #include "./texture_wrap_settings.hpp" +#include "./texture_link.hpp" /** - * Class which contains texture data - * Textures are paired with material via material id. - * Additionaly, you can load two textures for single material - * and switch materialId here to change texture. + * Class which contains texture data. + * Textures are paired with meshes via addUsage(), + * removeUsage() functions which use meshId and materialId. */ class MeshTexture { @@ -40,17 +40,12 @@ public: */ const u32 &getId() const { return id; }; - /** - * Core role of this variable is to assign texture to correct material. - * For example you can have two textures for single material. - * Example: Same player can have two textures (team A, team B) - */ - const u32 &getMaterialId() const { return materialId; }; - const u8 &getWidth() const { return width; }; const u8 &getHeight() const { return height; }; + const u32 &getTextureLinksCount() const { return texLinkCount; }; + texwrap_t *getWrapSettings() { return &wrapSettings; }; /** @@ -71,17 +66,13 @@ public: */ char *getName() const { return name; }; + /** Array of texture links. Size of getTextureLinksCount() */ + TextureLink *getTextureLinks() const { return texLinks; }; + // ---- // Setters // ---- - /** - * Core role of this variable is to assign texture to correct material. - * For example you can have two textures for single material. - * Example: Same player can have two textures (team A, team B) - */ - void setMaterialId(const u32 &t_val) { materialId = t_val; } - /** * Set texture size and allocate texture data * Do not call this method unless you know what you do. @@ -114,16 +105,22 @@ public: // Other // ---- + /** Assign texture to mesh and mesh material */ + void addLink(u32 t_meshId, u32 t_materialId); + + /** Remove mesh and mesh material assignment */ + void removeLink(u32 t_meshId, u32 t_materialId); + const u8 &isNameSet() const { return _isNameSet; }; const u8 &isSizeSet() const { return _isSizeSet; }; private: void setDefaultWrapSettings(); - texwrap_t wrapSettings; char *name; - u32 id, materialId; + TextureLink *texLinks; + u32 id, texLinkCount; u8 width, height, _isNameSet, _isSizeSet; unsigned char *data; }; diff --git a/src/engine/include/models/texture_link.hpp b/src/engine/include/models/texture_link.hpp new file mode 100644 index 0000000..c0f363d --- /dev/null +++ b/src/engine/include/models/texture_link.hpp @@ -0,0 +1,21 @@ +/* +# ______ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2020, tyra - https://github.com/h4570/tyra +# Licenced under Apache License 2.0 +# Sandro Sobczyński +*/ + +#ifndef _TYRA_TEXTURE_USAGE_ +#define _TYRA_TEXTURE_USAGE_ + +#include + +struct TextureLink +{ + u32 meshId, materialId; +}; + +#endif diff --git a/src/engine/include/modules/renderer.hpp b/src/engine/include/modules/renderer.hpp index be059c4..16d8b5e 100644 --- a/src/engine/include/modules/renderer.hpp +++ b/src/engine/include/modules/renderer.hpp @@ -19,6 +19,7 @@ #include "../models/math/plane.hpp" #include "../models/screen_settings.hpp" #include "../models/render_data.hpp" +#include "./texture_repository.hpp" /** Class responsible for intializing draw env, textures and buffers */ class Renderer @@ -55,17 +56,21 @@ public: void endFrame(float fps); + TextureRepository *getTextureRepository() { return &textureRepo; }; + private: + void changeTexture(Mesh *t_mesh, u8 t_textureIndex); + u32 lastTextureId; + texbuffer_t textureBuffer; + u8 isTextureVRAMAllocated; void allocateTextureBuffer(u16 t_width, u16 t_height); void deallocateTextureBuffer(); - void changeTexture(Mesh *t_mesh, u8 t_textureIndex); void flipBuffers(); void beginFrameIfNeeded(); - u8 isFrameEmpty, isTextureVRAMAllocated; + u8 isFrameEmpty; Matrix perspective; RenderData renderData; - texbuffer_t textureBuffer; - u32 lastTextureId; + TextureRepository textureRepo; GifSender *gifSender; VifSender *vifSender; packet_t *flipPacket; diff --git a/src/engine/include/modules/texture_repository.hpp b/src/engine/include/modules/texture_repository.hpp index 45fac61..621df96 100644 --- a/src/engine/include/modules/texture_repository.hpp +++ b/src/engine/include/modules/texture_repository.hpp @@ -24,10 +24,6 @@ public: ~TextureRepository(); private: - void allocateTextureBuffer(u16 t_width, u16 t_height); - void deallocateTextureBuffer(); - void changeTexture(Mesh *t_mesh, u8 t_textureIndex); - texbuffer_t textureBuffer; }; #endif diff --git a/src/engine/models/mesh.cpp b/src/engine/models/mesh.cpp index 7b6e721..e2d229d 100644 --- a/src/engine/models/mesh.cpp +++ b/src/engine/models/mesh.cpp @@ -171,29 +171,26 @@ void Mesh::loadTextures(char *t_subfolder, char *t_extension) BmpLoader bmpLoader = BmpLoader(); if (isObjLoaded) { - textures = new MeshTexture *[obj->frames[0].getMaterialsCount()]; + textures = new MeshTexture[obj->frames[0].getMaterialsCount()]; for (u8 i = 0; i < obj->frames[0].getMaterialsCount(); i++) { - textures[i] = new MeshTexture(); - bmpLoader.load(*textures[i], t_subfolder, obj->frames[0].getMaterial(i).getName(), t_extension); + bmpLoader.load(textures[i], t_subfolder, obj->frames[0].getMaterial(i).getName(), t_extension); // setDefaultWrapSettings(spec->textures[i].wrapSettings); } } else if (isMd2Loaded) { - textures = new MeshTexture *[1]; - textures[0] = new MeshTexture(); - bmpLoader.load(*textures[0], t_subfolder, md2->filename, t_extension); + textures = new MeshTexture[1]; + bmpLoader.load(textures[0], t_subfolder, md2->filename, t_extension); // setDefaultWrapSettings(spec->textures[0].wrapSettings); } else if (isDffLoaded) { - textures = new MeshTexture *[dff->clump.geometryList.geometries[0].materialList.data.materialCount]; + textures = new MeshTexture[dff->clump.geometryList.geometries[0].materialList.data.materialCount]; for (u8 i = 0; i < dff->clump.geometryList.geometries[0].materialList.data.materialCount; i++) for (u8 j = 0; j < dff->clump.geometryList.geometries[0].materialList.materials[i].data.textureCount; j++) { - textures[i] = new MeshTexture(); - bmpLoader.load(*textures[i], t_subfolder, dff->clump.geometryList.geometries[0].materialList.materials[i].textures[j].textureName.text, t_extension); + bmpLoader.load(textures[i], t_subfolder, dff->clump.geometryList.geometries[0].materialList.materials[i].textures[j].textureName.text, t_extension); // setDefaultWrapSettings(spec->textures[i].wrapSettings); } } diff --git a/src/engine/models/mesh_texture.cpp b/src/engine/models/mesh_texture.cpp index e204254..f3cb6b3 100644 --- a/src/engine/models/mesh_texture.cpp +++ b/src/engine/models/mesh_texture.cpp @@ -21,7 +21,7 @@ MeshTexture::MeshTexture() { id = rand() % 100000; - materialId = 0; + texLinkCount = 0; _isSizeSet = false; _isNameSet = false; setDefaultWrapSettings(); @@ -29,6 +29,8 @@ MeshTexture::MeshTexture() MeshTexture::~MeshTexture() { + if (texLinkCount > 0) + delete[] texLinks; if (_isNameSet) delete[] name; if (_isSizeSet) @@ -78,3 +80,31 @@ void MeshTexture::setWrapSettings(const WrapSettings t_horizontal, const WrapSet wrapSettings.horizontal = t_horizontal; wrapSettings.vertical = t_vertical; } + +void MeshTexture::addLink(u32 t_meshId, u32 t_materialId) +{ + TextureLink *savedLinks = texLinks; + texLinks = new TextureLink[++texLinkCount]; + for (u32 i = 0; i < texLinkCount - 1; i++) + { + texLinks[i].materialId = savedLinks[i].materialId; + texLinks[i].meshId = savedLinks[i].meshId; + } + delete[] savedLinks; + texLinks[texLinkCount - 1].materialId = t_materialId; + texLinks[texLinkCount - 1].meshId = t_meshId; +} + +void MeshTexture::removeLink(u32 t_meshId, u32 t_materialId) +{ + TextureLink *savedLinks = texLinks; + texLinks = new TextureLink[--texLinkCount]; + u32 savedCount = 0; + for (u32 i = 0; i < texLinkCount + 1; 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; +} diff --git a/src/engine/modules/renderer.cpp b/src/engine/modules/renderer.cpp index ee7de1b..258fd29 100644 --- a/src/engine/modules/renderer.cpp +++ b/src/engine/modules/renderer.cpp @@ -36,8 +36,9 @@ Renderer::Renderer(u32 t_packetSize, ScreenSettings *t_screen) dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer dma_channel_fast_waits(DMA_CHANNEL_GIF); context = 0; - lastTextureId = 0; + isTextureVRAMAllocated = false; isFrameEmpty = false; + lastTextureId = 0; flipPacket = packet_init(3, PACKET_UCAB); // Uncached accelerated allocateBuffers(t_screen->width, t_screen->height); initDrawingEnv(t_screen->width, t_screen->height); @@ -55,6 +56,42 @@ Renderer::~Renderer() {} // Methods // ---- +/** Configure and allocate vRAM for texture buffer */ +void Renderer::allocateTextureBuffer(u16 t_width, u16 t_height) +{ + textureBuffer.width = t_width; + textureBuffer.psm = GS_PSM_24; + textureBuffer.address = graph_vram_allocate(t_width, t_height, GS_PSM_24, GRAPH_ALIGN_BLOCK); + if (textureBuffer.address <= 1) + PRINT_ERR("Texture buffer allocation error. No memory!"); + textureBuffer.info.width = draw_log2(t_width); + textureBuffer.info.height = draw_log2(t_height); + textureBuffer.info.components = TEXTURE_COMPONENTS_RGB; + textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE; + isTextureVRAMAllocated = true; +} + +/** Configure and allocate vRAM for texture buffer */ +void Renderer::deallocateTextureBuffer() +{ + if (isTextureVRAMAllocated) + { + graph_vram_free(textureBuffer.address); + isTextureVRAMAllocated = false; + } +} + +void Renderer::changeTexture(Mesh *t_mesh, u8 t_textureIndex) +{ + if (t_mesh->textures[t_textureIndex].getId() != lastTextureId) + { + 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); + } +} + /** Initializes drawing environment (1st app packet) */ void Renderer::initDrawingEnv(float t_screenW, float t_screenH) { @@ -88,42 +125,6 @@ void Renderer::setPrim() PRINT_LOG("Prim set!"); } -/** Configure and allocate vRAM for texture buffer */ -void Renderer::allocateTextureBuffer(u16 t_width, u16 t_height) -{ - textureBuffer.width = t_width; - textureBuffer.psm = GS_PSM_24; - textureBuffer.address = graph_vram_allocate(t_width, t_height, GS_PSM_24, GRAPH_ALIGN_BLOCK); - if (textureBuffer.address <= 1) - PRINT_ERR("Texture buffer allocation error. No memory!"); - textureBuffer.info.width = draw_log2(t_width); - textureBuffer.info.height = draw_log2(t_height); - textureBuffer.info.components = TEXTURE_COMPONENTS_RGB; - textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE; - isTextureVRAMAllocated = true; -} - -/** Configure and allocate vRAM for texture buffer */ -void Renderer::deallocateTextureBuffer() -{ - if (isTextureVRAMAllocated) - { - graph_vram_free(textureBuffer.address); - isTextureVRAMAllocated = false; - } -} - -void Renderer::changeTexture(Mesh *t_mesh, u8 t_textureIndex) -{ - if (t_mesh->textures[t_textureIndex]->getId() != lastTextureId) - { - 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); - } -} - /** Defines and allocates framebuffers and zbuffer */ void Renderer::allocateBuffers(float t_screenW, float t_screenH) { diff --git a/src/samples/ari/Makefile b/src/samples/ari/Makefile index 97905aa..64424d2 100644 --- a/src/samples/ari/Makefile +++ b/src/samples/ari/Makefile @@ -18,6 +18,7 @@ EE_OBJS = \ ../../engine/modules/light.o \ ../../engine/modules/pad.o \ ../../engine/modules/renderer.o \ + ../../engine/modules/texture_repository.o \ ../../engine/modules/timer.o \ ../../engine/modules/vif_sender.o \ ../../engine/modules/vu1.o \ diff --git a/src/samples/ari/ari.cpp b/src/samples/ari/ari.cpp index 73406c3..288ab78 100644 --- a/src/samples/ari/ari.cpp +++ b/src/samples/ari/ari.cpp @@ -75,6 +75,7 @@ void Ari::onInit() engine.audio.init(0); engine.audio.setVolume(40); engine.audio.loadSong("MOV-CIRC.WAV"); + texRepo = engine.renderer->getTextureRepository(); // engine.audio.play(); // Vector3 islandPos = Vector3(0.0F, 10.0F, 0.0F); diff --git a/src/samples/ari/ari.hpp b/src/samples/ari/ari.hpp index 97520d1..9df35ba 100644 --- a/src/samples/ari/ari.hpp +++ b/src/samples/ari/ari.hpp @@ -16,6 +16,7 @@ #include #include "objects/player.hpp" #include +#include #include "./camera.hpp" class Ari : public Game @@ -35,6 +36,7 @@ private: LightBulb bulb; Player *player; Camera *camera; + TextureRepository *texRepo; }; #endif