Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Menu

Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menu

Mensajes - Kriller

#1
Programación gráfica / Mapear Objetos Segun Color
09 de Marzo de 2004, 06:52:48 PM
 ¿No estás matando moscas a cañonazos?

Yo haría lo siguiente: suponiendo que cada widget tuyo tiene una textura asociada, simplemente miraría el color del píxel que ha sido pinchado dentro de la textura (si la textura tiene canal alfa y está siendo usado, miraría ahí). Si es cero, es un hueco y por tanto no ha sido pinchado. Así te evitas renderizar los widgets dos veces y trastear con el backbuffer.

Ésto sólo es válido si tus widgets están hechos a base de texturas. Si los dibujas "a mano" (con líneas o algo así) entonces seguramente habría que hacer lo que dices tú.
#2
 Tengo un vago recuerdo de haber leído algo sobre el tema en tiempos pre-3D pero no le presté mucha atención en su día. A ver si con lo que me acuerdo y algo de imaginación:

Para cada scanline de un sprite, se guarda un array de coordenadas X donde empieza/termina el sprite. No basta con dos coordenadas porque hay que tener en cuenta que el sprite puede ser cóncavo (la letra C por ejemplo) y/o puede tener "huecos" interiores (un donut). Eso sí, siempre habrá un número par. Al final, el array correspondiente al scanline de coordenada Y se interpreta así:

* los tramos definidos por (array[0], Y)-(array[1]), (array[2], Y)-(array[3]), (array[4], Y)-(array[5]), etc. están ocupados por el sprite.

* los tramos definidos por (array[1], Y)-(array[2]), (array[3], Y)-(array[4]), (array[5], Y)-(array[6]), etc. son huecos.

Entonces, para comprobar colisión entre dos sprites, primero se hace por rectángulos y se determina el subrectángulo que se solapa. Finalmente se emparejan los scanlines de un sprite y otro que estén a la misma altura y, para cada pareja, se recorren los tramos de ambos. Si un tramo ocupado de un sprite se solapa con otro tramo ocupado del otro sprite, entonces hay colisión.

Nota 1: Casi todo esto acabo de sacármelo de la manga, o sea que puede que esté incompleto o incluso que  sea incorrecto.

Nota 2: Loover, me temo que esto no funcionaría para sprites que pueden estar rotados. Igual se puede adaptar pero se complicaría bastante.

Un saludo y suerte.
#3
Programación gráfica / Sky Dome. Un Shader Interesante
12 de Enero de 2004, 11:26:25 AM
 De joderme nada, acabo de hacer el pedido en PC Box de Madrid que está a 140€  (uoh) . La verdad, estaba buscando una tarjeta de marca pero por 90€ menos me da igual que sea Perico de los Palotes, S.A.

Gracias por el aviso.  (ole)  
#4
Programación gráfica / Sky Dome. Un Shader Interesante
12 de Enero de 2004, 01:44:33 AM
 Tengo encargada en Alternate una Radeon 9600 XT pero me sale por un pico, ¡230€! ¿Merece la pena la XT frente a la Pro? Empiezo a pensar que debería cambiar mi pedido. Parece ser que la XT es igualita a la Pro con algún que otro MHz de más.

P.D.: ¿Alguien sabe cómo hemos empezado a hablar de sky domes y hemos podido acabar hablando de pedidos en Alternate?  :blink:
#5
Programación gráfica / Abstraer Contexto De Renderizado
11 de Enero de 2004, 01:29:33 PM
 Vaya, el código ha salido descolocado. ¿Cómo hacéis para que salga con colorines y que todas las letras tengan la misma anchura?
#6
Programación gráfica / Abstraer Contexto De Renderizado
11 de Enero de 2004, 01:27:52 PM
 Pues ahí va mi clase base CGEGraphicEngine en su estado actual, clase principal del módulo de render (después del código lo comento un poco):


class CGEGraphicEngine
{
public:

