/// After the Run() has completed, you can call this function to /// fill a 'contact container', that is an object inherited from class /// ChContactContainer. For instance ChSystem, after each Run() /// collision detection, calls this method multiple times for all contact containers in the system, /// Children classes _must_ implement this. /// The basic behavior of the implementation should be the following: collision system /// will call in sequence the functions BeginAddContact(), AddContact() (x n times), /// EndAddContact() of the contact container. /// In case a specialized implementation (ex. a GPU parallel collision engine) /// finds that the contact container is a specialized one (ex with a GPU buffer) /// it can call more performant methods to add directly the contacts in batches, for instance /// by recognizing that he can call, say, some special AddAllContactsAsGpuBuffer() instead of many AddContact(). public abstract void ReportContacts(ChContactContainer mcontactcontainer);
public override void ReportContacts(ChContactContainer mcontactcontainer) { // This should remove all old contacts (or at least rewind the index) mcontactcontainer.BeginAddContact(); // NOTE: Bullet does not provide information on radius of curvature at a contact point. // As such, for all Bullet-identified contacts, the default value will be used (SMC only). ChCollisionInfo icontact = new ChCollisionInfo(); int numManifolds = bt_collision_world.GetDispatcher().GetNumManifolds(); for (int i = 0; i < numManifolds; i++) { PersistentManifold contactManifold = bt_collision_world.GetDispatcher().GetManifoldByIndexInternal(i); CollisionObject obA = (CollisionObject)(contactManifold.GetBody0()); CollisionObject obB = (CollisionObject)(contactManifold.GetBody1()); if (obA != null && obA != null) // Alan { contactManifold.RefreshContactPoints(ref obA.GetWorldTransform(), ref obB.GetWorldTransform()); icontact.modelA = (ChCollisionModel)obA.GetUserPointer(); icontact.modelB = (ChCollisionModel)obB.GetUserPointer(); double envelopeA = icontact.modelA.GetEnvelope(); double envelopeB = icontact.modelB.GetEnvelope(); double marginA = icontact.modelA.GetSafeMargin(); double marginB = icontact.modelB.GetSafeMargin(); // Execute custom broadphase callback, if any bool do_narrow_contactgeneration = true; if (this.broad_callback != null) { do_narrow_contactgeneration = this.broad_callback.OnBroadphase(icontact.modelA, icontact.modelB); } if (do_narrow_contactgeneration) { int numContacts = contactManifold.GetNumContacts(); //GetLog() << "numContacts=" << numContacts << "\n"; for (int j = 0; j < numContacts; j++) { // Debug.Log("contacts " + numContacts); ManifoldPoint pt = contactManifold.GetContactPoint(j); // Discard "too far" constraints (the Bullet engine also has its threshold) if (pt.GetDistance() < marginA + marginB) { IndexedVector3 ptA = pt.GetPositionWorldOnA(); IndexedVector3 ptB = pt.GetPositionWorldOnB(); icontact.vpA.Set(ptA.X, ptA.Y, ptA.Z); icontact.vpB.Set(ptB.X, ptB.Y, ptB.Z); icontact.vN.Set(-pt.GetNormalWorldOnB().X, -pt.GetNormalWorldOnB().Y, -pt.GetNormalWorldOnB().Z); icontact.vN.Normalize(); double ptdist = pt.GetDistance(); icontact.vpA = icontact.vpA - icontact.vN * envelopeA; icontact.vpB = icontact.vpB + icontact.vN * envelopeB; icontact.distance = ptdist + envelopeA + envelopeB; icontact.reaction_cache = pt.reactions_cache;// reactions_cache; // Execute some user custom callback, if any bool add_contact = true; if (this.narrow_callback != null) { add_contact = this.narrow_callback.OnNarrowphase(icontact); } // Add to contact container if (add_contact) { mcontactcontainer.AddContact(icontact); } } } } } // you can un-comment out this line, and then all points are removed // contactManifold->clearManifold(); } mcontactcontainer.EndAddContact(); }