Ich versuche, Geländekollision für meine Höhenkarte Terrain zu implementieren, und ich werde this folgen. Das Tutorial ist für Java, aber ich benutze C++, obwohl die Prinzipien die gleichen sind, so sollte es kein Problem sein.Geländekollision Probleme
Zu Beginn benötigen wir eine Funktion, um die Höhe des Geländes anhand der Kameraposition zu ermitteln. WorldX und WorldZ ist die Position der Kamera (x, z) und die Höhe ist ein 2D-Array, das alle Höhen der Ecken enthält.
float HeightMap::getHeightOfTerrain(float worldX, float worldZ, float heights[][256])
{
//Image is (256 x 256)
float gridLength = 256;
float terrainLength = 256;
float terrainX = worldX;
float terrainZ = worldZ;
float gridSquareLength = terrainLength/((float)gridLength - 1);
int gridX = (int)std::floor(terrainX/gridSquareLength);
int gridZ = (int)std::floor(terrainZ/gridSquareLength);
//Check if position is on the terrain
if (gridX >= gridLength - 1 || gridZ >= gridLength - 1 || gridX < 0 || gridZ < 0)
{
return 0;
}
//Find out where the player is on the grid square
float xCoord = std::fmod(terrainX, gridSquareLength)/gridSquareLength;
float zCoord = std::fmod(terrainZ, gridSquareLength)/gridSquareLength;
float answer = 0.0;
//Top triangle of a square else the bottom
if (xCoord <= (1 - zCoord))
{
answer = barryCentric(glm::vec3(0, heights[gridX][gridZ], 0),
glm::vec3(1, heights[gridX + 1][gridZ], 0), glm::vec3(0, heights[gridX][gridZ + 1], 1),
glm::vec2(xCoord, zCoord));
}
else
{
answer = barryCentric(glm::vec3(1, heights[gridX + 1][gridZ], 0),
glm::vec3(1, heights[gridX + 1][gridZ + 1], 1), glm::vec3(0, heights[gridX][gridZ + 1], 1),
glm::vec2(xCoord, zCoord));
}
return answer;
}
Um die Höhe des Dreiecks finden die Kamera aktuell wir Funktion die baryzentrische Interpolation steht.
float HeightMap::barryCentric(glm::vec3 p1, glm::vec3 p2, glm::vec3 p3, glm::vec2 pos)
{
float det = (p2.z - p3.z) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.z - p3.z);
float l1 = ((p2.z - p3.z) * (pos.x - p3.x) + (p3.x - p2.x) * (pos.y - p3.z))/det;
float l2 = ((p3.z - p1.z) * (pos.x - p3.x) + (p1.x - p3.x) * (pos.y - p3.z))/det;
float l3 = 1.0f - l1 - l2;
return l1 * p1.y + l2 * p2.y + l3 * p3.y;
}
Dann müssen wir nur die Höhe verwenden wir berechnet haben für Kollision während des Spiels
float terrainHeight = heightMap.getHeightOfTerrain(camera.Position.x, camera.Position.z, heights);
if (camera.Position.y < terrainHeight)
{
camera.Position.y = terrainHeight;
};
nun nach dem Tutorial zu überprüfen, sollte dies völlig in Ordnung arbeiten, aber die Höhe ist eher ab und an manchen Orten funktioniert es nicht einmal. Habe ich es etwas haben könnte, mit der Übersetzung und Skalierung Teil des Geländes
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0f, -0.3f, -15.0f));
model = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f));
und dass ich um 0,1 die Werte der Höhen-Array multiplizieren sollte zu tun, da die Skalierung für das Gelände, dass ein Teil tut auf der GPU Seite, aber das hat den Trick nicht gemacht.
Hinweis
Im Tutorial die ersten Zeilen in der getHeightOfTerrain Funktion sagen
float terrainX = worldX - x;
float terrainZ = worldZ - z;
wobei x und z die Weltposition des Geländes ist. Dies wird getan, um die Spielerposition relativ zur Position des Geländes zu erhalten. Ich habe versucht mit den Werten aus dem Übersetzungsteil, aber es funktioniert auch nicht. Ich habe diese Zeilen geändert, weil es nicht notwendig erscheint.
Ich sehe, jetzt weiß ich nicht, ob das albern klingt, aber wie könnte ich den Weltpositionsvektor finden, da ich nur einen Übersetzungsvektor habe, der die lokale Raumposition ausgleicht, aber ich kenne die lokale Raumposition nicht weil es für jede Ecke anders ist und die GPU jede Ecke einzeln mit diesem Übersetzungsvektor ausgleicht?Wenn du verstehst, was ich meine? @Evil Tak – Riggs
Sie benötigen nur die Welt-Raumposition der unteren linken Ecke (vorausgesetzt, die X-, Y- und Z-Achsen zeigen nach rechts, oben bzw. nach vorne) des Geländes. – EvilTak
Welches gefunden werden könnte, indem der erste Index des Vektors mit allen Scheitelpunkten überprüft und dann übersetzt wird: (0.0, 0.89, 0.0) + (0.0, -0.3, -15.0) = (0.0, 0.59, -15.0)? (Wenn ich keine Skalierung mache) @Evil Tak – Riggs