From 16d5aa5fecbb040b3594a63a9ad7c85df659a5dd Mon Sep 17 00:00:00 2001
From: Arthur CHEVALIER <arthur.chevalier@inria.fr>
Date: Fri, 13 Oct 2017 12:15:39 +0200
Subject: [PATCH] feat(opengl): Added symbolic matrix visualizer fix(src):
 Fixing some windows compatibility issues

---
 .gitignore                                    |   1 +
 plugins/MatrixVisualizer/CMakeLists.txt       |   2 -
 plugins/MatrixVisualizer/Common/Node.cpp      |   6 -
 plugins/MatrixVisualizer/Common/Node.hpp      |  13 -
 plugins/MatrixVisualizer/Common/QuadTree.cpp  | 245 +++++++++++++++++-
 plugins/MatrixVisualizer/Common/QuadTree.hpp  |  31 ++-
 .../MatrixVisualizer/Formats/SymbolMatrix.cpp |  17 +-
 .../MatrixVisualizer/Formats/SymbolMatrix.hpp |  41 ++-
 plugins/MatrixVisualizer/Helper.cpp           |   1 +
 plugins/MatrixVisualizer/Helper.hpp           |  17 +-
 plugins/MatrixVisualizer/MatrixVisualizer.cpp |   9 +-
 .../Parsers/Readers/Pastix.cpp                |  76 +++---
 .../Windows/MatrixGLWidget.cpp                |  56 ++--
 .../Windows/MatrixGLWidget.hpp                |  13 +-
 .../MatrixVisualizer/Windows/MatrixWindow.cpp |  10 +-
 src/render/Render_alternate.cpp               |   2 +
 src/render/Render_opengl.cpp                  |   4 +
 src/render/render_stats_opengl.cpp            |   4 +
 src/render/render_stats_svg.hpp               |   4 +
 src/render/vbo.cpp                            |  10 +
 20 files changed, 452 insertions(+), 110 deletions(-)
 delete mode 100644 plugins/MatrixVisualizer/Common/Node.cpp
 delete mode 100644 plugins/MatrixVisualizer/Common/Node.hpp

diff --git a/.gitignore b/.gitignore
index 60425f6b..606359f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,6 +54,7 @@ CTestTestfile.cmake
 plugins/*/*_autogen
 src/*_autogen
 build*
+.vs
 
 # Generated files
 src/common/ViteConfig.hpp
diff --git a/plugins/MatrixVisualizer/CMakeLists.txt b/plugins/MatrixVisualizer/CMakeLists.txt
index c1972fb7..86003ace 100644
--- a/plugins/MatrixVisualizer/CMakeLists.txt
+++ b/plugins/MatrixVisualizer/CMakeLists.txt
@@ -43,7 +43,6 @@ set (MATRIXVISUALIZER_hdrs
     Windows/MatrixGLWidget.hpp
 
     Common/QuadTree.hpp
-    Common/Node.hpp
 )
 
 set (MATRIXVISUALIZER_srcs
@@ -59,7 +58,6 @@ set (MATRIXVISUALIZER_srcs
     Windows/MatrixGLWidget.cpp
 
     Common/QuadTree.cpp
-    Common/Node.cpp
 )
 
 set (MATRIXVISUALIZER_forms_tmp
diff --git a/plugins/MatrixVisualizer/Common/Node.cpp b/plugins/MatrixVisualizer/Common/Node.cpp
deleted file mode 100644
index 4e330d3b..00000000
--- a/plugins/MatrixVisualizer/Common/Node.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "Node.hpp"
-
-Node::Node()
-{
-    m_children = nullptr;
-}
diff --git a/plugins/MatrixVisualizer/Common/Node.hpp b/plugins/MatrixVisualizer/Common/Node.hpp
deleted file mode 100644
index cf41a522..00000000
--- a/plugins/MatrixVisualizer/Common/Node.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef NODE_HPP
-#define NODE_HPP
-
-class Node
-{
-public:
-    Node();
-
-private:
-    Node*   m_children;
-};
-
-#endif
diff --git a/plugins/MatrixVisualizer/Common/QuadTree.cpp b/plugins/MatrixVisualizer/Common/QuadTree.cpp
index fa5083a1..5f9e84e1 100644
--- a/plugins/MatrixVisualizer/Common/QuadTree.cpp
+++ b/plugins/MatrixVisualizer/Common/QuadTree.cpp
@@ -1,18 +1,255 @@
 #include "QuadTree.hpp"
 
-QuadTree::QuadTree()
+#include "../Helper.hpp"
+
+bool QuadTreeRecur(symbol_matrix_t* matrix, Node* actual, int cutsRemaining, int startColumn, int endColumn, int startRow, int endRow);
+
+QuadTree::QuadTree(Node* root, symbol_matrix_t* matrix)
+	: m_root(root)
+	, m_matrix(matrix)
+{
+	// Fill correct colors
+	move(0.f, 1.f, 0.f, 1.f);
+}
+
+void destroyRecur(Node* actual)
 {
+	int i;
 
+	if (actual == nullptr)
+		return;
+
+	for (i = 0; i < actual->m_nbChildren; ++i)
+		destroyRecur(actual->m_children[i]);
+
+	delete actual;
+}
+
+QuadTree::~QuadTree()
+{
+	// Destroy quadtree
+	destroyRecur(m_root);
+
+	symbol_matrix_deinit(m_matrix);
+	delete m_matrix;
 }
 
 GLfloat QuadTree::getColor(int x, int y)
 {
-    return (float)(rand() % 100) / 100.f;
+    return m_colors[x][y];
+}
+
+#include <iostream>
+
+void QuadTree::move(float xStart, float xEnd, float yStart, float yEnd)
+{
+	int i, j;
+
+	int startCblk = xStart * m_matrix->m_cblknbr;
+	int endCbkl = startCblk + (xEnd - xStart) * m_matrix->m_cblknbr;
+
+	int diffCblk = endCbkl - startCblk;
+
+	int startRow = yStart * m_matrix->m_rowsnbr;
+	int endRow = startRow + (yEnd - yStart) * m_matrix->m_rowsnbr;
+
+	int diffRow = endRow - startRow;
+
+	symbol_cblk_t* cblks = m_matrix->m_cblktab;
+	symbol_blok_t* bloks = m_matrix->m_bloktab;
+
+	for (i = 0; i < DEFAULT_LEVEL_POWER_2; ++i)
+	{
+		for (j = 0; j < DEFAULT_LEVEL_POWER_2; ++j)
+		{
+			m_colors[i][j] = 0.f;
+		}
+	}
+
+	float xCoeff = 256.f / (float)diffCblk;
+	float yCoeff = 256.f / (float)diffRow;
+
+	for (i = startCblk; i < endCbkl; ++i)
+	{
+		int firstBlokNum = cblks[i].m_bloknum;
+		int nextBlokNum = (i + 1 != m_matrix->m_cblknbr ? cblks[i + 1].m_bloknum : m_matrix->m_cblknbr);
+
+		int x = (float)i * xCoeff;
+
+		for (j = firstBlokNum; j < nextBlokNum; ++j)
+		{
+			symbol_blok_t* blok = &(bloks[j]);
+
+			if (blok->m_frownum > startRow && blok->m_frownum <= endRow)
+			{
+				int y = (float)blok->m_frownum * yCoeff;
+
+				m_colors[x][y] = 1.0f;
+			}
+		}
+	}
+}
+
+size_t GetMemoryLoadRecur(Node* actual)
+{
+	int i;
+
+	size_t size = sizeof(Node);
+
+	for (i = 0; i < actual->m_nbChildren; ++i)
+	{
+		size += GetMemoryLoadRecur(actual->m_children[i]);
+	}
+
+	return size;
+}
+
+size_t GetMemoryLoad(Node* root)
+{
+	size_t result = GetMemoryLoadRecur(root);
+
+	return result;
 }
 
 QuadTree* QuadTree::constructFromSymbolMatrix(symbol_matrix_t* matrix)
 {
-    QuadTree* tree = new QuadTree();
+	Node* root = new Node;
+
+	// Construct quad tree
+	Helper::log(LogStatus::MESSAGE, "Starting building QuadTree");
+
+	root->m_id = 1;
+
+	QuadTreeRecur(matrix, root, QuadTree::DEFAULT_LEVEL, 0, matrix->m_cblknbr, 0, matrix->m_rowsnbr);
+
+	Helper::log(LogStatus::MESSAGE, "End building QuadTree");
 
-    return tree;
+	size_t memory_load = GetMemoryLoad(root) + sizeof(QuadTree);
+
+	Helper::log(LogStatus::MESSAGE, "QuadTree takes %.2lf %s of memory !",
+		MEMORY_WRITE(memory_load), MEMORY_UNIT_WRITE(memory_load));
+
+    return new QuadTree(root, matrix);
 }
+
+bool QuadTreeRecur(symbol_matrix_t* matrix, Node* actual, int cutsRemaining, int startColumn, int endColumn, int startRow, int endRow)
+{
+	int midCblk = (endColumn - startColumn) / 2;
+	int midRow = (endRow - startRow) / 2;
+
+	actual->m_startCblk = startColumn;
+	actual->m_endCblk = endColumn;
+	actual->m_startRow = startRow;
+	actual->m_endRow = endRow;
+
+	if (cutsRemaining == 0)
+	{
+		symbol_cblk_t* cblks = matrix->m_cblktab;
+		symbol_blok_t* bloks = matrix->m_bloktab;
+		int i, j;
+
+		for (i = startColumn; i <= endColumn; ++i)
+		{
+			int firstBlokNum = cblks[i].m_bloknum;
+			int nextBlokNum = (i + 1 != matrix->m_cblknbr ? cblks[i + 1].m_bloknum : matrix->m_cblknbr);
+
+			for (j = firstBlokNum; j < nextBlokNum; ++j)
+			{
+				symbol_blok_t* blok = &(bloks[j]);
+
+				if (blok->m_frownum >= startRow && blok->m_frownum <= endRow)
+				{
+					if (!(blok->m_flags & BLOK_FLAG_IN_TREE))
+					{
+						blok->m_localization = actual->m_id;
+						blok->m_flags |= BLOK_FLAG_IN_TREE;
+					}
+				}
+			}
+		}
+
+		return true;
+	}
+	else
+	{
+		int nbValidNode = 0;
+
+		Node* first = new Node;
+
+		first->m_id = actual->m_id << 2;
+		if (!QuadTreeRecur(matrix, first, cutsRemaining - 1, startColumn, startColumn + midCblk, startRow, startRow + midRow))
+		{
+			delete first;
+			first = nullptr;
+		}
+		else
+			nbValidNode++;
+
+		Node* second = new Node;
+
+		second->m_id = (actual->m_id << 2) | 1;
+		if (!QuadTreeRecur(matrix, second, cutsRemaining - 1, startColumn, startColumn + midCblk, startRow, startRow + midRow))
+		{
+			delete second;
+			second = nullptr;
+		}
+		else
+			nbValidNode++;
+
+		Node* third = new Node;
+
+		third->m_id = (actual->m_id << 2) | 2;
+		if (!QuadTreeRecur(matrix, third, cutsRemaining - 1, startColumn, startColumn + midCblk, startRow, startRow + midRow))
+		{
+			delete third;
+			third = nullptr;
+		}
+		else
+			nbValidNode++;
+
+		Node* fourth = new Node;
+
+		fourth->m_id = (actual->m_id << 2) | 3;
+		if (!QuadTreeRecur(matrix, fourth, cutsRemaining - 1, startColumn, startColumn + midCblk, startRow, startRow + midRow))
+		{
+			delete fourth;
+			fourth = nullptr;
+		}
+		else
+			nbValidNode++;
+
+		if (nbValidNode > 0)
+		{
+			actual->m_nbChildren = nbValidNode;
+			actual->m_children = (Node**)malloc(nbValidNode * sizeof(Node*));
+
+			Node** tmp = actual->m_children;
+			
+			if (first != nullptr)
+			{
+				*tmp = first;
+				tmp++;
+			}
+
+			if (second != nullptr)
+			{
+				*tmp = second;
+				tmp++;
+			}
+
+			if (third != nullptr)
+			{
+				*tmp = third;
+				tmp++;
+			}
+
+			if (fourth != nullptr)
+			{
+				*tmp = fourth;
+				tmp++;
+			}
+		}
+
+		return nbValidNode > 0;
+	}
+}
\ No newline at end of file
diff --git a/plugins/MatrixVisualizer/Common/QuadTree.hpp b/plugins/MatrixVisualizer/Common/QuadTree.hpp
index ace1a8ee..933f401e 100644
--- a/plugins/MatrixVisualizer/Common/QuadTree.hpp
+++ b/plugins/MatrixVisualizer/Common/QuadTree.hpp
@@ -4,19 +4,42 @@
 #include <QtOpenGL/QtOpenGL>
 
 #include "../Formats/SymbolMatrix.hpp"
-#include "Node.hpp"
+
+typedef struct Node
+{
+	uint32_t		m_id;
+	int32_t			m_nbChildren;
+
+	// Position
+	int32_t			m_startCblk;
+	int32_t			m_endCblk;
+	int32_t			m_startRow;
+	int32_t			m_endRow;
+
+	struct Node**	m_children;
+} Node;
 
 class QuadTree
 {
 public:
-    QuadTree();
+	static const int DEFAULT_LEVEL = 8;
+	static const int DEFAULT_LEVEL_POWER_2 = 256;
+
+public:
+    QuadTree(Node* root, symbol_matrix_t* matrix);
+	~QuadTree();
 
     GLfloat getColor(int x, int y);
 
-    static QuadTree*    constructFromSymbolMatrix(symbol_matrix_t* matrix);
+	void move(float xStart, float xEnd, float yStart, float yEnd);
+
+    static QuadTree* constructFromSymbolMatrix(symbol_matrix_t* matrix);
 
 private:
-    Node    m_root;
+    Node*				m_root;
+	symbol_matrix_t*	m_matrix;
+
+	GLfloat				m_colors[DEFAULT_LEVEL_POWER_2][DEFAULT_LEVEL_POWER_2];
 };
 
 #endif
diff --git a/plugins/MatrixVisualizer/Formats/SymbolMatrix.cpp b/plugins/MatrixVisualizer/Formats/SymbolMatrix.cpp
index d9045caa..6dcf8c5f 100644
--- a/plugins/MatrixVisualizer/Formats/SymbolMatrix.cpp
+++ b/plugins/MatrixVisualizer/Formats/SymbolMatrix.cpp
@@ -16,20 +16,6 @@ static inline int32_t imax(int32_t a, int32_t b)
 }
 
 /* Macros */
-#define MEMORY_WRITE(mem) ( ((mem) < 1<<10) ?                           \
-                            ( (double)(mem) ) :                         \
-                            ( ( (mem) < 1<<20 ) ?                       \
-                              ( (double)(mem)/(double)(1<<10) ) :       \
-                              ( ((mem) < 1<<30 ) ?                      \
-                                ( (double)(mem)/(double)(1<<20) ) :     \
-                                ( (double)(mem)/(double)(1<<30) ))))
-#define MEMORY_UNIT_WRITE(mem) (((mem) < 1<<10) ?                       \
-                                "o" :                                   \
-                                ( ( (mem) < 1<<20 ) ?                   \
-                                  "Ko" :                                \
-                                  ( ( (mem) < 1<<30 ) ?                 \
-                                    "Mo" :                              \
-                                    "Go" )))
 #define memFree(ptr) free((void*)(ptr))
 #define memFree_null(ptr) do			\
 	{					\
@@ -40,7 +26,6 @@ static inline int32_t imax(int32_t a, int32_t b)
 void symbol_matrix_init(symbol_matrix_t* matrix)
 {
     memset(matrix, 0, sizeof(symbol_matrix_t));
-    matrix->m_schurfcol = -1;
 
     return;
 }
@@ -59,6 +44,8 @@ void symbol_matrix_deinit(symbol_matrix_t* matrix)
     return;
 }
 
+#include <iostream>
+
 void symbol_matrix_print_stats(symbol_matrix_t* matrix)
 {
     symbol_cblk_t* cblk;
diff --git a/plugins/MatrixVisualizer/Formats/SymbolMatrix.hpp b/plugins/MatrixVisualizer/Formats/SymbolMatrix.hpp
index 054280b2..e2228886 100644
--- a/plugins/MatrixVisualizer/Formats/SymbolMatrix.hpp
+++ b/plugins/MatrixVisualizer/Formats/SymbolMatrix.hpp
@@ -5,10 +5,10 @@
 
 typedef struct symbol_cblk_s
 {
-    int32_t     m_fcolumn;
-    int32_t     m_lcolnum;
-    int32_t     m_bloknum;
-    int32_t     m_flags;
+    int32_t     m_fcolumn;	// First column index
+    int32_t     m_lcolnum;	// Last column index (inclusive)
+    int32_t     m_bloknum;	// First blok in column
+    int32_t     m_flags;	// Flags
 } symbol_cblk_t;
 
 #define CBLK_FLAG_2D    1
@@ -16,12 +16,35 @@ typedef struct symbol_cblk_s
 
 typedef struct symbol_blok_s
 {
-    int32_t     m_frownum;
-    int32_t     m_lrownum;
-    int32_t     m_lcblknm;  // local
-    int32_t     m_fcblknm;  // facing
+    int32_t     m_frownum;	// First row index
+    int32_t     m_lrownum;	// Last row index
+    int32_t     m_lcblknm;  // Local column blok
+    int32_t     m_fcblknm;  // Facing column blok
+
+	uint32_t	m_localization;	// Localization
+	int32_t		m_flags;
 } symbol_blok_t;
 
+#define BLOK_FLAG_IN_TREE	1
+
+/*
+
+How localization works ?
+=> See Z-curve identification
+
+We use Z-curve to ID the quadtree nodes and we flip the bit of the level.
+For example if we are in the third level of quadtreefication and we have the ID 2:
+
+0000 0000 0001 0010
+             ^   ^
+             |   ID of the node
+			 Bit flipped for the level
+
+With this technique we can store a 32 bits localization to allow 15 levels of details
+and know the parents of any node due to the Z-curve :D
+
+*/
+
 typedef struct symbol_matrix_s
 {
     int32_t         m_baseval;
@@ -30,7 +53,7 @@ typedef struct symbol_matrix_s
     int32_t         m_cblknbr;
     int32_t         m_bloknbr;
     int32_t         m_nodenbr;
-    int32_t         m_schurfcol;
+    int32_t         m_rowsnbr;
 
     symbol_cblk_t*  m_cblktab;
     symbol_blok_t*  m_bloktab;
diff --git a/plugins/MatrixVisualizer/Helper.cpp b/plugins/MatrixVisualizer/Helper.cpp
index 89d723a8..ff92080a 100644
--- a/plugins/MatrixVisualizer/Helper.cpp
+++ b/plugins/MatrixVisualizer/Helper.cpp
@@ -1,6 +1,7 @@
 #include "Helper.hpp"
 
 #include <cstdarg>
+#include <iostream>
 
 #include "MatrixVisualizer.hpp"
 
diff --git a/plugins/MatrixVisualizer/Helper.hpp b/plugins/MatrixVisualizer/Helper.hpp
index 1f1dc34e..fa8bf8bd 100644
--- a/plugins/MatrixVisualizer/Helper.hpp
+++ b/plugins/MatrixVisualizer/Helper.hpp
@@ -5,11 +5,26 @@ enum LogStatus
 {
     MESSAGE,
     WARNING,
-    ERROR,
+    FATAL,
 
     COUNT
 };
 
+#define MEMORY_WRITE(mem) ( ((mem) < 1<<10) ?                           \
+                            ( (double)(mem) ) :                         \
+                            ( ( (mem) < 1<<20 ) ?                       \
+                              ( (double)(mem)/(double)(1<<10) ) :       \
+                              ( ((mem) < 1<<30 ) ?                      \
+                                ( (double)(mem)/(double)(1<<20) ) :     \
+                                ( (double)(mem)/(double)(1<<30) ))))
+#define MEMORY_UNIT_WRITE(mem) (((mem) < 1<<10) ?                       \
+                                "o" :                                   \
+                                ( ( (mem) < 1<<20 ) ?                   \
+                                  "Ko" :                                \
+                                  ( ( (mem) < 1<<30 ) ?                 \
+                                    "Mo" :                              \
+                                    "Go" )))
+
 namespace Helper
 {
     void log(LogStatus status, const char* format, ...);
diff --git a/plugins/MatrixVisualizer/MatrixVisualizer.cpp b/plugins/MatrixVisualizer/MatrixVisualizer.cpp
index 2dbc2804..c2471a8a 100644
--- a/plugins/MatrixVisualizer/MatrixVisualizer.cpp
+++ b/plugins/MatrixVisualizer/MatrixVisualizer.cpp
@@ -15,6 +15,9 @@ Matrix_visualizer::Matrix_visualizer() {
     s_plugin = this;
 
     this->connect_widgets();
+
+	// For windows dev (pc: orange)
+	this->line_edit_symbol->setText("C:\\Data\\Lessons\\2017-2018\\PFA\\Matrix\\symb_lap40.txt");
 }
 
 Matrix_visualizer* Matrix_visualizer::Get()
@@ -57,7 +60,7 @@ void Matrix_visualizer::execute(){
 
     if (symbol_filepath.size() == 0)
     {
-        Helper::log(LogStatus::ERROR, "Empty filepath for symbol matrix file...");
+		Helper::log(LogStatus::FATAL, "Empty filepath for symbol matrix file...");
         return;
     }
 
@@ -97,8 +100,8 @@ void Matrix_visualizer::log(LogStatus status, const char* format, va_list ap)
     case WARNING:
         previous_text += "Warning: ";
         break;
-    case ERROR:
-        previous_text += "ERROR: ";
+    case FATAL:
+        previous_text += "FATAL: ";
         break;
     default:
         break;
diff --git a/plugins/MatrixVisualizer/Parsers/Readers/Pastix.cpp b/plugins/MatrixVisualizer/Parsers/Readers/Pastix.cpp
index ef15c686..94143015 100644
--- a/plugins/MatrixVisualizer/Parsers/Readers/Pastix.cpp
+++ b/plugins/MatrixVisualizer/Parsers/Readers/Pastix.cpp
@@ -1,48 +1,41 @@
 #include "Pastix.hpp"
 
 #include "../../Helper.hpp"
+#include <iostream>
 #include <cstdlib>
 #include <ctype.h>
 
 int pastix_read_symbol(FILE* stream, symbol_matrix_t* matrix)
 {
     int32_t versval;
-    int32_t i, j;
     int32_t cblknum;
     int32_t bloknum;
 
-    if ((pastix_read_int(stream, &versval) +
-         pastix_read_int(stream, &matrix->m_cblknbr) +
-         pastix_read_int(stream, &matrix->m_bloknbr) +
-         pastix_read_int(stream, &matrix->m_nodenbr) +
-         pastix_read_int(stream, &matrix->m_baseval) != 5) ||
+	int32_t result = 0;
+
+	result += pastix_read_int(stream, &versval);
+	result += pastix_read_int(stream, &matrix->m_cblknbr);
+	result += pastix_read_int(stream, &matrix->m_bloknbr);
+	result += pastix_read_int(stream, &matrix->m_nodenbr);
+	result += pastix_read_int(stream, &matrix->m_baseval);
+
+	if ((result != 5) ||
         (versval < 0)                                      ||
         (versval > 1)                                      ||
         (matrix->m_bloknbr < matrix->m_cblknbr)            ||
         (matrix->m_nodenbr < matrix->m_cblknbr))
     {
-        Helper::log(LogStatus::ERROR, "Loading symbol file %s, bad header !");
+        Helper::log(LogStatus::FATAL, "Loading symbol file, bad header !");
+
         return 1;
     }
 
-    Helper::log(LogStatus::MESSAGE,
-        "Loaded header:\n"
-        "  Version:             %10d\n"
-        "  Number of cblk:      %10d\n"
-        "  Number of blok:      %10d\n"
-        "  Number of nodes:     %10d\n"
-        "  Base value:          %10d\n",
-        versval,
-        matrix->m_cblknbr, matrix->m_bloknbr,
-        matrix->m_nodenbr, matrix->m_baseval
-    );
-
     matrix->m_cblktab = (symbol_cblk_t*)malloc((matrix->m_cblknbr + 1) * sizeof(symbol_cblk_t));
     matrix->m_bloktab = (symbol_blok_t*)malloc(matrix->m_bloknbr * sizeof(symbol_blok_t));
 
     if (matrix->m_cblktab == nullptr || matrix->m_bloktab == nullptr)
     {
-        Helper::log(LogStatus::ERROR, "Out of memory while allocating tabs !");
+        Helper::log(LogStatus::FATAL, "Out of memory while allocating tabs !");
 
         return 1;
     }
@@ -50,12 +43,14 @@ int pastix_read_symbol(FILE* stream, symbol_matrix_t* matrix)
     int32_t cblknbr = matrix->m_cblknbr;
     for (cblknum = 0; cblknum < cblknbr; ++cblknum)
     {
-        if ((pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_fcolumn)) +
-             pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_lcolnum)) +
-             pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_bloknum)) != 3) ||
+		result =  pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_fcolumn));
+		result += pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_lcolnum));
+		result += pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_bloknum));
+
+        if ((result != 3) ||
             (matrix->m_cblktab[cblknum].m_fcolumn > matrix->m_cblktab[cblknum].m_lcolnum))
         {
-            Helper::log(LogStatus::ERROR, "Bad input while reading cblk !");
+            Helper::log(LogStatus::FATAL, "Bad input while reading cblk !");
 
             return 1;
         }
@@ -66,30 +61,53 @@ int pastix_read_symbol(FILE* stream, symbol_matrix_t* matrix)
     matrix->m_cblktab[cblknbr].m_bloknum = matrix->m_bloknbr + matrix->m_baseval;
 
     int32_t bloknbr = matrix->m_bloknbr;
+	int32_t maxrow  = 0;
     for (bloknum = 0; bloknum < bloknbr; ++bloknum)
     {
-        if ((pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_frownum) +
-             pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_lrownum) +
-             pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_fcblknm) != 3) ||
+		result  = pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_frownum);
+		result += pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_lrownum);
+		result += pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_fcblknm);
+        if ((result != 3) ||
             (matrix->m_bloktab[bloknum].m_frownum > matrix->m_bloktab[bloknum].m_lrownum))
         {
-            Helper::log(LogStatus::ERROR, "Bad input while reading blok !", bloknum);
+            Helper::log(LogStatus::FATAL, "Bad input while reading blok %d !", bloknum);
 
             return 1;
         }
 
+		if (matrix->m_bloktab[bloknum].m_lrownum > maxrow)
+			maxrow = matrix->m_bloktab[bloknum].m_lrownum;
+
+		matrix->m_bloktab[bloknum].m_localization = 0;
+		matrix->m_bloktab[bloknum].m_flags = 0;
+
         // Compatibility block
         {
             int32_t tmp;
             if ((versval == 0) && (pastix_read_int(stream, &tmp) != 1))
             {
-                Helper::log(LogStatus::ERROR, "Bad input while reading lefval !");
+                Helper::log(LogStatus::FATAL, "Bad input while reading lefval !");
                 return 1;
             }
         }
     }
 
     matrix->m_dof = 1;
