【发布时间】:2019-03-24 14:25:14
【问题描述】:
我正在编写一个 Java Web 服务,可以在其中上传 3D 对象,对其进行操作并存储它。
我要做的是创建一个AIScene 实例,使用byte[] 作为输入参数,它是文件本身(它的内容)。
我在文档中找不到这样做的方法,所有导入方法都需要路径。
现在我正在查看 Assimp 的 lwjgl java 版本和 C++ 版本。使用哪一个来解决问题并不重要。
编辑:我正在尝试完成的代码:
@Override
public String uploadFile(MultipartFile file) {
AIFileIO fileIo = AIFileIO.create();
AIFileOpenProcI fileOpenProc = new AIFileOpenProc() {
public long invoke(long pFileIO, long fileName, long openMode) {
AIFile aiFile = AIFile.create();
final ByteBuffer data;
try {
data = ByteBuffer.wrap(file.getBytes());
} catch (IOException e) {
throw new RuntimeException();
}
AIFileReadProcI fileReadProc = new AIFileReadProc() {
public long invoke(long pFile, long pBuffer, long size, long count) {
long max = Math.min(data.remaining(), size * count);
memCopy(memAddress(data) + data.position(), pBuffer, max);
return max;
}
};
AIFileSeekI fileSeekProc = new AIFileSeek() {
public int invoke(long pFile, long offset, int origin) {
if (origin == Assimp.aiOrigin_CUR) {
data.position(data.position() + (int) offset);
} else if (origin == Assimp.aiOrigin_SET) {
data.position((int) offset);
} else if (origin == Assimp.aiOrigin_END) {
data.position(data.limit() + (int) offset);
}
return 0;
}
};
AIFileTellProcI fileTellProc = new AIFileTellProc() {
public long invoke(long pFile) {
return data.limit();
}
};
aiFile.ReadProc(fileReadProc);
aiFile.SeekProc(fileSeekProc);
aiFile.FileSizeProc(fileTellProc);
return aiFile.address();
}
};
AIFileCloseProcI fileCloseProc = new AIFileCloseProc() {
public void invoke(long pFileIO, long pFile) {
/* Nothing to do */
}
};
fileIo.set(fileOpenProc, fileCloseProc, NULL);
AIScene scene = aiImportFileEx(file.getName(),
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate, fileIo); // ISSUE HERE. file.getName() is not a path, just a name. so is getOriginalName() in my case.
try{
Long id = scene.mMeshes().get(0);
AIMesh mesh = AIMesh.create(id);
AIVector3D vertex = mesh.mVertices().get(0);
return mesh.mName().toString() + ": " + (vertex.x() + " " + vertex.y() + " " + vertex.z());
}catch(Exception e){
e.printStackTrace();
}
return "fail";
}
在调试方法时,我在绑定到本机的方法中遇到访问冲突:
public static long naiImportFileEx(long pFile, int pFlags, long pFS)
这是消息:
#
Java 运行时环境检测到致命错误:
#
在 pc=0x000000007400125d,pid=6400,tid=0x0000000000003058 处的异常_访问_VIOLATION (0xc0000005)
#
JRE 版本:Java(TM) SE 运行时环境 (8.0_201-b09)(内部版本 1.8.0_201-b09)
Java VM:Java HotSpot(TM) 64 位服务器 VM(25.201-b09 混合模式 windows-amd64 压缩 oops)
有问题的框架:
V [jvm.dll+0x1e125d]
#
无法写入核心转储。默认情况下,在 Windows 的客户端版本上不启用小型转储
#
包含更多信息的错误报告文件保存为:
C:\Users\ragos\IdeaProjects\objectstore3d\hs_err_pid6400.log
#
如果您想提交错误报告,请访问:
http://bugreport.java.com/bugreport/crash.jsp
#
【问题讨论】:
-
您可以通过
aiImportFileEx函数自定义加载过程。您可以为该函数提供一个包含回调函数的结构,以加载/读取资源(无论这些资源是什么)。请参阅 LWJGL/lwjgl3-demos 存储库中的此示例:github.com/LWJGL/lwjgl3-demos/blob/master/src/org/lwjgl/demo/… 它从类路径中作为 InputStreams/ByteBuffers 加载模型和材料。 -
感谢您的评论,但这里github.com/assimp/assimp/blob/… 它表明底层实现无论如何都使用文件的路径。定义的缓冲区是一个自定义的 IO 系统。因此,它会在我的代码中导致读取访问冲突,因为我没有来自 Spring 的
MultipartFile的有效文件路径。我错过了什么?我正在将我的代码添加到问题中。与您链接的内容基本相同,但获取数据除外。 -
文件名只是你和 Assimp 之间接口的一部分,让你知道/识别应该加载什么。字符串实际上可以是任何东西。只是为了让您知道要加载/做什么。
-
而文件名是用于加载链接资源,例如 Wavefront .obj 文件中按名称引用的 .mtl 文件。
-
那真的应该不是问题。你能帮我看看我在哪里搞砸了吗?我从第 8-10 行开始更改了代码,因为
MultipartFile只是传递了对象,而我已经将它的内容作为byte[]。