103 lines
2.9 KiB
Text
103 lines
2.9 KiB
Text
--
|
|
-- demo\rosetta\DeathStar.exw
|
|
--
|
|
include pGUI.e
|
|
|
|
Ihandle dlg, canvas
|
|
cdCanvas cddbuffer, cdcanvas
|
|
|
|
function dot(sequence x, sequence y)
|
|
return sum(sq_mul(x,y))
|
|
end function
|
|
|
|
function normalize(sequence v)
|
|
atom len = sqrt(dot(v, v))
|
|
if len=0 then return {0,0,0} end if
|
|
return sq_mul(v,1/len)
|
|
end function
|
|
|
|
enum X,Y,Z
|
|
|
|
function hit(sequence s, atom x, y, atom r)
|
|
x -= s[X]
|
|
y -= s[Y]
|
|
atom zsq := r*r - (x*x + y*y)
|
|
if zsq >= 0 then
|
|
atom zsqrt := sqrt(zsq)
|
|
return {s[Z] - zsqrt, s[Z] + zsqrt, true}
|
|
end if
|
|
return {0, 0, false}
|
|
end function
|
|
|
|
procedure deathStar(integer width, height, atom k, atom amb, sequence direction)
|
|
integer lum
|
|
sequence vec
|
|
integer r = floor((min(width,height)-40)/2)
|
|
integer cx = floor(width/2)
|
|
integer cy = floor(height/2)
|
|
sequence pos = {0,0,0},
|
|
neg = {r*-3/4,r*-3/4,r*-1/4}
|
|
|
|
for y = pos[Y]-r to pos[Y]+r do
|
|
for x = pos[X]-r to pos[X]+r do
|
|
atom {zb1, zb2, hit1} := hit(pos, x, y, r)
|
|
if hit1 then
|
|
atom {zs1, zs2, hit2} := hit(neg, x, y, r/2)
|
|
if not hit2 or zs2<=zb2 then
|
|
if hit2 and zs1<=zb1 then
|
|
vec = {neg[X] - x, neg[Y] - y, neg[Z] - zs2}
|
|
else
|
|
vec = {x - pos[X], y - pos[Y], zb1 - pos[Z]}
|
|
-- vec = {x, y, zb1}
|
|
end if
|
|
atom s = dot(direction, normalize(vec))
|
|
lum = and_bits(#FF,255*(iff(s<0?0:power(s,k))+amb)/(1+amb))
|
|
lum += lum*#100+lum*#10000
|
|
cdCanvasPixel(cddbuffer, cx+x, cy-y, lum)
|
|
end if
|
|
end if
|
|
end for
|
|
end for
|
|
end procedure
|
|
|
|
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)
|
|
integer {width, height} = IupGetIntInt(canvas, "DRAWSIZE")
|
|
cdCanvasActivate(cddbuffer)
|
|
cdCanvasClear(cddbuffer)
|
|
deathStar(width, height, 1.5, 0.2, normalize({20, -40, -10}))
|
|
cdCanvasFlush(cddbuffer)
|
|
return IUP_DEFAULT
|
|
end function
|
|
|
|
function map_cb(Ihandle ih)
|
|
cdcanvas = cdCreateCanvas(CD_IUP, ih)
|
|
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
|
|
cdCanvasSetBackground(cddbuffer, CD_BLACK)
|
|
return IUP_DEFAULT
|
|
end function
|
|
|
|
function esc_close(Ihandle /*ih*/, atom c)
|
|
if c=K_ESC then return IUP_CLOSE end if
|
|
return IUP_CONTINUE
|
|
end function
|
|
|
|
procedure main()
|
|
IupOpen()
|
|
|
|
canvas = IupCanvas(NULL)
|
|
IupSetAttribute(canvas, "RASTERSIZE", "340x340") -- initial size
|
|
IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
|
|
|
|
dlg = IupDialog(canvas)
|
|
IupSetAttribute(dlg, "TITLE", "Draw a sphere")
|
|
IupSetCallback(dlg, "K_ANY", Icallback("esc_close"))
|
|
IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
|
|
|
|
IupMap(dlg)
|
|
IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation
|
|
IupShowXY(dlg,IUP_CENTER,IUP_CENTER)
|
|
IupMainLoop()
|
|
IupClose()
|
|
end procedure
|
|
|
|
main()
|