Loading Blender animation into libGDX - libgdx

Hi Blender & libGDX Gurus,
I am trying to load an blender animation into libGDX for an android app. So I created an animation using Blenders action editor, I exported this into .fbx format. I then ran the fbx-conv tool to create a .G3DB file. I then proceeded to upload this file into libGDX using the modelLoader.
Everything seems to work fine (I am not receiving any error messages) except that the screen is blank. I can't see any animations or the model.
I have run this code in a Samsung galaxy tablet running kitkat, nexus phone running marshmallow and an emulator, but the same result.
I went thru the tutorials and am using some of the code to upload one of my blender models. I still can't figure this out and I need help figuring this out.
Any help will be greatly appreciated.
Here is the link to the Blender file:
Animated Low-Poly Horse No Lights and no Camera
Here is my code where I am uploading the model in libGDX. I basically am using the code from the tutorials.
#Override
public void create () {
// Create camera sized to screens width/height with Field of View of 75 degrees
camera = new PerspectiveCamera(
75,
Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
// Move the camera 5 units back along the z-axis and look at the origin
camera.position.set(0f,0f,7f);
camera.lookAt(0f,0f,0f);
// Near and Far (plane) represent the minimum and maximum ranges of the camera in, um, units
camera.near = 0.1f;
camera.far = 300.0f;
camera.update();
// A ModelBatch to batch up geometry for OpenGL
modelBatch = new ModelBatch();
// Model loader needs a binary json reader to decode
UBJsonReader jsonReader = new UBJsonReader();
// Create a model loader passing in our json reader
G3dModelLoader modelLoader = new G3dModelLoader(jsonReader);
// Now load the model by name
// Note, the model (g3db file ) and textures need to be added to the assets folder of the Android proj
model = modelLoader.loadModel(Gdx.files.getFileHandle("AnimatedLowPolyHorseStageFenced_Ver5.g3db", Files.FileType.Internal));
// Now create an instance. Instance holds the positioning data, etc of an instance of your model
modelInstance = new ModelInstance(model);
//fbx-conv is supposed to perform this rotation for you... it doesnt seem to
modelInstance.transform.rotate(1, 0, 0, -90);
//move the model down a bit on the screen ( in a z-up world, down is -z ).
modelInstance.transform.translate(0, 0, -2);
// Finally we want some light, or we wont see our color. The environment gets passed in during
// the rendering process. Create one, then create an Ambient ( non-positioned, non-directional ) light.
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.8f, 0.8f, 0.8f, 1.0f));
environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
// You use an AnimationController to um, control animations. Each control is tied to the model instance
controller = new AnimationController(modelInstance);
// Pick the current animation by name
controller.setAnimation("Armature|ArmatureAction",1, new AnimationListener(){
#Override
public void onEnd(AnimationDesc animation) {
// this will be called when the current animation is done.
// queue up another animation called "balloon".
// Passing a negative to loop count loops forever. 1f for speed is normal speed.
//controller.queue("Armature|ArmatureAction",-1,1f,null,0f);
}
#Override
public void onLoop(AnimationDesc animation) {
// TODO Auto-generated method stub
}
});
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#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(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
// For some flavor, lets spin our camera around the Y axis by 1 degree each time render is called
// You need to call update on the animation controller so it will advance the animation. Pass in frame delta
controller.update(Gdx.graphics.getDeltaTime());
// Like spriteBatch, just with models! pass in the box Instance and the environment
modelBatch.begin(camera);
modelBatch.render(modelInstance, environment);
modelBatch.end();
}

When converting to G3DB with fbxconv you got a warning,
"Mesh contains vertices with zero bone weights".
Try the following steps:
- Add a a new bone to your blend
- Connect it to non-animated (or all) vertices
- Re-export & convert
If you still get the warning, repeat but connect the new bone to all vertices.
I know this is an old question, but i had a similar problem recently and this worked.

Related

Need help to optimize texture drawing on LibGDX, SpriteBatch

I'm converting my game Hold & Drag from Swift (SpriteKit) to Android using LibGDX, I created my 'SpriteKit' api a little clone of the official on Xcode.
I'm looking for optimizing the render of textures especially because I got FPS drop (45-60 /60 fps)
When I don't draw textures I got 60 (the maximum).
I hope you will help me as efficiently as possible!
#Override
public void draw() {
if (texture == null)
return;
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
spriteBatch.setTransformMatrix(getTransformMatrix());
spriteBatch.begin();
Color color = spriteBatch.getColor();
color.a = getAlpha();
spriteBatch.setColor(color);
spriteBatch.draw(texture, -size.width / 2, -size.height / 2, size.width, size.height);
spriteBatch.end();
Gdx.gl.glDisable(GL20.GL_BLEND);
}
public List<SKNode> getParents() {
List<SKNode> parents = new ArrayList<>();
if (parent != null) {
parents.add(parent);
parents.addAll(parent.getParents());
}
return parents;
}
public Matrix4 getTransformMatrix() {
List<SKNode> nodes = getParents();
Collections.reverse(nodes);
nodes.add(this);
Matrix4 transformMatrix = new Matrix4();
transformMatrix.idt();
for (SKNode node : nodes) {
transformMatrix.translate(node.position.x + node.origin.x, node.position.y + node.origin.y, 0);
transformMatrix.rotate(0, 0, 1, node.zRotation);
transformMatrix.scale(node.xScale, node.yScale, 0);
transformMatrix.translate(-node.origin.x, -node.origin.y, 0);
}
return transformMatrix;
}
It is slow to do things that cause the sprite batch to "flush", which means it has to issue a number of OpenGL commands and transfer vertex data, etc. A flush occurs when you call spriteBatch.end() but also occurs if you:
Draw something with a different texture instance than the last thing drawn
Change the projection or transform matrices
Enable/disable blending
So you want to organize so you are not triggering a flush on every object you draw. What is typically done is to begin the batch, and then each sprite is drawn at its particular location with one of the spriteBatch.draw() methods that includes all the parameters you want. Like this:
batch.setProjectionMatrix(camera.combined);
batch.begin();
for (GameObject obj : myGameObjects)
obj.draw();
batch.end();
//And in your game object / sprite class
public void draw() {
if (texture == null)
return;
spriteBatch.setColor(1f, 1f, 1f, getAlpha());
spriteBatch.draw(texture, -size.width / 2, -size.height / 2, size.width, size.height);
}
Note that the above assumes you are referring to the same sprite batch instance in every object.
Now, to make it behave more like SpriteKit (I'm assuming since I haven't used it), your objects each need a transform. But you don't want to be calling setTransformMatrix or you will trigger a flush. Instead you can use the Affine2 class instead of Matrix4. It functions just as well for holding transform data for a 2D object. Then you can use spriteBatch.draw(textureRegion, width, height, affine2Transform) to draw it without triggering a flush.
To avoid triggering flushes from using different texture instances, you should use a TextureAtlas and texture regions. You can read up on that in the LibGDX documentation on their wiki.
As an aside, when using SpriteBatch, you do not need to make OpenGL calls to enable and disable blending. That is handled internally by SpriteBatch. Call spriteBatch.enableBlending() instead.

Messy diagram derives when it comes to printing it on pdf by using MS Windows 10 service

I've been writing Java SE 8 desktop application. I use Eclipse IDE, Oracle's JDK, and run it on MS Windows 10 OS.
My app draws diagrams, in short. I draw a diagram on JPanel which becomes part of JTabbedPane. It displays it well on GUI, and it is very responsive. The problem shows up when I pass the diagram on printing service. But instead of printing it on printer, I choose, "Microsoft print to PDF" service. What happens next, is that if the diagram is large, when you scroll it down, you will observe that its quality drops down. That is, grids start disappearing, new lines appear, etc.
The pic out here.
As you can see, eventually vertical grids vanish, diagonal line creeps in, and later gets even worse. And that is unwelcome.
Relevant code in here:
public final class GanttChartDiagram extends TopDiagram{
#Override
public void paintComponent(Graphics graph){
super.paintComponent(graph);
Graphics2D g2D = (Graphics2D)graph;
g2D.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
...........
#Override
public Dimension getPreferredSize(){
return new Dimension(this.diagramWidth + 20, this.diagramHeight + 20);
}
}
}
The getPreferredSize() method identifies the size of diagram, so that the app knows how to adjust the scroll-bars accordingly to fit the diagram in. Otherwise by default it return 0, if not overridden.
That is the class where I draw the diagram.
The super-class out here:
public abstract class TopDiagram extends JPanel implements Printable {
private static final long serialVersionUID = 1469816888488484L;
#Override
public void paintComponent(Graphics graph){
super.paintComponent(graph);
};
/**
* Prints selected diagram
*/
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
Graphics2D dimension = (Graphics2D)graphics;
dimension.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
if(pageIndex < PrintingImageBuffer.getImageBuffer().size()){
dimension.drawImage(PrintingImageBuffer.getImageBuffer().get(pageIndex), null, 0, 0);
return PAGE_EXISTS;
}
else{
return NO_SUCH_PAGE;
}
}
}
Now that is where I print the diagram:
public static void printDiagram(){
new Thread(new Runnable(){
public void run(){
TopDiagram diagram = null;
if(id.equalsIgnoreCase("GanttChart")){
diagram = ganttChartDiagram;
}
final PrinterJob printer = PrinterJob.getPrinte
rJob();
printer.setJobName("Printing the "+id+" Diagram");
PageFormat format = printer.pageDialog(page);
int nowWidth = (int)diagram.getPreferredSize().getWidth();
int nowHeight = (int)diagram.getPreferredSize().getHeight();
BufferedImage buffImg = new BufferedImage(nowWidth, nowHeight, BufferedImage.TYPE_INT_ARGB);//default type
Graphics2D d = (Graphics2D)buffImg.getGraphics();
....etc..................
}
}).start();
}
Now the interesting part is this:
int nowWidth = (int)diagram.getPreferredSize().getWidth();
int nowHeight = (int)diagram.getPreferredSize().getHeight();
On the same instance of diagram, on multiple invocations of print (or within the method), it may or may not return different values. So that it was causing me some sort of Raster exception. But I managed to get rid off of that exception by invoking size method only once and reusing that size value throughout the method. So that, the size value stays the same, cause it is read only once.
Bad solution, but it works.
I would like to solve this issue too. Firstly, how come that this invocation diagram.getPreferredSize().getWidth() on the same instance of diagram obj. returns different size value? One more thing, is that I overrode this method as has been presented above. And the diagram object is created only once, no recalculations.
This is where I create the diagram obj. on Swing Worker only once per application's life-cycle.
GanttChartSwingWorker ganttSwingWorker = new GanttChartSwingWorker(GanttChartDiagram::new, tabbedPane, showPerformanceDiagramTab, ganttChartDiagramTabReady);
ganttSwingWorker.execute();
new Thread(() -> {
try{
ganttChartDiagramTabReady.await();
ganttChartDiagram = ganttSwingWorker.getGanttChartDiagram();
}catch(InterruptedException ie){ie.printStackTrace();}
}
).start();
Swing Worker part:
diagram = this.get();
JScrollPane scrollPaneChart = addScrollPane(diagram);
tabbedPane.addTab("Gantt Chart", null, scrollPaneChart, "Displays Gantt Chart Diagram");
Some diagram objects can be time consuming to create, imposes delay, so I use Swing Worker to do that.
So, in summary:
How to make the diagram to appear clean when I print/save it on pdf file in the way that I explained?
How to make the diagram size to calculate consistently as per multiple invocations? What leads to different diagram size values retrieving it from the same diagram object instance on multiple calls?
I just figured out what the problem is.
I observed that when it comes to drawing the diagram, the
paintComponent(Graphics g) method has been invoked repeatedly. It keeps redrawing the diagram over and over again. It is invoked by the system implicitly, yet my implementation had been triggering it.
And that trigger comes in the form of this.setSize(width, height) method on derived JPanel object. So that each time the paintComponent(Graphics g) re-executes, it sets the size on JPanel which yet triggers additional execution of the painComponent method. In the end, it is an infinite loop.
And that infinite execution was the cause of the problem; it was producing distorted diagram image on pdf file.
Solution: execute the setSize method only when it is needed; on initial panel set-up, or resize.

spotlight not working in libGDX

I was playing around with spotLight in libGDX. I used this code to project the light source in -y direction. To my surpise, my floorModel was completely black. I went to docs and found this interesting fact:
Note that the default shader doesn't support spot lights, you'll have to supply your own shader to use this class.
I think this may be the reason the what spotlight isn't working. I have however found 0 examples of setting up spot light properly. Could you provide a simple example on setting up spot light properly?
EDIT for those who read the first question: after exporting custom object for a second time, the light interaction was working as exptected-meaning the object was not visible when only spotlight was used. Not sure why.
public void show() {
float factor=3f;
camera = new PerspectiveCamera(45, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
camera.position.set(1.4f * factor, 6f, -1f * factor);
camera.lookAt(0f,0f,0f);
camera.near =0.1f;
camera.far = 300f;
modelBatch = new ModelBatch();
modelBuilder=new ModelBuilder();
UBJsonReader jsonReader = new UBJsonReader();
G3dModelLoader modelLoader = new G3dModelLoader(jsonReader);
model = modelLoader.loadModel(Gdx.files.getFileHandle("convertedModel3.g3db", Files.FileType.Internal));
floorModel = modelBuilder.createBox(30,1,30,new Material(ColorAttribute.createDiffuse(Color.BLUE)), VertexAttributes.Usage.Position|VertexAttributes.Usage.Normal);
modelInstance = new ModelInstance(model);
floorInstance=new ModelInstance(floorModel);
Array<Material> materials=modelInstance.materials;
materials.get(0).set(ColorAttribute.createDiffuse(Color.WHITE));
materials.get(0).set(ColorAttribute.createReflection(Color.WHITE));
float intensity = 0.1f;
environment = new Environment();
Vector3 pos = new Vector3(0,10,0);
Vector3 dir = new Vector3(0,-10,0);
environment.add(new SpotLight().set(Color.WHITE,pos,dir,1f,100,1));
}
#Override
public void render(float delta) {
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
camera.update();
modelBatch.begin(camera);
modelBatch.render(modelInstance, environment);
modelBatch.render(floorInstance,environment);
modelBatch.end();}
As the documentation says, currently spotlight is not supported by the default shader. This is because good generic spotlight requires per fragment lighting and the default shader uses per vertex lighting. Therefor you wont find a simple example on that. You could wait for this pull request to be included. You could use that as an example (although it's probably an overkill for your usage and surely not simple). Or you could provide your own shader that includes spot lighting.
Here's a basic tutorial on how to create a shader. This wiki page contains more information about how to customize the shader. The actual shader implementation is not really libGDX specific (except for the uniform names), you can use any algorithm you like that is compatible with your target device.
Here you can find an example on how to adjust the default (per vertex lighting) shader to somewhat support spotlight (the quality depends on your models). Note that the modification to the DefaultShader class are already included, you'd only have to focus on the actual shader (GLSL) programs in that case.

LibGDX Android Game - displaying fixed text (ie Score) over a scrolling screen

I am beginning to write a game in LibGDX, only just beginning. I have got a basic tile map loaded, a player sprite and can move the character around and the screen (camera) scrolls around - perfect.
I have two overlayed textures in the bottom right of the screen, a left and right arrow, which are used as the joypad to control the character. I position these in relation to the players.x position, which is always fixed to the centre of the screen. Cool so far .... As below:
/////////////////////////////////////////////////////////////////
private void renderJoypad(float deltaTime)
{
batch.draw(Assets.leftJoypad, blockman.position.x-14, 1, 3, 3);
batch.draw(Assets.rightJoypad, blockman.position.x-9, 1, 3, 3);
}
I am now trying to put the player's score in the top left of the screen. The score is made of a Bitmap font, as below.
font = new BitmapFont(Gdx.files.internal("fonts/minecrafter.fnt"),Gdx.files.internal("fonts/minecrafter.png"),false);
font.setScale(0.02f);
In my render() method I cam calling some other methods to update, like the positions of the
leftJoypad etc, as in renderJoypad(). I am also calling my draw font method to update the position of the score, however, when I scroll it is all jerky, and sometimes it shows less characters than there should be.
public void drawScore(float deltaTime)
{
font.draw(batch, "00000", blockman.position.x, 10);
}
I believe that I need to place the score (and any other on screen texts, HUD etc) into a stage, but I cannot understand how to get it working with my existing code.
My show method is as follows:
public void show()
{
//load assets class to get images etc
Assets Assets = new Assets();
//start logging Framerate
Gdx.app.log( GameScreen.LOG, "Creating game" );
fpsLogger = new FPSLogger();
//set the stage - bazinga
Gdx.input.setInputProcessor(stage);
//stage.setCamera(camera);
//stage.setViewport(480, 360, false);
batch = new SpriteBatch();
//load the Joypad buttons
loadJoypad();
//background image
loadBackground();
//sounds
jumpSound = Gdx.audio.newSound(Gdx.files.internal("sounds/slime_jump.mp3"));
//LOAD block man here
// load the map, set the unit scale to 1/16 (1 unit == 16 pixels)
loadMap();
//draw the score
font = new BitmapFont(Gdx.files.internal("fonts/minecrafter.fnt"),Gdx.files.internal("fonts/minecrafter.png"),false);
font.setScale(0.02f);
// create an orthographic camera, shows us 30x20 units of the world
camera = new OrthographicCamera();
camera.setToOrtho(false, 30, 20);
camera.update();
// create the Blockman we want to move around the world
blockman = new Blockman();
blockman.position.set(25, 8);
}
and my render() method is as follows:
public void render(float delta)
{
// get the delta time
float deltaTime = Gdx.graphics.getDeltaTime();
stage.act(deltaTime);
stage.draw();
// clear the screen
Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderBackground(deltaTime);
batch = renderer.getSpriteBatch();
//updateBlockman(deltaTime);
blockman.update(deltaTime);
// let the camera follow the blockMan, x-axis only
camera.position.x = blockman.position.x;
camera.update();
// set the tile map rendere view based on what the
// camera sees and render the map
renderer.setView(camera);
renderer.render();
//start the main sprite batch
batch.begin();
// render the blockMan
renderBlockman(deltaTime);
renderJoypad(deltaTime);
drawScore(deltaTime);
batch.end();
fpsLogger.log();
}
I have tried to change the way things work with relation to the Spritebatch etc and just cannot seem to get it working as I require.
Can anyone suggest how I may approach getting a stage and actors to work, or a second camera or something to help me achieve a fixed score display in the corner.
Do I need to use Scene 2D or something - aahhh! My head is exploding....
I look forward and thank you in advance.
Regards
James
I have a couple of suggestions:
Check to see if you have setUseIntegerPositions set to true
(the default) when you draw your font. If you do, and you're scaling
it, then it can cause some odd effects similar to those that you
describe. Set it to false and see if it fixes the problem.
Reset your spritebatch's matrices before drawing the text, that way you won't need to adjust it for the scrolling.
I'd even go as far as to recommend not scaling the font if you can help it, because fonts often look a little odd after being scaled.

How to set Video Frame Capture Using Bitmap Data

I'm implementing an Augmented Reality application for android using Flash. In order to get the application working on my Android Phone (nexus One) the Phone Camera must be activated as well. So I need 2 layers one for the background which is the feed of my phone camera and an other one on top of it which is the view from away3d in this case.
So setting up a BitmapData object to hold the information of the most recent webcam still-frame I can make this work.
If I use papervision3D library and FLARToolkit we setting up the BitmapData using the following part of the code found from this video tutorial:
//import libraries
import org.libspark.flartoolkit.core.raster.rgb.FLARRgbRaster_BitmapData;
import org.libspark.flartoolkit.detector.FLARSingleMarkerDetector;
private function setupCamera():void
{
vid = new Video(640, 480);
cam = Camera.getCamera();
cam.setMode(320, 240, 10);
vid.attachCamera(cam);
addChild(vid);
}
private function setupBitmap():void
{
bmd = new BitmapData(640, 480);
bmd.draw(vid);
raster = new FLARRgbRaster_BitmapData(bmd);
detector = new FLARSingleMarkerDetector(fparams, mpattern, 80);
}
private function loop(e:Event):void
{
if(detector.detectMarkerLite(raster, 80) && detector.getConfidence() > 0.5)
{
vp.visible = true;
detector.getTransformMatrix(trans);
container.setTransformMatrix(trans);
bre.renderScene(scene, camera, vp);
}
else{
vp.visible = false}
}
catch(e:Error){}}}}
However, to implement my application Im using Away3D engine and FLARManager and the way of doing that is very different as I can understand. I have implement the following code but the only think it does is just show the Flash Camera in the front of the 3D view and I can't check if my application is work or not since it doesn't show me any 3D Object when I place the marker in front of the screen.
My code is:
//Setting Up Away3DLite Camera3D
import com.transmote.flar.camera.FLARCamera_Away3DLite;
private var camera3D:FLARCamera_Away3DLite;
this.camera3D = new FLARCamera_Away3DLite(this.flarManager, new Rectangle(0, 0, this.stage.stageWidth, this.stage.stageHeight));
//Setting Up the bitmapData
private function bitmap():void
{
c = Camera.getCamera();
c.setMode(320,240,10)
this.v.attachCamera(c);
addChild(this.v);
bmd = new BitmapData(640,480);
bmd.draw(this.v);
}
Can you please help me to find out how can I combine those two?
I will really appreciate any advice i can get from you.
Thank you
To isolate your problem, I'd try to break these two things up and make sure each part works first. It's sounds like you've got the camera part working, try doing just some 3D (no AR) draw a cube or something. Then try implementing the AR but have it do something simple like trace something out or making an object visible or invisible. Then start combining them.