|
|
@@ -3759,4 +3759,194 @@ namespace bimg
|
|
|
return total;
|
|
|
}
|
|
|
|
|
|
+ // +----------+
|
|
|
+ // |-z 2|
|
|
|
+ // | ^ +y |
|
|
|
+ // | | |
|
|
|
+ // | +---->+x |
|
|
|
+ // +----------+----------+----------+----------+
|
|
|
+ // |+y 1|+y 4|+y 0|+y 5|
|
|
|
+ // | ^ -x | ^ +z | ^ +x | ^ -z |
|
|
|
+ // | | | | | | | | |
|
|
|
+ // | +---->+z | +---->+x | +---->-z | +---->-x |
|
|
|
+ // +----------+----------+----------+----------+
|
|
|
+ // |+z 3|
|
|
|
+ // | ^ -y |
|
|
|
+ // | | |
|
|
|
+ // | +---->+x |
|
|
|
+ // +----------+
|
|
|
+ //
|
|
|
+ struct CubeMapFace
|
|
|
+ {
|
|
|
+ float uv[3][3];
|
|
|
+ };
|
|
|
+
|
|
|
+ static const CubeMapFace s_cubeMapFace[] =
|
|
|
+ {
|
|
|
+ {{ // +x face
|
|
|
+ { 0.0f, 0.0f, -1.0f }, // u -> -z
|
|
|
+ { 0.0f, -1.0f, 0.0f }, // v -> -y
|
|
|
+ { 1.0f, 0.0f, 0.0f }, // +x face
|
|
|
+ }},
|
|
|
+ {{ // -x face
|
|
|
+ { 0.0f, 0.0f, 1.0f }, // u -> +z
|
|
|
+ { 0.0f, -1.0f, 0.0f }, // v -> -y
|
|
|
+ { -1.0f, 0.0f, 0.0f }, // -x face
|
|
|
+ }},
|
|
|
+ {{ // +y face
|
|
|
+ { 1.0f, 0.0f, 0.0f }, // u -> +x
|
|
|
+ { 0.0f, 0.0f, 1.0f }, // v -> +z
|
|
|
+ { 0.0f, 1.0f, 0.0f }, // +y face
|
|
|
+ }},
|
|
|
+ {{ // -y face
|
|
|
+ { 1.0f, 0.0f, 0.0f }, // u -> +x
|
|
|
+ { 0.0f, 0.0f, -1.0f }, // v -> -z
|
|
|
+ { 0.0f, -1.0f, 0.0f }, // -y face
|
|
|
+ }},
|
|
|
+ {{ // +z face
|
|
|
+ { 1.0f, 0.0f, 0.0f }, // u -> +x
|
|
|
+ { 0.0f, -1.0f, 0.0f }, // v -> -y
|
|
|
+ { 0.0f, 0.0f, 1.0f }, // +z face
|
|
|
+ }},
|
|
|
+ {{ // -z face
|
|
|
+ { -1.0f, 0.0f, 0.0f }, // u -> -x
|
|
|
+ { 0.0f, -1.0f, 0.0f }, // v -> -y
|
|
|
+ { 0.0f, 0.0f, -1.0f }, // -z face
|
|
|
+ }},
|
|
|
+ };
|
|
|
+
|
|
|
+ /// _u and _v should be center addressing and in [-1.0+invSize..1.0-invSize] range.
|
|
|
+ void texelUvToDir(float* _result, uint8_t _side, float _u, float _v)
|
|
|
+ {
|
|
|
+ const CubeMapFace& face = s_cubeMapFace[_side];
|
|
|
+
|
|
|
+ float tmp[3];
|
|
|
+ tmp[0] = face.uv[0][0] * _u + face.uv[1][0] * _v + face.uv[2][0];
|
|
|
+ tmp[1] = face.uv[0][1] * _u + face.uv[1][1] * _v + face.uv[2][1];
|
|
|
+ tmp[2] = face.uv[0][2] * _u + face.uv[1][2] * _v + face.uv[2][2];
|
|
|
+ bx::vec3Norm(_result, tmp);
|
|
|
+ }
|
|
|
+
|
|
|
+ void latLongFromDir(float* _outU, float* _outV, const float* _in)
|
|
|
+ {
|
|
|
+ const float phi = bx::fatan2(_in[0], _in[2]);
|
|
|
+ const float theta = bx::facos(_in[1]);
|
|
|
+
|
|
|
+ *_outU = (bx::kPi + phi)/bx::kPi2;
|
|
|
+ *_outV = theta*bx::kInvPi;
|
|
|
+ }
|
|
|
+
|
|
|
+ ImageContainer* imageCubemapFromLatLongRgba32F(bx::AllocatorI* _allocator, const ImageContainer& _input, bool _useBilinearInterpolation, bx::Error* _err)
|
|
|
+ {
|
|
|
+ BX_ERROR_SCOPE(_err);
|
|
|
+
|
|
|
+ if (_input.m_depth != 1
|
|
|
+ && _input.m_numLayers != 1
|
|
|
+ && _input.m_format != TextureFormat::RGBA32F
|
|
|
+ && _input.m_width/2 != _input.m_height)
|
|
|
+ {
|
|
|
+ BX_ERROR_SET(_err, BIMG_ERROR, "Input image format is not equirectangular projection.");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ const uint32_t srcWidthMinusOne = _input.m_width-1;
|
|
|
+ const uint32_t srcHeightMinusOne = _input.m_height-1;
|
|
|
+ const uint32_t srcPitch = _input.m_width*16;
|
|
|
+ const uint32_t dstWidth = _input.m_height/2;
|
|
|
+ const uint32_t dstPitch = dstWidth*16;
|
|
|
+ const float invDstWidth = 1.0f / float(dstWidth);
|
|
|
+
|
|
|
+ ImageContainer* output = imageAlloc(_allocator
|
|
|
+ , _input.m_format
|
|
|
+ , uint16_t(dstWidth)
|
|
|
+ , uint16_t(dstWidth)
|
|
|
+ , uint16_t(1)
|
|
|
+ , 1
|
|
|
+ , true
|
|
|
+ , false
|
|
|
+ );
|
|
|
+
|
|
|
+ const uint8_t* srcData = (const uint8_t*)_input.m_data;
|
|
|
+
|
|
|
+ for (uint8_t side = 0; side < 6 && _err->isOk(); ++side)
|
|
|
+ {
|
|
|
+ ImageMip mip;
|
|
|
+ imageGetRawData(*output, side, 0, output->m_data, output->m_size, mip);
|
|
|
+
|
|
|
+ for (uint32_t yy = 0; yy < dstWidth; ++yy)
|
|
|
+ {
|
|
|
+ for (uint32_t xx = 0; xx < dstWidth; ++xx)
|
|
|
+ {
|
|
|
+ float* dstData = (float*)&mip.m_data[yy*dstPitch+xx*16];
|
|
|
+
|
|
|
+ const float uu = 2.0f*xx*invDstWidth - 1.0f;
|
|
|
+ const float vv = 2.0f*yy*invDstWidth - 1.0f;
|
|
|
+
|
|
|
+ float dir[3];
|
|
|
+ texelUvToDir(dir, side, uu, vv);
|
|
|
+
|
|
|
+ float srcU, srcV;
|
|
|
+ latLongFromDir(&srcU, &srcV, dir);
|
|
|
+
|
|
|
+ srcU *= srcWidthMinusOne;
|
|
|
+ srcV *= srcHeightMinusOne;
|
|
|
+
|
|
|
+ if (_useBilinearInterpolation)
|
|
|
+ {
|
|
|
+ const uint32_t x0 = uint32_t(srcU);
|
|
|
+ const uint32_t y0 = uint32_t(srcV);
|
|
|
+ const uint32_t x1 = bx::min(x0 + 1, srcWidthMinusOne);
|
|
|
+ const uint32_t y1 = bx::min(y0 + 1, srcHeightMinusOne);
|
|
|
+
|
|
|
+ const float* src0 = (const float*)&srcData[y0*srcPitch + x0*16];
|
|
|
+ const float* src1 = (const float*)&srcData[y0*srcPitch + x1*16];
|
|
|
+ const float* src2 = (const float*)&srcData[y1*srcPitch + x0*16];
|
|
|
+ const float* src3 = (const float*)&srcData[y1*srcPitch + x1*16];
|
|
|
+
|
|
|
+ const float tx = srcU - float(int32_t(x0) );
|
|
|
+ const float ty = srcV - float(int32_t(y0) );
|
|
|
+ const float omtx = 1.0f - tx;
|
|
|
+ const float omty = 1.0f - ty;
|
|
|
+
|
|
|
+ float p0[4];
|
|
|
+ bx::vec4Mul(p0, src0, omtx*omty);
|
|
|
+
|
|
|
+ float p1[4];
|
|
|
+ bx::vec4Mul(p1, src1, tx*omty);
|
|
|
+
|
|
|
+ float p2[4];
|
|
|
+ bx::vec4Mul(p2, src2, omtx*ty);
|
|
|
+
|
|
|
+ float p3[4];
|
|
|
+ bx::vec4Mul(p3, src3, tx*ty);
|
|
|
+
|
|
|
+ const float rr = p0[0] + p1[0] + p2[0] + p3[0];
|
|
|
+ const float gg = p0[1] + p1[1] + p2[1] + p3[1];
|
|
|
+ const float bb = p0[2] + p1[2] + p2[2] + p3[2];
|
|
|
+ const float aa = p0[3] + p1[3] + p2[3] + p3[3];
|
|
|
+
|
|
|
+ dstData[0] = rr;
|
|
|
+ dstData[1] = gg;
|
|
|
+ dstData[2] = bb;
|
|
|
+ dstData[3] = aa;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ const uint32_t x0 = uint32_t(srcU);
|
|
|
+ const uint32_t y0 = uint32_t(srcV);
|
|
|
+ const float* src0 = (const float*)&srcData[y0*srcPitch + x0*16];
|
|
|
+
|
|
|
+ dstData[0] = src0[0];
|
|
|
+ dstData[1] = src0[1];
|
|
|
+ dstData[2] = src0[2];
|
|
|
+ dstData[3] = src0[3];
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return output;
|
|
|
+ }
|
|
|
+
|
|
|
} // namespace bimg
|