Ok now, what the hell is going on here. Blender and bones are going to be the death of me

So i’ve posted a lot lately about my recent experiences with working with bones exported from Blender to LibGDX.  I encountered two problems, first only the base of the bone was available once exported.  Second, bones that were external to the mesh weren’t being updated.  The first isn’t really a big deal, except the solution to it seemingly is impacted by the second problem.  There was a thread over on LibGDX forums I posted my experiences on, and Xoppa, the guy behind the 3D portions of LibGDX posted that my observations simply weren’t correct.  This post here is mostly a recap of that thread.  I am not sure if anything in this thread will be of value to any of you, but it does illustrate that sometimes… who knows, it might just be gremlins!

 

So I set about creating a minimal sample to illustrate the problem I was having.  I have literally done this a few dozen, perhaps hundred, of times the past week.

 

I created an ultra simple model in Blender, with a bone external to mesh.  In my experiences to this point, every time I try to get the position of this external bone, the results will always be 0,0,0.  All internal bones will work fine, but the external one won’t.

 

Here is the model:

11

 

Simple enough, a mesh with a simple 3 bone armature bound to it.  What you don’t see is I’ve also done a small animation sequence ( as Default Take ).

 

I then load it with the following code.  The idea is draw a sphere at the location of each bone.  Pretty much what I expected to see is two two spheres, with the third one missing ( as it will actually be at 0,0,0, the same location as the first one.

package com.gamefromscratch;

 

import com.badlogic.gdx.ApplicationListener;

import com.badlogic.gdx.Files.FileType;

import com.badlogic.gdx.Gdx;

import com.badlogic.gdx.graphics.Color;

import com.badlogic.gdx.graphics.GL10;

import com.badlogic.gdx.graphics.GL20;

import com.badlogic.gdx.graphics.PerspectiveCamera;

import com.badlogic.gdx.graphics.VertexAttributes.Usage;

import com.badlogic.gdx.graphics.g3d.Environment;

import com.badlogic.gdx.graphics.g3d.Material;

import com.badlogic.gdx.graphics.g3d.Model;

import com.badlogic.gdx.graphics.g3d.ModelBatch;

import com.badlogic.gdx.graphics.g3d.ModelInstance;

import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;

import com.badlogic.gdx.graphics.g3d.loader.G3dModelLoader;

import com.badlogic.gdx.graphics.g3d.model.Node;

import com.badlogic.gdx.utils.JsonReader;

import com.badlogic.gdx.graphics.g3d.utils.AnimationController;

import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;

import com.badlogic.gdx.math.Vector3;

 

 

public class TankDemo implements ApplicationListener {

    private PerspectiveCamera camera;

    private ModelBatch modelBatch;

    private AnimationController animationController;

    

    private Model model;

    private ModelInstance modelInstance;

 

    private Model pivot;

    private ModelInstance p1, p2, p3;

    private Node bone1,bone2,bone3;

    

    private Environment environment;

    

    @Override

    public void create() {  

    camera = new PerspectiveCamera(

   75,

                Gdx.graphics.getWidth(),

                Gdx.graphics.getHeight());

        

        camera.position.set(0f,0f,-8f);

        camera.lookAt(0f,0f,0f);

        camera.near = 0.1f; 

        camera.far = 300.0f;

 

        modelBatch = new ModelBatch();

        

        JsonReader jsonReader = new JsonReader();

        G3dModelLoader modelLoader = new G3dModelLoader(jsonReader);

        model = modelLoader.loadModel(Gdx.files.getFileHandle(“data/demo.g3dj”, FileType.Internal));

        modelInstance = new ModelInstance(model);

        

        animationController = new AnimationController(modelInstance);

        animationController.animate(“Default Take”,-1,null,0);

        

        bone1 = modelInstance.getNode(“Bone”);

        bone2 = modelInstance.getNode(“Bone_001”);

        bone3 = modelInstance.getNode(“Bone_002”);

        

        ModelBuilder mb = new ModelBuilder();

        

        pivot = mb.createSphere(0.5f,0.5f,0.5f,10,10,GL20.GL_LINES,new Material(ColorAttribute.createDiffuse(Color.RED)),Usage.Position | Usage.Normal);

        p1 = new ModelInstance(pivot);

        p2 = new ModelInstance(pivot);

        p3 = new ModelInstance(pivot);

        

 

        

        environment = new Environment();

        environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.8f, 0.8f, 0.8f, 1.0f));

    }

 

    @Override

    public void dispose() {

        modelBatch.dispose();

        model.dispose();

    }

 

    @Override

    public void render() {

        Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

        Gdx.gl.glClearColor(1, 1, 1, 1);

        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        

        animationController.update(Gdx.graphics.getDeltaTime());

        Vector3 pos = new Vector3();

        bone1.globalTransform.getTranslation(pos);

        p1.transform.set(bone1.globalTransform);

        p2.transform.set(bone2.globalTransform);

        p3.transform.set(bone3.globalTransform);

        

        camera.update();

        modelBatch.begin(camera);

        modelBatch.render(modelInstance, environment);

        modelBatch.render(p1, environment);

        modelBatch.render(p2, environment);

        modelBatch.render(p3, environment);

        

        modelBatch.end();

    }

 

    @Override

    public void resize(int width, int height) {

    }

 

    @Override

    public void pause() {

    }

 

    @Override

    public void resume() {

    }

 

}

 

Then when I run this code I see:

1

 

Or, with the line rendering the main mesh itself commented out to more clearly show the bone locations:

2

 

For #[email protected]#[email protected] #@[email protected]#$ @#[email protected]$’s sake…

 

Why the swearing?  Because this is working EXACTLY how it is supposed to.  EXACTLY how I expected it to a week ago.  Exactly how Xoppa said it should.

 

What it isn’t doing is behaving EXACTLY how it has been for the last 50 or so times I tried the same thing!  Literally every time I did this before, that final bone didn’t update.  No bones in the armature that were external to the mesh itself were updated.  So I thought maybe that’s it…  maybe something about this export caused the third bone to be part of the geometry… maybe that’s it!

Wtf

No such luck.  The exported g3dj file looks just like any dozen of others I have generated in the past.

 

This is unbelievably frustrating at this point, as a problem I have been trying furiously to work around simply seems to no longer exist.  At this point I simply have NO idea what I was doing in the past that caused the entire process to break.  And that doesn’t leave me with a warm fuzzy feeling.

 

Getting content out of Blender has never been the funnest process, but this last week has been an exercise in frustration… and at the end of the day, the source of the frustration seems to no longer exist.

 

There are a few differences between this example and some of my prior ones.  Generally I load two different Models from disk ( instead of building one using ModelBuilder ), so perhaps once I add another model to the mix I will start seeing the old behaviour ( although that really wouldn’t make much sense ).  Also, I am using a different computer than I normally use ( on my Mac today ), but it is the same version level of Blender and LibGDX, so that shouldn’t be a factor either.

 

At this point, I just don’t know what to say… maybe the fates simply hated me last week… that would explain the infernal cold they inflicted upon me!

Programming


Scroll to Top