#Import "" #Import "" Using std.. Using mojo.. Global title:String="VGrid 0.1" Global AboutApp:=title+" Isometric Cube Experiment" Global Controls:="Grow=G,GrowX=X,GrowY=Y,GrowZ=Z,Clear=C,,Zoom=MouseWeel,Rotate=Cursor Keys" Global Contact:=",github.com/nitrologic/m2" Global Credits:=",Transpiled by Monkey2 :)" Const Qube:=27 Const Rubik:=13' -1 -3 -9 (-13) is rubik offset Const Rubit:=1 shl Rubik Const RubitMask:=$7ffffff 'bit per neighbor vacancy mask Global Order4:=New Int[](1,0,0,1, 0,1,-1,0, -1,0,0,-1, 0,-1,1,0) Class Cube Global CubeCounter:=0 Field id:int Field x:Int Field y:Int Field z:Int Field rubit:=Rubit Field image:Image Field color:Int Field kids:Cube[] Field style:Int Method New(skin:Image) image=skin CubeCounter+=1 id=CubeCounter Print "id="+id End Method Clone:Cube() Local cube:=New Cube(image) Return cube End Method SortDepth:Int(quadrant:Int) local ix:=Order4[quadrant*4+0] local iy:=Order4[quadrant*4+1] local jx:=Order4[quadrant*4+2] local jy:=Order4[quadrant*4+3] Local dx:=x*ix+z*jx Local dy:=x*iy+z*jy Return ((dx+dy) Shl 16) + y End ' meet cube at dx,dy,dz offset Method Meet(cube:Cube,dx:int,dy:int,dz:Int) Local index:=Rubik+dx+dy*3+dz*9 Local bit:=1 Shl index rubit|=bit Local mindex:=Rubik-dx-dy*3-dz*9 Local mbit:=1 Shl mindex cube.rubit|=mbit End Const D:=10 Method DrawCube(display:Canvas,zx:Double,zy:Double,rz:Double) Assert(rubit<>RubitMask) Local sx:Float=(x-z)+zy*y*2 Local sy:Float=(x+z)+zx*y*2 display.DrawImage(image,sx*D,sy*D,rz,0.125,0.25) 'facing eye ' display.DrawImage(image,sx*D,sy*D,0,0.125,0.25) 'facing sky end end Global scanCount:int Class DualAxisStack Field root:Cube Field org:Vec3 Field dim:Vec3 Field stack:List Field ordered:=New Cube[][4] ' quadrant facing 2d march order where y is always up Method New(rootCube:Cube) root=rootCube org=New Vec3(-1,-1,-1) dim=new Vec3(3,3,3) stack=New List stack.AddLast(root) BakeSort() End Method BakeSort() Local cullstack:=New List() For local cube:=Eachin stack If cube.rubit<>RubitMask ' level1 view cull cullstack.AddLast(cube) endif Next For local quadrant:=0 Until 4 Local order:=New List(cullstack) local func:=Lambda:Int(a:Cube,b:Cube) return b.SortDepth(quadrant)-a.SortDepth(quadrant) End order.Sort(func) ordered[quadrant]=order.ToArray() Next End end Class DualAxisGrid Extends DualAxisStack Field grid:Cube[,,] Method New(rootCube:Cube) Super.New(rootCube) grid=New Cube[dim.x,dim.y,dim.z] End Method Skin(xaxis:Bool=True,yaxis:bool=True,zaxis:Bool=True) Local dx:=Int(xaxis) Local dy:=Int(yaxis) Local dz:=Int(zaxis) org=new Vec3(org.x-dx,org.y-dy,org.z-dz) dim=New Vec3(dim.x+dx*2,dim.y+dy*2,dim.z+dz*2) grid=New Cube[dim.x,dim.y,dim.z] For Local point:=Eachin stack grid[point.x-org.x,point.y-org.y,point.z-org.z]=point Next ' first enamel parse Local enamel:=New List For Local cube:=Eachin stack Local sx:=cube.x-org.x Local sy:=cube.y-org.y Local sz:=cube.z-org.z For local x:=-dx To dx For Local y:=-dy To dy For local z:=-dz To dz If (x|y|z)=0 Continue If grid[sx+x,sy+y,sz+z]=Null Local cube2:=root.Clone() cube2.x=cube.x+x cube2.y=cube.y+y cube2.z=cube.z+z Assert(sx+x=cube2.x-org.x) Assert(sy+y=cube2.y-org.y) Assert(sz+z=cube2.z-org.z) enamel.AddLast(cube2) grid[sx+x,sy+y,sz+z]=cube2 Endif Next Next Next Next ' second vacant parse effect all neighbors of enamel For Local cube:=Eachin enamel stack.AddLast(cube) Local sx:=cube.x-org.x Local sy:=cube.y-org.y Local sz:=cube.z-org.z For local x:=-dx To dx For Local y:=-dy To dy For Local z:=-dz To dz If (x|y|z)=0 Continue Local cube2:=grid[sx+x,sy+y,sz+z] if cube2<>Null cube.Meet(cube2,x,y,z) Next Next Next Next BakeSort() End End Class Grid Field star:Cube Field grid:DualAxisGrid Field framecount:Int Field skin:Image Method New(image:Image) skin=image Clear() End Method Count:Int() Return grid.stack.Count() End Method Generate(xaxis:Bool=True,yaxis:bool=True,zaxis:Bool=True) grid.Skin(xaxis,yaxis,zaxis) End Method Clear() star=New Cube(skin) grid=New DualAxisGrid(star) end Field zx:Double Field zy:Double Field DrawQuadrant:Int Method IsoView(display:Canvas, width:double, height:double, theta:Double, scale:Double) zx=Cos(theta) zy=Sin(theta) local tx:=zx*scale local ty:=zy*scale display.Matrix=new AffineMat3f(tx,ty*0.5,-ty,tx*0.5,width*0.5,height*0.5) End Method DrawGrid( c:Canvas, width:double, height:double, theta:Double, zoom:Double ) c.PushMatrix() Local scale:=1.0/zoom IsoView(c,width,height,theta,scale) ' calulate draw order so we scan grid from far to near Local quadrant:Int=Int(2.5+2*theta/Pi)&3 DrawQuadrant=quadrant For Local cube:=Eachin grid.ordered[quadrant] cube.DrawCube(c,zx,zy,theta) Next c.PopMatrix() framecount+=1 End End Class VGrid Extends Window Field grid:Grid Field status:String Field zoom:Float Field framecount:Int Field drawcount:Int Field mousecount:Int Field cx:Float Field cy:Float Field rot:Double Field rotSpeed:Double Field radius:Float Global Transparent:=New Color(0,0,0,0) Global SmokedGlass:=New Color(0,0,0,0.7) Method New(title:String) Super.New(title,1024,800,WindowFlags.Resizable) ClearColor=Color.Black zoom=.2 radius=2.5 grid=New Grid(BallImage()) End Method BallImage:Image() local pix:=New Pixmap(128,128) pix.Clear(Color.None) Circle(pix,64,64,40,Color.Yellow) Circle(pix,64,64,34,Color.Black) Circle(pix,64,64,24,Color.Blue) Circle(pix,42,42,8,Color.White) local image:=new Image(pix)',TextureFlags.Filter|TextureFlags.Mipmap) image.Handle=New Vec2f( .5,.5 ) Return image End function Circle(pix:Pixmap,rx:int,ry:int,r:int,c:Color) Local x0:=rx-r Local x1:=rx+r Local y0:=ry-r Local y1:=ry+r x0=Max(x0,0) y0=Max(y0,0) For Local y:=y0 To y1 For Local x:=x0 To x1 Local dd:=(x-rx)*(x-rx)+(y-ry)*(y-ry) If dd