The source is here if you want look a really nasty source
Code: Select all
;3d Primer
;filled konvex polygon drawing
;
;To do:
;- add size detection and compensation
@REQUIRE "MUIRoyale"
@APPTITLE "ShowGeo"
@APPVERSION "$VER: ShowGeo 1.0 (02.01.13)"
@APPCOPYRIGHT "(C) Copyright 2013 by Lázi"
@APPAUTHOR "Lázi"
@APPDESCRIPTION "Display .geo format 3D polygon objects"
@DISPLAY {hidden=true,width=640,height=400}
@FILE 1,"videoscape/geo/boing"
@FILE 2,"videoscape/geo/theend"
SetFormStyle (#ANTIALIAS)
SetFillStyle (#FILLCOLOR)
world={
obj=0,
YMID=200,
XMID=320,
DIST=90,
ZOM=400,
filled=true,
bw=false
}
obj={{}}
;pontok
obj[0].pt={{x=-10, y=-10, z=-10},
{x= 10, y=-10, z=-10},
{x= 10, y= 10, z=-10},
{x=-10, y= 10, z=-10},
{x=-10, y=-10, z= 10},
{x= 10, y=-10, z= 10},
{x= 10, y= 10, z= 10},
{x=-10, y= 10, z= 10},
{x=0,y=0,z=0},
{x=30,y=0,z=0},
{x=0,y=30,z=0},
{x=0,y=0,z=30},
}
pal={$000000,$0050A0,$008C00,$008C8C,$A00000,$8CA0A0,$A07800,$8C8C8C,$000000,$0078F0,$00F000,$00F0F0,$F00000,$C800F0,$F0C800,$F0F0F0}
;élek
obj[0].P={{0,3,2,1,$0050A0},{0,1,5,4,$008C00},{2,3,7,6,$008C8C},{4,5,6,7,$A00000},{0,4,7,3,$8CA0A0},{1,2,6,5,$A07800}}
;elforgatott pontok
obj[0].rpt=CopyTable(obj[0].pt)
obj[0].rot={0,0,0}
;---------------------------------------------------------------
function p_dragmouse()
InstallEventHandler({onmousedown=0,onmouseup=p_releasemouse})
SetInterval(2,p_mousemove,1000/30,{x=MouseX(),y=MouseY()})
endfunction
function p_releasemouse()
ClearInterval(2)
InstallEventHandler({onmousedown=p_dragmouse,onmouseup=0,onmousemove=0})
Endfunction
function p_mousemove(msg)
kappa=Wrap(kappa-MouseX()+msg.userdata.x,0,359)
phi=Wrap(phi-MouseY()+msg.userdata.y,0,359)
p_rotate(0,0,0)
p_mainloop
SetInterval(2,p_mousemove,1000/30,{x=MouseX(),y=MouseY()})
endfunction
function p_zoomin()
world.zom=Min(world.zom+50,2500)
p_mainloop
endfunction
function p_zoomout()
world.zom=Max(world.zom-50,50)
p_mainloop
endfunction
factory_val=Val
function Val(s)
if LeftStr(s,1)="."
s="0"..s
elseif LeftStr(s,2)="-."
s="-0"..s
endif
Return(factory_val(s))
endfunction
;---------------------------------------------------------------
function p_loadgeo(o,f$,preopened)
local points,coords,g, i, n, nagyobb, scale
local fh=1
if preopened
fh=o
else
OpenFile(fh,f$,#MODE_READ)
endif
if ReadLine(fh)="3DG1"
obj[o]={pt={},rpt={},p={},rot={0,0,0}}
pt={}
points=Val(ReadLine(fh))-1
for local i=0 to points
g,n=SplitStr(ReadLine(fh)," ")
if n=3
gx=Val(g[0])
gy=-Val(g[1])
gz=Val(g[2])
nagyobb=Max(nagyobb,Abs(gx),Abs(gy),Abs(gz))
InsertItem(obj[o].pt,{x=gx,y=gy,z=gz},i)
endif
next
scale=10/(nagyobb)
for i=0 to ListItems(obj[o].pt)-1
obj[o].pt[i].x=obj[o].pt[i].x*scale
obj[o].pt[i].y=obj[o].pt[i].y*scale
obj[o].pt[i].z=obj[o].pt[i].z*scale
next
obj[o].rpt=CopyTable(obj[o].pt)
p={}
while not Eof(fh)
ll=TrimStr(ReadLine(fh)," ",false)
coords,points=SplitStr(ll," ")
gx={}
if points>1
For i=1 To coords[0]+1
InsertItem(gx,Val(coords[i]) ,i-1)
Next
;color
;drop special attributes
gx[i-2]=pal[gx[i-2] & 15 ]
InsertItem(obj[o].p,gx)
endif
wend
else
mui.request("ShowGeo","The selected file is not a .geo file what I can handle","Continue")
Return(false)
endif
CloseFile(fh)
mui.domethod("object","Insert",o,FilePart(f$))
Return(true)
endfunction
function p_rotate(dxr,dyr,dzr)
; Increment rotation angles around z,x,y
;teta=Wrap(teta+dzr,0,359)
;phi=Wrap(phi+dxr,0,359)
;kappa=Wrap(kappa+dyr,0,359)
; Precalculation of COSs and SINs
Local CPHI=Cos(Rad(PHI))
Local SPHI=Sin(Rad(PHI))
Local CTETA=Cos(Rad(TETA))
Local STETA=Sin(Rad(TETA))
Local CKAP=Cos(Rad(KAPPA))
Local SKAP=Sin(Rad(KAPPA))
; Calculation of rotated 3D coords of all points
; Rotation (X-Z with PHI) & rotation (X-Y with TETA)
For I=0 To ListItems(pt)-1
;x
rpt[I].z=(pt[I].z*cPHI-pt[I].y*sPHI)
rpt[I].y=(pt[I].z*sPHI+pt[I].y*cPHI)
rpt[I].x=pt[I].x
;y
local x=(rpt[I].z*sKAP+rpt[I].x*cKAP)
rpt[I].z=(rpt[I].z*cKAP-rpt[I].x*sKAP)
rpt[I].x=x
;z
x=(rpt[I].x*CTETA-rpt[I].y*STETA)
rpt[I].y=(rpt[I].x*STETA+rpt[I].y*CTETA)
rpt[I].x=x
Next
endfunction
function p_drawobject()
; Calculation of A,B,C,D screen coords and draw lines
local p1,p2,p3,abx,aby,abz,pvx,pvy,pvz,c,ci
For I=0 To ListItems(p)-1
if world.bw=false
c= P[I][ListItems(p[I])-1]
else
c=#WHITE
endif
if ListItems(p[i])>3 and world.filled=true
p1=p[i][0]
p2=p[i][1]
p3=p[i][2]
;' Calculation of AB vector
abx=rpt[p2].x-rpt[p1].x
aby=rpt[p2].y-rpt[p1].y
abz=rpt[p2].z-rpt[p1].z
;' Calculaton of AC vector
acx=rpt[p3].x-rpt[p1].x
acy=rpt[p3].y-rpt[p1].y
acz=rpt[p3].z-rpt[p1].z
;' Calculation of PV vector = AB^AC
pvx=aby*acz-abz*acy
pvy=abz*acx-abx*acz
pvz=abx*acy-aby*acx
;' Calculation of ENL scalair product PV.AB
;' (proportionnal with Enlightment of a Face)
Local ENL= PVX*rpt[p1].x + PVY*rpt[p1].y + PVZ*(rpt[p1].z + world.DIST)
;' Positive ENL means that the face is hidden
If enl<0 or mui.get("hidden","selected")
enl=(-enl)/(.05*world.dist)
vert={}
for t=0 to ListItems(p[i])-3
P1=P[I][t]
P2=P[I][t+1]
ox2=x2
oy2=y2
x2=world.XMID+(rpt[P2].x*world.ZOM)/(world.DIST+rpt[P2].z)
y2=world.YMID+(rpt[P2].y*world.ZOM)/(world.DIST+rpt[P2].z)
X1=world.XMID+(rpt[P1].x*world.ZOM)/(world.DIST+rpt[P1].z)
Y1=world.YMID+(rpt[P1].y*world.ZOM)/(world.DIST+rpt[P1].z)
if mui.get("wireframe","selected")
Line (X1,Y1 , X2,Y2,c)
endif
;Plot(x1,y1,c)
If t=0
ox1=x1
oy1=y1
InsertItem(vert,x1)
InsertItem(vert,y1)
EndIf
InsertItem(vert,x2)
InsertItem(vert,y2)
next
if mui.get("wireframe","selected")
Line (x2,y2,ox1,oy1,c)
endif
;Plot(x2,y2,c)
if mui.get("wireframe","selected")=False
InsertItem(vert,ox1)
InsertItem(vert,ox2)
Polygon(0,0,vert,ListItems(vert)/2-1,c);RGB(enl/2,0,enl/2))
endif
EndIf
else
for t=0 to ListItems(p[i])-3
P1=P[I][t]
P2=P[I][t+1]
ox2=x2
oy2=y2
x2=world.XMID+(rpt[P2].x*world.ZOM)/(world.DIST+rpt[P2].z)
y2=world.YMID+(rpt[P2].y*world.ZOM)/(world.DIST+rpt[P2].z)
X1=world.XMID+(rpt[P1].x*world.ZOM)/(world.DIST+rpt[P1].z)
Y1=world.YMID+(rpt[P1].y*world.ZOM)/(world.DIST+rpt[P1].z)
Line (X1,Y1 , X2,Y2,c)
;Plot(x1,y1,c)
If t=0
ox1=x1
oy1=y1
EndIf
next
Line (x2,y2,ox1,oy1,c)
;Plot(x2,y2,c)
endif
next
endfunction
function p_setobject(o)
p=obj[o].p
rpt=obj[o].rpt
pt=obj[o].pt
phi=obj[o].rot[0]
kappa=obj[o].rot[1]
teta=obj[o].rot[2]
endfunction
function p_mainloop()
Flip(true)
if mui.get("wvbl","selected") then VWait
Cls(100)
p_drawobject
p_rotate(1,2,0)
Endfunction
Function p_EventFunc(msg)
; has the size of our Hollywood class changed?
If msg.Action = "SizeWindow"
world.xmid = msg.Width/2
world.ymid = msg.Height/2
Return
EndIf
; handle MUI Royale events
Switch msg.class
Case "Window":
Switch msg.Attribute
Case "CloseRequest":
End
EndSwitch
Case "Button":
Switch msg.Attribute
Case "Pressed":
Switch msg.ID
Case "play":
SetInterval(1, p_demorotate, 1000/30)
Case "stop":
If HaveObject(#INTERVAL, 1) = True
ClearInterval(1)
EndIf
EndSwitch
EndSwitch
case "Listview":
switch msg.id
case "object":
world.obj=(mui.get("object","active"))
p_setobject(world.obj)
endswitch
case "Checkmark":
switch msg.id
case "wireframe":
if mui.get("hidden","selected") and mui.get("wireframe","selected")=false
mui.set("hidden","selected",false)
endif
case "antialias":
if mui.get("antialias","selected")
SetFormStyle (#ANTIALIAS)
else
SetFormStyle (#NONE)
endif
case "hidden":
if mui.get("wireframe","selected")=false and mui.get("hidden","selected")=true
mui.set("wireframe","selected",true)
endif
case "hwdb":
EndDoubleBuffer
if mui.get("hwdb","selected")
BeginDoubleBuffer(true)
else
BeginDoubleBuffer(false)
endif
endswitch
case "Popfile":
switch msg.id
case "file":
if p_loadgeo(mui.get("object","entries"),mui.get("file","contents"))
p_setobject(mui.get("object","entries")-1)
endif
endswitch
EndSwitch
p_mainloop
Flip
EndFunction
function p_demorotate()
; Increment rotation angles around z,x,y
teta=Wrap(teta+1,0,359)
phi=Wrap(phi+2,0,359)
kappa=Wrap(kappa+1,0,359)
p_mainloop
endfunction
mui.CreateGUI([[
<?xml version="1.0" encoding="iso-8859-1"?>
<application base="GEO-View">
<window title="ShowGeo" muiid="MAIN" notify="closerequest">
<hgroup>
<vgroup>
<listview shorthelp="Loaded object files" notify="active" id="object">
<column title="Object">
</column>
</listview>
<Label>Load object:</Label>
<popfile id="file" shorthelp="Add a .geo object file to the list" notify="contents" title="Select .geo file to load"/>
<colgroup frame="group" frametitle="Draw mode" columns="2">
<Label>Wireframe:</Label><checkmark notify="selected" id="wireframe"/>
<Label>Antialias:</Label><checkmark notify="selected" id="antialias" selected="true"/>
<Label>Hidden lines:</Label><checkmark notify="selected" id="hidden"/>
<Label>Hardware db:</Label><checkmark shorthelp="Hardware accelerated double buffered display." disabled="true" notify="selected" id="hwdb"/>
<Label>Wait vbl:</Label><checkmark id="wvbl" selected="true"/>
</colgroup>
</vgroup>
<vgroup>
<text preparse="\33c" frame="text">Use your mouse to rotate the object around, and the wheel to zoom it!</text>
<hollywood shorthelp="Display area. The object can be zoomed, rotated by the mouse." display="1" minwidth="640" minheight="400"
maxwidth="640" maxheight="400"/>
<hgroup>
<button id="play" notify="pressed">Start rotation</button>
<button id="stop" notify="pressed">Stop rotation</button>
</hgroup>
</vgroup>
</hgroup>
</window>
</application>
]])
mui.domethod("object","Insert",0,"Cube")
p_loadgeo(1,"videoscape/geo/boing",true)
p_loadgeo(2,"videoscape/geo/theend",true)
p_setobject(world.obj)
CreateBrush(1,10,10,#WHITE)
CopyBrush(1,2,{hardware=true})
if GetAttribute(#BRUSH,2,#ATTRHARDWARE)
mui.set("hwdb","disabled",0)
mui.set("hwdb","selected",true)
endif
FreeBrush(1)
FreeBrush(2)
BeginDoubleBuffer(mui.get("hwdb","disabled"))
SetInterval(1, p_demorotate, 1000/30)
InstallEventHandler({MUIRoyale = p_EventFunc, SizeWindow = p_EventFunc, onmousedown=p_dragmouse,onmouseup=0,onmousemove=0,onwheeldown=p_zoomin,onwheelup=p_zoomout,onrightmousedown=p_change})
Repeat
WaitEvent
forever