This commit is contained in:
gbrochar 2020-11-22 18:01:12 +01:00
parent fb540006b2
commit 5f3a00402f
35 changed files with 1633 additions and 0 deletions

18
Makefile Normal file
View File

@ -0,0 +1,18 @@
all: visu_rule
greedy:
@./res_npuzzle-gen.py -s -i 36 5 > test/test.txt
@head -1 test/test.txt
@./source/main.py -g test/test.txt
run:
@./res_npuzzle-gen.py -s -i 30 4 > test/test.txt
@head -1 test/test.txt
@./source/main.py test/test.txt
visu_rule:
@./res_npuzzle-gen.py -s -i 50000 3 > test/test.txt
@head -1 test/test.txt
@./source/main.py test/test.txt
@g++ visu/main.cpp visu/ogldev_util.cpp -lglut -lOpenGL -lGLEW
@./a.out

2
author Normal file
View File

@ -0,0 +1,2 @@
gbrochar
ygarrot

98
res_npuzzle-gen.py Executable file
View File

@ -0,0 +1,98 @@
#!/usr/bin/env python
import sys
import argparse
import random
def make_puzzle(s, solvable, iterations):
def swap_empty(p):
idx = p.index(0)
poss = []
if idx % s > 0:
poss.append(idx - 1)
if idx % s < s - 1:
poss.append(idx + 1)
if idx / s > 0 and idx - s >= 0:
poss.append(idx - s)
if idx / s < s - 1:
poss.append(idx + s)
swi = random.choice(poss)
p[idx] = p[swi]
p[swi] = 0
p = make_goal(s)
for i in range(iterations):
swap_empty(p)
if not solvable:
if p[0] == 0 or p[1] == 0:
p[-1], p[-2] = p[-2], p[-1]
else:
p[0], p[1] = p[1], p[0]
return p
def make_goal(s):
ts = s*s
puzzle = [-1 for i in range(ts)]
cur = 1
x = 0
ix = 1
y = 0
iy = 0
while True:
puzzle[x + y*s] = cur
if cur == 0:
break
cur += 1
if x + ix == s or x + ix < 0 or (ix != 0 and puzzle[x + ix + y*s] != -1):
iy = ix
ix = 0
elif y + iy == s or y + iy < 0 or (iy != 0 and puzzle[x + (y+iy)*s] != -1):
ix = -iy
iy = 0
x += ix
y += iy
if cur == s*s:
cur = 0
return puzzle
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("size", type=int, help="Size of the puzzle's side. Must be >3.")
parser.add_argument("-s", "--solvable", action="store_true", default=False, help="Forces generation of a solvable puzzle. Overrides -u.")
parser.add_argument("-u", "--unsolvable", action="store_true", default=False, help="Forces generation of an unsolvable puzzle")
parser.add_argument("-i", "--iterations", type=int, default=10000, help="Number of passes")
args = parser.parse_args()
random.seed()
if args.solvable and args.unsolvable:
print "Can't be both solvable AND unsolvable, dummy !"
sys.exit(1)
if args.size < 3:
print "Can't generate a puzzle with size lower than 2. It says so in the help. Dummy."
sys.exit(1)
if not args.solvable and not args.unsolvable:
solv = random.choice([True, False])
elif args.solvable:
solv = True
elif args.unsolvable:
solv = False
s = args.size
puzzle = make_puzzle(s, solvable=solv, iterations=args.iterations)
w = len(str(s*s))
print "# This puzzle is %s" % ("solvable" if solv else "unsolvable")
print "%d" % s
for y in range(s):
for x in range(s):
print "%s" % (str(puzzle[x + y*s]).rjust(w)),
print

105
source/Node.py Executable file
View File

@ -0,0 +1,105 @@
#!/usr/bin/env python3
import config
from heuristics import *
from math import sqrt
import numpy as np
import copy
def LEFT(i):
return i - 1
def RIGHT(i):
return i + 1
def UP(i, puzzle_size):
return i - puzzle_size
def DOWN(i, puzzle_size):
return i + puzzle_size
def chunks(l, n):
return [l[i:i+n] for i in range(0, len(l), n)]
class Node(object):
def __init__(self, h = 0, g = 0, f = 0, empty_case_index = 0, grid = []):
self.h = h
self.g = g
self.f = f
self.index = empty_case_index
self.right = None
self.left = None
self.up = None
self.down = None
self.size = len(grid)
self.sqrt = int(sqrt(len(grid)))
self.child = None
self.parents = []
self.grid = grid
def __eq__(self, other):
return self.f == other.f
def __lt__(self, other):
return self.f < other.f
def __str__(self):
lst = np.matrix(chunks(self.grid, int(sqrt(len(self.grid)))))
return str(lst)
def set_parent(self):
self.left = self.swap_left()
self.right = self.swap_right()
self.up = self.swap_up()
self.down = self.swap_down()
self.parents = [x for x in [self.right, self.left, self.up, self.down] if x is not None]
for node in self.parents:
node.h = config.heuristic_fn(node.grid)
node.size = len(node.grid)
node.sqrt = int(sqrt(len(node.grid)))
node.child = self
node.g = self.g + 1
node.f = config.calc_fScore(node.h, node.g)
def swap_left(self):
return self.tile_swap_2_index(LEFT(self.index), self.is_valid_horizontal_move)
def swap_right(self):
return self.tile_swap_2_index(RIGHT(self.index), self.is_valid_horizontal_move)
def swap_down(self):
return self.tile_swap_2_index(DOWN(self.index, self.sqrt), self.is_valid_vertical_move)
def swap_up(self):
return self.tile_swap_2_index(UP(self.index, self.sqrt), self.is_valid_vertical_move)
def is_valid_vertical_move(self, new_index):
return new_index >= 0 and new_index < self.size
def is_valid_horizontal_move(self, new_index):
index = self.index
i = index - new_index
if (new_index < 0 or new_index > self.size):
return False
if (index is 0 and i is -1):
return True
if (index is 1):
return True
if (((index + 1) % self.sqrt) is 0 and i is -1):
return False
if (((index + 1) % self.sqrt) is 1 and i is +1):
return False
return True
def tile_swap_2_index(self, new_index, valid_move_fn):
index = self.index
if not valid_move_fn(new_index):
return None
lst = copy.deepcopy(self.grid)
lst[index], lst[new_index] = lst[new_index], lst[index]
node = Node()
node.grid = lst
node.index = new_index
return node

