bool collideShapesCoarse(const QVector<const Shape*>& shapesA, const QVector<const Shape*>& shapesB, CollisionInfo& collision) { tempCollisions.clear(); foreach (const Shape* shapeA, shapesA) { foreach (const Shape* shapeB, shapesB) { ShapeCollider::collideShapes(shapeA, shapeB, tempCollisions); }
//----------------------------------------------------------------------------- // // VActorPhysicsController::findCollision( pCollision ); // // ... // //----------------------------------------------------------------------------- bool VActorPhysicsController::findCollision( Collision *&pCollision ) { // Setup Collision List. static CollisionList sCollisionList; sCollisionList.clear(); static Polyhedron sBoxPolyhedron; static ExtrudedPolyList sExtrudedPolyList; // Determine Positions. const Point3F preTickPosition = getPosition(); const VectorF preTickVelocity = getVelocity(); const Point3F postTickPosition = preTickPosition + ( preTickVelocity * TickSec ); const VectorF postTickVector = postTickPosition - preTickPosition; // Construct Scaled Box. Box3F scaledBox = mObject->getObjBox(); scaledBox.minExtents.convolve( mObject->getScale() ); scaledBox.maxExtents.convolve( mObject->getScale() ); // Setup Polyherdron. MatrixF collisionMatrix( true ); collisionMatrix.setPosition( preTickPosition ); sBoxPolyhedron.buildBox( collisionMatrix, scaledBox ); // Setup Extruded Poly List. sExtrudedPolyList.extrude( sBoxPolyhedron, postTickVector ); sExtrudedPolyList.setVelocity( preTickVelocity ); sExtrudedPolyList.setCollisionList( &sCollisionList ); // Construct World Convex Box & Adjust for Sweep. Box3F convexBox = scaledBox; getTransform().mul( convexBox ); convexBox.minExtents += postTickVector; convexBox.maxExtents += postTickVector; // Determine the Collision Mask. const U32 collisionMask = ( isInWater() ) ? ( sGroundCollisionMask | sMoveCollisionMask ) : sMoveCollisionMask; // Build List of Contacts. CollisionWorkingList &rList = mConvex.getWorkingList(); for ( CollisionWorkingList *pList = rList.wLink.mNext; pList != &rList; pList = pList->wLink.mNext ) { Convex *convexShape = pList->mConvex; // Valid Collision Target? if ( !( convexShape->getObject()->getTypeMask() & collisionMask ) ) { // No, Continue. continue; } // Overlap? const Box3F &collisionConvexBox = convexShape->getBoundingBox(); if ( convexBox.isOverlapped( collisionConvexBox ) ) { // Build Contact Information. convexShape->getPolyList( &sExtrudedPolyList ); } } // Valid Collision? if ( sCollisionList.getCount() == 0 || sCollisionList.getTime() > 1.f ) { // No, Quit Now. return false; } // Use First Collision. Collision *collision = &sCollisionList[0]; // More Collisions? if ( sCollisionList.getCount() > 1 ) { // Check for Better Contacts. for ( Collision *cp = ( collision + 1 ); cp != ( collision + sCollisionList.getCount() ); cp++ ) { if ( cp->faceDot > collision->faceDot ) { // Use this One. collision = cp; } } } // Store Reference. pCollision = collision; // Valid Collision. return true; }
//----------------------------------------------------------------------------- // // VActorPhysicsController::findGroundContact( pContactObject, pContactPoint, pContactNormal ); // // ... // //----------------------------------------------------------------------------- bool VActorPhysicsController::findGroundContact( SceneObject *&pContactObject, Point3F &pContactPoint, VectorF &pContactNormal ) { // Setup Collision List. static CollisionList sCollisionList; sCollisionList.clear(); static Polyhedron sBoxPolyhedron; static ExtrudedPolyList sExtrudedPolyList; // Fetch Max Step Height. const F32 stepHeight = mObject->getDataBlock()->getMaxStepHeight(); // Determine Positions. const Point3F preTickPosition = getPosition() + Point3F( 0.f, 0.f, stepHeight ); const VectorF preTickVelocity = getVelocity() + mGravity - VectorF( 0.f, 0.f, stepHeight / TickSec ); const Point3F postTickPosition = preTickPosition + ( preTickVelocity * TickSec ); const VectorF postTickVector = postTickPosition - preTickPosition; // Construct Scaled Box. Box3F scaledBox = mObject->getObjBox(); scaledBox.minExtents.convolve( mObject->getScale() ); scaledBox.maxExtents.convolve( mObject->getScale() ); // Setup Polyherdron. MatrixF collisionMatrix( true ); collisionMatrix.setPosition( preTickPosition ); sBoxPolyhedron.buildBox( collisionMatrix, scaledBox, true ); // Setup Extruded Poly List. sExtrudedPolyList.extrude( sBoxPolyhedron, postTickVector ); sExtrudedPolyList.setVelocity( preTickVelocity ); sExtrudedPolyList.setCollisionList( &sCollisionList ); // Construct World Convex Box & Adjust for Sweep. Box3F convexBox = scaledBox; getTransform().mul( convexBox ); convexBox.minExtents += postTickVector; convexBox.maxExtents += postTickVector; // Build List of Contacts. CollisionWorkingList &rList = mConvex.getWorkingList(); for ( CollisionWorkingList *pList = rList.wLink.mNext; pList != &rList; pList = pList->wLink.mNext ) { Convex *convexShape = pList->mConvex; // Ground Object? if ( !( convexShape->getObject()->getTypeMask() & sGroundCollisionMask ) ) { // No, Continue. continue; } // Overlap? const Box3F &collisionConvexBox = convexShape->getBoundingBox(); if ( convexBox.isOverlapped( collisionConvexBox ) ) { // Build Contact Information. convexShape->getPolyList( &sExtrudedPolyList ); } } // Valid Collision? if ( sCollisionList.getCount() == 0 || sCollisionList.getTime() < 0.f || sCollisionList.getTime() > 1.f ) { // No, Quit Now. return false; } // Use First Collision. Collision *collision = &sCollisionList[0]; // More Collisions? if ( sCollisionList.getCount() > 1 ) { // Check for Better Contacts. for ( Collision *cp = ( collision + 1 ); cp != ( collision + sCollisionList.getCount() ); cp++ ) { if ( cp->faceDot > collision->faceDot ) { // Use this One. collision = cp; } } } // Set Properties. pContactObject = collision->object; //pContactPoint = collision->point; pContactPoint = ( preTickPosition + ( preTickVelocity * TickSec * sCollisionList.getTime() ) ); pContactNormal = collision->normal; // Valid Contact. return true; }
Point3F Etherform::_move( const F32 travelTime, Collision *outCol ) { // Try and move to new pos F32 totalMotion = 0.0f; // TODO: not used? //F32 initialSpeed = mVelocity.len(); Point3F start; Point3F initialPosition; getTransform().getColumn(3,&start); initialPosition = start; static CollisionList collisionList; static CollisionList physZoneCollisionList; collisionList.clear(); physZoneCollisionList.clear(); MatrixF collisionMatrix(true); collisionMatrix.setColumn(3, start); VectorF firstNormal(0.0f, 0.0f, 0.0f); F32 time = travelTime; U32 count = 0; static Polyhedron sBoxPolyhedron; static ExtrudedPolyList sExtrudedPolyList; static ExtrudedPolyList sPhysZonePolyList; for (; count < sMoveRetryCount; count++) { F32 speed = mVelocity.len(); if(!speed) break; Point3F end = start + mVelocity * time; Point3F distance = end - start; if (mFabs(distance.x) < mObjBox.len_x() && mFabs(distance.y) < mObjBox.len_y() && mFabs(distance.z) < mObjBox.len_z()) { // We can potentially early out of this. If there are no polys in the clipped polylist at our // end position, then we can bail, and just set start = end; Box3F wBox = mScaledBox; wBox.minExtents += end; wBox.maxExtents += end; static EarlyOutPolyList eaPolyList; eaPolyList.clear(); eaPolyList.mNormal.set(0.0f, 0.0f, 0.0f); eaPolyList.mPlaneList.clear(); eaPolyList.mPlaneList.setSize(6); eaPolyList.mPlaneList[0].set(wBox.minExtents,VectorF(-1.0f, 0.0f, 0.0f)); eaPolyList.mPlaneList[1].set(wBox.maxExtents,VectorF(0.0f, 1.0f, 0.0f)); eaPolyList.mPlaneList[2].set(wBox.maxExtents,VectorF(1.0f, 0.0f, 0.0f)); eaPolyList.mPlaneList[3].set(wBox.minExtents,VectorF(0.0f, -1.0f, 0.0f)); eaPolyList.mPlaneList[4].set(wBox.minExtents,VectorF(0.0f, 0.0f, -1.0f)); eaPolyList.mPlaneList[5].set(wBox.maxExtents,VectorF(0.0f, 0.0f, 1.0f)); // Build list from convex states here... CollisionWorkingList& rList = mConvex.getWorkingList(); CollisionWorkingList* pList = rList.wLink.mNext; while (pList != &rList) { Convex* pConvex = pList->mConvex; if (pConvex->getObject()->getTypeMask() & sCollisionMoveMask) { Box3F convexBox = pConvex->getBoundingBox(); if (wBox.isOverlapped(convexBox)) { // No need to separate out the physical zones here, we want those // to cause a fallthrough as well... pConvex->getPolyList(&eaPolyList); } } pList = pList->wLink.mNext; } if (eaPolyList.isEmpty()) { totalMotion += (end - start).len(); start = end; break; } } collisionMatrix.setColumn(3, start); sBoxPolyhedron.buildBox(collisionMatrix, mScaledBox, true); // Setup the bounding box for the extrudedPolyList Box3F plistBox = mScaledBox; collisionMatrix.mul(plistBox); Point3F oldMin = plistBox.minExtents; Point3F oldMax = plistBox.maxExtents; plistBox.minExtents.setMin(oldMin + (mVelocity * time) - Point3F(0.1f, 0.1f, 0.1f)); plistBox.maxExtents.setMax(oldMax + (mVelocity * time) + Point3F(0.1f, 0.1f, 0.1f)); // Build extruded polyList... VectorF vector = end - start; sExtrudedPolyList.extrude(sBoxPolyhedron,vector); sExtrudedPolyList.setVelocity(mVelocity); sExtrudedPolyList.setCollisionList(&collisionList); sPhysZonePolyList.extrude(sBoxPolyhedron,vector); sPhysZonePolyList.setVelocity(mVelocity); sPhysZonePolyList.setCollisionList(&physZoneCollisionList); // Build list from convex states here... CollisionWorkingList& rList = mConvex.getWorkingList(); CollisionWorkingList* pList = rList.wLink.mNext; while (pList != &rList) { Convex* pConvex = pList->mConvex; if (pConvex->getObject()->getTypeMask() & sCollisionMoveMask) { Box3F convexBox = pConvex->getBoundingBox(); if (plistBox.isOverlapped(convexBox)) { if (pConvex->getObject()->getTypeMask() & PhysicalZoneObjectType) pConvex->getPolyList(&sPhysZonePolyList); else pConvex->getPolyList(&sExtrudedPolyList); } } pList = pList->wLink.mNext; } // Take into account any physical zones... for (U32 j = 0; j < physZoneCollisionList.getCount(); j++) { AssertFatal(dynamic_cast<PhysicalZone*>(physZoneCollisionList[j].object), "Bad phys zone!"); const PhysicalZone* pZone = (PhysicalZone*)physZoneCollisionList[j].object; if (pZone->isActive()) mVelocity *= pZone->getVelocityMod(); } if (collisionList.getCount() != 0 && collisionList.getTime() < 1.0f) { // Set to collision point F32 velLen = mVelocity.len(); F32 dt = time * getMin(collisionList.getTime(), 1.0f); start += mVelocity * dt; time -= dt; totalMotion += velLen * dt; // Back off... if ( velLen > 0.f ) { F32 newT = getMin(0.01f / velLen, dt); start -= mVelocity * newT; totalMotion -= velLen * newT; } // Pick the surface most parallel to the face that was hit. const Collision *collision = &collisionList[0]; const Collision *cp = collision + 1; const Collision *ep = collision + collisionList.getCount(); for (; cp != ep; cp++) { if (cp->faceDot > collision->faceDot) collision = cp; } F32 bd = -mDot(mVelocity, collision->normal); // Copy this collision out so // we can use it to do impacts // and query collision. *outCol = *collision; // Subtract out velocity VectorF dv = collision->normal * (bd + sNormalElasticity); mVelocity += dv; if (count == 0) { firstNormal = collision->normal; } else { if (count == 1) { // Re-orient velocity along the crease. if (mDot(dv,firstNormal) < 0.0f && mDot(collision->normal,firstNormal) < 0.0f) { VectorF nv; mCross(collision->normal,firstNormal,&nv); F32 nvl = nv.len(); if (nvl) { if (mDot(nv,mVelocity) < 0.0f) nvl = -nvl; nv *= mVelocity.len() / nvl; mVelocity = nv; } } } } } else { totalMotion += (end - start).len(); start = end; break; } } if (count == sMoveRetryCount) { // Failed to move start = initialPosition; mVelocity.set(0.0f, 0.0f, 0.0f); } return start; }