00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 inline
00024 int IntSquareRoot(int n) {
00025 return static_cast<int>(sqrt(static_cast<double>(n)));
00026 }
00027
00028 inline
00029 bool IsSquare(int n) {
00030 return sheep::sq(IntSquareRoot(n)) == n;
00031 }
00032
00033 inline
00034 void VectorToSphericalCoords(const sheep::Vector3 &v,
00035 sheep::Real *phi,
00036 sheep::Real *theta)
00037 {
00038 assert(v.IsUnitLength());
00039 assert(phi);
00040 assert(theta);
00041
00042 *phi = atan2(v.m_z, v.m_x);
00043
00044 if(*phi < 0.0)
00045 *phi += 2.0 * sheep::PI;
00046
00047 *theta = acos(v.m_y);
00048
00049 assert(*phi >= 0.0 && *phi <= 2.0 * sheep::PI);
00050 assert(*theta >= 0.0 && *theta <= sheep::PI);
00051 }
00052
00053 inline
00054 sheep::Vector3 SphericalCoordsToVector(sheep::Real phi, sheep::Real theta) {
00055 const sheep::Real sin_theta = sin(theta);
00056
00057 const sheep::Vector3 v(
00058 cos(phi) * sin_theta,
00059 cos(theta),
00060 sin(phi) * sin_theta);
00061
00062 assert(v.IsUnitLength());
00063
00064 return v;
00065 }
00066
00067 inline
00068 void PackSphericalCoords(sheep::Real phi, sheep::Real theta,
00069 sheep::uint8 *qphi, sheep::uint8 *qtheta)
00070 {
00071 assert(qphi);
00072 assert(qtheta);
00073
00074 phi = sheep::NormalizeAngle(phi);
00075 theta = sheep::NormalizeAngle(theta);
00076
00077 assert(phi >= 0.0 && phi <= 2.0 * sheep::PI);
00078 assert(theta >= 0.0 && theta <= sheep::PI);
00079
00080 int qphi1 = static_cast<int>(phi * (128.0 / sheep::PI));
00081 assert(qphi1 >= 0 && qphi1 <= 256);
00082
00083 if(qphi1 > 255)
00084 *qphi = 255;
00085 else *qphi = static_cast<sheep::uint8>(qphi1);
00086
00087 int qtheta1 = static_cast<int>(theta * (256.0 / sheep::PI));
00088 assert(qtheta1 >= 0 && qtheta1 <= 256);
00089
00090 if(qtheta1 > 255)
00091 *qtheta = 255;
00092 else *qtheta = static_cast<sheep::uint8>(qtheta1);
00093 }
00094
00095 inline
00096 void UnpackSphericalCoords(sheep::uint8 qphi, sheep::uint8 qtheta,
00097 sheep::Real *phi, sheep::Real *theta)
00098 {
00099
00100 *phi = qphi * (sheep::PI / 128.0);
00101 *theta = qtheta * (sheep::PI / 256.0);
00102
00103 assert(*phi >= 0.0 && *phi <= 2.0 * sheep::PI);
00104 assert(*theta >= 0.0 && *theta <= sheep::PI);
00105 }
00106
00107 inline
00108 void PackSphericalCoords(sheep::Real phi, sheep::Real theta,
00109 sheep::uint8 *q)
00110 {
00111 assert(q);
00112
00113 phi = sheep::NormalizeAngle(phi);
00114 theta = sheep::NormalizeAngle(theta);
00115
00116 assert(phi >= 0.0 && phi <= 2.0 * sheep::PI);
00117 assert(theta >= 0.0 && theta <= sheep::PI);
00118
00119 int qphi = static_cast<int>(phi * (8.0 / sheep::PI));
00120 assert(qphi >= 0 && qphi <= 16);
00121
00122 if(qphi > 15)
00123 qphi = 15;
00124
00125 int qtheta = static_cast<int>(theta * (16.0 / sheep::PI));
00126 assert(qtheta >= 0 && qtheta <= 16);
00127
00128 if(qtheta > 15)
00129 qtheta = 15;
00130
00131 *q = (static_cast<sheep::uint8>(qphi) << 4) + static_cast<sheep::uint8>(qtheta);
00132 }
00133
00134 inline
00135 void UnpackSphericalCoords(sheep::uint8 q,
00136 sheep::Real *phi, sheep::Real *theta)
00137 {
00138
00139 sheep::uint8 qphi = q >> 4;
00140 sheep::uint8 qtheta = q & 15;
00141
00142 *phi = qphi * (sheep::PI / 8.0);
00143 *theta = qtheta * (sheep::PI / 16.0);
00144
00145 assert(*phi >= 0.0 && *phi <= 2.0 * sheep::PI);
00146 assert(*theta >= 0.0 && *theta <= sheep::PI);
00147 }
00148
00149 inline
00150 void PackDirection(const sheep::Vector3 &v,
00151 sheep::uint8 *qphi,
00152 sheep::uint8 *qtheta)
00153 {
00154 sheep::Real phi, theta;
00155 VectorToSphericalCoords(v, &phi, &theta);
00156 PackSphericalCoords(phi, theta, qphi, qtheta);
00157 }
00158
00159 inline
00160 void PackDirection(const sheep::Vector3 &v, sheep::uint8 *q) {
00161 sheep::Real phi, theta;
00162 VectorToSphericalCoords(v, &phi, &theta);
00163 PackSphericalCoords(phi, theta, q);
00164 }
00165
00166 inline
00167 sheep::Vector3 UnpackDirection(sheep::uint8 qphi, sheep::uint8 qtheta) {
00168 const sheep::Real sin_theta = ConversionTables::m_sin_theta[qtheta];
00169
00170 const sheep::Vector3 v(
00171 ConversionTables::m_cos_phi[qphi] * sin_theta,
00172 ConversionTables::m_cos_theta[qtheta],
00173 ConversionTables::m_sin_phi[qphi] * sin_theta);
00174
00175 assert(v.IsUnitLength());
00176
00177 return v;
00178 }
00179
00180 inline
00181 sheep::Vector3 UnpackDirection(sheep::uint8 q) {
00182 return ConversionTables::m_direction[q];
00183 }