Renders a mesh within a libGDX widget.
package com.traviswyatt.example.ui; | |
import com.badlogic.gdx.Gdx; | |
import com.badlogic.gdx.graphics.GL10; | |
import com.badlogic.gdx.graphics.GLCommon; | |
import com.badlogic.gdx.graphics.PerspectiveCamera; | |
import com.badlogic.gdx.graphics.Pixmap.Format; | |
import com.badlogic.gdx.graphics.g2d.SpriteBatch; | |
import com.badlogic.gdx.graphics.g3d.model.Model; | |
import com.badlogic.gdx.graphics.glutils.FrameBuffer; | |
import com.badlogic.gdx.graphics.glutils.ShaderProgram; | |
import com.badlogic.gdx.math.Matrix4; | |
import com.badlogic.gdx.math.Vector2; | |
import com.badlogic.gdx.math.Vector3; | |
import com.badlogic.gdx.math.collision.BoundingBox; | |
import com.badlogic.gdx.scenes.scene2d.ui.ClickListener; | |
import com.badlogic.gdx.scenes.scene2d.ui.Widget; | |
public class ModelView extends Widget { | |
private PerspectiveCamera camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); | |
private final Model model; | |
private final ShaderProgram shader; | |
private ClickListener clickListener; | |
private final float prefWidth; | |
private final float prefHeight; | |
FrameBuffer frameBuffer = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true); | |
private static final Matrix4 modelView = new Matrix4(); | |
public ModelView(Model model, ShaderProgram shader, float width, float height, String name) { | |
super(name); | |
this.model = model; | |
this.shader = shader; | |
BoundingBox boundingBox = new BoundingBox(); | |
model.getBoundingBox(boundingBox); | |
Vector3 center = boundingBox.getCenter(); | |
camera.position.set(boundingBox.max.x, boundingBox.max.y, boundingBox.max.z).mul(2); | |
camera.lookAt(center.x, center.y, center.z); | |
camera.up.set(0, 0, 1); | |
camera.normalizeUp(); | |
camera.near = 1f; | |
camera.far = new Vector3(camera.position).dst2(center) * 2f; | |
camera.update(); | |
prefWidth = width; | |
prefHeight = height; | |
} | |
@Override | |
public float getPrefWidth() { | |
return prefWidth; | |
} | |
@Override | |
public float getPrefHeight() { | |
return prefHeight; | |
} | |
@Override | |
public void layout() { | |
camera.update(); | |
} | |
public void draw(SpriteBatch batch, float parentAlpha) { | |
validate(); | |
batch.end(); | |
float dt = Gdx.graphics.getDeltaTime(); | |
modelView.rotate(0, 0, 1, 100 * dt); | |
// actually stage coordinates! | |
Vector2 tmp = Vector2.tmp.set(0, 0); | |
toScreenCoordinates(this, tmp); | |
GLCommon gl = Gdx.graphics.getGLCommon(); | |
gl.glViewport((int)tmp.x, (int)tmp.y, (int)width, (int)height); | |
gl.glEnable(GL10.GL_DEPTH_TEST); | |
gl.glDepthMask(true); | |
gl.glDepthFunc(GL10.GL_LEQUAL); | |
gl.glDepthRangef(0f, 1f); | |
if (shader == null) { | |
// FIXME glLight and rotate | |
model.render(); | |
} else { | |
Vector3 light = camera.position; | |
shader.begin(); | |
shader.setUniformf("u_lightPosition", light.x, light.y, light.z); | |
shader.setUniformMatrix("u_modelView", modelView); | |
shader.setUniformMatrix("u_projModelView", camera.combined); | |
model.render(shader); | |
shader.end(); | |
} | |
gl.glDisable(GL10.GL_DEPTH_TEST); | |
gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); | |
batch.begin(); | |
} | |
public boolean touchDown (float x, float y, int pointer) { | |
return clickListener != null; | |
} | |
public void touchUp (float x, float y, int pointer) { | |
if (hit(x, y) == null) return; | |
if (clickListener != null) clickListener.click(this, x, y); | |
} | |
public void touchDragged (float x, float y, int pointer) { | |
} | |
public void setClickListener (ClickListener clickListener) { | |
this.clickListener = clickListener; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment