如何在LibGDX中绘制可缩放3D调试网格,辅助相机与模型调试
解决方案:LibGDX 3D网格缩放、球体变形修复与相机可视化
完全可以实现你提到的所有需求,下面分点解决你的问题并给出修改示例:
1. 修复球体挤压变形问题
你的球体出现变形主要有两个原因:
createSphere方法的第三个参数用了整数120,导致Z轴半径与X/Y轴的浮点数不一致,改成120f即可保证球体各轴比例正确。- 相机的视口宽高比未随窗口尺寸变化更新,需要重写
resize方法同步相机视口参数。
2. 将球体移至屏幕中央
当前你把球体位置设为 (100,100,0),而相机看向 (0,0,0),所以只需将球体的变换位置改为 (0,0,0),就能让球体处于相机视野的中央位置。
3. 实现可缩放的3D网格
通过修改 ModelInstance 的变换矩阵即可实现缩放,结合输入控制(比如鼠标滚轮)可以动态调整缩放比例:
- 定义一个缩放因子变量,通过鼠标滚轮输入更新该值
- 重置球体的变换矩阵,先平移到目标位置,再应用缩放变换
4. 可视化相机位置与参数
有两种直观的方式:
- 使用LibGDX内置的
DebugRenderer,可以直接绘制相机的视锥体、位置坐标轴 - 通过
SpriteBatch和BitmapFont将相机的参数(位置、FOV、近远裁剪面)渲染到屏幕UI层
修改后的完整代码示例
import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.PerspectiveCamera; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g3d.Environment; 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.utils.DebugRenderer; import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder; import com.badlogic.gdx.math.Quaternion; import com.badlogic.gdx.math.Vector3; public class YourGame extends ApplicationAdapter { private ModelBatch modelBatch; private Environment environment; private PerspectiveCamera cam; private Model model; private ModelInstance instance; private DebugRenderer debugRenderer; private SpriteBatch spriteBatch; private BitmapFont font; private float sphereScale = 1f; @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, 10f, 10f, 20f)); // 初始化相机 cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); cam.position.set(150f, -9f, 200f); cam.lookAt(0, 0, 0); cam.near = 1f; cam.far = 300f; cam.update(); // 创建球体(修复Z轴半径的类型问题) ModelBuilder modelBuilder = new ModelBuilder(); model = modelBuilder.createSphere(120f, 120f, 120f, 32, 32, new Material(ColorAttribute.createDiffuse(Color.GREEN)), com.badlogic.gdx.graphics.VertexAttributes.Usage.Position | com.badlogic.gdx.graphics.VertexAttributes.Usage.Normal); instance = new ModelInstance(model); // 将球体移至原点(相机看向的中心点) instance.transform.set(new Vector3(0, 0, 0), new Quaternion()); // 初始化调试工具与UI渲染组件 debugRenderer = new DebugRenderer(); spriteBatch = new SpriteBatch(); font = new BitmapFont(); } @Override public void resize(int width, int height) { // 同步相机视口与窗口尺寸,避免变形 cam.viewportWidth = width; cam.viewportHeight = height; cam.update(); } @Override public void render(float delta) { // 处理鼠标滚轮缩放 float scrollDelta = Gdx.input.getDeltaY(); if (scrollDelta != 0) { sphereScale += scrollDelta * 0.01f; sphereScale = Math.max(0.1f, sphereScale); // 限制最小缩放比例,防止球体消失 // 重置变换并应用新缩放 instance.transform.idt(); instance.transform.translate(0, 0, 0); instance.transform.scale(sphereScale, sphereScale, sphereScale); } // 清空屏幕 Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1f); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); // 渲染3D场景 modelBatch.begin(cam); modelBatch.render(instance, environment); modelBatch.end(); // 渲染相机调试视锥体与坐标轴 debugRenderer.render(cam, environment); // 渲染相机参数到屏幕 spriteBatch.begin(); font.draw(spriteBatch, "相机位置: " + cam.position, 10, Gdx.graphics.getHeight() - 20); font.draw(spriteBatch, "相机FOV: " + cam.fieldOfView, 10, Gdx.graphics.getHeight() - 40); font.draw(spriteBatch, "近裁剪面/远裁剪面: " + cam.near + "/" + cam.far, 10, Gdx.graphics.getHeight() - 60); font.draw(spriteBatch, "球体缩放比例: " + String.format("%.2f", sphereScale), 10, Gdx.graphics.getHeight() - 80); spriteBatch.end(); } @Override public void dispose() { // 释放资源 modelBatch.dispose(); model.dispose(); debugRenderer.dispose(); spriteBatch.dispose(); font.dispose(); } }
内容的提问来源于stack exchange,提问作者nutella_eater
相关产品推荐
相关产品推荐

