根据文件内容创建AIScene实例

时间:2019-03-24 14:25:15

标签: spring lwjgl assimp

我正在编写Java Web服务,可以在其中上传3D对象,对其进行操作并进行存储。

我要做的是使用AIScene作为输入参数(即文件本身(内容))创建byte[]实例。

我在文档中没有找到执行此操作的方法,所有导入方法都需要一个路径。

现在,我将同时考察Assimp的Java版本lwjgl和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运行时环境检测到致命错误:

     

     

EXCEPTION_ACCESS_VIOLATION(0xc0000005)at pc = 0x000000007400125d,pid = 6400,tid = 0x0000000000003058

     

     

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

     

1 个答案:

答案 0 :(得分:0)

如果使用aiImportFileFromMemory方法,则是可能的。

我要遵循的方法是从github演示复制而来,实际上不必要地复制了缓冲区。

访问冲突的原因是使用了间接缓冲区(有关更多信息,为什么会有此问题,请检查this)。

解决方案并不像我最初粘贴的代码那么复杂:

@Override
    public String uploadFile(MultipartFile file) throws IOException {
        ByteBuffer buffer = BufferUtils.createByteBuffer((int) file.getSize());
        buffer.put(file.getBytes());
        buffer.flip();
        AIScene scene = Assimp.aiImportFileFromMemory(buffer,aiProcess_Triangulate, (ByteBuffer) null);
        Long id = scene.mMeshes().get(0);
        AIMesh mesh = AIMesh.create(id);
        AIVector3D vertex = mesh.mVertices().get(0);
        return mesh.mName().dataString() + ": " + (vertex.x() + " " + vertex.y() + " " + vertex.z());
    }

在这里,我创建一个具有适当大小的 direct 缓冲区,加载数据并 flip it (这是必须的。)之后,让Assimp做它的魔力,因此您可以找到结构的指针。使用return语句,我只是检查是否获得了有效数据。

修改

正如在评论中指出的那样,此实现仅限于单个文件上传,并假定它从那个MultipartFile获取了所有必需的内容,但不适用于引用格式。有关更多详细信息,请参见docs

在问题注释中链接的演示(作为问题的基础使用)与我原来的用例不同。

相关问题