14
source/PriorityQueue.py Normal file
View File

@ -0,0 +1,14 @@
import heapq
class PriorityQueue:
def __init__(self):
self.elements = []
def empty(self):
return len(self.elements) == 0
def put(self, item):
heapq.heappush(self.elements, (item.f, item))
def get(self):
return heapq.heappop(self.elements)[1]

64
source/a_star.py Executable file
View File

@ -0,0 +1,64 @@
#!/usr/bin/env python3
#f score is the sum of the cost to reach that node and the heuristic value of that node.
import config
from Node import *
import numpy as np
from PriorityQueue import *
def chunks(l, n):
return [l[i:i+n] for i in range(0, len(l), n)]
def print_recc(f, elem):
if (elem.child):
print_recc(f, elem.child)
print(np.matrix(chunks(elem.grid, elem.sqrt)))
print()
f.write(' '.join(['{: >2}'.format(x) for x in elem.grid]))
f.write('\n')
def print_for_visu(process):
f = open("test/visu.txt", "w")
print_recc(f, process)
f.close()
def a_star_impl(grid, goal, heuristic_ptr):
heuristic_ptr= config.heuristic_fn
start = Node(h = heuristic_ptr(grid), empty_case_index = grid.index(0), grid = grid)
open_set = PriorityQueue()
closed_set = PriorityQueue()
open_set.put(start)
time_complexity = 0
size_complexity = 1
while open_set:
process = open_set.get()
if process.h is 0 or process.grid is goal:
print("Ordered Sequence:")
print_for_visu(process)
print("Number of moves: {}\n"
"Time Complexity: {}\n"
"Size Complexity: {}"
.format(process.g, time_complexity, size_complexity))
return
closed_set.put(process)
process.set_parent()
for node in process.parents:
in_close = node.grid in [x.grid for (p, x) in closed_set.elements]
in_open = node.grid in [x.grid for (p, x) in open_set.elements]
if in_close:
continue
new_g = process.g + 1
if not in_open:
node.g = new_g
open_set.put(node)
size_complexity += 1
else:
if (node.g > new_g):
node.g = new_g
node.f = config.calc_fScore(node.h, node.g)
time_complexity += 1
raise ValueError('No Path Found')

8
source/config.py Normal file
View File

@ -0,0 +1,8 @@
import heuristics
is_greedy = False
goal = []
heuristic_fn = None
def calc_fScore(h, g):
return h if is_greedy else g + h

62
source/heuristics.py Executable file
View File

@ -0,0 +1,62 @@
#!/usr/bin/env python3
import math
import config
def hamming_distance(grid):
h = 0
for i, v in enumerate(grid):
if i != config.goal.index(v):
h += 1
return h
def manhattan_distance(grid):
h = 0
size = int(math.sqrt(len(grid)))
for i, v in enumerate(grid):
if i != config.goal.index(v):
curr_col = i % size
curr_row = i // size
target_col = (config.goal.index(v)) % size
target_row = (config.goal.index(v)) // size
h += abs(target_col - curr_col) + abs(target_row - curr_row)
return h
def linear_conflict_manhattan_distance(grid):
h = manhattan_distance(grid)
size = int(math.sqrt(len(grid)))
for i, v in enumerate(grid):
if i != config.goal.index(v):
curr_col = i % size
curr_row = i // size
target_col = (config.goal.index(v)) % size
target_row = (config.goal.index(v)) // size
#move left
if target_col - curr_col > 0:
while (curr_col < target_col):
i += 1
curr_col = i % size
if (grid[v] - 1) // size == target_row:
h += 1
#move right
elif target_col - curr_col < 0:
while (curr_col > target_col):
i -= 1
curr_col = i % size
if (grid[v] - 1) // size == target_row:
h += 1
#move up
if target_row - curr_row > 0:
while (curr_row < target_row):
i += 3
curr_row = i // size
if (grid[i] - 1) % size == target_col:
h += 1
#move down
elif target_row - curr_row < 0:
while (curr_row > target_row):
i -= 3
curr_row = i // size
if (grid[i] - 1) % size == target_col:
h += 1
return h

86
source/main.py Executable file
View File

@ -0,0 +1,86 @@
#!/usr/bin/env python3
import argparse
import config
import re
import heuristics
from solvable import *
from snail import *
from a_star import a_star_impl
def make_goal(s):
ts = s*s
puzzle = [-1 for i in range(ts)]
cur = 1
x = 0
ix = 1
y = 0
iy = 0
while True:
puzzle[x + y*s] = cur
if cur == 0:
break
cur += 1
if x + ix == s or x + ix < 0 or (ix != 0 and puzzle[x + ix + y*s] != -1):
iy = ix
ix = 0
elif y + iy == s or y + iy < 0 or (iy != 0 and puzzle[x + (y+iy)*s] != -1):
ix = -iy
iy = 0
x += ix
y += iy
if cur == s*s:
cur = 0
return puzzle
def parse_file(file_name):
dict = {}
with open(file_name) as f:
content = f.read()
without_hash = re.sub('#.*', '', content).strip()
puzzles = without_hash.split()
try:
puzzle_size = int(puzzles[0])
except:
exit("Invalid size: " + puzzles[0])
puzzles = [ int(puzzle) for puzzle in puzzles[1:]]
without_hash = without_hash.splitlines()[1:]
for line in without_hash:
line_length = len(line.split())
if (line_length is not puzzle_size):
exit("Invalid value in puzzle")
return puzzles, puzzle_size
def parse_arg():
parser = argparse.ArgumentParser(description='Faster N-Puzzle you have ever seen')
parser.add_argument("-g", "--greedy", default=False, action="store_true",
help="Are You a Greedy Bastard?")
parser.add_argument("-a", "--algorithm", dest="heuristic",
default="manhattan_distance",
choices=["hamming_distance", "manhattan_distance", "linear_conflict_manhattan_distance"],
help="choose algorithm function")
parser.add_argument("path", type=str, default="none", help="input file name")
args = parser.parse_args()
config.is_greedy = args.greedy
config.heuristic_fn = getattr(heuristics, args.heuristic)
print("heuristic choosen: {}".format(args.heuristic))
return args.path
def main():
grid, size = parse_file(parse_arg())
config.goal = make_goal(size)
for tile in config.goal:
if tile not in grid:
exit("Parsing Error")
if not solvable(snail_to_ordered_by_ygarrot(grid, config.goal, size)):
exit("Error : N-puzzle not solvable !")
print("N-puzzle is solvable !")
#check if input puzzle go from 0 to N - 1
a_star_impl(grid, config.goal, config.heuristic_fn)
if __name__ == '__main__':
main()

83
source/snail.py Normal file
View File

@ -0,0 +1,83 @@
import numpy as np
from math import sqrt
def chunks(l):
n = int(sqrt(len(l)))
return np.matrix([l[i:i+n] for i in range(0, len(l), n)])
def snail_to_ordered_by_ygarrot(snail, goal, size):
'''
snail_to_ordered and ordered_to_snail functions are
historical curiosities left over from earlier days before
the advent of N-puzzle solving.
'''
toto = []
ordered = [i + 1 for i in range(size * size)]
ordered[-1] = 0
for i in range(len(ordered)):
toto.insert(i, snail[goal.index(ordered[i])])
return toto
# def snail_to_ordered(grid):
# size = int(math.sqrt(len(grid)))
# grid_ret = grid.copy()
# for i in range(size // 2):
# for j in range(size - 1 - 2 * i):
# index = size + j
# for k in range(i):
# index += (4 * (size - 2 * (k + 1))) + 2
# grid_ret[index] = grid[size * (j + i + 2) - i - 1]
# for i in range((size - 1) // 2 + (1 - size % 2)):
# for j in range(size - 1 - 2 * i):
# index = size + (size - 1) + j
# for k in range(i):
# index += (4 * (size - 2 * (k + 1)))
# grid_ret[index] = grid[size * (size - i) - (2 + i) - j]
# for i in range((size - 1) // 2):
# for j in range(size - 2 - 2 * i):
# index = size + 2 * (size - 1) + j
# for k in range(i):
# index += (4 * (size - 2 * (k + 1))) - 2
# grid_ret[index] = grid[size * (size - (2 + i)) - size * j + i]
# for i in range((size - 2) // 2 + size % 2):
# for j in range(size - 2 - 2 * i):
# index = size + 2 * (size - 1) + (size - 2) + j
# for k in range(i):
# index += (4 * (size - 2 * (k + 1))) - 4
# grid_ret[index] = grid[size * (i + 1) + (i + 1) + j]
# return grid_ret
# def ordered_to_snail(grid):
# size = int(math.sqrt(len(grid)))
# grid_ret = grid.copy()
# for i in range(size // 2):
# for j in range(size - 1 - 2 * i):
# index = size + j
# for k in range(i):
# index += (4 * (size - 2 * (k + 1))) + 2
# grid_ret[size * (j + i + 2) - i - 1] = grid[index]
# for i in range((size - 1) // 2):
# for j in range(size - 1 - 2 * i):
# index = size + (size - 1) + j
# for k in range(i):
# index += (4 * (size - 2 * (k + 1)))
# grid_ret[size * (size - i) - (2 + i) - j] = grid[index]
# for i in range((size - 1) // 2):
# for j in range(size - 2 - 2 * i):
# index = size + 2 * (size - 1) + j
# for k in range(i):
# index += (4 * (size - 2 * (k + 1))) - 2
# grid_ret[size * (size - (2 + i)) - size * j + i] = grid[index]
# for i in range((size - 2) // 2):
# for j in range(size - 2 - 2 * i):
# index = size + 2 * (size - 1) + (size - 2) + j
# for k in range(i):
# index += (4 * (size - 2 * (k + 1))) - 4
# grid_ret[size * (i + 1) + (i + 1) + j] = grid[index]
# if size % 2:
# grid_ret[len(grid_ret) // 2] = 0
# else:
# grid_ret[len(grid_ret) // 2 + (size - 4) // 2 + 1] = 0
# return grid_ret

25
source/solvable.py Normal file
View File

@ -0,0 +1,25 @@
import math
def get_inversions(grid):
inversions = 0
for i in range(len(grid)):
if grid[i] is 0:
continue
for j in range(i + 1, len(grid)):
if grid[j] is not 0 and grid[i] > grid[j]:
inversions += 1
return inversions
def odd(n):
return (n % 2) != 0
def solvable(grid):
"""Return True if the puzzle is solvable or False if it's not."""
size = int(math.sqrt(len(grid)))
inversions = get_inversions(grid)
if odd(size):
return not odd(inversions)
else:
if odd(grid.index(0)):
return not odd(inversions)
return odd(inversions)

7
test/test.txt Normal file
View File

@ -0,0 +1,7 @@
# This puzzle is solvable
5
2 18 3 4 5
1 0 19 20 6
24 14 23 22 7
17 16 15 21 8
13 12 11 10 9

5
test/test_3.txt Normal file
View File

@ -0,0 +1,5 @@
# This puzzle is solvable
3
1 2 3
8 6 4
7 5 0

6
test/test_4.txt Normal file
View File

@ -0,0 +1,6 @@
# This puzzle is solvable
4
1 2 4 5
12 14 0 3
11 13 15 6
10 9 8 7

