From edbd05a3f7a57a56ecd0cab600849272005a0d1a Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 17 Aug 2022 01:27:41 +0300 Subject: [PATCH] Support more NiPixelData formats (feature #6945) --- CHANGELOG.md | 1 + components/nif/data.hpp | 5 +++-- components/nifosg/nifloader.cpp | 40 ++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a24702725..aacb98999d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Bug #5057: Weapon swing sound plays at same pitch whether it hits or misses Bug #5129: Stuttering animation on Centurion Archer Bug #5977: Fatigueless NPCs' corpse underwater changes animation on game load + Feature #6945: Support S3TC-compressed and BGR/BGRA NiPixelData 0.48.0 ------ diff --git a/components/nif/data.hpp b/components/nif/data.hpp index f220aae373..5fcd63e759 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -115,10 +115,11 @@ struct NiPixelData : public Record NIPXFMT_RGBA8, NIPXFMT_PAL8, NIPXFMT_PALA8, + NIPXFMT_BGR8, + NIPXFMT_BGRA8, NIPXFMT_DXT1, NIPXFMT_DXT3, - NIPXFMT_DXT5, - NIPXFMT_DXT5_ALT + NIPXFMT_DXT5 }; Format fmt{NIPXFMT_RGB8}; diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index a313488074..19a83175a3 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1480,17 +1480,39 @@ namespace NifOsg { osg::ref_ptr image (new osg::Image); + // Pixel row alignment, defining it to be consistent with OSG DDS plugin + int packing = 1; GLenum pixelformat = 0; switch (pixelData->fmt) { case Nif::NiPixelData::NIPXFMT_RGB8: - case Nif::NiPixelData::NIPXFMT_PAL8: pixelformat = GL_RGB; break; case Nif::NiPixelData::NIPXFMT_RGBA8: - case Nif::NiPixelData::NIPXFMT_PALA8: pixelformat = GL_RGBA; break; + case Nif::NiPixelData::NIPXFMT_PAL8: + case Nif::NiPixelData::NIPXFMT_PALA8: + pixelformat = GL_RED; // Each color is defined by a byte. + break; + case Nif::NiPixelData::NIPXFMT_BGR8: + pixelformat = GL_BGR; + break; + case Nif::NiPixelData::NIPXFMT_BGRA8: + pixelformat = GL_BGRA; + break; + case Nif::NiPixelData::NIPXFMT_DXT1: + pixelformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + packing = 2; + break; + case Nif::NiPixelData::NIPXFMT_DXT3: + pixelformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + packing = 4; + break; + case Nif::NiPixelData::NIPXFMT_DXT5: + pixelformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + packing = 4; + break; default: Log(Debug::Info) << "Unhandled internal pixel format " << pixelData->fmt << " in " << mFilename; return nullptr; @@ -1507,7 +1529,7 @@ namespace NifOsg { const Nif::NiPixelData::Mipmap& mip = pixelData->mipmaps[i]; - size_t mipSize = mip.height * mip.width * pixelData->bpp / 8; + size_t mipSize = osg::Image::computeImageSizeInBytes(mip.width, mip.height, 1, pixelformat, GL_UNSIGNED_BYTE, packing); if (mipSize + mip.dataOffset > pixelData->data.size()) { Log(Debug::Info) << "Internal texture's mipmap data out of bounds, ignoring texture"; @@ -1534,10 +1556,15 @@ namespace NifOsg { case Nif::NiPixelData::NIPXFMT_RGB8: case Nif::NiPixelData::NIPXFMT_RGBA8: + case Nif::NiPixelData::NIPXFMT_BGR8: + case Nif::NiPixelData::NIPXFMT_BGRA8: + case Nif::NiPixelData::NIPXFMT_DXT1: + case Nif::NiPixelData::NIPXFMT_DXT3: + case Nif::NiPixelData::NIPXFMT_DXT5: { unsigned char* data = new unsigned char[pixels.size()]; memcpy(data, pixels.data(), pixels.size()); - image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE); + image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, packing); break; } case Nif::NiPixelData::NIPXFMT_PAL8: @@ -1548,6 +1575,7 @@ namespace NifOsg Log(Debug::Info) << "Palettized texture in " << mFilename << " is invalid, ignoring"; return nullptr; } + pixelformat = pixelData->fmt == Nif::NiPixelData::NIPXFMT_PAL8 ? GL_RGB : GL_RGBA; // We're going to convert the indices that pixel data contains // into real colors using the palette. const auto& palette = pixelData->palette->colors; @@ -1559,7 +1587,9 @@ namespace NifOsg memcpy(pixel, &palette[index], sizeof(unsigned char) * numChannels); pixel += numChannels; } - image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE); + for (unsigned int& offset : mipmapVector) + offset *= numChannels; + image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, packing); break; } default: