diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java
index fa5bf458dbf95a56235419fd73d13c77b5cf673f..8e30f66498cf2fe78821571d59e28f4458dd8dfb 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java
@@ -10,8 +10,12 @@ import cz.fidentis.analyst.symmetry.Plane;
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Objects;
 
 /**
  * This class encapsulates data for a 3D scan of a single human face.
@@ -34,36 +38,30 @@ import java.io.InputStream;
  * 
  * @author Radek Oslejsek
  */
-public class HumanFace implements MeshListener {
+public class HumanFace implements MeshListener, Serializable {
     
-    private MeshModel meshModel;
+    private final MeshModel meshModel;
 
     private Plane symmetryPlane;
 
     private MeshFacet cuttingPlane;
     
-    private EventBus eventBus = new EventBus();
+    private final transient EventBus eventBus = new EventBus();
+    
+    private final String id;
     
     /**
-     * Reads a 3D human phase from file.
+     * Reads a 3D human face from the given OBJ file.
+     * Use {@link restoreFromFile} to restore the human face from a dump file.
      * 
      * @param file OBJ file
      * @throws IOException on I/O failure
      */
     public HumanFace(File file) throws IOException {
-        this(new FileInputStream(file));
-    }
-    
-    /**
-     * Reads a 3D human phase from file.
-     * 
-     * @param is input stream with OBJ data
-     * @throws IOException on I/O failure
-     */
-    public HumanFace(InputStream is) throws IOException {
-        meshModel = MeshObjLoader.read(is);
+        meshModel = MeshObjLoader.read(new FileInputStream(file));
         meshModel.simplifyModel();
         meshModel.registerListener(this);
+        this.id = file.getCanonicalPath();
     }
     
     /**
@@ -136,4 +134,69 @@ public class HumanFace implements MeshListener {
     public MeshFacet getCuttingPlane() {
         return cuttingPlane;
     }
+    
+    /**
+     * Return unique ID of the face.
+     * 
+     * @return unique ID of the face. 
+     */
+    public String getId() {
+        return this.id;
+    }
+
+    /**
+     * Creates serialized dump of the human face. Event buses are not stored.
+     * Therefore, listeners have to re-register again after recovery.
+     * 
+     * @return Dump file
+     * @throws IOException on error in creating the dump file
+     */
+    public File dumpToFile() throws IOException {
+        File tempFile = File.createTempFile(this.getClass().getSimpleName(), ".ser");
+        tempFile.deleteOnExit();
+        try (ObjectOutputStream fos = new ObjectOutputStream(new FileOutputStream(tempFile))) {
+            fos.writeObject(this);
+        }
+        return tempFile;
+    }
+    
+    /**
+     * Restores human face from a dump file.
+     * 
+     * @param dumpFile The file
+     * @return Human face
+     * @throws IOException on error in reading the dump file
+     * @throws java.lang.ClassNotFoundException on error when instantiating the human face
+     */
+    public static HumanFace restoreFromFile(File dumpFile) throws IOException, ClassNotFoundException {
+        try (ObjectInputStream fos = new ObjectInputStream(new FileInputStream(dumpFile))) {
+            return (HumanFace) fos.readObject();
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 7;
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final HumanFace other = (HumanFace) obj;
+        if (!Objects.equals(this.id, other.id)) {
+            return false;
+        }
+        return true;
+    }
+    
+    
 }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceCache.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..99a42718049cd6b434a2aaa3caeb6fa2b3a9d657
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceCache.java
@@ -0,0 +1,224 @@
+package cz.fidentis.analyst.face;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Singleton flyweight factory that creates and caches human faces. Faces are
+ * stored in the memory until there is enough space in the Java heap. Then they 
+ * are cached on disk automatically. The dumping strategy is directed by sub-classes
+ * of this abstract class.
+ * <p>
+ * Dumping faces on disk and their recovery is time consuming (we use serialization
+ * of all data structure, i.e., triangular mesh, k-d tree, etc.). It can be faster
+ * to re-load the face from OBJ file again and re-compute the data structures from scratch.
+ * </p>
+ * <p>
+ * Currently, listeners registered to {@code HumanFace} and {@code KdTree} 
+ * are neither dumped nor reconstructed!
+ * </p>
+ * 
+ * @author Radek Oslejsek
+ */
+public abstract class HumanFaceCache {
+    
+    /**
+     * Keep at least this portion of the Java heap memory free
+     */
+    public static final double MIN_FREE_MEMORY = 0.05; // 5%
+    
+    private final Map<String, HumanFace> inMemoryFaces = new HashMap<>();
+    private final Map<String, File> dumpedFaces = new HashMap<>();
+    
+    /**
+     * Private constructor. Use {@link instance} instead to get and access the instance.
+     */
+    protected HumanFaceCache() {
+    }
+    
+    /**
+     * Loads new face. If the face is already loaded, then the existing instance
+     * is returned. 
+     * 
+     * @param file OBJ file with human face.
+     * @return Human face or {@code null}
+     */
+    public HumanFace loadFace(File file) {
+        try {
+            String faceId = file.getCanonicalPath();
+            //String faceId = Long.toHexString(Double.doubleToLongBits(Math.random()));
+            
+            // In memory face:
+            HumanFace face = inMemoryFaces.get(faceId);
+            if (face != null) {
+                return face;
+            }
+            
+            // Dumped face:
+            face = recoverFace(faceId);
+            if (face != null) {
+                return face;
+            }
+            
+            // New face:
+            return storeNewFace(file);
+        } catch (IOException|ClassNotFoundException|InterruptedException|ExecutionException ex) {
+            Logger.getLogger(HumanFaceCache.class.getName()).log(Level.SEVERE, null, ex);
+            return null;
+        }
+    }
+    
+    /**
+     * Returns a human face. Recovers the face from a dump file if necessary.
+     * 
+     * @param faceId ID of the face
+     * @return Human face or {@code null}
+     */
+    public HumanFace getFace(String faceId) {
+        try {
+            // In memory face:
+            HumanFace face = inMemoryFaces.get(faceId);
+            if (face != null) {
+                return face;
+            }
+            
+            // Dumped face:
+            face = recoverFace(faceId);
+            if (face != null) {
+                return face;
+            }
+            
+            // New face:
+            return null;
+        } catch (IOException|ClassNotFoundException|InterruptedException|ExecutionException ex) {
+            Logger.getLogger(HumanFaceCache.class.getName()).log(Level.SEVERE, null, ex);
+            return null;
+        }
+    }
+    
+    /**
+     * Removed the face from the cache.
+     * 
+     * @param faceId Face ID
+     */
+    public void removeFace(String faceId) {
+        if (inMemoryFaces.remove(faceId) == null) {
+            dumpedFaces.remove(faceId);
+        }
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder ret = new StringBuilder();
+        ret.append(formatSize(Runtime.getRuntime().freeMemory())).
+                append(" free memory out of ").
+                append(formatSize(Runtime.getRuntime().maxMemory()));
+        ret.append(". In memory: ").
+                append(this.inMemoryFaces.size()).
+                append(", dumped: ").
+                append(this.dumpedFaces.size());
+        return ret.toString();
+    }
+    
+    /**
+     * Recovers the face from the dump file.Heap memory is released (some existing 
+     * face is dumped) if necessary. 
+     * 
+     * @param faceId Face ID
+     * @return Recovered face or {@code null} if the face was not dumped.
+     * @throws IOException on I/O error
+     * @throws ClassNotFoundException on I/O error
+     * @throws java.lang.InterruptedException
+     * @throws java.util.concurrent.ExecutionException
+     */
+    protected HumanFace recoverFace(String faceId) throws IOException, ClassNotFoundException, InterruptedException, ExecutionException {
+        File dumpFile = dumpedFaces.get(faceId);
+        if (dumpFile == null) {
+            return null;
+        }
+
+        // Free memory and recover human face from dump file silultanously:
+        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+        final Future<HumanFace> result = executor.submit(() -> HumanFace.restoreFromFile(dumpFile));
+        executor.submit(() -> freeMemory());
+        executor.shutdown();
+        while (!executor.isTerminated()){}
+        HumanFace face = result.get();
+        
+        inMemoryFaces.put(faceId, face);
+        dumpedFaces.remove(faceId);
+        return face;
+    }
+    
+    /**
+     * Instantiates new face.Heap memory is released (some existing face is dumped) if necessary. 
+     * 
+     * @param file OBJ file
+     * @return Face instance.
+     * @throws IOException on I/O error
+     * @throws java.lang.InterruptedException
+     * @throws java.util.concurrent.ExecutionException
+     */
+    protected HumanFace storeNewFace(File file) throws IOException, InterruptedException, ExecutionException {
+        // Free memory and load human face simultaneously:
+        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+        final Future<HumanFace> result = executor.submit(() -> new HumanFace(file));
+        executor.submit(() -> freeMemory());
+        executor.shutdown();
+        while (!executor.isTerminated()){}
+        HumanFace face = result.get();
+        inMemoryFaces.put(face.getId(), face);
+        return face;
+    }
+    
+    /**
+     * Checks and releases the heap, if necessary.
+     * 
+     * @return true if some existing face has been dumped to free the memory.
+     * @throws IOException on I/O error
+     */
+    protected boolean freeMemory() throws IOException {
+        double ratio = (double) Runtime.getRuntime().freeMemory() / Runtime.getRuntime().maxMemory();
+        if (ratio > MIN_FREE_MEMORY) {
+            return false;
+        }
+        String faceId = selectFaceForDump();
+        if (faceId != null) {
+            HumanFace face = inMemoryFaces.remove(faceId);
+            dumpedFaces.put(faceId, face.dumpToFile());
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Selects a face that will be dumped to file.
+     * 
+     * @return ID of the face that will be dumped to file.
+     */
+    protected abstract String selectFaceForDump();
+    
+    protected static String formatSize(long v) {
+        if (v < 1024) {
+            return v + " B";
+        }
+        int z = (63 - Long.numberOfLeadingZeros(v)) / 10;
+        return String.format("%.1f %sB", (double)v / (1L << (z*10)), " KMGTPE".charAt(z));
+    }
+    
+    protected Map<String, HumanFace> getInMemoryFaces() {
+        return this.inMemoryFaces;
+    }
+    
+    protected Map<String, File> getDumpedFaces() {
+        return this.dumpedFaces;
+    }
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFacePrivilegedCache.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFacePrivilegedCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..3c73e046761d1ce4022f86bba360ac01ce3b8a5a
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFacePrivilegedCache.java
@@ -0,0 +1,69 @@
+package cz.fidentis.analyst.face;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * This cache preserves the first X faces (privileged faces) always in the memory. 
+ * Faces that are loaded when there is not enough free memory are always dumped
+ * to file and only one of them is stored in the memory when used.
+ * 
+ * @author Radek Oslejsek
+ */
+public class HumanFacePrivilegedCache extends HumanFaceCache {
+    
+    private static HumanFacePrivilegedCache factory;
+    
+    /**
+     * The only one dumped face currently in the memory
+     */
+    private String recoveredFace;
+    
+    /**
+     * Private constructor. Use {@link instance} instead to get and access the instance.
+     */
+    protected HumanFacePrivilegedCache() {
+    }
+    
+    /**
+     * Returns the factory singleton instance.
+     * 
+     * @return the factory singleton instance
+     */
+    public static HumanFacePrivilegedCache instance() {
+        if (factory == null) {
+            factory = new HumanFacePrivilegedCache();
+        }
+        return factory;
+    }
+
+    @Override
+    protected String selectFaceForDump() {
+        if (this.recoveredFace != null) {
+            return this.recoveredFace;
+        } else {
+            // This should not happen. But return any face from the memory, anyway.
+            for (String faceId: getInMemoryFaces().keySet()) {
+                return faceId; 
+            }
+        }
+        return null;
+    }
+    
+    @Override
+    public void removeFace(String faceId) {
+        if (faceId.equals(this.recoveredFace)) {
+            this.recoveredFace = null;
+        }
+        super.removeFace(faceId);
+    }
+    
+    @Override
+    protected HumanFace recoverFace(String faceId) throws IOException, ClassNotFoundException, InterruptedException, ExecutionException {
+        HumanFace face = super.recoverFace(faceId);
+        if (face != null) {
+            this.recoveredFace = face.getId();
+        }
+        return face;
+    }
+}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java
index f27a4d69f54ad0623b3ff3d8ddedceb84d026fdf..83fa87ff2f3000993c32e2c9e5798f62357e9727 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java
@@ -1,5 +1,6 @@
 package cz.fidentis.analyst.symmetry;
 
+import java.io.Serializable;
 import java.util.List;
 import javax.vecmath.Vector3d;
 
@@ -8,7 +9,7 @@ import javax.vecmath.Vector3d;
  * 
  * @author Natalia Bebjakova
  */
-public class Plane {
+public class Plane implements Serializable {
    
     private Vector3d normal;
     private double   distance;
diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
index a8f5bbda0436d519a4db9d7abf0e612a8d4b54c1..1d373075e860d79e97ac53d920ad0899e4d26fcd 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
@@ -1,6 +1,7 @@
 package cz.fidentis.analyst.tests;
 
 import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.face.HumanFacePrivilegedCache;
 import cz.fidentis.analyst.icp.Icp;
 import cz.fidentis.analyst.kdtree.KdTree;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
@@ -12,6 +13,7 @@ import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
 import cz.fidentis.analyst.visitors.mesh.HausdorffDistance.Strategy;
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -25,7 +27,7 @@ public class EfficiencyTests {
     private static File girlFile = new File("src/test/resources/cz/fidentis/analyst/average_girl_17-20.obj");
     private static File boyFile = new File("src/test/resources/cz/fidentis/analyst/average_boy_17-20.obj");
     private static File faceFile2 = new File("src/test/resources/cz/fidentis/analyst/00002_01_ECA.obj");
-    private static File faceFile4 = new File("src/test/resources/cz/fidentis/analyst/00004_01_ECA.obj");
+    private static File faceFile4 = new File("/home/oslejsek/GIT/HCI/analyst2/GUI/src/test/resources/cz/fidentis/analyst/00004_01_ECA.obj");
     private static File basicFaceFile = new File("src/test/resources/cz/fidentis/analyst/basic-model-04.obj");
     
     private static HumanFace face1;
@@ -36,16 +38,24 @@ public class EfficiencyTests {
      * @param args Input arguments 
      * @throws IOException on IO error
      */
-    public static void main(String[] args) throws IOException {
-        face1 = new HumanFace(boyFile);
-        face2 = new HumanFace(faceFile4);
+    public static void main(String[] args) throws IOException, ClassNotFoundException {
+        face1 = printFaceLoad(faceFile4);
+        face2 = printFaceLoad(faceFile4);
         
         face1.getMeshModel().simplifyModel();
         face2.getMeshModel().simplifyModel();
         
+        for (int i = 0; i < 10; i++) {
+            HumanFace face = HumanFacePrivilegedCache.instance().loadFace(faceFile4);
+            face.getMeshModel().simplifyModel();
+            System.out.println(i+".\t" + HumanFacePrivilegedCache.instance());
+        }
+        
         boolean relativeDist = false;
         boolean printDetails = false;
         
+        printFaceDump(face1);
+        
         //face1.getMeshModel().compute(new GaussianCurvature()); // initialize everything, then measure
         
         System.out.println("ICP:");
@@ -118,5 +128,30 @@ public class EfficiencyTests {
                 "\t" + plane.getNormal() + ", " + plane.getDistance()
         );
     }
+
+    private static void printFaceDump(HumanFace face) throws IOException, ClassNotFoundException {
+        long startTime = System.currentTimeMillis();
+        File file = face.dumpToFile();
+        long endTime =  System.currentTimeMillis();
+        System.out.println("Human face dumping:\t " +(endTime-startTime) + " msec");
+        
+        startTime = System.currentTimeMillis();
+        HumanFace f = HumanFace.restoreFromFile(file);
+        endTime =  System.currentTimeMillis();
+        System.out.println("Human face restore:\t " +(endTime-startTime) + " msec");
+    }
+    
+    private static HumanFace printFaceLoad(File file) throws IOException {
+        long startTime = System.currentTimeMillis();
+        HumanFace face = new HumanFace(file);
+        long endTime =  System.currentTimeMillis();
+        System.out.println("Human face loading:\t " +(endTime-startTime) + " msec");
+        return face;
+    }
     
+    public static String formatSize(long v) {
+        if (v < 1024) return v + " B";
+        int z = (63 - Long.numberOfLeadingZeros(v)) / 10;
+        return String.format("%.1f %sB", (double)v / (1L << (z*10)), " KMGTPE".charAt(z));
+    }
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java
index 6bf3652f8c22d10c4b984978c43b2dd935eee523..bee586a8620c2c1363ee5abdc28c66f71a202b20 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java
@@ -1,6 +1,7 @@
 package cz.fidentis.analyst.kdtree;
 
 import cz.fidentis.analyst.mesh.core.MeshFacet;
+import java.io.Serializable;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -14,7 +15,7 @@ import javax.vecmath.Vector3d;
  *
  * @author Maria Kocurekova
  */
-public class KdNode {
+public class KdNode implements Serializable {
     
     /**
      * Current depth in the kd-tree
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java
index 7feb0a6b065a21b829b37794d9fb71a8650be011..a2c6e7fd29eb1c3f9e62e4c70f321658bfb2c478 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java
@@ -4,6 +4,7 @@ import com.google.common.eventbus.EventBus;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -34,11 +35,11 @@ import javax.vecmath.Vector3d;
  * @author Maria Kocurekova
  * @author Radek Oslejsek
  */
-public class KdTree {
+public class KdTree implements Serializable {
     
     private KdNode root;
     
-    private EventBus eventBus = new EventBus();
+    private final transient EventBus eventBus = new EventBus();
     
     /**
      * Constructor.
@@ -140,8 +141,8 @@ public class KdTree {
     public void accept(KdTreeVisitor visitor) {
         visitor.visitKdTree(this);
     }
-
     
+
     /***********************************************************
      *  PRIVATE METHODS
      ***********************************************************/  
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java
index 5157c08588bd71954249e2a5e0ffddb6daf517a8..57cc5615e6858ddaf37ba5d3e90d68d43959cced 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java
@@ -1,5 +1,6 @@
 package cz.fidentis.analyst.mesh.core;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -13,7 +14,7 @@ import java.util.stream.Collectors;
  *
  * @author Matej Lukes
  */
-public class CornerTable {
+public class CornerTable implements Serializable {
 
     private final List<CornerTableRow> rows = new ArrayList<>();
     
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTableRow.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTableRow.java
index 761ce9e91820d2d438d17467abf436c1fc436743..77826dc70d799f95750dc93f2d0b98eef04227bc 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTableRow.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTableRow.java
@@ -1,11 +1,13 @@
 package cz.fidentis.analyst.mesh.core;
 
+import java.io.Serializable;
+
 /**
- * single row in corner table
+ * Single row in corner table.
  *
  * @author Matej Lukes
  */
-public class CornerTableRow {
+public class CornerTableRow implements Serializable {
     
     /**
      * Index to the corner (corner table row) with a vertex on the opposite triangle
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java
index 6f3a8f9f664a99dc4ab174e9d1787676709911f8..aad67f1981569741a561d4a9cff01376444a431a 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java
@@ -2,6 +2,7 @@ package cz.fidentis.analyst.mesh.core;
 
 import java.util.List;
 import cz.fidentis.analyst.mesh.MeshVisitor;
+import java.io.Serializable;
 import javax.vecmath.Vector3d;
 
 /**
@@ -11,7 +12,7 @@ import javax.vecmath.Vector3d;
  *
  * @author Matej Lukes
  */
-public interface MeshFacet extends Iterable<MeshTriangle> {
+public interface MeshFacet extends Iterable<MeshTriangle>, Serializable {
     
     /**
      * returns vertex of specified index
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
index de605a830a1428a3d32f3a94b5f12beab3334de9..b17354e39a52f5ed6d1aca263104c3178bc401db 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
@@ -7,6 +7,7 @@ import cz.fidentis.analyst.mesh.MeshVisitor;
 import cz.fidentis.analyst.mesh.events.FacetAddedEvent;
 import java.util.Collections;
 import cz.fidentis.analyst.mesh.events.MeshListener;
+import java.io.Serializable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -28,11 +29,11 @@ import java.util.concurrent.Executors;
  * @author Matej Lukes
  * @author Radek Oslejsek
  */
-public class MeshModel {
+public class MeshModel implements Serializable {
     
     private final List<MeshFacet> facets = new ArrayList<>();
     
-    private EventBus eventBus = new EventBus();
+    private final transient EventBus eventBus = new EventBus();
     
     /**
      * Constructor of MeshModel
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
index d79b27844fddb094b13f731e2273a642de4a976a..a395bdd7417502a266e44f607ac496e14a3babec 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
@@ -1,5 +1,6 @@
 package cz.fidentis.analyst.mesh.core;
 
+import java.io.Serializable;
 import javax.vecmath.Vector3d;
 
 /**
@@ -7,7 +8,7 @@ import javax.vecmath.Vector3d;
  *
  * @author Matej Lukes
  */
-public interface MeshPoint {
+public interface MeshPoint extends Serializable {
     
     /**
      * Helper method that calculates distance of two 3D points.
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/material/Material.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/material/Material.java
index 367d4243b7ca88343e57194ec2b9f8f9c604995f..5a062394e40f5e5cd6dfa9937fb6e71471aea1ac 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/material/Material.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/material/Material.java
@@ -3,18 +3,25 @@ import javax.media.j3d.Texture;
 import javax.vecmath.Vector3d;
 
 /**
+ * Material.
+ * 
  * @author Matej Lukes
  */
 public class Material {
-    private String name;
-
+    
+    private final String name;
     // colour info
-    private Vector3d ambient, diffuse, specularColors;
-    private double shininess, alpha, illumination;
+    private final Vector3d ambient;
+    private final Vector3d diffuse;
+    private final Vector3d specularColors;
+    
+    private final double shininess;
+    private final double alpha;
+    private final double illumination;
 
     // texture info
-    private String textureFileName;
-    private Texture texture;
+    private final String textureFileName;
+    private final Texture texture;
 
     /**
      *
diff --git a/application/src/main/resources/app.conf b/application/src/main/resources/app.conf
index 2503371a7b2162508fc9e5d9af74234de5182096..bcf74bd532b809b292776122adaf46395c7c830d 100644
--- a/application/src/main/resources/app.conf
+++ b/application/src/main/resources/app.conf
@@ -4,7 +4,7 @@ default_mac_userdir="${HOME}/Library/Application Support/${APPNAME}/dev"
 
 # options used by the launcher by default, can be overridden by explicit
 # command line switches
-default_options="--branding fidentisanalyst -J-Xms24m -J-Xmx1G"
+default_options="--branding fidentisanalyst -J-Xms4G -J-Xmx4G"
 # for development purposes you may wish to append: -J-Dnetbeans.logger.console=true -J-ea
 
 # default location of JDK/JRE, can be overridden by using --jdkhome <dir> switch