7
test/test_5.txt Normal file
View File

@ -0,0 +1,7 @@
# This puzzle is solvable
5
1 2 3 4 5
16 17 18 19 6
15 23 20 21 7
12 0 22 24 8
14 13 11 10 9

8
test/test_6.txt Normal file
View File

@ -0,0 +1,8 @@
# This puzzle is solvable
6
1 2 3 5 24 6
20 21 23 4 0 7
19 32 22 34 25 8
18 31 33 35 26 9
17 30 29 13 27 10
16 15 14 12 28 11

9
test/test_7.txt Normal file
View File

@ -0,0 +1,9 @@
# This puzzle is solvable
7
1 2 3 5 27 6 7
24 25 26 4 28 29 8
23 40 41 42 43 9 0
22 39 48 46 31 30 10
21 38 47 45 44 32 11
20 37 36 35 34 33 12
19 18 17 16 15 14 13

10
test/test_8.txt Normal file
View File

@ -0,0 +1,10 @@
# This puzzle is solvable
8
1 2 3 4 5 6 7 8
28 29 30 31 32 33 34 9
27 48 49 50 51 52 35 10
26 47 60 62 63 53 36 11
25 46 59 61 54 55 37 12
24 45 58 57 56 40 38 13
23 44 43 42 18 41 39 14
22 21 20 19 17 16 0 15

11
test/test_9.txt Normal file
View File

@ -0,0 +1,11 @@
# This puzzle is solvable
9
1 2 3 4 5 6 7 8 9
32 33 34 35 36 37 38 39 10
31 56 57 58 59 60 61 40 11
30 55 72 73 74 75 62 41 12
29 54 71 80 78 76 63 42 13
28 53 70 79 77 66 64 43 14
27 52 69 68 65 47 46 44 15
26 51 50 49 67 21 19 45 16
25 24 23 22 48 20 0 18 17

View File

@ -0,0 +1,5 @@
# This puzzle is unsolvable
3
1 8 2
7 4 3
0 6 5

View File

@ -0,0 +1,6 @@
# This puzzle is unsolvable
4
3 1 14 4
12 13 2 5
11 9 15 6
0 10 8 7

View File

@ -0,0 +1,7 @@
# This puzzle is unsolvable
5
2 1 3 4 5
16 17 18 6 8
15 24 20 19 21
14 23 22 0 10
13 12 11 9 7

View File

@ -0,0 +1,8 @@
# This puzzle is unsolvable
6
2 1 3 4 5 6
20 22 0 23 24 7
19 21 33 34 25 8
31 32 29 35 26 9
18 30 28 13 27 10
17 16 15 14 12 11

View File

@ -0,0 +1,9 @@
# This puzzle is unsolvable
7
2 1 3 4 5 6 7
24 25 26 27 28 29 8
23 41 42 43 30 31 9
22 40 39 48 44 32 10
21 38 47 46 45 33 11
20 37 36 35 34 0 12
19 18 17 16 15 14 13

View File

@ -0,0 +1,10 @@
# This puzzle is unsolvable
8
2 1 3 4 5 6 8 9
28 29 30 31 32 33 34 7
27 48 49 50 51 0 35 10
26 47 60 61 53 52 36 11
25 46 59 63 62 54 37 12
24 45 58 57 56 55 38 13
23 44 43 42 41 40 39 14
22 21 20 19 18 17 16 15

View File

@ -0,0 +1,11 @@
# This puzzle is unsolvable
9
2 1 3 4 5 6 7 8 9
32 33 34 35 36 37 38 39 10
31 56 57 73 58 60 61 40 11
30 55 72 80 59 75 62 41 12
29 54 71 79 74 76 63 42 13
28 53 70 68 78 77 64 43 14
27 52 50 67 0 66 65 44 15
26 51 49 69 48 47 46 45 16
25 24 23 22 21 20 19 18 17

47
test/visu.txt Normal file
View File

