Skip to content

Pack unit 3D vectors (such as normal vectors) into integer type

Notifications You must be signed in to change notification settings

akuukka/unitvectorpack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 

Repository files navigation

unitvectorpack

Efficient way to store 3D unit vectors (such as normals) into integers of desired size. Even 16 bits is enough for many applications.

The idea:

  • 3 bits are reserved for signs of x,y and z. This leaves us 7/6 (in the 16 bit case) or 15/14 (in the 32 bit case) for x and y components. Because we are dealing with unit vectors, there is no need to store any other information about the Z component than its sign.
  • Transform the vector to the octant with x>=0, y>=, z>=0.
  • Further transform the vector to the plane that passes through points (1,0,0),(0,1,0) and (0,0,1). Now x<=1,y<=1, x+y <= 1. Thus, (x,y) is inside the triangle defined by points (1,0),(0,1) and (0,0).
  • If y >= 0.5, then we transform x and y by the function (x,y) => (1-x,1-y). After this y is again less than 0.5. This gives us one extra bit of precision. Because this transform moves the point out of the triangle defined by points (1,0),(0,1) and (0,0), we can detect that the transform has been applied when we unpack the integer.

Example:

Vector3<float> v = random_unit_vector();
uint16_t vi = packUnitVector<uint16_t, float>(v);
Vector3<float> v2 = unpackUnitVector<Vector3<float>,float>(vi);
float error = v1.distanceTo(v2); // Quite small!

You can pass unnormalized vectors to packUnitVector. When the resulting integers are unpacked, you get unit vectors pointing to (approximately) the same direction as the original vector.

About

Pack unit 3D vectors (such as normal vectors) into integer type

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages