// Copyright (C) 1996 Keith Whitwell. // This file may only be copied under the terms of the GNU Library General // Public License - see the file COPYING in the lib3d distribution. #ifndef VectorInlines #define VectorInlines #include #include #include inline Vector3::Vector3() { } inline void Vector3::sub( const Vector3 &a, const Vector3 &b ) { v[0] = a.v[0] - b.v[0]; v[1] = a.v[1] - b.v[1]; v[2] = a.v[2] - b.v[2]; } inline void Vector3::add( const Vector3 &a, const Vector3 &b ) { v[0] = a.v[0] + b.v[0]; v[1] = a.v[1] + b.v[1]; v[2] = a.v[2] + b.v[2]; } inline void Vector3::add( const Vector3 &b ) { v[0] += b.v[0]; v[1] += b.v[1]; v[2] += b.v[2]; } inline void Vector3::clamp( float top ) { v[0] = min(top, v[0]); v[1] = min(top, v[1]); v[2] = min(top, v[2]); } inline bool Vector3::operator==( const Vector3 &b ) const { return (v[0] == b.v[0] && v[1] == b.v[1] && v[2] == b.v[2]); } inline bool Vector3::operator!=( const Vector3 &b ) const { return (v[0] != b.v[0] || v[1] != b.v[1] || v[2] != b.v[2]); } inline void Vector3::mul( const Matrix34 &m, const Vector3 &p ) { v[0] = float((m.v[0][0] * p.v[0]) + (m.v[0][1] * p.v[1]) + (m.v[0][2] * p.v[2]) + (m.v[0][3])); v[1] = float((m.v[1][0] * p.v[0]) + (m.v[1][1] * p.v[1]) + (m.v[1][2] * p.v[2]) + (m.v[1][3])); v[2] = float((m.v[2][0] * p.v[0]) + (m.v[2][1] * p.v[1]) + (m.v[2][2] * p.v[2]) + (m.v[2][3])); } inline void Vector3::mul_T( const Matrix34 &m, const Vector3 &p ) { v[0] = float((m.v[0][0] * p.v[0]) + (m.v[0][1] * p.v[1]) + (m.v[0][2] * p.v[2])); v[1] = float((m.v[1][0] * p.v[0]) + (m.v[1][1] * p.v[1]) + (m.v[1][2] * p.v[2])); v[2] = float((m.v[2][0] * p.v[0]) + (m.v[2][1] * p.v[1]) + (m.v[2][2] * p.v[2])); } inline void Vector3::assign( float a, float b, float c ) { v[0] = a; v[1] = b; v[2] = c; } inline void Vector3::assign( const Vector3 &a ) { v[0] = a.v[0]; v[1] = a.v[1]; v[2] = a.v[2]; } inline void Vector3::scale( const Vector3 &a ) { v[0] *= a.v[0]; v[1] *= a.v[1]; v[2] *= a.v[2]; } inline void Vector3::scale( const Vector3 &a, float s ) { v[0] = a.v[0] * s; v[1] = a.v[1] * s; v[2] = a.v[2] * s; } inline void Vector3::scale( float s ) { v[0] *= s; v[1] *= s; v[2] *= s; } inline void Vector3::mul( const Matrix34 &m ) { float x = v[0]; float y = v[1]; float z = v[2]; v[0] = float((m.v[0][0] * x) + (m.v[0][1] * y) + (m.v[0][2] * z) + (m.v[0][3])); v[1] = float((m.v[1][0] * x) + (m.v[1][1] * y) + (m.v[1][2] * z) + (m.v[1][3])); v[2] = float((m.v[2][0] * x) + (m.v[2][1] * y) + (m.v[2][2] * z) + (m.v[2][3])); } inline void Vector3::mul_T( const Matrix34 &m ) { float x = v[0]; float y = v[1]; float z = v[2]; v[0] = float((m.v[0][0] * x) + (m.v[0][1] * y) + (m.v[0][2] * z)); v[1] = float((m.v[1][0] * x) + (m.v[1][1] * y) + (m.v[1][2] * z)); v[2] = float((m.v[2][0] * x) + (m.v[2][1] * y) + (m.v[2][2] * z)); } inline float dot( const Vector3 &v1, const Vector3 &v2 ) { return (v1.v[0] * v2.v[0] + v1.v[1] * v2.v[1] + v1.v[2] * v2.v[2]); } inline DeviceVector::DeviceVector( int x, int y, int z ) { v[0] = x; v[1] = y; v[2] = z; } inline float DeviceVector::project( const Matrix4 &m, const Vector3 &p ) { float w = 1/float((m.v[3][0] * p.v[0]) + (m.v[3][1] * p.v[1]) + (m.v[3][2] * p.v[2]) + (m.v[3][3])); v[0] = int(((m.v[0][0] * p.v[0]) + (m.v[0][1] * p.v[1]) + (m.v[0][2] * p.v[2]) + (m.v[0][3])) * w); v[1] = int(((m.v[1][0] * p.v[0]) + (m.v[1][1] * p.v[1]) + (m.v[1][2] * p.v[2]) + (m.v[1][3])) * w); v[2] = int(((m.v[2][0] * p.v[0]) + (m.v[2][1] * p.v[1]) + (m.v[2][2] * p.v[2]) + (m.v[2][3])) * w); return w; } inline uint Vector3::computeOutcodes( float front ) const { #if 0 // Adapted from graphics gems IV, doesn't suffer from // hidden precision problems. #define NUMBITS sizeof(int)*8 #define v(x) *(int *) &(x) // fint(x) #define s(x) (((unsigned int)(x)) >> (NUMBITS-1)) // sign bit #define a(x) ((x) & ~(1 << (NUMBITS-1))) // fint(abs(x)) static float one = 1.0; static int i_one = v(one); uint oc; int i_D = v(front); int iz = v(v[Z]); int abs_z = a(iz); int s_iz = s(iz); // Compare Z against D and 1.0 oc = (s(i_one - abs_z) & s_iz); oc |= (s(abs_z - i_D) | s_iz) << 1; int ix = v(v[X]); int diff_x = s(abs_z - a(ix)); int tx = s(ix) + 4; oc |= diff_x << tx; int iy = v(v[Y]); int diff_y = s(abs_z - a(iy)); int ty = s(iy) + 2; oc |= diff_y << ty; return oc; #else // Can return incorrect results if your fpu holds more than 32 // bits of precision internally, and the function is inlined // immediately after the transformation of the vector. // As implemented, both approaches give about the same performance // on a Pentium in 32 bit fpu precision. uint outcodes = 0; if (v[Z] >= 1.0) outcodes |= 0x01; if (v[Z] <= front) outcodes |= 0x02; if (v[Y] >= v[Z]) outcodes |= 0x04; if (v[Y] <= -v[Z]) outcodes |= 0x08; if (v[X] >= v[Z]) outcodes |= 0x10; if (v[X] <= -v[Z]) outcodes |= 0x20; return outcodes; #endif } inline void Vector3::normalize() { float t = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] ); if (t == 0) return; float l = 1.0/t; v[0] *= l; v[1] *= l; v[2] *= l; } inline float Vector3::magnitude() { return sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] ); } inline Vector4::Vector4() { } inline void Vector4::assign( float i, float j, float k, float l ) { v[0] = i; v[1] = j; v[2] = k; v[3] = l; } inline Vector4 & Vector4::operator=(const float tmp[4]) { memcpy(v, tmp, sizeof(v)); return *this; } inline Vector4 & Vector4::operator=(const Vector4 &t) { memcpy(v, t.v, sizeof(v)); return *this; } #endif