diff --git a/interface/src/avatar/CauterizedModel.cpp b/interface/src/avatar/CauterizedModel.cpp index 02107e9d24..f6b470f024 100644 --- a/interface/src/avatar/CauterizedModel.cpp +++ b/interface/src/avatar/CauterizedModel.cpp @@ -116,7 +116,7 @@ void CauterizedModel::updateClusterMatrices() { for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); auto jointMatrix = _rig->getJointTransform(cluster.jointIndex); -#if GLM_ARCH & GLM_ARCH_SSE2 +#if (GLM_ARCH & GLM_ARCH_SSE2) && !(defined Q_OS_MACOS) glm::mat4 out, inverseBindMatrix = cluster.inverseBindMatrix; glm_mat4_mul((glm_vec4*)&jointMatrix, (glm_vec4*)&inverseBindMatrix, (glm_vec4*)&out); state.clusterMatrices[j] = out; @@ -155,7 +155,7 @@ void CauterizedModel::updateClusterMatrices() { if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) { jointMatrix = cauterizeMatrix; } -#if GLM_ARCH & GLM_ARCH_SSE2 +#if (GLM_ARCH & GLM_ARCH_SSE2) && !(defined Q_OS_MACOS) glm::mat4 out, inverseBindMatrix = cluster.inverseBindMatrix; glm_mat4_mul((glm_vec4*)&jointMatrix, (glm_vec4*)&inverseBindMatrix, (glm_vec4*)&out); state.clusterMatrices[j] = out; diff --git a/libraries/fbx/src/FBXReader_Node.cpp b/libraries/fbx/src/FBXReader_Node.cpp index 435c4d830b..61bd3321cb 100644 --- a/libraries/fbx/src/FBXReader_Node.cpp +++ b/libraries/fbx/src/FBXReader_Node.cpp @@ -62,7 +62,9 @@ template QVariant readBinaryArray(QDataStream& in, int& position) { position += sizeof(T) * arrayLength; in.readRawData(arrayData.data(), arrayData.size()); } - memcpy(&values[0], arrayData.constData(), arrayData.size()); + if (!arrayData.isEmpty()) { + memcpy(&values[0], arrayData.constData(), arrayData.size()); + } } else { values.reserve(arrayLength); const unsigned int DEFLATE_ENCODING = 1; diff --git a/libraries/gpu/src/gpu/Image.cpp b/libraries/gpu/src/gpu/Image.cpp new file mode 100644 index 0000000000..825803a7d9 --- /dev/null +++ b/libraries/gpu/src/gpu/Image.cpp @@ -0,0 +1,43 @@ +#include "Image.h" + + +int image::BC::cpp { 0 }; + +namespace image { + + namespace pixel { + template <> const RGB16_565 mix(const RGB16_565 p0, const RGB16_565 p1, const Byte alpha) { + return RGB16_565( + mix5_4(p0.r, p1.r, alpha), + mix6_4(p0.g, p1.g, alpha), + mix5_4(p0.b, p1.b, alpha)); + } + } + +template <> void compress(const PB_RGB32& src, CB_BC1& dst) { +} + +template <> void uncompress(const CB_BC1& src, PB_RGB32& dst) { + auto bc1 = src.bc; + + auto c0 = bc1.color0.val; + auto c1 = bc1.color1.val; + + for (int i = 0; i < PB_RGB32::LENGTH; ++i) { + //dst.pixels[i] = ; + auto r = pixel::mix( + c0, + c1, + (Byte)bc1.table); + } +} + +template <> void compress(const PB_RGBA32& src, CB_BC4& dst) { + +} + +template <> void uncompress(const CB_BC4& src, PB_RGBA32& dst) { + +} + +} diff --git a/libraries/gpu/src/gpu/Image.h b/libraries/gpu/src/gpu/Image.h new file mode 100644 index 0000000000..fd59406975 --- /dev/null +++ b/libraries/gpu/src/gpu/Image.h @@ -0,0 +1,492 @@ +/* + Let s try compressing images + +*/ + +#include +#include "Forward.h" + + +namespace image { + + // Storage types + using Byte = uint8_t; + using Byte2 = uint16_t; + using Byte4 = uint32_t; + using Byte8 = uint64_t; + + // Storage type selector based on size (sizeof of a type) + template + struct storage { typedef T1 type; }; + + template + struct storage<2, T1, T2, T4, T8> { typedef T2 type; }; + + template + struct storage<4, T1, T2, T4, T8> { typedef T4 type; }; + + template + struct storage<8, T1, T2, T4, T8> { typedef T8 type; }; + + static const Byte BLACK8 { 0 }; + static const Byte WHITE8 { 255 }; + + template int bitVal() { return 1 << N; } + template int bitProduct() { return bitVal() * bitVal(); } + template T mix(const T x, const T y, const A a) { return T(((bitVal() - a) * x + a * y) / bitProduct()); } + + Byte mix5_4(const Byte x, const Byte y, const Byte a) { return mix<5, 4>(x, y, a); } + Byte mix6_4(const Byte x, const Byte y, const Byte a) { return mix<6, 4>(x, y, a); } + + + + // Coordinate and count types + using Coord = uint16_t; + using Coord2 = glm::u16vec2; + using Count = uint32_t; + using Index = uint32_t; + + // Maximum pixel along one direction coord is 32768 + static const Coord MAX_COORD { 32768 }; + // Maximum number of pixels in an image + static const Count MAX_COUNT { MAX_COORD * MAX_COORD }; + static const Index MAX_INDEX { MAX_COUNT }; + + + namespace pixel { + + struct RGB32 { + Byte r { BLACK8 }; + Byte g { BLACK8 }; + Byte b { BLACK8 }; + Byte x { WHITE8 }; + }; + + struct RGBA32 { + Byte r { BLACK8 }; + Byte g { BLACK8 }; + Byte b { BLACK8 }; + Byte a { WHITE8 }; + }; + + struct R10G10B12 { + Byte4 r : 10; + Byte4 g : 10; + Byte4 b : 12; + }; + + struct RGB16_565 { + Byte2 b : 5; + Byte2 g : 6; + Byte2 r : 5; + + RGB16_565() : b(BLACK8), g(BLACK8), r(BLACK8) {} + RGB16_565(Byte pR, Byte pG, Byte pB) : b(pB), g(pG), r(pR) {} + }; + + struct R8 { + Byte r { BLACK8 }; + }; + + + template const P mix(const P p0, const P p1, const S alpha) { return p0; } + template <> const RGB16_565 mix(const RGB16_565 p0, const RGB16_565 p1, const Byte alpha); + + template ::type > class Pixel { + public: + using This = Pixel; + using Format = F; + using Storage = S; + + static const uint32_t SIZE { sizeof(S) }; + + Format val { Format() }; + + Pixel() : val(Format()) {}; + Pixel(Format v) : val(v) {} + Pixel(Storage s) : val(*static_cast (&s)) {} + + const Storage* storage() const { return static_cast (&val); } + + static This* cast(Storage* s) { return reinterpret_cast(s); } + static const This* cast(const Storage* s) { return reinterpret_cast(s); } + }; + + template class PixelBlock { + public: + using Format = typename P::Format; + using Storage = typename P::Storage; + + static const uint16_t LENGTH { length }; + static const uint32_t SIZE { length * sizeof(P) }; + + P pixels[length]; + + PixelBlock() {} + + PixelBlock(const P* srcPixels) { + setPixels(srcPixels); + } + + void setPixels(const P* srcPixels) { + memcpy(pixels, srcPixels, SIZE); + } + + const Storage* storage() const { return pixels->storage(); } + }; + + template class Tile { + public: + using Format = typename P::Format; + using Storage = typename P::Storage; + + using Block = PixelBlock; + + uint16_t getWidth() const { return tileW; } + uint16_t getHeight() const { return tileH; } + + Block _block; + + Tile() {} + Tile(const P* srcPixels) : _block(srcPixels) {} + + + }; + }; + + + + using PixRGB565 = pixel::Pixel; + using PixRGB32 = pixel::Pixel; + using PixRGBA32 = pixel::Pixel; + using PixR10G10B12 = pixel::Pixel; + using PixR8 = pixel::Pixel; + + + class BC { + public: + static int cpp; + + struct BC1 { + PixRGB565 color0; + PixRGB565 color1; + Byte4 table; + }; + + struct BC4 { + PixRGB565 color0; + PixRGB565 color1; + Byte4 table; + }; + }; + + template ::type> class CompressedBlock { + public: + using Format = F; + using Storage = S; + + static const uint32_t SIZE { sizeof(F) }; + + Format bc; + + CompressedBlock() {} + + const Storage* storage() const { return static_cast (&bc); } + }; + + + template void compress(const PB& srcBlock, CB& dstBlock) { } + template void uncompress(const CB& srcBlock, PB& dstBlock) { } + + + using PB_RGB32 = pixel::PixelBlock; + using PB_RGBA32 = pixel::PixelBlock; + + using CB_BC1 = CompressedBlock; + using CB_BC4 = CompressedBlock; + + template <> void compress(const PB_RGB32& src, CB_BC1& dst); + template <> void compress(const PB_RGBA32& src, CB_BC4& dst); + + template <> void uncompress(const CB_BC1& src, PB_RGB32& dst); + template <> void uncompress(const CB_BC4& src, PB_RGBA32& dst); + + + template + class PixelArray { + public: + using This = PixelArray

