use of com.jme3.util.IntMap in project jmonkeyengine by jMonkeyEngine.
the class FbxMesh method createGeometries.
private List<Geometry> createGeometries() throws IOException {
Mesh mesh = new Mesh();
mesh.setMode(Mode.Triangles);
// Moreover quads should be triangulated (this increases number of vertices)
if (indices != null) {
iCount = indices.length;
srcVertexCount = vertices.length / 3;
// Indices contains negative numbers to define polygon last index
// Check indices strides to be sure we have triangles or quads
vCount = 0;
// Count number of vertices to be produced
int polyVertCount = 0;
for (int i = 0; i < iCount; ++i) {
int index = indices[i];
polyVertCount++;
if (index < 0) {
if (polyVertCount == 3) {
// A triangle
vCount += 3;
} else if (polyVertCount == 4) {
// A quad produce two triangles
vCount += 6;
} else {
throw new AssetLoadException("Unsupported PolygonVertexIndex stride");
}
polyVertCount = 0;
}
}
// Unroll index array into vertex mapping
vertexMap = new ArrayList<>(vCount);
indexMap = new ArrayList<>(vCount);
polyVertCount = 0;
for (int i = 0; i < iCount; ++i) {
int index = indices[i];
polyVertCount++;
if (index < 0) {
int lastIndex = -(index + 1);
if (polyVertCount == 3) {
vertexMap.add(indices[i - 2]);
vertexMap.add(indices[i - 1]);
vertexMap.add(lastIndex);
indexMap.add(i - 2);
indexMap.add(i - 1);
indexMap.add(i - 0);
} else if (polyVertCount == 4) {
vertexMap.add(indices[i - 3]);
vertexMap.add(indices[i - 2]);
vertexMap.add(indices[i - 1]);
vertexMap.add(indices[i - 3]);
vertexMap.add(indices[i - 1]);
vertexMap.add(lastIndex);
indexMap.add(i - 3);
indexMap.add(i - 2);
indexMap.add(i - 1);
indexMap.add(i - 3);
indexMap.add(i - 1);
indexMap.add(i - 0);
}
polyVertCount = 0;
}
}
// Build reverse vertex mapping
reverseVertexMap = new ArrayList<>(srcVertexCount);
for (int i = 0; i < srcVertexCount; ++i) reverseVertexMap.add(new ArrayList<Integer>());
for (int i = 0; i < vCount; ++i) {
int index = vertexMap.get(i);
reverseVertexMap.get(index).add(i);
}
} else {
// Stub for no vertex indexing (direct mapping)
iCount = vCount = srcVertexCount;
vertexMap = new ArrayList<>(vCount);
indexMap = new ArrayList<>(vCount);
reverseVertexMap = new ArrayList<>(vCount);
for (int i = 0; i < vCount; ++i) {
vertexMap.set(i, i);
indexMap.set(i, i);
List<Integer> l = new ArrayList<Integer>(1);
l.add(i);
reverseVertexMap.add(l);
}
}
if (vertices != null) {
// Unroll vertices data array
FloatBuffer posBuf = BufferUtils.createFloatBuffer(vCount * 3);
mesh.setBuffer(VertexBuffer.Type.Position, 3, posBuf);
int srcCount = vertices.length / 3;
for (int i = 0; i < vCount; ++i) {
int index = vertexMap.get(i);
if (index > srcCount)
throw new AssetLoadException("Invalid vertex mapping. Unexpected lookup vertex " + index + " from " + srcCount);
// XXX Why we should scale by unit size?
float x = (float) vertices[3 * index + 0] / scene.unitSize * scene.xAxis;
float y = (float) vertices[3 * index + 1] / scene.unitSize * scene.yAxis;
float z = (float) vertices[3 * index + 2] / scene.unitSize * scene.zAxis;
posBuf.put(x).put(y).put(z);
}
}
if (normals != null) {
// Unroll normals data array
FloatBuffer normBuf = BufferUtils.createFloatBuffer(vCount * 3);
mesh.setBuffer(VertexBuffer.Type.Normal, 3, normBuf);
List<Integer> mapping = null;
if (normalsMapping.equals("ByVertice"))
mapping = vertexMap;
else if (normalsMapping.equals("ByPolygonVertex"))
mapping = indexMap;
else
throw new IOException("Unknown normals mapping type: " + normalsMapping);
int srcCount = normals.length / 3;
for (int i = 0; i < vCount; ++i) {
int index = mapping.get(i);
if (index > srcCount)
throw new AssetLoadException("Invalid normal mapping. Unexpected lookup normal " + index + " from " + srcCount);
float x = (float) normals[3 * index + 0] * scene.xAxis;
float y = (float) normals[3 * index + 1] * scene.yAxis;
float z = (float) normals[3 * index + 2] * scene.zAxis;
normBuf.put(x).put(y).put(z);
}
}
if (tangents != null) {
// Unroll normals data array
FloatBuffer tanBuf = BufferUtils.createFloatBuffer(vCount * 4);
mesh.setBuffer(VertexBuffer.Type.Tangent, 4, tanBuf);
List<Integer> mapping = null;
if (tangentsMapping.equals("ByVertice"))
mapping = vertexMap;
else if (tangentsMapping.equals("ByPolygonVertex"))
mapping = indexMap;
else
throw new IOException("Unknown tangents mapping type: " + tangentsMapping);
int srcCount = tangents.length / 3;
for (int i = 0; i < vCount; ++i) {
int index = mapping.get(i);
if (index > srcCount)
throw new AssetLoadException("Invalid tangent mapping. Unexpected lookup tangent " + index + " from " + srcCount);
float x = (float) tangents[3 * index + 0] * scene.xAxis;
float y = (float) tangents[3 * index + 1] * scene.yAxis;
float z = (float) tangents[3 * index + 2] * scene.zAxis;
tanBuf.put(x).put(y).put(z).put(-1.0f);
}
}
if (binormals != null) {
// Unroll normals data array
FloatBuffer binormBuf = BufferUtils.createFloatBuffer(vCount * 3);
mesh.setBuffer(VertexBuffer.Type.Binormal, 3, binormBuf);
List<Integer> mapping = null;
if (binormalsMapping.equals("ByVertice"))
mapping = vertexMap;
else if (binormalsMapping.equals("ByPolygonVertex"))
mapping = indexMap;
else
throw new IOException("Unknown binormals mapping type: " + binormalsMapping);
int srcCount = binormals.length / 3;
for (int i = 0; i < vCount; ++i) {
int index = mapping.get(i);
if (index > srcCount)
throw new AssetLoadException("Invalid binormal mapping. Unexpected lookup binormal " + index + " from " + srcCount);
float x = (float) binormals[3 * index + 0] * scene.xAxis;
float y = (float) binormals[3 * index + 1] * scene.yAxis;
float z = (float) binormals[3 * index + 2] * scene.zAxis;
binormBuf.put(x).put(y).put(z);
}
}
for (int uvLayer = 0; uvLayer < uvs.size(); ++uvLayer) {
double[] uv = uvs.get(uvLayer);
int[] uvIndex = uvIndexes.size() > uvLayer ? uvIndexes.get(uvLayer) : null;
List<Integer> unIndexMap = vertexMap;
if (uvIndex != null) {
int uvIndexSrcCount = uvIndex.length;
if (uvIndexSrcCount != iCount)
throw new AssetLoadException("Invalid number of texcoord index data " + uvIndexSrcCount + " expected " + iCount);
// Unroll UV index array
unIndexMap = new ArrayList<>(vCount);
int polyVertCount = 0;
for (int i = 0; i < iCount; ++i) {
int index = indices[i];
polyVertCount++;
if (index < 0) {
if (polyVertCount == 3) {
unIndexMap.add(uvIndex[i - 2]);
unIndexMap.add(uvIndex[i - 1]);
unIndexMap.add(uvIndex[i - 0]);
} else if (polyVertCount == 4) {
unIndexMap.add(uvIndex[i - 3]);
unIndexMap.add(uvIndex[i - 2]);
unIndexMap.add(uvIndex[i - 1]);
unIndexMap.add(uvIndex[i - 3]);
unIndexMap.add(uvIndex[i - 1]);
unIndexMap.add(uvIndex[i - 0]);
}
polyVertCount = 0;
}
}
}
// Unroll UV data array
FloatBuffer tcBuf = BufferUtils.createFloatBuffer(vCount * 2);
VertexBuffer.Type type = VertexBuffer.Type.TexCoord;
switch(uvLayer) {
case 1:
type = VertexBuffer.Type.TexCoord2;
break;
case 2:
type = VertexBuffer.Type.TexCoord3;
break;
case 3:
type = VertexBuffer.Type.TexCoord4;
break;
case 4:
type = VertexBuffer.Type.TexCoord5;
break;
case 5:
type = VertexBuffer.Type.TexCoord6;
break;
case 6:
type = VertexBuffer.Type.TexCoord7;
break;
case 7:
type = VertexBuffer.Type.TexCoord8;
break;
}
mesh.setBuffer(type, 2, tcBuf);
int srcCount = uv.length / 2;
for (int i = 0; i < vCount; ++i) {
int index = unIndexMap.get(i);
if (index > srcCount)
throw new AssetLoadException("Invalid texcoord mapping. Unexpected lookup texcoord " + index + " from " + srcCount);
float u = (index >= 0) ? (float) uv[2 * index + 0] : 0;
float v = (index >= 0) ? (float) uv[2 * index + 1] : 0;
tcBuf.put(u).put(v);
}
}
List<Geometry> geometries = new ArrayList<Geometry>();
if (materialsReference.equals("IndexToDirect") && materialsMapping.equals("ByPolygon")) {
IntMap<List<Integer>> indexBuffers = new IntMap<>();
for (int polygon = 0; polygon < materials.length; ++polygon) {
int material = materials[polygon];
List<Integer> list = indexBuffers.get(material);
if (list == null) {
list = new ArrayList<>();
indexBuffers.put(material, list);
}
list.add(polygon * 3 + 0);
list.add(polygon * 3 + 1);
list.add(polygon * 3 + 2);
}
Iterator<Entry<List<Integer>>> iterator = indexBuffers.iterator();
while (iterator.hasNext()) {
Entry<List<Integer>> e = iterator.next();
int materialId = e.getKey();
List<Integer> indexes = e.getValue();
Mesh newMesh = mesh.clone();
newMesh.setBuffer(VertexBuffer.Type.Index, 3, toArray(indexes.toArray(new Integer[indexes.size()])));
newMesh.setStatic();
newMesh.updateBound();
newMesh.updateCounts();
Geometry geom = new Geometry();
geom.setMesh(newMesh);
geometries.add(geom);
geom.setUserData("FBXMaterial", materialId);
}
} else {
mesh.setStatic();
mesh.updateBound();
mesh.updateCounts();
Geometry geom = new Geometry();
geom.setMesh(mesh);
geometries.add(geom);
}
return geometries;
}
use of com.jme3.util.IntMap in project jmonkeyengine by jMonkeyEngine.
the class GLTracer method generateConstantMap.
private static IntMap<String> generateConstantMap(Class<?>... classes) {
IntMap<String> constMap = new IntMap<String>();
for (Class<?> clazz : classes) {
for (Field field : clazz.getFields()) {
if (field.getType() == int.class) {
try {
int val = field.getInt(null);
String name = field.getName();
constMap.put(val, name);
} catch (IllegalArgumentException ex) {
} catch (IllegalAccessException ex) {
}
}
}
}
// GL_ONE is more common than GL_TRUE (which is a boolean anyway..)
constMap.put(1, "GL_ONE");
return constMap;
}
use of com.jme3.util.IntMap in project jmonkeyengine by jMonkeyEngine.
the class GLRenderer method renderMeshVertexArray.
private void renderMeshVertexArray(Mesh mesh, int lod, int count, VertexBuffer instanceData) {
if (mesh.getId() == -1) {
updateVertexArray(mesh, instanceData);
} else {
// TODO: Check if it was updated
}
if (context.boundVertexArray != mesh.getId()) {
gl3.glBindVertexArray(mesh.getId());
context.boundVertexArray = mesh.getId();
}
// IntMap<VertexBuffer> buffers = mesh.getBuffers();
VertexBuffer indices;
if (mesh.getNumLodLevels() > 0) {
indices = mesh.getLodLevel(lod);
} else {
indices = mesh.getBuffer(Type.Index);
}
if (indices != null) {
drawTriangleList(indices, mesh, count);
} else {
drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount());
}
clearVertexAttribs();
}
use of com.jme3.util.IntMap in project jmonkeyengine by jMonkeyEngine.
the class FbxMesh method toJmeObject.
@Override
protected IntMap<Mesh> toJmeObject() {
// Load clusters from SkinDeformer
if (skinDeformer != null) {
for (FbxCluster cluster : skinDeformer.getJmeObject()) {
applyCluster(cluster);
}
}
IrMesh irMesh = toIRMesh();
// Trim bone weights to 4 weights per vertex.
IrUtils.trimBoneWeights(irMesh);
// Convert tangents / binormals to tangents with parity.
IrUtils.toTangentsWithParity(irMesh);
// Triangulate quads.
IrUtils.triangulate(irMesh);
// Split meshes by material indices.
IntMap<IrMesh> irMeshes = IrUtils.splitByMaterial(irMesh);
// Create a jME3 Mesh for each material index.
IntMap<Mesh> jmeMeshes = new IntMap<Mesh>();
for (IntMap.Entry<IrMesh> irMeshEntry : irMeshes) {
Mesh jmeMesh = IrUtils.convertIrMeshToJmeMesh(irMeshEntry.getValue());
jmeMeshes.put(irMeshEntry.getKey(), jmeMesh);
}
if (jmeMeshes.size() == 0) {
// When will this actually happen? Not sure.
logger.log(Level.WARNING, "Empty FBX mesh found (unusual).");
}
// It makes sense only if the mesh uses a single material!
if (jmeMeshes.containsKey(-1) && jmeMeshes.size() > 1) {
logger.log(Level.WARNING, "Mesh has polygons with no material " + "indices (unusual) - they will use material index 0.");
}
return jmeMeshes;
}
use of com.jme3.util.IntMap in project jmonkeyengine by jMonkeyEngine.
the class FbxNode method toJmeObject.
@Override
public Spatial toJmeObject() {
Spatial spatial;
if (nodeAttribute instanceof FbxMesh) {
FbxMesh fbxMesh = (FbxMesh) nodeAttribute;
IntMap<Mesh> jmeMeshes = fbxMesh.getJmeObject();
if (jmeMeshes == null || jmeMeshes.size() == 0) {
// No meshes found on FBXMesh (??)
logger.log(Level.WARNING, "No meshes could be loaded. Creating empty node.");
spatial = new Node(getName() + "-node");
} else {
// Multiple jME3 geometries required for a single FBXMesh.
String nodeName;
if (children.isEmpty()) {
nodeName = getName() + "-mesh";
} else {
nodeName = getName() + "-node";
}
Node node = new Node(nodeName);
boolean singleMesh = jmeMeshes.size() == 1;
for (IntMap.Entry<Mesh> meshInfo : jmeMeshes) {
node.attachChild(tryCreateGeometry(meshInfo.getKey(), meshInfo.getValue(), singleMesh));
}
spatial = node;
}
} else {
if (nodeAttribute != null) {
// Just specifies that this is a "null" node.
nodeAttribute.getJmeObject();
}
// TODO: handle other node attribute types.
// right now everything we don't know about gets converted
// to jME3 Node.
spatial = new Node(getName() + "-node");
}
if (!children.isEmpty()) {
// Check uniform scale.
// Although, if inheritType is 0 (eInheritRrSs)
// it might not be a problem.
Vector3f localScale = jmeLocalNodeTransform.getScale();
if (!FastMath.approximateEquals(localScale.x, localScale.y) || !FastMath.approximateEquals(localScale.x, localScale.z)) {
logger.log(Level.WARNING, "Non-uniform scale detected on parent node. " + "The model may appear distorted.");
}
}
spatial.setLocalTransform(jmeLocalNodeTransform);
if (visibility == 0.0) {
spatial.setCullHint(CullHint.Always);
}
for (Map.Entry<String, Object> userDataEntry : userData.entrySet()) {
spatial.setUserData(userDataEntry.getKey(), userDataEntry.getValue());
}
return spatial;
}
Aggregations