I have tried to load a model and display it in my window for about 2 hours, but now i surrender. I tried about 10 different models that i downloaded from https://sketchfab.com, but none is displayed, i just get a black window. I searched for help in the web another 20 minutes now but as i am not very experienced in libgdx, i cant adapt the "solutions" i found to my programm. I hope you can help me!
Another question i have is, that if there was any way to use models with more indexes than the short value.
model i used: https://sketchfab.com/models/042201dac61041fabb88f483368daa3f
my code:
public class Game extends ApplicationAdapter
{
private PerspectiveCamera cam;
private CameraInputController camController;
private ModelBatch modelBatch;
private AssetManager assets;
private Array<ModelInstance> instances = new Array<ModelInstance>();
private Environment environment;
private boolean loading;
#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 PointLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f, 1f));
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(1f, 1f, 1f);
cam.lookAt(0,0,0);
cam.near = 0.1f;
cam.far = 300f;
cam.update();
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
assets = new AssetManager();
assets.load("basic.g3db", Model.class);
loading = true;
}
private void doneLoading() {
Model ship = assets.get("basic.g3db", Model.class);
ModelInstance shipInstance = new ModelInstance(ship);
instances.add(shipInstance);
loading = false;
}
#Override
public void render () {
if (loading && assets.update())
doneLoading();
camController.update();
Gdx.gl20.glViewport(0, 0, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
modelBatch.render(instances, environment);
modelBatch.end();
}
#Override
public void dispose () {
modelBatch.dispose();
instances.clear();
assets.dispose();
}
public void resume () {
}
public void resize (int width, int height) {
}
public void pause () {
}
}
Related
I'm new in Libgdx and I'm developing 3d game in libgdx, so I want to create first person system, I created a class -playercontroller- to move the player and then make the camera move with player and it work
But I want the player to move in the camera direction, so when I rotate the camera , the player walk in the new direction.
This my code:-
#Override
public void create() {
// load enviroment
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));
// setup camera
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(10f, 10f, 10f);
cam.lookAt(0, 0, 0);
cam.near = 0.001f;
cam.far = 3000f;
cam.update();
// setup controller for camera
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
// load the models
assets = new AssetManager();
assets.load("ground_stairs.g3db", Model.class);
assets.load("gathering_node.g3db", Model.class);
loading = true;
modelBatch = new ModelBatch();
// setup bulletphysics
Bullet.init();
collisionConfig = new btDefaultCollisionConfiguration();
dispatcher = new btCollisionDispatcher(collisionConfig);
broadphase = new btDbvtBroadphase();
constraintSolver = new btSequentialImpulseConstraintSolver();
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, constraintSolver, collisionConfig);
dynamicsWorld.setGravity(new Vector3(0, -10f, 0));
contactListener = new MyContactListener();
loadPlayer();
}
private void loadPlayer() {
// setup player/camera movement
pc = new PlayerController(instances,cam,dynamicsWorld);
}
private void doneLoading() {
loading = false;
onDoneLoadingStatic("ground_stairs.g3db", GROUND);
onDoneLoadingStatic("gathering_node.g3db", GATHERING_NODE);
gatheringNode = instances.get(instances.size() - 1);
}
public btRigidBody onDoneLoadingStatic(String fileName, int id) {
Model model = assets.get(fileName, Model.class);
ModelInstance instance = new ModelInstance(model);
instances.add(instance);
btBvhTriangleMeshShape shape = new btBvhTriangleMeshShape(instance.model.meshParts);
btRigidBody body = new btRigidBody(0, null, shape, new Vector3(0, 0, 0));
body.proceedToTransform(instance.transform);
// set id to find with collision detection
body.setUserValue(id);
dynamicsWorld.addRigidBody(body);
return body;
}
#Override
public void render() {
if (loading && assets.update()) {
doneLoading();
}
camController.update();
pc.update();
final float delta = Math.min(1f / 30f, Gdx.graphics.getDeltaTime());
dynamicsWorld.stepSimulation(delta, 5, 1f / 60f);
Gdx.gl20.glClearColor(0, 0.5f, 1, 1);
Gdx.gl20.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
modelBatch.render(instances, environment);
modelBatch.end();
}
#Override
public void dispose() {
modelBatch.dispose();
}
private class MyContactListener extends ContactListener {
#Override
public void onContactStarted(int userValue0, int userValue1) {
if (userValue0 == PLAYER && userValue1 == GATHERING_NODE) {
((ColorAttribute) gatheringNode.materials.first().get(ColorAttribute.Diffuse)).color.set(Color.RED);
}
if (userValue0 == PLAYER && userValue1 == GROUND) {
PlayerController.canJump = true;
}
}
#Override
public void onContactEnded(int userValue0, int userValue1) {
if (userValue0 == PLAYER && userValue1 == GATHERING_NODE) {
((ColorAttribute) gatheringNode.materials.first().get(ColorAttribute.Diffuse)).color.set(Color.BLUE);
}
}
}
}
PlayerController
public PlayerController(List<ModelInstance> instances,PerspectiveCamera cam,btDynamicsWorld dynamicWorld) {
this.instances = instances;
this.cam = cam;
this.dynamicsWorld = dynamicWorld;
player = new ModelInstance(new ModelBuilder()
.createCapsule(0.25f, 3, 10, new Material(ColorAttribute.createAmbient(Color.BLACK)), Usage.Normal | Usage.Position)
);
player.transform.translate(5, 7, 0);
instances.add(player);
// load player rigid body
btCapsuleShape playerShape = new btCapsuleShape(0.25f, 2.5f);
float mass = 10;
Vector3 localInertia = new Vector3();
playerShape.calculateLocalInertia(mass, localInertia);
playerBody = new btRigidBody(mass, null, playerShape, localInertia);
playerBody.proceedToTransform(player.transform);
playerBody.setCollisionFlags(playerBody.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
// set id to find with collision detection
playerBody.setUserValue(PLAYER);
dynamicsWorld.addRigidBody(playerBody);
}
public void update() {
// make sure to activate the player body so bullet doesnt put it to sleep
playerBody.activate();
// prevent the capsule from falling over
playerBody.setAngularFactor(new Vector3(0, 0, 0));
playerBody.getWorldTransform(player.transform);
Vector3 velocity = new Vector3(0, playerBody.getLinearVelocity().y, 0);
velocity.x = xposition;
velocity.z = yposition;
cam.position.set(player.transform.getTranslation(new Vector3()));
cam.position.y=5;
cam.rotate(Vector3.Y,angleX);
cam.rotate(cam.direction.cpy().crs(Vector3.Y),-angleY);
playerBody.setLinearVelocity(velocity);
cam.update();
}
}
The code is work without problem and I can walk forward and backward, but when I rotate the the direction doesn't work, so how can I make it work?
public float posX, posY, posZ;
private float move = 0.02f;
public void moveForward(float moveSpeed) {
// normal speed moveForward(3.9);
//call moveForward(0); to stop moving
moveRCam(-moveSpeed, 0);
}
public void moveBackward(float moveSpeed) {
moveRCam(moveSpeed, 0);
}
private void moveRCam(float moveSpeed, float st) {
float speed = moveSpeed * move;
float strVel = st * move;
float angleY = (cam.rotation.y / 180 * 3.141592654f);
posX += speed*(Math.sin(angleY));
posZ -= speed*(Math.cos(angleY));
angleY += (3.141592654f/2);
posX -= strVel*(Math.sin(angleY));
posZ += strVel*(Math.cos(angleY));
cam.position.x = posX;
cam.position.y = posY;
cam.position.z = posZ;
}
I'had like to use a FrameBuffer and to set his size in world units instead of pixel.
When I set the FrameBuffer size in pixel, i have the expected result. But when I use another personal units. The result is messed up.
Here a snippet of the working code:
public class FBOTestLibGDX implements ApplicationListener {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.useGL30 = false;
cfg.width = 640;
cfg.height = 480;
cfg.resizable = false;
new LwjglApplication(new FBOTestLibGDX(), cfg);
}
Texture atlas;
FrameBuffer fbo;
TextureRegion fboRegion;
Matrix4 projection = new Matrix4();
SpriteBatch batch;
OrthographicCamera cam;
#Override
public void create() {
atlas = new Texture(Gdx.files.local("src/test/resources/fboData/testTexture.jpg"));
fbo = new FrameBuffer(Format.RGBA8888, atlas.getWidth(), atlas.getHeight(), false);
fboRegion = new TextureRegion(fbo.getColorBufferTexture(), atlas.getWidth(), atlas.getHeight());
fboRegion.flip(false, true); // FBO uses lower left, TextureRegion uses
projection.setToOrtho2D(0, 0, atlas.getWidth(), atlas.getHeight());
batch = new SpriteBatch();
batch.setProjectionMatrix(projection);
cam = new OrthographicCamera(5, 5);
cam.setToOrtho(false);
renderTextureInFBO();
}
protected void renderTextureInFBO() {
fbo.begin();
Gdx.gl.glClearColor(0f, 0f, 0f, 0f);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.setProjectionMatrix(projection);
batch.draw(atlas, 0, 0);
batch.end();
fbo.end();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 0f);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(cam.combined);
batch.begin();
batch.draw(fboRegion, 0, 0, 5, 5);
batch.end();
}
#Override
public void resize(int width, int height) {
cam.setToOrtho(false, 5, 5);
//batch.setProjectionMatrix(cam.combined);
}
#Override
public void pause() {}
#Override
public void resume() {}
#Override
public void dispose() {}
}
Using pixel I obtain this result:
But if I use world units for FrameBuffer like this:
public void create() {
...
fbo = new FrameBuffer(Format.RGBA8888, 5, 5, false);
fboRegion = new TextureRegion(fbo.getColorBufferTexture(), 5, 5);
fboRegion.flip(false, true);
projection.setToOrtho2D(0, 0, 5, 5);
...
}
protected void renderTextureInFBO() {
...
batch.draw(atlas, 0, 0,5,5);
...
}
I obtain a low scaled result:
The question is, it is possible to set the FrameBuffer size in world unit as we do for batch and viewport or it is mandatory to set it in pixel?
As specified in the documentation, a FrameBuffer size have to be defined in pixel. cf:
FrameBuffer specification
FrameBuffer
public FrameBuffer(Pixmap.Format format,
int width,
int height,
boolean hasDepth,
boolean hasStencil)
Creates a new FrameBuffer having the given dimensions and potentially a depth and a stencil buffer attached.
Parameters:
format - the format of the color buffer; according to the OpenGL ES 2.0 spec, only RGB565, RGBA4444 and RGB5_A1 are color-renderable
width - the width of the framebuffer in pixels
height - the height of the framebuffer in pixels
hasDepth - whether to attach a depth buffer
Throws
GdxRuntimeException - in case the FrameBuffer could not be created
I'm very new to programming so bear with me here...
I'm making a basic 2d android game. I am trying to simply make a sprite jump up in the air a bit and then land back to where it originally started. The sprite that I want to jump is "ball2". This is my code so far (Basically just added textures and the sprite in the correct position to start the jump but haven't done anything else).
Any help is appreciated.
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture background;
Texture ball;
Texture spike1;
Texture spike2;
#Override
public void create () {
batch = new SpriteBatch();
background = new Texture("gamebackground.png");
ball = new Texture("ball2.png");
ball.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
spike1 = new Texture("spike1.png");
spike1.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
spike2 = new Texture("spike2.png");
}
#Override
public void render () {
batch.begin();
float scaleFactor = 2.0f;
batch.draw(background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.draw(ball, 80, 145, ball.getWidth() * scaleFactor, ball.getHeight() * scaleFactor);
batch.end();
}
#Override
public void render () {
batch.begin();
float scaleFactor = 2.0f;
batch.draw(background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.draw(ball, 80, 145, ball.getWidth() * scaleFactor, ball.getHeight() * scaleFactor);
batch.end();
Gdx.input.setInputProcessor(new InputAdapter () {
#Override
public boolean keyDown (int keycode) {
if(keycode==Keys.UP)
{
ball.setHeight(ball.getHeight()+50);
}
return true;
}
}
}
Then you need to add the timer down down or you could add down button. Not sure if you have spikes on the top as well. I don't know what it's supposed to look like.
Can someone just give me a real quick answer on how i would implement a viewport so this sprite would fill the whole screen?
Thanks
Current code (not working):
public SplashScreen(Jump game)
{
this.game = game;
cam = new OrthographicCamera();
cam.setToOrtho(false, 1920, 1080);
sb = new SpriteBatch();
}
public void show()
{
}
public void render(float delta)
{
Gdx.gl20.glClearColor(0.2F, 0.6F, 1F, 1F);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
cam.update();
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(Assets.splash_spr_background, 0, 0);
sb.end();
}
On
#Override
public void resize(int width, int height) {
stage.getViewport().update(Gdx.graphics.getWidth(),
Gdx.graphics.getHeight(), false);
}
as spritebatch does not have a viewport. You have to control this using stage or cam.
you can do that.
I have this approach which works and scales as expected on Windows Desktop:
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch m_batch;
FitViewport m_viewport;
OrthographicCamera m_camera;
private Texture img;
private BitmapFont m_font;
#Override
public void create() {
Gdx.app.setLogLevel(Application.LOG_NONE);
m_batch = new SpriteBatch();
m_camera = new OrthographicCamera();
m_camera.position.set(640 / 2f, 400 / 2f, 0);
m_camera.update();
m_viewport = new FitViewport(640, 400, m_camera);
img = new Texture("badlogic.jpg");
m_font = new BitmapFont();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
m_batch.begin();
m_font.draw(m_batch, "X000000000000000000000000000000000000000000000000000000000000000000000000000000X", 0, m_camera.viewportHeight);
m_batch.draw(img, 0, 0);
m_batch.end();
}
#Override
public void resize(int width, int height) {
m_viewport.update(width, height);
}
}
Initial Window Size:
Bigger Window Size
But if I deploy to Android (in this case Nexus 7 2013) it seems not to scale properly:
Why does it not work? How to solve this?
You forgot to use the camera in your sprite batch. Call
spriteBatch.setProjectionMatrix(viewport.getCamera().combined);
before spriteBatch.begin();.