Converting the model file formats
Conducted by Fraser Savage
Overview
As we plan to let the user upload models to a webapp and then download them for use in the hololens application, we need a way to automatically convert models from one of the provided formats stl to a format Unity can use obj. To summarise what was done in this experiment:
- Used the ASSIMP C++ library to import
stlfiles and export them asobjfiles - Used the Java Native Interface to make this functionality available for a Java application
1. Creating the Java function prototype and corresponding .h file
To be able to run C++ code from the Java application I first had to create the native function declaration in my Java class:
private native boolean convertStlToObj(String filePath, String fileName);
This native function needed to reside within a system library which, on Linux is a so file residing in /usr/lib (my distribution is Arch Linux). These libary's are typically named with the format of lib<name>.so.
The Java class which makes use of the native function requires for the library to be loaded using the System.loadlibrary() call in it's static block. For example to load the library file libconverter.so I would use the following:
static {
System.loadlibrary("converter");
}
Next I built the application, generating all the necessary class files. To generate the correct header file I then ran the following command in my shell environment from the 'root' of the output folder:
$ javah com.company.Main
This generated the com_company_Main.h header file for JNI usage by the Main class in com.company package.
2. Implementing the C++ function
With the javah generated header file I could then begin to explore the Assimp library. The reason for using JNI and making the codebase polyglot was because of the need to convert models into a format that we can use in Unity, so the requirement for this function is primarily to convert stl files to obj files. As a result additional postprocessing takes a back seat.
To function prototype generated by javah was:
JNIEXPORT jboolean JNICALL Java_com_company_Main_convertStlToObj
(JNIEnv *, jobject, jstring, jstring);
So implementing the function in the com_company_Main.cpp file I needed to use the same declaration and include the following libaries:
<jni.h>"com_company_Main.h"
In addition, I needed to include a couple of assimp header files, namely:
<assimp/Importer.hpp><assimp/Exporter.hpp><assimp/scene.h><assimp/postprocess.h>
I will omit the code snippet for the sake of brevity, but the "algorithm" that the function performs is as follows:
- Convert the
jstringparameters to native C++ strings - Use the
Assimp::Importerclass to read thestlfrom file - Store the imported
stlas aconst aiScene*, processing it at the same time - Check that the scene imported correctly
- Use the
Assimp::Exporterclass to export the scene to anobjfile in the same location as the importedstl - Check the
objfile generated can be imported correctly
The function will return JNI_FALSE to the calling java program if any of the steps fail, while returning JNI_TRUE if all is well.
3. Preparing it for user
The final step in preparing the native function was to use g++ to compile and link the two files, com_company_Main.cpp and com_company_Main.h with the Assimp library and point it towards the jdk include directories. This would compile the .so file which I then copied into the /usr/lib directory, allowing me to use the function to convert stl files to obj files within a Java application.
4. Conclusion
This experiment proved to be quite useful as it exposed me to interop between different classes of language within the same component of the application, as well as allowing me to explore the possibilities for preprocessing models for the HoloLens application.
It also highlighted that there is a flexibility over what language and framework to use for the server application, as long as it can call C/C++ libraries - conversion of model file types is a relatively important requirement.