📄 x3dtojme.java
字号:
// Set translation
Node translationNode = attrs.getNamedItem("translation");
if (translationNode != null) {
String translation = translationNode.getNodeValue().trim();
String[] split = translation.split(WHITESPACE_REGEX);
if (split.length >= 3) {
float x = getFloat(split[0], 0f);
float y = getFloat(split[1], 0f);
float z = getFloat(split[2], 0f);
sceneNode.setLocalTranslation(x, y, z);
}
}
// Set rotation
Node rotationNode = attrs.getNamedItem("rotation");
if (rotationNode != null) {
String rotation = rotationNode.getNodeValue().trim();
String[] split = rotation.split(WHITESPACE_REGEX);
if (split.length >= 4) {
try {
float axisX = Float.parseFloat(split[0]);
float axisY = Float.parseFloat(split[1]);
float axisZ = Float.parseFloat(split[2]);
float angle = Float.parseFloat(split[3]);
// logger.info("Setting rotation: ("+axisX+", "+axisY+",
// "+axisZ+"), "+angle);
sceneNode.getLocalRotation().fromAngleAxis(angle,
new Vector3f(axisX, axisY, axisZ));
} catch (NumberFormatException e) {
}
}
}
// Set scaling
Node scaleNode = attrs.getNamedItem("scale");
if (scaleNode != null) {
String scale = scaleNode.getNodeValue().trim();
String[] split = scale.split(WHITESPACE_REGEX);
if (split.length >= 3) {
float x = getFloat(split[0], 1f);
float y = getFloat(split[1], 1f);
float z = getFloat(split[2], 1f);
// logger.info("Setting scaling: ("+x+", "+y+", "+z+")");
sceneNode.setLocalScale(new Vector3f(x, y, z));
}
}
}
/**
* Gets an integer value from the specified String.
*
* @param num
* The String containing the value
* @param standard
* A value to be used in case the String is <code>null</code>
* or the parsing fails
* @return The resulting int value
*/
private int getInt(String num, int standard) {
if (num != null) {
try {
return Integer.parseInt(num);
} catch (NumberFormatException e) {
}
}
return standard;
}
/**
* Gets a float value from the specified String.
*
* @param num
* The String containing the value
* @param standard
* A value to be used in case the String is <code>null</code>
* or the parsing fails
* @return The resulting float value
*/
private float getFloat(String num, float standard) {
if (num != null) {
try {
return Float.parseFloat(num);
} catch (NumberFormatException e) {
}
}
return standard;
}
/**
* Parses the contents of an X3D Shape node and its children and creates a
* jME Node containing the geometry and appearance parameters read from the
* X3D shape node.
*
* @param node
* The Shape node
* @return The jME Geometry
* @throws Exception
* In case an error occurs during loading
*/
private Spatial parseShape(Node node) throws Exception {
com.jme.scene.Node shape = new com.jme.scene.Node();
// Check for a bounding box definition
BoundingBox bbox = parseBoundingBox(node);
// Find the geometry and appearance nodes
Node geometryNode = null;
Node appearanceNode = null;
Node child = node.getFirstChild();
while (child != null) {
if (child.getNodeName().equals("Appearance")) {
appearanceNode = child;
} else if (isGeometryType(child.getNodeName())) {
geometryNode = child;
}
child = child.getNextSibling();
}
// Parse and add the geometry, if available
Geometry geom = null;
if (geometryNode != null) {
geom = parseGeometry(geometryNode);
if (geom != null) {
shape.attachChild(geom);
}
if (geom != null && bbox != null) {
geom.setModelBound(bbox);
}
}
// Parse and set the appearance properties, if available
createBumpController = false; // Reset the create controller flag
addToTransparentQueue = false;
if (appearanceNode != null) {
RenderState[] states = parseAppearance(appearanceNode);
if (states != null && geom != null) {
/*
* Check if the parsed Appearance contained a Bump Map => set up
* a BumpMapColorController for the Geometry
*/
if (createBumpController) {
BumpMapColorController con = new BumpMapColorController(
geom);
geom.addController(con);
}
/*
* Check if the parsed Appearance contained transparency => add
* the geometry to the transparency renderQueue
*/
if (addToTransparentQueue) {
geom.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
}
// Apply the RenderStates
for (RenderState state : states) {
if (state != null) {
shape.setRenderState(state);
// If there are multiple textures, copy the texCoords
// (DUMMY)
if (state instanceof TextureState
&& ((TextureState) state)
.getNumberOfSetTextures() > 1) {
copyTexCoords((TextureState) state, geom);
}
}
}
}
}
return shape;
}
/**
* Checks if the given String represents one of the types of geometry nodes
* this loader understands.
*
* @param type
* The String to check
* @return <code>true</code>, if the String contains a valid geometry
* type, otherwise <code>false</code>
*/
private boolean isGeometryType(String type) {
for (String geom : GEOMETRY_TYPES) {
if (type.equals(geom)) {
return true;
}
}
return false;
}
/**
* Parses any X3D geometry node (Box, Cone, Cylinder, IndexedFaceSet,
* Sphere) and creates a corresponding jME Geometry object.
*
* @param node
* The X3D node
* @return The jME Geometry
* @throws Exception
* In case an error occurs during parsing
*/
private Geometry parseGeometry(Node node) throws Exception {
// Check for the USE attribute
Node use = node.getAttributes().getNamedItem("USE");
if (use != null) {
return (Geometry) getDef(use.getNodeValue());
}
// Check for the DEF attribute
Node def = node.getAttributes().getNamedItem("DEF");
String title = null;
if (def != null) {
title = def.getNodeValue();
}
// Parse the Geometry
Geometry geom = null;
String nodeName = node.getNodeName();
if (nodeName.equals("Box")) {
geom = parseBox(node, title);
} else if (nodeName.equals("IndexedFaceSet")) {
geom = parseIFS(node, title);
} else if (nodeName.equals("Sphere")) {
geom = parseSphere(node, title);
} else if (nodeName.equals("Cylinder")) {
geom = parseCylinder(node, title);
} else if (nodeName.equals("Cone")) {
geom = parseCone(node, title);
} else if (nodeName.equals("LineSet")) {
geom = parseLS(node, title);
}
if (geom != null) {
// Set up bounding volume
geom.setModelBound(new BoundingBox());
// Translate attribute "solid" into a CullState
boolean solid = true; // X3D default: true
Node solidNode = node.getAttributes().getNamedItem("solid");
if (solidNode != null
&& solidNode.getNodeValue().equalsIgnoreCase("false")) {
solid = false;
}
if (solid) {
CullState culling = DisplaySystem.getDisplaySystem()
.getRenderer().createCullState();
culling.setCullFace(CullState.Face.Back);
geom.setRenderState(culling);
}
// If the DEF attribute exists, store the Geometry for future USEs
if (title != null) {
CloneImportExport cloneEx = new CloneImportExport();
cloneEx.saveClone(geom);
defs.put(title, cloneEx);
}
}
return geom;
}
/**
* Parses an X3D Box node and creates a corresponding jME Box.
*
* @param node
* The X3D Box node
* @param title
* A title for the box. If <code>null</code> is passed, a
* generic title is used.
* @return The jME Box
*/
private Box parseBox(Node node, String title) {
Box box = null;
String size = node.getAttributes().getNamedItem("size").getNodeValue()
.trim();
String[] split = size.split(WHITESPACE_REGEX);
if (split.length >= 3) {
// jME interprets scaling as extent from center => size is scaled by
// 0.5
float x = getFloat(split[0], 0) * 0.5f;
float y = getFloat(split[1], 0) * 0.5f;
float z = getFloat(split[2], 0) * 0.5f;
if (x > 0 && y > 0 && z > 0) {
if (title != null) {
box = new Box(title, new Vector3f(), x, y, z);
} else {
box = new Box("X3D_Box", new Vector3f(), x, y, z);
}
}
}
return box;
}
/**
* Parses an X3D IndexedFaceSet node and creates a corresponding jME
* Geometry node. Because of jME's limitation that there can only be one
* index array that is used for vertices as well as normals, colors and
* texture coordinates, this method uses a workaround for the X3D
* IndexedFaceSet's colorIndex, normalIndex and texCoordIndex attributes:
* The vertices are "expanded" according to the indices from the coordIndex
* attributes, so that every three consecutive vertices define one triangle
* and the corresponding index array looks like [0, 1, 2, 3, 4, ...];
* polygons with more than three vertices are split up into triangles in the
* process. The attributes colorPerVertex and normalPerVertex are ignored,
* most likely resulting in an ArrayOutOfBoundsException or simply rendering
* errors when they are used in the X3D file (this should be fixed sometime
* in the future, so that colors or normals respectively are ignored
* altogether if these attributes are used)
*
* @param node
* The X3D IndexedFaceSet node
* @param title
* The name for the node
* @return The jME Geometry for the IndexedFaceSet
*/
private Geometry parseIFS(Node node, String title) {
// Parse the vertices
float[] vertices = null;
Node coords = getChildNode(node, "Coordinate");
if (coords != null) {
vertices = parseValues(coords, "point");
}
if (vertices == null) {
return null;
}
// Parse the coord indices
int[] indices = parseIndices(node, "coordIndex");
boolean indicesAvailable = false;
if (indices == null) {
// No indices specified => Every three consecutive vertices define a
// triangle
indices = new int[vertices.length];
for (int i = 0; i < indices.length; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -