Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Leer Vertex Buffers

Iniciado por Findeton, 16 de Noviembre de 2002, 10:31:03 PM

« anterior - próximo »

Findeton

                                Hola de nuevo. Me gustaría saber cómo poder obtener y leer el buffer de vértices una vez ha empezado el programa, querría saber qué falla aquí:

VERTCUBO* CCubo::dar(void){

   VOID* pVertices;

VERTCUBO cvVertices[18];

VERTCUBO* f;

   

// Siempre que queramos añadir vértices a nuestro buffer, debemos bloquear el

// buffer.

if(FAILED(BufferVert->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_READONLY )))

   {

       return FALSE;

   }



   // copiamos a la zona de memoria a la que apunta nuestro buffer

//de vértices a una variable.

   memcpy(cvVertices , pVertices, sizeof(pVertices));



   // ¡Nunca olvidar desbloquear el buffer cuando se halla terminado de rellenarlo!

   BufferVert->Unlock();

   f= cvVertices;

return f;

}



Para más datos, lo que quiero hacer es poder luego utilizar los datos de 'VERTCUBO* f;'  como muestro abajo, junto con la definición de la estructura VERTCUBO, tened en cuenta que hay 18 vértices en el buffer:



struct VERTCUBO

 {

  public:

  FLOAT x, y, z;  

  DWORD color;

  FLOAT tu, tv;

 };



//Y quiero utilizar f así:



VERTCUBO* f=Cubo2->dar();

  float aaa=f[0].x;
                               

Juan Mellado

Hola Findeton.

El tercer parámetro del memcpy() debería ser sizeof(cvVertices). Siempre y cuando sepas que siempre vas a tener 18 vértices en el buffer.

Por otra parte, no creo que te funcione. La variable cvVertices que devuelves es local. Una vez finalizada la función se pierde su contenido. No puedes pretender utilizar su contenido fuera de la misma. Mejor pasa a la función un puntero indicando el array donde quieres que copie los vértices (y el tamaño del array, aunque esto es opcional).

O un puntero a un puntero. Y haces tus propias funciones de reserva y liberación de memoria. No sé, hay varias posibilidades.

Espero haberte ayudado.
Saludos a todos.

Findeton

                                Muchas gracias, todabía no he conseguido que me vaya, sería algo tal que así?:



VERTCUBO* CCubo::dar(VERTCUBO* pcvVertices){ //paso a la

//funcion un puntero al array donde quiero copiar los vértices

   VOID* pVertices;    

  // Siempre que queramos añadir vértices a nuestro buffer, debemos bloquear el

  // buffer.

  if(FAILED(BufferVert->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_READONLY )))

   {

       return FALSE;

   }



   // copiamos a la zona de memoria a la que apunta nuestro buffer

//de vértices a una variable.



   memcpy(*pcvVertices , *pVertices, sizeof(*pcvVertices)); /*se copia  contenido de pVertices a la matriz indexada en pcvVertices*/



   // ¡Nunca olvidar desbloquear el buffer cuando se halla terminado de rellenarlo!

   BufferVert->Unlock();

 

  return pcvVertices;

}
                               

Findeton

                                Caya, me parece que todo está mal. Según me han dicho, el Vertex Buffer sólo almacena los vértices sin transformar, es decir, sin aplicar ninguna rotación o traslación. Yo lo que quíero es acceder a los vértices una vez son transformados cada frame, para detectar si colisionan unos triángulos con otros con una rutina que tengo. Alguien sabe si es posible hacer eso en directx?                                

Findeton

                                Caya=Vaya...                                

Juan Mellado

                                Lo de conseguir los vértices transformados con DirectX, creo que era con ProcessVertices(). Aunque mejor que te responda alguien que haya trabajado con ello. Yo no lo he hecho.

Si lo consigues, aún deberas acceder al buffer, por lo que seguirás necesitando tu función. El problema lo sigues teniendo con el memcpy().

El primer parámetro debe ser pcvVertices, y el segundo pVertices. Ambos son, directamente, los punteros a los buffers con los que se quiere trabajar (aquí hemos retrocedido un poco respecto a la primera versión). ¿Te compila sin warnings?

Respecto al tercer parámetro del memcpy(), en la primera versión estabas indicando el tamaño del puntero, y en esta segunda versión el tamaño de un sólo vértice (vamos acercándonos). Lo que debes indicar es el tamaño de los 18 vértices: 18 * sizeof(* pcvVertices), que es equivalente a 18 * sizeof(VERTCUBO). Aunque sigue existiendo la posibilidad de pasar el tamaño del buffer como parámetro, o el número de vértices. Depende de cómo lo quieras enfocar.

Otra cosa, has mezclado dos tipos distintos en el retorno de la función. Si falla el Lock retornas FALSE, y en caso contrario el propio puntero que te pasan como parámetro. Lo mejor (bueno, lo mejor no, sólo otra posibilidad) es que el tipo de retorno sea BOOL (o HRESULT), y retornes TRUE o FALSE en función de si pudo realizar con éxito o no la copia.

Te sugiero un repaso al tema de punteros y sizeof(). Espero que este comentario no te moleste. :I

Y para cualquier otra duda ya sabes donde estamos.
Saludos, y suerte.                                

Findeton

                                Gracias de nuevo por contestar.

En cuanto al repaso del tema de punteros y sizeof(), no me molesta en absoluto, yo soy novato en directx y hace medio año que empecé con el C++, aunque antes ya había trabajado con el Visual Basic... pero no es lo mismo.

Ahora sobre el código, es verdad, se me ha ido la olla y he puesto mal los 2 primeros parámetros de memcpy, y el último parámetro... gracias por recordármelo. Sin embargo aquí está la función, de nuevo compila bien pero hay algo que falla...

VERTCUBO* CCubo::dar(VERTCUBO* pcvVertices){ //paso a la

//funcion un puntero al array donde quiero copiar los vértices

   VOID* pVertices;      



  // Siempre que queramos añadir vértices a nuestro buffer, debemos bloquear el

  // buffer.

  if(FAILED(BufferVert->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_READONLY )))

   {

       return FALSE;

   }



   // copiamos a la zona de memoria a la que apunta nuestro buffer

//de vértices a una variable.



   memcpy(pcvVertices , pVertices, 18 * sizeof(VERTCUBO)); /*se copia  contenido de pVertices a la matriz indexada en pcvVertices*/



   // ¡Nunca olvidar desbloquear el buffer cuando se halla terminado de rellenarlo!

   BufferVert->Unlock();

   

  return pcvVertices;

}



Por si te sirve de algo, la función 'dar' la utilizo en la función 'colisiona', que aquí abajo describo, junto con el código que llama a estas dos funciones:

bool CCubo::colisiona(VERTCUBO* cvVertices2){



VOID* pVertices;

VERTCUBO cvVertices[18];

VERTCUBO* pcvVertices=cvVertices;

 pcvVertices = CCubo::dar(cvVertices);

   VERTCUBO t1[3],t2[3];

   for  (int x=0;x<16;x++){

 for(int y=0;y<16;y++){

  t1[0]=cvVertices[x];

  t1[1]=cvVertices[x+1];

  t1[2]=cvVertices[x+2];



  t2[0]=cvVertices2[y];

  t2[1]=cvVertices2[y+1];

  t2[2]=cvVertices2[y+2];

  if(itt(t1,t2)==1)                   //itt es la  función que devuelve 1 si interseccionan

   return 1;

 }

}

return false;

}



...

void GameLoop(){

...

               VERTCUBO* pcvVertices;

VERTCUBO cvVertices[18];

pcvVertices=cvVertices;

if(Cubo1->colisiona( Cubo2->dar(pcvVertices) ) )

 cout << "COLISIONA!!n" << endl;

}
                               

Juan Mellado

Bueno, pues te respondo yo mismo otra vez.

La función ya debería irte bien. Aún queda lo del tipo de retorno.

Dices que falla algo, pero no el qué. Matiza, para que podamos ayudarte. ¿No te copia los vértices al array?, ¿Te falla el Lock?, ...

Una depuración paso a paso te podría ayudar a entender como se cargan las variables y como varian su valor con la ejecución de cada sentencia.

Por cierto, desde el primer post tengo una duda: ¿18 vértices para un cubo? Entendería que fueran 8, e incluso 16 si utilizas las caras interiores. Pero, ¿18?. No sé, seguro que tiene una razón de ser, ¿no?. De hecho en colisiona() utilizas sólo 16. ¿colisiona() te funciona?, es un poco ... rarita.

Depura paso a paso, y mira en cada paso el valor de las variables, para entender que está haciendo tu código.

Saludos

_Grey

                                que yo sepa no se pueden leer los vertices transformados........

Ahora, si el error es que no puedes leer el VertexBuffer pude ser que lo crearas con D3DUSAGE_WRITEONLY!? o que el formato del tipo de vertice no sea VERTCUBO!?

Pero seguro que es lo primero que puse, a que si..... :ojo:                                

Findeton

                                Perdonad mi tardanza. el Vertex Buffer no lo he creado con D3DUSAGE_WRITEONLY, en el parámetro dnd podría haberlo puesto, he puesto 0. El formato de los vértices es VERTCUBO. Tengo 18 vértices pq dibujo todo con triangle strips, siendo los 4 primeros (0 a 3) los pertenecientes a la parte superior del cubo, del 4 al 13 las caras laterales y del 14 al 17 la cara inferior.

Y si, algo falla, pq yo sé de antemano lo que debe de dar, puesto que tengo en una variable una copia del buffer de vértices, pero al comparar el contenido de VERTCUBO* pcvVertices con lo que tendría que ser... no es lo mismo, en pcvVertices me salen números extraños y grandes(algo así como '2364849e-38'. Ahora me diréis que si tengo una copia del buffer de vértices, para qué quiero leerla...? pues pq necesito saber cómo acceder al buffer de vértices.                                

Juan Mellado

Sólo por curiosidad he pegado tu código en el compilador (quitando algunas cosas, claro) y... me funciona.



struct VERTCUBO{

    FLOAT x, y, z;          

    DWORD color;

    FLOAT tu, tv;

   };



LPDIRECT3DVERTEXBUFFER8 BufferVert = NULL;



BOOL dar(VERTCUBO * pcvVertices)

{

   VOID * pVertices = NULL;

   if( FAILED(BufferVert->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_READONLY) ) ){

        return(FALSE);

       }

   memcpy(pcvVertices, pVertices, 18 * sizeof(* pcvVertices) );



   BufferVert->Unlock();

   

   return(TRUE);

}



//... Creación e inicialización del vertex buffer



   g_pd3dDevice->CreateVertexBuffer(18 * sizeof(VERTCUBO), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, D3DPOOL_DEFAULT, &BufferVert);



   VERTCUBO * pcvVertices;

   if( FAILED(BufferVert->Lock(0, 0, (BYTE**)&pcvVertices, 0) ) ){

        return(FALSE);

       }



   pcvVertices[0].x = 1; //Algo sencillo

   pcvVertices[0].y = 2;

   pcvVertices[0].z = 3;



   BufferVert->Unlock();



// ... Prueba de copia



   VERTCUBO cvVertices[18];



   dar(cvVertices);





Después de llamar a dar(), cvVertices está inicializado con el contenido del BufferVert.

Los números grandes que ves seguramente se corresponden con un área de memoria que no está inicializada. Por defecto los compiladores inicializan la memoria con un valor determinado, como 0xCC, un código que provoca una excepción si se ejecuta. Sirve para controlar que no se machaque código con variables. Las variables de tipo numérico inicializadas así aparecen con un valor muy grande, como el que ves. Esto, ... me estoy yendo del tema.

Pues no sé, ejecutando paso a paso, justo antes del memcpy() deberías ver el contenido de la memoria a la que apunta pvcVertices sin inicializar y, una vez ejecutado memcpy(), ver que se ha rellenado con los valores de los vértices.

Ya nos contarás.
Saludos

Findeton

                                Ya me va!!  :D Gracias a todos por ayudarme, la pena es eso de que no pueda leer los vértices del objeto una vez están transformados. Me parece que tendré que utilizar un Oriented Bounding Box en el cubo e ir anotando el ángulo de cada eje y la traslación del objeto cada vez que quiera saber si los dos cubos colisionan. Sin embargo, leer el buffer de vértices me será muy útil a la hora de utilizar los octrees ( o los quadtrees en el terreno/suelo), y tb cuando quiera calcular la intersección entre un terreno y un modelo. Realmente muchas gracias.

Ya y por si acaso le sirve a alguien, pongo el código que he utilizado para comprobar si es correcto, además de poner en modo Debug, con Run to Cursor... :



BOOL dar(VERTCUBO * pcvVertices)

{

   VOID * pVertices = NULL;

   if( FAILED(BufferVert->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_READONLY) ) ){

        return(FALSE);

       }

   memcpy(pcvVertices, pVertices, 18 * sizeof(* pcvVertices) );



   BufferVert->Unlock();

   

   return(TRUE);

}







bool vertex_buffer(LPDIRECT3DDEVICE8 g_pD3DDev){



g_pD3DDev->CreateVertexBuffer(18 * sizeof(VERTCUBO), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, D3DPOOL_DEFAULT, &BufferVert);



   VERTCUBO * pcvVertices;

   if( FAILED(BufferVert->Lock(0, 0, (BYTE**)&pcvVertices, 0) ) ){

 MessageBox(g_hWnd, "No se pudo crear el Buffer de Vértices", "Error", MB_OK|MB_ICONEXCLAMATION);

 

        return(FALSE);

       }



   pcvVertices[0].x = 1; //Algo sencillo

   pcvVertices[0].y = 2;

   pcvVertices[0].z = 3;



   BufferVert->Unlock();

   VERTCUBO cvVertices[18];



float aaa=1;



   if(dar(cvVertices)){

 float bbb=cvVertices[0].x;

 if(aaa==bbb)



 return true;}

MessageBox(g_hWnd, "No se pudo LEER el buffer de vértices", "Error", MB_OK|MB_ICONEXCLAMATION);

 

return false;

}
                               






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.