n-puzzle
This commit is contained in:
parent
fb540006b2
commit
5f3a00402f
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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]
|
|
@ -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')
|
|
@ -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
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -0,0 +1,5 @@
|
||||||
|
# This puzzle is solvable
|
||||||
|
3
|
||||||
|
1 2 3
|
||||||
|
8 6 4
|
||||||
|
7 5 0
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,5 @@
|
||||||
|
# This puzzle is unsolvable
|
||||||
|
3
|
||||||
|
1 8 2
|
||||||
|
7 4 3
|
||||||
|
0 6 5
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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 */
|
||||||
|
|
Binary file not shown.
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue