Как получить доступ к данным модели Assimp для столкновений?
Это кажется простой задачей, но я не могу понять, как использовать импортированные данные из assimp для проверки столкновений треугольников. Я убедился, что мой алгоритм столкновения треугольников работает нормально, и буферизация вершин и индексов в openGL EBO и VBO для рисования работает отлично. Я склонен полагать, что это то, как я получаю доступ к данным из моего std::vector вершин и индексов, что неверно. В настоящее время я использую индикаторы в качестве индексов для вектора вершин.
void loadModel(std::string path) {
Assimp::Importer importer;
const aiScene * scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_JoinIdenticalVertices);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
printf_s("Assimp loading error \n%s\n", importer.GetErrorString());
return;
}
directory = path.substr(0, path.find_last_of('/'));
processNode(scene->mRootNode, scene);
}
void processNode(aiNode * node, const aiScene * scene) {
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
//processes all the nodes meshes
aiMesh * mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for (unsigned int i = 0; i < node->mNumChildren; i++) {
processNode(node->mChildren[i], scene);
}
}
Mesh processMesh(aiMesh * mesh, const aiScene * scene) {
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Texture> textures;
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
Vertex vertex;
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.position = vector;
//get other vertex information
vertices.push_back(vertex);
//for all vertices in the mesh, adds the data to a vector
}
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i];
if (face.mNumIndices == 3) {
indices.push_back(face.mIndices[0]);
indices.push_back(face.mIndices[1]);
indices.push_back(face.mIndices[2]);
//for all the indices in each face, add each indice
}
else {
printf("Odd mNumIndices \n");
//added as a just in case - but in my situation this case is never executed -> all faces are triangles
for (unsigned int j = 0; j < face.mNumIndices; j++) {
indices.push_back(face.mIndices[j]);
}
}
}
Теперь, чтобы получить доступ к этим данным, я просто перебираю все сетки модели, и для каждого индекса сетки я обращаюсь к соответствующей вершине.
bool collision(glm::mat4 worldSpaceTransform, glm::vec3 testVector) {
for (Mesh mesh : meshes) {
for (int i = 0; i < mesh.indices.size(); i += 3) {
//iterate through all faces of the mesh since each face has 3 vertices
glm::vec3 a = glm::vec3(worldSpaceTransform * glm::vec4(mesh.verticies[mesh.indices[i]].position, 1));
glm::vec3 b = glm::vec3(worldSpaceTransform * glm::vec4(mesh.verticies[mesh.indices[i + 1]].position, 1));
glm::vec3 c = glm::vec3(worldSpaceTransform * glm::vec4(mesh.verticies[mesh.indices[i + 2]].position, 1));
//use vector a, b and c (transformed to world space) for collision test with the test vector
//return true if the test vector collides with the triangle
}
}
return false;
}
Поэтому я использовал операторы print для вывода координат векторов ab и c, которые должны составлять треугольник. В одном случае я не смог найти эти точные векторы в необработанном файле.obj модели, я нашел их координаты x, y и z, но не все вместе в одном векторе (да, когда я проверял это, я печатал локальные пространственные координаты). В другом случае три вектора, которые должны образовать треугольник, в итоге образовали линию (два из трех векторов имели одинаковые координаты). Кроме того, я знаю, что тестирование вектора со всеми примитивами модели неэффективно, но сейчас я сосредотачиваюсь на том, чтобы что-то работало, прежде чем смотреть на оптимизацию. Многие из моделей слишком сложны для AABB, поэтому это "лучшее" решение, которое я придумал. Итак, я не уверен, что я делаю здесь неправильно, любые советы очень ценятся!
1 ответ
Формат obj просто сохраняет каждую вершину один раз и ссылается на нее на гранях. Таким образом, Assimp сгенерирует из этих позиций вершины для самого рендеринга. И это причина того, что вы не можете найти исходную информацию из импортированного вами obj-файла в форме, в которой obj хранит их в формате. Obj оптимизирован по размеру, промежуточный формат, используемый assimp, оптимизирован для рендеринга.
Хорошая стратегия хранения информации о столкновениях сильно зависит от вашей модели. Для меня это сработало, чтобы сгенерировать локальную ограничивающую рамку для всей модели и дочерние блоки для каждой сетки, хранящейся в графе узлов. ТАК можно использовать следующий подход:
- Сверьтесь с рамкой, ограничивающей сцену, сталкивается ли ваш треугольник с этой рамкой
- Если это так:
- Сверьтесь со всеми ограничивающими прямоугольниками узла
- Если вы можете обнаружить столкновение: проверьте все треугольники этого узла в сетках, чтобы найти правильный