@ -0,0 +1,47 @@
2 18 3 4 5 1 0 19 20 6 24 14 23 22 7 17 16 15 21 8 13 12 11 10 9
2 0 3 4 5 1 18 19 20 6 24 14 23 22 7 17 16 15 21 8 13 12 11 10 9
0 2 3 4 5 1 18 19 20 6 24 14 23 22 7 17 16 15 21 8 13 12 11 10 9
1 2 3 4 5 0 18 19 20 6 24 14 23 22 7 17 16 15 21 8 13 12 11 10 9
1 2 3 4 5 24 18 19 20 6 0 14 23 22 7 17 16 15 21 8 13 12 11 10 9
1 2 3 4 5 24 18 19 20 6 14 0 23 22 7 17 16 15 21 8 13 12 11 10 9
1 2 3 4 5 24 18 19 20 6 14 23 0 22 7 17 16 15 21 8 13 12 11 10 9
1 2 3 4 5 24 18 19 20 6 14 23 22 0 7 17 16 15 21 8 13 12 11 10 9
1 2 3 4 5 24 18 19 0 6 14 23 22 20 7 17 16 15 21 8 13 12 11 10 9
1 2 3 4 5 24 18 0 19 6 14 23 22 20 7 17 16 15 21 8 13 12 11 10 9
1 2 3 4 5 24 0 18 19 6 14 23 22 20 7 17 16 15 21 8 13 12 11 10 9
1 2 3 4 5 24 23 18 19 6 14 0 22 20 7 17 16 15 21 8 13 12 11 10 9
1 2 3 4 5 24 23 18 19 6 14 16 22 20 7 17 0 15 21 8 13 12 11 10 9
1 2 3 4 5 24 23 18 19 6 14 16 22 20 7 17 15 0 21 8 13 12 11 10 9
1 2 3 4 5 24 23 18 19 6 14 16 0 20 7 17 15 22 21 8 13 12 11 10 9
1 2 3 4 5 24 23 18 19 6 14 0 16 20 7 17 15 22 21 8 13 12 11 10 9
1 2 3 4 5 24 23 18 19 6 14 15 16 20 7 17 0 22 21 8 13 12 11 10 9
1 2 3 4 5 24 23 18 19 6 14 15 16 20 7 0 17 22 21 8 13 12 11 10 9
1 2 3 4 5 24 23 18 19 6 0 15 16 20 7 14 17 22 21 8 13 12 11 10 9
1 2 3 4 5 24 23 18 19 6 15 0 16 20 7 14 17 22 21 8 13 12 11 10 9
1 2 3 4 5 24 0 18 19 6 15 23 16 20 7 14 17 22 21 8 13 12 11 10 9
1 2 3 4 5 24 18 0 19 6 15 23 16 20 7 14 17 22 21 8 13 12 11 10 9
1 2 3 4 5 24 18 16 19 6 15 23 0 20 7 14 17 22 21 8 13 12 11 10 9
1 2 3 4 5 24 18 16 19 6 15 0 23 20 7 14 17 22 21 8 13 12 11 10 9
1 2 3 4 5 24 18 16 19 6 15 17 23 20 7 14 0 22 21 8 13 12 11 10 9
1 2 3 4 5 24 18 16 19 6 15 17 23 20 7 14 22 0 21 8 13 12 11 10 9
1 2 3 4 5 24 18 16 19 6 15 17 0 20 7 14 22 23 21 8 13 12 11 10 9
1 2 3 4 5 24 18 0 19 6 15 17 16 20 7 14 22 23 21 8 13 12 11 10 9
1 2 3 4 5 24 0 18 19 6 15 17 16 20 7 14 22 23 21 8 13 12 11 10 9
1 2 3 4 5 24 17 18 19 6 15 0 16 20 7 14 22 23 21 8 13 12 11 10 9
1 2 3 4 5 24 17 18 19 6 15 16 0 20 7 14 22 23 21 8 13 12 11 10 9
1 2 3 4 5 24 17 18 19 6 15 16 23 20 7 14 22 0 21 8 13 12 11 10 9
1 2 3 4 5 24 17 18 19 6 15 16 23 20 7 14 0 22 21 8 13 12 11 10 9
1 2 3 4 5 24 17 18 19 6 15 16 23 20 7 0 14 22 21 8 13 12 11 10 9
1 2 3 4 5 24 17 18 19 6 0 16 23 20 7 15 14 22 21 8 13 12 11 10 9
1 2 3 4 5 24 17 18 19 6 16 0 23 20 7 15 14 22 21 8 13 12 11 10 9
1 2 3 4 5 24 17 18 19 6 16 23 0 20 7 15 14 22 21 8 13 12 11 10 9
1 2 3 4 5 24 17 0 19 6 16 23 18 20 7 15 14 22 21 8 13 12 11 10 9
1 2 3 4 5 24 0 17 19 6 16 23 18 20 7 15 14 22 21 8 13 12 11 10 9
1 2 3 4 5 0 24 17 19 6 16 23 18 20 7 15 14 22 21 8 13 12 11 10 9
1 2 3 4 5 16 24 17 19 6 0 23 18 20 7 15 14 22 21 8 13 12 11 10 9
1 2 3 4 5 16 24 17 19 6 15 23 18 20 7 0 14 22 21 8 13 12 11 10 9
1 2 3 4 5 16 24 17 19 6 15 23 18 20 7 14 0 22 21 8 13 12 11 10 9
1 2 3 4 5 16 24 17 19 6 15 0 18 20 7 14 23 22 21 8 13 12 11 10 9
1 2 3 4 5 16 0 17 19 6 15 24 18 20 7 14 23 22 21 8 13 12 11 10 9
1 2 3 4 5 16 17 0 19 6 15 24 18 20 7 14 23 22 21 8 13 12 11 10 9
1 2 3 4 5 16 17 18 19 6 15 24 0 20 7 14 23 22 21 8 13 12 11 10 9

210
visu/main.cpp Normal file
View File

