Scale Problem?

Started by AGP, August 29, 2017, 10:04:27 PM

Previous topic - Next topic

AGP

I have a class called Bone, as defined in the following code. It's used as a bridge between the JSON-serialized format I created and Bones.


class Bone {
    protected String name;
    protected SimpleVector position;
    protected Matrix transform;
    protected int index, parentIndex;
    public Bone(String name, SimpleVector position, Matrix transform, int index, int parentIndex) {
        this.name = name;
        this.position = position;
        this.transform = transform;
        this.index = index;
        this.parentIndex = parentIndex;
    }
    public boolean hasParent () {
        return this.parentIndex >= 0;
    }
    public String toString () {
        return this.name + ": " + this.position;
    }
}


When I print its values as follows, I get perfectly reasonable numbers (values ranging from -30 to +120).

System.out.println(newBone.toString() +": "+newBone.index);

But, after creating my AnimatedGroup, as follows, the values range between -Infinity to +Infinity, with NaNs thrown in there for good measure.


    public static AnimatedGroup loadGroup(JsonLoader jsonLoader) {
        MaxBonesClip[] clips = Importer.getMaxBonesClips(jsonLoader);
        MaxBonesImporter jImporter = new MaxBonesImporter(jsonLoader, clips);
        ArrayList<ArrayList> objects = jImporter.getList();
        ArrayList<Bone> bones = jImporter.getBones();
        ArrayList<ArrayList> objectsBonesReferences = jImporter.getBonesReferences(); // for all objects, respects the same order of objects
        Animated3D anObject = null;
        SimpleVector center = null;
        scaleBones(bones);
        invertBonesCoords(bones);
        Skeleton skeleton = Importer.makeSkeleton(bones);
        SkeletonPose pose = new SkeletonPose(skeleton);
        pose.updateTransforms();
       
        Animated3D[] list = new Animated3D[objects.size()];
        for (int i = 0; i < objects.size(); i++) {
            ArrayList<ArrayList> theObject = objects.get(i);
            if (bones == null || bones.size() <= 0) {
                Logger.log("Problem: no bones. Try loadObject(String) instead.");
                java.awt.Toolkit.getDefaultToolkit().beep();
                return null;
            }
            anObject = makeAnimated3D(pose, objectsBonesReferences.get(i), theObject, new File(jsonLoader.getMainFileName()).getParent());
            anObject.build();
            list[i] = anObject;
        }
        System.out.println("To test: "+bones.get(JSONFrame.BONE_INDEX_TO_TEST));
        AnimatedGroup asGroup = new AnimatedGroup(list);
        asGroup.setSkinClipSequence(getSkinClipSequence(jImporter, anObject.getSkeleton()));
        return asGroup;
    }
    private static Animated3D makeAnimated3D(SkeletonPose pose, ArrayList<BoneReference> boneRefs, ArrayList<ArrayList> theImportedObject, String absolutePath) {
        ArrayList<ArrayList> vertices = theImportedObject.get(0);
        ArrayList<String> diffuseAndNormal = theImportedObject.get(3);
        int verticesCount = vertices.size();
       
        //skeletonDebugger = new SkeletonDebugger(pose, 0f, 1f);
       
        float[][] weights = new float[verticesCount][Importer.MAX_JOINTS_PER_VERTEX];
        short[][] jointIndices = new short[verticesCount][Importer.MAX_JOINTS_PER_VERTEX];
        int[] verticesCounters = new int[verticesCount];
        for (int i = 0; i < verticesCount; i++) verticesCounters[i] = 0;
       
        for (BoneReference aBoneRef: boneRefs) {
            int vertexRef = aBoneRef.vertexIndexReference;
           
            int verticesCounter = verticesCounters[vertexRef];
            if (verticesCounter < Importer.MAX_JOINTS_PER_VERTEX) {
                weights[vertexRef][verticesCounter] = aBoneRef.vertexWeight;
                jointIndices[vertexRef][verticesCounter] = aBoneRef.boneIndexReference;
                verticesCounters[vertexRef]++;
            }
        }
        SkinData skin = new SkinData(weights, jointIndices);
        if (!TextureManager.getInstance().containsTexture(diffuseAndNormal.get(0)))
        TextureManager.getInstance().addTexture(diffuseAndNormal.get(0), new Texture(absolutePath +File.separator+diffuseAndNormal.get(0)));
       
        MeshData meshData = makeMeshData(theImportedObject);
        Animated3D anAnimated = new Animated3D(meshData, skin, pose);
        anAnimated.setTexture(diffuseAndNormal.get(0));
        return anAnimated;
    }


These prints produce NaNs, and the infinities:

        for (int h = 0; h < asGroup.getSize(); h++) {
            Animated3D temp = asGroup.get(h);
           
            Skeleton s = asGroup.get(h).getSkeletonPose().getSkeleton();

            for (int i = 0; i < s.getNumberOfJoints(); i++) {
                System.out.println(temp.getSkinClipSequence().getClip(0).getSkeleton().getJoint(i).getBindPose().toString());

                //temp.applySkeletonPose();
                //temp.animateSkin(frame, sequence);
                //temp.applyAnimation();
            }
        }

EgonOlsen

Looking at the code, I would expect that one these methods screws it up:


scaleBones(bones);
invertBonesCoords(bones);


What are these doing and can you check if your bones are still correct afterwards?

AGP

#2
Sorry, I hadn't realized that you replied.

No, they were both attempts to fix the incomprehensible problem. scaleBones looks like this (where SCALE is currently set to 1.00f):


    private static void scaleBones(ArrayList<Bone> bones) {
        for (int i = 0; i < bones.size(); i++) {
            Bone aBone = bones.get(i);
            scaleBonePosition(aBone);
            scaleBoneMatrix(aBone);
        }
    }
    private static void scaleBonePosition(Bone aBone) {
        aBone.position.x *= SCALE;
        aBone.position.y *= SCALE;
        aBone.position.z *= SCALE;
    }
   
    private static void scaleBoneMatrix(Bone aBone) {
        aBone.transform.scalarMul(SCALE);
    }


invertBones just multiplies all values by -1. Neither attempts at solutions either help or hurt the problem.

raft

hard to say anything without knowing how that MaxBonesImporter creates Bone objects.

in any case, doesnt look like a Bones related problem.

AGP

If this isn't Bones-related, I don't know what is. Especially since the vertex animations all work perfectly.

AGP

Before animateSkin() ever gets called, I get the following bounding box: -0.328329, 0.343511, -0.159473, 0.230658, 0.00242225, 2.12075.

Afterwards, it becomes: -9.9999998E10, 9.9999998E10, -9.9999998E10, 9.9999998E10, -9.9999998E10, 9.9999998E10

The following is the method with which I print the world-space bounding box:


    public float[] getWorldSpaceBounds(Object3D obj) {
        float[] objectSpaceBounds = obj.getMesh().getBoundingBox();
       
        SimpleVector mins = new SimpleVector(objectSpaceBounds[0], objectSpaceBounds[2], objectSpaceBounds[4]);
        SimpleVector maxs = new SimpleVector(objectSpaceBounds[1], objectSpaceBounds[3], objectSpaceBounds[5]);

        SimpleVector[] p = new SimpleVector[8];
        p[0] = new SimpleVector(mins.x, mins.y, maxs.z);
        p[1] = new SimpleVector(mins.x, mins.y, mins.z);
        p[2] = new SimpleVector(maxs.x, mins.y, mins.z);
        p[3] = new SimpleVector(maxs.x, mins.y, maxs.z);
        p[4] = new SimpleVector(maxs.x, maxs.y, mins.z);
        p[5] = new SimpleVector(maxs.x, maxs.y, maxs.z);
        p[6] = new SimpleVector(mins.x, maxs.y, mins.z);
        p[7] = new SimpleVector(mins.x, maxs.y, maxs.z);

        float minX = Float.MAX_VALUE;
        float minY = Float.MAX_VALUE;
        float minZ = Float.MAX_VALUE;
        float maxX = -Float.MAX_VALUE;
        float maxY = -Float.MAX_VALUE;
        float maxZ = -Float.MAX_VALUE;

        for (int i = 0; i < 8; i++)  {
            p[i].matMul(obj.getWorldTransformation());

            if (p[i].x < minX) { minX = p[i].x; }
            if (p[i].y < minY) { minY = p[i].y; }
            if (p[i].z < minZ) { minZ = p[i].z; }
            if (p[i].x > maxX) { maxX = p[i].x; }
            if (p[i].y > maxY) { maxY = p[i].y; }
            if (p[i].z > maxZ) { maxZ = p[i].z; }
        }

        float[] worldSpaceBounds = new float[6];
        worldSpaceBounds[0] = minX;
        worldSpaceBounds[1] = maxX;
        worldSpaceBounds[2] = minY;
        worldSpaceBounds[3] = maxY;
        worldSpaceBounds[4] = minZ;
        worldSpaceBounds[5] = maxZ;

        return worldSpaceBounds;
    }

EgonOlsen

How does the bounding box look in object space?

AGP

Before animateSkin:
Quote
*****Object-space bounds: *****
-0.328329
0.343511
-0.159473
0.230658
0.00242225
2.12075
***** ****** *****
*****World-space bounds: *****
-0.328329
0.343511
-0.159473
0.230658
0.00242225
2.12075
***** ****** *****

After animateSkin:
Quote
*****Object-space bounds: *****
9.9999998E10
-9.9999998E10
9.9999998E10
-9.9999998E10
9.9999998E10
-9.9999998E10
***** ****** *****
*****World-space bounds: *****
-9.9999998E10
9.9999998E10
-9.9999998E10
9.9999998E10
-9.9999998E10
9.9999998E10
***** ****** *****

Any clues?

EgonOlsen

These values look like the initial values of the BB calculation. Which basically means that the object that you are using to calculate the BB on...is empty (i.e. no vertices at all).

AGP

I assume you mean that only the post-animateSkin values don't have vertices. Raft, any clue as to how animateSkin could destroy the model's vertices?

raft

Quote from: AGP on September 19, 2017, 06:02:45 AM
Raft, any clue as to how animateSkin could destroy the model's vertices?
no idea actually