00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 #include "colors.hxx"
00021 #include "construo_error.hxx"
00022 #include "particle_factory.hxx"
00023 #include "spring.hxx"
00024 
00025 Spring::Spring (Particle* f, Particle* s, float l)
00026 {
00027   particles.first  = f;
00028   particles.second = s;
00029   destroyed        = false;
00030   length           = l;
00031 
00032   stiffness   = 50.0f;
00033   damping     = .1f;
00034   max_stretch = 0.15f;
00035 
00036   f->spring_links += 1;
00037   s->spring_links += 1;
00038 }
00039 
00040 Spring::Spring (Particle* f, Particle* s) 
00041 {
00042   particles.first  = f;
00043   particles.second = s;
00044   destroyed        = false;
00045   length           = fabs((f->pos - s->pos).norm ());
00046 
00047   stiffness   = 50.0f;
00048   damping     = .1f;
00049   max_stretch = 0.15f;
00050 
00051   f->spring_links += 1;
00052   s->spring_links += 1;
00053 
00054   assert (length != 0);
00055 }
00056 
00057 Spring::Spring (World* world, lisp_object_t* cursor)
00058   : destroyed (false)
00059 {
00060   cursor = lisp_cdr(cursor); 
00061 
00062   int first_id = -1;
00063   int second_id = -1;
00064   length = -1;
00065 
00066   stiffness   = 50.0f;
00067   damping     = .1f;
00068   max_stretch = 0.15f;
00069 
00070   LispReader reader(cursor);
00071   reader.read_int ("first", &first_id);
00072   reader.read_int ("second", &second_id);
00073   reader.read_float ("length", &length);
00074   reader.read_float ("stiffness",   &stiffness);
00075   reader.read_float ("damping",     &damping);
00076   reader.read_float ("maxstretch", &max_stretch);
00077 
00078   particles.first  = world->get_particle_mgr()->lookup_particle (first_id);
00079   particles.second = world->get_particle_mgr()->lookup_particle (second_id);
00080 
00081   if (particles.first == 0 || particles.second == 0)
00082     {
00083       throw ConstruoError ("Spring: Pair lookup failed");
00084     }
00085 
00086   particles.first->spring_links  += 1;
00087   particles.second->spring_links += 1;
00088 
00089   if (length == -1)
00090     {
00091       
00092       length = fabs((particles.first->pos - particles.second->pos).norm ());
00093     }
00094 }
00095 
00096 Spring::~Spring ()
00097 {
00098   particles.first->spring_links -= 1;
00099   particles.second->spring_links -= 1;
00100 }
00101 
00102 void
00103 Spring::update (float delta)
00104 {
00105   Vector2d dist = particles.first->pos - particles.second->pos;
00106 
00107   
00108   
00109   float stretch = (dist.norm () - length);
00110   
00111   
00112   if (fabs(stretch/length) > max_stretch && 
00113       length > 10.0f) 
00114     { 
00115       destroyed = true;
00116     }
00117   else
00118     {
00119       stretch *= stiffness;
00120       float dterm = (dist.dot(particles.first->velocity - particles.second->velocity) * damping)/dist.norm ();
00121 
00122       dist.normalize ();
00123       Vector2d force = dist * (stretch + dterm);
00124       
00125       
00126 
00127 
00128 
00129       particles.first->add_force (-force);
00130       particles.second->add_force (force);
00131     }
00132 }
00133 
00134 void
00135 Spring::draw (ZoomGraphicContext* gc)
00136 {
00137   Vector2d dist = particles.first->pos - particles.second->pos;
00138   float stretch = fabs(dist.norm ()/length - 1.0f) * 10.0f;
00139   
00140   float color = fabs((stretch/max_stretch));
00141   
00142   if (particles.first->pos.y  < 598.5f
00143       || 
00144       particles.second->pos.y < 598.5f)
00145     {
00146       gc->GraphicContext::draw_line (particles.first->pos,
00147                                      particles.second->pos,
00148                                      Color(color, 1.0f - color, 0.0f),
00149                                      2);
00150     }
00151 }
00152 
00153 void
00154 Spring::draw_highlight (ZoomGraphicContext* gc)
00155 {
00156   gc->GraphicContext::draw_line (particles.first->pos, particles.second->pos,
00157                                  Colors::highlight, 4);
00158 }
00159 
00160 
00161 lisp_object_t* 
00162 Spring::serialize()
00163 {
00164   LispWriter obj ("spring");
00165   obj.write_int ("first", particles.first->get_id());
00166   obj.write_int ("second", particles.second->get_id());
00167   obj.write_float ("length", length);
00168   obj.write_float ("stiffness",   stiffness);
00169   obj.write_float ("damping",     damping);
00170   obj.write_float ("maxstretch", max_stretch);
00171 
00172   return obj.create_lisp ();
00173 }
00174 
00175 void
00176 Spring::recalc_length ()
00177 {
00178   length = fabs((particles.first->pos - particles.second->pos).norm ());
00179 }
00180 
00181