157 lines
5.2 KiB
C++
157 lines
5.2 KiB
C++
// Copyright (c) 2022 Dominic Masters
|
|
//
|
|
// This software is released under the MIT License.
|
|
// https://opensource.org/licenses/MIT
|
|
|
|
#include "TextureLoader.hpp"
|
|
#include "assert/assert.hpp"
|
|
|
|
using namespace Dawn;
|
|
|
|
const std::string TextureLoader::ASSET_TYPE = "texture";
|
|
|
|
TextureLoader::TextureLoader(
|
|
const std::shared_ptr<AssetManager> assetManager,
|
|
const std::string name
|
|
) :
|
|
AssetLoader(assetManager, name),
|
|
loader(name),
|
|
state(TextureLoaderLoadState::INITIAL)
|
|
{
|
|
this->typetest = this->getAssetType();
|
|
texture = std::make_shared<Texture>();
|
|
}
|
|
|
|
void TextureLoader::updateAsync() {
|
|
if(this->state != TextureLoaderLoadState::INITIAL) return;
|
|
this->state = TextureLoaderLoadState::ASYNC_LOADING;
|
|
this->loader.open();
|
|
|
|
// Read in the header.
|
|
uint8_t buffer[TEXTURE_LOADER_HEADER_SIZE];
|
|
size_t pos = 0;
|
|
|
|
// Read Version
|
|
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
|
std::string version = std::string((char*)buffer);
|
|
assertTrue(version == "DT_2.00", "Invalid Texture Version!");
|
|
|
|
// Read Texture Width
|
|
this->loader.setPosition(pos);
|
|
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
|
width = std::stoi(std::string((char*)buffer));
|
|
assertTrue(width > 0, "Invalid Texture Width!");
|
|
|
|
// Read Texture Height
|
|
this->loader.setPosition(pos);
|
|
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
|
height = std::stoi(std::string((char*)buffer));
|
|
assertTrue(height > 0, "Invalid Texture Height!");
|
|
|
|
// Texture Format (RGBA, RGB, etc)
|
|
this->loader.setPosition(pos);
|
|
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
|
int32_t iFormat = std::stoi(std::string((char*)buffer));
|
|
switch(iFormat) {
|
|
case 1: format = TextureFormat::R; break;
|
|
case 2: format = TextureFormat::RG; break;
|
|
case 3: format = TextureFormat::RGB; break;
|
|
case 4: format = TextureFormat::RGBA; break;
|
|
default: assertUnreachable("Invalid Texture Format %i!", iFormat);
|
|
}
|
|
|
|
// Wrap X
|
|
this->loader.setPosition(pos);
|
|
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
|
int32_t iWrapX = std::stoi(std::string((char*)buffer));
|
|
switch(iWrapX) {
|
|
case 0: wrapX = TextureWrapMode::REPEAT; break;
|
|
case 1: wrapX = TextureWrapMode::MIRRORED_REPEAT; break;
|
|
case 2: wrapX = TextureWrapMode::CLAMP_TO_EDGE; break;
|
|
case 3: wrapX = TextureWrapMode::CLAMP_TO_BORDER; break;
|
|
default: assertUnreachable("Invalid Texture Wrap X %i!", iWrapX);
|
|
}
|
|
|
|
// Wrap Y
|
|
this->loader.setPosition(pos);
|
|
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
|
int32_t iWrapY = std::stoi(std::string((char*)buffer));
|
|
switch(iWrapY) {
|
|
case 0: wrapY = TextureWrapMode::REPEAT; break;
|
|
case 1: wrapY = TextureWrapMode::MIRRORED_REPEAT; break;
|
|
case 2: wrapY = TextureWrapMode::CLAMP_TO_EDGE; break;
|
|
case 3: wrapY = TextureWrapMode::CLAMP_TO_BORDER; break;
|
|
default: assertUnreachable("Invalid Texture Wrap Y %i!", iWrapY);
|
|
}
|
|
|
|
// Filter Min
|
|
this->loader.setPosition(pos);
|
|
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
|
int32_t iFilterMin = std::stoi(std::string((char*)buffer));
|
|
switch(iFilterMin) {
|
|
case 0: filterMin = TextureFilterMode::NEAREST; break;
|
|
case 1: filterMin = TextureFilterMode::LINEAR; break;
|
|
default: assertUnreachable("Invalid Texture Filter Min %i!", iFilterMin);
|
|
}
|
|
|
|
// Filter Mag
|
|
this->loader.setPosition(pos);
|
|
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
|
int32_t iFilterMag = std::stoi(std::string((char*)buffer));
|
|
switch(iFilterMag) {
|
|
case 0: filterMag = TextureFilterMode::NEAREST; break;
|
|
case 1: filterMag = TextureFilterMode::LINEAR; break;
|
|
default: assertUnreachable("Invalid Texture Filter Mag %i!", iFilterMag);
|
|
}
|
|
|
|
// Data begins here. This part is done synchronously directly to the GPU.
|
|
this->loader.setPosition(pos);
|
|
size_t bufferSize = width * height * iFormat;
|
|
data = new uint8_t[bufferSize];
|
|
assertNotNull(data, "Failed to allocate texture data!");
|
|
this->loader.read(data, bufferSize);
|
|
|
|
// Handoff to sync to buffer to GPU.
|
|
this->state = TextureLoaderLoadState::ASYNC_DONE;
|
|
}
|
|
|
|
void TextureLoader::updateSync() {
|
|
if(this->state != TextureLoaderLoadState::ASYNC_DONE) return;
|
|
this->state = TextureLoaderLoadState::SYNC_LOADING;
|
|
|
|
assertNotNull(this->texture, "Texture is null!");
|
|
assertNotNull(this->data, "Texture data is null!");
|
|
|
|
// Setup Texture
|
|
this->texture->setSize(
|
|
this->width,
|
|
this->height,
|
|
this->format,
|
|
TextureDataFormat::UNSIGNED_BYTE
|
|
);
|
|
this->texture->buffer(this->data);
|
|
|
|
// Free data buffer
|
|
delete[] this->data;
|
|
this->data = nullptr;
|
|
|
|
// Hand off and call done
|
|
this->state = TextureLoaderLoadState::SYNC_DONE;
|
|
this->loaded = true;
|
|
}
|
|
|
|
std::string TextureLoader::getAssetType() const {
|
|
return TextureLoader::ASSET_TYPE;
|
|
}
|
|
|
|
std::shared_ptr<Texture> TextureLoader::getTexture() {
|
|
return this->texture;
|
|
}
|
|
|
|
TextureLoader::~TextureLoader() {
|
|
if(this->data != nullptr) {
|
|
delete[] this->data;
|
|
this->data = nullptr;
|
|
}
|
|
this->texture = nullptr;
|
|
} |