Changeset 2111 for code/branches/objecthierarchy/src/util/Math.cc
- Timestamp:
- Nov 2, 2008, 12:38:26 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/objecthierarchy/src/util/Math.cc
r2019 r2111 38 38 #include "SubString.h" 39 39 40 /** 41 @brief Function for writing a Radian to a stream. 42 */ 43 std::ostream& operator<<(std::ostream& out, const orxonox::Radian& radian) 40 namespace orxonox 44 41 { 45 out << radian.valueRadians(); 46 return out; 42 /** 43 @brief Function for writing a Radian to a stream. 44 */ 45 std::ostream& operator<<(std::ostream& out, const orxonox::Radian& radian) 46 { 47 out << radian.valueRadians(); 48 return out; 49 } 50 51 /** 52 @brief Function for reading a Radian from a stream. 53 */ 54 std::istream& operator>>(std::istream& in, orxonox::Radian& radian) 55 { 56 float temp; 57 in >> temp; 58 radian = temp; 59 return in; 60 } 61 62 /** 63 @brief Function for writing a Degree to a stream. 64 */ 65 std::ostream& operator<<(std::ostream& out, const orxonox::Degree& degree) 66 { 67 out << degree.valueDegrees(); 68 return out; 69 } 70 71 /** 72 @brief Function for reading a Degree from a stream. 73 */ 74 std::istream& operator>>(std::istream& in, orxonox::Degree& degree) 75 { 76 float temp; 77 in >> temp; 78 degree = temp; 79 return in; 80 } 81 82 83 /** 84 @brief Gets the angle between my viewing direction and the direction to the position of the other object. 85 @param myposition My position 86 @param mydirection My viewing direction 87 @param otherposition The position of the other object 88 @return The angle 89 90 @example 91 If the other object is exactly in front of me, the function returns 0. 92 If the other object is exactly behind me, the function returns pi. 93 If the other object is exactly right/left to me (or above/below), the function returns pi/2. 94 */ 95 float getAngle(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& otherposition) 96 { 97 orxonox::Vector3 distance = otherposition - myposition; 98 float distancelength = distance.length(); 99 if (distancelength == 0) 100 return 0; 101 else 102 return acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1)); 103 } 104 105 /** 106 @brief Gets the 2D viewing direction (up/down, left/right) to the position of the other object. 107 @param myposition My position 108 @param mydirection My viewing direction 109 @param myorthonormal My orthonormalvector (pointing upwards through my head) 110 @param otherposition The position of the other object 111 @return The viewing direction 112 113 @example 114 If the other object is exactly in front of me, the function returns Vector2(0, 0). 115 If the other object is exactly at my left, the function returns Vector2(-1, 0). 116 If the other object is exactly at my right, the function returns Vector2(1, 0). 117 If the other object is only a bit at my right, the function still returns Vector2(1, 0). 118 If the other object is exactly above me, the function returns Vector2(0, 1). 119 */ 120 orxonox::Vector2 get2DViewdirection(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition) 121 { 122 orxonox::Vector3 distance = otherposition - myposition; 123 124 // project difference vector on our plane 125 orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance); 126 127 float projectionlength = projection.length(); 128 if (projectionlength == 0) return orxonox::Vector2(0, 0); 129 float angle = acos(clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1)); 130 131 if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0) 132 return orxonox::Vector2(sin(angle), cos(angle)); 133 else 134 return orxonox::Vector2(-sin(angle), cos(angle)); 135 } 136 137 /** 138 @brief Gets the 2D viewing direction (up/down, left/right) to the position of the other object, multiplied with the viewing distance to the object (0° = 0, 180° = 1). 139 @param myposition My position 140 @param mydirection My viewing direction 141 @param myorthonormal My orthonormalvector (pointing upwards through my head) 142 @param otherposition The position of the other object 143 @return The viewing direction 144 145 @example 146 If the other object is exactly in front of me, the function returns Vector2(0, 0). 147 If the other object is exactly at my left, the function returns Vector2(-0.5, 0). 148 If the other object is exactly at my right, the function returns Vector2(0.5, 0). 149 If the other object is only a bit at my right, the function still returns Vector2(0.01, 0). 150 If the other object is exactly above me, the function returns Vector2(0, 0.5). 151 */ 152 orxonox::Vector2 get2DViewcoordinates(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition) 153 { 154 orxonox::Vector3 distance = otherposition - myposition; 155 156 // project difference vector on our plane 157 orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance); 158 159 float projectionlength = projection.length(); 160 if (projectionlength == 0) return orxonox::Vector2(0, 0); 161 float angle = acos(clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1)); 162 163 float distancelength = distance.length(); 164 if (distancelength == 0) return orxonox::Vector2(0, 0); 165 float radius = acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1)) / Ogre::Math::PI; 166 167 if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0) 168 return orxonox::Vector2(sin(angle) * radius, cos(angle) * radius); 169 else 170 return orxonox::Vector2(-sin(angle) * radius, cos(angle) * radius); 171 } 172 173 /** 174 @brief Returns the predicted position I have to aim at, if I want to hit a moving target with a moving projectile. 175 @param myposition My position 176 @param projectilespeed The speed of my projectile 177 @param targetposition The position of my target 178 @param targetvelocity The velocity of my target 179 @return The predicted position 180 181 The function predicts the position based on a linear velocity of the target. If the target changes speed or direction, the projectile will miss. 182 */ 183 orxonox::Vector3 getPredictedPosition(const orxonox::Vector3& myposition, float projectilespeed, const orxonox::Vector3& targetposition, const orxonox::Vector3& targetvelocity) 184 { 185 float squaredProjectilespeed = projectilespeed * projectilespeed; 186 orxonox::Vector3 distance = targetposition - myposition; 187 float a = distance.squaredLength(); 188 float b = 2 * (distance.x + distance.y + distance.z) * (targetvelocity.x + targetvelocity.y + targetvelocity.z); 189 float c = targetvelocity.squaredLength(); 190 191 float temp = 4*squaredProjectilespeed*c + a*a - 4*b*c; 192 if (temp < 0) 193 return orxonox::Vector3::ZERO; 194 195 temp = sqrt(temp); 196 float time = (temp + a) / (2 * (squaredProjectilespeed - b)); 197 return (targetposition + targetvelocity * time); 198 } 199 200 unsigned long getUniqueNumber() 201 { 202 static unsigned long aNumber = 135; 203 return aNumber++; 204 } 205 206 207 ////////////////////////// 208 // Conversion functions // 209 ////////////////////////// 210 211 // std::string to Vector2 212 bool ConverterFallback<std::string, orxonox::Vector2>::convert(orxonox::Vector2* output, const std::string& input) 213 { 214 size_t opening_parenthesis, closing_parenthesis = input.find(')'); 215 if ((opening_parenthesis = input.find('(')) == std::string::npos) 216 opening_parenthesis = 0; 217 else 218 opening_parenthesis++; 219 220 SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), 221 ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0'); 222 if (tokens.size() >= 2) 223 { 224 if (!ConvertValue(&(output->x), tokens[0])) 225 return false; 226 if (!ConvertValue(&(output->y), tokens[1])) 227 return false; 228 229 return true; 230 } 231 return false; 232 } 233 234 // std::string to Vector3 235 bool ConverterFallback<std::string, orxonox::Vector3>::convert(orxonox::Vector3* output, const std::string& input) 236 { 237 size_t opening_parenthesis, closing_parenthesis = input.find(')'); 238 if ((opening_parenthesis = input.find('(')) == std::string::npos) 239 opening_parenthesis = 0; 240 else 241 opening_parenthesis++; 242 243 SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), 244 ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0'); 245 if (tokens.size() >= 3) 246 { 247 if (!ConvertValue(&(output->x), tokens[0])) 248 return false; 249 if (!ConvertValue(&(output->y), tokens[1])) 250 return false; 251 if (!ConvertValue(&(output->z), tokens[2])) 252 return false; 253 254 return true; 255 } 256 return false; 257 } 258 259 // std::string to Vector4 260 bool ConverterFallback<std::string, orxonox::Vector4>::convert(orxonox::Vector4* output, const std::string& input) 261 { 262 size_t opening_parenthesis, closing_parenthesis = input.find(')'); 263 if ((opening_parenthesis = input.find('(')) == std::string::npos) 264 opening_parenthesis = 0; 265 else 266 opening_parenthesis++; 267 268 SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), 269 ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0'); 270 if (tokens.size() >= 4) 271 { 272 if (!ConvertValue(&(output->x), tokens[0])) 273 return false; 274 if (!ConvertValue(&(output->y), tokens[1])) 275 return false; 276 if (!ConvertValue(&(output->z), tokens[2])) 277 return false; 278 if (!ConvertValue(&(output->w), tokens[3])) 279 return false; 280 281 return true; 282 } 283 return false; 284 } 285 286 // std::string to Quaternion 287 bool ConverterFallback<std::string, orxonox::Quaternion>::convert(orxonox::Quaternion* output, const std::string& input) 288 { 289 size_t opening_parenthesis, closing_parenthesis = input.find(')'); 290 if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; } 291 292 SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0'); 293 if (tokens.size() >= 4) 294 { 295 if (!ConvertValue(&(output->w), tokens[0])) 296 return false; 297 if (!ConvertValue(&(output->x), tokens[1])) 298 return false; 299 if (!ConvertValue(&(output->y), tokens[2])) 300 return false; 301 if (!ConvertValue(&(output->z), tokens[3])) 302 return false; 303 304 return true; 305 } 306 return false; 307 } 308 309 // std::string to ColourValue 310 bool ConverterFallback<std::string, orxonox::ColourValue>::convert(orxonox::ColourValue* output, const std::string& input) 311 { 312 size_t opening_parenthesis, closing_parenthesis = input.find(')'); 313 if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; } 314 315 SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0'); 316 if (tokens.size() >= 3) 317 { 318 if (!ConvertValue(&(output->r), tokens[0])) 319 return false; 320 if (!ConvertValue(&(output->g), tokens[1])) 321 return false; 322 if (!ConvertValue(&(output->b), tokens[2])) 323 return false; 324 if (tokens.size() >= 4) 325 { 326 if (!ConvertValue(&(output->a), tokens[3])) 327 return false; 328 } 329 else 330 output->a = 1.0; 331 332 return true; 333 } 334 return false; 335 } 47 336 } 48 49 /**50 @brief Function for reading a Radian from a stream.51 */52 std::istream& operator>>(std::istream& in, orxonox::Radian& radian)53 {54 float temp;55 in >> temp;56 radian = temp;57 return in;58 }59 60 /**61 @brief Function for writing a Degree to a stream.62 */63 std::ostream& operator<<(std::ostream& out, const orxonox::Degree& degree)64 {65 out << degree.valueDegrees();66 return out;67 }68 69 /**70 @brief Function for reading a Degree from a stream.71 */72 std::istream& operator>>(std::istream& in, orxonox::Degree& degree)73 {74 float temp;75 in >> temp;76 degree = temp;77 return in;78 }79 80 81 /**82 @brief Gets the angle between my viewing direction and the direction to the position of the other object.83 @param myposition My position84 @param mydirection My viewing direction85 @param otherposition The position of the other object86 @return The angle87 88 @example89 If the other object is exactly in front of me, the function returns 0.90 If the other object is exactly behind me, the function returns pi.91 If the other object is exactly right/left to me (or above/below), the function returns pi/2.92 */93 float getAngle(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& otherposition)94 {95 orxonox::Vector3 distance = otherposition - myposition;96 float distancelength = distance.length();97 if (distancelength == 0)98 return 0;99 else100 return acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1));101 }102 103 /**104 @brief Gets the 2D viewing direction (up/down, left/right) to the position of the other object.105 @param myposition My position106 @param mydirection My viewing direction107 @param myorthonormal My orthonormalvector (pointing upwards through my head)108 @param otherposition The position of the other object109 @return The viewing direction110 111 @example112 If the other object is exactly in front of me, the function returns Vector2(0, 0).113 If the other object is exactly at my left, the function returns Vector2(-1, 0).114 If the other object is exactly at my right, the function returns Vector2(1, 0).115 If the other object is only a bit at my right, the function still returns Vector2(1, 0).116 If the other object is exactly above me, the function returns Vector2(0, 1).117 */118 orxonox::Vector2 get2DViewdirection(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition)119 {120 orxonox::Vector3 distance = otherposition - myposition;121 122 // project difference vector on our plane123 orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);124 125 float projectionlength = projection.length();126 if (projectionlength == 0) return orxonox::Vector2(0, 0);127 float angle = acos(clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1));128 129 if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)130 return orxonox::Vector2(sin(angle), cos(angle));131 else132 return orxonox::Vector2(-sin(angle), cos(angle));133 }134 135 /**136 @brief Gets the 2D viewing direction (up/down, left/right) to the position of the other object, multiplied with the viewing distance to the object (0° = 0, 180° = 1).137 @param myposition My position138 @param mydirection My viewing direction139 @param myorthonormal My orthonormalvector (pointing upwards through my head)140 @param otherposition The position of the other object141 @return The viewing direction142 143 @example144 If the other object is exactly in front of me, the function returns Vector2(0, 0).145 If the other object is exactly at my left, the function returns Vector2(-0.5, 0).146 If the other object is exactly at my right, the function returns Vector2(0.5, 0).147 If the other object is only a bit at my right, the function still returns Vector2(0.01, 0).148 If the other object is exactly above me, the function returns Vector2(0, 0.5).149 */150 orxonox::Vector2 get2DViewcoordinates(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition)151 {152 orxonox::Vector3 distance = otherposition - myposition;153 154 // project difference vector on our plane155 orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);156 157 float projectionlength = projection.length();158 if (projectionlength == 0) return orxonox::Vector2(0, 0);159 float angle = acos(clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1));160 161 float distancelength = distance.length();162 if (distancelength == 0) return orxonox::Vector2(0, 0);163 float radius = acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1)) / Ogre::Math::PI;164 165 if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)166 return orxonox::Vector2(sin(angle) * radius, cos(angle) * radius);167 else168 return orxonox::Vector2(-sin(angle) * radius, cos(angle) * radius);169 }170 171 /**172 @brief Returns the predicted position I have to aim at, if I want to hit a moving target with a moving projectile.173 @param myposition My position174 @param projectilespeed The speed of my projectile175 @param targetposition The position of my target176 @param targetvelocity The velocity of my target177 @return The predicted position178 179 The function predicts the position based on a linear velocity of the target. If the target changes speed or direction, the projectile will miss.180 */181 orxonox::Vector3 getPredictedPosition(const orxonox::Vector3& myposition, float projectilespeed, const orxonox::Vector3& targetposition, const orxonox::Vector3& targetvelocity)182 {183 float squaredProjectilespeed = projectilespeed * projectilespeed;184 orxonox::Vector3 distance = targetposition - myposition;185 float a = distance.squaredLength();186 float b = 2 * (distance.x + distance.y + distance.z) * (targetvelocity.x + targetvelocity.y + targetvelocity.z);187 float c = targetvelocity.squaredLength();188 189 float temp = 4*squaredProjectilespeed*c + a*a - 4*b*c;190 if (temp < 0)191 return orxonox::Vector3::ZERO;192 193 temp = sqrt(temp);194 float time = (temp + a) / (2 * (squaredProjectilespeed - b));195 return (targetposition + targetvelocity * time);196 }197 198 unsigned long getUniqueNumber()199 {200 static unsigned long aNumber = 135;201 return aNumber++;202 }203 204 205 //////////////////////////206 // Conversion functions //207 //////////////////////////208 209 // std::string to Vector2210 bool ConverterFallback<std::string, orxonox::Vector2>::convert(orxonox::Vector2* output, const std::string& input)211 {212 size_t opening_parenthesis, closing_parenthesis = input.find(')');213 if ((opening_parenthesis = input.find('(')) == std::string::npos)214 opening_parenthesis = 0;215 else216 opening_parenthesis++;217 218 SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),219 ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');220 if (tokens.size() >= 2)221 {222 if (!ConvertValue(&(output->x), tokens[0]))223 return false;224 if (!ConvertValue(&(output->y), tokens[1]))225 return false;226 227 return true;228 }229 return false;230 }231 232 // std::string to Vector3233 bool ConverterFallback<std::string, orxonox::Vector3>::convert(orxonox::Vector3* output, const std::string& input)234 {235 size_t opening_parenthesis, closing_parenthesis = input.find(')');236 if ((opening_parenthesis = input.find('(')) == std::string::npos)237 opening_parenthesis = 0;238 else239 opening_parenthesis++;240 241 SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),242 ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');243 if (tokens.size() >= 3)244 {245 if (!ConvertValue(&(output->x), tokens[0]))246 return false;247 if (!ConvertValue(&(output->y), tokens[1]))248 return false;249 if (!ConvertValue(&(output->z), tokens[2]))250 return false;251 252 return true;253 }254 return false;255 }256 257 // std::string to Vector4258 bool ConverterFallback<std::string, orxonox::Vector4>::convert(orxonox::Vector4* output, const std::string& input)259 {260 size_t opening_parenthesis, closing_parenthesis = input.find(')');261 if ((opening_parenthesis = input.find('(')) == std::string::npos)262 opening_parenthesis = 0;263 else264 opening_parenthesis++;265 266 SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),267 ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');268 if (tokens.size() >= 4)269 {270 if (!ConvertValue(&(output->x), tokens[0]))271 return false;272 if (!ConvertValue(&(output->y), tokens[1]))273 return false;274 if (!ConvertValue(&(output->z), tokens[2]))275 return false;276 if (!ConvertValue(&(output->w), tokens[3]))277 return false;278 279 return true;280 }281 return false;282 }283 284 // std::string to Quaternion285 bool ConverterFallback<std::string, orxonox::Quaternion>::convert(orxonox::Quaternion* output, const std::string& input)286 {287 size_t opening_parenthesis, closing_parenthesis = input.find(')');288 if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }289 290 SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');291 if (tokens.size() >= 4)292 {293 if (!ConvertValue(&(output->w), tokens[0]))294 return false;295 if (!ConvertValue(&(output->x), tokens[1]))296 return false;297 if (!ConvertValue(&(output->y), tokens[2]))298 return false;299 if (!ConvertValue(&(output->z), tokens[3]))300 return false;301 302 return true;303 }304 return false;305 }306 307 // std::string to ColourValue308 bool ConverterFallback<std::string, orxonox::ColourValue>::convert(orxonox::ColourValue* output, const std::string& input)309 {310 size_t opening_parenthesis, closing_parenthesis = input.find(')');311 if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }312 313 SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');314 if (tokens.size() >= 3)315 {316 if (!ConvertValue(&(output->r), tokens[0]))317 return false;318 if (!ConvertValue(&(output->g), tokens[1]))319 return false;320 if (!ConvertValue(&(output->b), tokens[2]))321 return false;322 if (tokens.size() >= 4)323 {324 if (!ConvertValue(&(output->a), tokens[3]))325 return false;326 }327 else328 output->a = 1.0;329 330 return true;331 }332 return false;333 }
Note: See TracChangeset
for help on using the changeset viewer.