Làm thế nào để có được cuộc gọi lại va chạm của hai đối tượng cụ thể bằng cách sử dụng vật lý đạn?


7

Tôi gặp vấn đề khi thực hiện gọi lại va chạm vào dự án của mình. Tôi muốn có sự phát hiện giữa hai đối tượng cụ thể. Tôi đã có va chạm Normall nhưng tôi muốn một đối tượng dừng hoặc thay đổi màu sắc hoặc bất cứ điều gì khi colides với một đối tượng khác. Tôi đã viết mã từ đạn wiki:

int numManifolds = dynamicsWorld->getDispatcher()->getNumManifolds();
    for (int i=0;i<numManifolds;i++)
    {
        btPersistentManifold* contactManifold =  dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
        btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
        btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());

        int numContacts = contactManifold->getNumContacts();
        for (int j=0;j<numContacts;j++)
        {
            btManifoldPoint& pt = contactManifold->getContactPoint(j);
            if (pt.getDistance()<0.f)
            {
                const btVector3& ptA = pt.getPositionWorldOnA();
                const btVector3& ptB = pt.getPositionWorldOnB();
                const btVector3& normalOnB = pt.m_normalWorldOnB;
                bool x = (ContactProcessedCallback)(pt,fallRigidBody,earthRigidBody);
                if(x)
                    printf("collision\n");
            }
        }
    }

trong đó fallRigidBody là một cơ thể năng động - một hình cầu và earthRigiBody là cơ thể tĩnh - StaticPlaneShape và hình cầu không chạm vào earthRigidBody mọi lúc. Tôi cũng có những vật thể khác đang va chạm với quả cầu và nó hoạt động tốt. Nhưng chương trình phát hiện va chạm mọi lúc. Nó không quan trọng nếu các đối tượng là hoặc không va chạm.

