From 5f3a00402fb9de8662bf404c5e929b106a2295ff Mon Sep 17 00:00:00 2001 From: gbrochar Date: Sun, 22 Nov 2020 18:01:12 +0100 Subject: [PATCH] n-puzzle --- Makefile | 18 ++ author | 2 + res_npuzzle-gen.py | 98 ++++++++++ source/Node.py | 105 +++++++++++ source/PriorityQueue.py | 14 ++ source/a_star.py | 64 +++++++ source/config.py | 8 + source/heuristics.py | 62 +++++++ source/main.py | 86 +++++++++ source/snail.py | 83 +++++++++ source/solvable.py | 25 +++ test/test.txt | 7 + test/test_3.txt | 5 + test/test_4.txt | 6 + test/test_5.txt | 7 + test/test_6.txt | 8 + test/test_7.txt | 9 + test/test_8.txt | 10 + test/test_9.txt | 11 ++ test/unsolvable_test_3.txt | 5 + test/unsolvable_test_4.txt | 6 + test/unsolvable_test_5.txt | 7 + test/unsolvable_test_6.txt | 8 + test/unsolvable_test_7.txt | 9 + test/unsolvable_test_8.txt | 10 + test/unsolvable_test_9.txt | 11 ++ test/visu.txt | 47 +++++ visu/main.cpp | 210 +++++++++++++++++++++ visu/ogldev_math_3d.h | 369 +++++++++++++++++++++++++++++++++++++ visu/ogldev_types.h | 35 ++++ visu/ogldev_util.cpp | 162 ++++++++++++++++ visu/ogldev_util.h | 88 +++++++++ visu/old_a | Bin 0 -> 30840 bytes visu/shader.fs | 28 +++ visu/shader.vs | 10 + 35 files changed, 1633 insertions(+) create mode 100644 Makefile create mode 100644 author create mode 100755 res_npuzzle-gen.py create mode 100755 source/Node.py create mode 100644 source/PriorityQueue.py create mode 100755 source/a_star.py create mode 100644 source/config.py create mode 100755 source/heuristics.py create mode 100755 source/main.py create mode 100644 source/snail.py create mode 100644 source/solvable.py create mode 100644 test/test.txt create mode 100644 test/test_3.txt create mode 100644 test/test_4.txt create mode 100644 test/test_5.txt create mode 100644 test/test_6.txt create mode 100644 test/test_7.txt create mode 100644 test/test_8.txt create mode 100644 test/test_9.txt create mode 100644 test/unsolvable_test_3.txt create mode 100644 test/unsolvable_test_4.txt create mode 100644 test/unsolvable_test_5.txt create mode 100644 test/unsolvable_test_6.txt create mode 100644 test/unsolvable_test_7.txt create mode 100644 test/unsolvable_test_8.txt create mode 100644 test/unsolvable_test_9.txt create mode 100644 test/visu.txt create mode 100644 visu/main.cpp create mode 100644 visu/ogldev_math_3d.h create mode 100644 visu/ogldev_types.h create mode 100644 visu/ogldev_util.cpp create mode 100644 visu/ogldev_util.h create mode 100755 visu/old_a create mode 100644 visu/shader.fs create mode 100644 visu/shader.vs diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..78cb8bb --- /dev/null +++ b/Makefile @@ -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 diff --git a/author b/author new file mode 100644 index 0000000..1c891da --- /dev/null +++ b/author @@ -0,0 +1,2 @@ +gbrochar +ygarrot diff --git a/res_npuzzle-gen.py b/res_npuzzle-gen.py new file mode 100755 index 0000000..b1e6df4 --- /dev/null +++ b/res_npuzzle-gen.py @@ -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 diff --git a/source/Node.py b/source/Node.py new file mode 100755 index 0000000..1361c25 --- /dev/null +++ b/source/Node.py @@ -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 diff --git a/source/PriorityQueue.py b/source/PriorityQueue.py new file mode 100644 index 0000000..97996c8 --- /dev/null +++ b/source/PriorityQueue.py @@ -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] diff --git a/source/a_star.py b/source/a_star.py new file mode 100755 index 0000000..88f7cf8 --- /dev/null +++ b/source/a_star.py @@ -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') diff --git a/source/config.py b/source/config.py new file mode 100644 index 0000000..79e2ce2 --- /dev/null +++ b/source/config.py @@ -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 diff --git a/source/heuristics.py b/source/heuristics.py new file mode 100755 index 0000000..aca7d80 --- /dev/null +++ b/source/heuristics.py @@ -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 diff --git a/source/main.py b/source/main.py new file mode 100755 index 0000000..cbeb28e --- /dev/null +++ b/source/main.py @@ -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() diff --git a/source/snail.py b/source/snail.py new file mode 100644 index 0000000..ae63859 --- /dev/null +++ b/source/snail.py @@ -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 diff --git a/source/solvable.py b/source/solvable.py new file mode 100644 index 0000000..f675526 --- /dev/null +++ b/source/solvable.py @@ -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) diff --git a/test/test.txt b/test/test.txt new file mode 100644 index 0000000..10940ea --- /dev/null +++ b/test/test.txt @@ -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 diff --git a/test/test_3.txt b/test/test_3.txt new file mode 100644 index 0000000..f31b5b7 --- /dev/null +++ b/test/test_3.txt @@ -0,0 +1,5 @@ +# This puzzle is solvable +3 +1 2 3 +8 6 4 +7 5 0 diff --git a/test/test_4.txt b/test/test_4.txt new file mode 100644 index 0000000..8acd321 --- /dev/null +++ b/test/test_4.txt @@ -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 diff --git a/test/test_5.txt b/test/test_5.txt new file mode 100644 index 0000000..e53298f --- /dev/null +++ b/test/test_5.txt @@ -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 diff --git a/test/test_6.txt b/test/test_6.txt new file mode 100644 index 0000000..1c1c531 --- /dev/null +++ b/test/test_6.txt @@ -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 diff --git a/test/test_7.txt b/test/test_7.txt new file mode 100644 index 0000000..fe692d2 --- /dev/null +++ b/test/test_7.txt @@ -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 diff --git a/test/test_8.txt b/test/test_8.txt new file mode 100644 index 0000000..8c06391 --- /dev/null +++ b/test/test_8.txt @@ -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 diff --git a/test/test_9.txt b/test/test_9.txt new file mode 100644 index 0000000..c0b5b73 --- /dev/null +++ b/test/test_9.txt @@ -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 diff --git a/test/unsolvable_test_3.txt b/test/unsolvable_test_3.txt new file mode 100644 index 0000000..7b59dbe --- /dev/null +++ b/test/unsolvable_test_3.txt @@ -0,0 +1,5 @@ +# This puzzle is unsolvable +3 +1 8 2 +7 4 3 +0 6 5 diff --git a/test/unsolvable_test_4.txt b/test/unsolvable_test_4.txt new file mode 100644 index 0000000..c5013ee --- /dev/null +++ b/test/unsolvable_test_4.txt @@ -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 diff --git a/test/unsolvable_test_5.txt b/test/unsolvable_test_5.txt new file mode 100644 index 0000000..97082f6 --- /dev/null +++ b/test/unsolvable_test_5.txt @@ -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 diff --git a/test/unsolvable_test_6.txt b/test/unsolvable_test_6.txt new file mode 100644 index 0000000..3407b4d --- /dev/null +++ b/test/unsolvable_test_6.txt @@ -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 diff --git a/test/unsolvable_test_7.txt b/test/unsolvable_test_7.txt new file mode 100644 index 0000000..bc394c7 --- /dev/null +++ b/test/unsolvable_test_7.txt @@ -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 diff --git a/test/unsolvable_test_8.txt b/test/unsolvable_test_8.txt new file mode 100644 index 0000000..21cf18e --- /dev/null +++ b/test/unsolvable_test_8.txt @@ -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 diff --git a/test/unsolvable_test_9.txt b/test/unsolvable_test_9.txt new file mode 100644 index 0000000..d8b1215 --- /dev/null +++ b/test/unsolvable_test_9.txt @@ -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 diff --git a/test/visu.txt b/test/visu.txt new file mode 100644 index 0000000..d059a38 --- /dev/null +++ b/test/visu.txt @@ -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 diff --git a/visu/main.cpp b/visu/main.cpp new file mode 100644 index 0000000..256aa3f --- /dev/null +++ b/visu/main.cpp @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include "ogldev_math_3d.h" +#include +#include +#include + +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); +} diff --git a/visu/ogldev_math_3d.h b/visu/ogldev_math_3d.h new file mode 100644 index 0000000..f8401c5 --- /dev/null +++ b/visu/ogldev_math_3d.h @@ -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 . +*/ + +#ifndef MATH_3D_H +#define MATH_3D_H + +#include +#ifdef WIN32 +#define _USE_MATH_DEFINES +#include +#else +#include +#endif + +#include +#include +#include + +#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 */ + diff --git a/visu/ogldev_types.h b/visu/ogldev_types.h new file mode 100644 index 0000000..c43df49 --- /dev/null +++ b/visu/ogldev_types.h @@ -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 . +*/ + +#ifndef OGLDEV_TYPES_H +#define OGLDEV_TYPES_H + +#ifndef WIN32 +#include +#endif + +#include + +typedef unsigned int uint; +typedef unsigned short ushort; +typedef unsigned char uchar; +typedef int32_t i32; +typedef uint32_t u32; + +#endif /* OGLDEV_TYPES_H */ + diff --git a/visu/ogldev_util.cpp b/visu/ogldev_util.cpp new file mode 100644 index 0000000..41ca06c --- /dev/null +++ b/visu/ogldev_util.cpp @@ -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 . + +*/ + +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif + +#include +#include +#include +#include +#include + +#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 +} diff --git a/visu/ogldev_util.h b/visu/ogldev_util.h new file mode 100644 index 0000000..5d41c81 --- /dev/null +++ b/visu/ogldev_util.h @@ -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 . +*/ + +#ifndef OGLDEV_UTIL_H +#define OGLDEV_UTIL_H + +#ifndef WIN32 +#include +#endif +#include +#include +#include +#include +#include +#include +#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 */ + diff --git a/visu/old_a b/visu/old_a new file mode 100755 index 0000000000000000000000000000000000000000..5d9684ebdbb1d9e6190686bf3527d65dc275e1f2 GIT binary patch literal 30840 zcmeHwdwf*Ywf{-NKtxOe0)k>4P&82qnLHr8E_pD?L=%W4!5G0|NG32k$%J`epxOpw zlyOX(+G6ch?~T{ii+XR1t*@d&5app&QCsl&X?)KBl?XnfqWOK-e$4DSnd48}-{X1ZOgX64UxH_dRnS_ADf+6!mR zn3bRH^JM3;a+7`1Eni&6Qlk16u3+-<;0Ysnc-HUh-ud)5^X|APc*47CL{e|V<{e`p zn}v&#C!hAE0y%v|%AC=uO}(Qvtz)V-H8n-srzLM0n>ykKraK#Yb8yYWMa^I#t|DB; zxXN&q&Ees}2AqiMg{b9c()-Jhh*Ia1Z~`r7&_+upnFx-CC_ zv-Ittb$oEkq~m>qOk`(;f&M0gbVnKJI}Plo0XO5)hfxOhpEc;Ge}{oY`R_BZ zb0PH2`b5E74e%)j<=SXqKgl4Un+^0A8R-8K^*C0WthH71+{)+ZQRH)+maets<3{u8^liFy*9&~F4u6BCJ84*c#tZu$I{lA?ojY{+2G}A0^yzSqu+y)@{~+vC>+roo ze~S)(UEoDJyg=CL)#1AYo~rZDCBn{1o&L8%f2$6^Qs~#~@CyXqqr(pfJNtFGhWX2C zcfe0GmORZ~QCnqia(bPsT|U3lTU%A?_Ov={9jn|<&2C@a;%T+}{0^_*Zr4`3%borj zzt`2ennz0<$<^xeLpR_r^*SAX=jE=}CeO7DC=0mVHH}`Uvz4(`4p(cX$J54`3dCCE z^0m1g>#ICX&M3xjn%vH^Kx<tiay5Q}1OMuw=&OWK^R z<&{+G94IaFI<77DdL8R2MycEB@Jd?haeKTJp}f+1Ih)oY0$kyCUJJYAm}O3{-`QU5 zhbvYw8$wL(S>u2+UF%{u8BWYUFB9jkyE>_Xsq#DERAa% zUc2AxaQS@|jn*0mKCH7GZD>DD)}@!$=no_^@0}aV5qD1c6%GTjHeZ?!N1OKxThLCnPMmfFSR*&5+dmP$yleW&++J;W$Z`N8IZiqB=Lg;DD*Lq!k zjBrlB-__#uG&eccYpnh>Y7bhoh{RLC=#AEiah{qujXg-2@+zK6EqI0iX-AeZR5~%H z(a5*T=i_oftxZ~aX{kLAgLrvmMMg^40t7TuU?t zpMoW`@9`=4W{#;M?o)8#;mauT$!vXw5V}SR8Rw)f#T)_2C{X%-&n?kCY0yOo9^K-i zJ0AEQSxy|15aUaHx5$9ljH~+m^_UE%YR51iqCoOPiac

l9j1`YI|<(T>49#V^A3 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 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); +} diff --git a/visu/shader.vs b/visu/shader.vs new file mode 100644 index 0000000..e5b7171 --- /dev/null +++ b/visu/shader.vs @@ -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); +}