Re: Polygon coordinates transformation
- Posted by jiri babor <jbabor at paradise.net.nz> Mar 19, 2004
- 355 views
Tommy, back in 1998 I proposed *fast* texture mapping routines that transform a given polygon to another polygon. The target polygon has only two restrictions: (1) it has to have the same number of vertices as the source polygon, and (2) it has to be 'horizontally' convex (but, of course, both these conditions can be circumvented with a tiny bit of effort...). I realize my transform (essentially mapping every point on a horizontal line in the target to a point in the source) is not exactly what you were asking for, but it can be perhaps adapted for your purposes. jiri -- map.e : texture mapping function space(integer n,integer y,integer y2) sequence s integer d,dy,e,f,m if n=1 then return {y} end if if y=y2 then return repeat(y,n) end if s = repeat(y,n) s[n] = y2 dy = 1 d = 2*(y2-y) m = n-1 f = 2*m e = -m if y>y2 then dy = -1 d = -d end if for i = 2 to m do e += d while e>=0 do e -= f y += dy end while s[i] = y end for return s end function global procedure map_image( sequence tex, -- texture bitmap, 2-d sequence sequence p, -- vertices in texture: {{u1,v1},..{un,vn}} sequence s -- polygon to be shown: {{x1,y1},..{xn,yn}} ) -- texture mapping, pixel mode: -- map polygon p in image (texture) tex into polygon s -- polygon s must be convex : any *horizontal* line has no -- more than *two* intersections with sides of such polygon sequence u,uu,v,vv,x,xx integer i1,i2,k,len,n,rows,u1,u2,v1,v2,x1,x2,y,y1,y2,yi,ymax,ymin s=floor(s) -- integers only n=length(s) -- number of sides -- get y extremes ymin=s[1][2] ymax=ymin for i=2 to n do if s[i][2]<ymin then ymin=s[i][2] end if if s[i][2]>ymax then ymax=s[i][2] end if end for -- set up edge arrays rows=ymax-ymin+1 xx=repeat({},rows) -- hold x-values uu=xx -- texture horizontal index vv=xx -- texture vertical index -- init & loop x2=s[n][1] y2=s[n][2]-ymin+1 u2=p[n][1] v2=p[n][2] for i=1 to n do x1=x2 x2=s[i][1] y1=y2 y2=s[i][2]-ymin+1 u1=u2 u2=p[i][1] v1=v2 v2=p[i][2] if y1=y2 then -- horizontal side xx[y1] &= x1 uu[y1] &= u1 vv[y1] &= v1 else -- non-horizontal side if y1>y2 then len=y1-y2+1 yi=-1 else len=y2-y1+1 yi=1 end if x=space(len,x1,x2) u=space(len,u1,u2) v=space(len,v1,v2) k=1 for j=y1 to y2-yi by yi do xx[j] &= x[k] uu[j] &= u[k] vv[j] &= v[k] k+=1 end for end if end for -- display y=ymin if length(xx[1])=1 then pixel(tex[vv[1][1]][uu[1][1]],{xx[1][1],y}) y+=1 i1=2 else i1=1 end if if length(xx[rows])=1 then i2=rows-1 pixel(tex[vv[rows][1]][uu[rows][1]],{xx[rows][1],ymax}) else i2=rows end if for i=i1 to i2 do x=xx[i] x1=x[1] x2=x[2] if x1<x2 then len=x2-x1+1 u=space(len,uu[i][1],uu[i][2]) v=space(len,vv[i][1],vv[i][2]) else len=x1-x2+1 u=space(len,uu[i][2],uu[i][1]) v=space(len,vv[i][2],vv[i][1]) x1=x2 end if x=repeat(0,len) for j=1 to len do x[j]=tex[v[j]][u[j]] end for pixel(x,{x1,y}) y+=1 end for end procedure -- map_image global procedure vmap_image( atom a, -- screen address integer w, -- screen width sequence tex, -- texture bitmap, 2-d sequence sequence p, -- vertices in texture: {{u1,v1},..{un,vn}} sequence s -- polygon to be shown: {{x1,y1},..{xn,yn}} ) -- texture mapping for virtual screens: -- map polygon p in image (texture) tex into polygon s -- polygon s must be convex : any *horizontal* line has no -- more than *two* intersections with sides of such polygon sequence u,uu,v,vv,x,xx integer i1,i2,k,len,n,rows,u1,u2,v1,v2,x1,x2,y1,y2,yi,ymax,ymin s=floor(s) -- integers only n=length(s) -- number of sides -- get y extremes ymin=s[1][2] ymax=ymin for i=2 to n do if s[i][2]<ymin then ymin=s[i][2] end if if s[i][2]>ymax then ymax=s[i][2] end if end for -- set up edge arrays rows=ymax-ymin+1 xx=repeat({},rows) -- hold x-values uu=xx -- texture horizontal index vv=xx -- texture vertical index -- init & loop x2=s[n][1] y2=s[n][2]-ymin+1 u2=p[n][1] v2=p[n][2] for i=1 to n do x1=x2 x2=s[i][1] y1=y2 y2=s[i][2]-ymin+1 u1=u2 u2=p[i][1] v1=v2 v2=p[i][2] if y1=y2 then -- horizontal side xx[y1] &= x1 uu[y1] &= u1 vv[y1] &= v1 else -- non-horizontal side if y1>y2 then len=y1-y2+1 yi=-1 else len=y2-y1+1 yi=1 end if x=space(len,x1,x2) u=space(len,u1,u2) v=space(len,v1,v2) k=1 for j=y1 to y2-yi by yi do xx[j] &= x[k] uu[j] &= u[k] vv[j] &= v[k] k+=1 end for end if end for -- display a+=w*ymin if length(xx[1])=1 then poke(a+xx[1][1],tex[vv[1][1]][uu[1][1]]) a+=w i1=2 else i1=1 end if if length(xx[rows])=1 then i2=rows-1 else i2=rows end if for i=i1 to i2 do x=xx[i] x1=x[1] x2=x[2] if x1<x2 then len=x2-x1+1 u=space(len,uu[i][1],uu[i][2]) v=space(len,vv[i][1],vv[i][2]) else len=x1-x2+1 u=space(len,uu[i][2],uu[i][1]) v=space(len,vv[i][2],vv[i][1]) x1=x2 end if x=repeat(0,len) for j=1 to len do x[j]=tex[v[j]][u[j]] end for poke(a+x1,x) a+=w end for if i2<rows then poke(a+xx[rows][1],tex[vv[rows][1]][uu[rows][1]]) end if end procedure -- vmap_image