fixed bug with negative module
This commit is contained in:
@@ -43,6 +43,11 @@ proc xlate*(x, y: float32) : X2d =
|
|||||||
result[2,0] = x
|
result[2,0] = x
|
||||||
result[2,1] = y
|
result[2,1] = y
|
||||||
|
|
||||||
|
proc xlate*(p: P2d) : X2d =
|
||||||
|
result = identity[3,float32]()
|
||||||
|
result[2,0] = p.x
|
||||||
|
result[2,1] = p.y
|
||||||
|
|
||||||
proc scale*(center : P2d, x, y : float32) : X2d = xlate(-center.x, -center.y) * scale(x,y) * xlate(center.x, center.y)
|
proc scale*(center : P2d, x, y : float32) : X2d = xlate(-center.x, -center.y) * scale(x,y) * xlate(center.x, center.y)
|
||||||
proc rot*(center : P2d, angle : float32) : X2d = xlate(-center.x, -center.y) * rot(angle) * xlate(center.x, center.y)
|
proc rot*(center : P2d, angle : float32) : X2d = xlate(-center.x, -center.y) * rot(angle) * xlate(center.x, center.y)
|
||||||
|
|
||||||
|
45
grid.nim
45
grid.nim
@@ -1,57 +1,58 @@
|
|||||||
import random
|
import random
|
||||||
from times import epochTime
|
from times import epochTime
|
||||||
|
from nwo/utils import nmod
|
||||||
type Grid* = object
|
type Grid* = object
|
||||||
rows*, columns* : uint32
|
rows*, columns* : int
|
||||||
data : seq[uint32]
|
data : seq[uint32]
|
||||||
|
|
||||||
proc newGrid*(rows, columns : uint32) : Grid =
|
proc newGrid*(rows, columns : int) : Grid =
|
||||||
Grid(
|
Grid(
|
||||||
rows: rows,
|
rows: rows,
|
||||||
columns: columns,
|
columns: columns,
|
||||||
data: newSeq[uint32]((rows * columns + 8 - 1) div 8)
|
data: newSeq[uint32]((rows * columns + 8 - 1) div 8)
|
||||||
)
|
)
|
||||||
|
|
||||||
proc get(grid : Grid, x, y : uint32) : bool =
|
proc get(grid : Grid, x, y : int) : bool =
|
||||||
assert x < grid.columns
|
assert x < grid.columns
|
||||||
assert y < grid.rows
|
assert y < grid.rows
|
||||||
let index = y * grid.columns + x
|
let index = y * grid.columns + x
|
||||||
(grid.data[index div 8] and (1u32 shl (index mod 8))) != 0
|
(grid.data[index div 8] and (1u32 shl (index mod 8))) != 0
|
||||||
|
|
||||||
proc set(grid : var Grid, x, y : uint32, value : bool) : void =
|
proc set(grid : var Grid, x, y : int, value : bool) : void =
|
||||||
assert x < grid.columns
|
assert x < grid.columns
|
||||||
assert y < grid.rows
|
assert y < grid.rows
|
||||||
let index = y * grid.columns + x
|
let index = y * grid.columns + x
|
||||||
grid.data[(index div 8)] =
|
grid.data[index div 8] =
|
||||||
if value:
|
if value:
|
||||||
grid.data[(index div 8)] or (1u32 shl (index mod 8))
|
grid.data[index div 8] or (1u32 shl (index mod 8))
|
||||||
else:
|
else:
|
||||||
grid.data[(index div 8)] and (not (1u32 shl (index mod 8)))
|
grid.data[index div 8] and (not (1u32 shl (index mod 8)))
|
||||||
|
|
||||||
template `[]`*(grid : Grid, x,y : uint32) : bool =
|
template `[]`*(grid : Grid, x,y : int) : bool =
|
||||||
get(grid, x, y)
|
get(grid, x, y)
|
||||||
|
|
||||||
template `[]=`*(grid : Grid, x,y : uint32, value : bool) =
|
template `[]=`*(grid : Grid, x,y : int, value : bool) =
|
||||||
set(grid, x, y, value)
|
set(grid, x, y, value)
|
||||||
|
|
||||||
proc next_step*(old_grid, new_grid : var Grid) =
|
proc next_step*(old_grid, new_grid : var Grid) =
|
||||||
for x in 0..<old_grid.columns:
|
for x in 0..<old_grid.columns:
|
||||||
for y in 0..<old_grid.rows:
|
for y in 0..<old_grid.rows:
|
||||||
var alive_neighbours = 0
|
var alive_neighbours = 0
|
||||||
if old_grid[(x+1) mod old_grid.columns, y]:
|
if old_grid[nmod(x+1, old_grid.columns), y]:
|
||||||
alive_neighbours += 1
|
alive_neighbours += 1
|
||||||
if old_grid[(x+1) mod old_grid.columns, (y+1) mod old_grid.rows]:
|
if old_grid[nmod(x+1, old_grid.columns), nmod(y+1, old_grid.rows)]:
|
||||||
alive_neighbours += 1
|
alive_neighbours += 1
|
||||||
if old_grid[(x+1) mod old_grid.columns, (y-1) mod old_grid.rows]:
|
if old_grid[nmod(x+1, old_grid.columns), nmod(y-1, old_grid.rows)]:
|
||||||
alive_neighbours += 1
|
alive_neighbours += 1
|
||||||
if old_grid[(x-1) mod old_grid.columns, y]:
|
if old_grid[nmod(x-1, old_grid.columns), y]:
|
||||||
alive_neighbours += 1
|
alive_neighbours += 1
|
||||||
if old_grid[(x-1) mod old_grid.columns, (y + 1) mod old_grid.rows]:
|
if old_grid[nmod(x-1, old_grid.columns), nmod(y + 1, old_grid.rows)]:
|
||||||
alive_neighbours += 1
|
alive_neighbours += 1
|
||||||
if old_grid[(x-1) mod old_grid.columns, (y - 1) mod old_grid.rows]:
|
if old_grid[nmod(x-1, old_grid.columns), nmod(y - 1, old_grid.rows)]:
|
||||||
alive_neighbours += 1
|
alive_neighbours += 1
|
||||||
if old_grid[x mod old_grid.columns, (y + 1) mod old_grid.rows]:
|
if old_grid[nmod(x, old_grid.columns), nmod(y + 1, old_grid.rows)]:
|
||||||
alive_neighbours += 1
|
alive_neighbours += 1
|
||||||
if old_grid[x mod old_grid.columns, (y - 1) mod old_grid.rows]:
|
if old_grid[nmod(x, old_grid.columns), nmod(y - 1, old_grid.rows)]:
|
||||||
alive_neighbours += 1
|
alive_neighbours += 1
|
||||||
|
|
||||||
if old_grid[x, y]:
|
if old_grid[x, y]:
|
||||||
@@ -63,6 +64,10 @@ proc next_step*(old_grid, new_grid : var Grid) =
|
|||||||
new_grid[x, y] = true
|
new_grid[x, y] = true
|
||||||
else:
|
else:
|
||||||
new_grid[x, y] = false
|
new_grid[x, y] = false
|
||||||
|
let tmp = old_grid
|
||||||
|
old_grid = new_grid
|
||||||
|
new_grid = tmp
|
||||||
|
|
||||||
|
|
||||||
proc rand_init*(grid : var Grid) =
|
proc rand_init*(grid : var Grid) =
|
||||||
var rand = initRand(epochTime().int64)
|
var rand = initRand(epochTime().int64)
|
||||||
@@ -70,4 +75,8 @@ proc rand_init*(grid : var Grid) =
|
|||||||
for y in 0..<grid.rows:
|
for y in 0..<grid.rows:
|
||||||
grid[x, y] = (rand.next() mod 2) != 0
|
grid[x, y] = (rand.next() mod 2) != 0
|
||||||
|
|
||||||
|
proc clear*(grid : var Grid) =
|
||||||
|
for x in 0..<grid.columns:
|
||||||
|
for y in 0..<grid.rows:
|
||||||
|
grid[x, y] = false
|
||||||
|
|
||||||
|
88
main.nim
88
main.nim
@@ -30,10 +30,10 @@ var
|
|||||||
fpsman: FpsManager
|
fpsman: FpsManager
|
||||||
fpsman.init
|
fpsman.init
|
||||||
|
|
||||||
let side : uint32 = 5
|
let side = 5
|
||||||
let
|
let
|
||||||
pixelx = 200u32
|
pixelx = 200
|
||||||
pixely = 200u32
|
pixely = 200
|
||||||
|
|
||||||
var
|
var
|
||||||
current_grid, next_grid : ref[Grid]
|
current_grid, next_grid : ref[Grid]
|
||||||
@@ -44,9 +44,10 @@ block:
|
|||||||
next_grid = box(grid)
|
next_grid = box(grid)
|
||||||
|
|
||||||
let bb = newRect2d(0f32, 0f32, float32(side * pixelx), float32(side * pixely))
|
let bb = newRect2d(0f32, 0f32, float32(side * pixelx), float32(side * pixely))
|
||||||
let step = 3
|
var step = 3
|
||||||
var elapsed_time_sec = 0
|
var elapsed_time_sec = 0
|
||||||
var
|
var
|
||||||
|
xform : X2d = identity[3, float32]()
|
||||||
uxform : X2d = identity[3, float32]()
|
uxform : X2d = identity[3, float32]()
|
||||||
pan_start : Option[P2d] = none[P2d]()
|
pan_start : Option[P2d] = none[P2d]()
|
||||||
|
|
||||||
@@ -62,33 +63,61 @@ while not quit:
|
|||||||
break
|
break
|
||||||
of KeyDown:
|
of KeyDown:
|
||||||
let keyboardEvent = cast[KeyboardEventPtr](addr(evt))
|
let keyboardEvent = cast[KeyboardEventPtr](addr(evt))
|
||||||
case keyboardEvent.keysym.sym.char:
|
case keyboardEvent.keysym.sym:
|
||||||
of ' ':
|
of ' '.int:
|
||||||
freeze = not freeze
|
freeze = not freeze
|
||||||
of 'h':
|
of 'h'.int:
|
||||||
uxform = identity[3, float32]()
|
uxform = identity[3, float32]()
|
||||||
|
of 'c'.int:
|
||||||
|
current_grid[].clear()
|
||||||
|
of 's'.int:
|
||||||
|
next_step(current_grid[], next_grid[])
|
||||||
|
of '['.int:
|
||||||
|
if step > 1:
|
||||||
|
step -= 1
|
||||||
|
of ']'.int:
|
||||||
|
if step < 10:
|
||||||
|
step += 1
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
of MouseButtonDown:
|
of MouseButtonDown:
|
||||||
let mouseButtonDownEvent = cast[MouseButtonEventPtr](addr(evt))
|
let mouseButtonDownEvent = cast[MouseButtonEventPtr](addr(evt))
|
||||||
if mouseButtonDownEvent.which == BUTTON_RIGHT:
|
case mouseButtonDownEvent.button:
|
||||||
pan_start = some(newP2d(mouseButtonDownEvent.x.float32, mouseButtonDownEvent.y.float32))
|
of BUTTON_RIGHT:
|
||||||
|
pan_start = some(newP2d(mouseButtonDownEvent.x.float32, mouseButtonDownEvent.y.float32))
|
||||||
|
of BUTTON_LEFT:
|
||||||
|
let inv = xform.invert()
|
||||||
|
let position = newP2d(mouseButtonDownEvent.x.float32, mouseButtonDownEvent.y.float32) * inv / side.float32
|
||||||
|
let row = position.x.int
|
||||||
|
let column = position.y.int
|
||||||
|
current_grid[][row, column] = not current_grid[][row, column]
|
||||||
|
else:
|
||||||
|
discard
|
||||||
of MouseButtonUp:
|
of MouseButtonUp:
|
||||||
let mouseButtonDownEvent = cast[MouseButtonEventPtr](addr(evt))
|
let mouseButtonUpEvent = cast[MouseButtonEventPtr](addr(evt))
|
||||||
if mouseButtonDownEvent.which == BUTTON_RIGHT and pan_start.isSome():
|
case mouseButtonUpEvent.button:
|
||||||
let xlation = newP2d(mouseButtonDownEvent.x.float32, mouseButtonDownEvent.y.float32) - pan_start.get()
|
of BUTTON_RIGHT:
|
||||||
pan_start = none[P2d]()
|
let xlation = newP2d(mouseButtonUpEvent.x.float32, mouseButtonUpEvent.y.float32) - pan_start.get()
|
||||||
uxform = uxform * xlate(xlation.x, xlation.y)
|
pan_start = none[P2d]()
|
||||||
|
uxform = uxform * xlate(xlation.x, xlation.y)
|
||||||
|
else:
|
||||||
|
discard
|
||||||
of MouseWheel:
|
of MouseWheel:
|
||||||
let mouseWheelEvent = cast[MouseWheelEventPtr](addr(evt))
|
let mouseWheelEvent = cast[MouseWheelEventPtr](addr(evt))
|
||||||
|
let zoomCenter = (block:
|
||||||
|
var x,y : cint
|
||||||
|
getMouseState(x,y)
|
||||||
|
newP2d(x.float32, y.float32)
|
||||||
|
)
|
||||||
if mouseWheelEvent.y > 0:
|
if mouseWheelEvent.y > 0:
|
||||||
uxform = uxform * scale(newP2d(windowSize.width.float32 / 2f32, windowSize.height.float32 / 2f32), 1.1f32, 1.1f32)
|
uxform = uxform * scale(zoomCenter, 1.1f32, 1.1f32)
|
||||||
else:
|
else:
|
||||||
uxform = uxform * scale(newP2d(windowSize.width.float32 / 2f32, windowSize.height.float32 / 2f32), 0.9f32, 0.9f32)
|
uxform = uxform * scale(zoomCenter, 0.9f32, 0.9f32)
|
||||||
of MouseMotion:
|
# of MouseMotion:
|
||||||
let mouseMotionEvent = cast[MouseMotionEventPtr](addr(evt))
|
# let mouseMotionEvent = cast[MouseMotionEventPtr](addr(evt))
|
||||||
let position = newP2d(mouseMotionEvent.x.float32, mouseMotionEvent.y.float32)
|
# if pan_start.isSome:
|
||||||
|
# pan = pan * xlate(newP2d(mouseMotionEvent.x.float32, mouseMotionEvent.y.float32) - pan_start.get())
|
||||||
|
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
@@ -102,8 +131,20 @@ while not quit:
|
|||||||
|
|
||||||
render.setDrawColor 127,127,127,255
|
render.setDrawColor 127,127,127,255
|
||||||
let f = min(windowSize.width / bb.width, windowSize.height / bb.height)
|
let f = min(windowSize.width / bb.width, windowSize.height / bb.height)
|
||||||
let xform = xlate(-bb.width / 2.0f32, -bb.height / 2.0f32) * scale(f, f) *
|
# let pan_xform = block:
|
||||||
xlate(windowSize.width / 2.0f32, windowSize.height / 2.0f32) * uxform
|
# if pan_start.isSome():
|
||||||
|
# x
|
||||||
|
|
||||||
|
let pan = block:
|
||||||
|
if pan_start.isSome:
|
||||||
|
var x, y : cint
|
||||||
|
getMouseState(x, y)
|
||||||
|
xlate(newP2d(x.float32, y.float32) - pan_start.get())
|
||||||
|
else:
|
||||||
|
identity[3, float32]()
|
||||||
|
|
||||||
|
xform = xlate(-bb.width / 2.0f32, -bb.height / 2.0f32) * scale(f, f) *
|
||||||
|
xlate(windowSize.width / 2.0f32, windowSize.height / 2.0f32) * uxform * pan
|
||||||
|
|
||||||
while x <= bb.width:
|
while x <= bb.width:
|
||||||
render.drawLine(newP2d(x, bb.top) * xform, newP2d(x, bb.height) * xform)
|
render.drawLine(newP2d(x, bb.top) * xform, newP2d(x, bb.height) * xform)
|
||||||
@@ -124,9 +165,6 @@ while not quit:
|
|||||||
if not freeze and current_time_sec > elapsed_time_sec:
|
if not freeze and current_time_sec > elapsed_time_sec:
|
||||||
elapsed_time_sec = current_time_sec
|
elapsed_time_sec = current_time_sec
|
||||||
next_step(current_grid[], next_grid[])
|
next_step(current_grid[], next_grid[])
|
||||||
let tmp = current_grid
|
|
||||||
current_grid = next_grid
|
|
||||||
next_grid = tmp
|
|
||||||
|
|
||||||
destroy render
|
destroy render
|
||||||
destroy window
|
destroy window
|
Reference in New Issue
Block a user