You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 22:38:11