三、加载场景

在上一个教程中,我们已经了解了如何使用LibGDX转换、加载和显示模型。现在我们来看看如何加载一个完整的3D场景。

这里我们继续使用上一篇的代码。我们有一个ModelInstance实例数组,我们将使用它来定义场景。我们已经学习了如何加载飞船模型,接下来让我们再添加几个模型。你可以点击这里下载这本篇教程使用的模型。它包含4个模型(obj文件):

image.png

之前我们使用fbx-conv转换模型。我们也将对这些模型进行转换,但现在我们只使用obj文件。如下为加载这些模型的代码:


import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
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.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;

public class MainGame extends ApplicationAdapter{
	public PerspectiveCamera cam;
	private  CameraInputController camCtrol;
	private ModelBatch modelBatch;
	private AssetManager assets;
	private Array<ModelInstance> instances = new Array<>();
	private Environment env;
	
	private boolean loading;
	private Array<ModelInstance> blocks = new Array<>();
	private Array<ModelInstance> invaders = new Array<>();
	private ModelInstance ship;
	private ModelInstance space;
	
	@Override
	public void create() {
		modelBatch = new ModelBatch();
		
		env = new Environment();
		env.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
		env.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(7f, 7f, 7f);
		cam.lookAt(0,0,0);
		cam.near = 1f;
		cam.far = 300f;
		cam.update();
		
		camCtrol = new CameraInputController(cam);
		Gdx.input.setInputProcessor(camCtrol);
		
		assets = new AssetManager();
		assets.load("model/scene/ship.obj", Model.class);
		assets.load("model/scene/block.obj", Model.class);
		assets.load("model/scene/invader.obj", Model.class);
		assets.load("model/scene/spacesphere.obj", Model.class);
		
		loading = true;
	}
	
	private void doneLoading() {
		ship = new ModelInstance(assets.get("model/scene/ship.obj", Model.class));
		ship.transform.setToRotation(Vector3.Y, 180).trn(0, 0, 6f);
		instances.add(ship);

		Model blockModel = assets.get("model/scene/block.obj", Model.class);
		for (float x = -5f; x <= 5f; x += 2f) {
			ModelInstance block = new ModelInstance(blockModel);
			block.transform.setToTranslation(x, 0, 3f);
			instances.add(block);
			blocks.add(block);
		}
		
		Model invaderModel = assets.get("model/scene/invader.obj", Model.class);
//		invaderModel.animations.i
		for (float x = -5f; x <= 5f; x += 2f) {
			for (float z = -8f; z <= 0f; z += 2f) {
				ModelInstance invader = new ModelInstance(invaderModel);
				invader.transform.setToTranslation(x, 0, z);
				instances.add(invader);
				invaders.add(invader);
			}
		}
		
		space = new ModelInstance(assets.get("model/scene/spacesphere.obj", Model.class));
		
		loading = false;
	}
	
	@Override
	public void resize (int width, int height) {
	}

	@Override
	public void render () {
		if (loading && assets.update())
			doneLoading();
		camCtrol.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(instances, env);
		if (space != null)
			modelBatch.render(space);
		modelBatch.end();
		
	}

	@Override
	public void pause () {
	}

	@Override
	public void resume () {
	}

	@Override
	public void dispose () {
		modelBatch.dispose();
		instances.clear();
		assets.dispose();
	}
}

这里测试我用的是obj文件,如上一篇所述,应该使用fbx-conv将其转换才会使性能更好点。运行效果如下:

image.png