LibGDX 3d Getting Null Pointer Exception in ModelInstance - java

I have tried the below code but I am getting NullPointerException in the below highlighted line.
Class Name: Terrain
Getting Exception in the below line
modelInstance = new ModelInstance(modelBuilder.end(),0,0,0);
Please find the code below
Code:
private PerspectiveCamera camera;
private ModelBatch modelBatch;
private ModelBuilder modelBuilder;
private Model box;
private ModelInstance modelInstance;
private Environment environment;
#Override
public void create () {
camera = new PerspectiveCamera(75,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
camera.position.set(0f, 0f, 3f);
camera.lookAt(0f,0f,0f);
camera.near =0.1f;
camera.far = 300f;
modelBatch = new ModelBatch();
modelBuilder = new ModelBuilder();
modelBuilder.begin();
MeshPartBuilder part=modelBuilder.part("Box1", GL20.GL_TRIANGLES, Usage.Position, null);
part.rect(new Vector3(0,0,0),new Vector3(100,0,0),new Vector3(100,100,0),new Vector3(0,100,0),new Vector3(0,0,0));
modelInstance = new ModelInstance(modelBuilder.end(),0,0,0);
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight,0.8f,0.8f,0.8f,1f));
Gdx.input.setInputProcessor(this);
}
#Override
public void render () {
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.end();
}
#Override
public boolean keyDown(int keycode) {
// In the real world, do not create NEW variables over and over, create
// a temporary static member instead
if(keycode == Input.Keys.LEFT)
camera.rotateAround(new Vector3(0f, 0f, 0f), new Vector3(0f, 1f, 0f), 1f);
if(keycode == Input.Keys.RIGHT)
camera.rotateAround(new Vector3(0f,0f,0f),new Vector3(0f,1f,0f), -1f);
return true;
}
I am getting the below error when I try to execute the above code.
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.badlogic.gdx.graphics.g3d.ModelInstance.invalidate(ModelInstance.java:269)
at com.badlogic.gdx.graphics.g3d.ModelInstance.invalidate(ModelInstance.java:283)
at com.badlogic.gdx.graphics.g3d.ModelInstance.copyNodes(ModelInstance.java:226)
at com.badlogic.gdx.graphics.g3d.ModelInstance.(ModelInstance.java:154)
at com.badlogic.gdx.graphics.g3d.ModelInstance.(ModelInstance.java:146)
at com.badlogic.gdx.graphics.g3d.ModelInstance.(ModelInstance.java:62)
at com.badlogic.gdx.graphics.g3d.ModelInstance.(ModelInstance.java:188)
at com.mygdx.game.desktop.Terrain.create(Terrain.java:63)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:147)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)
Can someone please provide a solution to make the code work.

Related

Rendered 3d object using libgdx does not have colors as used to create using blender

I have created a 3d object using a blender. and I exported it as a g3db and gsdj types and used with libgdx. everything works fine but the colors of the object are not rendering as expected.
I tried using various ways to create an object and exporting with a blender. and In the past, I’ve tried libgdx-fbx-conv to convert fbx to g3db. and its also not working.
public class experiments extends ApplicationAdapter {
private ModelBatch modelBatch;
private Environment environment;
private PerspectiveCamera cam;
private Model model;
private ModelInstance instance;
private CameraInputController camController;
#Override
public void create() {
modelBatch = new ModelBatch();
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
float color = 0.0001f;
environment.add(new DirectionalLight().set(color, color, color, -1f, -0.8f, -0.2f));
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(3f, 3f, 3f);
cam.lookAt(0, 0, 0);
cam.near = 1f;
cam.far = 300f;
cam.update();
G3dModelLoader loader = new G3dModelLoader(new UBJsonReader());
model = loader.loadModel(Gdx.files.internal("test.g3db"));
instance = new ModelInstance(model);
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
}
#Override
public void render() {
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
modelBatch.render(instance, environment);
modelBatch.end();
}
#Override
public void dispose() {
}
}
this is what blender shows
https://drive.google.com/open?id=1WAjrP_Z4IVjohk-CZSFeLk5st8PNOQGz
and this is what I have
https://drive.google.com/open?id=1AbRGLathCuESesTpcTFvKue49V1k533Z
That has most likely just something to do with the way it is being rendered. Blender renders it with either Cycles or Eevee (with Belender 2.8), while LibGDX uses OpenGl. It's like you make a photograph of the same object with two different cameras.

LibGDX application crash: "batch cannot be null"

i'm creating a 2D platform game with Android Studio and LibGDX.
Right now, I'm implementing an on-screen controller to move the character, but when I start the launcher, it closes automatically.
When I run the launcher, this is what the console shows:
Exception in thread "LWJGL Application" java.lang.IllegalArgumentException: batch cannot be null.
at com.badlogic.gdx.scenes.scene2d.Stage.<init>(Stage.java:108)
at com.globapps.supermarioclon.Tools.Controles.<init>(Controles.java:30)
at com.globapps.supermarioclon.Screens.PantallaJuego.<init>(PantallaJuego.java:57)
at com.globapps.supermarioclon.MarioBros.create(MarioBros.java:34)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:147)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)
This is the code from the controller class:
public class Controles {
Viewport viewport;
Stage stage;
boolean salto, izquierda, derecha;
OrthographicCamera cam;
public Controles() {
cam = new OrthographicCamera();
viewport = new FitViewport(800, 480, cam);
stage = new Stage(viewport, PantallaJuego.batch);
Gdx.input.setInputProcessor(stage);
Table table1 = new Table();
Table table2 = new Table();
table1.left().bottom();
table2.right().bottom();
Image flechaizquierda = new Image(new Texture("flechaIzquierda.png"));
flechaizquierda.setSize(50, 50);
flechaizquierda.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
izquierda = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
izquierda = false;
}
});
final Image flechaderecha = new Image(new Texture("flechaDerecha.png"));
flechaderecha.setSize(50, 50);
flechaderecha.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
derecha = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
derecha = false;
}
});
Image flechasalto = new Image(new Texture("flechaIzquierda.png"));
flechasalto.setSize(50, 50);
flechasalto.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
salto = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
}
});
table1.add();
table1.add(flechaizquierda).size(flechaizquierda.getWidth(), flechaizquierda.getHeight());
table1.add();
table1.row().pad(0, 5, 0, 5);
table1.add();
table1.add(flechaderecha).size(flechaderecha.getWidth(), flechaderecha.getHeight());
table2.add();
table2.add(flechasalto).size(flechasalto.getWidth(), flechasalto.getHeight());
table2.row().padRight(5);
table2.add();
stage.addActor(table1);
stage.addActor(table2);
}
public void draw() {
stage.draw();
}
public boolean isDerecha() {
return derecha;
}
public boolean isIzquierda() {
return izquierda;
}
public boolean isSalto() {
return salto;
}
public void resize(int ancho, int alto) {
viewport.update(ancho, alto);
}
}
And this is the PlayScreen class:
public class PantallaJuego extends ApplicationAdapter implements Screen {
private MarioBros game;
public static SpriteBatch batch;
private TextureAtlas atlas;
private OrthographicCamera gamecam, cam;
private Viewport gamePort, viewport;
private HUD hud;
private TmxMapLoader maploader;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
private World world;
private Box2DDebugRenderer b2dr;
Controles controles;
private Mario player;
private Music musica;
public PantallaJuego(MarioBros game) {
atlas = new TextureAtlas("MarioyEnemigos.pack");
this.game = game;
gamecam = new OrthographicCamera();
gamePort = new FitViewport(MarioBros.V_WIDTH / MarioBros.PPM, MarioBros.V_HEIGHT / MarioBros.PPM, gamecam);
hud = new HUD(game.batch);
controles = new Controles();
batch = new SpriteBatch();
maploader = new TmxMapLoader();
map = maploader.load("nivel1mario.tmx");
renderer = new OrthogonalTiledMapRenderer(map, 1/MarioBros.PPM);
gamecam.position.set(gamePort.getWorldWidth()/2, gamePort.getWorldHeight()/2, 0);
world = new World(new Vector2(0,-10), true);
b2dr = new Box2DDebugRenderer();
player = new Mario(world, this);
new B2WorldCreator(world, map);
world.setContactListener(new WorldContactListener());
musica = MarioBros.manager.get("Audio/Música/Super Mario World - Overworld Theme Music (FULL VERSION).mp3", Music.class);
musica.setLooping(true);
musica.play();
}
public TextureAtlas getAtlas() {
return atlas;
}
#Override
public void show() {
}
public void handleInput(float dt) {
if(controles.isDerecha())
player.b2body.applyLinearImpulse(new Vector2(0.1f, 0), player.b2body.getWorldCenter(), true);
if(controles.isSalto())
MarioBros.manager.get("Audio/Sonidos/Super Mario Bros- Mario Jump Sound Effect.mp3", Sound.class).play();
player.b2body.applyLinearImpulse(new Vector2(0, 4f), player.b2body.getWorldCenter(), true);
if(controles.isIzquierda())
player.b2body.applyLinearImpulse(new Vector2(-0.1f, 0), player.b2body.getWorldCenter(), true);
}
public void update(float dt) {
handleInput(dt);
world.step(1 / 60f, 6, 2);
gamecam.position.x = player.b2body.getPosition().x;
cam.position.set(viewport.getWorldWidth() / 2, viewport.getWorldHeight() / 2, 0);
player.update(dt);
hud.update(dt);
if(Gdx.app.getType() == Application.ApplicationType.Android)
controles.draw();
gamecam.update();
cam.update();
renderer.setView(gamecam);
}
#Override
public void render(float delta) {
update(delta);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
b2dr.render(world, cam.combined);
b2dr.render(world, gamecam.combined);
game.batch.setProjectionMatrix(gamecam.combined);
game.batch.begin();
player.draw(game.batch);
game.batch.end();
game.batch.setProjectionMatrix(hud.stage.getCamera().combined);
hud.stage.draw();
}
If someone could help me, I'd be very grateful. Thank you.
I think you should instantiate your batch in PantallaJueago class before instantiating controles field.
public PantallaJuego(MarioBros game) {
atlas = new TextureAtlas("MarioyEnemigos.pack");
this.game = game;
gamecam = new OrthographicCamera();
gamePort = new FitViewport(MarioBros.V_WIDTH / MarioBros.PPM, MarioBros.V_HEIGHT / MarioBros.PPM, gamecam);
hud = new HUD(game.batch);
batch = new SpriteBatch();
controles = new Controles();
Because it is null while you instantiating your "controles". You are getting this error for your line
stage = new Stage(viewport, PantallaJuego.batch);
PantallaJuego.batch is null.
Well you should learn some more of the basics before you continue. This is related to a a NullPointerException and is usually very easy to fix. It tells you that you are trying to access a method or variable in nothing since you did not initialize it. Let's take your stack and find whats wrong.
Exception in thread "LWJGL Application" java.lang.IllegalArgumentException: batch cannot be null.
//Great! So let's fix this.
at com.badlogic.gdx.scenes.scene2d.Stage.<init>(Stage.java:108)
//This is a LibGDX class so there is probably nothing wrong with this
at com.globapps.supermarioclon.Tools.Controles.<init>(Controles.java:30)
//This is your class so let's go to this specific line, you can double click it.
stage = new Stage(viewport, PantallaJuego.batch);
//So either viewport or batch is null in this line.
//You can put a breakpoint here and run a debug,
//your program will stop on this line and you can hover
//to see what is in the variables. You will see that batch
// is null. Why, you may ask.
In the constructor of your main class you first set new Controles()
controles = new Controles();
Now the constructor of Controles will run and comes to this line:
stage = new Stage(viewport, PantallaJuego.batch);
And since your code did not reach batch = new SpriteBatch(); in PantallaJuego batch is still null and since stage does not accept that it will throw a NullPointer. A quick fix is to turn around new SpriteBatch() and new Controles().
The reason I say you should start learning the basics first is because your code is very poorly formed. You should format your code in a neat way and use much smaller methods since right now certain methods and constructors do all kind of stuff and it is very hard to read. Apart from this you are picking up very bad habits like making a global from that SpriteBatch (public static). There is really no need for this and it is partly responsible for your failure here.
Have a look at What is a NullPointerException, and how do I fix it? although your error is not a NullPointerException it is very related. Stage() does a check of it's own for it to be null and throws another exception before it tries to access it and get a nullpointer then.

libGDX does foreach create an object?

Im learning by these tutourials g3d: https://xoppa.github.io/blog/using-materials-with-libgdx/
Now I have heard that the foreach loop creates an object and thats bad to use in the render method.
Example:
private PerspectiveCamera cam;
private CameraInputController camController;
private Shader shader;
private Model model;
private Array<ModelInstance> instances = new Array<ModelInstance>();
private ModelBatch modelBatch;
#Override
public void show() {
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(2f, 2f, 2f);
cam.lookAt(0, 0, 0);
cam.near = 1f;
cam.far = 300f;
cam.update();
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
ModelBuilder modelBuilder = new ModelBuilder();
model = modelBuilder.createSphere(2f, 2f, 2f, 20, 20,
new Material(),
VertexAttributes.Usage.Position |
VertexAttributes.Usage.Normal |
VertexAttributes.Usage.TextureCoordinates);
for (int x = -5; x <= 5; x+=2) {
for (int z = -5; z <= 5; z+=2) {
instances.add(new ModelInstance(model, x, 0, z));
}
}
shader = new TestShader();
shader.init();
modelBatch = new ModelBatch();
}
#Override
public void render(float delta) {
camController.update();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
for (ModelInstance instance : instances) {
modelBatch.render(instance, shader);
}
modelBatch.end();
}
Is this true does it create an Object?
What would be a solution?
No, it does not create an Object. The for-each loop is simply a syntactical shortcut. See Does the Java foreach loop create a new object?

Displaying 3D models with an OrthographicCamera in LibGDX

So basically I'm trying to display a .obj 3D Model with an OrthographicCamera in 2D rather than in 3D with a PerspectiveCamera.
Everything works fine when I render with the PerspectiveCamera, however if I switch it to Orthographic, nothing displays, just the blank background.
Below is the code I'm using with the PerspectiveCamera stuff commented out. I'm not sure if there is a different way that I need to setup the OrthographicCamera, or if I need to use a PerspectiveCamera with some modified to views to achieve this. At this point it really doesn't matter which axis I "eliminate".
Essentially what I want to achieve is being able to use Blender for my 2D animation. I've figured this out on the Blender side and it works very well, however they must be imported as .obj(or .fbx) into LibGDX, these are loaded into LibGDX as Models, and as such must be rendered with a ModelBatch using a ModelInstance and an Environment. I need a way to view this object using a 2D Orthographic projection rather than a 3D Perspective projection.
Anyone got any suggestions for this?
public class Test extends ApplicationAdapter {
//public PerspectiveCamera cam;
public OrthographicCamera cam;
public CameraInputController camController;
public ModelBatch modelBatch;
public ModelInstance ship;
public Environment environment;
#Override
public void create() {
modelBatch = new ModelBatch();
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
/*
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(10f, 10f, 10f);
cam.lookAt(0, 0, 0);
cam.near = 1f;
cam.far = 10f;
cam.update();
*/
cam = new OrthographicCamera();
cam.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.update();
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
ObjLoader loader = new ObjLoader();
Model model = loader.loadModel(Gdx.files.internal("data/invader.obj"));
ship = new ModelInstance(model);
}
#Override
public void render() {
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
modelBatch.render(ship, environment);
modelBatch.end();
}
#Override
public void dispose() {
modelBatch.dispose();
}
}

LIBGDX keeps printing "DefaultShaderProvider: Creating new shader" to terminal

I am creating a 3d game in libGDX. For some reason my game keeps printing
DefaultShaderProvider: Creating new shader
in the terminal. This is driving me absolutely insane because I can not debug my program with the terminal because of the spamming of that line. I checked my code for anything that would print this but I can not find anything that would.
Could anyone tell me why this is happening?
Here is my code:
public class puppetDemo implements ApplicationListener {
public PerspectiveCamera camera;
public ModelBatch modelBatch;
public ModelInstance box;
public ModelInstance sphere;
public Array<ModelInstance> instances = new Array<ModelInstance>();
public AssetManager assets;
public Lights lights;
public CameraInputController camController;
public boolean loading = true;
#Override
public void create() {
camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
camera.position.set(10f, 0f, -100f);
camera.lookAt(0, 0, 0);
camera.near = 0.1f;
camera.far = 300f;
camera.update();
lights = new Lights();
lights.ambientLight.set(0.4f, 0.4f, 0.4f, 1f);
lights.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f,
-0.2f));
assets = new AssetManager();
assets.load("data/box.obj", Model.class);
assets.load("data/sphere.obj", Model.class);
}
#Override
public void resize(int width, int height) {
}
#Override
public void render() {
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
modelBatch = new ModelBatch();
modelBatch.begin(camera);// Begin Rendering
modelBatch.render(instances, lights);
modelBatch.end();// End Rendering
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
modelBatch.dispose();
}
}
When you call new ModelBatch() in your render method, this is creating a new instance of the DefaultShaderProvider:
public ModelBatch() {
this(new RenderContext(new DefaultTextureBinder(DefaultTextureBinder.ROUNDROBIN, 1)),
new DefaultShaderProvider(),
new DefaultRenderableSorter());
}
Looking at the source for DefaultShaderProvider you'll notice logging output in the createShader method:
#Override
protected Shader createShader(final Renderable renderable) {
Gdx.app.log("DefaultShaderProvider", "Creating new shader");
// ...
}
Instantiate modelBatch in the create method instead of in render and I suspect you'll only see the output once. If not, it might be worth filing an issue to have logging statement removed as it seems unnecessary.

Categories

Resources