vgrid.monkey2 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. #Import "<std>"
  2. #Import "<mojo>"
  3. Using std..
  4. Using mojo..
  5. Global title:String="VGrid 0.1"
  6. Global AboutApp:=title+" Isometric Cube Experiment"
  7. Global Controls:="Grow=G,GrowX=X,GrowY=Y,GrowZ=Z,Clear=C,,Zoom=MouseWeel,Rotate=Cursor Keys"
  8. Global Contact:=",github.com/nitrologic/m2"
  9. Global Credits:=",Transpiled by Monkey2 :)"
  10. Const Qube:=27
  11. Const Rubik:=13' -1 -3 -9 (-13) is rubik offset
  12. Const Rubit:=1 shl Rubik
  13. Const RubitMask:=$7ffffff 'bit per neighbor vacancy mask
  14. Global Order4:=New Int[](1,0,0,1, 0,1,-1,0, -1,0,0,-1, 0,-1,1,0)
  15. Class Cube
  16. Global CubeCounter:=0
  17. Field id:int
  18. Field x:Int
  19. Field y:Int
  20. Field z:Int
  21. Field rubit:=Rubit
  22. Field image:Image
  23. Field color:Int
  24. Field kids:Cube[]
  25. Field style:Int
  26. Method New(skin:Image)
  27. image=skin
  28. CubeCounter+=1
  29. id=CubeCounter
  30. Print "id="+id
  31. End
  32. Method Clone:Cube()
  33. Local cube:=New Cube(image)
  34. Return cube
  35. End
  36. Method SortDepth:Int(quadrant:Int)
  37. local ix:=Order4[quadrant*4+0]
  38. local iy:=Order4[quadrant*4+1]
  39. local jx:=Order4[quadrant*4+2]
  40. local jy:=Order4[quadrant*4+3]
  41. Local dx:=x*ix+z*jx
  42. Local dy:=x*iy+z*jy
  43. Return ((dx+dy) Shl 16) + y
  44. End
  45. ' meet cube at dx,dy,dz offset
  46. Method Meet(cube:Cube,dx:int,dy:int,dz:Int)
  47. Local index:=Rubik+dx+dy*3+dz*9
  48. Local bit:=1 Shl index
  49. rubit|=bit
  50. Local mindex:=Rubik-dx-dy*3-dz*9
  51. Local mbit:=1 Shl mindex
  52. cube.rubit|=mbit
  53. End
  54. Const D:=10
  55. Method DrawCube(display:Canvas,zx:Double,zy:Double,rz:Double)
  56. Assert(rubit<>RubitMask)
  57. Local sx:Float=(x-z)+zy*y*2
  58. Local sy:Float=(x+z)+zx*y*2
  59. display.DrawImage(image,sx*D,sy*D,rz,0.125,0.25) 'facing eye
  60. ' display.DrawImage(image,sx*D,sy*D,0,0.125,0.25) 'facing sky
  61. end
  62. end
  63. Global scanCount:int
  64. Class DualAxisStack
  65. Field root:Cube
  66. Field org:Vec3<Int>
  67. Field dim:Vec3<Int>
  68. Field stack:List<Cube>
  69. Field ordered:=New Cube[][4] ' quadrant facing 2d march order where y is always up
  70. Method New(rootCube:Cube)
  71. root=rootCube
  72. org=New Vec3<int>(-1,-1,-1)
  73. dim=new Vec3<Int>(3,3,3)
  74. stack=New List<Cube>
  75. stack.AddLast(root)
  76. BakeSort()
  77. End
  78. Method BakeSort()
  79. Local cullstack:=New List<Cube>()
  80. For local cube:=Eachin stack
  81. If cube.rubit<>RubitMask ' level1 view cull
  82. cullstack.AddLast(cube)
  83. endif
  84. Next
  85. For local quadrant:=0 Until 4
  86. Local order:=New List<Cube>(cullstack)
  87. local func:=Lambda:Int(a:Cube,b:Cube)
  88. return b.SortDepth(quadrant)-a.SortDepth(quadrant)
  89. End
  90. order.Sort(func)
  91. ordered[quadrant]=order.ToArray()
  92. Next
  93. End
  94. end
  95. Class DualAxisGrid Extends DualAxisStack
  96. Field grid:Cube[,,]
  97. Method New(rootCube:Cube)
  98. Super.New(rootCube)
  99. grid=New Cube[dim.x,dim.y,dim.z]
  100. End
  101. Method Skin(xaxis:Bool=True,yaxis:bool=True,zaxis:Bool=True)
  102. Local dx:=Int(xaxis)
  103. Local dy:=Int(yaxis)
  104. Local dz:=Int(zaxis)
  105. org=new Vec3<int>(org.x-dx,org.y-dy,org.z-dz)
  106. dim=New Vec3<Int>(dim.x+dx*2,dim.y+dy*2,dim.z+dz*2)
  107. grid=New Cube[dim.x,dim.y,dim.z]
  108. For Local point:=Eachin stack
  109. grid[point.x-org.x,point.y-org.y,point.z-org.z]=point
  110. Next
  111. ' first enamel parse
  112. Local enamel:=New List<Cube>
  113. For Local cube:=Eachin stack
  114. Local sx:=cube.x-org.x
  115. Local sy:=cube.y-org.y
  116. Local sz:=cube.z-org.z
  117. For local x:=-dx To dx
  118. For Local y:=-dy To dy
  119. For local z:=-dz To dz
  120. If (x|y|z)=0 Continue
  121. If grid[sx+x,sy+y,sz+z]=Null
  122. Local cube2:=root.Clone()
  123. cube2.x=cube.x+x
  124. cube2.y=cube.y+y
  125. cube2.z=cube.z+z
  126. Assert(sx+x=cube2.x-org.x)
  127. Assert(sy+y=cube2.y-org.y)
  128. Assert(sz+z=cube2.z-org.z)
  129. enamel.AddLast(cube2)
  130. grid[sx+x,sy+y,sz+z]=cube2
  131. Endif
  132. Next
  133. Next
  134. Next
  135. Next
  136. ' second vacant parse effect all neighbors of enamel
  137. For Local cube:=Eachin enamel
  138. stack.AddLast(cube)
  139. Local sx:=cube.x-org.x
  140. Local sy:=cube.y-org.y
  141. Local sz:=cube.z-org.z
  142. For local x:=-dx To dx
  143. For Local y:=-dy To dy
  144. For Local z:=-dz To dz
  145. If (x|y|z)=0 Continue
  146. Local cube2:=grid[sx+x,sy+y,sz+z]
  147. if cube2<>Null cube.Meet(cube2,x,y,z)
  148. Next
  149. Next
  150. Next
  151. Next
  152. BakeSort()
  153. End
  154. End
  155. Class Grid
  156. Field star:Cube
  157. Field grid:DualAxisGrid
  158. Field framecount:Int
  159. Field skin:Image
  160. Method New(image:Image)
  161. skin=image
  162. Clear()
  163. End
  164. Method Count:Int()
  165. Return grid.stack.Count()
  166. End
  167. Method Generate(xaxis:Bool=True,yaxis:bool=True,zaxis:Bool=True)
  168. grid.Skin(xaxis,yaxis,zaxis)
  169. End
  170. Method Clear()
  171. star=New Cube(skin)
  172. grid=New DualAxisGrid(star)
  173. end
  174. Field zx:Double
  175. Field zy:Double
  176. Field DrawQuadrant:Int
  177. Method IsoView(display:Canvas, width:double, height:double, theta:Double, scale:Double)
  178. zx=Cos(theta)
  179. zy=Sin(theta)
  180. local tx:=zx*scale
  181. local ty:=zy*scale
  182. display.Matrix=new AffineMat3f(tx,ty*0.5,-ty,tx*0.5,width*0.5,height*0.5)
  183. End
  184. Method DrawGrid( c:Canvas, width:double, height:double, theta:Double, zoom:Double )
  185. c.PushMatrix()
  186. Local scale:=1.0/zoom
  187. IsoView(c,width,height,theta,scale)
  188. ' calulate draw order so we scan grid from far to near
  189. Local quadrant:Int=Int(2.5+2*theta/Pi)&3
  190. DrawQuadrant=quadrant
  191. For Local cube:=Eachin grid.ordered[quadrant]
  192. cube.DrawCube(c,zx,zy,theta)
  193. Next
  194. c.PopMatrix()
  195. framecount+=1
  196. End
  197. End
  198. Class VGrid Extends Window
  199. Field grid:Grid
  200. Field status:String
  201. Field zoom:Float
  202. Field framecount:Int
  203. Field drawcount:Int
  204. Field mousecount:Int
  205. Field cx:Float
  206. Field cy:Float
  207. Field rot:Double
  208. Field rotSpeed:Double
  209. Field radius:Float
  210. Global Transparent:=New Color(0,0,0,0)
  211. Global SmokedGlass:=New Color(0,0,0,0.7)
  212. Method New(title:String)
  213. Super.New(title,1024,800,WindowFlags.Resizable)
  214. ClearColor=Color.Black
  215. zoom=.2
  216. radius=2.5
  217. grid=New Grid(BallImage())
  218. End
  219. Method BallImage:Image()
  220. local pix:=New Pixmap(128,128)
  221. pix.Clear(Color.None)
  222. Circle(pix,64,64,40,Color.Yellow)
  223. Circle(pix,64,64,34,Color.Black)
  224. Circle(pix,64,64,24,Color.Blue)
  225. Circle(pix,42,42,8,Color.White)
  226. local image:=new Image(pix)',TextureFlags.Filter|TextureFlags.Mipmap)
  227. image.Handle=New Vec2f( .5,.5 )
  228. Return image
  229. End
  230. function Circle(pix:Pixmap,rx:int,ry:int,r:int,c:Color)
  231. Local x0:=rx-r
  232. Local x1:=rx+r
  233. Local y0:=ry-r
  234. Local y1:=ry+r
  235. x0=Max(x0,0)
  236. y0=Max(y0,0)
  237. For Local y:=y0 To y1
  238. For Local x:=x0 To x1
  239. Local dd:=(x-rx)*(x-rx)+(y-ry)*(y-ry)
  240. If dd<r*r
  241. pix.SetPixel(x,y,c)
  242. endif
  243. Next
  244. Next
  245. End
  246. Method DrawStats(display:Canvas)
  247. Local cy:=10
  248. display.Color=SmokedGlass
  249. display.DrawRect(0,0,200,Height)
  250. display.Color=Color.Grey
  251. Local content:=AboutApp
  252. content+=",,"+Controls
  253. content+=",,Count="+grid.Count()
  254. content+=",Quadrant="+grid.DrawQuadrant
  255. content+=","+Contact+","+Credits
  256. For Local line:=Eachin content.Split(",")
  257. Local cx:=10
  258. For Local tab:=Eachin line.Split("=")
  259. tab=tab.Replace(":)",":=")
  260. display.DrawText(tab,cx,cy)
  261. cx+=60
  262. Next
  263. cy+=16
  264. Next
  265. End
  266. Method OnRender( display:Canvas ) Override
  267. App.RequestRender()
  268. rot+=rotSpeed*rotSpeed*rotSpeed
  269. If rot<0
  270. rot=Pi*2-((-rot) Mod (Pi*2))
  271. Else
  272. rot=rot Mod (Pi*2)
  273. Endif
  274. grid.DrawGrid(display,Width,Height,rot,zoom)
  275. DrawStats(display)
  276. End
  277. Method Hold()
  278. rotSpeed=0
  279. rot=0
  280. End
  281. Method OnKeyEvent( event:KeyEvent ) Override
  282. Select event.Type
  283. Case EventType.KeyDown
  284. Select event.Key
  285. Case Key.C
  286. grid.Clear()
  287. Case Key.G
  288. grid.Generate(True,True,True)
  289. Case Key.X
  290. grid.Generate(True,False,False)
  291. Case Key.Y
  292. grid.Generate(False,True,false)
  293. Case Key.Z
  294. grid.Generate(false,false,True)
  295. Case Key.Escape
  296. App.Terminate()
  297. Case Key.F1
  298. Fullscreen = Not Fullscreen
  299. Case Key.Space
  300. Hold()
  301. Case Key.Left
  302. rotSpeed+=1.0/16
  303. Case Key.Right
  304. rotSpeed-=1.0/16
  305. Case Key.Down
  306. radius*=0.8
  307. Case Key.Up
  308. radius*=1.2
  309. end
  310. End
  311. End
  312. Method OnMouseEvent(event:MouseEvent ) Override
  313. Select event.Type
  314. Case EventType.MouseWheel
  315. local w:=event.Wheel.Y
  316. zoom-=w/8.0
  317. If zoom<1.0/8 zoom=1.0/8
  318. End
  319. End
  320. End
  321. Function Main()
  322. Print title
  323. New AppInstance
  324. New VGrid(title)
  325. App.Run()
  326. End