1

我正在编写一个自定义导出脚本来解析搅拌机文件中的所有对象,按名称过滤它们,然后检查以确保它们符合某些特定条件。

我正在使用搅拌机 2.68a。我创建了一个带有一些基本 2d 和 3d 网格的搅拌机文件,以及一些不符合我的测试标准的文件。我在 Blender 的内部 Python 控制台中工作。这是使用 blender python API 的唯一方法,因为它们的 python 环境是定制的。

我已经排序了如何使用 for 循环和 D.objects 迭代器遍历对象,然后使用正则表达式检查名称匹配,然后使用以下方法从对象中获取网格:

mesh = obj.to_mesh(C.scene, True, 'RENDER') #where obj is an bpy.data.object[index] in the scene
mesh.update(True, True) 
mesh.polygons[index].<long list of possible functions>

让我访问一个多边形数组,以了解是否存在一组带有形成多边形的边的顶点,以及它们的键值是什么。

我无法解决的是如何从 python 控制台确定一个多边形是一张脸还是一个多边形。是否有内置功能,或者我可以执行哪些测试来以编程方式确定这一点?例如,我可以有一个网格 4 个顶点和 4 个没有面的边,我不想导出它,但是如果我要编辑相同的 4 个顶点/边并在上面放置一个面,那么它成为理想的出口。

谁能解释 bpy.data.object 数据结构或解释“面孔”的存储位置?似乎这将是 npolys 本身的属性,但 API 并没有使其显而易见。任何澄清这一点的帮助将不胜感激。干杯。

4

1 回答 1

2

所以,我在 blender.org 论坛上问了这个问题,http://www.blender.org/forum/viewtopic.php? t=28286&postdays=0&postorder=asc&start=0一个非常乐于助人的人在过去的几次中帮助了我每次我都陷入自己的努力来克服这个问题。

简短的答案列表是:

1)所有多边形都是面。如果它不存储为多边形,则它不是面。
2) 在对象上使用 to_mesh() 函数会返回该函数的副本,因此对副本所做的任何选择都不会反映在上下文中,因此我使用的方法有缺陷。访问活动对象的唯一方法是使用:

bpy.data.objects[<index or object name>].data.vertices[<index>].co[<0,1,2> which correspond to x,y,z respectively]  
bpy.data.objects[<index or object name>].data.polygons[<index>].edge_keys  

第一个使您可以访问对象中所有顶点的有序索引(假设它是“MESH”类型)及其坐标。
第二个使您可以访问表示边的有序对的二维数组。它包含在元组中的数字对应于第一个命令中顶点列表中的索引值,因此您可以获得边缘之间的坐标。也可以创建一个新的 BMesh 对象并将您感兴趣的对象复制到 BMesh 中。这为您提供了更多无法在活动对象上访问的功能。答案 3 中的代码显示了一个示例。

3)请参阅下文以回答我关于检查网格中的面的问题。

事实证明,确定对象是否具有面并且所有边都是面的一部分的一种方法是使用由有用的用户 CoDEmanX 在上述线程上编写的以下代码片段。

import bpy, bmesh 

for ob in bpy.context.scene.objects: 
    if ob.type != 'MESH': 
        continue
    bm = bmesh.new() 
    bm.from_object(ob, bpy.context.scene) 

    if len(bm.faces) > 0 and 0 not in (len(e.link_faces) for e in bm.edges): 
        print(ob.name, "is valid") 
    else: 
        print(ob.name, "has errors") 

我稍微改变了一点,因为我不希望它循环遍历所有对象,而是将它作为一个函数,如果传入的对象有效,则返回 true,否则返回 false。这让我可以序列化我的调用,以便我的插件只尝试验证名称与正则表达式匹配的对象。

def validate(obj):
    import bpy, bmesh 

    if obj.type == 'MESH':                
        bm = bmesh.new() 
        bm.from_object(obj, bpy.context.scene) 

        if len(bm.faces) > 0 and 0 not in (len(e.link_faces) for e in bm.edges): 
            return True
    return False
于 2013-10-01T14:52:47.153 回答