Thanks a lot guys.
I've never actually heard of the spherical coordinate system before, so I'll check it out.
I tried out you code this morning Ashaman but it didn't seem to work correctly. My test app just gave completely wrong results. However, I did manage to create my own implementation. I'm not sure how good or correct it is, though. Below is the entire source code to my little test app with my implementation. It uses
GLM for the vector stuff in case anyone is wondering. It assumes that each component of the input normal is scaled and biased in the [0, 1] range.
#include <iostream>#include <conio.h>#include <glm/glm.h>using namespace glm;vec4 pack_normal(vec3 normal){ // Multiplying the vector by vec3(2048.0, 2048.0, 1024.0) results in values of 1 // not being represented correctly. Changing to these values seems to work alright. normal *= vec3(2047.0f, 2047.0f, 1023.0f); // The high part of the x axis is the first 8 bits. This is stored in the entire 8 // bits of the x component of the return value. The low part is the last 3 bits and // is stored in the first 3 bits of the y component of the return value. float x_hi = floor(normal.x * (1.0f / 8.0f)); float x_lo = floor(normal.x - x_hi * 8.0f) * 32.0f; // The high part of the y axis is the first 5 bits. This is stored in the lower 5 bits // of the y component of the return value. The low part is the last 6 bits and is stored // in the first 6 bits of the z component of the return value. float y_hi = floor(normal.y * (1.0f / 64.0f)); float y_lo = floor(normal.y - y_hi * 64.0f) * 4.0f; // The high part of the z axis is the first 2 bits. This is stored in the lower 2 bits // of the z component of the return value. The low part is the last 8 bits and is // stored in the entire alpah component of the return value. float z_hi = floor(normal.z * (1.0f / 256.0f)); float z_lo = floor(normal.z - z_hi * 256.0f); return vec4(x_hi, x_lo + y_hi, y_lo + z_hi, z_lo) / 255.0f;}vec3 unpack_normal(vec4 packedNormal){ packedNormal *= 255.0f; float x_hi = packedNormal.x * 8.0f; float x_lo = floor(packedNormal.y * (1.0f / 32.0f)); float y_hi = (packedNormal.y - x_lo * 32.0f) * 64.0f; float y_lo = floor(packedNormal.z * (1.0f / 4.0f)); float z_hi = (packedNormal.z - y_lo * 4.0f) * 256.0f; float z_lo = packedNormal.a; vec3 scale = vec3(1.0f / 2047.0f, 1.0f / 2047.0f, 1.0f / 1023.0f); return vec3(x_hi + x_lo, y_hi + y_lo, z_hi + z_lo) * scale;}void DoTest(vec3 normal){ vec4 packed = pack_normal(normal); vec3 unpacked = unpack_normal(packed); vec3 difference = normal - unpacked; std::cout << "Original Value: " << normal.x << " " << normal.y << " " << normal.z << std::endl; std::cout << "Packed Value: " << packed.x << " " << packed.y << " " << packed.z << " " << packed.a << std::endl; std::cout << "Unpacked Value: " << unpacked.x << " " << unpacked.y << " " << unpacked.z << std::endl; std::cout << "Difference: " << difference.x << " " << difference.y << " " << difference.z << std::endl << std::endl;}int main(){ // Do some tests. DoTest(vec3(1.0f, 1.0f, 1.0f)); DoTest(vec3(0.0f, 0.0f, 0.0f)); DoTest(vec3(0.25f, 0.5f, 0.75f)); DoTest(vec3(0.333f, 0.666f, 0.999f)); DoTest(vec3(0.123f, 0.123f, 0.123f)); DoTest(vec3(0.1f, 0.2f, 0.3f)); std::cout << "Finished testing..." << std::endl; _getch(); return 0;}
The results of those tests are as follows:
Original Value: 1 1 1Packed Value: 1 1 1 1Unpacked Value: 1 1 1Difference: 0 0 0Original Value: 0 0 0Packed Value: 0 0 0 0Unpacked Value: 0 0 0Difference: 0 0 0Original Value: 0.25 0.5 0.75Packed Value: 0.247059 0.937255 0.996078 1Unpacked Value: 0.249634 0.499756 0.749756Difference: 0.00036639 0.00024426 0.000244379Original Value: 0.333 0.666 0.999Packed Value: 0.333333 0.207843 0.309804 0.992157Unpacked Value: 0.332682 0.665852 0.998045Difference: 0.000318021 0.000147521 0.000955045Original Value: 0.123 0.123 0.123Packed Value: 0.121569 0.388235 0.92549 0.490196Unpacked Value: 0.122618 0.122618 0.12219Difference: 0.000381537 0.000381537 0.000810362Original Value: 0.1 0.2 0.3Packed Value: 0.0980392 0.52549 0.396078 0.196078Unpacked Value: 0.099658 0.199805 0.29912Difference: 0.000341967 0.000195414 0.000879765Finished testing...
So do those test results look alright? Is that the kind of precision I should expect? Also, is the actual algorithm I use to pack/unpack alright?
Thanks a lot.