 virtual                   ~CGEGraphicEngine         ()  { End(); }

 virtual void              End                       ();
 bool                      IsOk                      () const  { return m_bOk; }

 CGEFactory               *GetFactory                () const  { return m_pFactory; }
 CGEVertexBufferManager   *GetVertexBufferManager    ()  { return &m_VertexBufferManager; }
//  CGEIndexBufferManager    *GetIndexBufferManager     ()  { return &m_IndexBufferManager; }
 CGETextureManager        *GetTextureManager         ()  { return &m_TextureManager; }

 bool                      SetVideoMode              (const TGEVideoMode &VideoMode);
 TGEVideoMode              GetVideoMode              () const  { return m_VideoMode; }

 inline void               SetWorldTransform         (const TMatrix4 &mWorldTransform);
 inline CGECamera         *GetCamera                 ()  { return m_pCamera; }


 //
 // Render configuration
 //

 inline void               SetLightingEnabled        (bool bEnabled);
 inline void               SetTexture                (unsigned uTextureStage, CGETexture *pTexture);
 inline void               SetTransparencyType       (TGETransparencyType TransparencyType);
 inline void               SetBackfaceCullingType    (TGECullingType BackfaceCullingType);
 inline void               SetDepthBufferType        (TGEDepthBufferType DepthBufferType);
 inline void               SetDepthBufferWriteEnabled(bool bEnabled);
 inline void               SetTextureMinFilter       (unsigned uTextureStage, TGETextureFilterType FilterType);
 inline void               SetTextureMagFilter       (unsigned uTextureStage, TGETextureFilterType FilterType);


 //
 // Drawing operations
 //

 virtual void              BeginDraw                 () = 0;
 virtual void              EndDraw                   () = 0;

 virtual void              DrawMesh                  (const CGEMeshData *pMeshData) = 0;


protected:

 // Constructor and Init() are protected to avoid instantiating this class
                           CGEGraphicEngine          ()  { m_bOk = false; }
 bool                      Init                      (const TGEWindow &Window, const TGEVideoMode &VideoMode);
 void                      PostInit                  ();

 void                      ResetVars                 ();
 void                      FreeVars                  ();

 inline void               SetViewTransform          (const TMatrix4 &mViewTransform);
 inline void               SetProjectionTransform    (const TMatrix4 &mProjectionTransform);


 //
 // Pure virtual methods that must be implemented by concrete graphics engines
 //

 virtual bool              SetVideoMode_Impl           (const TGEVideoMode &VideoMode) = 0;
 virtual void              SetWorldTransform_Impl      (const TMatrix4 &mWorldTransform) = 0;
 virtual void              SetViewTransform_Impl       (const TMatrix4 &mViewTransform) = 0;
 virtual void              SetProjectionTransform_Impl (const TMatrix4 &mProjectionTransform) = 0;
 virtual void              SetLightingEnabled_Impl     (bool bEnabled) = 0;
 virtual void              SetTexture_Impl             (unsigned uTextureStage, CGETexture *pTexture) = 0;
 virtual void              SetTransparencyType_Impl    (TGETransparencyType TransparencyType) = 0;
 virtual void              SetBackfaceCullingType_Impl (TGECullingType BackfaceCullingType) = 0;
 virtual void              SetDepthBufferType_Impl     (TGEDepthBufferType DepthBufferType) = 0;
 virtual void              SetDepthBufferWriteEnabled_Impl (bool bEnabled) = 0;
 virtual void              SetTextureMinFilter_Impl    (unsigned uTextureStage, TGETextureFilterType FilterType) = 0;
 virtual void              SetTextureMagFilter_Impl    (unsigned uTextureStage, TGETextureFilterType FilterType) = 0;

//
// Variables miembro eliminadas para que no ocupe tanto
//


private:


};


