顺序导入.obj文件变得非常快速

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了顺序导入.obj文件变得非常快速相关的知识,希望对你有一定的参考价值。

我编写了一个非常简单的脚本,逐个导入许多obj文件并呈现它们。导入的网格有~10k到~120k的顶点。渲染后,我会在导入下一个网格之前完全删除导入的网格(及其数据块)。但是,随着for循环的进行,导入过程变得非常慢。我注意到导入函数开始以奇怪的方式运行,导入对象需要花费大量时间。我不确定为什么会这样。最初我认为内存问题导致了这一点,但我认为删除数据块应解决内存泄漏问题。即使不对导入的对象进行任何渲染或任何操作,也会发生这种情况。以下是导入网格时导入功能打印的实例:

(  0.0002 sec |   0.0002 sec) Importing OBJ '/data/e1f2651d55aecd7d8f2b6fca0ec9a39dn7a9/models/model.obj'...
(  0.0308 sec |   0.0306 sec) Parsing OBJ file...
(  1.8534 sec |   1.8511 sec) Done, loading materials and images...
(  2.0450 sec |   2.0426 sec) Done, building geometries (verts:72707 faces:137005 materials: 44 smoothgroups:0) ...
(  5.4944 sec |   5.4921 sec) Done.
(  5.4946 sec |   5.4945 sec) Finished importing: 'data/e1f2651d55aecd7d8f2b6fca0ec9a39dn7a9/models/model.obj'
Progress: 100.00%

随着导入更多对象,导入函数的行为越来越慢,即使对于更简单的形状(例如~12k顶点),您将得到如下内容:

(  0.0002 sec |   0.0002 sec) Importing OBJ '/data/jjgd2e3f46f7cc1e8ba69a5e14689f7b974/models/model.obj'...
  (  0.0266 sec |   0.0263 sec) Parsing OBJ file...
    (  0.7060 sec |   0.6793 sec) Done, loading materials and images...
    (  3.0993 sec |   3.0726 sec) Done, building geometries (verts:12668 faces:43914 materials: 28 smoothgroups:0) ...
    ( 18.6672 sec |  18.6405 sec) Done.
  ( 18.6673 sec |  18.6671 sec) Finished importing: '/data/jjgd2e3f46f7cc1e8ba69a5e14689f7b974/models/model.obj'
Progress: 100.00%

但是,如果首先导入具有~12k顶点的相同对象,我得到如下内容:

(  0.0001 sec |   0.0001 sec) Importing OBJ '/data/jjgd2e3f46f7cc1e8ba69a5e14689f7b974/models/model.obj'...
  (  0.0025 sec |   0.0023 sec) Parsing OBJ file...
    (  0.5541 sec |   0.5516 sec) Done, loading materials and images...
    (  0.5572 sec |   0.5547 sec) Done, building geometries (verts:12668 faces:43914 materials: 28 smoothgroups:0) ...
    (  1.0660 sec |   1.0635 sec) Done.
  (  1.0663 sec |   1.0662 sec) Finished importing: '/data/jjgd2e3f46f7cc1e8ba69a5e14689f7b974/models/model.obj'
Progress: 100.00%

这是我的代码:

#blenderClass.py
import bpy, math, timeit
import numpy as np

class Blender(object):
    def __init__(self):
        self.bpy = bpy
        self.scene = self.bpy.context.scene
        self.scene.render.use_sequencer = False

        # Some memory management
        self.scene.render.use_free_image_textures = True
        self.bpy.context.user_preferences.edit.undo_steps = 0
        self.bpy.context.user_preferences.edit.undo_memory_limit = 60
        self.bpy.context.user_preferences.edit.use_global_undo = False

    def setupScene(self):
        self.removeCamera()
        self.removeMesh()
        self.bpy.ops.object.camera_add(location=tuple(1, -0.5, 0.3))
        self.pointObjTo(self.scene.objects.active, (0.0, 0.0, 0.0)) # My objects are all centered on (0, 0, 0)

    def render(self, objPath):
        self.bpy.ops.import_scene.obj(filepath=objPath)
        self.removeMesh()
        self.removeDataBlocks()


    def removeDataBlocks(self, removeAll=False):
        # Removes unlinked data blocks and prevents memory leakage

        for block in self.bpy.data.meshes:
            if block.users == 0:
                self.bpy.data.meshes.remove(block)

        for block in self.bpy.data.materials:
            if block.users == 0:
                self.bpy.data.materials.remove(block)

        for block in self.bpy.data.textures:
            if block.users == 0:
                self.bpy.data.textures.remove(block)

        for block in self.bpy.data.images:
            if block.users == 0:
                self.bpy.data.images.remove(block)


    def removeMesh(self, layer = -1):
        for obj in self.scene.objects:
            if obj.type == 'MESH':
                obj.select = True
            else:
                obj.select = False
        self.bpy.ops.object.delete()


    def removeCamera(self):
        for obj in self.scene.objects:
            if obj.type == 'CAMERA':
                obj.select = True
            else:
                obj.select = False
        self.bpy.ops.object.delete()


    def pointObjTo(self, obj, xyzTarget):
        # This function operates directly on the input object (obj)
        from mathutils import Vector
        xyzTarget = Vector(xyzTarget)
        direction = xyzTarget - obj.location
        rot_quat = direction.to_track_quat('-Z', 'Y')
        obj.rotation_euler = rot_quat.to_euler()

这就是我运行代码的方式:

#main.py
import blenderClass import Blender
blender = Blender()
blender.setupScene()

objPaths = ['obj1.obj', 'obj2.obj', 'obj3.obj', 'obj4.obj']

for objPath in objPaths:
    blender.render(objPath)

不幸的是我无法以精确的方式监视系统资源(我在服务器上运行它)但我担心导入功能不会释放一些资源或者某种程度上内存被填满。我尝试在桌面计算机中将许多形状导入Blender,并在手动删除网格后执行数据块删除功能。我的猜测是,当我导入许多3D形状时,即使它是400MB,也可以将内存消耗降低到10MB左右。如果你想尝试上面的代码,也许一个简单的解决方案是使用原始形状,如球体,立方体等,并细分它们,使它们有很多顶点(可能~50-70k)并将它们存储为obj。我认为有大约10-15个obj文件应该可以工作。在为我导入第3个或第4个对象后,事情开始变得很慢。

我不确定这是否相关,但我称之为Blender函数的方式不是通过在background中调用它。相反,我手动编译Blender 2.79作为Python模块,并通过我机器上安装的Python中的import bpy导入其API。

虽然我相当确定删除数据块会释放内存,但我也尝试使用Python的垃圾收集器,但它没有帮助。

有谁知道我做错了什么?我很迷茫 ...

答案

虽然很奇怪,但是如果我不导入带有标志的对象,看起来导入函数会做一些导致长时间运行缓慢的东西。因此,使用以下内容替换obj导入行将解决此问题:

self.bpy.ops.import_scene.obj(filepath=objPath, split_mode="OFF")

但是我宁愿输入不相交的对象,但这解决了导入减速问题。感谢doublebishop对blenderartists。

以上是关于顺序导入.obj文件变得非常快速的主要内容,如果未能解决你的问题,请参考以下文章

模块简介模块的两种导入语句导入文件的补充判断文件类型模块的查找顺序

Python 快速检测配置文件是不是变更

mybatis框架快速入门

如何将 obj 和 mtl 文件导入到 three.js

html 将以编程方式附加外部脚本文件的javascript代码片段,并按顺序排列。用于响应式网站,其中ma

如何用Babylon.js导入一个.obj模型