Libgdx New 3D API 教程之 -- 使用Libgdx加载模型

http://bbs.9ria.com/thread-221701-1-1.html

在前面的教程中,我们已经看到如何设置libgdx渲染3D场景。我们已经设置了Camera,增加了一些灯光并渲染一个绿色的盒子。现在让我们添加一个比盒子更有趣的东西,模型Model。

  您可以从您喜爱的建模应用程序或使用已有的模型。我找了gdx-invaders里面的飞船模型文件,你可以点这里下载。您可以解压缩后,将文件放到的android项目的assets目录下。请注意,它包含三个文件,这些文件需要放同一个文件夹中:

ship.obj:我们要加载的wavefront模型文件
ship.mtl:wavefront模型文件使用的material文件
ship.png:纹理文件

 现在让我们修改Basic3DTest,用模型替代原本的方盒子:

  1. public class Basic3DTest implements ApplicationListener {
  2. ...
  3. @Override
  4. public void create () {
  5. modelBatch = new ModelBatch();
  6. lights = new Lights();
  7. lights.ambientLight.set(0.4f, 0.4f, 0.4f, 1f);
  8. lights.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
  9. cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
  10. cam.position.set(1f, 1f, 1f);
  11. cam.lookAt(0,0,0);
  12. cam.near = 0.1f;
  13. cam.far = 300f;
  14. cam.update();
  15. ModelLoader loader = new ObjLoader();
  16. model = loader.loadModel(Gdx.files.internal("data/ship.obj"));
  17. instance = new ModelInstance(model);
  18. camController = new CameraInputController(cam);
  19. Gdx.input.setInputProcessor(camController);
  20. }
  21. ...
  22. }

复制代码

  只有一点点改动,首先,camera离原点更近了,因为这飞船太小,然后,我们删掉了ModelBuilder,新建了一个ModelLoader,通过这个Loader,加载了一个模型飞船。结果就像下面这样:

<ignore_js_op>

2013-6-27 18:15:50 上传

下载附件 (84.89 KB)

  这么做,测试的时候是没什么问题的,可是大型应用中,你将需要AssetManager去管理模型文件。下面,我们来添加:

  1. public class Basic3DTest implements ApplicationListener {
  2. public PerspectiveCamera cam;
  3. public CameraInputController camController;
  4. public ModelBatch modelBatch;
  5. public AssetManager assets;
  6. public Array<ModelInstance> instances = new Array<ModelInstance>();
  7. public Lights lights;
  8. public boolean loading;
  9. @Override
  10. public void create () {
  11. modelBatch = new ModelBatch();
  12. lights = new Lights();
  13. lights.ambientLight.set(0.4f, 0.4f, 0.4f, 1f);
  14. lights.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
  15. cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
  16. cam.position.set(1f, 1f, 1f);
  17. cam.lookAt(0,0,0);
  18. cam.near = 0.1f;
  19. cam.far = 300f;
  20. cam.update();
  21. camController = new CameraInputController(cam);
  22. Gdx.input.setInputProcessor(camController);
  23. assets = new AssetManager();
  24. assets.load("data/ship.obj", Model.class);
  25. loading = true;
  26. }
  27. private void doneLoading() {
  28. Model ship = assets.get("data/ship.obj", Model.class);
  29. ModelInstance shipInstance = new ModelInstance(ship);
  30. instances.add(shipInstance);
  31. loading = false;
  32. }
  33. @Override
  34. public void render () {
  35. if (loading && assets.update())
  36. doneLoading();
  37. camController.update();
  38. Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
  39. Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
  40. modelBatch.begin(cam);
  41. for (ModelInstance instance : instances)
  42. modelBatch.render(instance, lights);
  43. modelBatch.end();
  44. }
  45. @Override
  46. public void dispose () {
  47. modelBatch.dispose();
  48. instances.clear();
  49. assets.dispose();
  50. }
  51. public boolean needsGL20 () {
  52. return true;
  53. }
  54. public void resume () {
  55. }
  56. public void resize (int width, int height) {
  57. }
  58. public void pause () {
  59. }
  60. }

复制代码

  过一遍都有哪些改动,去掉了Model instance,创建了AssetManager, 我们没有再使用单个的ModelInstance对象,而新建了一个数组,以便渲染多个实例,看起来更帖近实际。我们还添加了一个flag,标记加载是否正在进行。
现在,在Create方法中,我们创建一个asset manager, 并通过他加载飞船的模型文件。紧接着,我们设置了loading flag,通过它,我们就可以得知,需要更新assetmanager,来取得资源加载状态。在render方法中,我们读取loading flag的值,如果为 true,就说明asset manager正在加载资源,那我们需要调用assets.update(),如果返回的true,则加载结束,调用doneLoading()。同样在render方法里,我们渲染所有instance数组中的对象,而不是仅仅某一个。如果资源没加载成功,这个数组就为空。

  新的方法doneLoading()得到我们刚刚加载的 ship 模型,创建一个名为shipInstance的modelInstance,并把它添加到的instances数组,使得它被渲染。最后,我们需要设置加载标志设置为false,这之后render中,assets.update()将不再被调用。

  如果你运行这个,你会看到跟以前一样画面。并且,你会在看到飞船前,看到黑屏,这是通过asset manager异步加载模型造成的。

  我们的程序支持多个model instances, 所以我们改成下面这样。

  1. public class Basic3DTest implements ApplicationListener {
  2. ...
  3. @Override
  4. public void create () {
  5. ...
  6. cam.position.set(7f, 7f, 7f);
  7. ...
  8. }
  9. private void doneLoading() {
  10. Model ship = assets.get("data/ship.obj", Model.class);
  11. for (float x = -5f; x <= 5f; x += 2f) {
  12. for (float z = -5f; z <= 5f; z += 2f) {
  13. ModelInstance shipInstance = new ModelInstance(ship);
  14. shipInstance.transform.setToTranslation(x, 0, z);
  15. instances.add(shipInstance);
  16. }
  17. }
  18. loading = false;
  19. }
  20. ...
  21. }

复制代码

  我们把相机又调远了些,这样可以在屏幕里,显示出所有的ship. 您可以通过鼠标滚轮来控制远近(放大,缩小)。在DoneLoading方法中,我们创建多个instance, 并放在一个基于x, z轴的网格中。

<ignore_js_op>

2013-6-27 18:15:49 上传

下载附件 (118.78 KB)

  使用obj(wavefront)文件做测试还不错,可是现实应用中,就不太合适了,因为这种格式无法包函足够的信息去存储复杂的模型。而在Libgdx中,ObjLoader也就是为了测试用的,没太多也许是你想要的功能。

  幸运的是,我们有:FBX-CONV,可以将建模软件生成的模型文件转成libgdx可识别的格式。名字可以有点误导,fbx-conv可以转化包括fbx在内的很多格式,(包括obj),FBX是首选的文件格式,因为几乎所有的建模程序都支持它。
获取fbx-conv的运行程序,如果你还没有,你可下载源码,或下载windows版的,点击下载(应该不是最新的)。fbx-conv可以生成两种格式,g3dj(json,用于debugging)&g3db(二进制,发布程序时用,因为更小,并且加载更快)。

  命令运行如下:

  1. fbx-conv ship.obj

复制代码

  确保其他文件都在同一目录下,它将为您生成一个名为 ship.g3db 的文件。我们在程序中用一下:

  1. public class Basic3DTest implements ApplicationListener {
  2. ...
  3. @Override
  4. public void create () {
  5. ...
  6. assets.load("data/ship.g3db", Model.class);
  7. ...
  8. }
  9. private void doneLoading() {
  10. Model ship = assets.get("data/ship.g3db", Model.class);
  11. ...
  12. }
  13. ...
  14. }

复制代码

  原文地址:http://blog.csdn.net/q26335804/article/details/8994401

时间: 2024-10-31 15:21:49

Libgdx New 3D API 教程之 -- 使用Libgdx加载模型的相关文章

Libgdx New 3D API 教程之 -- Libgdx中的3D frustum culling

This blog is a chinese version of xoppa's Libgdx new 3D api tutorial. For English version, please refer to >>LINK<< 我要偷懒了,好久没看LibGDX,也很久没看3D,新教程的题目我就不懂了.不过看了课程的内容,相信你们都会理解. 正文: 当渲染一个3d场景时,其中真正可见的对象通常都比总对象数少很多.因此渲染全部的物体,包括那些根本看不到的,即浪费了富贵的GPU时间,