Como veis, cada operación básica que debe hacer un renderer aparece aquí como método virtual puro. Además tengo una clase CGEFactory que también implementa cada renderer que sigue el esquema del patrón de diseño Abstract Factory y cuya misión es crear y destruir los objetos que son dependientes del renderer (vertex buffers, index buffers y texturas por ahora).

Por cierto, algo que se me ocurrió y que me ha simplificado mucho la vida. En vez de obligar al renderer a que sea capaz de dibujar muchos tipos de objetos visuales (malla, texto2D, quad, partícula, etc., etc.), el renderer sólo entiende de objetos CGEMeshData, que no son más que una encapsulación de un vertex buffer y opcionalmente un index buffer, y que acepta cualquier tipo de vértice y de primitiva. En la capa de mayor nivel de mi motor es donde tengo toda una jerarquía de objetos visuales, y la mayoría de ellos encapsulan un CGEMeshData imponiéndole cada uno sus propias restricciones. Con esto, consigo simplificar un montón tanto la capa del renderer como la capa superior.

Saludos.

P.D.: Lo siento por el post tan largo.
#7
Programación gráfica / Sky Dome. Un Shader Interesante
11 de Enero de 2004, 11:33:21 AM
 Retomando el tema, ¿realmente merece la pena hacerlo con un shader? Se podría hacer como dice fiero pero con una ligera modificación. Se podría desactivar la escritura en Z-buffer pero dejar los tests activados, y entonces dibujar el sky dome al final del todo. De esta manera se aprovecha la optimización que dices tú, Haddd, que si no se ve nada del cielo el Z-buffer lo descarta rápidamente (por eso lo de dejar los tests activados). Además tenemos la escritura en Z-buffer desactivada, por lo tanto una optimización más.

Vuelvo a sacar el tema porque en breves voy a implementar esto en mi motor y no quiero pelearme todavía con los shaders, aunque si me convencéis de que merece la pena pues habrá que hacerlo...  ;)

Saludos.
#8
General Programadores / Std::vector Y Punteros
11 de Enero de 2004, 02:08:00 AM
 ethernet, sí he visto el ejemplo y por supuesto que petaría, por eso digo que hay que anderse con mucho ojo. Un caso real en el que me planteé usar contador de referencias: me planteaba para mi motor que diera la posibilidad al usuario de tener varios objetos CCamara y poder pasarle al motor una u otra en cada momento. Si el usuario se cepillaba el objeto CCamara que estuviera usando el motor y luego seguía usando el motor entonces explotaría; con un contador de referencias se evitaría ese problema. Pero al final decidí emplear otra filosofía  ;) .

Como dice seryu, las macros no muerden, aunque yo las utilizo en muy determinadas circunstancias. De hecho hay casos en los que no hay otra manera de hacer algo. Por ejemplo, para lo que yo digo: sobrecargando el delete no puedes poner a NULL el puntero que te han pasado, tendrías que hacerte una función tuya equivalente a la que le pasas un doble puntero.

A ver, no digo que no haya que usar contadores de referencias, sólo digo que la mayor parte del tiempo puedes vivir sin ello y que por eso no me gusta como filosofía permanente, sólo hay que emplearlas en casos concretos en los que realmente te reporten un beneficio.
#9
Programación gráfica / Problema Con Quadtree/octree
11 de Enero de 2004, 01:24:20 AM
 Miki, no sé si te entiendo, es que igual me he explicado yo mal. El caso es que tal como te digo que lo hagas NO haces cuarenta mil swaps de textura, sólo haces tantos swaps como texturas renderices en un frame (o sea, el mínimo que puedes hacer).

Lo explico con un poco de pseudocódigo. Suponiendo que tienes n texturas:

1) Determinar los nodos del quadtree visibles
2) Para TexturaActual=1 hasta n hacer
3)   Cambiar a la textura TexturaActual
4)   Para NodoActual=1 hasta NumNodosVisibles hacer
5)     Determinar polígonos de NodoActual que utilizan la textura TexturaActual
6)     Renderizar esos polígonos
7)   Fin para
8) Fin para

El paso 5) sería muy rápido porque en cada nodo ya tienes separados en diferentes listas los polígonos según utilicen una textura u otra. Y por supuesto, antes de hacer nada en cada iteración del bucle exterior (o sea, antes de cambiar de textura) habría que comprobar si TexturaActual es utilizada en alguno de los nodos visibles.

Espero haberme explicado y que te resuelva el problema...
#10
Programación gráfica / Problema Con Quadtree/octree
10 de Enero de 2004, 01:15:40 PM
 Pues por ejemplo puedes tener la lista de cada nodo del quadtree ordenada por textura, o incluso mejor que cada nodo tenga una lista distinta para cada textura (o sea, cada lista contiene los polígonos que utilizan una textura determinada). Así, como tú dices, suponiendo que tienes n texturas, cuando vayas a renderizar recorres n veces todos los nodos visibles; en cada pasada preguntas a cada nodo por los polígonos con la textura i=1..n y los renderizas.
#11
General Programadores / Std::vector Y Punteros
10 de Enero de 2004, 11:43:59 AM
 Eso es verdad, no son comparables. Ahora bien, que lo de poner un puntero a NULL después de liberarlo es cutre no estoy en absoluto de acuerdo, es todo lo contrario. De esa manera siempre sabes con total certeza que si un puntero es distinto de NULL, entonces apunta a algo válido.

Lo del contador de referencias creo que no es necesario en la mayoría de los casos y que con el otro método es completamente suficiente (vamos, a mí me va muy bien). Eso sí, te obliga a ser muy disciplinado y riguroso con cuándo y dónde reservas/liberas pero, ¿no hay que serlo también con el resto?  :P

Saludos.
#12
 Eso ya depende totalmente de cada malla. Por ejemplo, si levantas la cara de arriba (como si fuera la tapa del cubo) te aparecen otros dos vértices base, es decir 10, cuando sigues teniendo 36 vértices reales y 12 triángulos.

Lo que puedes hacer es recorrer a lo bruto todos los vértices de la malla (los 36 en el cubo) e ir creando grupos de vértices. Todos los vértices que compartan una misma posición estarán en el mismo grupo. Al final, el número de grupos es el número de vértices base que buscas.
#13
General Programadores / Std::vector Y Punteros
10 de Enero de 2004, 02:07:19 AM
 Otra forma de evitar hacer un delete de un puntero ya liberado es poniendo siempre el puntero a NULL justo después de hacer el delete (con una macro por ejemplo). El delete no hace nada cuando se le pasa NULL así que el segundo delete no tendría ningún efecto.

Personalmente esto me gusta más que el contador de referencias.
#14
 Precisamente, si tienes un TRIANGLELIST tienes que multiplicar por 3 el número de triángulos para obtener el número de vértices. Si no es eso lo que quieres saber intenta explicarlo mejor.

Saludos.
#15
Programación gráfica / Texturizar Polígonos En 3d
16 de Diciembre de 2003, 07:58:07 PM
 Hola. El problema que tienes que resolver es más general que poner textura a un triángulo, te sirve también para colorearlo, iluminarlo, etc. La idea es recorrer cada "scanline" (= línea horizontal) del triángulo interpolando para cada píxel algún valor que te interese; en tu caso, las coordenadas de la textura u,v. Tienes que interpolar porque sólo conoces los valores inicial y final de u,v pero no los intermedios (es una interpolación lineal, muy sencilla). Por tanto para cada píxel obtienes un par u,v determinado, que simplemente escalándolos por la anchura y la altura respectivamente de tu textura obtienes qué punto de la textura corresponde al píxel del triángulo.

A este problema se le suele llamar "triangle rasterization", "polygon rasterization" o algo similar. Si buscas en la red seguramente encuentres algo. Por cierto, en el libro "Tricks of the 3D game programming gurus" de André LaMothe viene explicado.