Forum Replies Created
-
AuthorPosts
-
*Very* basic example:
[/crayon]Monkey1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677[crayon-5cba94c4334ce361864731 inline="true" ]#Import "<std>"#Import "<mojo>"#Import "<mojox>"'#Import "shadedDark12.png"Using std..Using mojo..Using mojox..Function Main()New AppInstanceNew MyWindowApp.Run()End'------Class MyWindow Extends WindowMethod New()Super.New( "Button Demo",640,480,WindowFlags.Resizable )SaveString(CreateButtonTheme(), AssetsDir() + "/myTheme.json")Local theme:=App.Theme.Load("asset::myTheme.json")Local image:Image = CreateButtonImage(200, 40)'Local image := Image.Load( "asset::shadedDark12.png" )Local button:=New PushButton("", image)button.Style = GetStyle("myButton")button.Layout="float"button.Gravity=New Vec2f( .5,.5 )button.MaxSize=New Vec2i( 100,0 )ClearColor = Color.LightGreybutton.Clicked=Lambda()Alert( "Well done sir!" )EndContentView=buttonEndEnd'---- Generated Content:Function CreateButtonTheme:String()Local strJson:StringstrJson += "{~n~qextends~q:~qdefault~q,~n"strJson += "~qstyles~q:{~n"strJson += "~t~qmyButton~q:{~n"strJson += "~t~t~qstates~q:{~n"strJson += "~t~t~t~qhover~q:{~n"strJson += "~t~t~t~t~qiconColor~q:~q#FFFF00FF~q~n~t~t~t},~n"strJson += "~t~t~t~qactive~q:{~n"strJson += "~t~t~t~t~qiconColor~q:~q#FF0000FF~q~n~t~t~t}~n"strJson += "~n~t~t}~n"strJson += "~t}~n}~n}"Print strJsonReturn strJsonEndFunction CreateButtonImage:Image(w:Int, h:Int)Local img:Image = New Image(w, h)Local canvas:=New Canvas(img)canvas.Clear(Color.None)canvas.Color=Color.Whitecanvas.DrawRect(0, 0, w, h)canvas.Color=Color.Blackcanvas.DrawText("My Image", 0, 0)canvas.Flush()Return imgEndThere’s no denying we *are* limiting mx23d’s potential user base by going with gles3, but IMO it’s worth it. It’ll make my life a ton easier, and the new features are likely to allow entirely new approaches to terrains, sprites, environmental effects and a bunch of other stuff.
I agree. An emphatic vote for GLES3 from me…
Then there are new features such as geometry shaders (which I *really* want to play with!), transform feedback (eg: render to ‘vertex buffer’), and a bunch of other features that just plain make stuff ‘go faster’ such as uniform buffers, geometry instancing (draw a bunch of models in one hit), vertex arrays and so on.
..Though geometry shaders are a capability of GLES3.2 (released 2015), so support for that particular feature might be very limited?
https://en.wikipedia.org/wiki/OpenGL_ES
Utilising a graphics subsystem higher than gles2 would kill off the emscripten (i.e. browser) target in the near term because gles3 (via WebGl 2.0) isn’t supported yet by most browsers.
http://caniuse.com/#feat=webgl2
Also, gles2 underlies the current mojo incarnation so mixing 2d with 3d might not be possible if Mark uses gles3 for 3d.
My personal ideal would be a Vulkan/Metal/DX12-based engine, ditching support for all the old stuff and incapable target platforms, but that would probably take ten times longer and alienate most of monkey2’s potential user-base.
So, I see Mark’s current plan as “realistic” and something to look forward to, as, like with everything, there are positives as well as negatives.
Nice. Looks like a realistic plan. Can’t wait to see the results.
I can’t find a way to do it so I’m going to paste only the pertinent function(s) in each post body and “attach” the complete runnable example as a zip file…
EDIT: Still a “wall of code” but not quite as bad.
Relevant theory links for the previous two examples…
Particle Deposition:
Generating heightmaps using particle depositionFault Algorithm:
http://www.lighthouse3d.com/opengl/terrain/index.php?faultFault Algorithm:
(See attachment for runnable example)
[/crayon]Monkey12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061[crayon-5cba94c441ea1805065635 inline="true" ]'http://www.lighthouse3d.com/opengl/terrain/index.php?faultFunction GenerateFaultMap:Void(array:Double[,], realism:Float)'Generate a heightmap in a 2d array using the "fault line" algorithm.'realism: number of fault lines: higher number (> 500) gives greater realism. Minimum 1.'NOTE: This is a comparatively slow algorithm.If Not array Then ReturnLocal width := array.GetSize(0)Local height := array.GetSize(1)For Local x := 0 Until widthFor Local y := 0 Until heightarray[x, y] = 0.0NextNextLocal d := Sqrt((width * width) + (height * height))Local disp:Double = 10.0For Local n := 1 To realismLocal v := Rnd(0, 359)Local a := Sin((v * (Pi / 180.0)))Local b := Cos((v * (Pi / 180.0)))Local c := (Rnd(0, 1) * d) - (d / 2)For Local x := 0 Until widthFor Local y := 0 Until heightIf (((a * x) + (b * y) - c) > 0.0)array[x, y] += dispElsearray[x, y] -= dispEndifNextNextNext'''NormaliseLocal minv := array[0, 0]Local maxv := array[0, 0]For Local x := 0 Until widthFor Local y:= 0 Until heightIf (array[x, y] < minv)minv = array[x, y]ElseIf (array[x, y] > maxv) Then maxv = array[x, y]EndifNextNextFor Local x := 0 Until widthFor Local y:= 0 Until heightarray[x, y] = (array[x, y] - minv) / (maxv - minv)NextNext'''EndAttachments:
Particle deposition:
(See attachment for runnable example)
[/crayon]Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131[crayon-5cba94c44657e967639515 inline="true" ]Function GenerateParticleMap:Void(array:Double[,], particles:Int, clusters:Int, sticky:Bool = True, amts:Int[] = Null)'Generate a heightmap in a 2d array using the "particle" algorithms.'particles: number of particles to calculate per cluster. Minimum 1.'clusters: number of clusters: higher number gives greater map density. Minimum 1.'sticky: algorithm variation: True = sticky, False = rolling.'amts: particle variation. Should be an integer array of 4 values. Suggested range -5 to 5.If Not array Then ReturnLocal width := array.GetSize(0)Local height := array.GetSize(1)For Local x := 0 Until widthFor Local y := 0 Until heightarray[x, y] = 0.0NextNextIf amts = Null Or amts.Length < 4 Then amts = New Int[](-1, 1, -1, 1)Local disp:Float = 1.0If sticky 'Sticky styleFor Local m := 1 To clustersLocal x := Floor(Rnd(0, width))Local y := Floor(Rnd(0, height))For Local n := 1 To particlesIf (((x < width) And (y < height) And (x >= 0) And (y >= 0)))array[x, y] += dispSelect Floor(Rnd(0, amts.Length))Case 0x += amts[0]Case 1x += amts[1]Case 2y += amts[2]Case 3y += amts[3]EndEndifNextNextElse 'Rolling styleFor Local m := 1 To clustersLocal x := Floor(Rnd(0, width))Local y := Floor(Rnd(0, height))For Local n := 1 To particlesIf (((x < width) And (y < height) And (x >= 0) And (y >= 0)))Local h := array[x, y] + disparray[x, y] = hLocal startx := x - 1If (startx < 0) Then startx = 0Local endx := x + 1If (endx > width) Then endx = widthLocal starty := y - 1If (starty < 0) Then starty = 0Local endy := y + 1If (endy > height) Then endy = heightFor Local x2 := startx Until endxFor Local y2 := starty Until endyLocal h2 := array[x2, y2]If (h2 < h) Then array[x2, y2] += dispNextNextEndifSelect Floor(Rnd(0, amts.Length))Case 0x += amts[0]Case 1x += amts[1]Case 2y += amts[2]Case 3y += amts[3]EndNextNextEndif'''NormaliseLocal minv := array[0, 0]Local maxv := array[0, 0]For Local x := 0 Until widthFor Local y:= 0 Until heightIf (array[x, y] < minv)minv = array[x, y]ElseIf (array[x, y] > maxv) Then maxv = array[x, y]EndifNextNextFor Local x := 0 Until widthFor Local y:= 0 Until heightarray[x, y] = (array[x, y] - minv) / (maxv - minv)NextNext'''EndAttachments:
That’s good enough, no improvement necessary.
For simple proof of concept code I usually don’t bother seeding with a unique number per run but I should. So I’m going to incorporate your code snippet, though slightly simplified.
Another way to do it, if you’re not generating something right at the start, is to seed with Microsecs at the point of first user interaction. That’s what I do for my game projects and simulations.
Yes, if you seed the RNG with the same number you should see the same results regardless of platform, since Monkey 2’s RNG algorithm is platform agnostic.
EDIT. Sorry, I misunderstood your statement. Yes, I realise Millisecs and Microsecs are derived from the application start time so the results are likely to be the same…
Here are some links that explain, in depth, the algorithms that the above code is inspired/based on:
Perlin
http://devmag.org.za/2009/04/25/perlin-noise/Hill algorithm.
http://www.stuffwithstuff.com/robot-frog/3d/hills/hill.htmlMidpoint displacement (aka Diamond Square algorithm)
https://en.wikipedia.org/wiki/Diamond-square_algorithmYour technique sounds similar to the “hill algorithm”, except you use rectangles instead of circles/ovals. I’d be interested in seeing your code!
Midpoint Displacement
(See attachment for runnable example)
[/crayon]Monkey12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394[crayon-5cba94c454f5d278496750 inline="true" ]Function GenerateMPDMap:Void(array:Double[,], grain:Float)'Generate a heightmap in a 2d array using the "midpoint displacement" algorithm.'grain: graininess. Suggested range 0.1 to 2.0If Not array Then ReturnLocal width := array.GetSize(0)Local height := array.GetSize(1)For Local x := 0 Until widthFor Local y := 0 Until heightarray[x, y] = -1.0NextNextarray[0, 0] = Rnd(0.0, 1.0)array[width - 1, 0] = Rnd(0.0, 1.0)array[0, height - 1] = Rnd(0.0, 1.0)array[width - 1, height - 1] = Rnd(0.0, 1.0)recurseMPD(array, 0, 0, width - 1, height - 1, grain, 1.0)'''NormaliseLocal minv := array[0, 0]Local maxv := array[0, 0]For Local x := 0 Until widthFor Local y:= 0 Until heightIf (array[x, y] < minv)minv = array[x, y]ElseIf (array[x, y] > maxv) Then maxv = array[x, y]EndifNextNextFor Local x := 0 Until widthFor Local y:= 0 Until heightarray[x, y] = (array[x, y] - minv) / (maxv - minv)NextNext'''EndFunction recurseMPD:Void(array:Double[,], x0:Int, y0:Int, x2:Int, y2:Int, grain:Double, level:Double)'Recursive function used by the GenerateMPDMap function.Local MPD := Lambda:Double(x0:Int, y0:Int, x1:Int, y1:Int, x2:Int, y2:Int)Local r:Double = Rnd(-grain, grain) / levelr += ((array[x0, y0] + array[x2, y2]) / 2.0)r = Clamp(r, Cast<Double>(0.0), Cast<Double>(1.0))array[x1, y1] = rReturn rEndIf (Not(((x2 - x0) < 2) And ((y2 - y0) < 2)))Local v:Double, i:Doublelevel = 2.0 * levelLocal x1:Int = Ceil((x0 + x2) / 2.0)Local y1:Int = Ceil((y0 + y2) / 2.0)v = array[x1, y0]If (v = -1.0) Then v = MPD(x0, y0, x1, y0, x2, y0)i = vv = array[x2, y1]If (v = -1.0) Then v = MPD(x2, y0, x2, y1, x2, y2)i += vv = array[x1, y2]If (v = -1.0) Then v = MPD(x0, y2, x1, y2, x2, y2)i += vv = array[x0, y1]If (v = -1.0) Then v = MPD(x0, y0, x0, y1, x0, y2)i += vIf (array[x1, y1] = -1.0) Then array[x1, y1] = i/4.0recurseMPD(array, x0, y0, x1, y1, grain, level)recurseMPD(array, x1, y0, x2, y1, grain, level)recurseMPD(array, x1, y1, x2, y2, grain, level)recurseMPD(array, x0, y1, x1, y2, grain, level)EndifEndAttachments:
Hill algorithm:
(See attachment for runnable example)
[/crayon]Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778[crayon-5cba94c45b64e898542817 inline="true" ]Function GenerateHillMap:void(array:Double[,], numHills:UInt, maxHillRadius:Double, island:Bool = false)'Generate a heightmap in a 2d array using the "hill" algorithm.'numHills: number of "hills". Recommended range: 250 to 2000.'maxHillRadiussize: maximum hill radius. For best results, value should be significantly'less than the map's shortest dimension.'island: create an island-like result. True/FalseIf Not array Then ReturnLocal width := array.GetSize(0)Local height := array.GetSize(1)For Local x := 0 Until widthFor Local y := 0 Until heightarray[x, y] = 0.0NextNextIf island Then maxHillRadius *= 0.5For Local n := 1 To numHillsLocal radius :Double = Floor(Rnd(0, maxHillRadius))Local centrex:Double = Floor(Rnd(0, width))Local centrey:Double = Floor(Rnd(0, height))If islandLocal theta := Rnd(0.0, 359.0)Local distx := Floor(Rnd(0, width * 0.5 - radius))Local disty := Floor(Rnd(0, height * 0.5 - radius))centrex = width * 0.5 + (Cos(theta) * distx)centrey = height * 0.5 + (Sin(theta) * disty)EndifLocal startx := centrex - radiusIf startx < 0 Then startx = 0Local endx := centrex + radiusIf endx > width Then endx = widthLocal starty := centrey - radiusIf starty < 0 Then starty = 0Local endy := centrey + radiusIf endy > height Then endy = heightFor Local x := startx Until endxFor Local y := starty Until endyLocal h:Double = (radius * radius) - (((x - centrex) * (x - centrex)) + ((y - centrey) * (y - centrey)))If (h > 0.0) Then array[x, y] += hNextNextNext'''NormaliseLocal minv := array[0, 0]Local maxv := array[0, 0]For Local x := 0 Until widthFor Local y:= 0 Until heightIf (array[x, y] < minv)minv = array[x, y]ElseIf (array[x, y] > maxv) Then maxv = array[x, y]EndifNextNextFor Local x := 0 Until widthFor Local y:= 0 Until heightarray[x, y] = (array[x, y] - minv) / (maxv - minv)NextNext'''EndAttachments:
@danilo. Very interesting, thanks for the info… Don’t you just love all the complexity and “edge cases” associated with software development?
Do you need to double the font sizes?
I’d assume it depends on the amount of DPI. Higher amounts would require higher multiples font size. IIRC, Ted2 fonts are really small by default. I have to use the “zoom” functionality of the “View” menu item – but only on the first run.
Not sure about your problem above. Would have to see the relevant code… You might need an additional RequestRender call somewhere or to manually adjust View rects, etc…
-
AuthorPosts