📄 x3dtojme.java
字号:
indices[i] = i;
}
} else {
/*
* Indices available => in order to also use color and normal
* indices, the vertices list must be expanded
*/
indicesAvailable = true;
}
// Parse the colors
float[] colorValues = null;
int colorSize = 3; // Number of values per color (Color or ColorRGBA)
Node colors = getChildNode(node, "Color");
if (colors == null) {
colorSize = 4;
colors = getChildNode(node, "ColorRGBA");
}
if (colors != null) {
colorValues = parseValues(colors, "color");
}
// Parse the color indices
int[] colorIndices = null;
if (colorValues != null) {
colorIndices = parseIndices(node, "colorIndex");
}
// Expand RGB color values to RGBA values
if (colorValues != null && colorSize == 3) {
float[] temp = new float[colorValues.length / 3 * 4];
for (int i = 0; i * 3 < colorValues.length; i++) {
temp[i * 4 + 0] = colorValues[i * 3 + 0];
temp[i * 4 + 1] = colorValues[i * 3 + 1];
temp[i * 4 + 2] = colorValues[i * 3 + 2];
temp[i * 4 + 3] = 1.0f;
}
colorValues = temp;
colorSize = 4;
}
// // If no colors are available, set up default colors
// if (colorValues == null) {
// colorValues = new float[indices.length * 4];
// for (int i = 0; i < colorValues.length; i++) {
// colorValues[i] = i;
// }
// }
// Parse the normals
float[] normalValues = null;
Node normals = getChildNode(node, "Normal");
if (normals != null) {
normalValues = parseValues(normals, "vector");
}
// Parse the normal indices
int[] normalIndices = null;
if (normalValues != null) {
normalIndices = parseIndices(node, "normalIndex");
}
// Get the crease angle, in case no normals are specified
float creaseAngle = getFloat(node.getAttributes().getNamedItem(
"creaseAngle").getNodeValue().trim(), 0);
// Parse the texture coordinates
// TODO: Enable MultiTextureCoordinate parsing!
float[] texCoordValues = null;
Node texCoords = getChildNode(node, "TextureCoordinate");
if (texCoords != null) {
texCoordValues = parseValues(texCoords, "point");
}
// Parse the texCoord indices
int[] texCoordIndices = null;
if (texCoordValues != null) {
texCoordIndices = parseIndices(node, "texCoordIndex");
}
// If no tex coords are available, generate them
if (texCoordValues == null) {
texCoordValues = generateTexCoords(vertices);
}
// Create the Mesh
TriMesh mesh;
if (indicesAvailable && normalIndices == null && colorIndices == null
&& texCoordIndices == null) {
// The mesh contains vertex indices, but no separate indices for
// normals, colors or texCoords => The values can be used without
// modification
IntBuffer indexBuffer = BufferUtils.createIntBuffer(indices);
FloatBuffer vertexBuffer = BufferUtils.createFloatBuffer(vertices);
FloatBuffer colorBuffer = BufferUtils
.createFloatBuffer(colorValues);
FloatBuffer normalBuffer = BufferUtils
.createFloatBuffer(normalValues);
FloatBuffer texCoordBuffer = BufferUtils
.createFloatBuffer(texCoordValues);
mesh = new TriMesh(null, vertexBuffer, normalBuffer, colorBuffer,
new TexCoords(texCoordBuffer), indexBuffer);
// If no normals are available, they are generated
if (normalBuffer == null) {
normalGenerator.generateNormals(mesh, creaseAngle);
}
} else {
int[] indicesBackup = indices.clone();
// If vertex indices are specified as well as normal/color/texCoord
// indices, the vertices have to be expanded so that every three
// consecutive vertices define on triangle
if (indicesAvailable) {
vertices = expandValues(vertices, indices, 3, true);
}
// If separate indices are specified for normals/colors/texCoords,
// expand the corresponding values accordingly. Otherwise, expand
// them using the vertex indices, if available
if (normalValues != null) {
if (normalIndices != null) {
normalValues = expandValues(normalValues, normalIndices, 3,
false);
} else if (indicesAvailable) {
normalValues = expandValues(normalValues, indicesBackup, 3,
false);
}
}
if (colorValues != null) {
if (colorIndices != null) {
colorValues = expandValues(colorValues, colorIndices,
colorSize, false);
} else if (indicesAvailable) {
colorValues = expandValues(colorValues, indicesBackup,
colorSize, false);
}
}
if (texCoordValues != null) {
if (texCoordIndices != null) {
texCoordValues = expandValues(texCoordValues,
texCoordIndices, 2, false);
} else if (indicesAvailable) {
texCoordValues = expandValues(texCoordValues,
indicesBackup, 2, false);
}
}
// If no normals are available, they are generated
if (normalValues == null) {
normalValues = nonIndexedNormalGenerator.generateNormals(
vertices, indicesBackup, creaseAngle);
}
// Set up the mesh
IntBuffer indexBuffer = BufferUtils.createIntBuffer(indices);
FloatBuffer vertexBuffer = BufferUtils.createFloatBuffer(vertices);
FloatBuffer colorBuffer = BufferUtils
.createFloatBuffer(colorValues);
FloatBuffer normalBuffer = BufferUtils
.createFloatBuffer(normalValues);
FloatBuffer texCoordBuffer = BufferUtils
.createFloatBuffer(texCoordValues);
mesh = new TriMesh(null, vertexBuffer, normalBuffer, colorBuffer,
new TexCoords(texCoordBuffer), indexBuffer);
}
if (colorValues == null) {
mesh.setDefaultColor(ColorRGBA.white.clone());
}
String name = (title != null) ? title : "X3D_IndexedFaceSet";
mesh.setName(name);
return mesh;
}
/**
* Parses the values contained in the given X3D Coordinate, Color, Color3f
* or Normal node and stores them in a float array
*
* @param node
* The X3D node
* @param attributeName
* The name of the attribute containing the values
* @return An array containing the values
*/
private float[] parseValues(Node node, String attributeName) {
Node valuesNode = node.getAttributes().getNamedItem(attributeName);
if (valuesNode == null) {
return null;
}
String valuesString = valuesNode.getNodeValue().trim();
String[] split = valuesString.split(WHITESPACE_COMMA_REGEX);
float[] values = new float[split.length];
for (int i = 0; i < split.length; i++) {
values[i] = getFloat(split[i], 0);
}
return values;
}
/**
* Parses one of the index attributes of an X3D IndexedFaceSet node,
* translates the per-polygon indices into per-triangle indices and returns
* the indices as an array. This method can be used for all of the index
* attributes of an IndexedFaceSet, as they are declared in the same manner
* (consecutive indices define a polygon until a "-1"-index occurs)
*
* @param node
* The X3D IndexedFaceSet node
* @param attributeName
* The name of the index attribute to be parsed
* @return The index array, or <code>null</code> if no coordIndex
* attribute was available
*/
private int[] parseIndices(Node node, String attributeName) {
Node indexNode = node.getAttributes().getNamedItem(attributeName);
if (indexNode == null) {
return null;
}
String indexString = indexNode.getNodeValue().trim();
String[] split = indexString.split(WHITESPACE_COMMA_REGEX);
int maxVerts = 5;
int[] polygon = new int[maxVerts];
int indexCount = 0;
ArrayList<int[]> triangles = new ArrayList<int[]>(split.length / 4 * 3);
for (int i = 0; i < split.length; i++) {
int index = getInt(split[i], 0);
if (index > -1) {
// One more index for the current polygon
if (indexCount == maxVerts) {
int[] temp = new int[maxVerts + 1];
System.arraycopy(polygon, 0, temp, 0, maxVerts);
polygon = temp;
maxVerts++;
}
polygon[indexCount++] = index;
} else {
// Value <= -1: current polygon complete; split up into
// triangles
splitPolygon(polygon, triangles, indexCount);
indexCount = 0;
}
}
if (indexCount > 2) {
splitPolygon(polygon, triangles, indexCount);
}
// Assemble the index array
int[] result = new int[triangles.size() * 3];
for (int i = 0; i < triangles.size(); i++) {
int[] triangle = triangles.get(i);
result[i * 3 + 0] = triangle[0];
result[i * 3 + 1] = triangle[1];
result[i * 3 + 2] = triangle[2];
}
return result;
}
/**
* Splits a polygon of 3 or more indices into triangles. This is currently
* achieved by using the last vertex of the polygon as the center of a fan.
*
* @param polyIndices
* An array containing <code>indexCount</code> polygon indices
* @param triangles
* A list to store arrays of indices, each one containing the
* indices of one triangle
* @param indexCount
* The number of indices of the current polygon
*/
private void splitPolygon(int[] polyIndices, ArrayList<int[]> triangles,
int indexCount) {
for (int i = 0; i < indexCount - 2; i++) {
triangles.add(new int[] { polyIndices[i], polyIndices[i + 1],
polyIndices[indexCount - 1] });
}
}
/**
* Expands the list of value sets so that every three consecutive value sets
* define a triangle. The corresponding index array can be overwritten
* accordingly, so that it looks like this: (0, 1, 2, 3, 4, ...)
*
* @param values
* The values
* @param indices
* The indices
* @param setLength
* The length of one set of values (e.g. a vector, a color, ...).
* The length for vectors is 3, for RGB-colors 3, for RGBA-Colors
* 4 and for texture coordinates 2
* @param rearrangeIndices
* If <code>true</code>, the index array is overwritten
* @return The expanded vertices list
*/
private float[] expandValues(float[] values, int[] indices, int setLength,
boolean rearrangeIndices) {
float[] expValues = new float[indices.length * setLength];
for (int i = 0; i < indices.length; i++) {
for (int j = 0; j < setLength; j++) {
expValues[i * setLength + j] = values[indices[i] * setLength
+ j];
}
if (rearrangeIndices) {
indices[i] = i;
}
}
return expValues;
}
// /**
// * Creates an index array that contains equal indices to equal vectors in
// * the array created by the method
// * {@link #expandValues(float[], int[], int, boolean)}. Each index points
// * to the first occurrence of the vector in the expanded value array.
// * (Yeah, I know the method's name sounds stupid, couldn't find an
// * appropriate one...)
// * @param indices An array containing the original vertex indices
// * @return The array with the changed indices
// */
// private int[] changeIndices(int[] indices, int[] target) {
// int[] sortedIndices = target;
// if (sortedIndices == null) {
// sortedIndices = new int[indices.length];
// }
// Arrays.fill(sortedIndices, -1);
// for (int i = 0; i < indices.length; i++) {
// if (sortedIndices[i] == -1) {
// for (int j = i; j < indices.length; j++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -