-
Notifications
You must be signed in to change notification settings - Fork 3
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
Feature: 3D Renderer and Preview Export of Thumbnails #87
Conversation
Thanks for the PR. In order to be able to review this it would be nice if you could add some minimal working example / documentation snippet as to how this can be used and tested. Furthermore, I was wondering if it would be possible to have a minimal UnitTest that makes sure that rendering works. See PR #84 for further reference. |
In addition to the detailed comments and the previous remark, I have two more fundamental issue with this PR and the way the M3D module is setup:
In its current state, the PR seems to violate some basic principles of the project (e.g., the ability to include or omit certain modules). Furthermore, it seems to be a bit messy since it's littered with empty classes and deprecated code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pull request is clearly not ready. It contains lots of Java code that has no place in a kotlin code base (especially not under src/main/kotlin), including various deprecated methods, interfaces, and classes. The rendering mechanism is needlessly complicated and does not adhere to any of the architectural conventions we introduced in this project. The way this is now, this looks not maintainable. Some substantial rework is required before this can be merged.
* position and scale the model in the scene. The [Material] objects are used to define the | ||
* appearance of the model. | ||
*/ | ||
data class Model( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This, again, is a very generic name, as it could 'model' anything. I suggest renaming it to something more descriptive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed model to model3d to specify that a 3d model is used
@@ -117,7 +117,7 @@ class CachedContentFactory : ContentFactoriesFactory { | |||
return content | |||
} | |||
|
|||
override fun newMeshContent(model3D: Model3D): Model3DContent { | |||
override fun newMeshContent(model: Model): ModelContent { | |||
check(!this.closed) { "CachedContentFactory has been closed." } | |||
TODO() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be properly implemented before merging this PR.
|
||
/** | ||
* A 3D [ContentElement]. | ||
* | ||
* @author Rahel Arnold | ||
* @version 1.0.0 | ||
*/ | ||
interface Model3DContent: ContentElement<Model3D>{ | ||
/** The [ContentType] of a [Model3DContent] is always [ContentType.MESH]. */ | ||
interface ModelContent: ContentElement<Model>{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ModelContent
is very generic; the previous name was more descriptive. I'd change it back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done👍
private val modelId: String | ||
) { | ||
private val LOGGER = LogManager.getLogger() | ||
class Entity(val id: String, val modelId: String) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This, again, is a very generic name. I'm sure there is a more descriptive one.
|
||
import org.joml.Vector3f | ||
|
||
/** | ||
* | ||
*/ | ||
interface IModel { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm personally not a big fan of the I-prefix naming scheme for interfaces. It usually indicates that there is another thing that should have a more specific name.
* Used to indicate that a key is not valid. | ||
*/ | ||
@SuppressWarnings("unused") | ||
public class VariantException extends RuntimeException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
???
* If a job is a CONTROL job it contains a command | ||
* {@link JobControlCommand} | ||
*/ | ||
public abstract class Job { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why this is needed
* This class is used to parse the annotations of a state provider | ||
* @see StateProviderAnnotationParser#runTransitionMethods(Object, State, State, Transition, Variant) | ||
*/ | ||
public class StateProviderAnnotationParser { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very much not the kotlin way of thigs
* @see <a href="https://stackoverflow.com/questions/5923767/simple-state-machine-example-in-c"> | ||
* https://stackoverflow.com/questions/5923767/simple-state-machine-example-in-c/a> | ||
*/ | ||
public class FiniteStateMachine { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WHY?!
val renderWorker = RenderWorker(renderJobQueue) | ||
|
||
/* Run RenderWorker on the main thread. */ | ||
renderWorker.run() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
Thank you for the detailed review @lucaro. I will work through the comments and make the adjustments. Nevertheless, I think we should discuss whether the complete rendering logic that uses LWJGL must be translated to Kotlin or if we can include this independent Java code. The code was directly copied from Cineast, so the finite state machine was implemented like this before. Furthermore, I have not found a Java class in src/main/kotlin. Please point them out. For me, all Java code is located under src/main/java. @ppanopticon Thank you as well for your feedback. I will add an example and unit tests and rewrite some parts to remove the JOML dependency in the core module. |
Signed-off-by: Ralph Gasser <[email protected]>
Signed-off-by: Ralph Gasser <[email protected]>
I'm aware that this was implemented like this in Cineast. It was over-engineered there (as I already pointed out back then), and it is over-engineered here. Here, it's even worse since Cineast had already collected some bloat over the years, so the addition was relatively not as bad. I'm also opposed to supporting multiple languages in a project with no clear benefit. This just complicates maintenance and reduces readability in the long run. Translating the Java code to Kotlin is straightforward and even (mostly) automated by Intellij. While translating this (or, mostly, having it automatically translated), there will also be room to get rid of some inherent boilerplate code that is just not required in Kotlin. |
Okay so I have taken another look at this, especially how this can be integrated without interfering with the flow of the integrating application. Having spent half a day on this I can conclude, that the only way we can use the rendering logic without hooking it into the application's main thread is by externalising it into a different process. For this purpose, I have created the Having said that: I agree with @lucaro that the entire rendering logic (i.e., this state-machine stuff) is way too complicated for solving a simple problem such as rendering a few previews. I really wonder, if this can't be simplified. To me, the fact that the entire state-machine logic in |
Signed-off-by: Ralph Gasser <[email protected]>
The JOML dependency in the |
An example of how the configuration should look like to create previews can already be found in the Wiki: https://github.com/vitrivr/vitrivr-engine/wiki/Example#3d-model-pipeline |
Signed-off-by: Ralph Gasser <[email protected]>
Signed-off-by: Ralph Gasser <[email protected]>
Signed-off-by: Ralph Gasser <[email protected]>
Signed-off-by: Ralph Gasser <[email protected]>
…to work). Signed-off-by: Ralph Gasser <[email protected]>
Signed-off-by: Ralph Gasser <[email protected]>
Signed-off-by: Ralph Gasser <[email protected]>
Signed-off-by: Ralph Gasser <[email protected]>
Signed-off-by: Ralph Gasser <[email protected]>
Signed-off-by: Ralph Gasser <[email protected]>
…ess. Signed-off-by: Ralph Gasser <[email protected]>
Signed-off-by: Ralph Gasser <[email protected]>
…h current Cottontail DB driver version.
} | ||
|
||
/* Initialize RenderWorker on the main thread. */ | ||
val renderJobQueue = LinkedBlockingDeque<RenderJob>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding this to the vitrivr-engine-server like this goes against the modularity idea of vitrivr-engine (i.e., the ability to actually omit this module in a concrete project).
@@ -7,6 +7,7 @@ plugins { | |||
dependencies { | |||
/* vitrivr core dependency. */ | |||
api project(':vitrivr-engine-core') | |||
api project(':vitrivr-engine-module-m3d') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vitrivr-engine-index
module must no depend on vitrivr-engine-module-m3d
. This makes no sense from an architectural perspective.
If anything, the vitrivr-engine-module-m3d
can be added to the vitrivr-engine-module-server
for testing purposes only.
|
||
import java.util.Objects; | ||
|
||
public class Pair<K, V> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this was Kotlin code, then we wouldn't need to have this class.
@@ -0,0 +1,2 @@ | |||
package org.vitrivr.engine.model3d.data.render.lwjgl;public class Renderer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of this class?
* - Rendering of single Mesh or VoxelGrid - Free positioning of the camera in terms of either cartesian or polar coordinate - Snapshot of the rendered image can be obtained at any time. | ||
* @deprecated This interface is deprecated it can be simplified if the old JOGL renderer is removed. | ||
*/ | ||
@Deprecated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why add this to the project if it is already deprecated?
...vr-engine-module-m3d/src/main/kotlin/org/vitrivr/engine/model3d/renderer/ExternalRenderer.kt
Outdated
Show resolved
Hide resolved
@lucaro This pull request is ready to merge from my side. Could you please review it once more? |
If @ppanopticon gave his approval, it's good enough for me 😉 |
This pull request integrates a 3D model renderer and introduces a 3D model preview exporter.
The renderer, originally developed by @net-cscience-raphael for Cineast using LWJGL, retains its core functionality while the texture model has been translated to Kotlin for enhanced integration. This updated version replaces the previous implementation in the
vitrivr-engine-core
module.In addition, new functionality has been added to create previews of 3D models in the
vitrivr-engine-module-m3d/src/main/kotlin/org/vitrivr/engine/model3d/ModelPreviewExporter.kt
. By specifying settings in theschema-config.json
file, users can export either GIFs or JPGs that showcase 3D models. GIFs allow for a customizable number of views capturing different angles of the 3D model, while the JPG version provides four predefined views. To ensure correct formatting of exported previe ws, themimeType
of theDiskResolver
must be adjusted in the config file.Overview of new Functionality: