Skip to content

Commit

Permalink
Add the possibility to convert model to glTF.
Browse files Browse the repository at this point in the history
  • Loading branch information
kovacsv committed Oct 9, 2021
1 parent 5275c82 commit fe89582
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 36 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ set (ASSIMP_BUILD_TESTS OFF CACHE BOOL "")
set (ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE BOOL "")
set (ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT OFF CACHE BOOL "")
set (ASSIMP_BUILD_ASSJSON_EXPORTER ON CACHE BOOL "")
set (ASSIMP_BUILD_GLTF_EXPORTER ON CACHE BOOL "")

# undefined behaviour because of alignment issues, crashes and memory leaks
# https://github.com/assimp/assimp/pull/4044
Expand Down
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# assimpjs

The [emscripten](https://emscripten.org) interface for the [assimp](https://github.com/assimp/assimp) library. It runs entirely in the browser, and allows you to import 40+ 3D file formats and access the result in JSON format. This is not a full port of assimp, but an easy to use interface to access it's functionality.
The [emscripten](https://emscripten.org) interface for the [assimp](https://github.com/assimp/assimp) library. It runs entirely in the browser, and allows you to import 40+ 3D file formats and access the result in JSON or glTF format. This is not a full port of assimp, but an easy to use interface to access it's functionality.

[Check out the live demo here!](http://kovacsv.github.io/assimpjs)

Expand All @@ -27,6 +27,8 @@ You should provide two things for every file:
- **name:** The name of the file. It's used if files are referring to each other.
- **content:** The content of the file as an `Uint8Array` object.

The supported target formats are: `assjson`, `gltf`, `gltf2`, `glb`, and `glb2`. The number of result files depends on the format.

### Use from the browser

First, include the `assimpjs.js` file in your website.
Expand All @@ -53,8 +55,8 @@ assimpjs ().then (function (ajs) {
fileList.AddFile (files[i], new Uint8Array (arrayBuffers[i]));
}

// convert file list
let result = ajs.ConvertFileList (fileList);
// convert file list to assimp json
let result = ajs.ConvertFileList (fileList, 'assjson');

// check if the conversion succeeded
if (!result.IsSuccess () || result.FileCount () == 0) {
Expand All @@ -80,7 +82,7 @@ You should require the `assimpjs` module in your script. In node.js you can use

```js
let fs = require ('fs');
const assimpjs = require ('../dist/assimpjs.js')();
const assimpjs = require ('assimpjs')();

assimpjs.then ((ajs) => {
// create new file list object
Expand All @@ -96,8 +98,8 @@ assimpjs.then ((ajs) => {
fs.readFileSync ('testfiles/cube_with_materials.mtl')
);

// convert file list
let result = ajs.ConvertFileList (fileList);
// convert file list to assimp json
let result = ajs.ConvertFileList (fileList, 'assjson');

// check if the conversion succeeded
if (!result.IsSuccess () || result.FileCount () == 0) {
Expand All @@ -118,13 +120,15 @@ It's also possible to delay load the required files so they have to be loaded on

```js
let fs = require ('fs');
const assimpjs = require ('../dist/assimpjs.js')();
const assimpjs = require ('assimpjs')();

assimpjs.then ((ajs) => {
// convert model
let result = ajs.ConvertFile (
// file name
'cube_with_materials.obj',
// file format
'assjson',
// file content as arraybuffer
fs.readFileSync ('testfiles/cube_with_materials.obj'),
// check if file exists by name
Expand Down
2 changes: 1 addition & 1 deletion assimpjs/example/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ int main (int argc, const char* argv[])
fileList.AddFile (file.path, file.content);
}

ConvertFileList (fileList);
ConvertFileList (fileList, "gltf2");
return 0;
}
33 changes: 24 additions & 9 deletions assimpjs/src/assimpjs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,20 @@ static const aiScene* ImportFileListByMainFile (Assimp::Importer& importer, cons
return nullptr;
}

static bool ExportScene (const aiScene* scene, Result& result)
static std::string GetFileNameFromFormat (const std::string& format)
{
std::string fileName = "result";
if (format == "assjson") {
fileName += ".json";
} else if (format == "gltf" || format == "gltf2") {
fileName += ".gltf";
} else if (format == "glb" || format == "glb2") {
fileName += ".glb";
}
return fileName;
}

static bool ExportScene (const aiScene* scene, const std::string& format, Result& result)
{
if (scene == nullptr) {
result.errorCode = ErrorCode::ImportError;
Expand All @@ -36,7 +49,8 @@ static bool ExportScene (const aiScene* scene, Result& result)

Assimp::ExportProperties exportProperties;
exportProperties.SetPropertyBool ("JSON_SKIP_WHITESPACES", true);
aiReturn exportResult = exporter.Export (scene, "assjson", "result.json", 0u, &exportProperties);
std::string fileName = GetFileNameFromFormat (format);
aiReturn exportResult = exporter.Export (scene, format.c_str (), fileName.c_str (), 0u, &exportProperties);
if (exportResult != aiReturn_SUCCESS) {
result.errorCode = ErrorCode::ExportError;
return false;
Expand All @@ -46,18 +60,18 @@ static bool ExportScene (const aiScene* scene, Result& result)
return true;
}

Result ConvertFile (const File& file, const FileLoader& loader)
Result ConvertFile (const File& file, const std::string& format, const FileLoader& loader)
{
Assimp::Importer importer;
importer.SetIOHandler (new DelayLoadedIOSystemReadAdapter (file, loader));
const aiScene* scene = ImportFileListByMainFile (importer, file);

Result result;
ExportScene (scene, result);
ExportScene (scene, format, result);
return result;
}

Result ConvertFileList (const FileList& fileList)
Result ConvertFileList (const FileList& fileList, const std::string& format)
{
if (fileList.FileCount () == 0) {
return Result (ErrorCode::NoFilesFound);
Expand All @@ -76,14 +90,15 @@ Result ConvertFileList (const FileList& fileList)
}

Result result;
ExportScene (scene, result);
ExportScene (scene, format, result);
return result;
}

#ifdef EMSCRIPTEN

Result ConvertFileEmscripten (
const std::string& name,
const std::string& format,
const emscripten::val& content,
const emscripten::val& existsFunc,
const emscripten::val& loadFunc)
Expand Down Expand Up @@ -125,7 +140,7 @@ Result ConvertFileEmscripten (
Buffer buffer = emscripten::vecFromJSArray<std::uint8_t> (content);
File file (name, buffer);
FileLoaderEmscripten loader (existsFunc, loadFunc);
return ConvertFile (file, loader);
return ConvertFile (file, format, loader);
}

EMSCRIPTEN_BINDINGS (assimpjs)
Expand All @@ -149,8 +164,8 @@ EMSCRIPTEN_BINDINGS (assimpjs)
.function ("GetFile", &Result::GetFile)
;

emscripten::function<Result, const std::string&, const emscripten::val&, const emscripten::val&, const emscripten::val&> ("ConvertFile", &ConvertFileEmscripten);
emscripten::function<Result, const FileList&> ("ConvertFileList", &ConvertFileList);
emscripten::function<Result, const std::string&, const std::string&, const emscripten::val&, const emscripten::val&, const emscripten::val&> ("ConvertFile", &ConvertFileEmscripten);
emscripten::function<Result, const FileList&, const std::string&> ("ConvertFileList", &ConvertFileList);
}

#endif
4 changes: 2 additions & 2 deletions assimpjs/src/assimpjs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <vector>
#include <string>

Result ConvertFile (const File& file, const FileLoader& loader);
Result ConvertFileList (const FileList& fileList);
Result ConvertFile (const File& file, const std::string& format, const FileLoader& loader);
Result ConvertFileList (const FileList& fileList, const std::string& format);

#endif
21 changes: 13 additions & 8 deletions assimpjs/src/fileio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ static size_t ReadFromBuffer (const Buffer* buffer, size_t& position, void* pvBu
return readableElemCount;
}

static size_t WriteToBuffer (Buffer* buffer, size_t& position, const void* pvBuffer, size_t pSize, size_t pCount)
{
size_t memSize = pSize * pCount;
size_t newBufferSize = std::max (buffer->size (), position + memSize);
if (newBufferSize > buffer->size ()) {
buffer->resize (newBufferSize);
}
memcpy (buffer->data () + position, pvBuffer, memSize);
position += memSize;
return pCount;
}

static aiReturn SeekInBuffer (const Buffer* buffer, size_t& position, size_t pOffset, aiOrigin pOrigin)
{
switch (pOrigin) {
Expand Down Expand Up @@ -110,14 +122,7 @@ size_t BufferIOStreamWriteAdapter::Read (void* pvBuffer, size_t pSize, size_t pC

size_t BufferIOStreamWriteAdapter::Write (const void* pvBuffer, size_t pSize, size_t pCount)
{
size_t memSize = pSize * pCount;
size_t newBufferSize = std::max (buffer->size (), position + memSize);
if (newBufferSize > buffer->size ()) {
buffer->resize (newBufferSize);
}
memcpy (buffer->data () + position, pvBuffer, memSize);
position += memSize;
return memSize;
return WriteToBuffer (buffer, position, pvBuffer, pSize, pCount);
}

aiReturn BufferIOStreamWriteAdapter::Seek (size_t pOffset, aiOrigin pOrigin)
Expand Down
2 changes: 1 addition & 1 deletion demo/source/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function LoadModel (ajs, files, onLoad)
for (let i = 0; i < arrayBuffers.length; i++) {
fileList.AddFile (files[i].name, new Uint8Array (arrayBuffers[i]));
}
let result = ajs.ConvertFileList (fileList);
let result = ajs.ConvertFileList (fileList, 'assjson');
if (!result.IsSuccess () || result.FileCount () == 0) {
onLoad ({
error: result.GetErrorCode ()
Expand Down
2 changes: 1 addition & 1 deletion dist/assimpjs.js

Large diffs are not rendered by default.

Binary file modified dist/assimpjs.wasm
Binary file not shown.
4 changes: 2 additions & 2 deletions examples/browser_download_test.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
fileList.AddFile (files[i], new Uint8Array (arrayBuffers[i]));
}

// convert file list
let result = ajs.ConvertFileList (fileList);
// convert file list to assimp json
let result = ajs.ConvertFileList (fileList, 'assjson');

// check if the conversion succeeded
if (!result.IsSuccess () || result.FileCount () == 0) {
Expand Down
4 changes: 2 additions & 2 deletions examples/browser_dragdrop_test.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
fileList.AddFile (files[i].name, new Uint8Array (arrayBuffers[i]));
}

// convert file list
let result = ajs.ConvertFileList (fileList);
// convert file list to assimp json
let result = ajs.ConvertFileList (fileList, 'assjson');

// check if the conversion succeeded
if (!result.IsSuccess () || result.FileCount () == 0) {
Expand Down
2 changes: 2 additions & 0 deletions examples/node_local_delay_load_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ assimpjs.then ((ajs) => {
let result = ajs.ConvertFile (
// file name
'cube_with_materials.obj',
// file format
'assjson',
// file content as arraybuffer
fs.readFileSync ('testfiles/cube_with_materials.obj'),
// check if file exists by name
Expand Down
4 changes: 2 additions & 2 deletions examples/node_local_load_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ assimpjs.then ((ajs) => {
fs.readFileSync ('testfiles/cube_with_materials.mtl')
);

// convert file list
let result = ajs.ConvertFileList (fileList);
// convert file list to assimp json
let result = ajs.ConvertFileList (fileList, 'assjson');

// check if the conversion succeeded
if (!result.IsSuccess () || result.FileCount () == 0) {
Expand Down
25 changes: 24 additions & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function LoadModel (files)
let filePath = GetTestFileLocation (files[i]);
fileList.AddFile (filePath, fs.readFileSync (filePath))
}
return ajs.ConvertFileList (fileList);
return ajs.ConvertFileList (fileList, 'assjson');
}

function IsError (files)
Expand Down Expand Up @@ -61,6 +61,7 @@ it ('Independent order', function () {
it ('Delay load', function () {
let result = ajs.ConvertFile (
'OBJ/cube_usemtl.obj',
'assjson',
fs.readFileSync (GetTestFileLocation ('OBJ/cube_usemtl.obj')),
function (fileName) {
return fs.existsSync (GetTestFileLocation ('OBJ/' + fileName));
Expand All @@ -77,6 +78,28 @@ it ('Delay load', function () {
assert.deepStrictEqual (scene.materials[1].properties[2].value, [1, 1, 1]);
});

it ('glTF export', function () {
let files = ['OBJ/cube_usemtl.obj', 'OBJ/cube_usemtl.mtl'];
let fileList = new ajs.FileList ();
for (let i = 0; i < files.length; i++) {
let filePath = GetTestFileLocation (files[i]);
fileList.AddFile (filePath, fs.readFileSync (filePath))
}
{
let result = ajs.ConvertFileList (fileList, 'gltf2');
assert (result.IsSuccess ());
assert.equal (result.FileCount (), 2);
assert.equal (result.GetFile (0).GetPath (), 'result.gltf');
assert.equal (result.GetFile (1).GetPath (), 'result.bin');
}
{
let result = ajs.ConvertFileList (fileList, 'glb2');
assert (result.IsSuccess ());
assert.equal (result.FileCount (), 1);
assert.equal (result.GetFile (0).GetPath (), 'result.glb');
}
});

it ('3D', function () {
assert (IsSuccess (['3D/box.uc', '3D/box_a.3d', '3D/box_d.3d']));
});
Expand Down

0 comments on commit fe89582

Please sign in to comment.