Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for virtual filesystems through IOSystem #10

Merged
merged 8 commits into from
Mar 30, 2018
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# Created by .ignore support plugin (hsz.mobi)
.idea/
.idea/
out
build
.gradle
41 changes: 24 additions & 17 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,20 @@ apply plugin: 'com.github.johnrengelman.shadow'

dependencies {

compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
compile "org.jetbrains.kotlin:kotlin-reflect"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
implementation "org.jetbrains.kotlin:kotlin-reflect"

compile 'com.github.kotlin-graphics:uno-sdk:641ec79aa3d5cf696590276f75b8b89804dc9d09'
implementation 'com.github.kotlin-graphics:uno-sdk:641ec79aa3d5cf696590276f75b8b89804dc9d09'

testCompile 'io.kotlintest:kotlintest:2.0.7'

compile 'io.github.microutils:kotlin-logging:1.4.6'
implementation 'io.github.microutils:kotlin-logging:1.4.6'

// compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0'
// compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.10.0'

compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.25'
//implementation group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.25'
implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'

switch (OperatingSystem.current()) {
case OperatingSystem.WINDOWS:
Expand All @@ -54,19 +55,21 @@ dependencies {
ext.lwjglNatives = "natives-macos"
break
}

ext.lwjglVersion = "3.1.5-SNAPSHOT"
compile "org.lwjgl:lwjgl:${lwjglVersion}"
compile "org.lwjgl:lwjgl-glfw:${lwjglVersion}"
compile "org.lwjgl:lwjgl-jemalloc:${lwjglVersion}"
compile "org.lwjgl:lwjgl-openal:${lwjglVersion}"
compile "org.lwjgl:lwjgl-opengl:${lwjglVersion}"
compile "org.lwjgl:lwjgl-stb:${lwjglVersion}"
runtime "org.lwjgl:lwjgl:${lwjglVersion}:${lwjglNatives}"
runtime "org.lwjgl:lwjgl-glfw:${lwjglVersion}:${lwjglNatives}"
runtime "org.lwjgl:lwjgl-jemalloc:${lwjglVersion}:${lwjglNatives}"
runtime "org.lwjgl:lwjgl-openal:${lwjglVersion}:${lwjglNatives}"
runtime "org.lwjgl:lwjgl-opengl:${lwjglVersion}:${lwjglNatives}"
runtime "org.lwjgl:lwjgl-stb:${lwjglVersion}:${lwjglNatives}"
implementation "org.lwjgl:lwjgl:${lwjglVersion}"
implementation "org.lwjgl:lwjgl-glfw:${lwjglVersion}"
implementation "org.lwjgl:lwjgl-jemalloc:${lwjglVersion}"
implementation "org.lwjgl:lwjgl-openal:${lwjglVersion}"
implementation "org.lwjgl:lwjgl-opengl:${lwjglVersion}"
implementation "org.lwjgl:lwjgl-stb:${lwjglVersion}"

testRuntime "org.lwjgl:lwjgl:${lwjglVersion}:${lwjglNatives}"
testRuntime "org.lwjgl:lwjgl-glfw:${lwjglVersion}:${lwjglNatives}"
testRuntime "org.lwjgl:lwjgl-jemalloc:${lwjglVersion}:${lwjglNatives}"
testRuntime "org.lwjgl:lwjgl-openal:${lwjglVersion}:${lwjglNatives}"
testRuntime "org.lwjgl:lwjgl-opengl:${lwjglVersion}:${lwjglNatives}"
testRuntime "org.lwjgl:lwjgl-stb:${lwjglVersion}:${lwjglNatives}"
}

repositories {
Expand All @@ -86,6 +89,10 @@ task javadocJar(type: Jar, dependsOn: javadoc) {
from javadoc.destinationDir
}

test {
workingDir = "src/test/resources"
}

artifacts {
archives sourcesJar
archives javadocJar
Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/assimp/BaseImporter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ abstract class BaseImporter {
* time to examine the contents of the file to be loaded for magic bytes, keywords, etc to be able to load files
* with unknown/not existent file extensions.
* @return true if the class can read this file, false if not. */
abstract fun canRead(file: URI, checkSig: Boolean): Boolean
abstract fun canRead(file: String, pIOHandler: IOSystem, checkSig: Boolean): Boolean
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any user functions should have this same idea applied


/** Imports the given file and returns the imported data.
* If the import succeeds, ownership of the data is transferred to the caller. If the import fails, null is
Expand All @@ -48,7 +48,7 @@ abstract class BaseImporter {
* exception is thrown somewhere in internReadFile(), this function will catch it and transform it into a suitable
* response to the caller.
*/
fun readFile(imp: Importer, file: URI): AiScene? {
fun readFile(imp: Importer, pIOHandler: IOSystem, filePath: String): AiScene? {
progress = imp.progressHandler
assert(progress != null)

Expand All @@ -60,7 +60,7 @@ abstract class BaseImporter {

// dispatch importing
try {
internReadFile(file, sc)
internReadFile(filePath, pIOHandler, sc)
} catch (err: Exception) {
// extract error description
err.printStackTrace()
Expand Down Expand Up @@ -120,9 +120,9 @@ abstract class BaseImporter {
* @param file Path of the file to be imported.
* @param scene The scene object to hold the imported data. Null is not a valid parameter.
* */
open fun internReadFile(file: String, scene: AiScene) = internReadFile(file.uri, scene)
open fun internReadFile(file: String, pIOHandler: IOSystem, scene: AiScene) = Unit//internReadFile(file.uri, scene)

open fun internReadFile(file: URI, scene: AiScene) = Unit
//open fun internReadFile(file: URI, pIOHandler: IOSystem, scene: AiScene) = Unit

companion object {
/** Extract file extension from a string
Expand Down
31 changes: 31 additions & 0 deletions src/main/kotlin/assimp/DefaultIOSystem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package assimp

import java.io.*

class DefaultIOSystem : IOSystem{
override fun Exists(pFile: String) = File(pFile).exists()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lowercase function names


override fun Open(pFile: String): IOStream {
var file = File(pFile)
println(File(".").absolutePath)
if(!file.exists())
throw IOException("File doesn't exist: "+pFile)


return FileIOStream(file)
}

class FileIOStream(val file: File) : IOStream{
override fun read() = FileInputStream(file)

override fun reader() = BufferedReader(FileReader(file))

override val path: String
get() = file.absolutePath

override val filename: String
get() = file.name

override fun parentPath() = file.parentFile.absolutePath
}
}
17 changes: 17 additions & 0 deletions src/main/kotlin/assimp/IOStream.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package assimp

import java.io.BufferedReader
import java.io.InputStream
import java.io.Reader

interface IOStream {
val path : String

val filename: String

fun read() : InputStream

fun reader() : BufferedReader

fun parentPath() : String
}
12 changes: 12 additions & 0 deletions src/main/kotlin/assimp/IOSystem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package assimp

/** Interface to the file system. */
interface IOSystem {
fun Exists(pFile: String): Boolean

fun Open(pFile : String): IOStream

fun Close(ioStream: IOStream) = Unit //unused ?

fun getOsSeperator() = "/"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separator: java.io.File.separator

}
23 changes: 15 additions & 8 deletions src/main/kotlin/assimp/Importer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ constructor() {
}
}

var ioHandler: IOSystem
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the way the original assimp does it though
http://assimp.sourceforge.net/lib_html/class_assimp_1_1_importer.html#a1161f46318af18bb86dfe0fc3edea4df

Is there some Kotlin trickery I can use to mirror that into the importers ( probably has to do with var and get() = something something ) ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, after playing around myself, you're good on this.

get() = impl.ioSystem

set(value) { if(value != null) impl.ioSystem = value}

/** Checks whether a default progress handler is active
* A default handler is active as long the application doesn't supply its own custom progress handler via
* setProgressHandler().
Expand Down Expand Up @@ -221,6 +226,8 @@ constructor() {
/** Get the currently set progress handler */
val progressHandler get() = impl.progressHandler

fun readFile(uri: URI, flags: Int = 0) = readFile(uri.path, flags)

/** Reads the given file and returns its contents if successful.
*
* If the call succeeds, the contents of the file are returned as a pointer to an AiScene object. The returned data
Expand All @@ -238,11 +245,10 @@ constructor() {
*
* @note Assimp is able to determine the file format of a file automatically.
*/
fun readFile(file: String, flags: Int = 0) = readFile(file.uri, flags)
//fun readFile(file: URI, flags: Int = 0): AiScene? {
fun readFile(file: String, flags: Int = 0): AiScene? {

fun readFile(file: URI, flags: Int = 0): AiScene? {

writeLogOpening(file.path)
writeLogOpening(file)

// Check whether this Importer instance has already loaded a scene. In this case we need to delete the old one
if (impl.scene != null) {
Expand All @@ -251,19 +257,20 @@ constructor() {
}

// First check if the file is accessible at all
if (!file.exists()) {
// handled by exception in IOSystem
/*if (!file.exists()) {
impl.errorString = "Unable to open file \"$file\"."
logger.error { impl.errorString }
return null
}
}*/

// TODO std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
// if (profiler) {
// profiler->BeginRegion("total");
// }

// Find an worker class which can handle the file
val imp = impl.importer.find { it.canRead(file, false) }
val imp = impl.importer.find { it.canRead(file, ioHandler,false) }

if (imp == null) {
// not so bad yet ... try format auto detection.
Expand Down Expand Up @@ -300,7 +307,7 @@ constructor() {
// profiler->BeginRegion("import");
// }

impl.scene = imp.readFile(this, file)
impl.scene = imp.readFile(this, ioHandler, file)
impl.progressHandler.updateFileRead(fileSize, fileSize)

// if (profiler) { TODO
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/assimp/ImporterPimpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class ImporterPimpl {
var progressHandler: ProgressHandler = DefaultProgressHandler()
var isDefaultProgressHandler = true

var ioSystem: IOSystem = DefaultIOSystem()

/** Format-specific importer worker objects - one for each format we can read.*/
val importer = importerInstanceList

Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/assimp/format/X/XFileImporter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ class XFileImporter : BaseImporter() {

var mBuffer: Pointer<Char> = Pointer<Char>(arrayOf())

override fun canRead(pFile: URI, checkSig: Boolean): Boolean {
override fun canRead(pFile: String, ioSystem: IOSystem, checkSig: Boolean): Boolean {
if (!checkSig) //Check File Extension
return pFile.s.substring(pFile.s.lastIndexOf('.') + 1).toLowerCase() == "x"
return pFile.substring(pFile.lastIndexOf('.') + 1).toLowerCase() == "x"
else //Check file Header
return false
}

override fun internReadFile(pFile: URI, pScene: AiScene) {
override fun internReadFile(pFile: String, ioSystem: IOSystem, pScene: AiScene) {
// Read file into memory
var file = File(pFile)
if (!file.canRead()) throw FileSystemException(file, null, "Failed to open file \$pFile.")
Expand Down
9 changes: 5 additions & 4 deletions src/main/kotlin/assimp/format/assbin/AssbinLoader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import glm_.*
import java.io.File
import java.io.InputStream
import java.net.URI
import java.net.URL

class AssbinLoader : BaseImporter() {

Expand All @@ -21,12 +22,12 @@ class AssbinLoader : BaseImporter() {
var compressed = false
private val be = false // big endian TODO glm global?

override fun canRead(file: URI, checkSig: Boolean) =
File(file).inputStream().use { i -> "ASSIMP.binary-dump.".all { it.i == i.read() } }
override fun canRead(file: String, ioSystem: IOSystem, checkSig: Boolean) =
ioSystem.Open(file).read().use { i -> "ASSIMP.binary-dump.".all { it.i == i.read() } }

override fun internReadFile(file: URI, scene: AiScene) {
override fun internReadFile(file: String, ioSystem: IOSystem, scene: AiScene) {

file.toURL().openStream().use {
ioSystem.Open(file).read().use {

it.skip(44) // signature

Expand Down
7 changes: 3 additions & 4 deletions src/main/kotlin/assimp/format/blender/BlenderLoader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ import java.io.FileOutputStream
import java.io.FileInputStream
import java.util.zip.GZIPInputStream


lateinit var buffer: ByteBuffer

val tokens = "BLENDER"

class BlenderImporter : BaseImporter() {

/** Returns whether the class can handle the format of the given file. */
override fun canRead(file: URI, checkSig: Boolean): Boolean {
override fun canRead(file: String, ioSystem: IOSystem, checkSig: Boolean): Boolean {

val extension = file.extension
val extension = getExtension(file)
if (extension == "blend") return true
else if (extension.isEmpty() || checkSig) {
TODO()
Expand All @@ -46,7 +45,7 @@ class BlenderImporter : BaseImporter() {
maxMinor = 50,
fileExtensions = listOf("blend"))

override fun internReadFile(file: URI, scene: AiScene) {
override fun internReadFile(file: String, ioSystem: IOSystem, scene: AiScene) {

val fileChannel = RandomAccessFile(File(file), "r").channel
buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size()).order(ByteOrder.nativeOrder())
Expand Down
15 changes: 8 additions & 7 deletions src/main/kotlin/assimp/format/collada/ColladaLoader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ColladaLoader : BaseImporter() {
}

/** Filename, for a verbose error message */
lateinit var mFileName: URI
lateinit var mFileName: String

/** Which mesh-material compound was stored under which mesh ID */
val mMeshIndexByID = mutableMapOf<ColladaMeshIndex, Int>()
Expand Down Expand Up @@ -68,10 +68,10 @@ class ColladaLoader : BaseImporter() {

// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
override fun canRead(file: URI, checkSig: Boolean): Boolean {
override fun canRead(file: String, ioSystem: IOSystem, checkSig: Boolean): Boolean {

// check file extension
val extension = file.s.substring(file.s.lastIndexOf('.') + 1).toLowerCase()
val extension = file.substring(file.lastIndexOf('.') + 1).toLowerCase()

if (extension == "dae")
return true
Expand All @@ -84,10 +84,10 @@ class ColladaLoader : BaseImporter() {

// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
override fun internReadFile(file: URI, scene: AiScene) {
override fun internReadFile(file: String, ioSystem: IOSystem, scene: AiScene) {
mFileName = file
// parse the input file
val parser = ColladaParser(file)
val parser = ColladaParser(ioSystem.Open(file))
if (parser.mRootNode == null) throw Error("Collada: File came out empty. Something is wrong here.")
// create the materials first, for the meshes to find
buildMaterials(parser)
Expand Down Expand Up @@ -516,7 +516,7 @@ class ColladaLoader : BaseImporter() {
val dstBones = MutableList(numBones, { mutableListOf<AiVertexWeight>() })

// build a temporary array of pointers to the start of each vertex's weights
val weightStartPerVertex = ArrayList<Long>()
val weightStartPerVertex = LongArray(pSrcController.weightCounts.size)

var pit = 0L
pSrcController.weightCounts.forEachIndexed { i, a ->
Expand Down Expand Up @@ -651,7 +651,8 @@ class ColladaLoader : BaseImporter() {
0
}

mat.textures.add(idx, tex)
if(idx != -1)
mat.textures.add(idx, tex)
}

/** Fills materials from the collada material definitions */
Expand Down