package teamcomm.gui.drawings; import com.jogamp.opengl.GL2; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.swing.JOptionPane; import javax.xml.stream.XMLStreamException; /** * Singleton class for managing the loading of models from ros2 files. * * @author Felix Thielke */ public class RoSi2Loader { /** * Path to the file containing models for the default drawings. */ public static final String COMMON_SCENE_FILE = "scene/TeamComm.ros2"; private static final RoSi2Loader instance = new RoSi2Loader(); private final Map<GL2, Map<String, Map<String, Integer>>> models = new HashMap<>(); private final Map<GL2, Map<String, Set<String>>> modelsToLoad = new HashMap<>(); private RoSi2Loader() { } /** * Returns the only instance of the RoSi2Loader. * * @return instance */ public static RoSi2Loader getInstance() { return instance; } /** * Hints that the given models should be loaded from the common scene file. * This way the file has to be parsed only once when loading the models. * * @param gl OpenGL context * @param modelnames names of the models to load */ public void cacheModels(final GL2 gl, final String[] modelnames) { cacheModels(gl, COMMON_SCENE_FILE, modelnames); } /** * Hints that the given models should be loaded from the given scene file. * This way the file has to be parsed only once when loading the models. * Calling this method is advised in the init()-method of drawings. * * @param gl OpenGL context * @param filename path to the scene file * @param modelnames names of the models to load */ public void cacheModels(final GL2 gl, final String filename, final String... modelnames) { final Set<String> modelNameSet = new HashSet<>(Arrays.asList(modelnames)); // Check if some of the models have already been loaded final Map<String, Map<String, Integer>> modelFileMap = models.get(gl); if (modelFileMap != null) { final Map<String, Integer> modelMap = modelFileMap.get(filename); if (modelMap != null) { final Iterator<String> iter = modelNameSet.iterator(); while (iter.hasNext()) { if (modelMap.containsKey(iter.next())) { iter.remove(); } } } } // Add models to the set of models to load if (!modelNameSet.isEmpty()) { Map<String, Set<String>> fileMap = modelsToLoad.get(gl); if (fileMap == null) { fileMap = new HashMap<>(); modelsToLoad.put(gl, fileMap); } Set<String> nameSet = fileMap.get(filename); if (nameSet == null) { fileMap.put(filename, modelNameSet); } else { nameSet.addAll(modelNameSet); } } } /** * Loads the given model from the common scene file into a display list of * the given OpenGL context. * * @param gl OpenGL context * @param modelname name of the model * @return id of the display list */ public int loadModel(final GL2 gl, final String modelname) { return loadModel(gl, COMMON_SCENE_FILE, modelname); } /** * Loads the given model from the given scene file into a display list of * the given OpenGL context. * * @param gl OpenGL context * @param filename path to the scene file * @param modelname name of the model * @return id of the display list */ public int loadModel(final GL2 gl, final String filename, final String modelname) { // Check if the model has already been loaded Map<String, Map<String, Integer>> fileMap = models.get(gl); if (fileMap == null) { fileMap = new HashMap<>(); models.put(gl, fileMap); } Map<String, Integer> modelMap = fileMap.get(filename); if (modelMap == null) { modelMap = new HashMap<>(); fileMap.put(filename, modelMap); } else { final Integer id = modelMap.get(modelname); if (id != null) { return id; } } // Determine models to load from the same file Map<String, Set<String>> loadFileMap = modelsToLoad.get(gl); if (loadFileMap == null) { loadFileMap = new HashMap<>(); modelsToLoad.put(gl, loadFileMap); } Set<String> nameSet = loadFileMap.get(filename); if (nameSet == null) { nameSet = new HashSet<>(); loadFileMap.put(filename, nameSet); } nameSet.add(modelname); // Load models try { for (final RoSi2Element e : RoSi2Element.parseFile(filename).findElements(nameSet)) { modelMap.put(e.getName(), e.instantiate(gl).createDisplayList()); } } catch (RoSi2Element.RoSi2ParseException | XMLStreamException | IOException ex) { JOptionPane.showMessageDialog(null, ex.getMessage(), "Error loading scene", JOptionPane.ERROR_MESSAGE); System.exit(-1); } nameSet.clear(); return modelMap.get(modelname); } }