#include "c_api/TTexture.h" #include #include #include #include #include #include #include #include #include #include #include #include "Log.hpp" #ifdef __cplusplus namespace thermion { extern "C" { using namespace filament::backend; #endif EMSCRIPTEN_KEEPALIVE TLinearImage *Image_decode(uint8_t *data, size_t length, const char *name = "image") { std::istringstream stream(std::string(reinterpret_cast(data), length)); auto *linearImage = new image::LinearImage(::image::ImageDecoder::decode(stream, name, ::image::ImageDecoder::ColorSpace::SRGB)); if (!linearImage->isValid()) { Log("Failed to decode image."); return nullptr; } return reinterpret_cast(linearImage); } EMSCRIPTEN_KEEPALIVE float *Image_getBytes(TLinearImage *tLinearImage) { auto *linearImage = reinterpret_cast<::image::LinearImage *>(tLinearImage); return linearImage->getPixelRef(); } EMSCRIPTEN_KEEPALIVE uint32_t Image_getWidth(TLinearImage *tLinearImage) { auto *linearImage = reinterpret_cast<::image::LinearImage *>(tLinearImage); return linearImage->getWidth(); } EMSCRIPTEN_KEEPALIVE uint32_t Image_getHeight(TLinearImage *tLinearImage) { auto *linearImage = reinterpret_cast<::image::LinearImage *>(tLinearImage); return linearImage->getHeight(); } EMSCRIPTEN_KEEPALIVE uint32_t Image_getChannels(TLinearImage *tLinearImage) { auto *linearImage = reinterpret_cast<::image::LinearImage *>(tLinearImage); return linearImage->getChannels(); } EMSCRIPTEN_KEEPALIVE void Image_destroy(TLinearImage *tLinearImage) { auto *linearImage = reinterpret_cast<::image::LinearImage *>(tLinearImage); delete linearImage; } EMSCRIPTEN_KEEPALIVE bool Texture_loadImage(TEngine *tEngine, TTexture *tTexture, TLinearImage *tImage, TPixelDataFormat tBufferFormat, TPixelDataType tPixelDataType) { auto engine = reinterpret_cast(tEngine); auto image = reinterpret_cast<::image::LinearImage *>(tImage); auto texture = reinterpret_cast(tTexture); auto bufferFormat = static_cast(static_cast(tBufferFormat)); auto pixelDataType = static_cast(static_cast(tPixelDataType)); uint32_t w = image->getWidth(); uint32_t h = image->getHeight(); uint32_t channels = image->getChannels(); size_t size; switch (bufferFormat) { case PixelBufferDescriptor::PixelDataFormat::RGB: case PixelBufferDescriptor::PixelDataFormat::RGBA: size = w * h * channels * sizeof(float); break; case PixelBufferDescriptor::PixelDataFormat::RGB_INTEGER: case PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER: size = w * h * channels * sizeof(uint8_t); break; default: Log("Unsupported buffer format type : %d", bufferFormat); return false; } TRACE("Loading image from dimensions %d x %d, channels %d, size %d, buffer format %d and pixel data type %d", w, h, channels, size, bufferFormat, pixelDataType); filament::Texture::PixelBufferDescriptor buffer( image->getPixelRef(), size, bufferFormat, pixelDataType); texture->setImage(*engine, 0, std::move(buffer)); return true; } EMSCRIPTEN_KEEPALIVE bool Texture_setImage( TEngine *tEngine, TTexture *tTexture, uint32_t level, uint8_t *data, size_t size, uint32_t width, uint32_t height, uint32_t channels, uint32_t tBufferFormat, uint32_t tPixelDataType) { auto engine = reinterpret_cast(tEngine); auto texture = reinterpret_cast(tTexture); auto bufferFormat = static_cast(tBufferFormat); auto pixelDataType = static_cast(tPixelDataType); switch (bufferFormat) { case PixelBufferDescriptor::PixelDataFormat::RGB: case PixelBufferDescriptor::PixelDataFormat::RGBA: { size_t expectedSize = width * height * channels * sizeof(float); if (size != expectedSize) { Log("Size mismatch (expected %d, got %d)", expectedSize, size); return false; } break; } case PixelBufferDescriptor::PixelDataFormat::RGB_INTEGER: case PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER: if (size != width * height * channels * sizeof(uint8_t)) { Log("Size mismatch"); // return false; } break; default: Log("Unsupported buffer format type : %d", bufferFormat); return false; } // the texture upload is async, so we need to copy the buffer auto *buffer = new std::vector(size); std::copy(data, data + size, buffer->begin()); filament::Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t, void *data) { delete reinterpret_cast *>(data); }; filament::Texture::PixelBufferDescriptor pbd( buffer->data(), size, bufferFormat, pixelDataType, 1, // alignment 0, // left 0, // top 0, // stride freeCallback, buffer); texture->setImage(*engine, level, std::move(pbd)); return true; } EMSCRIPTEN_KEEPALIVE bool Texture_setImageWithDepth( TEngine *tEngine, TTexture *tTexture, uint32_t level, uint8_t *data, size_t size, uint32_t x_offset, uint32_t y_offset, uint32_t z_offset, uint32_t width, uint32_t height, uint32_t channels, uint32_t depth, uint32_t tBufferFormat, uint32_t tPixelDataType) { auto engine = reinterpret_cast(tEngine); auto texture = reinterpret_cast(tTexture); auto bufferFormat = static_cast(tBufferFormat); auto pixelDataType = static_cast(tPixelDataType); TRACE("Setting texture image (depth %d, %dx%dx%d (%d bytes, z_offset %d)", depth, width, height, channels, size, z_offset); switch (bufferFormat) { case PixelBufferDescriptor::PixelDataFormat::RGB: case PixelBufferDescriptor::PixelDataFormat::RGBA: { size_t expectedSize = width * height * channels * sizeof(float); if (size != expectedSize) { Log("Size mismatch (expected %d, got %d)", expectedSize, size); return false; } break; } case PixelBufferDescriptor::PixelDataFormat::RGB_INTEGER: case PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER: { if (size != width * height * channels * sizeof(uint8_t)) { Log("Size mismatch"); // return false; } break; } default: Log("Unsupported buffer format type : %d", bufferFormat); return false; } // the texture upload is async, so we need to copy the buffer auto *buffer = new std::vector(size); std::copy(data, data + size, buffer->begin()); filament::Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t, void *data) { delete reinterpret_cast *>(data); }; filament::Texture::PixelBufferDescriptor pbd( buffer->data(), size, bufferFormat, pixelDataType, 1, // alignment 0, // left 0, // top 0, // stride freeCallback, buffer); texture->setImage( *engine, level, x_offset, y_offset, z_offset, width, height, depth, std::move(pbd)); return true; } EMSCRIPTEN_KEEPALIVE uint32_t Texture_getWidth(TTexture *tTexture, uint32_t level) { auto *texture = reinterpret_cast(tTexture); return texture->getWidth(); } EMSCRIPTEN_KEEPALIVE uint32_t Texture_getHeight(TTexture *tTexture, uint32_t level) { auto *texture = reinterpret_cast(tTexture); return texture->getHeight(); } EMSCRIPTEN_KEEPALIVE uint32_t Texture_getDepth(TTexture *tTexture, uint32_t level) { auto *texture = reinterpret_cast(tTexture); return texture->getDepth(); } EMSCRIPTEN_KEEPALIVE TLinearImage *Image_createEmpty(uint32_t width, uint32_t height, uint32_t channel) { auto *image = new ::image::LinearImage(width, height, channel); return reinterpret_cast(image); } EMSCRIPTEN_KEEPALIVE TTextureSampler *TextureSampler_create() { auto *sampler = new filament::TextureSampler(filament::TextureSampler::CompareMode::COMPARE_TO_TEXTURE); return reinterpret_cast(sampler); } EMSCRIPTEN_KEEPALIVE TTextureSampler *TextureSampler_createWithFiltering( TSamplerMinFilter minFilter, TSamplerMagFilter magFilter, TSamplerWrapMode wrapS, TSamplerWrapMode wrapT, TSamplerWrapMode wrapR) { filament::TextureSampler::MinFilter min = static_cast(minFilter); filament::TextureSampler::MagFilter mag = static_cast(magFilter); filament::TextureSampler::WrapMode s = static_cast(wrapS); filament::TextureSampler::WrapMode t = static_cast(wrapT); filament::TextureSampler::WrapMode r = static_cast(wrapR); auto *sampler = new filament::TextureSampler(min, mag, s, t, r); return reinterpret_cast(sampler); } EMSCRIPTEN_KEEPALIVE TTextureSampler *TextureSampler_createWithComparison( TSamplerCompareMode compareMode, TSamplerCompareFunc compareFunc) { if(compareMode == COMPARE_MODE_NONE) { TRACE("COMPARE MODE NONE"); } else if(compareMode == COMPARE_MODE_COMPARE_TO_TEXTURE) { TRACE("COMPARE MODE COMPARE TO TEXTURE"); } else { TRACE("UNKNWON COMPARE MODE"); } filament::TextureSampler::CompareMode mode = static_cast(static_cast(compareMode)); filament::TextureSampler::CompareFunc func = static_cast(static_cast(compareFunc)); TRACE("Creating texture sampler with compare mode %d and compare func %d"); auto *sampler = new filament::TextureSampler(mode, func); return reinterpret_cast(sampler); } EMSCRIPTEN_KEEPALIVE void TextureSampler_setMinFilter( TTextureSampler *sampler, TSamplerMinFilter filter) { if (sampler) { auto *textureSampler = reinterpret_cast(sampler); textureSampler->setMinFilter(static_cast(filter)); } } EMSCRIPTEN_KEEPALIVE void TextureSampler_setAnisotropy( TTextureSampler *sampler, double anisotropy) { auto *textureSampler = reinterpret_cast(sampler); textureSampler->setAnisotropy(static_cast(anisotropy)); } EMSCRIPTEN_KEEPALIVE void TextureSampler_setMagFilter( TTextureSampler *sampler, TSamplerMagFilter filter) { if (sampler) { auto *textureSampler = reinterpret_cast(sampler); textureSampler->setMagFilter(static_cast(filter)); } } EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeS( TTextureSampler *sampler, TSamplerWrapMode mode) { if (sampler) { auto *textureSampler = reinterpret_cast(sampler); textureSampler->setWrapModeS(static_cast(mode)); } } EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeT( TTextureSampler *sampler, TSamplerWrapMode mode) { if (sampler) { auto *textureSampler = reinterpret_cast(sampler); textureSampler->setWrapModeT(static_cast(mode)); } } EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeR( TTextureSampler *sampler, TSamplerWrapMode mode) { if (sampler) { auto *textureSampler = reinterpret_cast(sampler); textureSampler->setWrapModeR(static_cast(mode)); } } EMSCRIPTEN_KEEPALIVE void TextureSampler_setCompareMode( TTextureSampler *sampler, TSamplerCompareMode mode, TSamplerCompareFunc func) { if (sampler) { auto *textureSampler = reinterpret_cast(sampler); textureSampler->setCompareMode( static_cast(mode), static_cast(func)); } } EMSCRIPTEN_KEEPALIVE void TextureSampler_destroy(TTextureSampler *sampler) { if (sampler) { auto *textureSampler = reinterpret_cast(sampler); delete textureSampler; } } EMSCRIPTEN_KEEPALIVE TTexture *RenderTarget_getColorTexture(TRenderTarget *tRenderTarget) { auto renderTarget = reinterpret_cast(tRenderTarget); auto texture = renderTarget->getTexture(filament::RenderTarget::AttachmentPoint::COLOR0); return reinterpret_cast(texture); } EMSCRIPTEN_KEEPALIVE TTexture *RenderTarget_getDepthTexture(TRenderTarget *tRenderTarget) { auto renderTarget = reinterpret_cast(tRenderTarget); auto texture = renderTarget->getTexture(filament::RenderTarget::AttachmentPoint::DEPTH); return reinterpret_cast(texture); } #ifdef __cplusplus } } #endif