@ -0,0 +1,210 @@
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "ogldev_math_3d.h"
#include <iostream>
#include <sstream>
#include <cmath>
GLuint VBO;
GLuint gridLocation;
GLuint nLocation;
GLuint timeLocation;
const char* pVSFileName = "visu/shader.vs";
const char* pFSFileName = "visu/shader.fs";
const char* pGridFileName = "./test/visu.txt";
static void RenderSceneCB()
{
glClear(GL_COLOR_BUFFER_BIT);
string grid_file;
if (!ReadFile(pGridFileName, grid_file))
exit(1);
static float time = 0.0f;
time += 0.03;
stringstream ssin(grid_file);
string token;
string token2;
int garbage[1024];
int i = 0;
int j = 0;
int x = 0, y = 0;
while (std::getline(ssin, token, '\n'))
{
j = 0;
stringstream ssin2(token);
while (ssin2.good())
{
ssin2 >> garbage[j];
j++;
if (j > x)
x = j;
}
i++;
if (i > y)
y = i;
}
int n = (int)sqrt(x);
int grid[y][x];
stringstream ssin3(grid_file);
i = 0;
while (ssin3.good() && i < x * y)
{
ssin3 >> grid[(int)(i / x)][i % x];
i++;
}
glUniform1f(timeLocation, time);
glUniform1i(nLocation, n);
if ((int)time < sizeof(grid) / sizeof(*grid))
glUniform1iv(gridLocation, n * n, grid[(int)time]);
else
exit(1);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
// first GL_POINT or GL_TRIANGLES
// second start of draw
// third number of vertices to draw
glDrawArrays(GL_QUADS, 0, 4);
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
static void InitializeGlutCallbacks(void)
{
glutDisplayFunc(RenderSceneCB);
glutIdleFunc(RenderSceneCB);
}
static void CreateVertexBuffer(void)
{
Vector3f Vertices[4];
Vertices[0] = Vector3f(-1.0f, -1.0f, 0.0f);
Vertices[1] = Vector3f(1.0f, -1.0f, 0.0f);
Vertices[2] = Vector3f(1.0f, 1.0f, 0.0f);
Vertices[3] = Vector3f(-1.0f, 1.0f, 0.0f);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}
static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
GLuint ShaderObj = glCreateShader(ShaderType);
if (ShaderObj == 0)
{
fprintf(stderr, "Error creating shader type %d\n", ShaderType);
exit(0);
}
const GLchar* p[1];
p[0] = pShaderText;
GLint Lengths[1];
Lengths[0] = strlen(pShaderText);
glShaderSource(ShaderObj, 1, p, Lengths);
glCompileShader(ShaderObj);
GLint success;
glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
if (!success)
{
GLchar InfoLog[1024];
glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
exit(1);
}
glAttachShader(ShaderProgram, ShaderObj);
}
static void CompileShaders()
{
GLuint ShaderProgram = glCreateProgram();
if (ShaderProgram == 0)
{
fprintf(stderr, "Error creating shader program\n");
exit(1);
}
string vs;
string fs;
if (!ReadFile(pVSFileName, vs))
exit(1);
if (!ReadFile(pFSFileName, fs))
exit(1);
AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);
GLint Success = 0;
GLchar ErrorLog[1024] = { 0 };
glLinkProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
if (Success == 0)
{
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Error linking shader program : '%s'\n", ErrorLog);
exit(1);
}
glValidateProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
if (!Success)
{
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Invalid shader program '%s'\n", ErrorLog);
exit(1);
}
glUseProgram(ShaderProgram);
gridLocation = glGetUniformLocation(ShaderProgram, "grid");
assert(gridLocation != 0xFFFFFFFF);
nLocation = glGetUniformLocation(ShaderProgram, "n");
assert(nLocation != 0xFFFFFFFF);
timeLocation = glGetUniformLocation(ShaderProgram, "time");
assert(timeLocation != 0xFFFFFFFF);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(800, 600);
glutCreateWindow("N-Puzzle");
//glutFullScreen();
InitializeGlutCallbacks();
// Must be done after glut is initialized !
GLenum res = glewInit();
if (res != GLEW_OK)
{
fprintf(stderr, "Error : '%s'\n", glewGetErrorString(res));
return (1);
}
printf("GL version: %s\n", glGetString(GL_VERSION));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
CreateVertexBuffer();
CompileShaders();
glutMainLoop();
return (0);
}

369
visu/ogldev_math_3d.h Normal file
View File

