package com.badlogic.gdx.graphics.g3d.loaders.collada;
import java.io.InputStream;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g3d.ModelLoaderHints;
import com.badlogic.gdx.graphics.g3d.loaders.SkeletonModelLoader;
import com.badlogic.gdx.graphics.g3d.model.skeleton.Skeleton;
import com.badlogic.gdx.graphics.g3d.model.skeleton.SkeletonAnimation;
import com.badlogic.gdx.graphics.g3d.model.skeleton.SkeletonJoint;
import com.badlogic.gdx.graphics.g3d.model.skeleton.SkeletonModel;
import com.badlogic.gdx.graphics.g3d.model.skeleton.SkeletonSubMesh;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.XmlReader;
import com.badlogic.gdx.utils.XmlReader.Element;
public class ColladaLoaderSkeleton implements SkeletonModelLoader {
@Override
public SkeletonModel load(FileHandle handle, ModelLoaderHints hints) {
return loadSkeletonModel(handle);
}
public static SkeletonModel loadSkeletonModel (FileHandle handle) {
return loadSkeletonModel(handle.read());
}
public static SkeletonModel loadSkeletonModel (InputStream in) {
XmlReader xml = new XmlReader();
Element root = null;
try {
root = xml.parse(in);
} catch (Exception e) {
throw new GdxRuntimeException("Couldn't load Collada model", e);
}
// get geometries
Array<Geometry> geos = ColladaLoader.readGeometries(root);
Array<Skin> skins = readSkins(root);
Joint joint = readJoint(root);
Animation anim = readAnim(root);
// convert geometries to meshes
SkeletonSubMesh[] meshes = createSkeletonSubMeshes(geos, skins);
Skeleton skeleton = createSkeleton(skins, joint.joint,anim);
// create SkeletonModel
SkeletonModel model = new SkeletonModel(skeleton,meshes);
return model;
}
private static Array<Skin> readSkins (Element root) {
// check whether the library_controllers element is there
Element colladaGeoLibrary = root.getChildByName("library_controllers");
if (colladaGeoLibrary == null) throw new GdxRuntimeException("not <library_controllers> element in file");
// check for controller
Element colladaController = colladaGeoLibrary.getChildByName("controller");
if (colladaController == null) throw new GdxRuntimeException("no <controller> elements in file");
// check for controller
Array<Element> colladaSkin = colladaController.getChildrenByName("skin");
if (colladaSkin == null) throw new GdxRuntimeException("no <skin> elements in file");
Array<Skin> skins = new Array<Skin>();
for (int i = 0; i < colladaSkin.size; i++) {
skins.add(new Skin(colladaSkin.get(i)));
}
return skins;
}
private static Joint readJoint (Element root) {
// check whether the library_controllers element is there
Element colladaLibrary = root.getChildByName("library_visual_scenes");
if (colladaLibrary == null) throw new GdxRuntimeException("not <library_visual_scenes> element in file");
// check for controller
Element colladaScene = colladaLibrary.getChildByName("visual_scene");
if (colladaScene == null) throw new GdxRuntimeException("no <controller> elements in file");
return new Joint(colladaScene);
}
private static Animation readAnim (Element root) {
// check whether the library_controllers element is there
Element colladaAnimationLib = root.getChildByName("library_animations");
if (colladaAnimationLib == null) throw new GdxRuntimeException("not <library_animations> element in file");
return new Animation(colladaAnimationLib);
}
private static Skeleton createSkeleton(Array<Skin> skins, SkeletonJoint joint, Animation anim)
{
Skeleton skeleton = new Skeleton();
for(int i=0;i<joint.children.size;i++){
skeleton.hierarchy.add(joint.children.get(i));
}
skeleton.buildFromHierarchy();
float[] times = anim.inputMap.values().next();
float totalDuration = times[times.length-1];
skeleton.animations.put("My Animation", new SkeletonAnimation("My Animation", totalDuration, anim.keyFrames));
return skeleton;
}
private static SkeletonSubMesh[] createSkeletonSubMeshes (Array<Geometry> geos, Array<Skin> skins) {
SkeletonSubMesh[] meshes = new SkeletonSubMesh[geos.size];
for (int i = 0; i < geos.size; i++) {
meshes[i] = geos.get(i).getSkeletonSubMesh(skins.get(i));
}
return meshes;
}
}