Skip to content

Commit

Permalink
Merge pull request #48 from vitrivr/feature/3d-objects
Browse files Browse the repository at this point in the history
Feature/3d objects
  • Loading branch information
rahelarnold98 authored Mar 12, 2024
2 parents 4a9088f + 2ebd4ba commit 287d9c5
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package org.vitrivr.engine.core.content

import org.vitrivr.engine.core.model.content.element.AudioContent
import org.vitrivr.engine.core.model.content.element.ImageContent
import org.vitrivr.engine.core.model.content.element.Model3DContent
import org.vitrivr.engine.core.model.content.element.TextContent
import org.vitrivr.engine.core.model.mesh.Model3D
import java.awt.image.BufferedImage
import java.nio.ShortBuffer

Expand All @@ -12,4 +14,6 @@ interface ContentFactory {
fun newAudioContent(channel: Int, samplingRate: Int, audio: ShortBuffer): AudioContent

fun newTextContent(text: String): TextContent

fun newMeshContent(model3D: Model3D): Model3DContent
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@ package org.vitrivr.engine.core.content.impl
import org.vitrivr.engine.core.content.ContentFactory
import org.vitrivr.engine.core.model.content.element.AudioContent
import org.vitrivr.engine.core.model.content.element.ImageContent
import org.vitrivr.engine.core.model.content.element.Model3DContent
import org.vitrivr.engine.core.model.content.element.TextContent
import org.vitrivr.engine.core.model.content.impl.InMemoryAudioContent
import org.vitrivr.engine.core.model.content.impl.InMemoryImageContent
import org.vitrivr.engine.core.model.content.impl.InMemoryMeshContent
import org.vitrivr.engine.core.model.content.impl.InMemoryTextContent
import org.vitrivr.engine.core.model.mesh.Model3D
import java.awt.image.BufferedImage
import java.nio.ShortBuffer

class
InMemoryContentFactory : ContentFactory {
class InMemoryContentFactory : ContentFactory {

override fun newImageContent(bufferedImage: BufferedImage): ImageContent = InMemoryImageContent(bufferedImage)

override fun newAudioContent(channel: Int, samplingRate: Int, audio: ShortBuffer): AudioContent = InMemoryAudioContent(channel, samplingRate, audio)

override fun newTextContent(text: String): TextContent = InMemoryTextContent(text)

override fun newMeshContent(model3D: Model3D): Model3DContent = InMemoryMeshContent(model3D)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.vitrivr.engine.core.model.content.impl

import org.vitrivr.engine.core.model.content.element.ImageContent
import org.vitrivr.engine.core.model.content.element.Model3DContent
import org.vitrivr.engine.core.model.mesh.Model3D
import java.awt.image.BufferedImage

/**
* A naive in-memory implementation of the [ImageContent] interface.
*
* Warning: Usage of [InMemoryMeshContent] may lead to out-of-memory situations in large extraction pipelines.
*
* @author Luca Rossetto.
* @version 1.0.0
*/
data class InMemoryMeshContent(override val content: Model3D) : Model3DContent
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import io.github.oshai.kotlinlogging.KotlinLogging
import org.vitrivr.engine.core.content.ContentFactory
import org.vitrivr.engine.core.model.content.element.AudioContent
import org.vitrivr.engine.core.model.content.element.ImageContent
import org.vitrivr.engine.core.model.content.element.Model3DContent
import org.vitrivr.engine.core.model.content.element.TextContent
import org.vitrivr.engine.core.model.mesh.Model3D
import org.vitrivr.engine.core.util.extension.getRGBArray
import org.vitrivr.engine.core.util.extension.setRGBArray
import java.awt.SystemColor.text
import java.awt.image.BufferedImage
import java.io.IOException
import java.lang.ref.PhantomReference
Expand Down Expand Up @@ -171,4 +174,7 @@ class FileCachedContentFactory(private val basePath: Path) : ContentFactory {
}

override fun newTextContent(text: String): TextContent = FileBackedTextContent(text)
override fun newMeshContent(model3D: Model3D): Model3DContent {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.vitrivr.engine.core.model.content.element.ContentElement
import org.vitrivr.engine.core.model.content.element.ImageContent
import org.vitrivr.engine.core.model.content.element.TextContent
import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor
import org.vitrivr.engine.core.model.metamodel.Analyser
import org.vitrivr.engine.core.model.metamodel.Schema
import org.vitrivr.engine.core.model.retrievable.Retrievable
import org.vitrivr.engine.core.operators.Operator
Expand Down
73 changes: 73 additions & 0 deletions vitrivr-engine-plugin-m3d/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
plugins {
id 'maven-publish'
id 'org.jetbrains.kotlin.plugin.serialization' version "$version_kotlin"
id 'signing'
}

project.ext.lwjglVersion = "3.3.3"
Expand Down Expand Up @@ -75,4 +77,75 @@ dependencies {
runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
if (lwjglNatives == "natives-macos" || lwjglNatives == "natives-macos-arm64") runtimeOnly "org.lwjgl:lwjgl-vulkan::$lwjglNatives"

}

dependencies {
api project(':vitrivr-engine-core')
}

/* Publication of vitrivr engine query to Maven Central. */
publishing {
publications {
mavenJava(MavenPublication) {
groupId = 'org.vitrivr'
artifactId = 'vitrivr-engine-plugin-m3d'
version = System.getenv().getOrDefault("MAVEN_PUBLICATION_VERSION", version.toString())
from components.java
pom {
name = 'vitrivr Engine Base'
description = 'Shared based components of the vitrivr multimedia retrieval engine (e.g., database connection, features).'
url = 'https://github.com/vitrivr/vitrivr-engine/'
licenses {
license {
name = 'MIT License'
}
}
developers {
developer {
id = 'ppanopticon'
name = 'Ralph Gasser'
email = '[email protected]'
}
developer {
id = 'lucaro'
name = 'Luca Rossetto'
email = '[email protected]'
}
developer {
id = 'net-cscience-raphael'
name = 'Raphael Waltensül'
email = '[email protected]'
}
developer {
id = 'rahelarnold98'
name = 'Rahel Arnold'
email = '[email protected]'
}
developer {
id = 'faberf'
name = 'Fynn Faber'
email = '[email protected]'
}
}
scm {
connection = 'scm:git:https://github.com/vitrivr/vitrivr-engine.git'
url = 'https://github.com/vitrivr/vitrivr-engine/'
}
}
}
}
repositories {
repositories {
maven {
def releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
def snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/'
name = "OSSRH"
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
credentials {
username = System.getenv("MAVEN_USERNAME")
password = System.getenv("MAVEN_PASSWORD")
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.vitrivr.engine.model3d.decoder

import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.mapNotNull
import org.vitrivr.engine.core.context.IndexContext
import org.vitrivr.engine.core.model.content.decorators.SourcedContent
import org.vitrivr.engine.core.model.content.element.Model3DContent
import org.vitrivr.engine.core.operators.ingest.Decoder
import org.vitrivr.engine.core.operators.ingest.DecoderFactory
import org.vitrivr.engine.core.operators.ingest.Enumerator
import org.vitrivr.engine.core.source.MediaType
import org.vitrivr.engine.core.source.Source
import org.vitrivr.engine.model3d.ModelHandler
import java.io.IOException

/**
* A [Decoder] that can decode [MeshDecoder] from a [Source] of [MediaType.OBJ] or [MediaType.GLTF].
*
* @author Rahel Arnold
* @version 1.0.0
*/
class MeshDecoder : DecoderFactory {

/**
* Creates a new [Decoder] instance from this [Model3DDecoder].
*
* @param input The input [Enumerator].
* @param context The [IndexContext] to use.
* @param parameters Optional set of parameters.
*/
override fun newOperator(input: Enumerator, context: IndexContext, parameters: Map<String, String>): Decoder =
Instance(input, context)

/**
* The [Decoder] returned by this [MeshDecoder].
*/
private class Instance(override val input: Enumerator, private val context: IndexContext) : Decoder {

/** [KLogger] instance. */
private val logger: KLogger = KotlinLogging.logger {}

/**
* Converts this [MeshDecoder] to a [Flow] of [Content] elements.
*
* Produces [MeshDecoder] elements.
*
* @param scope The [CoroutineScope] used for conversion.
* @return [Flow] of [Content]
*/
override fun toFlow(scope: CoroutineScope): Flow<Model3DContent> = this.input.toFlow(scope).filter {
it.type == MediaType.MESH
}.mapNotNull { source ->
logger.info { "Decoding source ${source.name} (${source.sourceId})" }
try {
val handler = ModelHandler()
val model = source.newInputStream().use {
this.context.contentFactory.newMeshContent(handler.loadModel(source.sourceId.toString(), source.name.substringAfterLast(".")))
}
MeshDecoderWithSource(model, source)
} catch (e: IOException) {
logger.error(e) { "Failed to decode 3D model from $source due to an IO exception." }
null
}
}


/**
* An internal class that represents a single 3D model associated with a [Source].
*
* @see MeshDecoder
* @see SourcedContent
*/
class MeshDecoderWithSource(model: Model3DContent, override val source: Source) :
Model3DContent by model, SourcedContent
}
}

0 comments on commit 287d9c5

Please sign in to comment.