Wie neu berechnen axis-aligned bounding box nach dem übersetzen/drehen?
Als ich zum ersten laden mein Objekt-ich berechne die ersten AABB mit der max und min (x,y,z) Punkte. Dies ist aber im Objekt-Raum und das Objekt bewegt sich um die Welt und noch wichtiger ist, dreht.
Wie kann ich eine Neuberechnung der neue AABB jedes mal, wenn das Objekt übersetzt/gedreht? Dies geschieht im Grunde bei jedem frame, ist es wohl ein sehr intensiver Vorgang um eine Neuberechnung der neue AABB jeden frame? Wenn ja, was wäre die alternative?
Ich weiß AABBs mein Kollisionserkennung weniger genau, aber es ist einfacher zu implementieren die collision detection code als OBBs und ich möchte, dass dies einen Schritt zu einer Zeit.
Hier ist meine aktuelle code nach einige Einblicke aus den Antworten unten:
typedef struct sAxisAlignedBoundingBox {
Vector3D bounds[8];
Vector3D max, min;
} AxisAlignedBoundingBox;
void drawAxisAlignedBoundingBox(AxisAlignedBoundingBox box) {
glPushAttrib(GL_LIGHTING_BIT | GL_POLYGON_BIT);
glEnable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHTING);
glColor3f(1.0f, 1.0f, 0.0f);
glBegin(GL_LINE_LOOP);
glVertex3f(box.bounds[0].x, box.bounds[0].y, box.bounds[0].z);
glVertex3f(box.bounds[1].x, box.bounds[1].y, box.bounds[1].z);
glVertex3f(box.bounds[2].x, box.bounds[2].y, box.bounds[2].z);
glVertex3f(box.bounds[3].x, box.bounds[3].y, box.bounds[3].z);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f(box.bounds[4].x, box.bounds[4].y, box.bounds[4].z);
glVertex3f(box.bounds[5].x, box.bounds[5].y, box.bounds[5].z);
glVertex3f(box.bounds[6].x, box.bounds[6].y, box.bounds[6].z);
glVertex3f(box.bounds[7].x, box.bounds[7].y, box.bounds[7].z);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f(box.bounds[0].x, box.bounds[0].y, box.bounds[0].z);
glVertex3f(box.bounds[5].x, box.bounds[5].y, box.bounds[5].z);
glVertex3f(box.bounds[6].x, box.bounds[6].y, box.bounds[6].z);
glVertex3f(box.bounds[1].x, box.bounds[1].y, box.bounds[1].z);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f(box.bounds[4].x, box.bounds[4].y, box.bounds[4].z);
glVertex3f(box.bounds[7].x, box.bounds[7].y, box.bounds[7].z);
glVertex3f(box.bounds[2].x, box.bounds[2].y, box.bounds[2].z);
glVertex3f(box.bounds[3].x, box.bounds[3].y, box.bounds[3].z);
glEnd();
glPopAttrib();
}
void calculateAxisAlignedBoundingBox(GLMmodel *model, float matrix[16]) {
AxisAlignedBoundingBox box;
float dimensions[3];
//This will give me the absolute dimensions of the object
glmDimensions(model, dimensions);
//This calculates the max and min points in object space
box.max.x = dimensions[0] / 2.0f, box.min.x = -1.0f * box.max.x;
box.max.y = dimensions[1] / 2.0f, box.min.y = -1.0f * box.max.y;
box.max.z = dimensions[2] / 2.0f, box.min.z = -1.0f * box.max.z;
//These calculations are probably the culprit but I don't know what I'm doing wrong
box.max.x = matrix[0] * box.max.x + matrix[4] * box.max.y + matrix[8] * box.max.z + matrix[12];
box.max.y = matrix[1] * box.max.x + matrix[5] * box.max.y + matrix[9] * box.max.z + matrix[13];
box.max.z = matrix[2] * box.max.x + matrix[6] * box.max.y + matrix[10] * box.max.z + matrix[14];
box.min.x = matrix[0] * box.min.x + matrix[4] * box.min.y + matrix[8] * box.min.z + matrix[12];
box.min.y = matrix[1] * box.min.x + matrix[5] * box.min.y + matrix[9] * box.min.z + matrix[13];
box.min.z = matrix[2] * box.min.x + matrix[6] * box.min.y + matrix[10] * box.min.z + matrix[14];
/* NOTE: If I remove the above calculations and do something like this:
box.max = box.max + objPlayer.position;
box.min = box.min + objPlayer.position;
The bounding box will move correctly when I move the player, the same does not
happen with the calculations above. It makes sense and it's very simple to move
the box like this. The only problem is when I rotate the player, the box should
be adapted and increased/decreased in size to properly fit the object as a AABB.
*/
box.bounds[0] = Vector3D(box.max.x, box.max.y, box.min.z);
box.bounds[1] = Vector3D(box.min.x, box.max.y, box.min.z);
box.bounds[2] = Vector3D(box.min.x, box.min.y, box.min.z);
box.bounds[3] = Vector3D(box.max.x, box.min.y, box.min.z);
box.bounds[4] = Vector3D(box.max.x, box.min.y, box.max.z);
box.bounds[5] = Vector3D(box.max.x, box.max.y, box.max.z);
box.bounds[6] = Vector3D(box.min.x, box.max.y, box.max.z);
box.bounds[7] = Vector3D(box.min.x, box.min.y, box.max.z);
//This draw call is for testing porpuses only
drawAxisAlignedBoundingBox(box);
}
void drawObjectPlayer(void) {
static float mvMatrix[16];
if(SceneCamera.GetActiveCameraMode() == CAMERA_MODE_THIRD_PERSON) {
objPlayer.position = SceneCamera.GetPlayerPosition();
objPlayer.rotation = SceneCamera.GetRotationAngles();
objPlayer.position.y += -PLAYER_EYE_HEIGHT + 0.875f;
/* Only one of the two code blocks below should be active at the same time
Neither of them is working as expected. The bounding box doesn't is all
messed up with either code. */
//Attempt #1
glPushMatrix();
glTranslatef(objPlayer.position.x, objPlayer.position.y, objPlayer.position.z);
glRotatef(objPlayer.rotation.y + 180.0f, 0.0f, 1.0f, 0.0f);
glCallList(gameDisplayLists.player);
glGetFloatv(GL_MODELVIEW_MATRIX, mvMatrix);
glPopMatrix();
//Attempt #2
glPushMatrix();
glLoadIdentity();
glTranslatef(objPlayer.position.x, objPlayer.position.y, objPlayer.position.z);
glRotatef(objPlayer.rotation.y + 180.0f, 0.0f, 1.0f, 0.0f);
glGetFloatv(GL_MODELVIEW_MATRIX, mvMatrix);
glPopMatrix();
calculateAxisAlignedBoundingBox(objPlayer.model, mvMatrix);
}
}
Aber es funktioniert nicht wie es sollte... Was mache ich falsch?
InformationsquelleAutor der Frage Ricardo Amaral | 2011-05-19
Du musst angemeldet sein, um einen Kommentar abzugeben.
Einfach neu berechnen, die AABB des transformierten AABB. Dies bedeutet die Umwandlung 8 Ecken ( 8 vertex - matrix-Multiplikationen ) und 8 vertex-vertex Vergleiche.
Also bei der Initialisierung, Sie berechnen Ihre AABB in Modellbereich : für jedes x,y,z jedes vertex des Modells, markieren Sie das Kontrollkästchen vor xmin, xmax, ymin, ymax, ...
Jedem frame, erzeugen Sie eine neue Transformations-matrix. In OpenGL ist dies mit glLoadIdentity gefolgt von glTransform/Drehen/Skalieren (bei Verwendung der alten API). Dies ist das Modell Matrix, wie lmmilewski sagte.
Berechnest du diese transformation matrix ein zweites mal (außerhalb von Opengl, z.B. mit glm). Sie können auch erhalten OpenGL die resultierende matrix mit glGet.
Multiplizieren Sie jede Ihrer AABB acht Scheitelpunkte von dieser matrix. Verwenden glm für matrix-Vektor-Multiplikation. Sie bekommen Ihr verwandelt AABB (Welt-Raum). Es es sehr wahrscheinlich gedreht (nicht die Achse ausgerichtet und mehr)
Nun den Algorithmus wahrscheinlich nur mit Achse ausgerichtet Zeug, damit Ihre Frage. So, jetzt habt Ihr ungefähr mit dem neuen bounding-box des transformierten Modells durch takinf die bounding box die bounding box transformiert:
für jedes x,y,z von jedem Eckpunkt des neuen AABB überprüfen Sie vor xmin, xmax, ymin, ymax, ... damit erhalten Sie einen Welt-Raum, AABB, die Sie verwenden können, in Ihrem clipping-Algorithmus.
Dies ist nicht optimal (AABB-Weise), erhalten Sie jede Menge leerer Raum, aber performance-Weise, ist es viel viel besser, recomputing die AABB der gesamten mesh.
Als für die Transformations-matrix, in drawObjectPlayer:
Kann nicht erklären, weiter als das... wie gesagt in den Kommentaren, die Sie hatten, es zu tun zweimal. Sie hätte nicht diese Probleme und hässliche workarounds in OpenGL 3, btw, da wären Sie voll verantwortlich für Ihre eigenen Matrizen. Entspricht in OpenGL 2 :
viel sauberer rechten
InformationsquelleAutor der Antwort Calvin1602
Zitat einer vorherigen Antwort: AABB @ Stackoverflow
Skurmedel
Dem Beklagten den Vorschlag, und meine, ist die Umsetzung orientierte bounding-Boxen haben Sie AABB arbeiten, und auch auf Hinweis: Sie können aabb ist der Teile eines Netzes zu fudge Kollisionserkennung mit größerer Genauigkeit als 1 riesige box für jedes Objekt.
InformationsquelleAutor der Antwort TurboKnight
Zu tun, dass Sie haben, um eine Schleife über jeden Eckpunkt berechnen Sie die position in der Welt (durch multiplizieren modelview) und minimum /maximum-vertex-Koordinaten innerhalb jedes Objekt (wie wenn Sie berechnen für die erste Zeit).
Können Sie die Skalierung ein bisschen Ihre AABB, so dass Sie nicht haben, um neu berechnen - es ist genug, um es zu vergrößern um den Faktor sqrt(2) - des gedrehten Objekts, dann passt immer in AABB.
Es ist auch eine Frage, in welche Richtung Sie drehen? Wenn immer, dann können Sie vergrößern AABB nur in diese Richtung.
Optional können Sie verwenden, bounding-Sphären anstelle von AABBs.Dann brauchen Sie sich nicht kümmern, rotation und Skalierung ist kein problem.
Am Ende muss ich Fragen, wenn Sie sicher sind, dass diese einen Engpass in Ihrer Anwendung. Ich glaube, es ist nicht und in diesem Fall würde ich die erste option, die ich erwähnt (iterieren über alle Eckpunkte).
InformationsquelleAutor der Antwort Łukasz Milewski
Warum nicht die GPU? Heute habe ich implimented eine Lösung dieses Problems durch rendening ein paar frames.
nach unten auf das Objekt.
nichts.
Ich weiß, das ist nicht eine Lösung für alle Fälle, aber mit einigen Vorkenntnissen, ist dies sehr effizient.
Für die Darstellung vom Bildschirm sehen hier.
InformationsquelleAutor der Antwort user2378218