Libgdx: 打开外部文件时出现“内部”文件未找到错误

3

这是一个不错的问题。

我正在尝试使用external打开一个文件。

FileHandle dirHandel = Gdx.files.external("MyApps/skanectModel.g3db");
boolean isDir = Gdx.files.external("MyApps/skanectModel.g3db").exists();

我知道文件在那里,而且布尔值告诉我它确实在那里。

主要问题是我收到了这个错误。

Caused by: com.badlogic.gdx.utils.GdxRuntimeException: Error reading file: MyApps/skanectModel.png (Internal)

我不知道为什么会这样做,我并没有寻找内部文件。

出于好奇,我在我的资产文件夹中创建了一个文件,就像这样assets/MyApps/skanectModel.png,代码运行得很完美,应用程序也可以在我的安卓设备上播放。

但是...我需要能够只读取外部文件。我正在构建一个简单的3D查看器,为一些朋友发送3D模型。

以下是代码副本:

package com.mygdx.game;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.loaders.ModelLoader;
import com.badlogic.gdx.Files;
import com.badlogic.gdx.files.FileHandle;
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.loader.G3dModelLoader;
import com.badlogic.gdx.graphics.g3d.loader.ObjLoader;
import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.UBJsonReader;

public class MyGdxGame implements ApplicationListener {
    public Environment environment;
    public PerspectiveCamera cam;
    public CameraInputController camController;
    public ModelBatch modelBatch;
    public Model model;
    public ModelInstance instance;

@Override
public void create() {
    environment = new Environment();
    environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 1.4f, 1.4f, 1.4f, 5f));
    environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));

    cam = new PerspectiveCamera(75,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
    cam.position.set(50f, 1f, 50f);
    cam.lookAt(0,0,0);
    cam.near = 0.1f;
    cam.far = 500f;
    cam.update();

    modelBatch = new ModelBatch();
//      ModelLoader<?> loader = new ObjLoader();
    UBJsonReader jsonReader = new UBJsonReader();
    G3dModelLoader modelLoader = new G3dModelLoader(jsonReader);

//      model = modelLoader.loadModel(Gdx.files.getFileHandle("root/MyApps/skanectModel.g3db",Files.FileType.Absolute));
//      model = modelLoader.loadModel(Gdx.files.getFileHandle("skanectModel.g3db",Files.FileType.External));

    FileHandle dirHandel = Gdx.files.external("MyApps/skanectModel.g3db");
    boolean isDir = Gdx.files.external("MyApps/skanectModel.g3db").exists();
    Gdx.app.log("is it", String.valueOf(isDir));
//      for (FileHandle entry: dirHandel.list()){
//          Gdx.app.log("Path",entry.toString());
//      }
    model = modelLoader.loadModel(dirHandel);
//      model = modelLoader.loadModel(Gdx.files.getFileHandle("skanectModel.g3db",Files.FileType.External));
    instance = new ModelInstance(model);
    instance.transform.rotate(90f,0f,0,-90f);


    camController = new CameraInputController(cam);
    Gdx.input.setInputProcessor(camController);
}

@Override
public void render() {
    camController.update();

    Gdx.gl.glViewport(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
    Gdx.gl.glClearColor(.5f,1,1,1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);

    modelBatch.begin(cam);
    modelBatch.render(instance, environment);
    modelBatch.end();
}

@Override
public void dispose() {
    modelBatch.dispose();
    model.dispose();
}

@Override
    public void resize(int width, int height) {
}

@Override
    public void pause() {
}

@Override
    public void resume() {
}
}

请帮忙! 编辑: 以下是完整的错误日志:
06-20 10:00:47.918    3205-3221/com.mygdx.game.android E/AndroidRuntime﹕    FATAL EXCEPTION: GLThread 39207
Process: com.mygdx.game.android, PID: 3205
com.badlogic.gdx.utils.GdxRuntimeException: Couldn't load file:MyApps/skanectModel.png
at com.badlogic.gdx.graphics.Pixmap.<init>(Pixmap.java:140)
at com.badlogic.gdx.graphics.TextureData$Factory.loadFromFile(TextureData.java:98)  at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:100) 
at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:92)
at com.badlogic.gdx.graphics.g3d.utils.TextureProvider$FileTextureProvider.load(TextureProvider.java:34) 
at com.badlogic.gdx.graphics.g3d.Model.convertMaterial(Model.java:290)
at com.badlogic.gdx.graphics.g3d.Model.loadMaterials(Model.java:266)
at com.badlogic.gdx.graphics.g3d.Model.load(Model.java:107)
at com.badlogic.gdx.graphics.g3d.Model.<init>(Model.java:102)
at com.badlogic.gdx.assets.loaders.ModelLoader.loadModel(ModelLoader.java:54)
at com.badlogic.gdx.assets.loaders.ModelLoader.loadModel(ModelLoader.java:69)
at com.mygdx.game.MyGdxGame.create(MyGdxGame.java:65)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:241)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1520)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1248)
Caused by: com.badlogic.gdx.utils.GdxRuntimeException: Error reading file: MyApps/skanectModel.png (Internal)
at com.badlogic.gdx.backends.android.AndroidFileHandle.read(AndroidFileHandle.java:77)
at com.badlogic.gdx.files.FileHandle.readBytes(FileHandle.java:222)
at com.badlogic.gdx.graphics.Pixmap.<init>(Pixmap.java:137)
at com.badlogic.gdx.graphics.TextureData$Factory.loadFromFile(TextureData.java:98)
at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:100)
at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:92)
at com.badlogic.gdx.graphics.g3d.utils.TextureProvider$FileTextureProvider.load(TextureProvider.java:34)
at com.badlogic.gdx.graphics.g3d.Model.convertMaterial(Model.java:290)
at com.badlogic.gdx.graphics.g3d.Model.loadMaterials(Model.java:266)
at com.badlogic.gdx.graphics.g3d.Model.load(Model.java:107)
at com.badlogic.gdx.graphics.g3d.Model.<init>(Model.java:102)
at com.badlogic.gdx.assets.loaders.ModelLoader.loadModel(ModelLoader.java:54)
at com.badlogic.gdx.assets.loaders.ModelLoader.loadModel(ModelLoader.java:69)
at com.mygdx.game.MyGdxGame.create(MyGdxGame.java:65)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:241)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1520)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1248)
Caused by: java.io.FileNotFoundException: MyApps/skanectModel.png
at android.content.res.AssetManager.openAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:324)
at android.content.res.AssetManager.open(AssetManager.java:298)
at com.badlogic.gdx.backends.android.AndroidFileHandle.read(AndroidFileHandle.java:75)
at com.badlogic.gdx.files.FileHandle.readBytes(FileHandle.java:222)
at com.badlogic.gdx.graphics.Pixmap.<init>(Pixmap.java:137)
at com.badlogic.gdx.graphics.TextureData$Factory.loadFromFile(TextureData.java:98)
at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:100)
at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:92)
at com.badlogic.gdx.graphics.g3d.utils.TextureProvider$FileTextureProvider.load(TextureProvider.java:34)
at com.badlogic.gdx.graphics.g3d.Model.convertMaterial(Model.java:290)
at com.badlogic.gdx.graphics.g3d.Model.loadMaterials(Model.java:266)
at com.badlogic.gdx.graphics.g3d.Model.load(Model.java:107)
at com.badlogic.gdx.graphics.g3d.Model.<init>(Model.java:102)
at com.badlogic.gdx.assets.loaders.ModelLoader.loadModel(ModelLoader.java:54)
at com.badlogic.gdx.assets.loaders.ModelLoader.loadModel(ModelLoader.java:69)
at com.mygdx.game.MyGdxGame.create(MyGdxGame.java:65)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphi cs.java:241)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1520)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1248)

******编辑***** 在MadEqua的快速建议下,我实施了修复。

FileHandle dirHandel = Gdx.files.external("MyApps/skanectModel.g3db");
myT = new TextureProvider() {
@Override
public Texture load(String fileName) {
Texture result = new Texture(Gdx.files.external(fileName));
result.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
result.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);
return result;
  }
};
myT.load("Myapps/skanectModel.png");
model = modelLoader.loadModel(dirHandel,myT);
2个回答

2
经过仔细查看您的堆栈跟踪,似乎模型文件本身已经成功加载。
问题出现在加载模型的纹理时:

在com.badlogic.gdx.backends.android.AndroidFileHandle.read(AndroidFileHandle.java:75)处, 在com.badlogic.gdx.files.FileHandle.readBytes(FileHandle.java:222)处, 在com.badlogic.gdx.graphics.Pixmap.(Pixmap.java:137)处, 在com.badlogic.gdx.graphics.TextureData$Factory.loadFromFile(TextureData.java:98)处, 在com.badlogic.gdx.graphics.Texture.(Texture.java:100)处, 在com.badlogic.gdx.graphics.Texture.(Texture.java:92)处, 在com.badlogic.gdx.graphics.g3d.utils.TextureProvider$FileTextureProvider.load(TextureProvider.java:34)处, 在com.badlogic.gdx.graphics.g3d.Model.convertMaterial(Model.java:290)处, 在com.badlogic.gdx.graphics.g3d.Model.loadMaterials(Model.java:266)处发生错误。

我认为libGDX正在尝试从错误的位置加载纹理文件(一个内部位置,解释了您收到的错误)。
我从未使用过libDGX模型函数,但我认为你应该改用这种方法:loadModel(FileHandle fileHandle, TextureProvider textureProvider)
并传入一个TextureProvider,从外部文件夹加载纹理文件。(确保纹理文件在那里)。
很容易实现一个自定义的TextureProvider,通过查看FileTextureProvider来完成这个任务。

如果可以的话,我现在就亲你一口....!!! 简直完美。这是我的做法: FileHandle dirHandel = Gdx.files.external("MyApps/skanectModel.g3db"); myT = new TextureProvider() { @Override public Texture load(String fileName) { Texture result = new Texture(Gdx.files.external(fileName)); result.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear); result.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat); return result; } }; myT.load("Myapps/skanectModel.png"); model = modelLoader.loadModel(dirHandel,myT); - Javier Camacho
是的,我也花了一些时间才明白那是一个纹理问题。顺便说一句,这行代码没有任何作用,可以删除:myT.load("Myapps/skanectModel.png");。加载操作在ModelLoader内部调用。不过不要亲亲,哈哈。;-) - MadEqua

1

文件处理Libgdx Wiki

来自他们的Wiki

在Android上,外部文件路径相对于SD卡根目录,在桌面系统上则相对于当前用户的主目录。

以及

本地文件存储在桌面应用程序的根目录或工作目录相对位置,并相对于Android应用程序的内部(私有)存储。请注意,在桌面上,本地和内部存储基本相同。

因此,如果您的文件位于项目根目录中,则应使用local而不是external。您能否提供更多信息,例如测试平台。


感谢您的回复。我非常清楚libgdx的文件处理方式。但是我正在尝试使用外部文件“root”从Android加载模型,但是libgdx仍在内部寻找纹理而不是在外部文件的相同目录中查找。请阅读我的原始帖子以更好地了解发生了什么。 - Javier Camacho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接