Another addition to ModelLoader.
This time around, .3DS has been added, and .OBJ has been more refined to turn the model node directly into the imported model when it isn't a trimesh.
A CVS diff patch was sent, though of course I'm not a dev, so I have no means of addings it.
Enjoy!
/**
* This is a utility that will prompt for a model file and then load it into
* a scene.
*
* @author Matthew D. Hicks
* @author Alexander J. Gilpin
*/
public class ModelLoader {
public static void main(String[] args) {
// Store the texture in the binary file
// Texture.DEFAULT_STORE_TEXTURE = true;
try {
JFileChooser chooser = new JFileChooser();
Preferences preferences = Preferences.userNodeForPackage(ModelLoader.class);
File directory = new File(preferences.get("StartDirectory", "."));
chooser.setCurrentDirectory(directory);
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
if (isValidModelFile(file)) {
// Set it in preferences so we remember next time
preferences.put("StartDirectory", file.getAbsolutePath());
StandardGame game = new StandardGame("Model Loader");
try {
game.getSettings().clear();
} catch(Exception exc) {
exc.printStackTrace();
}
game.start();
GameTaskQueueManager.getManager().update(new Callable<Object>() {
public Object call() throws Exception {
//MouseInput.get().setCursorVisible(true);
return null;
}
});
DebugGameState debug = new DebugGameState();
GameStateManager.getInstance().attachChild(debug);
debug.setActive(true);
LoadingGameState loading = new LoadingGameState();
GameStateManager.getInstance().attachChild(loading);
loading.setActive(true);
loading.setProgress(0.5f, "Loading Model: " + file.getName());
long time = System.currentTimeMillis();
final Node modelNode = loadModel(file);
outputElapsed(time);
if (modelNode != null) {
//modelNode.setLocalScale(0.2f);
modelNode.setModelBound(new BoundingBox());
modelNode.updateModelBound();
modelNode.updateRenderState();
debug.getRootNode().attachChild(modelNode);
debug.getRootNode().updateRenderState();
if (file.getName().toLowerCase().endsWith(".jme")) {
loading.setProgress(1.0f, "Loaded Successfully");
} else {
loading.setProgress(0.8f, "Loaded Successfully - Saving");
try {
BinaryExporter.getInstance().save(modelNode, createJMEFile(file.getAbsoluteFile()));
loading.setProgress(1.0f, "Binary File Written Successfully");
} catch(IOException exc) {
exc.printStackTrace();
loading.setProgress(0.9f, "Binary Save Failure");
try {
Thread.sleep(5000);
} catch(InterruptedException exc2) {
exc2.printStackTrace();
}
loading.setProgress(1.0f);
}
}
} else {
loading.setProgress(0.9f, "Model Not Loaded");
try {
Thread.sleep(5000);
} catch(InterruptedException exc) {
exc.printStackTrace();
}
loading.setProgress(1.0f);
}
} else {
JOptionPane.showMessageDialog(null, "Selected file's extension is unknown model type: " + file.getName());
}
}
} catch(Throwable t) {
StringWriter writer = new StringWriter();
PrintWriter stream = new PrintWriter(writer);
t.printStackTrace(stream);
JFrame frame = new JFrame();
frame.setTitle("ModelLoader - StackTrace");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextPane panel = new JTextPane();
panel.setPreferredSize(new Dimension(400, 400));
panel.setContentType("text/plain");
panel.setText(writer.getBuffer().toString());
frame.setContentPane(new JScrollPane(panel));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
private static final File createJMEFile(File f) {
String filename = f.getName();
if (filename.indexOf('.') != -1) {
filename = filename.substring(0, filename.lastIndexOf('.'));
}
filename = filename + ".jme";
return new File(f.getParentFile(), filename);
}
private static final void outputElapsed(long startTime) {
float elapsed = (System.currentTimeMillis() - startTime) / 1000.0f;
System.out.println("Took " + elapsed + " seconds to load the model.");
}
public static final Node loadModel(final File file) throws Exception {
String filename = file.getName().toUpperCase();
Node model = null;
try {
if (filename.endsWith(".DAE")) {
Future<Node> future = GameTaskQueueManager.getManager().update(new Callable<Node>() {
public Node call() throws Exception {
ColladaImporter.load(file.toURI().toURL().openStream(), file.getAbsoluteFile().getParentFile().toURI().toURL(), "Model");
Node model = ColladaImporter.getModel();
return model;
}
});
model = future.get();
} else if (filename.endsWith(".JME")) {
model = (Node)BinaryImporter.getInstance().load(file);
} else if (filename.endsWith(".OBJ")) {
// Note that .OBJ Ambient colors are multiplied. I would strongly suggest making them black.
Future<Node> future = GameTaskQueueManager.getManager().update(new Callable<Node>() {
public Node call() throws Exception {
FormatConverter converter = new ObjToJme();
converter.setProperty("mtllib", file.getParentFile().toURI().toURL());
converter.setProperty("texdir", file.getParentFile().toURI().toURL());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
converter.convert(file.toURI().toURL().openStream(), bos);
if (BinaryImporter.getInstance().load(new ByteArrayInputStream(bos.toByteArray())).getClass() == TriMesh.class) {
Node model = new Node("Imported Model " + file.getName());
System.out.println("Trimesh! Attaching the Trimesh to the model Node!");
model.attachChild((Spatial)BinaryImporter.getInstance().load(new ByteArrayInputStream(bos.toByteArray())));
return model;
} else {
System.out.println("NOT a Trimesh! Directly converting to a Node!");
Node model = (Node)BinaryImporter.getInstance().load(new ByteArrayInputStream(bos.toByteArray()));
return model;
}
}
});
model = future.get();
} else if (filename.endsWith(".3DS")) {
// Note that some .3DS Animations from Blender may not work. I'd suggest using a version of 3DSMax.
Future<Node> future = GameTaskQueueManager.getManager().update(new Callable<Node>() {
public Node call() throws Exception {
FormatConverter converter = new MaxToJme();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
converter.convert(file.toURI().toURL().openStream(), bos);
Node model = (Node)BinaryImporter.getInstance().load(new ByteArrayInputStream(bos.toByteArray()));
return model;
}
});
model = future.get();
}
} catch(IOException exc) {
exc.printStackTrace();
}
return model;
}
public static final boolean isValidModelFile(File file) {
String filename = file.getName().toUpperCase();
if (filename.endsWith(".DAE")) return true;
else if (filename.endsWith(".JME")) return true;
else if (filename.endsWith(".OBJ")) return true;
else if (filename.endsWith(".3DS")) return true;
return false;
}
}