计算轴对齐边界框的大小
Calculating the size of an Axis Aligned Bounding Box
我目前正在学习使用 LWJGL 和 OpenGL 的 ThinMatrix 3d 游戏开发教程。我正在尝试在我的游戏中实施碰撞检测。我已经准备好检测 AABB 与 AABB 碰撞的代码,但似乎无法弄清楚如何获取实体周围边界框的大小。有人可以指导我计算 AABB 的大小吗?这是 OBJFileLoader class -
package objConverter;
import models.RawModel;
import org.lwjgl.util.vector.*;
import renderEngine.Loader;
import java.io.*;
import java.util.*;
public class OBJFileLoader {
private static final String RES_LOC = "res/models/";
public static RawModel loadOBJ(String objFileName, Loader loader) {
FileReader isr = null;
File objFile = new File(RES_LOC + objFileName + ".obj");
try {
isr = new FileReader(objFile);
} catch (FileNotFoundException e) {
System.err.println("File not found in res; don't use any extension: " + e.getMessage());
}
BufferedReader reader = new BufferedReader(isr);
String line;
List<Vertex> vertices = new ArrayList<>();
List<Vector2f> textures = new ArrayList<>();
List<Vector3f> normals = new ArrayList<>();
List<Integer> indices = new ArrayList<>();
try {
while (true) {
line = reader.readLine();
if (line.startsWith("v ")) {
String[] currentLine = line.split(" ");
Vector3f vertex = new Vector3f(Float.valueOf(currentLine[1]), Float.valueOf(currentLine[2]), Float.valueOf(currentLine[3]));
Vertex newVertex = new Vertex(vertices.size(), vertex);
vertices.add(newVertex);
} else if (line.startsWith("vt ")) {
String[] currentLine = line.split(" ");
Vector2f texture = new Vector2f(Float.valueOf(currentLine[1]), Float.valueOf(currentLine[2]));
textures.add(texture);
} else if (line.startsWith("vn ")) {
String[] currentLine = line.split(" ");
Vector3f normal = new Vector3f(Float.valueOf(currentLine[1]), Float.valueOf(currentLine[2]), Float.valueOf(currentLine[3]));
normals.add(normal);
} else if (line.startsWith("f ")) {
break;
}
}
while (line != null && line.startsWith("f ")) {
String[] currentLine = line.split(" ");
String[] vertex1 = currentLine[1].split("/");
String[] vertex2 = currentLine[2].split("/");
String[] vertex3 = currentLine[3].split("/");
Vertex v0 = processVertex(vertex1, vertices, indices);
Vertex v1 = processVertex(vertex2, vertices, indices);
Vertex v2 = processVertex(vertex3, vertices, indices);
calculateTangents(v0, v1, v2, textures);
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
System.err.println("Error reading the file");
}
removeUnusedVertices(vertices);
float[] verticesArray = new float[vertices.size() * 3];
float[] texturesArray = new float[vertices.size() * 2];
float[] normalsArray = new float[vertices.size() * 3];
float[] tangentsArray = new float[vertices.size() * 3];
float furthest = convertDataToArrays(vertices, textures, normals, verticesArray, texturesArray, normalsArray, tangentsArray);
int[] indicesArray = convertIndicesListToArray(indices);
// ModelData data = new ModelData(verticesArray, texturesArray, normalsArray, tangentsArray, indicesArray, furthest);
return loader.loadToVAO(verticesArray, texturesArray, normalsArray, indicesArray);
}
private static void calculateTangents(Vertex v0, Vertex v1, Vertex v2, List<Vector2f> textures) {
Vector3f delatPos1 = Vector3f.sub(v1.getPosition(), v0.getPosition(), null);
Vector3f delatPos2 = Vector3f.sub(v2.getPosition(), v0.getPosition(), null);
Vector2f uv0 = textures.get(v0.getTextureIndex());
Vector2f uv1 = textures.get(v1.getTextureIndex());
Vector2f uv2 = textures.get(v2.getTextureIndex());
Vector2f deltaUv1 = Vector2f.sub(uv1, uv0, null);
Vector2f deltaUv2 = Vector2f.sub(uv2, uv0, null);
float r = 1.0f / (deltaUv1.x * deltaUv2.y - deltaUv1.y * deltaUv2.x);
delatPos1.scale(deltaUv2.y);
delatPos2.scale(deltaUv1.y);
Vector3f tangent = Vector3f.sub(delatPos1, delatPos2, null);
tangent.scale(r);
v0.addTangent(tangent);
v1.addTangent(tangent);
v2.addTangent(tangent);
}
private static Vertex processVertex(String[] vertex, List<Vertex> vertices, List<Integer> indices) {
int index = Integer.parseInt(vertex[0]) - 1;
Vertex currentVertex = vertices.get(index);
int textureIndex = Integer.parseInt(vertex[1]) - 1;
int normalIndex = Integer.parseInt(vertex[2]) - 1;
if (!currentVertex.isSet()) {
currentVertex.setTextureIndex(textureIndex);
currentVertex.setNormalIndex(normalIndex);
indices.add(index);
return currentVertex;
} else {
return dealWithAlreadyProcessedVertex(currentVertex, textureIndex, normalIndex, indices, vertices);
}
}
private static int[] convertIndicesListToArray(List<Integer> indices) {
int[] indicesArray = new int[indices.size()];
for (int i = 0; i < indicesArray.length; i++) {
indicesArray[i] = indices.get(i);
}
return indicesArray;
}
private static float convertDataToArrays(List<Vertex> vertices, List<Vector2f> textures, List<Vector3f> normals, float[] verticesArray, float[] texturesArray, float[] normalsArray, float[] tangentsArray) {
float furthestPoint = 0;
for (int i = 0; i < vertices.size(); i++) {
Vertex currentVertex = vertices.get(i);
if (currentVertex.getLength() > furthestPoint) {
furthestPoint = currentVertex.getLength();
}
Vector3f position = currentVertex.getPosition();
Vector2f textureCoord = textures.get(currentVertex.getTextureIndex());
Vector3f normalVector = normals.get(currentVertex.getNormalIndex());
Vector3f tangent = currentVertex.getAverageTangent();
verticesArray[i * 3] = position.x;
verticesArray[i * 3 + 1] = position.y;
verticesArray[i * 3 + 2] = position.z;
texturesArray[i * 2] = textureCoord.x;
texturesArray[i * 2 + 1] = 1 - textureCoord.y;
normalsArray[i * 3] = normalVector.x;
normalsArray[i * 3 + 1] = normalVector.y;
normalsArray[i * 3 + 2] = normalVector.z;
tangentsArray[i * 3] = tangent.x;
tangentsArray[i * 3 + 1] = tangent.y;
tangentsArray[i * 3 + 2] = tangent.z;
}
return furthestPoint;
}
private static Vertex dealWithAlreadyProcessedVertex(Vertex previousVertex, int newTextureIndex, int newNormalIndex, List<Integer> indices, List<Vertex> vertices) {
if (previousVertex.hasSameTextureAndNormal(newTextureIndex, newNormalIndex)) {
indices.add(previousVertex.getIndex());
return previousVertex;
} else {
Vertex anotherVertex = previousVertex.getDuplicateVertex();
if (anotherVertex != null) {
return dealWithAlreadyProcessedVertex(anotherVertex, newTextureIndex, newNormalIndex, indices, vertices);
} else {
Vertex duplicateVertex = new Vertex(vertices.size(), previousVertex.getPosition());
duplicateVertex.setTextureIndex(newTextureIndex);
duplicateVertex.setNormalIndex(newNormalIndex);
previousVertex.setDuplicateVertex(duplicateVertex);
vertices.add(duplicateVertex);
indices.add(duplicateVertex.getIndex());
return duplicateVertex;
}
}
}
private static void removeUnusedVertices(List<Vertex> vertices) {
for (Vertex vertex : vertices) {
vertex.averageTangents();
if (!vertex.isSet()) {
vertex.setTextureIndex(0);
vertex.setNormalIndex(0);
}
}
}
}
我很久以前就学习了这个教程。您需要做的是存储最小和最大 x、y 和 z 分量。我建议在存储顶点的情况下这样做。你可以这样做:
float minX, minY, minZ, maxX, maxY, maxZ;
try {
while(true) {
if ("v ") {
Vector3f ver = new Vector3f(Float.valueOf(curentLine[0]... );
if (ver.x < minX) minX = ver.x;
else if (ver.x > maxX) maxX = ver.x;
if (ver.y < minY) minY = ver.y;
...
}
...
}
这是获取实体的最小和最大 x、y 和 z 边界的粗略但简单的方法。希望这有帮助。
aabb 的绝对大小应该是 max - min
;所有最大分量减负。 Max - min 也称为对角线(aabb 本身就是对角线)。
这是一个使用 glm 的例子:
vec3 max(100);
vec3 min(90);
vec3 size = max - min; // vec3(10)
我目前正在学习使用 LWJGL 和 OpenGL 的 ThinMatrix 3d 游戏开发教程。我正在尝试在我的游戏中实施碰撞检测。我已经准备好检测 AABB 与 AABB 碰撞的代码,但似乎无法弄清楚如何获取实体周围边界框的大小。有人可以指导我计算 AABB 的大小吗?这是 OBJFileLoader class -
package objConverter;
import models.RawModel;
import org.lwjgl.util.vector.*;
import renderEngine.Loader;
import java.io.*;
import java.util.*;
public class OBJFileLoader {
private static final String RES_LOC = "res/models/";
public static RawModel loadOBJ(String objFileName, Loader loader) {
FileReader isr = null;
File objFile = new File(RES_LOC + objFileName + ".obj");
try {
isr = new FileReader(objFile);
} catch (FileNotFoundException e) {
System.err.println("File not found in res; don't use any extension: " + e.getMessage());
}
BufferedReader reader = new BufferedReader(isr);
String line;
List<Vertex> vertices = new ArrayList<>();
List<Vector2f> textures = new ArrayList<>();
List<Vector3f> normals = new ArrayList<>();
List<Integer> indices = new ArrayList<>();
try {
while (true) {
line = reader.readLine();
if (line.startsWith("v ")) {
String[] currentLine = line.split(" ");
Vector3f vertex = new Vector3f(Float.valueOf(currentLine[1]), Float.valueOf(currentLine[2]), Float.valueOf(currentLine[3]));
Vertex newVertex = new Vertex(vertices.size(), vertex);
vertices.add(newVertex);
} else if (line.startsWith("vt ")) {
String[] currentLine = line.split(" ");
Vector2f texture = new Vector2f(Float.valueOf(currentLine[1]), Float.valueOf(currentLine[2]));
textures.add(texture);
} else if (line.startsWith("vn ")) {
String[] currentLine = line.split(" ");
Vector3f normal = new Vector3f(Float.valueOf(currentLine[1]), Float.valueOf(currentLine[2]), Float.valueOf(currentLine[3]));
normals.add(normal);
} else if (line.startsWith("f ")) {
break;
}
}
while (line != null && line.startsWith("f ")) {
String[] currentLine = line.split(" ");
String[] vertex1 = currentLine[1].split("/");
String[] vertex2 = currentLine[2].split("/");
String[] vertex3 = currentLine[3].split("/");
Vertex v0 = processVertex(vertex1, vertices, indices);
Vertex v1 = processVertex(vertex2, vertices, indices);
Vertex v2 = processVertex(vertex3, vertices, indices);
calculateTangents(v0, v1, v2, textures);
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
System.err.println("Error reading the file");
}
removeUnusedVertices(vertices);
float[] verticesArray = new float[vertices.size() * 3];
float[] texturesArray = new float[vertices.size() * 2];
float[] normalsArray = new float[vertices.size() * 3];
float[] tangentsArray = new float[vertices.size() * 3];
float furthest = convertDataToArrays(vertices, textures, normals, verticesArray, texturesArray, normalsArray, tangentsArray);
int[] indicesArray = convertIndicesListToArray(indices);
// ModelData data = new ModelData(verticesArray, texturesArray, normalsArray, tangentsArray, indicesArray, furthest);
return loader.loadToVAO(verticesArray, texturesArray, normalsArray, indicesArray);
}
private static void calculateTangents(Vertex v0, Vertex v1, Vertex v2, List<Vector2f> textures) {
Vector3f delatPos1 = Vector3f.sub(v1.getPosition(), v0.getPosition(), null);
Vector3f delatPos2 = Vector3f.sub(v2.getPosition(), v0.getPosition(), null);
Vector2f uv0 = textures.get(v0.getTextureIndex());
Vector2f uv1 = textures.get(v1.getTextureIndex());
Vector2f uv2 = textures.get(v2.getTextureIndex());
Vector2f deltaUv1 = Vector2f.sub(uv1, uv0, null);
Vector2f deltaUv2 = Vector2f.sub(uv2, uv0, null);
float r = 1.0f / (deltaUv1.x * deltaUv2.y - deltaUv1.y * deltaUv2.x);
delatPos1.scale(deltaUv2.y);
delatPos2.scale(deltaUv1.y);
Vector3f tangent = Vector3f.sub(delatPos1, delatPos2, null);
tangent.scale(r);
v0.addTangent(tangent);
v1.addTangent(tangent);
v2.addTangent(tangent);
}
private static Vertex processVertex(String[] vertex, List<Vertex> vertices, List<Integer> indices) {
int index = Integer.parseInt(vertex[0]) - 1;
Vertex currentVertex = vertices.get(index);
int textureIndex = Integer.parseInt(vertex[1]) - 1;
int normalIndex = Integer.parseInt(vertex[2]) - 1;
if (!currentVertex.isSet()) {
currentVertex.setTextureIndex(textureIndex);
currentVertex.setNormalIndex(normalIndex);
indices.add(index);
return currentVertex;
} else {
return dealWithAlreadyProcessedVertex(currentVertex, textureIndex, normalIndex, indices, vertices);
}
}
private static int[] convertIndicesListToArray(List<Integer> indices) {
int[] indicesArray = new int[indices.size()];
for (int i = 0; i < indicesArray.length; i++) {
indicesArray[i] = indices.get(i);
}
return indicesArray;
}
private static float convertDataToArrays(List<Vertex> vertices, List<Vector2f> textures, List<Vector3f> normals, float[] verticesArray, float[] texturesArray, float[] normalsArray, float[] tangentsArray) {
float furthestPoint = 0;
for (int i = 0; i < vertices.size(); i++) {
Vertex currentVertex = vertices.get(i);
if (currentVertex.getLength() > furthestPoint) {
furthestPoint = currentVertex.getLength();
}
Vector3f position = currentVertex.getPosition();
Vector2f textureCoord = textures.get(currentVertex.getTextureIndex());
Vector3f normalVector = normals.get(currentVertex.getNormalIndex());
Vector3f tangent = currentVertex.getAverageTangent();
verticesArray[i * 3] = position.x;
verticesArray[i * 3 + 1] = position.y;
verticesArray[i * 3 + 2] = position.z;
texturesArray[i * 2] = textureCoord.x;
texturesArray[i * 2 + 1] = 1 - textureCoord.y;
normalsArray[i * 3] = normalVector.x;
normalsArray[i * 3 + 1] = normalVector.y;
normalsArray[i * 3 + 2] = normalVector.z;
tangentsArray[i * 3] = tangent.x;
tangentsArray[i * 3 + 1] = tangent.y;
tangentsArray[i * 3 + 2] = tangent.z;
}
return furthestPoint;
}
private static Vertex dealWithAlreadyProcessedVertex(Vertex previousVertex, int newTextureIndex, int newNormalIndex, List<Integer> indices, List<Vertex> vertices) {
if (previousVertex.hasSameTextureAndNormal(newTextureIndex, newNormalIndex)) {
indices.add(previousVertex.getIndex());
return previousVertex;
} else {
Vertex anotherVertex = previousVertex.getDuplicateVertex();
if (anotherVertex != null) {
return dealWithAlreadyProcessedVertex(anotherVertex, newTextureIndex, newNormalIndex, indices, vertices);
} else {
Vertex duplicateVertex = new Vertex(vertices.size(), previousVertex.getPosition());
duplicateVertex.setTextureIndex(newTextureIndex);
duplicateVertex.setNormalIndex(newNormalIndex);
previousVertex.setDuplicateVertex(duplicateVertex);
vertices.add(duplicateVertex);
indices.add(duplicateVertex.getIndex());
return duplicateVertex;
}
}
}
private static void removeUnusedVertices(List<Vertex> vertices) {
for (Vertex vertex : vertices) {
vertex.averageTangents();
if (!vertex.isSet()) {
vertex.setTextureIndex(0);
vertex.setNormalIndex(0);
}
}
}
}
我很久以前就学习了这个教程。您需要做的是存储最小和最大 x、y 和 z 分量。我建议在存储顶点的情况下这样做。你可以这样做:
float minX, minY, minZ, maxX, maxY, maxZ;
try {
while(true) {
if ("v ") {
Vector3f ver = new Vector3f(Float.valueOf(curentLine[0]... );
if (ver.x < minX) minX = ver.x;
else if (ver.x > maxX) maxX = ver.x;
if (ver.y < minY) minY = ver.y;
...
}
...
}
这是获取实体的最小和最大 x、y 和 z 边界的粗略但简单的方法。希望这有帮助。
aabb 的绝对大小应该是 max - min
;所有最大分量减负。 Max - min 也称为对角线(aabb 本身就是对角线)。
这是一个使用 glm 的例子:
vec3 max(100);
vec3 min(90);
vec3 size = max - min; // vec3(10)