Tôi cũng đã thêm sau khi tuyên bố của cơ thể cứng nhắc:

    earthRigidBody->setCollisionFlags(earthRigidBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
fallRigidBody->setCollisionFlags(fallRigidBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);

Vì vậy, ai đó có thể cho tôi biết những gì tôi đang làm sai? Có lẽ nó là một cái gì đó đơn giản?


Câu trả lời:


3

Tôi quen thuộc với JBONS nhưng vì cổng java của bản gốc nên khái niệm này phải giống nhau.

Dường như với tôi rằng luôn có một sự va chạm với mặt phẳng tĩnh của bạn và các vật thể khác. Nhưng bạn cần phải làm một cái gì đó chỉ khi va chạm của các đối tượng cụ thể. Những gì bạn cần sử dụng là con trỏ người dùng của hình dạng va chạm. Đây là một đoạn mã từ công cụ của riêng tôi trong java. Ở đây GameEntity là lớp tôi bọc các đối tượng của mình và CollisionListener là một lớp khác của tôi mà tôi sử dụng để thực hiện những gì va chạm. Tôi cũng vượt qua các vị trí và va chạm bình thường để người nghe đạt được các hiệu ứng lạ mắt hơn.

            if (pt.getDistance() < 0.f) {
                Vector3f ptA = pt.getPositionWorldOnA(new Vector3f());
                Vector3f ptB = pt.getPositionWorldOnB(new Vector3f());
                Vector3f normalOnB = pt.normalWorldOnB;
                GameEntity thisObject = (GameEntity) (obA.getUserPointer());
                GameEntity thatObject = (GameEntity) (obB.getUserPointer());
                if(thisObject == null){
                    return;
                }
                if (thisObject.getCollisionListener() != null) {
                    thisObject.getCollisionListener().collided(
                            ptA, ptB, normalOnB, thatObject);
                }
                if (thatObject.getCollisionListener() != null) {
                    thatObject.getCollisionListener().collided(
                            ptB, ptA, normalOnB, thisObject);
                }
            }

0

Ví dụ runnable tối thiểu

Hai quả cầu rơi từ độ cao khác nhau về chức năng của thời gian.

Vì chúng bắt đầu ở các độ cao khác nhau, chúng sẽ chạm đất vào những thời điểm khác nhau.

Chúng tôi phát hiện mặt đất chạm vào, và in ra quả cầu nào chạm đất khi nào.

Trực quan Gnuplot của thiết bị xuất chuẩn:

Xem cách làm:

  • Khi một quả cầu chạm đất, chỉ báo va chạm hình vuông màu hồng sẽ chuyển sang 1
  • Khi quả cầu khác chạm đất, màu xanh lá cây Xchuyển sang1

Mã số:

#include <cstdio>
#include <cstdlib>
#include <map>
#include <vector>

#include <btBulletDynamicsCommon.h>

#define PRINTF_FLOAT "%7.3f"

constexpr float gravity = -10.0f;
constexpr float timeStep = 1.0f / 60.0f;
constexpr float groundRestitution = 0.9f;
constexpr float objectRestitution = 0.9f;
constexpr int maxNPoints = 500;
constexpr float initialXs[] = {  0.0f, 5.0f };
constexpr float initialYs[] = { 10.0f, 5.0f };
constexpr size_t nObjects = sizeof(initialYs) / sizeof(*initialYs);

std::map<const btCollisionObject*,std::vector<btManifoldPoint*>> objectsCollisions;
void myTickCallback(btDynamicsWorld *dynamicsWorld, btScalar timeStep) {
    objectsCollisions.clear();
    int numManifolds = dynamicsWorld->getDispatcher()->getNumManifolds();
    for (int i = 0; i < numManifolds; i++) {
        btPersistentManifold *contactManifold = dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
        auto *objA = contactManifold->getBody0();
        auto *objB = contactManifold->getBody1();
        auto& collisionsA = objectsCollisions[objA];
        auto& collisionsB = objectsCollisions[objB];
        int numContacts = contactManifold->getNumContacts();
        for (int j = 0; j < numContacts; j++) {
            btManifoldPoint& pt = contactManifold->getContactPoint(j);
            collisionsA.push_back(&pt);
            collisionsB.push_back(&pt);
        }
    }
}

int main() {
    int i, j;

    btDefaultCollisionConfiguration *collisionConfiguration
            = new btDefaultCollisionConfiguration();
    btCollisionDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration);
    btBroadphaseInterface *overlappingPairCache = new btDbvtBroadphase();
    btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
    btDiscreteDynamicsWorld *dynamicsWorld = new btDiscreteDynamicsWorld(
            dispatcher, overlappingPairCache, solver, collisionConfiguration);
    dynamicsWorld->setGravity(btVector3(0, gravity, 0));
    dynamicsWorld->setInternalTickCallback(myTickCallback);
    btAlignedObjectArray<btCollisionShape*> collisionShapes;

    // Ground.
    {
        btTransform groundTransform;
        groundTransform.setIdentity();
        groundTransform.setOrigin(btVector3(0, 0, 0));
        btCollisionShape* groundShape;
        groundShape = new btStaticPlaneShape(btVector3(0, 1, 0), -1);
        collisionShapes.push_back(groundShape);
        btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
        btRigidBody::btRigidBodyConstructionInfo rbInfo(0, myMotionState, groundShape, btVector3(0, 0, 0));
        btRigidBody* body = new btRigidBody(rbInfo);
        body->setRestitution(groundRestitution);
        dynamicsWorld->addRigidBody(body);
    }

    // Objects.
    for (size_t i = 0; i < nObjects; ++i) {
        btCollisionShape *colShape;
        colShape = new btSphereShape(btScalar(1.0));
        collisionShapes.push_back(colShape);
        btTransform startTransform;
        startTransform.setIdentity();
        startTransform.setOrigin(btVector3(initialXs[i], initialYs[i], 0));
        btVector3 localInertia(0, 0, 0);
        btScalar mass(1.0f);
        colShape->calculateLocalInertia(mass, localInertia);
        btDefaultMotionState *myMotionState = new btDefaultMotionState(startTransform);
        btRigidBody *body = new btRigidBody(btRigidBody::btRigidBodyConstructionInfo(
                mass, myMotionState, colShape, localInertia));
        body->setRestitution(objectRestitution);
        dynamicsWorld->addRigidBody(body);
    }

    // Main loop.
    std::printf("step body x y z collision2 collision1\n");
    for (i = 0; i < maxNPoints; ++i) {
        dynamicsWorld->stepSimulation(timeStep);
        for (j = dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; --j) {
            btCollisionObject *obj = dynamicsWorld->getCollisionObjectArray()[j];
            btRigidBody *body = btRigidBody::upcast(obj);
            btTransform trans;
            if (body && body->getMotionState()) {
                body->getMotionState()->getWorldTransform(trans);
            } else {
                trans = obj->getWorldTransform();
            }
            btVector3 origin = trans.getOrigin();
            std::printf("%d %d " PRINTF_FLOAT " " PRINTF_FLOAT " " PRINTF_FLOAT " ",
                    i, j, origin.getX(), origin.getY(), origin.getZ());
            auto& manifoldPoints = objectsCollisions[body];
            if (manifoldPoints.empty()) {
                std::printf("0");
            } else {
                std::printf("1");
            }
            puts("");
        }
    }

    // Cleanup.
    for (i = dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; --i) {
        btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[i];
        btRigidBody* body = btRigidBody::upcast(obj);
        if (body && body->getMotionState()) {
            delete body->getMotionState();
        }
        dynamicsWorld->removeCollisionObject(obj);
        delete obj;
    }
    for (i = 0; i < collisionShapes.size(); ++i) {
        delete collisionShapes[i];
    }
    delete dynamicsWorld;
    delete solver;
    delete overlappingPairCache;
    delete dispatcher;
    delete collisionConfiguration;
    collisionShapes.clear();
}

Đã thử nghiệm trên Bullet 2.83, Ubuntu 15.10.

GitHub ngược dòng: https://github.com/cirosantilli/cpp-cheat/blob/d7b70153b8f86b5864c22fbc6f7005049a93491f/bONS/which_collision.cpp


@Downvoters, vui lòng giải thích để tôi có thể học hỏi và cải thiện ;-)
Ciro Santilli 病毒 审查 六四 事件 26/07/17
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.