fixed bug with negative module

This commit is contained in:
2019-02-09 12:16:13 +00:00
parent d853f9f14c
commit fb7d72cf7a
3 changed files with 95 additions and 43 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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,32 +63,60 @@ 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:
of BUTTON_RIGHT:
pan_start = some(newP2d(mouseButtonDownEvent.x.float32, mouseButtonDownEvent.y.float32)) 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:
let xlation = newP2d(mouseButtonUpEvent.x.float32, mouseButtonUpEvent.y.float32) - pan_start.get()
pan_start = none[P2d]() pan_start = none[P2d]()
uxform = uxform * xlate(xlation.x, xlation.y) 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