📄 x3dtojme.java
字号:
}
/**
* Loads a scene (model) from the X3D file contained in the specified input
* stream.<br />
* <strong>Please note:</strong> This loader is NOT thread-safe!
*
* @param x3dIn
* An InputStream holding the X3D file
* @param texData
* A Map mapping the paths of texture files to InputStreams
* holding the file content
* @param lightState
* The LightState to attach scene lights to. If <code>null</code>
* is passed, a new LightState is created and attached to the
* model root, which causes the lights in the X3D scene to light
* only the X3D scene itself
* @return The model, if it was successfully loaded, otherwise
* <code>null</code>
* @throws An
* Exception, in case any error occurs
*/
public Spatial loadScene(InputStream x3dIn,
Map<String, InputStream> texData, LightState lightState)
throws Exception {
this.texData = texData;
// Timer timer = Timer.getTimer();
// timer.reset();
// Parse the XML document, build the DOM-document
Document doc;
// try {
doc = documentBuilder.parse(x3dIn);
// } catch (Exception e) {
// logger.info("Unable to parse X3D file: " + e + " ("
// + e.getMessage() + ")");
// return new com.jme.scene.Node();
// }
// float parsingTime = timer.getTimeInSeconds();
// logger.info("X3D parsed in "+(parsingTime * 1000)+" ms");
// timer.reset();
// Create the scene root
NodeList nodes = doc.getElementsByTagName("X3D");
if (nodes.getLength() == 0) {
logger.info("No X3D document root!");
return new com.jme.scene.Node();
}
Node scene = getChildNode(nodes.item(0), "Scene");
com.jme.scene.Node sceneRoot = new com.jme.scene.Node();
/*
* Check the LightState. If none has been passed, create a new one and
* attach it to the scene root
*/
if (lightState == null) {
this.lightState = DisplaySystem.getDisplaySystem().getRenderer()
.createLightState();
this.lightState.setEnabled(true);
sceneRoot.setRenderState(this.lightState);
} else {
this.lightState = lightState;
}
// Set the scene's title
Node worldInfo = getChildNode(scene, "WorldInfo");
if (worldInfo != null) {
Node titleNode = worldInfo.getAttributes().getNamedItem("title");
if (titleNode != null) {
sceneRoot.setName(titleNode.getNodeValue());
}
}
// Check for a Layer3D child node. If one exists, use it instead of X3D
Node layer3D = getChildNode(scene, "Layer3D");
if (layer3D != null) {
scene = layer3D;
}
// Process all child nodes
Node child = scene.getFirstChild();
while (child != null) {
if (child.getNodeType() != Node.TEXT_NODE
&& child.getNodeType() != Node.COMMENT_NODE) {
Spatial node = parseNode(child);
if (node != null) {
sceneRoot.attachChild(node);
}
}
child = child.getNextSibling();
}
// Update the bounds of the root node and all children
sceneRoot.setModelBound(new BoundingBox());
sceneRoot.updateModelBound();
// Reset all used data
defs.clear();
this.texData = null;
this.lightState = null;
this.addToTransparentQueue = false;
this.createBumpController = false;
try {
x3dIn.close();
} catch (IOException e) {
}
// parsingTime = timer.getTimeInSeconds();
// logger.info("Scene parsed in "+(parsingTime * 1000)+" ms");
return sceneRoot;
}
/**
* Gets the child node with the specified name from the specified node.
*
* @param node
* The node to get the child node from
* @param name
* The name of the child element to get (case is ignored)
* @return The first child node with the specified name, or
* <code>null</code> if such a node does not exist
*/
private Node getChildNode(Node node, String name) {
Node child = node.getFirstChild();
while (child != null && child.getNodeName() != name) {
child = child.getNextSibling();
}
return child;
}
/**
* Parses a node in the DOM (grouping, shape or light node) and creates a
* scene node according to the DOM node's attributes and child elements.
*
* @param node
* The DOM node
* @return The jME Node
* @throws Exception
* In case an error occurs during parsing
*/
private Spatial parseNode(Node node) throws Exception {
// Check for the USE attribute
Node use = node.getAttributes().getNamedItem("USE");
if (use != null) {
return (Spatial) getDef(use.getNodeValue());
}
// Parse the node
String type = node.getNodeName();
Spatial result = null;
if (type.equals("Group") || type.equals("StaticGroup")
|| type.equals("Transform") || type.equals("Switch")) {
result = parseGroup(node);
} else if (type.equals("Shape")) {
result = parseShape(node);
} else if (type.equals("DirectionalLight") || type.equals("PointLight")
|| type.equals("SpotLight")) {
result = parseLight(node);
}
// Check for the DEF attribute
if (result != null) {
Node def = node.getAttributes().getNamedItem("DEF");
if (def != null) {
result.setName(def.getNodeValue());
CloneImportExport cloneEx = new CloneImportExport();
cloneEx.saveClone(result);
defs.put(def.getNodeValue(), cloneEx);
}
}
return result;
}
/**
* Gets a clone of a previously defined Savable.
*
* @param result
* A Savable to store the clone data.
* @param def
* The ID of the predefined Savable
* @return The passed Savable, filled with the clone data, or
* <code>null</code> if no predefined object matching the ID was
* found
*/
private Savable getDef(String def) {
CloneImportExport cloneIn = (CloneImportExport) defs.get(def);
if (cloneIn != null) {
return cloneIn.loadClone();
}
return null;
}
/**
* Parses a DOM Group, StaticGroup, TransformGroup or Switch node and
* creates a jME node with the appropriate properties
*
* @param node
* The DOM node
* @return The jME node
* @throws Exception
* In case an error occurs during parsing
*/
private com.jme.scene.Node parseGroup(Node node) throws Exception {
// Init node
boolean isSwitch;
com.jme.scene.Node group;
if (node.getNodeName().equals("Switch")) {
group = new SwitchNode();
isSwitch = true;
} else {
group = new com.jme.scene.Node();
isSwitch = false;
}
// Parse BoundingBox
BoundingBox bbox = parseBoundingBox(node);
if (bbox != null) {
group.setModelBound(bbox);
}
// Parse children
Node child = node.getFirstChild();
while (child != null) {
if (isSceneNodeType(child.getNodeName())) {
Spatial subnode = parseNode(child);
if (subnode != null) {
group.attachChild(subnode);
}
}
child = child.getNextSibling();
}
// Extra settings for Switch and Transform nodes
if (isSwitch) {
String selection = node.getAttributes().getNamedItem("whichChoice")
.getNodeValue().trim();
try {
int item = Integer.parseInt(selection);
((SwitchNode) group).setActiveChild(item);
} catch (NumberFormatException e) {
((SwitchNode) group).setActiveChild(-1);
}
} else if (node.getNodeName().equals("Transform")) {
setTransformation(group, node);
}
return group;
}
/**
* Creates a BoundingBox according to the attributes bboxCenter and bboxSize
* of the given node.
*
* @param node
* The node
* @return A BoundingBox created from the attribute values, or
* <code>null</code> if the attributes were unavailable or
* specified a buggy or negative box.
*/
private BoundingBox parseBoundingBox(Node node) {
NamedNodeMap attrs = node.getAttributes();
// Parse size
Node sizeNode = attrs.getNamedItem("bboxSize");
if (sizeNode == null) {
return null;
}
String size = sizeNode.getNodeValue().trim();
String[] split = size.split(WHITESPACE_REGEX);
if (split.length < 3) {
return null;
}
float sizeX = getFloat(split[0], -1);
float sizeY = getFloat(split[1], -1);
float sizeZ = getFloat(split[2], -1);
if (sizeX < 0 || sizeY < 0 || sizeZ < 0) {
return null;
}
// Parse center
Node centerNode = attrs.getNamedItem("bboxCenter");
if (centerNode == null) {
return null;
}
String center = centerNode.getNodeValue().trim();
split = center.split(WHITESPACE_REGEX);
if (split.length < 3) {
return null;
}
float centerX = getFloat(split[0], 0);
float centerY = getFloat(split[1], 0);
float centerZ = getFloat(split[2], 0);
return new BoundingBox(new Vector3f(centerX, centerY, centerZ),
sizeX * 0.5f, sizeY * 0.5f, sizeZ * 0.5f);
}
/**
* Checks if the specified String represents a scene node type (i.e. a
* group, shape or light type)
*
* @param type
* The type String
* @return <code>true</code>, if the String is a scene node type,
* otherwise <code>false</code>
*/
private boolean isSceneNodeType(String type) {
for (String node : SCENE_NODE_TYPES) {
if (type.equals(node)) {
return true;
}
}
return false;
}
/**
* Sets the translation, rotation and scaling values for the given scene
* node according to the attributes of the DOM node, if it is a Transform
* node.
*
* @param sceneNode
* The scene node to set the transformation for
* @param node
* The DOM node
*/
private void setTransformation(com.jme.scene.Node sceneNode, Node node) {
NamedNodeMap attrs = node.getAttributes();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -