Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Motor Común En C#

Iniciado por Haddd, 16 de Septiembre de 2004, 09:43:27 AM

« anterior - próximo »

Haddd

 Berserker, para que vaya más rápido, añade lo siguiente en Video.cs, en el constructor de CInicializar:


               presentParams.PresentationInterval = PresentInterval.Immediate;


Yo estoy ahora con el mismo problema que tienes tu, los atributos al crear el mesh. Mañana le echaré un vistazo a un libro que tengo en el trabajo donde lo explica.


BeRSeRKeR

 Lo de los atributos para definir subsets creo que ya se cómo hacerlo. El problema es que me salta una excepción.

Estoy probando con algo sencillo (utilizando el tutorial#3 del SDK de DX para C#). Lo que hago es crear un D3DXMesh y relleno el vertex & index buffer con los vértices e índices de dos quads. Lo que quiero es que esos dos quads sea cada uno un subset. Aquí está el código:

short[] indices = {
   0,1,2,    // Cara#1
   0,2,3,
   4,6,5,    // Cara#2
   4,7,6
};

mesh = new Mesh(4, 8, MeshFlags.Managed,
                           CustomVertex.PositionTextured.Format, device);

using (VertexBuffer vb = mesh.VertexBuffer)
{
   GraphicsStream data = vb.Lock(0, 0, LockFlags.None);

   // Vértices para la cara#1
   data.Write(new CustomVertex.PositionTextured(-0.2f, 2.0f, 0.0f, 0.0f, 1.0f));
   data.Write(new CustomVertex.PositionTextured(-0.2f, 0.0f, 0.0f, 1.0f, 1.0f));
   data.Write(new CustomVertex.PositionTextured(-2.0f, 0.0f, 0.0f, 1.0f, 0.0f));
   data.Write(new CustomVertex.PositionTextured(-2.0f, 2.0f, 0.0f, 0.0f, 0.0f));
   // Vértices para la cara#2
   data.Write(new CustomVertex.PositionTextured(0.2f, 2.0f, 0.0f, 0.0f, 1.0f));
   data.Write(new CustomVertex.PositionTextured(0.2f, 0.0f, 0.0f, 1.0f, 1.0f));
   data.Write(new CustomVertex.PositionTextured(2.0f, 0.0f, 0.0f, 1.0f, 0.0f));
   data.Write(new CustomVertex.PositionTextured(2.0f, 2.0f, 0.0f, 0.0f, 0.0f));

   vb.Unlock();
}

using (IndexBuffer ib = mesh.IndexBuffer)
{
   ib.SetData(indices, 0, LockFlags.None);
   ib.Unlock();
}


Una vez rellenados los buffers, intento crear los subsets con:

int[] attr = new int[] { 0, 0, 1, 1 };
GraphicsStream gs = mesh.LockAttributeBuffer(LockFlags.Discard);
gs.Write(attr);
mesh.UnlockAttributeBuffer();


Lo que hace esto es que a cada cara del mesh le asocia un attributeID de forma que en este caso, el primer quad (2 triángulos) es el subset #0 y el otro el subset #1. Pues bien, al hacer el gs.Write, me salta una exceptión de la clase InvalidOperationException que me dice:

CitarOperation is not valid due to the current state of the object.

Y ahí me he quedado parado. Estoy buscando por la red a ver si encuentro una solución pero de momento nada. A ver si tú o alguien más sabe qué es lo que pasa.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 Creo que tienes que utilizar SetAttributeTable. Yo también tengo que probarlo, pero ya tendrá que ser esta noche. El primero que lo descubra que ponga el código.  ;)  

BeRSeRKeR

 Por lo que he leído se puede hacer tanto con LockAttributeBuffer como con SetAttributeTable. A mí me gusta más LockAttributeBuffer pero peta y con SetAttributeTable probé y aunque no peta, no parece hacer nada. Será que no lo estoy haciendo bien, claro.

Y nada, si es que con LockAttributeBuffer debe ir seguro. De hecho me deja escribir el atributo para la primera cara y efectivamente me separa esa cara de las demas, es decir, crea dos subsets, pero en cuanto intento escribir en la segunda cara pues salta la excepción. He probado a leer el contenido del attribute buffer y está bien. Para el caso este de dos quads hay 4 attributeIDs (al principio todos puestos a cero), como era de esperar.

Bueno, a ver si logro solucionarlo.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

BeRSeRKeR

 Vaya tela, resulta que el attributeID que hay que meter en el buffer al hacer el LockAttributeBuffer es de tipo byte y yo estaba metiendo IDs de tipo int. Ahora parece funcionar:

byte[] attr = new byte[] { 0, 0, 1, 1 };
GraphicsStream gs = mesh.LockAttributeBuffer(LockFlags.Discard);
gs.Write(attr);
mesh.UnlockAttributeBuffer();


Eso quiere decir que el máximo número de subsets es 256...

Saludos.

EDIT: aunque no salta la excepción parece que no funciona del todo. Lo cierto es que me ha creado la attributeTable perfectamente pero cuando hago el DrawSubset no me pinta lo que debería.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 Veo que el attributeID del segundo grupo es un nº erróneo. He probado con LockAttributeArray pero parece que tampoco va bien. :(  

BeRSeRKeR

 Pues es muy raro porque estoy probando un un modelo del doom3 que está compuesto por 4 submeshes. He programado el cargador de forma que cree 4 subsets (con LockAttributeBuffer). Si después rellenar el attribute buffer vuelco su contenido en un archivo, la información que imprime es totalmente correcta aunque eso no se plasma en pantalla (sigue renderizando todo en un sólo subset). Y si justo después de rellenar el attribute buffer llamo a Optimize (que es como debería ser ya que se encarga de crear el attribute table), si luego vuelvo a volcar el attribute buffer en un archivo, me lo rellena todo de ceros, es decir, sólo existe el subset #0.

Así que nada, sólo me falta solucionar eso para dar por finalizado la carga de MD5 sin animación. No quiero ni pensar cuando tenga que empezar a meter los bones, weights y demás en las estructuras de D3DXMesh. No creo que salga con vida. :lol:

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 Bien, he estado haciendo pruebas. En el libro Introduction to Game Programming whith DirectX9, explica la forma de crear tablas de atributos y lo que haces es correcto. Al bloquear el buffer, te devuelve un array de int ( nada de byte !!)  y eso es lo que modificas. Por tanto, lo hacemos bien(salvo en el caso tuyo que usas byte para que no aslte la excepción)

Por tanto, he pensado que si funciona con byte y no con int debe ser un problema de espacio de memoria. He subido las caras, multiplicandolas por 4 y entonces al utilizar int y definir los atributos, ¡ha funcionado!

¡Pero tengo 16 caras en lugar de 4! :huh:  He intentado luego hacer un compact para ver si me las quitaba pero no ha habido forma. Por tanto, creo que es un bug de DX.  (nooo)

Seguiré investigando, a ver si descubro algo más.

Haddd

 No hay forma!! :(  Estoy convencido de que es un enorme bug. He puesto un post en las news de DX, pero por ahora nadie ha contestado. ¡Vaya forma de parar un proyecto! (grrr)  Los subset eran muy importantes para poder realizar las importaciones y demás que estoy probando. (nooo)


BeRSeRKeR

 Yo le he preguntado a Robert Dunlop, MVP de DirectX. A ver si me contesta que últimamente está perdido.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

BeRSeRKeR

 Lo que digo yo es que el método Mesh.FromFile tiene, sin más remedio, que crear los subsets porque he probado a cargar el modelo del aeroplano (airplane2.x) y efectivamente crea varios subsets (creo que 2). Pero claro, no tenemos el código de ese método para saber cómo lo hace... :D

Aunque lo raro es que si después de cargar el aeroplano, recojo el attribute buffer y lo vuelco a un archivo, me lo rellena de ceros cuando en realidad deberían ser todo ceros y unos. :lol:

Así que tal vez sí que puede que exista un bug en las runtime DirectX de .NET...

Pero bueno, habrá que esperar a que nos contesten los expertos. O eso o que a alguno se nos encienda la lucecita. :lol:

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 Bueno, para poder salir del paso voy a crear una lista dentro de la clase mesh. En realidad esa lista sustituye al subset y lo que haré será crear tantos meshes como atributos tenga el mesh. Es la única forma de salir del paso que se me ocurre hasta que se resuelve el problema.

¿Qué te parece?

Intentaré tenerlo listo mañana por la tarde, sin embargo...puede que se demore un poquito hasta el Lunes, porque este fin de semana no voy a poder hacer casi nada.

Ya he hecho una gran parte del cargador( String.Split te resuelve un montón de problemas) de los ficheros Haddd. También tengo una escena enorme que espero que pueda llegar a cargar. Si además Berserker puede terminar su código de MD5, creo que la semana que viene tendremos una buena actualización.

¡A ver si os animais, que hay mucho que hacer!  (ole)

Otra cosa, es posible que C# no sea todo lo rápido que quisiéramos, pero os aseguro que es LO MAS PRODUCTIVO QUE HE VISTO EN MI VIDA. Aunque hay cosas que expondré aquí para que me ayudeis a resolver que no sé cómo se pueden resolver sin los punteros de toda la vida.

Por cierto, resulta que para el nuevo Windows Longhorn, los drivers de vídeo(y supongo que todos los demás) tienen que estar en Managed code. ATI ya los ha convertido y NVidia ha dicho que está en ello. Sinceramente, si los drivers que están a bajo nivel TIENEN que estar en Managed, me parece que no permitirán que se hagan cosas sin Managed. Así que es posible que las DX9 sean las últimas que pueden ejecutarse en código no managed...

Lord Trancos 2

 Argh!

No me digas q el c# no tiene punteros!!!!  (grrr)  
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

BeRSeRKeR

 
Cita de: "Haddd"Bueno, para poder salir del paso voy a crear una lista dentro de la clase mesh. En realidad esa lista sustituye al subset y lo que haré será crear tantos meshes como atributos tenga el mesh. Es la única forma de salir del paso que se me ocurre hasta que se resuelve el problema.

¿Qué te parece?
Bueno, está claro que tiene que ser una salida temporal ya que para cada mes crear un vertex & index buffer y eso no es demasiado bueno. pero bueno, para salir del paso está bien.

Cita de: "Haddd"Ya he hecho una gran parte del cargador( String.Split te resuelve un montón de problemas) de los ficheros Haddd. También tengo una escena enorme que espero que pueda llegar a cargar.
Yo he creado un parser genérico (utilizando un singleton) que hace uso de  Split  para crear los tokens de una línea del archivo y enumerators para recorrer esos tokens. Es lo que he utilizado para analizar los archivos MD5 y la verdad es que funciona muy bien. A lo mejor esta noche pongo el código por si quieres utilizarlo.

Cita de: "Haddd"Si además Berserker puede terminar su código de MD5, creo que la semana que viene tendremos una buena actualización.
Sí, en cuanto hagas lo de los sub-meshes, saca el código y lo adapto al cargador de MD5. Decir que de momento sólo carga los modelos estáticos. La animación tardará algo en llegar, más que nada porque tengo que averiguar cómo rellenar la clase SkinInformation y demás.

Cita de: "Haddd"¡A ver si os animais, que hay mucho que hacer!  (ole)
Pues sí, yo la verdad es que estoy haciendo esto porque de esta forma profundizo más en C# y al mismo tiempo aporto cosas a la comunidad.

Cita de: "Haddd"Otra cosa, es posible que C# no sea todo lo rápido que quisiéramos, pero os aseguro que es LO MAS PRODUCTIVO QUE HE VISTO EN MI VIDA.
A mí me encanta. :)

Por cierto, como hemos estado parados en el tema de los subsets, me he puesto a crear una clase cámara decente. He pensado en crear una clase abstracta cámara y después de esa derivar tres clases. Una cámara tipo trackball como la de los paquetes de modelado 3D (MAX, Maya, XSI, etc), otra para manejear una cámara autónoma (por ejemplo una cámara que siga un recorrido exportado del MAX) y otra para manejar cámaras a través de dispositivos de entrada (teclado, ratón, gamepad). Para ello también tendré que programar una clase que envuelva DInput. Y lo que había pensado es, para el tipo de cámara controlada por teclado/ratón/etc, hacer que dicha clase se suscriba a eventos del tipo MouseEventHandler y KeyEventHandler cuyo ofertante podría ser un formulario o incluso un objeto que envuelva dispositivos a través de DInput. De esa forma el control de la cámara se produciría en la propia clase cámara. Por supuesto tendríamos un método a través del cual se rellenaría una estructura (a gusto del usuario) en la que se especificarían las acciones (por ejemplo moverse hacia adelante) y las teclas asociadas a dichas acciones (por ejemplo para cada acción podríamos tener una tecla primaria y una secundaria, como la mayoría de juegos hacen).

Pero bueno, eso es algo que habrá que pensar más y lo menciono para que déis vuestra opinión.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

BeRSeRKeR

 Bueno, pues he creado una pequeña aplicación de consola explicando muy básicamente cómo funciona el parser que he creado (Parser.cs). Lo podéis descargar de aquí.

También he creado una pequeña prueba de cómo estoy pensando en implementar el manejo de acciones de la cámara para ver qué os parece. He creado una clase cámara (nada que ver con lo que sería en realidad) que se suscribe al evento KeyDown del formulario de forma que si el usuario presiona una tecla con el formulario activo, éste notifica a la cámara que se ha pulsado una tecla y ésta se encargará de reaccionar apropiadamente. También es interesante que os fijéis en la propuesta que hago de cómo manejar las acciones de la cámara y cómo el usuario puede especificar las teclas para dichas acciones. Tened en cuenta que sólo es una prueba de las primeras ideas que me han venido a la cabeza de cómo implementar la cámara (y posiblemente cualquier objeto manejable por el usuario). Podéis descargar el test aquí.

Una cosa a tener en cuenta. Para que veáis la reacción de la cámara al pulsarse las teclas, saco por la consola información como la acción que se llevó a cabo y la nueva posición de la cámara. Lo que pasa es que la información no sale por consola sino que he redireccionado la salida al archivo de texto "out.txt". Así que ese es el archivo que tenéis que abrir para ver la salida del programa.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!






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.