Added support for attachment nodes.
JME now supports byte buffers for index buffer
This commit is contained in:
parent
d6c74dbf37
commit
1bdebd5505
@ -2592,6 +2592,7 @@ public final class GLRenderer implements Renderer {
|
||||
}
|
||||
|
||||
switch (indexBuf.getFormat()) {
|
||||
case UnsignedByte:
|
||||
case UnsignedShort:
|
||||
// OK: Works on all platforms.
|
||||
break;
|
||||
|
@ -53,6 +53,8 @@ import com.jme3.util.IntMap.Entry;
|
||||
import com.jme3.util.SafeArrayList;
|
||||
import com.jme3.util.clone.Cloner;
|
||||
import com.jme3.util.clone.JmeCloneable;
|
||||
import com.sun.javaws.exceptions.InvalidArgumentException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.*;
|
||||
import java.util.ArrayList;
|
||||
@ -402,11 +404,20 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
|
||||
// convert indices to ubytes on the heap
|
||||
VertexBuffer indices = getBuffer(Type.BoneIndex);
|
||||
if (!indices.getData().hasArray()) {
|
||||
ByteBuffer originalIndex = (ByteBuffer) indices.getData();
|
||||
ByteBuffer arrayIndex = ByteBuffer.allocate(originalIndex.capacity());
|
||||
originalIndex.clear();
|
||||
arrayIndex.put(originalIndex);
|
||||
indices.updateData(arrayIndex);
|
||||
if (indices.getFormat() == Format.UnsignedByte) {
|
||||
ByteBuffer originalIndex = (ByteBuffer) indices.getData();
|
||||
ByteBuffer arrayIndex = ByteBuffer.allocate(originalIndex.capacity());
|
||||
originalIndex.clear();
|
||||
arrayIndex.put(originalIndex);
|
||||
indices.updateData(arrayIndex);
|
||||
} else {
|
||||
//bone indices can be stored in an UnsignedShort buffer
|
||||
ShortBuffer originalIndex = (ShortBuffer) indices.getData();
|
||||
ShortBuffer arrayIndex = ShortBuffer.allocate(originalIndex.capacity());
|
||||
originalIndex.clear();
|
||||
arrayIndex.put(originalIndex);
|
||||
indices.updateData(arrayIndex);
|
||||
}
|
||||
}
|
||||
indices.setUsage(Usage.CpuOnly);
|
||||
|
||||
@ -1437,7 +1448,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
|
||||
return false; // no bone animation data
|
||||
}
|
||||
|
||||
ByteBuffer boneIndexBuffer = (ByteBuffer) biBuf.getData();
|
||||
BufferUtils.ByteShortIntBufferReader boneIndexBuffer = new BufferUtils.ByteShortIntBufferReader(biBuf.getData());
|
||||
boneIndexBuffer.rewind();
|
||||
int numBoneIndices = boneIndexBuffer.remaining();
|
||||
assert numBoneIndices % 4 == 0 : numBoneIndices;
|
||||
@ -1450,10 +1461,10 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
|
||||
/*
|
||||
* Test each vertex to determine whether the bone affects it.
|
||||
*/
|
||||
byte biByte = (byte) boneIndex; // bone indices wrap after 127
|
||||
int biByte = boneIndex;
|
||||
for (int vIndex = 0; vIndex < numVertices; vIndex++) {
|
||||
for (int wIndex = 0; wIndex < 4; wIndex++) {
|
||||
byte bIndex = boneIndexBuffer.get();
|
||||
int bIndex = boneIndexBuffer.get();
|
||||
float weight = weightBuffer.get();
|
||||
if (wIndex < maxNumWeights && bIndex == biByte && weight != 0f) {
|
||||
return true;
|
||||
|
@ -1340,4 +1340,44 @@ public final class BufferUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ByteShortIntBufferReader {
|
||||
Buffer buffer;
|
||||
|
||||
public ByteShortIntBufferReader(Buffer buffer) {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
public int get() {
|
||||
if (buffer instanceof ByteBuffer) {
|
||||
return ((ByteBuffer) buffer).get();
|
||||
} else if (buffer instanceof ShortBuffer) {
|
||||
return ((ShortBuffer) buffer).get();
|
||||
} else if (buffer instanceof IntBuffer) {
|
||||
return ((IntBuffer) buffer).get();
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Buffer must be a ByteBuffer, a ShortBuffer or an IntBuffer");
|
||||
}
|
||||
}
|
||||
|
||||
public int get(int index) {
|
||||
if (buffer instanceof ByteBuffer) {
|
||||
return ((ByteBuffer) buffer).get(index);
|
||||
} else if (buffer instanceof ShortBuffer) {
|
||||
return ((ShortBuffer) buffer).get(index);
|
||||
} else if (buffer instanceof IntBuffer) {
|
||||
return ((IntBuffer) buffer).get(index);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Buffer must be a ByteBuffer, a ShortBuffer or an IntBuffer");
|
||||
}
|
||||
}
|
||||
|
||||
public void rewind() {
|
||||
buffer.rewind();
|
||||
}
|
||||
|
||||
public int remaining() {
|
||||
return buffer.remaining();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -894,7 +894,6 @@ public class GltfLoader implements AssetLoader {
|
||||
int boneIndex = joints.get(i).getAsInt();
|
||||
//we don't need the inverse bind matrix, we need the bind matrix so let's invert it.
|
||||
Matrix4f modelBindMatrix = inverseBindMatrices[i].invertLocal();
|
||||
//TODO actually a regular node or a geometry can be attached to a bone, we have to handle this and attach it to the AttachementNode.
|
||||
bones[i] = readNodeAsBone(boneIndex, i, index, modelBindMatrix);
|
||||
}
|
||||
|
||||
@ -990,10 +989,11 @@ public class GltfLoader implements AssetLoader {
|
||||
return bone;
|
||||
}
|
||||
|
||||
private void findChildren(int nodeIndex) {
|
||||
private void findChildren(int nodeIndex) throws IOException {
|
||||
BoneWrapper bw = fetchFromCache("nodes", nodeIndex, BoneWrapper.class);
|
||||
JsonObject nodeData = nodes.get(nodeIndex).getAsJsonObject();
|
||||
JsonArray children = nodeData.getAsJsonArray("children");
|
||||
|
||||
if (children != null) {
|
||||
for (JsonElement child : children) {
|
||||
int childIndex = child.getAsInt();
|
||||
@ -1001,8 +1001,18 @@ public class GltfLoader implements AssetLoader {
|
||||
if (cbw != null) {
|
||||
bw.bone.addChild(cbw.bone);
|
||||
bw.children.add(childIndex);
|
||||
} else {
|
||||
JsonObject childNode = nodes.get(childIndex).getAsJsonObject();
|
||||
//The child might be a Geom
|
||||
if (getAsInteger(childNode, "mesh") != null) {
|
||||
//this is a geometry, let's load it as a spatial
|
||||
Spatial s = (Spatial) readNode(childIndex);
|
||||
bw.attachedSpatial = s;
|
||||
// addToCache("nodes", nodeIndex, s, nodes.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1010,6 +1020,10 @@ public class GltfLoader implements AssetLoader {
|
||||
for (SkinData skinData : skinnedSpatials.keySet()) {
|
||||
List<Spatial> spatials = skinnedSpatials.get(skinData);
|
||||
Spatial spatial;
|
||||
if (spatials.isEmpty()) {
|
||||
//can happen when a file contains a skin that is not used by any mesh...
|
||||
continue;
|
||||
}
|
||||
if (spatials.size() >= 1) {
|
||||
spatial = findCommonAncestor(spatials);
|
||||
} else {
|
||||
@ -1028,9 +1042,17 @@ public class GltfLoader implements AssetLoader {
|
||||
|
||||
if (skinData.animControl != null) {
|
||||
spatial.addControl(skinData.animControl);
|
||||
spatial.addControl(skinData.skeletonControl);
|
||||
}
|
||||
spatial.addControl(skinData.skeletonControl);
|
||||
}
|
||||
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
BoneWrapper bw = fetchFromCache("nodes", i, BoneWrapper.class);
|
||||
if (bw == null || bw.attachedSpatial == null) {
|
||||
continue;
|
||||
}
|
||||
SkinData skinData = fetchFromCache("skins", bw.skinIndex, SkinData.class);
|
||||
skinData.skeletonControl.getAttachmentsNode(bw.bone.getName()).attachChild(bw.attachedSpatial);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1044,7 +1066,13 @@ public class GltfLoader implements AssetLoader {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
return type.cast(data[index]);
|
||||
try {
|
||||
T ret = type.cast(data[index]);
|
||||
return ret;
|
||||
} catch (ClassCastException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void addToCache(String name, int index, Object object, int maxLength) {
|
||||
@ -1128,6 +1156,7 @@ public class GltfLoader implements AssetLoader {
|
||||
Transform localTransform;
|
||||
Matrix4f modelBindMatrix;
|
||||
boolean isRoot = false;
|
||||
Spatial attachedSpatial;
|
||||
List<Integer> children = new ArrayList<>();
|
||||
|
||||
public BoneWrapper(Bone bone, int boneIndex, int skinIndex, Matrix4f modelBindMatrix, Transform localTransform) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user