It seems that SceneLoader can’t handle the most simple of Blender object nesting. The Blender dotScene exporter cleanly exports parent mesh Object “Par” and two child mesh Objects “Auto” and “Manual” (named to indicate how I parented them). SceneLoader just ignores “Auto” and “Manual”. Compare the dotScene file http://pub.admc.com/misc/jme/scene.xml and a jME export of what SceneLoader actually loaded, http://pub.admc.com/misc/jme/ogrescene-jme.xml.
I’m pretty handy with the structures involved. Is there any reason why I should not look into the code to see if I can patch it to support Blender object nesting? If yes, do you have any suggestions or pointers to save me time?
With respect to loading scene objects from files at runtime, what I usually want to do is load files consisting of "world objects". I.e., some graph-related meshes and materials (I have another post about parenting-child relationships, but for our purposes here you can assume peer meshes). I do this efficiently with jME XML files all the time. I would like to use your loader to do the same thing with Ogre XML files.
My problem is, OgreLoader.loadModel() doesn't load models unless for some reason you are defining "model" == "mesh". IMO it is just a poorly labelled wrapper for the loadMesh method. Besides not restoring any inter-mesh relationships, this can't even restore the mesh's transform. At the other extreme, SceneLoader requires a Renderer to be in the runtime context and has built-in functionality for cameras and/or lighting. If it isnt' inherently harmful to load this scenery stuff without enabling it, I don't have the CPU cycles and RAM to spare.
Do I need to implement another loader method or class, or is there already something relevant in your API?
It seems that SceneLoader can't handle the most simple of Blender object nesting.
Yeah, actually thanks to you I just discovered that the dotScene format supports this kind of nesting. The neccessary code can be changed in the class SceneLoader.
OgreLoader.loadModel() doesn't load models unless for some reason you are defining "model" == "mesh".
IMO it is just a poorly labelled wrapper for the loadMesh method.
This kind of convention actually comes from the Ogre3D way of handling things.. In Ogre, a "Mesh" is considered a model, or an "Entity", while inside it are "Submeshes". This is similar to the jME1 of doing things, where the TriMesh object has multiple TriangleBatches. The OgreLoader.loadModel() can be named pretty much anything, it is the only load method that is actually public (users never see the method loadMesh).
Besides not restoring any inter-mesh relationships, this can't even restore the mesh's transform.
The Mesh.XML format does not define any transformations applied to the objects themselves, only the bones have transforms (relative to the model's root).
At the other extreme, SceneLoader requires a Renderer to be in the runtime context
Unfortunately there's really no way around this. The MaterialLoader requires this too and the SceneLoader depends on it so you cannot avoid this dependency. The reason is that to create any type of RenderState a Renderer needs to be in the runtime context.
has built-in functionality for cameras and/or lighting. If it isnt' inherently harmful to load this scenery stuff without enabling it, I don't have the CPU cycles and RAM to spare.
The lighting is applied to the scene so it enabled. The camera code seems to be commented out at the last SVN release. These are objects included in the dotScene files so it is neccessary to load them.
the Ogre exporters very much encourage the practice of keeping the scene resource files in a single directory
The Ogre exporters do not encourge it, it is simply more convinient from the user's side to only ask for 1 folder path. If you look at the Ogre3D Media directory, you'll see that the opposite is encourged, materials/scripts contains the .material files, materials/programs contains GLSL/HLSL/Cg shaders, and materials/textures contain the texture files. Likewise models/ contain the mesh and skeleton files. I suppose it's possible to add this feature for people who are not planning to follow Ogre3D's Media storage style.
Thanks very much for the informative and insightful answers.
Momoko_Fan said:
It seems that SceneLoader can't handle the most simple of Blender object nesting.
Yeah, actually thanks to you I just discovered that the dotScene format supports this kind of nesting. The neccessary code can be changed in the class SceneLoader.
Do you want me to send you patch, post it here, or add me as a project developer? If you choose the last, you would benefit from having a bug-fixer (for example, the way that the Loader hangs without any indication of a problem if the materials file is bad). You can review my jme2 commit history to assess my qualifications. googlecode user "blaine.dev".
OgreLoader.loadModel() doesn't load models unless for some reason you are defining "model" == "mesh".
IMO it is just a poorly labelled wrapper for the loadMesh method.
This kind of convention actually comes from the Ogre3D way of handling things.. In Ogre, a "Mesh" is considered a model, or an "Entity", while inside it are "Submeshes". This is similar to the jME1 of doing things, where the TriMesh object has multiple TriangleBatches. The OgreLoader.loadModel() can be named pretty much anything, it is the only load method that is actually public (users never see the method loadMesh).
Understood
Besides not restoring any inter-mesh relationships, this can't even restore the mesh's transform.
The Mesh.XML format does not define any transformations applied to the objects themselves, only the bones have transforms (relative to the model's root).
I know that. I was just justifying my assertion that mesh-loading is too specific for general model-loading needs.
At the other extreme, SceneLoader requires a Renderer to be in the runtime context
Unfortunately there's really no way around this. The MaterialLoader requires this too and the SceneLoader depends on it so you cannot avoid this dependency. The reason is that to create any type of RenderState a Renderer needs to be in the runtime context.
has built-in functionality for cameras and/or lighting. If it isnt' inherently harmful to load this scenery stuff without enabling it, I don't have the CPU cycles and RAM to spare.
The lighting is applied to the scene so it enabled. The camera code seems to be commented out at the last SVN release. These are objects included in the dotScene files so it is neccessary to load them.
Understood
the Ogre exporters very much encourage the practice of keeping the scene resource files in a single directory
The Ogre exporters do not encourge it, it is simply more convinient from the user's side to only ask for 1 folder path. If you look at the Ogre3D Media directory, you'll see that the opposite is encourged, materials/scripts contains the .material files, materials/programs contains GLSL/HLSL/Cg shaders, and materials/textures contain the texture files. Likewise models/ contain the mesh and skeleton files.
I stand corrected. Thanks.
I suppose it's possible to add this feature for people who are not planning to follow Ogre3D's Media storage style.
Just let me know if you think it's a net gain for the product. I'll add it if so.
I have a ready-to-run beta quality model viewer which I have just made Ogre-Loader-compatible. The known bugs are listed on the app help page.
http://pub.admc.com/misc/modeler.jnlp or http://pub.admc.com/misc/modeler-samesettings.jnlp, depending on whether you want to re-run the setup screen.
The reason I am posting it here is that you can load dotScene files and automatically run then control the animations by just selecting the desired OgreMesh node in the scene tree. This shows off the animation features of Ogreloader.
If you don’t have an Ogre-exported animated file on hand, you can download my sample from http://pub.admc.com/misc/jme/ogrescene-jme.xml.
The repeat mode is quirky with Ogreloaded models. I’ll be looking into this, since repeatability works perfectly reliably with both jME AnimationControllers and SpatialTransformation animations. You can see an example of the latter by using the pulldown or pop-up window to instantiate “com.admc.play.AnimatedSphere, aname”.
I had to make a couple modifications of the Ogreloader code because the Ogreloader MeshAnimationController does not give read access to the animation state like the SpatialTransformer class does. Divergence from jME conventions of the very nicely behaved SpatialTransformer also added unnecessary work to the implementation. (Admittedly, jME’s AnimationController lacks these hooks and more). For these reasons, I request the following simple modifications to MeshAnimationController (which I can do in minutes if given privileges).
Add a getCurTime() method, mirroring jME’s.
Add a public Set<String> getAnimationNames() method.
Fix getMinTime() and getMaxTime() in addition to getAnimationLength(). IMO it would make sense if they got the times for the active or last animation.
You can review my jme2 commit history to assess my qualifications. googlecode user "blaine.dev".
Okay.
Added you as a project member to "radakan".
http://code.google.com/p/radakan/
You can make the needed modifications as you see fit. :)
If you're planning to add any major features, make sure to inform me as I am planning in using OgreLoader for future projects of mine.
EDIT: I tried this modeler program, seems fine so far though I couldn't get the model visible in the scene. Beside that there seems to be a bug with the drop-down combo box in the file chooser menu. You cannot select any items, its like the combo box gui is completely frozen. This probably has something to do with how JMEDesktop does things.
Momoko_Fan said:
You can review my jme2 commit history to assess my qualifications. googlecode user "blaine.dev".
Okay.
Added you as a project member to "radakan".
http://code.google.com/p/radakan/
You can make the needed modifications as you see fit. :)
If you're planning to add any major features, make sure to inform me as I am planning in using OgreLoader for future projects of mine.
I wouldn't do that (big changes without asking). I know it's your project.
Thanks very much.
EDIT: I tried this modeler program, seems fine so far though I couldn't get the model visible in the scene. Beside that there seems to be a bug with the drop-down combo box in the file chooser menu. You cannot select any items, its like the combo box gui is completely frozen. This probably has something to do with how JMEDesktop does things.
Hm. I dont' know why the model wouldn't be visible. Maybe you need to toggle the Lights with L? If the object isn't centered, you may need to back up (S) to bring it into the frustum. The grid, which you toggle with /, makes it easier to get oriented when moving around. UPDATE: The problem is due to trying to load a .mesh.xml file instead of a dotScene file. See details in the more recent post above.
The problem with pulldowns in modals is a known issue with JMEDesktop and is listed in the bug list of the help page. I will fix it eventually, but it's a pretty hairy issue. (Pulldowns do generally work. The problem is only with modals = JOptionPanes and JFileChoosers).
I've implemented general node nesting.
I wasted a good amount of time figuring out why colors were being assigned to the wrong objects until I saw that you remove any .* suffix from material names. This mangles Blender-generated names like "Material.001", etc. Are there exporter variants that write file names as material names in the dotScene file, or some other reason for changing material names?
May I change the spatial naming convention? (a) May I change the node names from "OgreMesh"? Besides being extremely non-unique, the name is misleading in that the named Spatials are not meshes, but Node parents of meshes. (b) May I change the actual Mesh spatial objects from material names. The name is misleading in that the named Spatial is a Mesh not a material (I am thinking of enhancing the Ogre exporter to support Blender-Object-attached materials, and then the current OgreLoader naming convention would fall apart).
I wasted a good amount of time figuring out why colors were being assigned to the wrong objects until I saw that you remove any .* suffix from material names. This mangles Blender-generated names like "Material.001", etc.
I don't remember why exactly was that added.. It's quite strange actually because the material names in the Mesh.XML file do not have an extension. For this one I shall shamelessly shift the guilt to another Radakan programmer :P
(a) May I change the node names from "OgreMesh"? Besides being extremely non-unique, the name is misleading in that the named Spatials are not meshes, but Node parents of meshes.
Here I followed the Ogre naming convention again (mesh.xml), how exactly could you determine the model name then? You must know the file name in order to set a proper name I assume.
(b) May I change the actual Mesh spatial objects from material names. The name is misleading in that the named Spatial is a Mesh not a material (I am thinking of enhancing the Ogre exporter to support Blender-Object-attached materials, and then the current OgreLoader naming convention would fall apart).
Okay. But do note that there's a special structure that allows specifying explicit submesh names called "submeshnames" for that purpose.
Momoko_Fan said:
EDIT: I tried this modeler program, seems fine so far though I couldn't get the model visible in the scene...
This is because (a) you are trying to load a Ogre Mesh file instead of an Ogre dotScene file; and (b) your SceneLoader program does not detect that it is loading a file of the wrong format. Regarding "a", in the post you are replying to I said "The reason I am posting it here is that you can load dotScene files"; and the File chooser you used to open the file says ".xml (*-jme.xml for jME; otherwise Ogre dotScene)"; and the online help says "Load OGRE dotScene or jME XML model files.". Since I always load models containing multiple meshes, loading individual .mesh.xml files is not a use case that I have implemented in the Modeler.
The Ninja model loads and animates great. Just throw this dotScene file into the same "data" directory and load this into the Modeler. You can copy and paste it from here (naming it anything + ".xml") or download from http://pub.admc.com/misc/jme/ninja-scene.xml. For the added convience of readers who don't have the OgreLoader product handy, just extract this http://pub.admc.com/misc/jme/ninjamodel.zip to any directory and load the ninja-scene.xml file into Modeler.
<scene formatVersion="1.0.0">
<nodes>
<node name="Ninja">
<entity name="Ninja" meshFile="ninja.mesh"/>
<quaternion x="0" y="1" z="0" w="0"/>
<scale x=".05" y=".05" z=".05"/>
</node>
</nodes>
<externals>
<item type="material">
<file name="Example.material"/>
</item>
</externals>
<environment/>
</scene>
Just click in background, Shift-HOME to put the camera straight ahead in default jME position, / to draw a reference grid. Then click on the OgreMesh Ninja node in the tree and he will walk. Use the pulldown list to select and run any of the 20 animations! (The scene file above just scales the model and points him towards the light. You could use a completely default dotScene file and use the Modeler Gui to scale and rotate if you prefer). UPDATE: I've changed the ogreloader Spatial naming so that the node with the Controllers is now "Ninja", not "OgreMesh".
What appears to be a duplicate node in the tree is the result of the extreme non-uniqueness of submeshes, as discussed in a peer thread to this one. One of the peers is for the skin mesh; the other for the animation mesh.
ALSO NOTE: The Modeler requires Java 1.6.
I haven't gotten that far yet, but in the worse case, names OgreNode001, OgreNode002, OgreNode003 would be far more accurate and useful than OgreMesh, OgreMesh, OgreMesh, seeing that they are jME Nodes, not Meshes. But more likely, I can make a much more user-friendly and intuitive name derived from an ancestor node name.
Okay then. It's better than what it is right now, that's for sure.
I'm talking about setting reasonable defaults, not supporting explicit names. Setting the name of a mesh object to shared material name "x" because the mesh happens to have a material="x" attribute is like setting the name to "false" because the mesh happens to have an attribute usesharedvertices="false". The material case is worse because the added ambiguity of re-using a name that is already the valid name for a material object.
This is as close as you can get to unique naming, since its not possible to get the names of either meshes or submeshes (without the submeshnames structure) so material names was the only fallback that was available.
This is because (a) you are trying to load a Ogre Mesh file instead of an Ogre dotScene file; and (b) your SceneLoader program does not detect that it is loading a file of the wrong format.
That's rather strange, because I could see the model's structure in the tree view, with "OgreMesh" name and all, I assumed the loading worked fine.
blaine said:
Momoko_Fan said:
(a) May I change the node names from "OgreMesh"? Besides being extremely non-unique, the name is misleading in that the named Spatials are not meshes, but Node parents of meshes.
Here I followed the Ogre naming convention again (mesh.xml), how exactly could you determine the model name then? You must know the file name in order to set a proper name I assume.
I haven't gotten that far yet, but in the worse case, names OgreNode001, OgreNode002, OgreNode003 would be far more accurate and useful than OgreMesh, OgreMesh, OgreMesh, seeing that they are jME Nodes, not Meshes. But more likely, I can make a much more user-friendly and intuitive name derived from an ancestor node name.
Momoko_Fan said:
(b) May I change the actual Mesh spatial objects from material names. The name is misleading in that the named Spatial is a Mesh not a material (I am thinking of enhancing the Ogre exporter to support Blender-Object-attached materials, and then the current OgreLoader naming convention would fall apart).
Okay. But do note that there's a special structure that allows specifying explicit submesh names called "submeshnames" for that purpose.
I'm talking about setting reasonable defaults, not supporting explicit names. Setting the name of a mesh object to shared material name "x" because the mesh happens to have a material="x" attribute is like setting the name to "false" because the mesh happens to have an attribute usesharedvertices="false". The material case is worse because the added ambiguity of re-using a name that is already the valid name for a material object.
You can see a clear example of the practical effects of the non-unique names by loading up the Ninja model in the Modeler and seeing that the Ninja's OgreMesh node has two indistinguishable peer child nodes in the scene tree, both named "Examples/Ninja". (CORRECTION:) One of which is the body mesh, the other the weapon mesh. When peer nodes in any graph have the same name, there is a design problem.
I'm holding off on renaming these nodes until I make sure you are ok with the change. Though you can see I don't mind advocating to fix what I see as inadequacies, I defer to your opinion about what is best for your product.
Momoko_Fan said:
...
I'm talking about setting reasonable defaults, not supporting explicit names. Setting the name of a mesh object to shared material name "x" because the mesh happens to have a material="x" attribute is like setting the name to "false" because the mesh happens to have an attribute usesharedvertices="false". The material case is worse because the added ambiguity of re-using a name that is already the valid name for a material object.
This is as close as you can get to unique naming, since its not possible to get the names of either meshes or submeshes (without the submeshnames structure) so material names was the only fallback that was available.
Naming them "Mesh.001" or similar, with incrementing (loader instance member) integers would have been easy to do at that time. These names would be unique and accurately indicate the object type. Not only are material attribute values non-unique-- they are optional (i.e. they may not be present).
This is because (a) you are trying to load a Ogre Mesh file instead of an Ogre dotScene file; and (b) your SceneLoader program does not detect that it is loading a file of the wrong format.
That's rather strange, because I could see the model's structure in the tree view, with "OgreMesh" name and all, I assumed the loading worked fine.
I had the same reaction when I tried to load a *.mesh.xml file with your SceneLoader the first time. Like I said, it just silently does a mangled load. Here's my load code:
protected SceneLoader ogreSceneLoader = null;
...
ogreSceneLoader = new SceneLoader();
...
ogreSceneLoader.load(file.toURI());
UPDATE: I see that since I fixed a bug in your XML utility class, that it just lists the empty scene node after attempting to load a .mesh.xml as a scene. That makes sense, because the method I fixed was returning false positive node hits. I'll change it to really validate the root XML node when I have time. UPDATE UPDATE: Done. The root node of dotScena and *.mesh.xml files are now validated upload load().
Not sure if anyone's interested but I made a patch to allow adding multiple meshes into a single MeshAnimationController.
Index: src/com/radakan/jme/mxml/anim/MeshAnimationController.java
===================================================================
--- src/com/radakan/jme/mxml/anim/MeshAnimationController.java (revision 633)
+++ src/com/radakan/jme/mxml/anim/MeshAnimationController.java (working copy)
@@ -31,6 +31,8 @@
import com.jme.math.Matrix4f;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera.FrustumIntersect;
+
+import java.util.Arrays;
import java.util.Map;
import java.util.Set;
@@ -53,7 +55,7 @@
/**
* List of targets which this controller effects.
*/
- private final OgreMesh[] targets;
+ private OgreMesh[] targets;
/**
* Skeleton object must contain corresponding data for the targets' weight buffers.
@@ -154,6 +156,15 @@
}
/**
+ * Adds a mesh to this controllers targets.
+ */
+ public boolean addMesh(OgreMesh mesh) {
+ targets = Arrays.copyOf(targets, targets.length + 1);
+ targets[targets.length - 1] = mesh;
+ return true;
+ }
+
+ /**
* Sets the currently active animation.
* Use the animation name "<bind>" to set the model into bind pose.
*
And example usage...
private void takeControl(Node equipment) {
equipment.getChild(0).clearControllers();
animControl.addMesh((OgreMesh)((Node) equipment.getChild(0)).getChild(0));
equipment.getChild(1).clearControllers();
animControl.addMesh((OgreMesh)((Node) equipment.getChild(1)).getChild(0));
}
The second two lines are for the wiremesh node that generates the outline effect on my models. The equipment node contains both the original OgreMesh node and the outlined version, hence having to dig two children down to get to the mesh. Hope this helps someone.
Regarding the mangled loading of Mesh files as dotScene…
The inverse situation caused the corresponding problem. One could load a dotScene file as a Mesh file. I fixed both of these situations and others by adding competent XML parsing.
I also fixed a very basic bug in the Material token scanner which hosed my models repeatedly. (Problem was encountered whenever you use a mesh without a material directly attached, and was exacerbated by the Ogre Exporter's incompetence in this area).
The Material scanner could be made about a hundred times more robust and fast by using JFlex and a parser like Cup or Beaver. (For ogreloader, the robustness is more critical). More generally, XML and Material scanning could be more accommodating to manual edits and customized exporters, and get a performance boost by using a few precompiled java.util.regex.Patterns instead of regenerating hundreds of String regex splitters.
Momoko_Fan said:
my exporter (maya) is able to export shared geometry. your importer doesn't reckognize that [so it seems to me]. if i turn on sharedgeometry within the xmlfile, my app crashes.
That's really odd because the importer does support shared geometry. Are you sure you're using the latest SVN version?
yes i'm always using the latest version. just got an idea of what is running wrong: it seems that the MeshAnimationController doesn't like my skeleton, no idea why, it always stops working when trying to set an animation. it says:
Exception in game loop
java.lang.NullPointerException
at com.radakan.jme.mxml.anim.MeshAnimationController.softwareSkinUpdate(MeshAnimationController.java:292)
at com.radakan.jme.mxml.anim.MeshAnimationController.update(MeshAnimationController.java:543)
(this is line "ByteBuffer ib = mesh.getWeightBuffer().getIndexes();")
on my application at line "rootNode.updateGeometricState(0, true);"
maybe you know what's wrong
btw: it works if i only load the mesh without setting an animation (also with shared geometry)
got it: it's a problem with the cloner. it seems that it doesn't clone the buffers always correctly. i got 2 different meshes with 2 different skeletons. in one case it works perfectly, in the other case i got that nullpointerexception.
in the first case, i use your xml-format, so sharedGeometry off, but used, in the other (not working case) i use normal sharedgeometry. maybe i find the answer
I remember I've got similar problem trying to load model into my scene. The model was animated in 3D studio max and then exported using Ogre tools for exporting. I remember that I fixed that because there was bug in OgreImporter.
I've refactored naming of the Spatials generated during import.
The only backwards-compatibility issue is the point of the refactor-- the names of the Spatials underneath the "OgreScene" will be different. (Unless you happen to use the new SceneLoader.load(URI) method that I just added a couple days ago, in which case the OgreScene name will change too).
You can now import multiple scenes into a scene graph and have a unique attachment node for each. SceneLoader.load(URI) will derive a name from the specified URI; otherwise you can call SceneLoader.setName(String) between instantiation and load().
Modeler now has unique, green icons to distinguish the Ogre "Entity" nodes and the OgreMesh nodes. This, combined with the new, meaningful Spatial names, results in the tree window giving a good summary of exactly what ogreloader has added to your scene graph. UPDATE: Modeler now supports loading *.mesh.xml files in addiition to jME XML and dotScene files, and loading *.material files and listing currently available materials.
I started submesh naming at "BasenameMesh000" instead of "BasenameMesh001", but I'll switch to the latter if Momoko_Fan prefers that.
Hi all,
I put a fix (hope so) for MaterialLoader here:
http://www.jmonkeyengine.com/jmeforum/index.php?topic=11027.0
could someone give it a look, please ?
Thank you !!
foxat said:
Hi all,
I put a fix (hope so) for MaterialLoader here:
http://www.jmonkeyengine.com/jmeforum/index.php?topic=11027.0
could someone give it a look, please ?
Thank you !!
Applied. Please test revision 651 with an alpha renderer in place and verify that it works as expected with apha values 0f, .5f, 1f, for each of the four color specs, and get back to me. I have tested as much as possible without setting up an alpha renderer.
Keep an eye out for logger warnings about "negligable alpha value".
UPDATE: I see that materials which specify a texture and no color still invoke readColor(), setting color.a to 0. It's an understatement to say this parser isn't very careful. I suppose this could cause problems, depending on the settings for combining colors and textures...? I have lots of other work to do and would appreciate any help testing this.