Extension to OgreSceneLoader

I start a new Topic here, because I assume I should post contributions here and not in the Development Discussion sub-forum(http://www.jmonkeyengine.com/forum/index.php?topic=14055.0) :wink:



This patach adds Light loading support, own Materiallist definition support (if no Materiallist specified, it still uses the default).

And some minor changes.



If plz, someone can commit it?

<— edited, there was an bug in there —>



Index: SceneLoader.java
--- SceneLoader.java Base (BASE)
+++ SceneLoader.java Locally Modified (Based On LOCAL)
@@ -1,9 +1,13 @@
 package com.jme3.scene.plugins.ogre;
 
+import com.jme3.scene.Geometry;
+import com.jme3.light.Light;
 import com.jme3.asset.AssetInfo;
 import com.jme3.asset.AssetKey;
 import com.jme3.asset.AssetLoader;
 import com.jme3.asset.AssetManager;
+import com.jme3.light.DirectionalLight;
+import com.jme3.light.PointLight;
 import com.jme3.math.Quaternion;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Node;
@@ -12,6 +16,7 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.util.Stack;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
@@ -36,6 +41,7 @@
     private Node entityNode;
     private int nodeIdx = 0;
     private static volatile int sceneIdx = 0;
+    private Light light;
 
     public SceneLoader(){
         super();
@@ -49,8 +55,42 @@
     public void endDocument() {
     }
 
+    private void parseLightNormal(Attributes attribs) throws SAXException {
+        assert elementStack.peek().equals("light");
+        // SpotLight will be supporting a direction-normal, too.
+        if(light instanceof DirectionalLight)
+            ((DirectionalLight) light).setDirection(parseVector3(attribs));
+    }
    
+    private void parseLightAttenuation(Attributes attribs) throws SAXException {
+        // NOTE: Only radius is supported atm ( for pointlights only, since there are no spotlights, yet).
+        assert elementStack.peek().equals("light");
+        // SpotLight will be supporting a direction-normal, too.
+        if(light instanceof PointLight)
+            ((PointLight) light).setRadius(parseFloat(attribs.getValue("range")));
+    }
 
+    private void parseLight(Attributes attribs) throws SAXException {
+        assert node != null;
+        assert node.getParent() != null;
+        assert elementStack.peek().equals("node");
+        String lightType = attribs.getValue("type");
+        if(lightType.equals("point")) {
+            light = new PointLight();
+        } else if(lightType.equals("directional")) {
+            light = new DirectionalLight();
+        } else if(lightType.equals("spotLight")) {
+            // TODO: SpotLight class.
+            logger.warning("No SpotLight class atm, using Pointlight instead.");
+            light = new PointLight();
+        } else {
+            logger.log(Level.WARNING, "No matching jME3 LightType found for OGRE LightType: {0}", lightType);
+        }
+        logger.info(light + " created.");
+        // "attach" it to the parent of this node
+        if(light != null) node.getParent().addLight(light);
+    }
+
     private Quaternion parseQuat(Attributes attribs) throws SAXException{
         if (attribs.getValue("x") != null){
             // defined as quaternion
@@ -92,10 +132,15 @@
                 root = new Node("OgreDotScene"+(++sceneIdx));
             else
                 root = new Node(sceneName+"-scene_node");
-           
             node = root;
         }else if (qName.equals("externals")){
             assert elementStack.peek().equals("scene");
+        }else if (qName.equals("item")){
+            assert elementStack.peek().equals("externals");
+        }else if (qName.equals("file")){
+            assert elementStack.peek().equals("item");
+            materialList = (OgreMaterialList)
+                    assetManager.loadAsset(folderName+attribs.getValue("name"));
         }else if (qName.equals("node")){
             String curElement = elementStack.peek();
             assert curElement.equals("nodes") || curElement.equals("node");
@@ -147,9 +192,21 @@
             node.setLocalRotation(parseQuat(attribs));
         }else if (qName.equals("scale")){
             node.setLocalScale(SAXUtil.parseVector3(attribs));
+        }// light loading code:
+        else if (qName.equals("light")) {
+            parseLight(attribs);
+        } else if (qName.equals("colourDiffuse")) { // NOTE: colOUr ;-)
+            assert elementStack.peek().equals("light");
+            light.setColor(parseColor(attribs));
+        } else if (qName.equals("normal")) {
+            parseLightNormal(attribs);
+        } else if (qName.equals("lightAttenuation")) {
+            parseLightAttenuation(attribs);
+        }// TODO: specularColor
+        // end light loading code.
+       
+        elementStack.push(qName);
         }
-        elementStack.add(qName);
-    }
 
     @Override
     public void endElement(String uri, String name, String qName) {
@@ -160,6 +217,8 @@
         }else if (qName.equals("entity")){
             node = entityNode.getParent();
             entityNode = null;
+        }else if (qName.equals("light")){
+            light = null;
         }
         assert elementStack.peek().equals(qName);
         elementStack.pop();
@@ -169,7 +228,7 @@
     public void characters(char ch[], int start, int length) {
     }
 
-    public Object load(AssetInfo info) throws IOException {
+    public Spatial load(AssetInfo info) throws IOException {
         try{
             assetManager = info.getManager();
             sceneName = info.getKey().getName();
@@ -188,9 +247,7 @@
             r.close();
             return root;
         }catch (SAXException ex){
-            IOException ioEx = new IOException("Error while parsing Ogre3D dotScene");
-            ioEx.initCause(ex);
-            throw ioEx;
+            throw new IOException("Error while parsing Ogre3D dotScene", ex);
         }
     }
 

Aand, I found a bug while loading a LightList:

it would throw an ArrayIndexOutOfBoundsException, if the Lightlist is bigger than one light.


Index: LightList.java
--- LightList.java Base (BASE)
+++ LightList.java Locally Modified (Based On LOCAL)
@@ -220,11 +220,11 @@
         InputCapsule ic = im.getCapsule(this);
         owner = (Spatial) ic.readSavable("owner", null);
 
-        list = new Light[DEFAULT_SIZE];
         distToOwner = new float[DEFAULT_SIZE];
        
         List<Light> lights = ic.readSavableArrayList("lights", null);
         listSize = lights.size();
+        list = new Light[listSize];
         for (int i = 0; i < listSize; i++){
             list[i] = lights.get(i);
         }

Some things:

  1. Loading material file is useless because all the models are loaded before that XML node is reached.
  2. jME3 uses the same color for specular of lights as diffuse.
  3. The constructor of IOException that you're using is unsupported in Java 1.5.
  4. For the LightList issue, you should probably use the listSize for initialization of distToOwner array as well.



    Other than that, I applied the changes in my local copy. Thanks :wink: