/// User can override this material combiner by implementing gContactAddedCallback and setting // body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; private static float calculateCombinedFriction(CollisionObject body0, CollisionObject body1) { float friction = body0.getFriction() * body1.getFriction(); float MAX_FRICTION = 10f; if (friction < -MAX_FRICTION) { friction = -MAX_FRICTION; } if (friction > MAX_FRICTION) { friction = MAX_FRICTION; } return friction; }
// 衝突したか? public boolean isCollided(CollisionObject obj) { if (obj.getBoundBox().intersects(m_BoundBox)) { return true; } return false; }
public void addContactPoint(Vector3f normalOnBInWorld, Vector3f pointInWorld, float depth) { assert (manifoldPtr != null); // order in manifold needs to match if (depth > manifoldPtr.getContactBreakingThreshold()) { return; } stack.vectors.push(); try { boolean isSwapped = manifoldPtr.getBody0() != body0; Vector3f pointA = stack.vectors.get(); pointA.scaleAdd(depth, normalOnBInWorld, pointInWorld); Vector3f localA = stack.vectors.get(); Vector3f localB = stack.vectors.get(); if (isSwapped) { rootTransB.invXform(pointA, localA); rootTransA.invXform(pointInWorld, localB); } else { rootTransA.invXform(pointA, localA); rootTransB.invXform(pointInWorld, localB); } ManifoldPoint newPt = pointsPool.get(); newPt.init(localA, localB, normalOnBInWorld, depth); newPt.positionWorldOnA.set(pointA); newPt.positionWorldOnB.set(pointInWorld); int insertIndex = manifoldPtr.getCacheEntry(newPt); newPt.combinedFriction = calculateCombinedFriction(body0, body1); newPt.combinedRestitution = calculateCombinedRestitution(body0, body1); /// todo, check this for any side effects if (insertIndex >= 0) { // const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); manifoldPtr.replaceContactPoint(newPt, insertIndex); } else { manifoldPtr.addManifoldPoint(newPt); } // User can override friction and/or restitution if (BulletGlobals.gContactAddedCallback != null && // and if either of the two bodies requires custom material ((body0.getCollisionFlags() & CollisionFlags.CUSTOM_MATERIAL_CALLBACK) != 0 || (body1.getCollisionFlags() & CollisionFlags.CUSTOM_MATERIAL_CALLBACK) != 0)) { // experimental feature info, for per-triangle material etc. CollisionObject obj0 = isSwapped ? body1 : body0; CollisionObject obj1 = isSwapped ? body0 : body1; BulletGlobals.gContactAddedCallback.invoke( newPt, obj0, partId0, index0, obj1, partId1, index1); } pointsPool.release(newPt); } finally { stack.vectors.pop(); } }
public void init(CollisionObject body0, CollisionObject body1) { this.body0 = body0; this.body1 = body1; this.rootTransA.set(body0.getWorldTransform()); this.rootTransB.set(body1.getWorldTransform()); }
private static float calculateCombinedRestitution(CollisionObject body0, CollisionObject body1) { return body0.getRestitution() * body1.getRestitution(); }
// 詳細な衝突判定 public int getIntersectSide(CollisionObject obj) { Rectangle peer = obj.getBoundBox(); int result = 0; int weight = 0; // 当たり判定に寄与した度合い int mostEffected = 0; // 最も寄与した辺 // 自分自身の当たり判定 int selfTop = m_BoundBox.y; int selfBottom = m_BoundBox.y + m_BoundBox.height; int selfLeft = m_BoundBox.x; int selfRight = m_BoundBox.x + m_BoundBox.width; // 相手の当たり判定 int peerTop = peer.y; int peerBottom = peer.y + peer.height; int peerLeft = peer.x; int peerRight = peer.x + peer.width; // 上辺が交差 if (peerTop > selfTop && peerTop < selfBottom && peerLeft < selfRight && peerRight > selfLeft) { int w = 0; // 影響度 if (peerTop > selfTop) { w = peerTop - selfTop; } else if (peerTop < selfBottom) { w = selfBottom - peerTop; } // 影響度の更新 if (w > weight) { weight = w; mostEffected = INTERSECT_TOP; } result |= INTERSECT_TOP; } // 下辺が交差 if (peerBottom > selfTop && peerBottom < selfBottom && peerLeft < selfRight && peerRight > selfLeft) { int w = 0; // 影響度 if (peerBottom > selfTop) { w = peerBottom - selfTop; } else if (peerBottom < selfBottom) { w = selfBottom - peerBottom; } // 影響度の更新 if (w > weight) { weight = w; mostEffected = INTERSECT_BOTTOM; } result |= INTERSECT_BOTTOM; } // 左辺が交差 if (peerLeft > selfLeft && peerLeft < selfRight && peerTop < selfBottom && peerBottom > selfTop) { int w = 0; // 影響度 if (peerLeft > selfLeft) { w = peerLeft - selfLeft; } else if (peerLeft < selfRight) { w = selfRight - peerLeft; } // 影響度の更新 if (w > weight) { weight = w; mostEffected = INTERSECT_LEFT; } result |= INTERSECT_LEFT; } // 右辺が交差 if (peerRight > selfLeft && peerRight < selfRight && peerTop < selfBottom && peerBottom > selfTop) { int w = 0; // 影響度 if (peerRight > selfLeft) { w = peerRight - selfLeft; } else if (peerRight < selfRight) { w = selfRight - peerRight; } // 影響度の更新 if (w > weight) { weight = w; mostEffected = INTERSECT_RIGHT; } result |= INTERSECT_RIGHT; } return result | mostEffected << 8; }