@ -0,0 +1,369 @@
/*
Copyright 2010 Etay Meiri
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MATH_3D_H
#define MATH_3D_H
#include <stdio.h>
#ifdef WIN32
#define _USE_MATH_DEFINES
#include <cmath>
#else
#include <math.h>
#endif
#include <assimp/vector3.h>
#include <assimp/matrix3x3.h>
#include <assimp/matrix4x4.h>
#include "ogldev_util.h"
#define ToRadian(x) (float)(((x) * M_PI / 180.0f))
#define ToDegree(x) (float)(((x) * 180.0f / M_PI))
float RandomFloat();
struct Vector2i
{
int x;
int y;
};
struct Vector2f
{
float x;
float y;
Vector2f()
{
}
Vector2f(float _x, float _y)
{
x = _x;
y = _y;
}
};
struct Vector3f
{
float x;
float y;
float z;
Vector3f() {}
Vector3f(float _x, float _y, float _z)
{
x = _x;
y = _y;
z = _z;
}
Vector3f(const float* pFloat)
{
x = pFloat[0];
y = pFloat[0];
z = pFloat[0];
}
Vector3f(float f)
{
x = y = z = f;
}
Vector3f& operator+=(const Vector3f& r)
{
x += r.x;
y += r.y;
z += r.z;
return *this;
}
Vector3f& operator-=(const Vector3f& r)
{
x -= r.x;
y -= r.y;
z -= r.z;
return *this;
}
Vector3f& operator*=(float f)
{
x *= f;
y *= f;
z *= f;
return *this;
}
operator const float*() const
{
return &(x);
}
Vector3f Cross(const Vector3f& v) const;
Vector3f& Normalize();
void Rotate(float Angle, const Vector3f& Axis);
void Print() const
{
printf("(%.02f, %.02f, %.02f)", x, y, z);
}
};
struct Vector4f
{
float x;
float y;
float z;
float w;
Vector4f()
{
}
Vector4f(float _x, float _y, float _z, float _w)
{
x = _x;
y = _y;
z = _z;
w = _w;
}
void Print(bool endl = true) const
{
printf("(%.02f, %.02f, %.02f, %.02f)", x, y, z, w);
if (endl) {
printf("\n");
}
}
Vector3f to3f() const
{
Vector3f v(x, y, z);
return v;
}
};
inline Vector3f operator+(const Vector3f& l, const Vector3f& r)
{
Vector3f Ret(l.x + r.x,
l.y + r.y,
l.z + r.z);
return Ret;
}
inline Vector3f operator-(const Vector3f& l, const Vector3f& r)
{
Vector3f Ret(l.x - r.x,
l.y - r.y,
l.z - r.z);
return Ret;
}
inline Vector3f operator*(const Vector3f& l, float f)
{
Vector3f Ret(l.x * f,
l.y * f,
l.z * f);
return Ret;
}
inline Vector4f operator/(const Vector4f& l, float f)
{
Vector4f Ret(l.x / f,
l.y / f,
l.z / f,
l.w / f);
return Ret;
}
struct PersProjInfo
{
float FOV;
float Width;
float Height;
float zNear;
float zFar;
};
struct OrthoProjInfo
{
float r; // right
float l; // left
float b; // bottom
float t; // top
float n; // z near
float f; // z far
};
struct Quaternion
{
float x, y, z, w;
Quaternion(float _x, float _y, float _z, float _w);
void Normalize();
Quaternion Conjugate();
Vector3f ToDegrees();
};
class Matrix4f
{
public:
float m[4][4];
Matrix4f()
{
}
// constructor from Assimp matrix
Matrix4f(const aiMatrix4x4& AssimpMatrix)
{
m[0][0] = AssimpMatrix.a1; m[0][1] = AssimpMatrix.a2; m[0][2] = AssimpMatrix.a3; m[0][3] = AssimpMatrix.a4;
m[1][0] = AssimpMatrix.b1; m[1][1] = AssimpMatrix.b2; m[1][2] = AssimpMatrix.b3; m[1][3] = AssimpMatrix.b4;
m[2][0] = AssimpMatrix.c1; m[2][1] = AssimpMatrix.c2; m[2][2] = AssimpMatrix.c3; m[2][3] = AssimpMatrix.c4;
m[3][0] = AssimpMatrix.d1; m[3][1] = AssimpMatrix.d2; m[3][2] = AssimpMatrix.d3; m[3][3] = AssimpMatrix.d4;
}
Matrix4f(const aiMatrix3x3& AssimpMatrix)
{
m[0][0] = AssimpMatrix.a1; m[0][1] = AssimpMatrix.a2; m[0][2] = AssimpMatrix.a3; m[0][3] = 0.0f;
m[1][0] = AssimpMatrix.b1; m[1][1] = AssimpMatrix.b2; m[1][2] = AssimpMatrix.b3; m[1][3] = 0.0f;
m[2][0] = AssimpMatrix.c1; m[2][1] = AssimpMatrix.c2; m[2][2] = AssimpMatrix.c3; m[2][3] = 0.0f;
m[3][0] = 0.0f ; m[3][1] = 0.0f ; m[3][2] = 0.0f ; m[3][3] = 1.0f;
}
Matrix4f(float a00, float a01, float a02, float a03,
float a10, float a11, float a12, float a13,
float a20, float a21, float a22, float a23,
float a30, float a31, float a32, float a33)
{
m[0][0] = a00; m[0][1] = a01; m[0][2] = a02; m[0][3] = a03;
m[1][0] = a10; m[1][1] = a11; m[1][2] = a12; m[1][3] = a13;
m[2][0] = a20; m[2][1] = a21; m[2][2] = a22; m[2][3] = a23;
m[3][0] = a30; m[3][1] = a31; m[3][2] = a32; m[3][3] = a33;
}
void SetZero()
{
ZERO_MEM(m);
}
Matrix4f Transpose() const
{
Matrix4f n;
for (unsigned int i = 0 ; i < 4 ; i++) {
for (unsigned int j = 0 ; j < 4 ; j++) {
n.m[i][j] = m[j][i];
}
}
return n;
}
inline void InitIdentity()
{
m[0][0] = 1.0f; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = 0.0f;
m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f; m[1][3] = 0.0f;
m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = 0.0f;
m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f;
}
inline Matrix4f operator*(const Matrix4f& Right) const
{
Matrix4f Ret;
for (unsigned int i = 0 ; i < 4 ; i++) {
for (unsigned int j = 0 ; j < 4 ; j++) {
Ret.m[i][j] = m[i][0] * Right.m[0][j] +
m[i][1] * Right.m[1][j] +
m[i][2] * Right.m[2][j] +
m[i][3] * Right.m[3][j];
}
}
return Ret;
}
Vector4f operator*(const Vector4f& v) const
{
Vector4f r;
r.x = m[0][0]* v.x + m[0][1]* v.y + m[0][2]* v.z + m[0][3]* v.w;
r.y = m[1][0]* v.x + m[1][1]* v.y + m[1][2]* v.z + m[1][3]* v.w;
r.z = m[2][0]* v.x + m[2][1]* v.y + m[2][2]* v.z + m[2][3]* v.w;
r.w = m[3][0]* v.x + m[3][1]* v.y + m[3][2]* v.z + m[3][3]* v.w;
return r;
}
operator const float*() const
{
return &(m[0][0]);
}
void Print() const
{
for (int i = 0 ; i < 4 ; i++) {
printf("%f %f %f %f\n", m[i][0], m[i][1], m[i][2], m[i][3]);
}
}
float Determinant() const;
Matrix4f& Inverse();
void InitScaleTransform(float ScaleX, float ScaleY, float ScaleZ);
void InitRotateTransform(float RotateX, float RotateY, float RotateZ);
void InitRotateTransform(const Quaternion& quat);
void InitTranslationTransform(float x, float y, float z);
void InitCameraTransform(const Vector3f& Target, const Vector3f& Up);
void InitPersProjTransform(const PersProjInfo& p);
void InitOrthoProjTransform(const OrthoProjInfo& p);
};
Quaternion operator*(const Quaternion& l, const Quaternion& r);
Quaternion operator*(const Quaternion& q, const Vector3f& v);
#endif /* MATH_3D_H */

35
visu/ogldev_types.h Normal file
View File

@ -0,0 +1,35 @@
/*
Copyright 2011 Etay Meiri
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OGLDEV_TYPES_H
#define OGLDEV_TYPES_H
#ifndef WIN32
#include <unistd.h>
#endif
#include <cstdint>
typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef int32_t i32;
typedef uint32_t u32;
#endif /* OGLDEV_TYPES_H */

162
visu/ogldev_util.cpp Normal file
View File

@ -0,0 +1,162 @@
/*
Copyright 2014 Etay Meiri
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <fstream>
#ifdef WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdarg.h>
#include "ogldev_util.h"
bool ReadFile(const char* pFileName, string& outFile)
{
ifstream f(pFileName);
bool ret = false;
if (f.is_open()) {
string line;
while (getline(f, line)) {
outFile.append(line);
outFile.append("\n");
}
f.close();
ret = true;
}
else {
OGLDEV_FILE_ERROR(pFileName);
}
return ret;
}
#ifdef WIN32
char* ReadBinaryFile(const char* pFileName, int& size)
{
HANDLE f = CreateFileA(pFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (f == INVALID_HANDLE_VALUE) {
OGLDEV_FILE_ERROR(pFileName);
return false;
}
size = GetFileSize(f, NULL);
if (size == INVALID_FILE_SIZE) {
OGLDEV_ERROR("Invalid file size %s\n", pFileName);
return false;
}
// wip for tutorial51
assert(0);
return true;
}
#else
char* ReadBinaryFile(const char* pFileName, int& size)
{
int f = open(pFileName, O_RDONLY);
if (f == -1) {
OGLDEV_ERROR("Error opening '%s': %s\n", pFileName, strerror(errno));
return NULL;
}
struct stat stat_buf;
int error = stat(pFileName, &stat_buf);
if (error) {
OGLDEV_ERROR("Error getting file stats: %s\n", strerror(errno));
return NULL;
}
size = stat_buf.st_size;
char* p = (char*)malloc(size);
assert(p);
int read_len = read(f, p, size);
if (read_len != size) {
OGLDEV_ERROR("Error reading file: %s\n", strerror(errno));
return NULL;
}
close(f);
return p;
}
#endif
void OgldevError(const char* pFileName, uint line, const char* format, ...)
{
char msg[1000];
va_list args;
va_start(args, format);
VSNPRINTF(msg, sizeof(msg), format, args);
va_end(args);
#ifdef WIN32
char msg2[1000];
_snprintf_s(msg2, sizeof(msg2), "%s:%d: %s", pFileName, line, msg);
MessageBoxA(NULL, msg2, NULL, 0);
#else
fprintf(stderr, "%s:%d - %s", pFileName, line, msg);
#endif
}
void OgldevFileError(const char* pFileName, uint line, const char* pFileError)
{
#ifdef WIN32
char msg[1000];
_snprintf_s(msg, sizeof(msg), "%s:%d: unable to open file `%s`", pFileName, line, pFileError);
MessageBoxA(NULL, msg, NULL, 0);
#else
fprintf(stderr, "%s:%d: unable to open file `%s`\n", pFileName, line, pFileError);
#endif
}
long long GetCurrentTimeMillis()
{
#ifdef WIN32
return GetTickCount();
#else
timeval t;
gettimeofday(&t, NULL);
long long ret = t.tv_sec * 1000 + t.tv_usec / 1000;
return ret;
#endif
}

88
visu/ogldev_util.h Normal file
View File

@ -0,0 +1,88 @@
/*
Copyright 2014 Etay Meiri
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OGLDEV_UTIL_H
#define OGLDEV_UTIL_H
#ifndef WIN32
#include <unistd.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <string.h>
#include <assert.h>
#include "ogldev_types.h"
using namespace std;
bool ReadFile(const char* fileName, string& outFile);
char* ReadBinaryFile(const char* pFileName, int& size);
void OgldevError(const char* pFileName, uint line, const char* msg, ... );
void OgldevFileError(const char* pFileName, uint line, const char* pFileError);
#define OGLDEV_ERROR0(msg) OgldevError(__FILE__, __LINE__, msg)
#define OGLDEV_ERROR(msg, ...) OgldevError(__FILE__, __LINE__, msg, __VA_ARGS__)
#define OGLDEV_FILE_ERROR(FileError) OgldevFileError(__FILE__, __LINE__, FileError);
#define ZERO_MEM(a) memset(a, 0, sizeof(a))
#define ZERO_MEM_VAR(var) memset(&var, 0, sizeof(var))
#define ARRAY_SIZE_IN_ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifdef WIN32
#define SNPRINTF _snprintf_s
#define VSNPRINTF vsnprintf_s
#define RANDOM rand
#define SRANDOM srand((unsigned)time(NULL))
#else
#define SNPRINTF snprintf
#define VSNPRINTF vsnprintf
#define RANDOM random
#define SRANDOM srandom(getpid())
#endif
#define INVALID_UNIFORM_LOCATION 0xffffffff
#define INVALID_OGL_VALUE 0xffffffff
#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }
#define GLExitIfError \
{ \
GLenum Error = glGetError(); \
\
if (Error != GL_NO_ERROR) { \
printf("OpenGL error in %s:%d: 0x%x\n", __FILE__, __LINE__, Error); \
exit(0); \
} \
}
#define GLCheckError() (glGetError() == GL_NO_ERROR)
long long GetCurrentTimeMillis();
#define ASSIMP_LOAD_FLAGS (aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | aiProcess_JoinIdenticalVertices)
#endif /* OGLDEV_UTIL_H */

BIN
visu/old_a Executable file

Binary file not shown.

28
visu/shader.fs Normal file
View File

@ -0,0 +1,28 @@
#version 330
uniform float time;
uniform int n;
vec2 resolution = vec2(800, 600);
uniform int grid[1024];
void main()
{
vec2 uv = (gl_FragCoord.xy-0.5*resolution.xy)/resolution.y;
vec3 col = vec3(0);
vec2 guv = fract(vec2(uv + 0.5 + 1. / float(n)) * float(n));
vec2 id = floor(vec2(uv + 0.5 + 1. / float(n)) * float(n));
float m = 0.;
if (id.x > 0. && id.x <= float(n) && id.y > 0. && id.y <= float(n))
{
col.gb = smoothstep(1., float(n), abs(mod(id + time, float(n)) - float(n) / 2.) + 1.);
float d = length(guv - 0.5);
float dist = length(id) * 10.;
float r = mix(.0001, .2, (sin(time) * 0.2 + 1.2) * float(grid[int(float(n) - id.y) * n + int(id.x - 1.)]) / float(n * n));
m += 1 - smoothstep(r, r * .1, d);
}
col.xyz += vec3(m);
gl_FragColor = vec4(col,1.0);
}

10
visu/shader.vs Normal file
View File

@ -0,0 +1,10 @@
#version 330
layout (location = 0) in vec3 Position;
uniform float gScale;
void main()
{
gl_Position = vec4(Position.x, Position.y, Position.z, 1.0);
}