Я пытаюсь создать AABB на 3D-моделях в OpenGL. Когда я использую 3D box.obj, где все вершины 1.0, у меня нет проблем с обнаружением столкновения между моделями. Однако возникает проблема, когда я использую более сложные 3D-модели с разными значениями для вершин. Сложные модели меньше, чем box.obj, и имеют значения вершин, такие как .18 и .06, поэтому ограничивающие рамки на них настолько велики, что мой движок обнаруживает столкновения между объектами, когда они не касаются. Решением этой проблемы является отслеживание максимального / минимального значения для каждой оси x, y и z при чтении модели в мою игру, но у меня возникают проблемы при этом.
Ниже мой код для чтения в моделях:
bool Model::buffer(string objFile)
{
vector<vec3> locs;
vector<vec2> uvs;
vector<vec3> norms;
vector<VertInd> vertInds;
// Open file for reading
ifstream inFile;
inFile.open(objFile);
string line;
if (inFile.is_open())
{
// Enter a loop that reads every line iteration from file until file is empty
while (getline(inFile, line))
{
istringstream ss(line);
string lineLabel;
// Read a string (the line label) from the line
ss >> lineLabel;
if (lineLabel == "v") // Vertices
{
float a, b, c;
ss >> a >> b >> c;
locs.push_back(vec3(a, b, c));
}
else if (lineLabel == "vt") // Texture Coordinates
{
float a, b;
ss >> a >> b;
uvs.push_back(vec2(a, b));
}
else if (lineLabel == "vn") // Vertex Normals
{
float a, b, c;
ss >> a >> b >> c;
norms.push_back(vec3(a, b, c));
}
// Get indices
else if (lineLabel == "f")
{
// do three times
for (int i = 0; i < 3; i++)
{
unsigned int a, b, c;
char s1, s2;
// Read int, then char slash
ss >> a >> s1 >> b >> s2 >> c;
// Decrement each of the ints by 1
vertInds.push_back(VertInd{ a - 1, b - 1, c - 1 });
}
}
/* GLfloat min_x, max_x, min_y, max_y, min_z, max_z;
min_x = max_x = locs[0].x;
min_y = max_y = locs[0].y;
min_z = max_z = locs[0].z;
for (int i = 0; i < locs.size(); i++)
{
if (locs[i].x < min_x) min_x = locs[i].x;
if (locs[i].x > max_x) max_x = locs[i].x;
if (locs[i].y < min_y) min_y = locs[i].y;
if (locs[i].y > max_y) max_y = locs[i].y;
if (locs[i].z < min_z) min_z = locs[i].z;
if (locs[i].z > max_z) max_z = locs[i].z;
}
vec3 size = vec3(max_x - min_x, max_y - min_y, max_z - min_z);
vec3 center = vec3((min_x + max_x) / 2, (min_y + max_y) / 2, (min_z + max_z) / 2);
mat4 transform = translate(mat4(1), center) * scale(mat4(1), size);
mat4 m = camera.camMat * transform;
glUniformMatrix4fv(2, 1, GL_FALSE, &m[0][0]); */
}
// Close the file
inFile.close();
}
vertCount = vertInds.size();
GLuint vertBuf;
vector<Vertex> vertBufData(vertCount);
for (unsigned int i = 0; i < vertCount; i++)
vertBufData[i] = { locs[vertInds[i].locInd], uvs[vertInds[i].uvInd], norms[vertInds[i].normInd] };
// Vertex array
glGenVertexArrays(1, &vertArr);
glGenBuffers(1, &vertBuf);
// Buffer data
glBindVertexArray(vertArr);
glBindBuffer(GL_ARRAY_BUFFER, vertBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) *vertCount, &vertBufData[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)sizeof(vec3)); // (void*)sizeof(VertInd));
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(vec3) + sizeof(vec2)));
glBindVertexArray(0);
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
return true;
}
Закомментированный раздел / ** / — это та часть, которую я недавно добавил в попытке получить минимальные / максимальные значения верт и центрировать мою модель, но теперь сцена даже не загружается. Любая помощь будет принята с благодарностью. Спасибо.
Смотрите пример использования Вот:
// return the min/max points of pts
template< typename Vec >
pair< Vec, Vec > GetExtents( const Vec* pts, size_t stride, size_t count )
{
unsigned char* base = (unsigned char*)pts;
Vec pmin( *(Vec*)base );
Vec pmax( *(Vec*)base );
for( size_t i = 0; i < count; ++i, base += stride )
{
const Vec& pt = *(Vec*)base;
pmin = glm::min( pmin, pt );
pmax = glm::max( pmax, pt );
}
return make_pair( pmin, pmax );
}
// centers geometry around the origin
// and scales it to fit in a size^3 box
template< typename Vec >
void CenterAndScale( Vec* pts, size_t stride, size_t count, const typename Vec::value_type& size )
{
typedef typename Vec::value_type Scalar;
// get min/max extents
pair< Vec, Vec > exts = GetExtents( pts, stride, count );
// center and scale
const Vec center = ( exts.first * Scalar( 0.5 ) ) + ( exts.second * Scalar( 0.5f ) );
const Scalar factor = size / glm::compMax( exts.second - exts.first );
unsigned char* base = (unsigned char*)pts;
for( size_t i = 0; i < count; ++i, base += stride )
{
Vec& pt = *(Vec*)base;
pt = ( ( pt - center ) * factor );
}
}
Других решений пока нет …