Libgdx New 3D API 教程之 -- 加载3D场景的背后-第二部分

http://bbs.9ria.com/thread-221699-1-1.html 在本教程的第一部分,我们已经看过LibGDX 3D API中Model类的总体结构.在第2部分中,我们将会分析渲染管道,从加载模型开始,到真正的渲染模型.我们将不会在渲染管道的某个问题上进行深入探讨.我们只会介绍一些非常基本的内容,这是我觉得你使用3D API时,应该了解的. 在这一部分,我们要分析渲染究竟做了什么.明白我们在渲染时所做的事很重要.在前一部分本教程,我们已经看到,一个Model是由很多个Node

SWFObject使用方法和中文教程及IE无法加载播放的问题

SWFObject使用方法和中文教程 SWFObject的使用是非常简单的,只需要包含 swfobject.js这个js文件,然后在DOM中插入一些简单的JS代码,就能嵌入Flash媒体资源了. 下面是一个最简单的范例: 1.文件顶部需加载swfobject.js <script type="text/javascript" src="swfobject.js"></script> <script type="text/jav

unity 3D里有两种动态加载机制

unity 3D里有两种动态加载机制: 一是Resources.Load: 一是通过AssetBundle: 其实两者本质上没有什么区别.Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时动态加载,可以指定路径和来源的.其实场景里所有静态的对象也有这么一个加载过程,只是Unity后台替你自动完成了. 1.    AssetBundles是什么? 在一些大型的网络游戏,或者加载比较多的一些场景时,如果要等

【Unity3d】3d网页游戏场景打包与加载

http://www.cnblogs.com/dosomething/archive/2012/04/07/2436353.html 3d游戏中  一个场景往往比较大  如果游戏的进行需要下载一个10M甚至更大的场景时  加载所用的时间会导致很大部分玩家的流失 我们知道unity3d中的内置地形是使用一张高度图  加载场景时  首先加载地形并显示  再去加载场景中的部件(比如树.房子等)  将会很有必要 在加载场景中的部件时  可以根据玩家当前所在的位置  由近到远的去加载 场景中的每个部件实际

node-webkit教程(15)当图片加载失败的时候

在node-webkit教程(14)禁用缓存中,简单讲了当前禁用缓存的几种方法. 在实际开发过程中,我遇到了一个因为缓存引起的诡异的问题.应用场景如下: 在一个编辑器里,不停的向画布上添加svg或者其他格式的图片文件,问题主要出在svg文件上. 插入svg图片的过程中,经常出现无法加载的现象,检测文件和url都是正确的.而且svg文件达到一定数量之后,再也无法插入新的文件.经过反复排查,确定是缓存引起的问题,无奈之下只能走清除缓存的路,实属下策. ps:对此文章感兴趣的读者,可以加qq群:Hac

esri-leaflet入门教程(4)-加载各类图层

by 李远祥 在leaflet中图层一般分为底图(Basemap)和叠加图层(Overlay).前面章节已经介绍过底图其实也是实现了TileLayer 接口,而其他的叠加图层要么就是叠加的业务图层,要么就是动态显示的图形和符号.这一点在esri leaflet中也是有对照的. ArcGIS产品中比较让人熟知的图层包括ArcGISDynamicMapServiceLayer.ArcGISImageServiceLayer.ArcGISTiledMapServiceLayer.FeatureLaye

Web API 之SelfHost与OwinSelfHots加载外部程序

下面就一些web api的一些基础内容进行阐述,然后就web api宿主承载中的实际业务问题进行解决 HttpController HttpController的激活是由处于消息处理管道尾端的HttpRoutingDispatcher来完成的,具体来说是HttpRoutingDispatcher利用HttpControllerDispatcher实现了针对目标HttpController的激活和执行.激活目标HttpController的前提是能够正确解析出HttpController的真实类型

OpenCV教程【002 VideoCapture加载并播放视频】

#include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; //opencv3.0 alpha加载并播放视频 2015.11.07 int main(int argc, char* argv[]) { const char* vedioName = "D:/演示源码/视频/djxzBrightness.mp4"; cv::VideoCaptu