【问题标题】:Importing OBJ file in QtCreator在 QtCreator 中导入 OBJ 文件
【发布时间】:2020-02-06 15:05:12
【问题描述】:

我是使用 Qt Creator(版本 4.10.0,基于 Qt 5.13.1)的新手。我已经使用了customitemgraph example,我想用新文件替换现有的.obj 文件。 我从网上下载了一些免费的模型。其中一些有效,但另一些无效。

这里有两个例子。

使用记事本打开的.obj 文件的摘录,该文件正在运行

...
vn 0.3531 -0.8627 -0.3620
vn 0.3815 -0.9243 -0.0148
usemtl Default_OBJ
s 1
f 1/1/1 2/2/2 3/3/3 4/4/4
f 2/2/2 5/5/5 6/6/6 3/3/3
f 4/4/4 3/3/3 7/7/7 8/8/8
...

一个不工作的案例:

...
vn -0.1013 -0.8959 -0.4325
vn -0.1003 -0.8978 -0.4287
usemtl Body
s 1
f 225536//133387 225537//133388 225544//133389 225543//133390
f 225537//133388 225538//133391 225545//133392 225544//133389
f 225538//133391 225539//133393 225546//133394 225545//133392
f 225539//133393 225540//133395 225547//133396 225546//133394
...

当它不起作用时,错误消息是:

tot 4ASSERT failure in QVector<T>::operator[]: "index out of range", file c:\Users\qt\work\install\include/QtCore/qvector.h, line 448

我尝试过的

我用记事本打开了.obj 文件,发现在工作的情况下只有一个/ 字符分隔数字,而在不工作的情况下有// 两个斜杠,中间没有数字。用一个单斜杠替换双斜杠后没有任何变化,问题仍然存在。

我尝试了一些取自here 的简单.obj 文件来进一步诊断问题,但这些示例都不起作用。

我错过了什么吗?有没有解决的办法?在此示例中使用我的 .obj 文件的另一种方法?感谢您的帮助。

【问题讨论】:

  • 根据this spec,这些 face 值之间不应有斜线。然而,最终使用的索引太大了。您可以通过在调试器中运行代码并捕获该异常来找出位置。
  • @trojanfoe 谢谢,但您链接的网站是我用于手工制作示例的网站,但它们不起作用。我会尝试使用调试器并更新我的答案......
  • 我对斜线的理解是错误的(我看的不够仔细)。让你的解析器处理双斜杠,但为了避免崩溃,在访问它们之前检查向量的长度并在优雅地返回之前生成错误消息(或者如果你不喜欢优雅地抛出异常,这也可以) .
  • @trojanfoe 我刚刚查看了我的 impl。用于波前对象。它读取 _with _ 斜线的面部索引。如果我只注意到我在哪里找到了规范。我是按照……写的。虽然,索引值看起来确实很大。
  • 是的,// 可能显示缺少值,而 .obj 只是完全损坏。

标签: c++ qt wavefront qvector


【解决方案1】:

关于:

我尝试了一些取自 here 的简单 .obj 文件来进一步诊断问题,但这些示例都不起作用。

我也从here 中提取了样本——cube.obj

# This cube has a different material
# applied to each of its faces.
mtllib master.mtl
v 0.000000 2.000000 2.000000
v 0.000000 0.000000 2.000000
v 2.000000 0.000000 2.000000
v 2.000000 2.000000 2.000000
v 0.000000 2.000000 0.000000
v 0.000000 0.000000 0.000000
v 2.000000 0.000000 0.000000
v 2.000000 2.000000 0.000000
# 8 vertices
g front
usemtl red
f 1 2 3 4
g back
usemtl blue
f 8 7 6 5
g right
usemtl green
f 4 3 7 8
g top
usemtl gold
f 5 1 4 8
g left
usemtl orange
f 5 6 2 1
g bottom
usemtl purple
f 2 6 7 3
# 6 elements

示例引用了master.mtl,我在任何地方都找不到。

因此,我从零开始写了一篇——master.mtl

