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