顺序导入 .obj 文件很快就会变得非常慢
Sequentially importing .obj files becomes drastically slow very quickly
我写了一个非常简单的脚本,一个一个地导入许多 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)
不幸的是,我无法以精确的方式监控系统资源(我在服务器上 运行ning 这个)但我担心导入功能不会释放某些资源或不知何故内存越来越满。我尝试在我的台式计算机上将许多形状导入 Blender,并在手动删除网格后执行数据块删除功能。我的猜测是这样做可以将内存消耗减少到 10MB 左右,即使当我导入许多 3D 形状时它是 400MB。如果你想尝试上面的代码,也许一个简单的解决方案是使用基本形状,如球体、立方体等,然后 细分 它们,这样它们就会有很多顶点(也许 ~ 50-70k) 并将它们存储为 obj.我认为拥有大约 10-15 个 obj 文件应该可行。为我导入第 3 个或第 4 个对象后,事情开始变慢。
我不确定这是否相关,但我调用 Blender 函数的方式不是在 background 中调用它。相反,我手动将 Blender 2.79 编译为 Python 模块,并通过 import bpy
在我机器上安装的 Python 中导入它的 API。
虽然我相当确定删除数据块可以释放内存,但我也尝试过使用 Python 的垃圾收集器,但它没有帮助。
有谁知道我可能做错了什么?我很困惑...
虽然很奇怪,但如果我不导入带有标志的对象,导入函数看起来会导致长时间 运行 速度变慢。因此,用以下内容替换 obj 导入行将解决问题:
self.bpy.ops.import_scene.obj(filepath=objPath, split_mode="OFF")
不过我更愿意输入不相交的对象,但这暂时解决了导入速度变慢的问题。感谢 blenderartists 上的 doublebishop
。
我写了一个非常简单的脚本,一个一个地导入许多 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)
不幸的是,我无法以精确的方式监控系统资源(我在服务器上 运行ning 这个)但我担心导入功能不会释放某些资源或不知何故内存越来越满。我尝试在我的台式计算机上将许多形状导入 Blender,并在手动删除网格后执行数据块删除功能。我的猜测是这样做可以将内存消耗减少到 10MB 左右,即使当我导入许多 3D 形状时它是 400MB。如果你想尝试上面的代码,也许一个简单的解决方案是使用基本形状,如球体、立方体等,然后 细分 它们,这样它们就会有很多顶点(也许 ~ 50-70k) 并将它们存储为 obj.我认为拥有大约 10-15 个 obj 文件应该可行。为我导入第 3 个或第 4 个对象后,事情开始变慢。
我不确定这是否相关,但我调用 Blender 函数的方式不是在 background 中调用它。相反,我手动将 Blender 2.79 编译为 Python 模块,并通过 import bpy
在我机器上安装的 Python 中导入它的 API。
虽然我相当确定删除数据块可以释放内存,但我也尝试过使用 Python 的垃圾收集器,但它没有帮助。
有谁知道我可能做错了什么?我很困惑...
虽然很奇怪,但如果我不导入带有标志的对象,导入函数看起来会导致长时间 运行 速度变慢。因此,用以下内容替换 obj 导入行将解决问题:
self.bpy.ops.import_scene.obj(filepath=objPath, split_mode="OFF")
不过我更愿意输入不相交的对象,但这暂时解决了导入速度变慢的问题。感谢 blenderartists 上的 doublebishop
。