00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "rigidobject.h"
00024 #include "subspace.h"
00025 #include "world.h"
00026
00027 using namespace sheep;
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 void Subspace::Step(Real start_time, Real end_time) {
00086 const Real EPSILON = 1e-6;
00087
00088
00089 assert(end_time - start_time > EPSILON);
00090
00091 m_cd.RefreshTransformations();
00092
00093 while(end_time - start_time > EPSILON) {
00094 find_contacts();
00095
00096 #ifdef DEBUG_INFO
00097 *m_debug << "Resting contacts so far: "
00098 << m_ch.GetRestingContactTracker()->GetRestingContacts().size() << br;
00099 #endif // DEBUG_INFO
00100
00101 for(rigidobject_list::iterator i = m_objects.begin(); i != m_objects.end(); i++) {
00102 RigidBody *body = (*i)->GetBody();
00103
00104 body->ZeroForce();
00105 body->ZeroTorque();
00106
00107
00108
00109
00110 body->ApplyForce(Vector3(0, -9.8, 0));
00111
00112
00113 body->ApplyForce(-0.2 * body->GetLinearVelocity());
00114 body->ApplyTorque(-0.2 * body->GetAngularVelocity());
00115 }
00116
00117
00118
00119
00120
00121
00122
00123 m_jm.ApplyContraints();
00124 m_ch.ResolveAll();
00125
00126 Real step_end = compute_step_end(start_time, end_time);
00127
00128 assert(step_end <= end_time);
00129 assert(step_end - start_time > EPSILON);
00130
00131 #ifdef DEBUG_INFO
00132 *m_debug << "Step by " << step_end - start_time << br;
00133 #endif // DEBUG_INFO
00134
00135 step_bodies(start_time, step_end - start_time);
00136
00137 start_time = step_end;
00138 }
00139 }
00140
00141 void Subspace::save_state(state_snapshot *s) {
00142 assert(s);
00143
00144 s->m_states = new RigidBody::StateVector[m_objects.size()];
00145
00146 RigidBody::StateVector *p = s->m_states;
00147
00148 for(rigidobject_list::iterator i = m_objects.begin(); i != m_objects.end(); i++) {
00149 *p++ = (*i)->GetBody()->GetState();
00150 }
00151 }
00152
00153 void Subspace::restore_state(const state_snapshot &s) {
00154 RigidBody::StateVector *p = s.m_states;
00155
00156 for(rigidobject_list::iterator i = m_objects.begin(); i != m_objects.end(); i++) {
00157 (*i)->GetBody()->SetState(*p++);
00158 }
00159
00160 m_cd.RefreshTransformations();
00161 }
00162
00163 void Subspace::find_contacts() {
00164 #ifdef DEBUG_INFO
00165 *m_debug << "Let's now compute contacts:" << br;
00166 #endif // DEBUG_INFO
00167
00168 ContactList contacts;
00169
00170 m_cd.FindContacts(&contacts);
00171
00172 for(ContactList::iterator i = contacts.begin(); i != contacts.end(); i++) {
00173 Contact &c = *i;
00174
00175 if((c.m_fa.m_type == Feature::Type::FACE && c.m_fb.m_type == Feature::Type::VERTEX) ||
00176 (c.m_fa.m_type == Feature::Type::EDGE && c.m_fb.m_type == Feature::Type::VERTEX)) {
00177 std::swap(c.m_a, c.m_b);
00178 std::swap(c.m_fa, c.m_fb);
00179 }
00180
00181 c.Update();
00182
00183 if(c.GetType() == Contact::Type::SEPARATING_CONTACT) {
00184 #ifdef DEBUG_INFO
00185 *m_debug << "It is a separating contact. Skipping it." << br;
00186 #endif // DEBUG_INFO
00187 continue;
00188 }
00189
00190 if(c.GetType() == Contact::Type::RESTING_CONTACT) {
00191 const ContactVector &rc = m_ch.GetRCTracker().GetRestingContacts();
00192 bool known_rc = false;
00193
00194 for(ContactVector::const_iterator i = rc.begin(); i != rc.end(); i++) {
00195 if(c == *i) {
00196 known_rc = true;
00197 break;
00198 }
00199 }
00200
00201 if(known_rc) {
00202 #ifdef DEBUG_INFO
00203 *m_debug << "It is an already known resting contact. Skipping it." << br;
00204 #endif // DEBUG_INFO
00205 continue;
00206 }
00207 }
00208
00209 #ifdef DEBUG_INFO
00210 *m_debug << "Adding the following contact to the contact list:" << br;
00211 print_contact(c);
00212 #endif // DEBUG_INFO
00213
00214 m_ch.Insert(c);
00215 }
00216 }
00217
00218 Real Subspace::compute_step_end(Real start_time, Real end_time) {
00219
00220
00221
00222 const Real EPSILON = 1e-6;
00223
00224 assert(end_time - start_time > EPSILON);
00225 assert(m_cd.AreObjectsDisjoint());
00226
00227 state_snapshot orig_state;
00228 save_state(&orig_state);
00229
00230 Real step_end = start_time;
00231 Real step = end_time - start_time;
00232
00233 while(true) {
00234 assert(end_time - step_end >= 0);
00235
00236 if(end_time - step_end < EPSILON) {
00237 #ifdef DEBUG_INFO
00238 *m_debug << "Maximum step reached." << br;
00239 #endif // DEBUG_INFO
00240 break;
00241 }
00242
00243 assert(m_cd.AreObjectsDisjoint());
00244
00245 state_snapshot last_state;
00246 save_state(&last_state);
00247
00248 assert(step > EPSILON);
00249
00250 step_bodies(step_end, step);
00251
00252 if(!m_cd.AreObjectsDisjoint()) {
00253 restore_state(last_state);
00254
00255 step /= 2;
00256
00257 if(step <= EPSILON) {
00258 #ifdef DEBUG_INFO
00259 *m_debug << "Giving up time bisection." << br;
00260 *m_debug << "Hint: one or several objects may be moving too fast." << br;
00261 #endif // DEBUG_INFO
00262 break;
00263 }
00264 } else {
00265 step_end += step;
00266
00267 if(!m_cd.AreObjectHullsDisjoint()) {
00268 #ifdef DEBUG_INFO
00269 *m_debug << "Interference detected." << br;
00270 #endif // DEBUG_INFO
00271 break;
00272 }
00273 }
00274 }
00275
00276 restore_state(orig_state);
00277
00278 assert(m_cd.AreObjectsDisjoint());
00279
00280 assert(step_end <= end_time);
00281 assert(step_end - start_time > EPSILON);
00282
00283 return step_end;
00284 }
00285
00286 void Subspace::step_bodies(Real time, Real step) {
00287 const Real EPSILON = 1e-6;
00288
00289
00290 assert(step > EPSILON);
00291
00292 for(rigidobject_list::iterator i = m_objects.begin(); i != m_objects.end(); i++) {
00293 RigidBody *body = (*i)->GetBody();
00294
00295 if(body->IsFrozen())
00296 continue;
00297
00298 body->EvolveOneStep(m_solver, time, step);
00299 }
00300
00301 m_cd.RefreshTransformations();
00302 }