Как получить данные и отредактировать их по краям UV-карты? - PullRequest
1 голос
/ 17 марта 2020

У меня есть УФ-карта: enter image description here

Я хочу получить пиксели текстуры вокруг связанных со мной sh сторон, как это (выделено красным): enter image description here

Как это сделать с Python Blender API?

1 Ответ

2 голосов
/ 24 марта 2020

Сделать "УФ" bme sh

enter image description here

Учитывая объект me sh выше с УФ, сделайте bme sh из кругов

  • l oop face
  • l oop face loop, добавьте вертолет в новый bme sh at uv.x, uv.y, 0
  • создать грань из вершин
  • удалить дубликаты
  • (опционально) растворить неграничные ребра
  • (опционально) удалить грани.
  • добавили Целочисленный слой для вершин и граней с индексом оригинальных вершин и граней.

Тестовый скрипт, запускаемый в объектном режиме

import bpy
import bmesh

context = bpy.context
ob = context.object
me = ob.data
bm = bmesh.new()
bm.from_mesh(me)
uvbm = bmesh.new()

uv_layer = bm.loops.layers.uv.verify()
vert_index = uvbm.verts.layers.int.new("index")
face_index = uvbm.faces.layers.int.new("index")
# adjust uv coordinates
for face in bm.faces:
    fverts = []
    for loop in face.loops:
        uv = loop[uv_layer].uv
        v = uvbm.verts.new((uv.x, uv.y, 0))
        v[vert_index] = loop.vert.index
        fverts.append(v)
    f = bmesh.ops.contextual_create(uvbm, geom=fverts)["faces"].pop()
    f[face_index] = face.index

# remove doubles

bmesh.ops.remove_doubles(uvbm, verts=uvbm.verts, dist=1e-7)

'''

# ignore face indices of original if using any option here
# optionally disolve non boundary edges

bmesh.ops.dissolve_edges(uvbm, 
        edges=[e for e in uvbm.edges if not e.is_boundary],
        )


# optionally remove faces

faces = uvbm.faces[:]
while faces:
    uvbm.faces.remove(faces.pop())
'''        
#make an object to see it
me = bpy.data.meshes.new("UVEdgeMesh")
uvbm.to_mesh(me)
ob = bpy.data.objects.new("UVEdgeMesh", me)
bpy.context.collection.objects.link(ob)
ob.show_wire = True


# make a LUT based on verts of original
from collections import defaultdict

edge_pairs = defaultdict(list)
boundary_edges = [e for e in uvbm.edges if e.is_boundary]

for e in boundary_edges:
    key = tuple(sorted(v[vert_index] for v in e.verts))
    edge_pairs[key].append(e)

# print result, add text object to show matching edges
# Make sure to remove code below before running on detailed UV as in question, 
# adding that many text objects via operator 
# will slow code down considerably.

uvbm.verts.ensure_lookup_table()
for key, edges in edge_pairs.items():

    print(key, [e.index for e in edges]) 

    for e in edges:
        if not e.is_boundary:
            continue
        f = e.link_faces[0]
        p = (e.verts[0].co + e.verts[1].co) / 2
        p += (f.calc_center_median() - p) / 4
        bpy.ops.object.text_add(radius=0.04, location=p)
        bpy.context.object.data.body = f"{key}"

Создает bme sh, здесь он преобразуется в me sh

enter image description here

Координаты xy для "UV" bme sh являются координатами UV. Единственными ребрами являются ультрафиолетовые граничные ребра. Преобразовать в пиксельные координаты, используя данные.

Использует здесь метод, чтобы связать вершины с оригиналом, используя метод здесь https://blender.stackexchange.com/a/70729/15543 для хранения индексов исходных вершин / ребер в слое данных "UV" bme sh.

Вывод на примере выше. Первый ряд, два ребра, которые сделаны из вершин 0 и 1 из оригинального me sh, являются ребрами 0 и 14 в "UV" bme sh.

(0, 1) [0, 14]
(0, 2) [1, 17]
(2, 3) [2, 4]
(1, 3) [3, 22]
(2, 6) [5, 16]
(6, 7) [6, 8]
(3, 7) [7, 23]
(4, 6) [9, 19]
(4, 5) [10, 12]
(5, 7) [11, 20]
(0, 4) [13, 18]
(1, 5) [15, 21]

EDIT: Чтобы визуализировать это дальше, добавили текстовый объект к каждому лицу от каждого края. Например, посмотрите, где ребро из вершин (i, j) совпадает на двух гранях. Каждый текстовый объект расположен на одной четверти пути от центра края к центру лица.

enter image description here В качестве альтернативы можно просто напечатать исходные индексы вершин в вершинах

Помните, что uvbme sh находится в UV-координатах, отображенных в диапазоне действительных чисел [0, 1] в U и V. Пиксельные координаты просто отображают это в дискретный целочисленный диапазон на основе размера изображения.

...