Ich verwende Bullet und versuche, einen Kollisionsalgorithmus zu erstellen, der Kontaktpunkte aus einem würfelbasierten Gelände zusammen mit der entsprechenden Kollisionsantwort generiert. Ich habe auch vor, dies auf Nicht-Box-Formen auszudehnen, aber das ist im Moment nicht wichtig. Ich habe festgestellt, dass die Verwendung eines Dreiecksnetzes für große Karten zu viel RAM ist.
Ich habe das hier von Byte56 beschriebene Verfahren ausprobiert , habe jedoch eine Reihe von Fragen zur Implementierung mit Bullet:
- Wie erzeugt man eine Kollisionsform für die Welt? Verwenden Sie eine benutzerdefinierte Form? Was willst du
m_shapeType
drauf haben? - Oder verwenden Sie immer noch eine Kastenform von der Größe der Welt?
- Wie stellen Sie sicher, dass Kontaktstellen freigegeben werden?
- Wie genau modifizierst du
processCollision
?
Was ich getan habe:
- Ich habe eine
that extends
TerrainShape btBoxShape, the only difference being that
m_shapeType = CUSTOM_CONVEX_SHAPE_TYPE` erstellt, damit ich beim Dispatcher einen neuen Kollisionsalgorithmus für Objekte mit nur dieser Form registrieren kann. - Ich habe die
btRigidBody
Klasse auf ähnliche Weise wie Byte56 in seiner Frage erweitert (siehe den Link im 2. Absatz), gebe jedochcheckCollisionWith(CollisionObject * co)
true zurück, wenn ein Voxel im AABB vonco
nicht air ist. Ich habe die erweiterte
btCollisionAlgorithm
Klasse, in ähnlicher Weise wiebtCompoundCollisionAlgorithm
mitprocessCollision
dem folgenden Aktionen ausführen:- Überprüfen Sie die kollidierenden Objekte, die als Argumente übergeben wurden, und bestimmen Sie, welches das Terrain und welches die Entität ist.
- Löschen Sie die Verteiler aller untergeordneten Algorithmen.
- Anruf
resultOut->setPersistantManifold(resultOut)
- Generieren Sie neue Boxformen und Transformationen in der AABB, die von der kollidierenden Entität belegt wird, und rufen Sie dann auf
m_dispatcher->findAlgorithm
. Speichern Sie die Form, Transformation und den gefundenen Algorithmus in einer untergeordneten Algorithmusstruktur für jedes Voxel innerhalb des AABB. - Durchlaufen Sie alle untergeordneten Algorithmen und rufen Sie sie auf
proccessCollision
. - Durchlaufen Sie alle untergeordneten Algorithmen und entfernen Sie alle jetzt außerhalb des AABB der kollidierenden Entität. (ruft
~btCollisionAlgorithm()
dann anm_dispatcher->freeCollisionAlgorithm()
) - Rufen Sie an
resultOut->refreshContactPoints()
.
Was funktioniert: processCollision
Wird immer dann aufgerufen, wenn sich der AABB des Spielers mit Nicht-Luft-Voxeln schneidet.
Was nicht: Die Kollisionsreaktion ist einfach komisch ... Die Spielerentität beginnt nach oben zu schweben. Wenn es in etwas hineingeht, prallt es heftig ab. Manchmal kann es sich nicht mehr auf einer Achse bewegen, nachdem es in etwas hineingegangen ist. Was ich vermute, ist, dass Kontaktpunkte nach einer Kollisionsreaktion nicht freigegeben werden, möglicherweise weil sich die Spielerentität immer im AABB des Weltobjekts befindet. Ich bin gespannt, ob ich in Bezug auf den richtigen Baum belle processCollision
?
quelle
Antworten:
Leider konnte ich mit der in der Antwort, auf die Sie sich beziehen, beschriebenen Methode keine zuverlässigen Ergebnisse erzielen . Ähnlich wie bei Ihnen würde ich seltsame schwebende Ereignisse bekommen oder Situationen, in denen das Entfernen eines Voxels dazu führen würde, dass darüber schwebende Objekte in der Luft schweben oder eine seltsame oszillierende Feder zu Boden fällt. Ich habe diese Strategie für eine neue Strategie aufgegeben.
Ich fing an, benutzerdefinierte Kollisionsnetze für jedes Stück Voxel-Terrain zu erstellen. Ich mache das mit dem
BvhTriangleMeshShape
. Das funktioniert ganz gut:Weitere Details zur Implementierung der benutzerdefinierten Kollisionsnetze finden Sie hier .
quelle