Use custom IO callbacks for assimp;

This commit is contained in:
bjorn 2017-10-21 00:19:05 -07:00
parent 9a47643d20
commit a12a003ccb
4 changed files with 128 additions and 21 deletions

View File

@ -195,7 +195,9 @@ int l_lovrFilesystemGetSaveDirectory(lua_State* L) {
int l_lovrFilesystemGetSize(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
lua_pushinteger(L, lovrFilesystemGetSize(path));
File* file = lovrFilesystemOpen(path, OPEN_READ);
lua_pushinteger(L, lovrFilesystemGetSize(file));
lovrFilesystemClose(file);
return 1;
}

View File

@ -55,6 +55,10 @@ void lovrFilesystemDestroy() {
PHYSFS_deinit();
}
void lovrFilesystemClose(File* file) {
PHYSFS_close(file);
}
int lovrFilesystemCreateDirectory(const char* path) {
return !PHYSFS_mkdir(path);
}
@ -63,6 +67,10 @@ int lovrFilesystemExists(const char* path) {
return PHYSFS_exists(path);
}
void lovrFilesystemFileRead(File* file, void* data, size_t size, size_t count, size_t* bytesRead) {
*bytesRead = PHYSFS_read(file, data, size, count);
}
int lovrFilesystemGetAppdataDirectory(char* dest, unsigned int size) {
#ifdef __APPLE__
const char* home;
@ -136,15 +144,8 @@ const char* lovrFilesystemGetSaveDirectory() {
return state.savePathFull;
}
int lovrFilesystemGetSize(const char* path) {
PHYSFS_file* handle = PHYSFS_openRead(path);
if (!handle) {
return -1;
}
int length = PHYSFS_fileLength(handle);
PHYSFS_close(handle);
return length;
size_t lovrFilesystemGetSize(File* file) {
return PHYSFS_fileLength(file);
}
const char* lovrFilesystemGetSource() {
@ -171,16 +172,24 @@ int lovrFilesystemMount(const char* path, const char* mountpoint, int append) {
return !PHYSFS_mount(path, mountpoint, append);
}
void* lovrFilesystemOpen(const char* path, FileMode mode) {
switch (mode) {
case OPEN_READ: return PHYSFS_openRead(path);
case OPEN_WRITE: return PHYSFS_openWrite(path);
case OPEN_APPEND: return PHYSFS_openAppend(path);
}
}
void* lovrFilesystemRead(const char* path, size_t* bytesRead) {
// Open file
PHYSFS_file* handle = PHYSFS_openRead(path);
if (!handle) {
PHYSFS_file* file = lovrFilesystemOpen(path, OPEN_READ);
if (!file) {
return NULL;
}
// Get file size
int size = PHYSFS_fileLength(handle);
int size = PHYSFS_fileLength(file);
if (size < 0) {
return NULL;
}
@ -192,8 +201,8 @@ void* lovrFilesystemRead(const char* path, size_t* bytesRead) {
}
// Perform read
*bytesRead = PHYSFS_read(handle, data, 1, size);
PHYSFS_close(handle);
lovrFilesystemFileRead(file, data, 1, size, bytesRead);
lovrFilesystemClose(file);
// Make sure we got everything
if (*bytesRead != (size_t) size) {
@ -208,6 +217,10 @@ int lovrFilesystemRemove(const char* path) {
return !PHYSFS_delete(path);
}
int lovrFilesystemSeek(File* file, size_t position) {
return !PHYSFS_seek(file, position);
}
int lovrFilesystemSetIdentity(const char* identity) {
state.identity = identity;
@ -238,17 +251,21 @@ int lovrFilesystemSetIdentity(const char* identity) {
return 0;
}
size_t lovrFilesystemTell(File* file) {
return PHYSFS_tell(file);
}
int lovrFilesystemUnmount(const char* path) {
return !PHYSFS_removeFromSearchPath(path);
}
int lovrFilesystemWrite(const char* path, const char* content, size_t size, int append) {
PHYSFS_file* handle = append ? PHYSFS_openAppend(path) : PHYSFS_openWrite(path);
if (!handle) {
PHYSFS_file* file = lovrFilesystemOpen(path, append ? OPEN_APPEND : OPEN_WRITE);
if (!file) {
return 0;
}
int bytesWritten = PHYSFS_write(handle, content, 1, size);
PHYSFS_close(handle);
int bytesWritten = PHYSFS_write(file, content, 1, size);
lovrFilesystemClose(file);
return bytesWritten;
}

View File

@ -6,6 +6,14 @@
typedef void getDirectoryItemsCallback(void* userdata, const char* dir, const char* file);
typedef enum {
OPEN_READ,
OPEN_WRITE,
OPEN_APPEND
} FileMode;
typedef void File;
typedef struct {
char* source;
const char* identity;
@ -16,8 +24,10 @@ typedef struct {
void lovrFilesystemInit(const char* arg0, const char* arg1);
void lovrFilesystemDestroy();
void lovrFilesystemClose(File* file);
int lovrFilesystemCreateDirectory(const char* path);
int lovrFilesystemExists(const char* path);
void lovrFilesystemFileRead(File* file, void* data, size_t size, size_t count, size_t* bytesRead);
int lovrFilesystemGetAppdataDirectory(char* dest, unsigned int size);
void lovrFilesystemGetDirectoryItems(const char* path, getDirectoryItemsCallback callback, void* userdata);
int lovrFilesystemGetExecutablePath(char* dest, unsigned int size);
@ -25,16 +35,19 @@ const char* lovrFilesystemGetIdentity();
long lovrFilesystemGetLastModified(const char* path);
const char* lovrFilesystemGetRealDirectory(const char* path);
const char* lovrFilesystemGetSaveDirectory();
int lovrFilesystemGetSize(const char* path);
size_t lovrFilesystemGetSize(File* file);
const char* lovrFilesystemGetSource();
const char* lovrFilesystemGetUserDirectory();
int lovrFilesystemIsDirectory(const char* path);
int lovrFilesystemIsFile(const char* path);
int lovrFilesystemIsFused();
int lovrFilesystemMount(const char* path, const char* mountpoint, int append);
File* lovrFilesystemOpen(const char* path, FileMode mode);
void* lovrFilesystemRead(const char* path, size_t* bytesRead);
int lovrFilesystemRemove(const char* path);
int lovrFilesystemSeek(File* file, size_t position);
int lovrFilesystemSetIdentity(const char* identity);
int lovrFilesystemSetSource(const char* source);
size_t lovrFilesystemTell(File* file);
int lovrFilesystemUnmount(const char* path);
int lovrFilesystemWrite(const char* path, const char* content, size_t size, int append);

View File

@ -1,6 +1,8 @@
#include "loaders/model.h"
#include "filesystem/filesystem.h"
#include "math/mat4.h"
#include <stdlib.h>
#include <assimp/cfileio.h>
#include <assimp/cimport.h>
#include <assimp/config.h>
#include <assimp/scene.h>
@ -9,6 +11,74 @@
#include <assimp/vector3.h>
#include <assimp/postprocess.h>
// Blob IO (to avoid reading data twice)
static unsigned long assimpBlobRead(struct aiFile* file, char* buffer, size_t size, size_t count) {
Blob* blob = (Blob*) file->UserData;
char* data = blob->data;
memcpy(buffer, data, count * size * sizeof(char));
return count * size * sizeof(char);
}
static size_t assimpBlobGetSize(struct aiFile* file) {
Blob* blob = (Blob*) file->UserData;
return blob->size;
}
static aiReturn assimpBlobSeek(struct aiFile* file, unsigned long position, enum aiOrigin origin) {
lovrThrow("Seek is not implemented for Blobs");
return aiReturn_FAILURE;
}
static unsigned long assimpBlobTell(struct aiFile* file) {
lovrThrow("Tell is not implemented for Blobs");
return 0;
}
// File IO (for reading referenced materials/textures)
static unsigned long assimpFileRead(struct aiFile* file, char* buffer, size_t size, size_t count) {
size_t bytesRead;
lovrFilesystemFileRead(file->UserData, buffer, count, size, &bytesRead);
return bytesRead;
}
static size_t assimpFileGetSize(struct aiFile* file) {
return lovrFilesystemGetSize(file->UserData);
}
static aiReturn assimpFileSeek(struct aiFile* file, unsigned long position, enum aiOrigin origin) {
return lovrFilesystemSeek(file->UserData, position) ? aiReturn_FAILURE : aiReturn_SUCCESS;
}
static unsigned long assimpFileTell(struct aiFile* file) {
return lovrFilesystemTell(file->UserData);
}
static struct aiFile* assimpFileOpen(struct aiFileIO* io, const char* path, const char* mode) {
struct aiFile* file = malloc(sizeof(struct aiFile));
Blob* blob = (Blob*) io->UserData;
if (!strcmp(blob->name, path)) {
file->ReadProc = assimpBlobRead;
file->FileSizeProc = assimpBlobGetSize;
file->SeekProc = assimpBlobSeek;
file->TellProc = assimpBlobTell;
file->UserData = (void*) blob;
} else {
file->ReadProc = assimpFileRead;
file->FileSizeProc = assimpFileGetSize;
file->SeekProc = assimpFileSeek;
file->TellProc = assimpFileTell;
file->UserData = lovrFilesystemOpen(path, OPEN_READ);
}
return file;
}
static void assimpFileClose(struct aiFileIO* io, struct aiFile* file) {
void* blob = io->UserData;
if (file->UserData != blob) {
lovrFilesystemClose(file->UserData);
}
}
static void assimpSumChildren(struct aiNode* assimpNode, int* totalChildren) {
(*totalChildren)++;
for (unsigned int i = 0; i < assimpNode->mNumChildren; i++) {
@ -44,10 +114,15 @@ ModelData* lovrModelDataCreate(Blob* blob) {
ModelData* modelData = malloc(sizeof(ModelData));
if (!modelData) return NULL;
struct aiFileIO assimpIO;
assimpIO.OpenProc = assimpFileOpen;
assimpIO.CloseProc = assimpFileClose;
assimpIO.UserData = (void*) blob;
struct aiPropertyStore* propertyStore = aiCreatePropertyStore();
aiSetImportPropertyInteger(propertyStore, AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_POINT | aiPrimitiveType_LINE);
unsigned int flags = aiProcessPreset_TargetRealtime_MaxQuality | aiProcess_OptimizeGraph | aiProcess_FlipUVs;
const struct aiScene* scene = aiImportFileFromMemoryWithProperties(blob->data, blob->size, flags, NULL, propertyStore);
const struct aiScene* scene = aiImportFileExWithProperties(blob->name, flags, &assimpIO, propertyStore);
aiReleasePropertyStore(propertyStore);
modelData->nodeCount = 0;