Ver la versión completa : Triangulos rellenos 2d
Hola, buenas.
Estoy a medio haciendo un juego de navecitas 2D, ya tengo algo de engine, y he pensado en utilizar primitivas 2d para los enemigos (los prites siempre me quedan feos); lo que passa es que no me veo muy capaz de dibujar un trinagulo de manera rapida^^. Si alguien tiene una rutina ya, que me consta que si :P, se lo agradeceria mucho ._.
PiZZaCaT
26/10/2005, 22:11
A mi los que más me gustan son éstos:
P.D: ¿Te refieres a ese relleno o tal vez los prefieres de chocolate? :)
Y usar algo cutre como un triangulo en un sprite y manejarlo de esa forma?
Asi te evitas trabajar con primitivas, y tener que pintar el triangulo :P
Saludos
PD.Se que no sirve de nada, pero te uppeo el hilo xDD
PD.Se que no sirve de nada, pero te uppeo el hilo xDD
Pues gracias xD, no en serio creo que seria muy lento i poco versatil en spirts, supongo que al final me tocara escribirla a mi xD
Wild[Kyo]
27/10/2005, 03:06
A mi los que más me gustan son éstos:
P.D: ¿Te refieres a ese relleno o tal vez los prefieres de chocolate? :)
Eso que es? tiene una pinta que no veas... :babea:
D_Skywalk
27/10/2005, 04:28
Por que no pruebas las SDL de Chui? traen SDL_Gfx que tienen unas funciones de primitivas que te vendran de perlas :)
Un Saludo
Wonder Boy
27/10/2005, 04:38
A mi los que más me gustan son éstos:
P.D: ¿Te refieres a ese relleno o tal vez los prefieres de chocolate? :)mmmm que buenos
Bueno, voy a explicar el algoritmo que uso yo (que no quiere decir que lo haya inventado yo). Siento no ser más grafico, he intentado buscar algún ejemplo, pero no he encontrado nada, así que tendrás que echar mano del pensamiento gráfico :D
Al pintar un triángulo tenemos que tener en cuenta que siempre habrá, observando la coordenada Y, un punto superior, un punto en medio y un punto inferior. A veces nos encontraremos con que hay dos puntos en la misma linea. En este caso escogemos indistintamente uno como el mediano y otro como superior (o inferior, segun el caso).
Una vez que tenemos etiquetados o seleccionados los puntos por su altura Y, vamos a hacer el mecanismo de relleno en 2 partes. En la primera parte rellenaremos el triángulo con lineas horizontales, desde el vértice superior al mediano, en la segunda parte haremos lo mismo pero rellenando desde el vertine de en medio hasta el inferior.
Es decir, cogeremos cada una de las filas de pixeles y pintaremos lineas horizontales que vayan desde el lado izquierdo del triangulo al derecho. Para esto tenemos que emplear un poco de trigonometría básica, pero básicamente necesitamos conocer 2 puntos:
1) el punto de corte de la linea horizontal con la recta que uno los puntos superior y mediano. Es decir, la coordenada X de dicha recta para la coordenada Y dada.
2) el mismo punto de corte, pero con la recta que pasa por el punto superior y el inferior
Una vez tenemos los 2 puntos, se pinta la linea horizontal que los une y tan contentos
En la segunda parte se hace lo mismo, pero cambian las rectas que utilizamos para hayar los puntos del borde del triángulo, que son:
1) la recta que pasa por el punto medio y por el inferior.
2) la recta que pasa por el punto superior y el inferior.
Eso es todo. Puede parecer complejo, pero es uno de los más sencillos y rápidos que hay (y permite degradado vertical). Sobre todo tener mucho cuidado cuando 2 puntos están en la misma coordenada Y, ya que esto puede llevar a divisiones entre 0. Espero que sea de ayuda.
He encontrado un ejemplo de este algoritmo, pero en su caso más general aplicado a cualquier polígono, lo que lo hace bastante más complicado, pero tiene un applet que ayuda a entender el funcionamiento. Además de alguna formulita que te puede venir bien:
http://www.cse.unsw.edu.au/~cs3421/slides/bres/ScanLine.html
A.r.R.c.H.E.r
27/10/2005, 09:14
Aqui tienes una rutina para pintar triangulos rellenos y triangulos texturizados que ha hecho Damizean, va bastante rapida :)
EDITADO: Borro el archivo porque damizean pondra la rutina correcta ;)
Aqui tienes una rutina para pintar triangulos rellenos y triangulos texturizados que ha hecho Damizean, va bastante rapida :)
Muchas gracias a los dos :) , i también por la explicación.
Clipping, texturas... usando operaciones de coma fija... :babea: a ver cuando puedo probarlo!
Haohmaru
27/10/2005, 18:12
Hola, buenas.
Estoy a medio haciendo un juego de navecitas 2D, ya tengo algo de engine, y he pensado en utilizar primitivas 2d para los enemigos (los prites siempre me quedan feos); lo que passa es que no me veo muy capaz de dibujar un trinagulo de manera rapida^^. Si alguien tiene una rutina ya, que me consta que si :P, se lo agradeceria mucho ._.
Y porque no cojes el sprite de un buen juego? como el Do Don Pachi yasi te queda mas chulo xD, esque un triangulo....es una cutrada.
cada uno que haga el juego como quiera :)
Por que no pruebas las SDL de Chui? traen SDL_Gfx que tienen unas funciones de primitivas que te vendran de perlas :)
Seria una possibildad, ya he provado algunas cosas en SDL, pero este lo he empezado sin sdl ._.
Y porque no cojes el sprite de un buen juego? como el Do Don Pachi yasi te queda mas chulo xD, esque un triangulo....es una cutrada.
Si consigo terminar lo que tengo pensado, el triangulo dara bastante juego.
A mi la idea de los triangulitos me parece muy buena. Una cosa que yo personalmente aprecio de este tipo de juegos, es que sean muy dinámicos, ver constantemente la pantalla en movimiento. Prefiero ver 20 triangulitos en formación disparando tiros como locos en todas direcciones y moviendose por toda la pantalla, que 3 o 4 sprites currados que pegan 2 tiros y se van...
Bueno, es solo una preferencia personal. [wei3]
Aqui tienes una rutina para pintar triangulos rellenos y triangulos texturizados que ha hecho Damizean, va bastante rapida :)
Una pregunta un poco chorra. ¿Las funciones inline podían recibir parámetros?
Damizean
28/10/2005, 23:37
Sí :) (Y relleno un poco el post para que me deje postearlo)
Mh mirandome el .c (ahora que tengo tiempo:() me doy cuenta de que me faltan cosas (imagino que el .h )
Si damizean o algien lo puede subir junto con la version correcta lo agradeceria mucho :P
EDITADO: Borro el archivo porque damizean pondra la rutina correcta
Damizean
22/11/2005, 02:28
Hum, no se que dependencias podia tener. De todas formas esta adaptado de este:
http://skal.planet-d.net/demo/fatmap.txt
Que aunque tiene un poco de source en ASM, aqui tienes la adaptacion correspondiente en SDL:
#ifndef TRIANGLE_H
#define TRIANGLE_H
#ifdef _cplusplus
extern "C" {
#endif
// --- Includes ------------------------------------------------------------
#include <SDL/SDL.h>
#include "main.h"
// --- Structures ----------------------------------------------------------
#define SCREEN_MAXW 639
#define SCREEN_MAXH 479
typedef struct stVertex
{
float x, y;
float u, v;
} Vertex;
// --- Methods -------------------------------------------------------------
void DrawTexturedTriangle ( SDL_Surface * dstSurface, SDL_Surface * srcSurface, Vertex * vtx );
#ifdef _cplusplus
};
#endif
#endif
// --- Includes ------------------------------------------------------------
#include <SDL/SDL.h>
#include <stdlib.h>
#include "triangle.h"
// --- Variables used in texture mapping routine ---------------------------
static Vertex * leftSection[3], * rightSection[3];
static int leftSectionPoints, rightSectionPoints;
static int leftSectionHeight, rightSectionHeight;
static float deltaU, deltaV;
static float leftU, deltaLeftU, leftV, deltaLeftV;
static float leftX, deltaLeftX, rightX, deltaRightX;
// --- Methods -------------------------------------------------------------
inline int RightSection ()
{
// --- Get next points of the right section ----------------------------
Vertex * v1 = rightSection[ rightSectionPoints ];
Vertex * v2 = rightSection[ rightSectionPoints - 1 ];
// --- Calculate height ------------------------------------------------
int height = (int) (v2->y - v1->y);
if ( height == 0 ) height = 1;
float inverseHeight = 1/((float) height);
// --- Calculate deltas of this section --------------------------------
deltaRightX = ( v2->x - v1->x ) / ((float) height);
rightX = v1->x;
rightSectionHeight = height;
// --- Do clipping -----------------------------------------------------
if ( v1->y < 0 )
{
rightX += deltaRightX * -v1->y;
rightSectionHeight = (int) (height + v1->y);
}
if ( v2->y > 239 )
rightSectionHeight = (int) (239 - v1->y);
return abs(height);
}
inline int LeftSection ()
{
// --- Get next points of the right section ----------------------------
Vertex * v1 = leftSection[ leftSectionPoints ];
Vertex * v2 = leftSection[ leftSectionPoints - 1 ];
// --- Calculate height ------------------------------------------------
int height = (int) ( v2->y - v1->y );
if ( height == 0 ) height = 1;
float inverseHeight = 1/((float) height);
deltaLeftX = ( v2->x - v1->x ) * inverseHeight;
leftX = v1->x;
deltaLeftU = ( v2->u - v1->u ) * inverseHeight;
leftU = v1->u;
deltaLeftV = ( v2->v - v1->v ) * inverseHeight;
leftV = v1->v;
leftSectionHeight = height;
// --- Do clipping -----------------------------------------------------
if ( v1->y < 0 )
{
leftX += deltaLeftX * -v1->y;
leftU += deltaLeftU * -v1->y;
leftV += deltaLeftV * -v1->y;
leftSectionHeight = (int) (height + v1->y);
}
if ( v2->y > 239 )
leftSectionHeight = (int) (239 - v1->y);
return abs(height);
}
void DrawTexturedTriangle ( SDL_Surface * dstSurface, SDL_Surface * srcSurface, Vertex * vtx )
{
Vertex * v1 = (Vertex*) &vtx[0];
Vertex * v2 = (Vertex*) &vtx[1];
Vertex * v3 = (Vertex*) &vtx[2];
Vertex * v;
int height, xFrom, xTo, y, spanWidth, i;
float pixelU, pixelV;
float tmpDelta, tmpInverse;
float widestSpan;
unsigned char * srcBuffer, * dstBuffer, * dstPointer;
// Sort the vertexes in decreasing order
if ( v1->y > v2->y ) { v = v1; v1 = v2; v2 = v; }
if ( v1->y > v3->y ) { v = v1; v1 = v3; v3 = v; }
if ( v2->y > v3->y ) { v = v2; v2 = v3; v3 = v; }
// Fast y rejection
if ( v1->y > 239 ) return;
if ( v3->y < 0 ) return;
// Fast x rejection
if ( (v1->x > 319) && (v2->x > 319) && (v3->x > 319) ) return;
if ( (v1->x < 0) && (v2->x < 0) && (v3->x < 0) ) return;
// Calculate height and discard if needed
height = (int) (v3->y - v1->y);
if ( height == 0 ) height = 1;
// Calculate widest span
tmpDelta = (v2->y - v1->y) / ((float) height);
widestSpan = (tmpDelta * (v3->x - v1->x)) + (v1->x - v2->x);
if ( widestSpan == 0 ) return;
// Calculate on wich side the widest span was
if ( widestSpan < 0 ) // Right side
{
// Store vertexes
rightSection[0] = v3;
rightSection[1] = v2;
rightSection[2] = v1;
rightSectionPoints = 2;
leftSection[0] = v3;
leftSection[1] = v1;
leftSectionPoints = 1;
}
else // Left side
{
// Store vertexes
leftSection[0] = v3;
leftSection[1] = v2;
leftSection[2] = v1;
leftSectionPoints = 2;
rightSection[0] = v3;
rightSection[1] = v1;
rightSectionPoints = 1;
}
while ( LeftSection() <= 0 )
{
leftSectionPoints--;
if ( leftSectionPoints == 0 ) return;
}
while ( RightSection() <= 0 )
{
rightSectionPoints--;
if ( rightSectionPoints == 0 ) return;
}
// Calculate UV constant delta
tmpInverse = 1/widestSpan;
deltaU = (tmpDelta * ( v3->u - v1->u ) + ( v1->u - v2->u )) * tmpInverse;
deltaV = (tmpDelta * ( v3->v - v1->v ) + ( v1->v - v2->v )) * tmpInverse;
// Get source and destiny buffers
srcBuffer = (unsigned char*) srcSurface -> pixels;
dstBuffer = (unsigned char*) dstSurface -> pixels;
// Drawing loop
y = (int) v1->y;
if ( y < 0 ) y = 0;
for (;;)
{
// Get span data
xFrom = (int) leftX;
xTo = (int) rightX;
pixelU = leftU;
pixelV = leftV;
// Check if we should draw.
if ( (xTo - xFrom) > 0 )
{
// Do clipping if needed
if ( xFrom < 0 )
{
pixelU += deltaU * (-leftX);
pixelV += deltaV * (-leftX);
xFrom = 0;
}
if ( xTo > 319 )
xTo = 319;
// Get pointer to screen
dstPointer = (unsigned char*) &dstBuffer[ xFrom + (y * dstSurface -> pitch ) ];
// Draw
for ( i = xFrom; i < xTo; i++ )
{
* dstPointer++ = srcBuffer[ (((int)pixelU) & 0x3F) + ((((int)pixelV) & 0x3F)*64) ];
pixelU += deltaU;
pixelV += deltaV;
}
}
y++;
if ( --leftSectionHeight > 0 )
{
// Interpolate to next span
leftX += deltaLeftX;
leftU += deltaLeftU;
leftV += deltaLeftV;
} else {
// Check if we have finished the section
leftSectionPoints--;
if ( leftSectionPoints == 0 ) return;
while ( LeftSection() <= 0 )
{
leftSectionPoints--;
if ( leftSectionPoints == 0 ) return;
}
}
if ( --rightSectionHeight > 0 )
{
// Interpolate to next span
rightX += deltaRightX;
} else {
// Check if we have finished the section
rightSectionPoints--;
if ( rightSectionPoints == 0 ) return;
while ( RightSection() <= 0 )
{
rightSectionPoints--;
if ( rightSectionPoints == 0 ) return;
}
}
}
}
Eso si, esta en floats, tendras que adaptarlo tu a punto fijo :) Por cierto, esta forma de hacer clipping no es la mejor, seria mucho mejor borrar como hago el clipping y implementar el metodo sutherland-hodgman ( clipear un triangulo para crear un poligono que este dentro de los limites de la pantalla).
Bueno es que yo no estaba trabajando en SDL, la versióm que cayo en mis manos era a pelo (unsigned char *srcBuffer) y le faltavan las variables esas statics, ademas de que todas la variables estan renombradas...
bueno es igual, utilizaré trianglulos no rellenos i menus feina xD
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions Inc. All rights reserved.