@ -41,6 +41,8 @@ import com.jme3.asset.AssetNotFoundException;
import com.jme3.light.DirectionalLight ;
import com.jme3.light.DirectionalLight ;
import com.jme3.light.Light ;
import com.jme3.light.Light ;
import com.jme3.light.PointLight ;
import com.jme3.light.PointLight ;
import com.jme3.light.SpotLight ;
import com.jme3.math.FastMath ;
import com.jme3.math.Quaternion ;
import com.jme3.math.Quaternion ;
import com.jme3.math.Vector3f ;
import com.jme3.math.Vector3f ;
import com.jme3.scene.Node ;
import com.jme3.scene.Node ;
@ -104,16 +106,22 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
light = null ;
light = null ;
}
}
private void checkTopNode ( String topNode ) throws SAXException {
if ( ! elementStack . peek ( ) . equals ( topNode ) ) {
throw new SAXException ( "dotScene parse error: Expected parent node to be " + topNode ) ;
}
}
private Quaternion parseQuat ( Attributes attribs ) throws SAXException {
private Quaternion parseQuat ( Attributes attribs ) throws SAXException {
if ( attribs . getValue ( "x" ) ! = null ) {
if ( attribs . getValue ( "x" ) ! = null ) {
// defined as quaternion
// defined as quaternion
// qx, qy, qz, qw defined
float x = parseFloat ( attribs . getValue ( "x" ) ) ;
float x = parseFloat ( attribs . getValue ( "x" ) ) ;
float y = parseFloat ( attribs . getValue ( "y" ) ) ;
float y = parseFloat ( attribs . getValue ( "y" ) ) ;
float z = parseFloat ( attribs . getValue ( "z" ) ) ;
float z = parseFloat ( attribs . getValue ( "z" ) ) ;
float w = parseFloat ( attribs . getValue ( "w" ) ) ;
float w = parseFloat ( attribs . getValue ( "w" ) ) ;
return new Quaternion ( x , y , z , w ) ;
return new Quaternion ( x , y , z , w ) ;
} else if ( attribs . getValue ( "qx" ) ! = null ) {
} else if ( attribs . getValue ( "qx" ) ! = null ) {
// defined as quaternion with prefix "q"
float x = parseFloat ( attribs . getValue ( "qx" ) ) ;
float x = parseFloat ( attribs . getValue ( "qx" ) ) ;
float y = parseFloat ( attribs . getValue ( "qy" ) ) ;
float y = parseFloat ( attribs . getValue ( "qy" ) ) ;
float z = parseFloat ( attribs . getValue ( "qz" ) ) ;
float z = parseFloat ( attribs . getValue ( "qz" ) ) ;
@ -129,6 +137,7 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
q . fromAngleAxis ( angle , new Vector3f ( axisX , axisY , axisZ ) ) ;
q . fromAngleAxis ( angle , new Vector3f ( axisX , axisY , axisZ ) ) ;
return q ;
return q ;
} else {
} else {
// defines as 3 angles along XYZ axes
float angleX = parseFloat ( attribs . getValue ( "angleX" ) ) ;
float angleX = parseFloat ( attribs . getValue ( "angleX" ) ) ;
float angleY = parseFloat ( attribs . getValue ( "angleY" ) ) ;
float angleY = parseFloat ( attribs . getValue ( "angleY" ) ) ;
float angleZ = parseFloat ( attribs . getValue ( "angleZ" ) ) ;
float angleZ = parseFloat ( attribs . getValue ( "angleZ" ) ) ;
@ -139,19 +148,22 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
}
}
private void parseLightNormal ( Attributes attribs ) throws SAXException {
private void parseLightNormal ( Attributes attribs ) throws SAXException {
assert elementStack . peek ( ) . equals ( "light" ) ;
checkTopNode ( "light" ) ;
// SpotLight will be supporting a direction-normal, too.
// SpotLight will be supporting a direction-normal, too.
if ( light instanceof DirectionalLight )
if ( light instanceof DirectionalLight )
( ( DirectionalLight ) light ) . setDirection ( parseVector3 ( attribs ) ) ;
( ( DirectionalLight ) light ) . setDirection ( parseVector3 ( attribs ) ) ;
else if ( light instanceof SpotLight ) {
( ( SpotLight ) light ) . setDirection ( parseVector3 ( attribs ) ) ;
}
}
}
private void parseLightAttenuation ( Attributes attribs ) throws SAXException {
private void parseLightAttenuation ( Attributes attribs ) throws SAXException {
// NOTE: Only radius is supported atm ( for pointlights only, since there are no spotlights, yet).
// NOTE: Derives range based on "linear" if it is used solely
assert elementStack . peek ( ) . equals ( "light" ) ;
// for the attenuation. Otherwise derives it from "range"
checkTopNode ( "light" ) ;
// SpotLight will be supporting a direction-normal, too.
if ( light instanceof PointLight | | light instanceof SpotLight ) {
if ( light instanceof PointLight ) {
float range = parseFloat ( attribs . getValue ( "range" ) ) ;
float range = parseFloat ( attribs . getValue ( "range" ) ) ;
float constant = parseFloat ( attribs . getValue ( "constant" ) ) ;
float constant = parseFloat ( attribs . getValue ( "constant" ) ) ;
float linear = parseFloat ( attribs . getValue ( "linear" ) ) ;
float linear = parseFloat ( attribs . getValue ( "linear" ) ) ;
@ -165,15 +177,36 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
if ( constant = = 1 & & quadratic = = 0 & & linear > 0 ) {
if ( constant = = 1 & & quadratic = = 0 & & linear > 0 ) {
range = 1f / linear ;
range = 1f / linear ;
}
}
( ( PointLight ) light ) . setRadius ( range ) ;
if ( light instanceof PointLight ) {
( ( PointLight ) light ) . setRadius ( range ) ;
} else {
( ( SpotLight ) light ) . setSpotRange ( range ) ;
}
}
}
private void parseLightSpotLightRange ( Attributes attribs ) throws SAXException {
checkTopNode ( "light" ) ;
float outer = SAXUtil . parseFloat ( attribs . getValue ( "outer" ) ) ;
float inner = SAXUtil . parseFloat ( attribs . getValue ( "inner" ) ) ;
if ( ! ( light instanceof SpotLight ) ) {
throw new SAXException ( "dotScene parse error: spotLightRange "
+ "can only appear under 'spot' light elements" ) ;
}
}
SpotLight sl = ( SpotLight ) light ;
sl . setSpotInnerAngle ( inner * 0 . 5f ) ;
sl . setSpotOuterAngle ( outer * 0 . 5f ) ;
}
}
private void parseLight ( Attributes attribs ) throws SAXException {
private void parseLight ( Attributes attribs ) throws SAXException {
assert node ! = null ;
if ( node = = null | | node . getParent ( ) = = null )
assert node . getParent ( ) ! = null ;
throw new SAXException ( "dotScene parse error: light can only appear under a node" ) ;
assert elementStack . peek ( ) . equals ( "node" ) ;
checkTopNode ( "node" ) ;
String lightType = parseString ( attribs . getValue ( "type" ) , "point" ) ;
String lightType = parseString ( attribs . getValue ( "type" ) , "point" ) ;
if ( lightType . equals ( "point" ) ) {
if ( lightType . equals ( "point" ) ) {
@ -182,10 +215,8 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
light = new DirectionalLight ( ) ;
light = new DirectionalLight ( ) ;
// Assuming "normal" property is not provided
// Assuming "normal" property is not provided
( ( DirectionalLight ) light ) . setDirection ( Vector3f . UNIT_Z ) ;
( ( DirectionalLight ) light ) . setDirection ( Vector3f . UNIT_Z ) ;
} else if ( lightType . equals ( "spotLight" ) ) {
} else if ( lightType . equals ( "spotLight" ) | | lightType . equals ( "spot" ) ) {
// TODO: SpotLight class.
light = new SpotLight ( ) ;
logger . warning ( "No SpotLight class atm, using Pointlight instead." ) ;
light = new PointLight ( ) ;
} else {
} else {
logger . log ( Level . WARNING , "No matching jME3 LightType found for OGRE LightType: {0}" , lightType ) ;
logger . log ( Level . WARNING , "No matching jME3 LightType found for OGRE LightType: {0}" , lightType ) ;
}
}
@ -203,14 +234,19 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
@Override
@Override
public void startElement ( String uri , String localName , String qName , Attributes attribs ) throws SAXException {
public void startElement ( String uri , String localName , String qName , Attributes attribs ) throws SAXException {
if ( qName . equals ( "scene" ) ) {
if ( qName . equals ( "scene" ) ) {
assert elementStack . size ( ) = = 0 ;
if ( elementStack . size ( ) ! = 0 ) {
throw new SAXException ( "dotScene parse error: 'scene' element must be the root XML element" ) ;
}
String version = attribs . getValue ( "formatVersion" ) ;
String version = attribs . getValue ( "formatVersion" ) ;
if ( version = = null | | ! version . equals ( "1.0.0" ) )
if ( version = = null & & ! version . equals ( "1.0.0" ) & & ! version . equals ( "1.0.1 " ) )
logger . log ( Level . WARNING , "Unrecognized version number"
logger . log ( Level . WARNING , "Unrecognized version number"
+ " in dotScene file: {0}" , version ) ;
+ " in dotScene file: {0}" , version ) ;
} else if ( qName . equals ( "nodes" ) ) {
} else if ( qName . equals ( "nodes" ) ) {
assert root = = null ;
if ( root ! = null ) {
throw new SAXException ( "dotScene parse error: nodes element was specified twice" ) ;
}
if ( sceneName = = null )
if ( sceneName = = null )
root = new Node ( "OgreDotScene" + ( + + sceneIdx ) ) ;
root = new Node ( "OgreDotScene" + ( + + sceneIdx ) ) ;
else
else
@ -218,22 +254,31 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
node = root ;
node = root ;
} else if ( qName . equals ( "externals" ) ) {
} else if ( qName . equals ( "externals" ) ) {
assert elementStack . peek ( ) . equals ( "scene" ) ;
checkTopNode ( "scene" ) ;
// Not loaded currently
} else if ( qName . equals ( "item" ) ) {
} else if ( qName . equals ( "item" ) ) {
assert elementStack . peek ( ) . equals ( "externals" ) ;
checkTopNode ( "externals" ) ;
} else if ( qName . equals ( "file" ) ) {
} else if ( qName . equals ( "file" ) ) {
assert elementStack . peek ( ) . equals ( "item" ) ;
checkTopNode ( "item" ) ;
String matFile = folderName + attribs . getValue ( "name" ) ;
try {
// XXX: Currently material file name is based
materialList = ( MaterialList ) assetManager . loadAsset ( new OgreMaterialKey ( matFile ) ) ;
// on the scene's filename. THIS IS NOT CORRECT.
} catch ( AssetNotFoundException ex ) {
// To solve, port SceneLoader to use DOM instead of SAX
materialList = null ;
logger . log ( Level . WARNING , "Cannot locate material file: {0}" , matFile ) ;
//String matFile = folderName+attribs.getValue("name");
}
//try {
// materialList = (MaterialList) assetManager.loadAsset(new OgreMaterialKey(matFile));
//} catch (AssetNotFoundException ex){
// materialList = null;
// logger.log(Level.WARNING, "Cannot locate material file: {0}", matFile);
//}
} else if ( qName . equals ( "node" ) ) {
} else if ( qName . equals ( "node" ) ) {
String curElement = elementStack . peek ( ) ;
String curElement = elementStack . peek ( ) ;
assert curElement . equals ( "nodes" ) | | curElement . equals ( "node" ) ;
if ( ! curElement . equals ( "node" ) & & ! curElement . equals ( "nodes" ) ) {
throw new SAXException ( "dotScene parse error: "
+ "node element can only appear under 'node' or 'nodes'" ) ;
}
String name = attribs . getValue ( "name" ) ;
String name = attribs . getValue ( "name" ) ;
if ( name = = null )
if ( name = = null )
name = "OgreNode-" + ( + + nodeIdx ) ;
name = "OgreNode-" + ( + + nodeIdx ) ;
@ -259,7 +304,8 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
}
}
}
}
} else if ( qName . equals ( "entity" ) ) {
} else if ( qName . equals ( "entity" ) ) {
assert elementStack . peek ( ) . equals ( "node" ) ;
checkTopNode ( "node" ) ;
String name = attribs . getValue ( "name" ) ;
String name = attribs . getValue ( "name" ) ;
if ( name = = null )
if ( name = = null )
name = "OgreEntity-" + ( + + nodeIdx ) ;
name = "OgreEntity-" + ( + + nodeIdx ) ;
@ -267,32 +313,31 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
name + = "-entity" ;
name + = "-entity" ;
String meshFile = attribs . getValue ( "meshFile" ) ;
String meshFile = attribs . getValue ( "meshFile" ) ;
if ( meshFile = = null )
if ( meshFile = = null ) {
throw new SAXException ( "Required attribute 'meshFile' missing for 'entity' node" ) ;
throw new SAXException ( "Required attribute 'meshFile' missing for 'entity' node" ) ;
}
// TODO: Not currently used
String materialName = attribs . getValue ( "materialName" ) ;
String materialName = attribs . getValue ( "materialName" ) ;
// NOTE: append "xml" since its assumed mesh filse are binary in dotScene
if ( folderName ! = null ) {
if ( folderName ! = null )
meshFile = folderName + meshFile ;
meshFile = folderName + meshFile ;
}
// NOTE: append "xml" since its assumed mesh files are binary in dotScene
meshFile + = ".xml" ;
meshFile + = ".xml" ;
entityNode = new Node ( name ) ;
entityNode = new Node ( name ) ;
OgreMeshKey key = new OgreMeshKey ( meshFile , materialList ) ;
OgreMeshKey key = new OgreMeshKey ( meshFile , materialList ) ;
Spatial ogreMesh =
Spatial ogreMesh = assetManager . loadModel ( key ) ;
( Spatial ) assetManager . loadAsset ( key ) ;
//TODO:workaround for meshxml / mesh.xml
if ( ogreMesh = = null ) {
meshFile = folderName + attribs . getValue ( "meshFile" ) + "xml" ;
key = new OgreMeshKey ( meshFile , materialList ) ;
ogreMesh = ( Spatial ) assetManager . loadAsset ( key ) ;
}
entityNode . attachChild ( ogreMesh ) ;
entityNode . attachChild ( ogreMesh ) ;
node . attachChild ( entityNode ) ;
node . attachChild ( entityNode ) ;
node = null ;
node = null ;
} else if ( qName . equals ( "position" ) ) {
} else if ( qName . equals ( "position" ) ) {
node . setLocalTranslation ( SAXUtil . parseVector3 ( attribs ) ) ;
if ( elementStack . peek ( ) . equals ( "node" ) ) {
node . setLocalTranslation ( SAXUtil . parseVector3 ( attribs ) ) ;
}
} else if ( qName . equals ( "quaternion" ) | | qName . equals ( "rotation" ) ) {
} else if ( qName . equals ( "quaternion" ) | | qName . equals ( "rotation" ) ) {
node . setLocalRotation ( parseQuat ( attribs ) ) ;
node . setLocalRotation ( parseQuat ( attribs ) ) ;
} else if ( qName . equals ( "scale" ) ) {
} else if ( qName . equals ( "scale" ) ) {
@ -305,19 +350,22 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
light . setColor ( parseColor ( attribs ) ) ;
light . setColor ( parseColor ( attribs ) ) ;
}
}
} else {
} else {
assert elementStack . peek ( ) . equals ( "environment" ) ;
checkTopNode ( "environment" ) ;
}
}
} else if ( qName . equals ( "normal" ) ) {
} else if ( qName . equals ( "normal" ) | | qName . equals ( "direction" ) ) {
checkTopNode ( "light" ) ;
parseLightNormal ( attribs ) ;
parseLightNormal ( attribs ) ;
} else if ( qName . equals ( "lightAttenuation" ) ) {
} else if ( qName . equals ( "lightAttenuation" ) ) {
parseLightAttenuation ( attribs ) ;
parseLightAttenuation ( attribs ) ;
} else if ( qName . equals ( "spotLightRange" ) | | qName . equals ( "lightRange" ) ) {
parseLightSpotLightRange ( attribs ) ;
}
}
elementStack . push ( qName ) ;
elementStack . push ( qName ) ;
}
}
@Override
@Override
public void endElement ( String uri , String name , String qName ) {
public void endElement ( String uri , String name , String qName ) throws SAXException {
if ( qName . equals ( "node" ) ) {
if ( qName . equals ( "node" ) ) {
node = node . getParent ( ) ;
node = node . getParent ( ) ;
} else if ( qName . equals ( "nodes" ) ) {
} else if ( qName . equals ( "nodes" ) ) {
@ -339,11 +387,21 @@ public class SceneLoader extends DefaultHandler implements AssetLoader {
PointLight pl = ( PointLight ) light ;
PointLight pl = ( PointLight ) light ;
Vector3f pos = node . getWorldTranslation ( ) ;
Vector3f pos = node . getWorldTranslation ( ) ;
pl . setPosition ( pos ) ;
pl . setPosition ( pos ) ;
} else if ( light instanceof SpotLight ) {
SpotLight sl = ( SpotLight ) light ;
Vector3f pos = node . getWorldTranslation ( ) ;
sl . setPosition ( pos ) ;
Quaternion q = node . getWorldRotation ( ) ;
Vector3f dir = sl . getDirection ( ) ;
q . multLocal ( dir ) ;
sl . setDirection ( dir ) ;
}
}
}
}
light = null ;
light = null ;
}
}
assert elementStack . peek ( ) . equals ( qName ) ;
checkTopNode ( qName ) ;
elementStack . pop ( ) ;
elementStack . pop ( ) ;
}
}