PDA

Ver la versión completa : [Programación] Dibujado de triángulos en Fenix



Segata Sanshiro
02/12/2008, 00:15
Resulta que llevaba un tiempo con varias pajas mentales rondándome la cabeza, todas ellas dependientes de que se pudieran dibujar triángulos en Fenix, y resulta que no encuentro función alguna para realizarlos (al menos no sin tirar de dll's).

¿Sería difícil programar una función nueva que los dibujara? La gracia estaría en que los dibuje rellenos, si no, se pueden realizar con tres líneas.

El algoritmo no es complicado:

the coordinates of vertices are (A.x,A.y), (B.x,B.y), (C.x,C.y); we assume that A.y<=B.y<=C.y (you should sort them first)
dx1,dx2,dx3 are deltas used in interpolation
horizline draws horizontal segment with coordinates (S.x,Y), (E.x,Y)
S.x, E.x are left and right x-coordinates of the segment we have to draw
S=A means that S.x=A.x; S.y=A.y;
*** begin triangle filler ***

if (B.y-A.y > 0) dx1=(B.x-A.x)/(B.y-A.y) else dx1=B.x - A.x;
if (C.y-A.y > 0) dx2=(C.x-A.x)/(C.y-A.y) else dx2=0;
if (C.y-B.y > 0) dx3=(C.x-B.x)/(C.y-B.y) else dx3=0;

S=E=A;
if(dx1 > dx2) {
for(;S.y<=B.y;S.y++,E.y++,S.x+=dx2,E.x+=dx1)
horizline(S.x,E.x,S.y,color);
E=B;
for(;S.y<=C.y;S.y++,E.y++,S.x+=dx2,E.x+=dx3)
horizline(S.x,E.x,S.y,color);
} else {
for(;S.y<=B.y;S.y++,E.y++,S.x+=dx1,E.x+=dx2)
horizline(S.x,E.x,S.y,color);
S=B;
for(;S.y<=C.y;S.y++,E.y++,S.x+=dx3,E.x+=dx2)
horizline(S.x,E.x,S.y,color);
}

Pero yo no tengo ni idea de lenguajes "de verdad", salvo Java. Se podría hacer el algoritmo en Fenix, pero supongo que sería demasiado lento.

¿Alguna idea/comentario al respecto?

ArChEr
02/12/2008, 07:01
Segun para que lo quieras... la velocidad es algo critico en lo que quieres hacer?

Yo ahora estoy liado con una nueva funcion de pintado de triangulos para el engine, a ver si consigo hacer que valla mas rapido... pero tampoco encuentro muchos metodos... la idea que tenia era la siguiente:

tener 2 buffers de 240 unidades cada uno... guardar la posicion de las aristas con algun metodo rapido como el EFLA o el bresenham, luego se recorren los 2 buffers simultaneamente desde la coordenada Y del vertice superior a la cordenada Y del vertice inferior y se rellena la linea horizontal delimitada por los 2 buffers usando memset en ensamblador...


Esa seria la teoria, luego se le podria añadir recortes al triangulo para cuando esta parcialmente fuera de la pantalla que no hiciese los calculos de la linea... y asi ahorrrar algo de tiempo...

hardyx
02/12/2008, 09:54
Hay un tutorial de dibujo en 3d (http://www.qzx.com/pc-gpe/tut9.txt) de la época de las demos en MSDOS. Tiene un código que dibuja polígonos de 4 lados en Pascal y se entiende bien. Puede usarlo para dibujar un polígono en el que el punto 3 y 4 sean iguales (o sea, un triángulo), y quizá puedas adaptar el código para el caso que x4=x3 y y4=y3.



Procedure DrawPoly(x1,y1, x2,y2, x3,y3, x4,y4:integer; color:byte);
var
x:integer;
mny,mxy:integer;
mnx,mxx,yc:integer;
mul1,div1,
mul2,div2,
mul3,div3,
mul4,div4:integer;

begin
mny:=y1; mxy:=y1;
if y2<mny then mny:=y2;
if y2>mxy then mxy:=y2;
if y3<mny then mny:=y3;
if y3>mxy then mxy:=y3; { Choose the min y mny and max y mxy }
if y4<mny then mny:=y4;
if y4>mxy then mxy:=y4;

if mny<0 then mny:=0;
if mxy>199 then mxy:=199;
if mny>199 then exit;
if mxy<0 then exit; { Verticle range checking }

mul1:=x1-x4; div1:=y1-y4;
mul2:=x2-x1; div2:=y2-y1;
mul3:=x3-x2; div3:=y3-y2;
mul4:=x4-x3; div4:=y4-y3; { Constansts needed for intersection calc }

for yc:=mny to mxy do
begin
mnx:=320;
mxx:=-1;
if (y4>=yc) or (y1>=yc) then
if (y4<=yc) or (y1<=yc) then { Check that yc is between y1 and y4 }
if not(y4=y1) then
begin
x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }
if x<mnx then
mnx:=x;
if x>mxx then
mxx:=x; { Set point as start or end of horiz line }
end;
if (y1>=yc) or (y2>=yc) then
if (y1<=yc) or (y2<=yc) then { Check that yc is between y1 and y2 }
if not(y1=y2) then
begin
x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }
if x<mnx then
mnx:=x;
if x>mxx then
mxx:=x; { Set point as start or end of horiz line }
end;
if (y2>=yc) or (y3>=yc) then
if (y2<=yc) or (y3<=yc) then { Check that yc is between y2 and y3 }
if not(y2=y3) then
begin
x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }
if x<mnx then
mnx:=x;
if x>mxx then
mxx:=x; { Set point as start or end of horiz line }
end;
if (y3>=yc) or (y4>=yc) then
if (y3<=yc) or (y4<=yc) then { Check that yc is between y3 and y4 }
if not(y3=y4) then
begin
x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }
if x<mnx then
mnx:=x;
if x>mxx then
mxx:=x; { Set point as start or end of horiz line }
end;
if mnx<0 then
mnx:=0;
if mxx>319 then
mxx:=319; { Range checking on horizontal line }
if mnx<=mxx then
hline (mnx,mxx,yc,color); { Draw the horizontal line }
end;
end;

