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