head.cpp

Go to the documentation of this file.
00001 
00032 // implementation of a class that models the motion of a human head.
00033 // The physics aren't quite right, but it will suffice for right now.
00034 
00035 #include "llviewerprecompiledheaders.h"
00036 
00037 #include "head.h"
00038 
00039 #ifndef PI
00040   #define PI ((F32) 3.14159265358979323846264338327)
00041 #endif
00042 
00043 // The friction force of the neck is modeled as:
00044 //   friction = -E*phi_dot - F*phi_dot  (for positive phi_dot)
00045 #define E1 0.75
00046 #define F1 0.0
00047 
00048 // TODO -- use the other PI defined in the math libs somewhere.
00049 
00050 // --------------------------------------------------
00051 // Misc. function delclarations...
00052 // --------------------------------------------------
00053 F32 phi_spring(F32 phi, F32 theta);
00054 F32 theta_spring(F32 theta, F32 phi);
00055 
00056 
00057 // --------------------------------------------------
00058 // Class Head member functions...
00059 // --------------------------------------------------
00060 
00061 Head::Head() {
00062   mass = 1.0f;
00063   radius = 1.0f;
00064   inertia = 2.0f * mass * radius * radius / 5.0f;
00065   phi = 0.0f;
00066   theta = 0.0f;
00067   //gettimeofday(&t, &tz);
00068 }
00069 
00070 Head::Head(F32 m, F32 r) {
00071   mass = m;
00072   radius = r;
00073   inertia = 2.0f * mass * radius * radius / 5.0f;
00074   phi = 0.0f;
00075   theta = 0.0f;
00076   //gettimeofday(&t, &tz);
00077 }
00078 
00079 F32 Head::setMass(F32 m) { 
00080   mass = m; 
00081   inertia = 2.0f * mass * radius * radius / 5.0f;
00082   return mass;
00083 }
00084 
00085 F32 Head::setRadius(F32 r) { 
00086   radius = r; 
00087   inertia = 2.0f * mass * radius * radius / 5.0f;
00088   return radius;
00089 }
00090 
00091 F32 Head::getMass()    { return mass;    }
00092 F32 Head::getRadius()  { return radius;  }
00093 F32 Head::getInertia() { return inertia; }
00094 
00095 void Head::propagate(F32 horizontal_force, F32 vertical_force, F32 dt) {
00096   //struct timeval t1;
00097   //F32 dt, temp;
00098   F32 phi_torque, theta_torque;
00099   F32 phi_dot, theta_dot;
00100 
00101   //gettimeofday(&t1, &tz);
00102   //dt = ((t1.tv_sec - t.tv_sec) * 1000000.0  + (t1.tv_usec - t.tv_usec)) / 1000000.0;
00103   //dt = 0.033;  // This is a kluge to prevent instabilities when using a stepper
00104 
00105   // Calculate the return forces...
00106   // Note: horizontal_force is positive toward right, so it's resultant torque
00107   // is negative, since the phi spin angle is out the top of the head (using 
00108   // right-hand rule).
00109   phi_torque   = radius * (phi_spring(phi, theta)   - horizontal_force); 
00110   theta_torque = radius * (theta_spring(phi, theta) + vertical_force);
00111 
00112   // Propagate phi...
00113   phi_dot = dt * phi_torque / inertia;
00114  
00115   phi += dt * phi_dot;
00116   if (phi >= PI/2.0f) {
00117     phi = PI/2.0f;
00118   }
00119   else if (phi <= -PI/2.0f) {
00120     phi = -PI/2.0f;
00121   }
00122 
00123   // Propagate theta...
00124   theta_dot = dt * theta_torque / inertia;
00125   theta += dt * theta_dot;
00126   if (theta >= PI/2.0f) {
00127     theta = PI/2.0f;
00128   }
00129   else if (theta <= -PI/2.0f) {
00130     theta = -PI/2.0f;
00131   }
00132 
00133   //t = t1;
00134   return;
00135 }
00136 
00137 
00138 F32 phi_spring(F32 phi, F32 theta) {
00139 // The srping force is linear with -phi and the magnitude of theta.
00140   F32 phi_force;
00141   phi_force = - 30 * phi;
00142   phi_force = phi_force * (1.0f + (F32)fabs(theta) / PI);
00143   return phi_force;
00144 }
00145 
00146 
00147 F32 theta_spring(F32 phi, F32 theta) {
00148   return phi_spring(theta, phi);
00149 }
00150 
00151 
00152 
00153 

Generated on Thu Jul 1 06:08:17 2010 for Second Life Viewer by  doxygen 1.4.7