+	matrix->m_rowsnbr = maxrow + 1;
+
+	Helper::log(LogStatus::MESSAGE,
+		"Loaded header:\n"
+		"  Version:             %10d\n"
+		"  Number of cblk:      %10d\n"
+		"  Number of rows:      %10d\n"
+		"  Number of blok:      %10d\n"
+		"  Number of nodes:     %10d\n"
+		"  Base value:          %10d\n",
+		versval,
+		matrix->m_cblknbr, matrix->m_rowsnbr,
+		matrix->m_bloknbr, matrix->m_nodenbr,
+		matrix->m_baseval
+	);
 
     return 0;
 }
diff --git a/plugins/MatrixVisualizer/Windows/MatrixGLWidget.cpp b/plugins/MatrixVisualizer/Windows/MatrixGLWidget.cpp
index 5a7fe783..0dbbc779 100644
--- a/plugins/MatrixVisualizer/Windows/MatrixGLWidget.cpp
+++ b/plugins/MatrixVisualizer/Windows/MatrixGLWidget.cpp
@@ -2,11 +2,9 @@
 
 #include "MatrixWindow.hpp"
 
-#define BACKGROUND_COLOR_R      0.f
-#define BACKGROUND_COLOR_G      0.f
-#define BACKGROUND_COLOR_B      0.f
-
-#define NB_BLOK_BY_SIDE         256
+#define BACKGROUND_COLOR_R      1.f
+#define BACKGROUND_COLOR_G      1.f
+#define BACKGROUND_COLOR_B      1.f
 
 /* Helpers */
 static void drawSquare(GLfloat x, GLfloat y, GLfloat dx, GLfloat dy, GLfloat r, GLfloat g, GLfloat b)
@@ -28,25 +26,32 @@ static void drawEmpty()
     glBegin(GL_TRIANGLES);
         glColor3f(BACKGROUND_COLOR_R, BACKGROUND_COLOR_G, BACKGROUND_COLOR_B);
 
