5

Actualmente estoy usando las clases GLTools que vienen con la 5ª edición de Superbible. Busco en la clase GLTriangleBatch y tiene el siguiente código:Objeto de búfer OpenGL Vertex, ¿puedo acceder a los datos de vértice para otros usos, como la detección de colisión?

// Create the master vertex array object 
glGenVertexArrays(1, &vertexArrayBufferObject); 
glBindVertexArray(vertexArrayBufferObject); 


// Create the buffer objects 
glGenBuffers(4, bufferObjects); 

#define VERTEX_DATA  0 
#define NORMAL_DATA  1 
#define TEXTURE_DATA 2 
#define INDEX_DATA  3 

// Copy data to video memory 
// Vertex data 
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[VERTEX_DATA]); 
glEnableVertexAttribArray(GLT_ATTRIBUTE_VERTEX); 
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*3, pVerts, GL_STATIC_DRAW); 
glVertexAttribPointer(GLT_ATTRIBUTE_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0); 

// Normal data 
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[NORMAL_DATA]); 
glEnableVertexAttribArray(GLT_ATTRIBUTE_NORMAL); 
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*3, pNorms, GL_STATIC_DRAW); 
glVertexAttribPointer(GLT_ATTRIBUTE_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, 0); 

// Texture coordinates 
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[TEXTURE_DATA]); 
glEnableVertexAttribArray(GLT_ATTRIBUTE_TEXTURE0); 
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*2, pTexCoords, GL_STATIC_DRAW); 
glVertexAttribPointer(GLT_ATTRIBUTE_TEXTURE0, 2, GL_FLOAT, GL_FALSE, 0, 0); 

// Indexes 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObjects[INDEX_DATA]); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*nNumIndexes, pIndexes, GL_STATIC_DRAW); 

// Done 
glBindVertexArray(0); 

// Free older, larger arrays 
delete [] pIndexes; 
delete [] pVerts; 
delete [] pNorms; 
delete [] pTexCoords; 

// Reasign pointers so they are marked as unused 
pIndexes = NULL; 
pVerts = NULL; 
pNorms = NULL; 
pTexCoords = NULL; 

Por lo que entiendo el código pasa a las matrices que los punteros pVerts, pNorms, pTexCoords, pIndexes y los almacena en una tabla de objeto Vertex, que esencialmente es una matriz de objetos de búfer de vértice. Estos se almacenan en la memoria en la GPU. Los punteros originales se eliminan.

Estoy interesado en acceder a las posiciones de los vértices, que se mantuvieron en la matriz apuntada pVert.

Ahora mi pregunta gira en torno a la detección de colisiones. Quiero poder acceder a una matriz de todos los vértices de mi GLTriangleBatch. ¿Puedo obtenerlos a través del vertexBufferObject más adelante utilizando algún tipo de método getter? ¿Sería mejor mantener el puntero pVerts y usar un método getter para eso? Estoy pensando en términos de rendimiento, como espero para implementar un algoritmo de detección de colisiones GJK en el futuro ...

Respuesta

7

objetos de búfer, cuando se utilizan como fuentes de datos de vértices, existir para el beneficio de la prestación . Retroceder (leer los datos) generalmente no es aconsejable desde el punto de vista del rendimiento.

La sugerencia que le da a glBufferData tiene tres patrones de acceso: DRAW, READ y COPY; estos le dicen a OpenGL cómo pretende obtener/recuperar datos del objeto de búfer directamente. Las sugerencias no regulan cómo OpenGL debería leer/escribir desde/hacia él. Estos son solo consejos; la API no impone ningún comportamiento en particular, pero violarlos puede provocar un rendimiento deficiente.

DRAW significa que va a poner datos en el búfer, pero no leerá de él. LECTURA significa que leerá datos del búfer, pero no escribirá en él (por lo general, para comentarios de transformación o búferes de píxeles). Y COPY significa que no leerá ni escribirá directamente en el búfer.

Observe que no hay ninguna pista para "leer y escribir". Solo hay "escribir", "leer" y "ninguno". Considere la posibilidad de una buena idea de escribir datos en un búfer directamente y luego comenzar a leer desde ese búfer.

De nuevo, los consejos son para que el usuario obtenga o recupere datos directamente. glBufferData, glBufferSubData, y las diversas funciones de mapeo todas escriben, mientras que glGetBufferSubData y las funciones de mapeo hacen lecturas.

En cualquier caso, no, no deberías hacer esto. Mantenga una copia de los datos de posición en la memoria del cliente si necesita usarla en el cliente.

Además, algunos controladores ignoran las sugerencias de uso por completo. En su lugar, deciden dónde ubicar el objeto del búfer en función de cómo lo usa realmente, en lugar de cómo dice que tiene la intención de usarlo. Esto será peor para usted, porque si comienza a leer desde ese búfer, el controlador puede mover los datos del búfer a la memoria que no sea tan rápida. Se puede mover de la GPU e incluso dentro del espacio de memoria del cliente.

Sin embargo, si insistes en hacer esto, hay dos maneras de leer datos de un objeto de memoria intermedia. glGetBufferSubData es el inverso de glBufferSubData. Y siempre puede asignar el búfer para leer en lugar de escribir.

+1

¡Gracias! ¡Esa respuesta fue muy útil! Mantendré el puntero pVert para acceder a los datos de vértice más tarde. – kbirk

+0

@ user785259: Mantener solo el puntero no es suficiente. De hecho, debe mantener la memoria asignada, es decir, no 'eliminar []' o 'libre (...)'. Incluso después de liberar memoria, puede tener el puntero en C, que luego no es válido. Tal vez vienes de un lenguaje basura, luego descartar un puntero implica en realidad liberar memoria, y sí, esta es la semántica cuerda. Pero esto es C++ con el que estás lidiando y todo esto es una necesidad ineludible. – datenwolf

Cuestiones relacionadas