Segata Sanshiro
02/12/2008, 13:08
Segun para que lo quieras... la velocidad es algo critico en lo que quieres hacer?

Contaba con unos 100-200 triángulos aproximadamente en pantalla, a 320x240 y unos 30 o 60 fps.

A ver si enseñas algo :D Quizás vaya siendo hora de que pase a usar C+SDL u OpenGL, pero como para conseguir el mismo resultado que en Fenix te tiras 10 veces más rato... Claro, que está el problema de las cosas que NO se pueden hacer en Fenix.

Gracias por el código hardyx, parece simple y solo usa enteros, así que si alguien se anima...

Drumpi
03/12/2008, 20:21
Si supiera hacer dlls yo mismo te ayudaría a construir la .so, pero de momento, una sencilla que suma y resta, se me sale al menu y aun no se por qué.
Además, mira por forum,divsite.net, en proyectos tienes la ETD.dll para Fenix (creo que 084, pero se puede portar fácilmente porque trae codigo fuente), que es un motor sencillo de 3D, además de la VSE, para hacer entornos VOXEL (un modo7 con relieve) bastante apañados, pero eso, aun no puedo portarlos a gp2x.

Segata Sanshiro
03/12/2008, 22:06
Si supiera hacer dlls yo mismo te ayudaría a construir la .so, pero de momento, una sencilla que suma y resta, se me sale al menu y aun no se por qué.
Además, mira por forum,divsite.net, en proyectos tienes la ETD.dll para Fenix (creo que 084, pero se puede portar fácilmente porque trae codigo fuente), que es un motor sencillo de 3D, además de la VSE, para hacer entornos VOXEL (un modo7 con relieve) bastante apañados, pero eso, aun no puedo portarlos a gp2x.

Gracias por mirarlo. La ETD esa era lo más parecido que he visto, pero igual es demasiado compleja. No sé, le eché un ojo hace un trillón de años más o menos por última vez :D