-        glVertex2f(0,               NB_BLOK_BY_SIDE);
-        glVertex2f(NB_BLOK_BY_SIDE, NB_BLOK_BY_SIDE);
-        glVertex2f(NB_BLOK_BY_SIDE, 0);
+        glVertex2f(0,								QuadTree::DEFAULT_LEVEL_POWER_2);
+        glVertex2f(QuadTree::DEFAULT_LEVEL_POWER_2, QuadTree::DEFAULT_LEVEL_POWER_2);
+        glVertex2f(QuadTree::DEFAULT_LEVEL_POWER_2, 0);
     glEnd();
 }
 
-MatrixGLWidget::MatrixGLWidget(QWidget* parent, symbol_matrix_t* matrix)
+MatrixGLWidget::MatrixGLWidget(QWidget* parent, symbol_matrix_t* matrix, QLabel* label)
 #ifdef USE_QT5
     : QOpenGLWidget(parent)
 #else
     : QGLWidget(parent)
 #endif
+	, m_label(label)
+	, m_frameCount(0)
 {
     this->setFixedSize(MATRIX_WINDOW_LENGTH, MATRIX_WINDOW_HEIGHT);
 
     m_quadtree = QuadTree::constructFromSymbolMatrix(matrix);
 
-    symbol_matrix_deinit(matrix);
-    delete matrix;
+#ifdef USE_QT5
+	connect(&m_updateTimer, &QTimer::timeout, this, &MatrixGLWidget::updateTimer);
+#else
+	connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
+#endif
+
+	m_updateTimer.start(1000 / 60);
 }
 
 MatrixGLWidget::~MatrixGLWidget()
@@ -63,7 +68,7 @@ void MatrixGLWidget::initializeGL()
 
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    glOrtho(0, NB_BLOK_BY_SIDE+2, 0, NB_BLOK_BY_SIDE+2, -1, 1);
+    glOrtho(0, QuadTree::DEFAULT_LEVEL_POWER_2+2, 0, QuadTree::DEFAULT_LEVEL_POWER_2+2, -1, 1);
 
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
@@ -74,7 +79,7 @@ void MatrixGLWidget::resizeGL(int w, int h)
 {
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    glOrtho(0, NB_BLOK_BY_SIDE, 0, NB_BLOK_BY_SIDE, -1, 1);
+    glOrtho(0, QuadTree::DEFAULT_LEVEL_POWER_2, 0, QuadTree::DEFAULT_LEVEL_POWER_2, -1, 1);
 
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
@@ -87,17 +92,36 @@ void MatrixGLWidget::paintGL()
 #ifdef USE_QT5
     initializeOpenGLFunctions();
 #endif
+
+	if (m_frameCount == 0)
+		m_time.start();
+	else
+	{
+		sprintf(m_fpsString, "FPS: %f ms", m_time.elapsed() / float(m_frameCount));
+		m_label->setText(m_fpsString);
+	}
+
 	glClear(GL_COLOR_BUFFER_BIT);
 
-    for (i = 0; i < NB_BLOK_BY_SIDE; ++i)
+    for (i = 0; i < QuadTree::DEFAULT_LEVEL_POWER_2; ++i)
     {
-        for (j = 0; j < NB_BLOK_BY_SIDE; ++j)
+        for (j = 0; j < QuadTree::DEFAULT_LEVEL_POWER_2; ++j)
         {
-            drawSquare(i, j, 1, 1, m_quadtree->getColor(i, j), 0.f, 0.f);
+			GLfloat grey = m_quadtree->getColor(i, j);
+            drawSquare(i, j, 1, 1, grey, grey, grey);
         }
     }
 
     drawEmpty();
+
+	m_frameCount++;
+}
+
+void MatrixGLWidget::updateTimer()
+{
+	// Need to do this because the connect function cannot
+	// differenciate overloaded cases of update
+	update();
 }
 
 void MatrixGLWidget::keyPressEvent(QKeyEvent *keyEvent)
diff --git a/plugins/MatrixVisualizer/Windows/MatrixGLWidget.hpp b/plugins/MatrixVisualizer/Windows/MatrixGLWidget.hpp
index 73383af9..7eaca4d8 100644
--- a/plugins/MatrixVisualizer/Windows/MatrixGLWidget.hpp
+++ b/plugins/MatrixVisualizer/Windows/MatrixGLWidget.hpp
@@ -24,7 +24,7 @@ class MatrixGLWidget :
 #endif
 {
 public:
-    MatrixGLWidget(QWidget* parent, symbol_matrix_t* matrix);
+    MatrixGLWidget(QWidget* parent, symbol_matrix_t* matrix, QLabel* label);
     ~MatrixGLWidget();
 
 protected:
@@ -34,11 +34,18 @@ protected:
 
 	void keyPressEvent(QKeyEvent *keyEvent);
 
-private:
+private slots:
     /* Helpers */
+	void updateTimer();
 
 private:
-    QuadTree*           m_quadtree;
+    QuadTree*	m_quadtree;
+	uint32_t	m_frameCount;
+	QTime		m_time;
+	QTimer		m_updateTimer;
+	QLabel*		m_label;
+
+	char		m_fpsString[256];
 };
 
 #endif
diff --git a/plugins/MatrixVisualizer/Windows/MatrixWindow.cpp b/plugins/MatrixVisualizer/Windows/MatrixWindow.cpp
index 2433ad51..69004afa 100644
--- a/plugins/MatrixVisualizer/Windows/MatrixWindow.cpp
+++ b/plugins/MatrixVisualizer/Windows/MatrixWindow.cpp
@@ -7,11 +7,11 @@ Matrix_window::Matrix_window(symbol_matrix_t* matrix)
     QWidget* widget = new QWidget();
     QVBoxLayout* layout = new QVBoxLayout(widget);
 
-    m_gl = new MatrixGLWidget(nullptr, matrix);
-    m_gl->setObjectName(QString("matrix_gl_visualizer"));
+	m_label = new QLabel(nullptr);
+	m_label->setText("Infos: ");
 
-    m_label = new QLabel(nullptr);
-    m_label->setText("Infos: ");
+    m_gl = new MatrixGLWidget(nullptr, matrix, m_label);
+    m_gl->setObjectName(QString("matrix_gl_visualizer"));
 
     layout->addWidget(m_gl);
     layout->addWidget(m_label);
@@ -26,7 +26,7 @@ Matrix_window::~Matrix_window()
 
 void Matrix_window::closeEvent(QCloseEvent* event)
 {
-    // D�gueu
+    // Dégueu
     delete this;
 }
 
diff --git a/src/render/Render_alternate.cpp b/src/render/Render_alternate.cpp
index e4f73c00..bd9379ce 100644
--- a/src/render/Render_alternate.cpp
+++ b/src/render/Render_alternate.cpp
@@ -806,6 +806,8 @@ GLuint Render_alternate::draw_wait() {
         _wait->add(-0.25, -0.25, 0, 0);
         _wait->config(_glsl);
     }
+
+	return 1;
 }
 
 
diff --git a/src/render/Render_opengl.cpp b/src/render/Render_opengl.cpp
index f38d2e7c..3591798f 100644
--- a/src/render/Render_opengl.cpp
+++ b/src/render/Render_opengl.cpp
@@ -44,6 +44,10 @@
  *\file Render_opengl.cpp
  */
 
+#ifdef _WIN32
+	#include <Windows.h>
+#endif
+
 #include <sstream>
 #include <cmath>
 /* -- */
diff --git a/src/render/render_stats_opengl.cpp b/src/render/render_stats_opengl.cpp
index eb4da0cb..30e0a031 100644
--- a/src/render/render_stats_opengl.cpp
+++ b/src/render/render_stats_opengl.cpp
@@ -44,6 +44,10 @@
  *\file render_stats_opengl.cpp
  */
 
+#ifdef _WIN32
+	#include <Windows.h>
+#endif
+
 #include <cstdio>
 #include <string>
 /* -- */
diff --git a/src/render/render_stats_svg.hpp b/src/render/render_stats_svg.hpp
index 16b14368..e08ed5b2 100644
--- a/src/render/render_stats_svg.hpp
+++ b/src/render/render_stats_svg.hpp
@@ -47,6 +47,10 @@
 #ifndef RENDER_STATS_SVG_HPP
 #define RENDER_STATS_SVG_HPP
 
+#ifdef _WIN32
+	#include <algorithm>
+#endif
+
 class Render_stats_svg;
 
 #define _RENDER_WIDTH_DEFAULT  550.f
diff --git a/src/render/vbo.cpp b/src/render/vbo.cpp
index 33a19c26..915aaf3a 100644
--- a/src/render/vbo.cpp
+++ b/src/render/vbo.cpp
@@ -112,6 +112,8 @@ int Vbo::add(Element_pos x, Element_pos y, Element_col r, Element_col g, Element
     _colors.push_back(g);
     _colors.push_back(b);
     _nbVertex++;
+
+	return 1;
 }
 
 /* add vertex for a vbo using coordinates and texture*/
@@ -121,6 +123,8 @@ int Vbo::add(Element_pos x, Element_pos y, Element_pos tx, Element_pos ty){
     _texture_coord.push_back(tx);
     _texture_coord.push_back(ty);
     _nbVertex++;
+
+	return 1;
 }
 
 /* add vertex for state vbo using a char for shade (glsl 330 or later)*/
@@ -129,6 +133,8 @@ int Vbo::add(Element_pos x, Element_pos y, char b){
     _vertex.push_back(y);
     _shaded.push_back(b);
     _nbVertex++;
+
+	return 1;
 }
 
 /* add vertex for state vbo with glsl < 330*/
@@ -137,6 +143,8 @@ int Vbo::add(Element_pos x, Element_pos y, float b){
     _vertex.push_back(y);
     _shaded2.push_back(b);
     _nbVertex++;
+
+	return 1;
 }
 
 /*add vertex for link or event vbo*/
@@ -144,6 +152,8 @@ int Vbo::add(Element_pos x, Element_pos y){
     _vertex.push_back(x);
     _vertex.push_back(y);
     _nbVertex++;
+
+	return 1;
 }
 
 void Vbo::config(int glsl){
-- 
GitLab