The Code-Bin
Links
Home
Add your code!
All Listings
About
Latest Entry
Featured Scripts
Author's Website
Latest Entries
FFMPEG Thumbnail Scr...
PHP, 0.8KB
Jul. 29, 10:24pm
John
Z80 Assembler, 190 bytes
Feb. 17, 3:36am
John
Z80 Assembler, 176 bytes
Sep. 13, 2:19am
John
Z80 Assembler, 77 bytes
Sep. 13, 2:18am
John
Z80 Assembler, 209 bytes
Sep. 13, 2:17am
Compressing Normals (and other unit vectors)
Posted by: aav | February 7, 2009 @ 4:12pm
Revision 1 - Original post on February 7, 2009 @ 4:07pm
C++ Code
[
Download
]
void TraceLine( float3 n, int3* pPoints, int& size ) { int x1 = 0; int y1 = 0; int z1 = 0; int x2 = n.x * (2<<24); int y2 = n.y * (2<<24); int z2 = n.z * (2<<24); int xd, yd, zd; int x, y, z; int ax, ay, az; int sx, sy, sz; int dx, dy, dz; dx = x2 - x1; dy = y2 - y1; dz = z2 - z1; ax = abs(dx) << 1; ay = abs(dy) << 1; az = abs(dz) << 1; sx = sign(dx); sy = sign(dy); sz = sign(dz); x = x1; y = y1; z = z1; size = 0; if (ax >= max(ay, az)) /* x dominant */ { yd = ay - (ax >> 1); zd = az - (ax >> 1); while( x*x < 127*127 ) { pPoints[size++] = int3( x, y, z ); if (yd >= 0) { y += sy; yd -= ax; } if (zd >= 0) { z += sz; zd -= ax; } x += sx; yd += ay; zd += az; } } else if (ay >= max(ax, az)) /* y dominant */ { xd = ax - (ay >> 1); zd = az - (ay >> 1); while( y*y < 127*127 ) { pPoints[size++] = int3( x, y, z ); if (xd >= 0) { x += sx; xd -= ay; } if (zd >= 0) { z += sz; zd -= ay; } y += sy; xd += ax; zd += az; } } else if (az >= max(ax, ay)) /* z dominant */ { xd = ax - (az >> 1); yd = ay - (az >> 1); while( z*z < 127*127 ) { pPoints[size++] = int3( x, y, z ); if (xd >= 0) { x += sx; xd -= az; } if (yd >= 0) { y += sy; yd -= az; } z += sz; xd += ax; yd += ay; } } assert( size <= 128 ); for( ; size < 128; size++ ) { pPoints[size] = int3(0,0,0); } } void NormalToUByte4( float3 n, unsigned char* pOutVec ) { n = normalize(n); // // Find the candidate points. // int3 points[128]; int pointCount = 0; TraceLine( n, &points[0], pointCount ); int3 best( 0, 0, 0 ); float bestError = std::numeric_limits<float>::max(); for( int i = 0; i < pointCount; i++ ) { float3 cf = normalize( float3( points[i].x, points[i].y, points[i].z ) ); float err = acos( dot( n, cf ) ); // Don't need the acos here really. Just to see the error in radians. if( err < bestError ) { bestError = err; best = points[i]; } } best.x = max( 0, min( 255, best.x + 128 ) ); best.y = max( 0, min( 255, best.y + 128 ) ); best.z = max( 0, min( 255, best.z + 128 ) ); #ifdef BENCHMARK float3 bf = normalize( float3(best.x,best.y,best.z) ); std::cout << " Input vector: " << n.x << ", " << n.y << ", " << n.z << std::endl; std::cout << " Result vec I: " << best.x << ", " << best.y << ", " << best.z << std::endl; std::cout << " Result vec F: " << bf.x << ", " << bf.y << ", " << bf.z << std::endl; std::cout << " Error: " << bestError << std::endl; std::cout << std::endl; #endif pOutVec[0] = best.x; pOutVec[1] = best.y; pOutVec[2] = best.z; pOutVec[3] = 0; }
Syntax Highlighting
[
Open in new window
]
Author Comments
none
Rating
4.37 / 8
116 Votes