; + using Pixel = P; + using Storage = typename P::Storage; + + static int evalNumPixels(size_t byteSize) { + size_t numPixels = byteSize / Pixel::SIZE; + if (byteSize > numPixels * Pixel::SIZE) { + numPixels++; + } + return (int)numPixels; + }; + static size_t evalByteSize(int numPixels) { + return numPixels * Pixel::SIZE; + }; + + struct Storages { + Storage* _bytes {nullptr}; + Count _count {0}; + + Storage* data() { + return _bytes; + } + const Storage* data() const { + return _bytes; + } + + Count count() const { return _count; } + + ~Storages() { if (_bytes) { delete _bytes; } } + Storages() {} + Storages(Count c) : _count(c) { if (_count) { _bytes = new Storage[_count]; } + + } + }; + + + + PixelArray() { + resetBytes(0, nullptr); + } + PixelArray(size_t byteSize, const void* bytes) { + resetBytes(byteSize, bytes); + } + PixelArray(const PixelArray& src) { + resetBytes(src.byteSize(), src.readBytes(0)); + } + PixelArray(PixelArray&& src) { + _buffer.reset(src._buffer.release()); + } + This& operator = (This&& src) { + _buffer.reset(src._buffer.release()); + } + + int numPixels() const { return _buffer->count(); } + size_t byteSize() const { return evalByteSize(_buffer->count()); } + + //access storage or pixel types at index in the buffer + const Storage* readBytes(const Index index) const { return _buffer->data() + index; } + const Pixel* readPixel(const Index index) const { return Pixel::cast(readBytes(index)); } + + Storage* editBytes(const Index index) { return _buffer->data() + index; } + Pixel* editPixel(const Index index) { return Pixel::cast(editBytes(index)); } + + private: + std::unique_ptr _buffer; + + void resetBytes(size_t byteSize, const void* bytes) { + _buffer.reset(new Storages(evalNumPixels(byteSize))); + if (bytes) { + memcpy(_buffer->data(), bytes, byteSize); + } + } + }; + + template + class PixelBlockArray { + public: + using Block = B; + using Blocks = std::vector; + + static int evalNumBlocks(size_t byteSize) { + size_t numBlocks = byteSize / Block::SIZE; + if (byteSize > numBlocks * Block::SIZE) { + numBlocks++; + } + return (int) numBlocks; + }; + static size_t evalByteSize(int numBlocks) { + return numBlocks * Block::SIZE; + }; + + PixelBlockArray(size_t byteSize, const void* bytes) { + setBytes(byteSize, bytes); + } + + int numBlocks() const { return evalByteSize(_blocks.size()); } + size_t byteSize() const { return evalByteSize(_blocks.size()); } + + Blocks _blocks; + + private: + void setBytes(size_t byteSize, const void* bytes) { + _blocks = Blocks(evalNumBlocks(byteSize)); + if (bytes) { + memcpy(_blocks.data(), bytes, byteSize); + } + } + }; + + class Grid { + public: + using Coord = uint16_t; + using Coord2 = glm::u16vec2; + using Size = uint32_t; + + static const Coord2 TILE_PIXEL; + static const Coord2 TILE_QUAD; + static const Coord2 TILE_DEFAULT; + + Grid(const Coord2& surface, const Coord2& tile = TILE_DEFAULT) : _surface(surface), _tile(tile) {} + Grid(Coord width, Coord height, const Coord2& tile = TILE_DEFAULT) : _surface(width, height), _tile(tile) {} + + Coord2 _surface { 1, 1 }; + Coord2 _tile { TILE_DEFAULT }; + + Coord width() const { return _surface.x; } + Coord height() const { return _surface.y; } + const Coord2& size() const { return _surface; } + + Coord tileWidth() const { return evalNumTiles(_surface.x, _tile.x); } + Coord tileHeight() const { return evalNumTiles(_surface.y, _tile.y); } + Coord2 tileSize() const { return Coord2(tileWidth(), tileHeight()); } + + + Coord2 toTile(const Coord2& pixel) const { return pixel / _tile; } + Coord2 toTileSubpix(const Coord2& pixel) const { return pixel % _tile; } + Coord2 toTile(const Coord2& pixel, Coord2& subpix) const { + subpix = toTileSubpix(pixel); + return toTile(pixel); + } + + Coord2 toPixel(const Coord2& tile) const { return tile * _tile; } + Coord2 toPixel(const Coord2& tile, const Coord2& subpix) const { return tile * _tile + subpix; } + + + static Coord evalNumTiles(Coord pixelLength, Coord tileLength) { + auto tilePos = pixelLength / tileLength; + if (tilePos * tileLength < pixelLength) { + tilePos++; + } + return tilePos; + } + }; + + template + class Tilemap { + public: + using Tile = T; + using Block = typename T::Block; + + Grid _grid; + PixelBlockArray _blocks; + + void resize(const Grid::Coord2& widthHeight) { + _grid = Grid(widthHeight, Coord2(Tile::getWidth(), Tile::getHeight())); + + } + + }; + + class Dim { + public: + + Coord2 _dims { 0 }; + + static Coord cap(Coord c) { return (c < MAX_COORD ? c : MAX_COORD); } + static Coord2 cap(const Coord2& dims) { return Coord2(cap(dims.x), cap(dims.y)); } + + static Count numPixels(const Coord2& dims) { return Count(cap(dims.x)) * Count(cap(dims.y)); } + + + static Coord nextMip(Coord c) { return (c > 1 ? (c >> 1) : c); } + static Coord2 nextMip(const Coord2& dims) { return Coord2(nextMip(dims.x), nextMip(dims.y)); } + + Dim(Coord w, Coord h) : _dims(w, h) {} + Dim(const Coord2& dims) : _dims(dims) {} + + Count numPixels() const { return Dim::numPixels(_dims); } + Dim nextMip() const { return Dim(nextMip(_dims)); } + + int maxLevel() const { + int level = 0; + auto dim = (*this); + while (dim._dims.x > 1 || dim._dims.y > 1) { + level++; + dim = dim.nextMip(); + } + return level; + } + + Index indexAt(Coord x, Coord y) const { return (Index) y * (Index) _dims.x + (Index) x; } + }; + + template < typename P > class Surface { + public: + using This = Surface

; + using Pixel = P; + using Format = typename P::Format; + using Pixels = PixelArray

; + + Dim _dim { 0, 0 }; + Pixels _pixels; + + /* Surface(This&& src) { + _dim = src._dim; + _pixels = src._pixels; + + }*/ + Surface(Coord width, Coord height, size_t byteSize = 0, const void* bytes = nullptr) : + _dim(width, height), + _pixels((byteSize ? byteSize : Pixels::evalByteSize(width * height)), bytes) + {} + + This nextMip() const { + Dim subDim = _dim.nextMip(); + auto sub = Surface

(subDim._dims.x, subDim._dims.y); + + for (int y = 0; y < subDim._dims.y; y++) { + for (int x = 0; x < subDim._dims.x; x++) { + + // get pixels from source at 2x, 2x +1 2y, 2y +1 + auto srcIndex0 = _dim.indexAt(2 * x, 2 * y); + auto srcIndex1 = _dim.indexAt(2 * x, 2 * y + 1); + + auto srcP0 = (*_pixels.readPixel(srcIndex0)); + auto srcP01 = (*_pixels.readPixel(srcIndex0 + 1)); + auto srcP1 = (*_pixels.readPixel(srcIndex1)); + auto srcP11 = (*_pixels.readPixel(srcIndex1 + 1)); + + // and filter + auto destIndex = subDim.indexAt(x, y); + auto destP = sub._pixels.editPixel(destIndex); + + // assign to dest + *destP = srcP0; + } + } + return sub; + } + + void downsample(std::vector& mips, int num) const { + if (num == 0) { + return; + } + auto maxLevel = _dim.maxLevel(); + + if (num == -1 || num > maxLevel) { + num = maxLevel; + } + else if (num < -1) { + return; + } + + + mips.emplace_back(nextMip()); + + for (int i = 1; i < num; i++) { + mips.emplace_back(mips.back().nextMip()); + } + + } + + }; +} + diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index e4fc8420da..feca360531 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -17,7 +17,7 @@ #include #include "ModelLogging.h" - +#include using namespace model; using namespace gpu; @@ -142,8 +142,9 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val validAlpha = (numOpaques != NUM_PIXELS); } - if (!validAlpha && image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); + //if (!validAlpha && image.format() != QImage::Format_RGB888) { + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); } return image; @@ -254,10 +255,57 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag } theTexture->setUsage(usage.build()); - theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); + + /* image::PixRGB32 pix0; + + image::PixRGBA32 pix1; + + image::PixR8 pix2; + + image::PixRGB565 pix3; + + image::PB_RGB32 pb0; + image::PB_RGB32 pb1; + + auto pix0_s = sizeof(pix0); + auto pix1_s = sizeof(pix1); + auto pix2_s = sizeof(pix2); + auto pix3_s = sizeof(pix3); + + auto pb0_s = sizeof(pb0); + +*/ + + bool check = false; + if (image.width() == 2048) { + check = true; + } + image::Surface surface(image.width(), image.height(), image.byteCount(), image.constBits()); + + + theTexture->assignStoredMip(0, formatMip, surface._pixels.byteSize(), (const Byte *) surface._pixels.readBytes(0)); + + + // theMap(image.width(), image.height(), image.byteCount(), image.constBits()); if (generateMips) { - ::generateMips(theTexture, image, formatMip); + + { + + PROFILE_RANGE(resource_parse, "generateMipsSAM"); + auto numMips = theTexture->evalNumMips(); + + std::vector> mips; + + surface.downsample(mips, numMips); + + for (uint16 level = 1; level < numMips && (mips.size() <= level); ++level) { + + const auto& m = mips[level - 1]; + theTexture->assignStoredMip(level, formatMip, m._pixels.byteSize(), (const Byte *) m._pixels.readBytes(0)); + } + } + // ::generateMips(theTexture, image, formatMip); } } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index e1627f2fd6..665e063a6e 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1178,7 +1178,7 @@ void Model::updateClusterMatrices() { for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); auto jointMatrix = _rig->getJointTransform(cluster.jointIndex); -#if GLM_ARCH & GLM_ARCH_SSE2 +#if (GLM_ARCH & GLM_ARCH_SSE2) && !(defined Q_OS_MACOS) glm::mat4 out, inverseBindMatrix = cluster.inverseBindMatrix; glm_mat4_mul((glm_vec4*)&jointMatrix, (glm_vec4*)&inverseBindMatrix, (glm_vec4*)&out); state.clusterMatrices[j] = out;