;Coded by *Kronos* the Wizard 4 - Mar - 1996 ;Instructions: ;Left mouse button & drag = rotate ;Right mouse button & drag = scale ;caveat: the first line of the window remains dirty because of a bug in the ;WCls instruction (not mine; ask Acid Software). #AXIS=0 ;1=On (if you wanna view the axis) #WIDTH=320 ;width of the screen #HEIGHT=256 ;height of the screen #NUMPTS=8 ;number of points of the poligon #NUMEDGES=12 ;number of edges of the poligon NEWTYPE.pt ;a point (wow!) is obviously made of 3 coords (x,y,z) x.f y.f z.f End NEWTYPE NEWTYPE.ed ;an edge is (start_vertex, end_vertex) stver.w enver.w End NEWTYPE Dim vertex.pt(#NUMPTS) ;here go points Dim edge.ed(#NUMEDGES) ;this is filled with edges Restore ptdat ;initialize arrays For k.w=0 To #NUMPTS-1 Read vertex(k)\x Read vertex(k)\y Read vertex(k)\z Next k Restore edgedat For k=0 To #NUMEDGES-1 Read edge(k)\stver Read edge(k)\enver Next k ;This Statement gets three parameters: the two angles a and b and the vertex ;number. It rotates the selected vertex around axis Z and X with angles a and ;b respectively. Statement RotZX{a.f,b.f,n.w} SHARED vertex.pt() x.f=vertex(n)\x y.f=vertex(n)\y z.f=vertex(n)\z vertex(n)\x=x*Cos(a)+y*Sin(a)*Cos(b)+z*Sin(a)*Sin(b) vertex(n)\y=-x*Sin(a)+y*Cos(a)*Cos(b)+z*Cos(a)*Sin(b) vertex(n)\z=-y*Sin(b)+z*Cos(b) End Statement ;The following routine has two points (x,y,z) as parameters: it projects ;them on the 2-dimensional screen and draws the line connecting them. ;Because Blitz2 doesn't allow more than 6 parameters per Statement I had ;to Share the line pattern linpat.w. The dashed lines are obtained by ;assigning the 16-bit value $F0F0 to the LinePtrn field of the RastPort ;and by using the graphics.library routines Move and Draw instead of the ;built-in Blitz2 Line instruction. ;I use the variables cospi6 and sinpi6 loaded respectively with the cosine ;and the sine of 30 deg (instead of calculating them every time the Statement ;is called) to speed up computing. Statement ProjLine{x1.f,y1.f,z1.f,x2.f,y2.f,z2.f} SHARED vertex(),edge(),cospi6.f,sinpi6.f,*rp.RastPort,linpat.w stpx.f=y1*cospi6-x1*cospi6+#WIDTH/2 stpy.f=y1*sinpi6+x1*sinpi6-z1+#HEIGHT/2 enpx.f=y2*cospi6-x2*cospi6+#WIDTH/2 enpy.f=y2*sinpi6+x2*sinpi6-z2+#HEIGHT/2 *rp\LinePtrn=linpat *rp\linpatcnt=15 *rp\Flags=*rp\Flags|#FRST_DOT Move_ *rp,stpx,stpy Draw_ *rp,enpx,enpy End Statement ;This Statement cycles through edges and draws the poligon. Statement DrawAll{} SHARED vertex(),edge.ed(),cospi6.f,sinpi6.f,linpat.w,*rp ;This is a trick to recognize the hidden vertex (only if you have one hidden ;vertex at a time): it's the one with the most negative sum of its three ;coords. totmin.f=0 For k.w=0 To #NUMPTS-1 If totmin>vertex(k)\x+vertex(k)\y+vertex(k)\z totmin=vertex(k)\x+vertex(k)\y+vertex(k)\z totver.w=k EndIf Next k WCls cospi6.f=Cos(Pi/6) sinpi6.f=Sin(Pi/6) CNIF #AXIS=1 linpat.w=$FFFF SetAPen_ *rp,2 ProjLine{0,0,0,80,0,0} ;X axis SetAPen_ *rp,3 ProjLine{0,0,0,0,80,0} ;Y axis SetAPen_ *rp,4 ProjLine{0,0,0,0,0,80} ;Z axis CEND SetAPen_ *rp,1 For k=0 To #NUMEDGES-1 linpat.w=$FFFF ;If the current edge departs from the hidden vertex then the line is dashed If edge(k)\stver=totver OR edge(k)\enver=totver Then linpat=$F0F0 vx1.f=vertex(edge(k)\stver)\x vy1.f=vertex(edge(k)\stver)\y vz1.f=vertex(edge(k)\stver)\z vx2.f=vertex(edge(k)\enver)\x vy2.f=vertex(edge(k)\enver)\y vz2.f=vertex(edge(k)\enver)\z ProjLine{vx1,vy1,vz1,vx2,vy2,vz2} ;project and draw Next k End Statement ;Begin flags.l=#WFLG_CLOSEGADGET|#WFLG_ACTIVATE|#WFLG_SMART_REFRESH|#WFLG_RMBTRAP|#WFLG_GIMMEZEROZERO Screen 0,0,0,#WIDTH,#HEIGHT,3,0,"3DRot",0,1 Window 0,0,0,#WIDTH,#HEIGHT,flags,"3DRotation by *Kronos* the Wizard",0,1 *rp.RastPort=RastPort(0) restart: ev.l=WaitEvent If ev=$200 OR EventWindow<>0 Then Goto bye omx.w=WMouseX omy.w=WMouseY ;This is the main loop. Repeat nmx.w=WMouseX nmy.w=WMouseY If nmx<>omx OR nmy<>omy ;if mouse position has changed... Select Joyb(0) Case 1 ;if left mouse button ;To make the rotation relative to the mouse starting point (when the user ;pressed the left button) and not to its absolute position on the screen, ;I subtract the starting position omx from the new one nmx and then I ;multiply the resulting quantity with the fraction of 360 deg represented ;by one pixel. anglez.f=(nmx-omx)*((2*Pi)/#WIDTH) ;rot around third coord (z) anglex.f=(nmy-omy)*((2*Pi)/#HEIGHT) ;rot around first coord (x) For k.w=0 To #NUMPTS-1 RotZX{anglez,anglex,k} ;rotates all vertices Next k DrawAll{} ;and then draw the entire poligon Case 2 ;if right mouse button ;The scaling factor scalefac depends on the mouse distance from the origin: ;this is why I compute the radius (squared) r2 of a circle centered in the ;origin of the axis (the center of the screen). Here also, as I did before ;for the rotation part, I use the mouse position relative to the starting ;point. r2.w=((nmx-#WIDTH/2)^2+(nmy-#HEIGHT/2)^2)-((omx-#WIDTH/2)^2+(omy-#HEIGHT/2)^2) If r2>0 scalefac.f=1.1 Else scalefac.f=0.9 EndIf For k.w=0 To #NUMPTS-1 ;scale all vertices vertex(k)\x=vertex(k)\x*scalefac vertex(k)\y=vertex(k)\y*scalefac vertex(k)\z=vertex(k)\z*scalefac Next k DrawAll{} ;and draw the entire poligon End Select omx=nmx omy=nmy EndIf Until Joyb(0)=0 ;until user releases the mouse button Goto restart bye: Free Window 0 Free Screen 0 End ptdat: ;vertex coords (x, y, z) Data.f -100,-100,-100 Data.f -100,100,-100 Data.f 100,100,-100 Data.f 100,-100,-100 Data.f -100,-100,100 Data.f -100,100,100 Data.f 100,100,100 Data.f 100,-100,100 edgedat: ;edge=(start_vertex, end_vertex) Data.w 0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7