# Create as many materials as desired
# Each is referenced by name before the faces it applies to in the obj file

newmtl red
Ka 1.000000 0.000000 0.000000
Kd 1.000000 0.000000 0.000000
Ks 0.000000 0.000000 0.000000
Ns 0.000000

newmtl blue
Ka 0.000000 0.000000 1.000000
Kd 0.000000 0.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ns 0.000000

newmtl green
Ka 0.000000 1.000000 0.000000
Kd 0.000000 1.000000 0.000000
Ks 0.000000 0.000000 0.000000
Ns 0.000000

newmtl gold
Ka 1.000000 1.000000 0.000000
Kd 1.000000 1.000000 0.000000
Ks 1.000000 1.000000 0.000000
Ns 0.000000

newmtl orange
Ka 1.000000 0.500000 0.000000
Kd 1.000000 0.500000 0.000000
Ks 0.000000 0.000000 0.000000
Ns 0.000000

newmtl purple
Ka 1.000000 0.000000 1.000000
Kd 1.000000 0.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ns 0.000000

然后,我用我们的加载器试了一下,得到了这个:

然后,我修改了cube.obj 以添加法线。

这是一个示例,其中双斜杠 (//) 出现在面索引中(由于缺少纹理坐标)。

带有法线的文件 – cubeN.obj:

# This cube has a different material
# applied to each of its faces.
mtllib master.mtl
v 0.000000 2.000000 2.000000
v 0.000000 0.000000 2.000000
v 2.000000 0.000000 2.000000
v 2.000000 2.000000 2.000000
v 0.000000 2.000000 0.000000
v 0.000000 0.000000 0.000000
v 2.000000 0.000000 0.000000
v 2.000000 2.000000 0.000000
vn 0 0 1
vn 0 0 -1
vn 1 0 0
vn 0 1 0
vn -1 0 0
vn 0 -1 0
# 8 vertices
g front
usemtl red
f 1//1 2//1 3//1 4//1
g back
usemtl blue
f 8//2 7//2 6//2 5//2
g right
usemtl green
f 4//3 3//3 7//3 8//3
g top
usemtl gold
f 5//4 1//4 4//4 8//4
g left
usemtl orange
f 5//5 6//5 2//5 1//5
g bottom
usemtl purple
f 2//6 6//6 7//6 3//6
# 6 elements

除了样本没有完全损坏(在我们的加载程序中)之外,不确定这是否能证明任何事情。

【讨论】:

  • 我尝试使用您提供的文件。我将cubeN.objmaster.mtl 放在同一个文件夹中,然后在我的代码中调用item-&gt;setMeshFile("cubeN.obj");,但错误仍然出现。
  • 是的,是一样的。
  • @Sandra 我修改了样本。在查看源代码objgeometryloader.cpp 后,我不确定制表符 (\t) 是否有问题并删除了所有标签(或用空格替换它们)。你能再试一次吗? (我之前在另一条评论中提到的来源显然是错误的——我的错,对不起。)
  • @Sandra 在源代码中阅读更多内容,我发现两个可能的问题:1. 只有空格被视为值之间的分隔符(我没有发现任何用空格替换制表符); 2. cmets(以#为前缀)可能没有缩进。我不确定这是否符合规范,但我确信我们的加载程序可以容忍这一点。因此,这些文件可能已经在我们这边工作了,但不在 QtCreator 中。 (但是,我会进一步调查......)
  • 谢谢,我尝试了你的新样本,但它不起作用(同样的错误消息)
【解决方案2】:

我必须承认,今天是我第一次使用 QtCreator 以及 QML。

与 OP 相反,我在实验中使用了一个更简单的示例:

Qt 3D: Wireframe QML Example

经过一番折腾,我得到了以下收据:

  1. 在 QtCreator 中打开 wireframe 示例。
    该示例使用 Wavefront OBJ 文件trefoil.obj

  2. 在磁盘上找到trefoil.obj
    我在.../Qt/Examples/Qt-5.13.0/qt3d/exampleresources/assets/obj 下找到它。

  3. 将来自the other answer 的示例文件cube.objcubeN.obj 存储到此文件夹中。
    无论如何,在此示例中都没有引用材料文件master.mtl。 据我了解,材料是在 QML 中定义的。 – 在任何情况下,任何加载的材料都会被覆盖。

  4. 在QtCreator的项目树视图中,将示例文件cube.objcubeN.obj添加到Resources/.../Qt/Examples/Qt-5.13.0/qt3d/exampleresources/obj.qrc/assets/obj
    之后在文本编辑器中打开.../Qt/Examples/Qt-5.13.0/qt3d/exampleresources/obj.qrc,我发现:

<RCC>
    <qresource prefix="/">
        <file>assets/obj/trefoil.obj</file>
        <file>assets/obj/toyplane.obj</file>
        <file>assets/obj/ball.obj</file>
        <file>assets/obj/plane-10x10.obj</file>
        <file>assets/obj/material-sphere.obj</file>
        <file>assets/obj/cube.obj</file>
        <file>assets/obj/cubeN.obj</file>
    </qresource>
</RCC>
  1. 我将文件QML/TrefoilKnot.qml复制到QML/Cube.qmlQML/CubeN.qml并分别替换了source条目-Cube.qml
import Qt3D.Core 2.0
import Qt3D.Render 2.0

Entity {
    id: root

    property real x: 0.0
    property real y: 0.0
    property real z: 0.0
    property real scale: 1.0
    property real theta: 0.0
    property real phi: 0.0
    property Material material

    components: [ transform, mesh, root.material ]

    Transform {
        id: transform
        translation: Qt.vector3d(root.x, root.y, root.z)
        rotation: fromEulerAngles(theta, phi, 0)
        scale: root.scale
    }

    Mesh {
        id: mesh
        source: "assets/obj/cube.obj"
    }
}
  1. 我将文件Cube.qmlCubeN.qml 添加到Resources/wireframe.qrc
  2. 我更改了QML/main.qml 以添加实体CubeCubeN
    TrefoilKnot {
        id: trefoilKnot
        material: wireframeMaterial
    }
    Cube {
        id: cube
        material: wireframeMaterial
    }
    /* Excluded:
    CubeN {
        id: cubeN
        material: wireframeMaterial
    }*/

启动应用后,得到如下结果:

我对@9​​87654366@ 进行了同样的尝试,结果看起来很相似:

我在 Windows 10(64 位)上使用 Qt 5.13.0 和 Qt Creator 4.9.1。


关于objgeometryloader.cpp

根据我在资料中找到的,支持以下OBJ命令:

  • v 定义一个顶点坐标
  • vn 定义一个顶点法线
  • vt 定义了一个顶点纹理坐标
  • f 定义一个面(三角形或三角扇形)
  • o 定义了一个有名字的对象。

此外,如果 hashmark # 出现在行首(没有缩进),则会跳过空行并使用 cmets。

其他行,例如

  • mtllib 参考材料文件
  • usemtl从素材文件激活某个素材
  • g开群
  • s激活某个平滑组

似乎只是被忽略了。

考虑到这个插件是几何加载器,这似乎是合理的。


我还在 woboq 上看到了场景解析器的插件:

qt5/qt3d/src/plugins/sceneparsers/
+ assimp/
+ gltf/
+ gltfexport/

我用 Google 搜索了一下,但除了Open Asset Import Library, version 4.1.0 之外,找不到与我当前的 Qt 版本 5.13 直接相关的任何内容。

【讨论】:

    【解决方案3】:

    我建议您使用 Qt 3D 模块中的QMesh 来渲染复杂的 3D 文件。 Here 您可以找到有关如何将此类与 .stl 文件一起使用的示例,但是,如果您仔细阅读文档,您可以找到它使用 .obj 文件的部分。

    【讨论】:

    • .stl 完美搭配,.obj 仍有一些问题。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 2017-11-17
    相关资源
    最近更新 更多