Temporal Napisano 9 Grudzień 2014 Napisano 9 Grudzień 2014 Da sie w blenderze, tak jak w maxie zmirrorowac wagi z jednej strony na druga? Wiem, ze moge pokopiowac grupy i pozniej zrobic mirrora, ale chcialbym szybciej bez takich zabaw. Przyjmujemy ze tworzylem wagi bez wlaczonego mirror X, wiec malowalem wagi tylko po jednej stronie majac gdzies druga. Skonczlem cala lewa strone symetrycznego modelu i teraz chcialbym za pomoca jakies funkcji skopiowac to na prawa. Jest funkcja mirror ktora przerzuca nam z jednej strony na druga, co wiaze sie wlasnie z kopiowaniem wszystkich wag. Oczywiscie wszystkie kosci mam ponazywane wedlug schematu XXXX.L i XXXX.R
Monio Napisano 10 Grudzień 2014 Napisano 10 Grudzień 2014 (edytowane) Nie znalazłem takiej opcji, ani w standardzie ani w addonie. Dziwne, to musi być częsty problem. Za to mam trick który ci usprawni proces. Załóżmy że malowałeś Lewą stronę. 1. Zduplikuj obiekt gdzieś obok. 2. Na duplikacie odpal Mirror Weights z opcjami: All Groups i Flip names. Zmirroruje ci wszystkie wagi i przeniesie na grupy z Rką. Teraz tylko musisz połączyć grupy z obu obiektów. 3. Nadal na duplikacie. Kasujesz manualnie (niestety..) wszystkie grupy z Lką, bo je już masz namalowane na bazowym obiekcie. 4. Zaznaczasz duplikat a oryginał zaznaczasz jako ostatni (active). Odpalasz Transfer Weights z opcją Vertex Index. Przetestuj ten transfer. Możliwe że obejdzie się bez kasowania rzeczy. Nie wiem. Edytowane 10 Grudzień 2014 przez Monio
Zuorion Napisano 10 Grudzień 2014 Napisano 10 Grudzień 2014 lepszym sposobem chyba jest pomalować addem z sila 0(albo praktycznie 0) wszystko, tylko że tym razem z właczonym mirrorem jedną strone. Albo usunąć część modelu i dać ją modyfikatorem mirror.
Temporal Napisano 11 Grudzień 2014 Autor Napisano 11 Grudzień 2014 @Monio no nawet to jest jakis pomysl, dzieki. @Zuorion zerowa sila robi to, ze nic nie robi. Trzeba dac jakas minmalna wartosc ponad zero, w niektorych przypadkach dziala pieknie, w innym jakimims cudem drastycznie zmienia kolor/wage na obu stronach. Coz... chyba najlepiej jednak wyrobic sobie nawyk, by na starcie miec wlaczony mirror X i malowac/przypisywac wagi rownolegle na obu stronach.
Zuorion Napisano 11 Grudzień 2014 Napisano 11 Grudzień 2014 A zamiast Add 0, to moze Multiply z Weigh 1? Zrobiłem malutki test i nie zauważyłem artefaktów, a działało przenoszenie.
Monio Napisano 11 Grudzień 2014 Napisano 11 Grudzień 2014 Może i działa ale nie rozumiem jaki to ma sens. Temporal musiałby z osoba zaznaczyć każdą grupę i obmalować cały model. Nadal jest szansa na artefakty. Prościej zaznaczyć każdą grupę i dwoma klikami ją skopiować i zmirrorować. Można to jeszcze sobie przyśpieszyć n-razy z tym moim patentem z paru postów wyżej.
Temporal Napisano 12 Grudzień 2014 Autor Napisano 12 Grudzień 2014 Mysle ze ten trick Monio'a z duplikatem, chyba bedzie najbardziej efektywny. Najmniej kombinowania a efekt uzyskany.
alex3d Napisano 13 Grudzień 2014 Napisano 13 Grudzień 2014 Nawyk dobra rzecz, ale czasem trzeba jakoś wybrnąć, szkoda, że nie można tego w standardzie zrobić na wielu vertex grupach. Ten skrypt poniżej był niezły i powinien nadal działać w B 2.72. (o tyle fajny, że można wybrać oś lokalną) Źródło: http://blenderartists.org/forum/showthread.php?272153-Copy-and-Mirror-Weight-vertex Poza tym z tego co przeglądam moje zakładki odnośnie wag to był jeszcze płatny addon http://blog.machinimatrix.org/sparkles/smart-mirror-weight-copy/ z dodatkowym algorytmem, ale tego nie używałem nigdy, bo skrypt poniżej mi wystarczył. Testuj ostrożnie, ale powinien działać, wprowadzałem kiedyś jakieś modyfikacje w tym kodzie albo jego starszej wersji na własny użytek, ale nie mogę już odnaleźć pliku. import bpy, bmesh import datetime from bpy.props import * from bpy.types import Operator, Panel def copy_mirror_weight(Axis,Way,Pattern,special_pattern,left_side,right_side,tolerance): start = (datetime.datetime.now()) print('start') #items = [('4', '_l and _r', '4'),('3', '_L and _R', '3'),('2', '.l and .r', '2'),('1', '.L and .R', '1')]) L_side='' R_side='' ori_side='' dest_side='' if Pattern=='1': L_side='.L' R_side='.R' if Pattern=='2': L_side='.l' R_side='.r' if Pattern=='3': L_side='_L' R_side='_R' if Pattern=='4': L_side='_l' R_side='_r' if special_pattern==True: ori_side=left_side dest_side=right_side obj = bpy.context.active_object mesh = bpy.data.objects[obj.name].data.name x_multiply = 1 y_multiply = 1 z_multiply = 1 if Axis == 'X': axis_num = 0 x_multiply = -1 if Axis == 'Y': axis_num = 1 y_multiply = -1 if Axis == 'Z': axis_num = 2 z_multiply = -1 ## create the dict for the groups attache the index to the name DictGroup = {} ##ask the index it will give you the name DictGroupINV = {} ## ask the name, it will give you the index i=0 for group in bpy.context.active_object.vertex_groups: DictGroup[i]=group.name i+=1 for item in DictGroup: DictGroupINV[DictGroup[item]]=item #for each vertices of the mesh DictVertexOri = {} DictVertexDest = {} DictMirror = {} L_side_count = 0 R_side_count = 0 for vertex in bpy.data.meshes[mesh].vertices: #create the dicts for the good side #print (vertex.co[axis_num]) if (vertex.co[axis_num]>tolerance and Way=='normal') or (vertex.co[axis_num] DictVertexOri[vertex.index]=vertex.co #create the dicts for the mirror side if (vertex.co[axis_num]-tolerance and Way=='reverse'):#compare with the tolerance and position of the origin #print("MIRROR") DictVertexDest[vertex.index]=vertex.co for vertex in DictVertexOri: for groups in bpy.data.meshes[mesh].vertices[vertex].groups: #when it's the automatic pattern, it checks the most used on the original side .L or .R and assign them after if obj.vertex_groups[groups.group].name.find(L_side)>-1: L_side_count+=1 if obj.vertex_groups[groups.group].name.find(R_side)>-1: R_side_count+=1 if L_side_count>R_side_count and special_pattern==False: ori_side=L_side dest_side=R_side if R_side_count>L_side_count and special_pattern==False: ori_side=R_side dest_side=L_side vertexCoXOri = DictVertexOri[vertex][0] vertexCoYOri = DictVertexOri[vertex][1] vertexCoZOri = DictVertexOri[vertex][2] for vertexMirror in DictVertexDest: #check the coordinates of each axis, the multiply is inversing the mirror axes from -x.xxxx to x.xxxx so that the side doesn't matter if vertexCoXOri-tolerance if vertexCoYOri-tolerance if vertexCoZOri-tolerance DictMirror[vertex]=vertexMirror for vertex in DictMirror: myGroupVertex = {} myMirrorGroupVertex = {} for groups in bpy.data.meshes[mesh].vertices[vertex].groups: myGroupVertex[groups.group] = groups.weight #create a dictionary nameGroup = weight for OneGroup in myGroupVertex: #create a new dictionnary with the name mirror if obj.vertex_groups[OneGroup].name.find(ori_side)>-1: mirror_normal_group_name = obj.vertex_groups[OneGroup].name.replace(ori_side,dest_side) if mirror_normal_group_name in DictGroupINV: myMirrorGroupVertex[DictGroupINV[mirror_normal_group_name]] = myGroupVertex[OneGroup] else: #if this group doesn't exist yet add it to the group and the dictionnary length=len(DictGroup) bpy.context.active_object.vertex_groups.new(name=mirror_normal_group_name) DictGroup[length] = mirror_normal_group_name DictGroupINV[mirror_normal_group_name]=length if obj.vertex_groups[OneGroup].name.find(dest_side)>-1: mirror_normal_group_name = obj.vertex_groups[OneGroup].name.replace(dest_side,ori_side) if mirror_normal_group_name in DictGroupINV: myMirrorGroupVertex[DictGroupINV[mirror_normal_group_name]] = myGroupVertex[OneGroup] else: #if this group doesn't exist yet add it to the group and the dictionnary length=len(DictGroup) bpy.context.active_object.vertex_groups.new(name=mirror_normal_group_name) DictGroup[length] = mirror_normal_group_name DictGroupINV[mirror_normal_group_name]=length if obj.vertex_groups[OneGroup].name.find(ori_side)==-1 and obj.vertex_groups[OneGroup].name.find(dest_side)==-1: myMirrorGroupVertex[OneGroup] = myGroupVertex[OneGroup] ##remove the older group for group in bpy.data.meshes[mesh].vertices[DictMirror[vertex]].groups: print(DictGroup[group.group]) print(DictMirror[vertex]) obj.vertex_groups[DictGroup[group.group]].remove([DictMirror[vertex]]) #add the new ones for OneGroupVertex in myMirrorGroupVertex.keys(): obj.vertex_groups[DictGroup[OneGroupVertex]].add([DictMirror[vertex]],myMirrorGroupVertex[OneGroupVertex],'REPLACE') print('end') end = (datetime.datetime.now()) timing = end-start print(timing) def window_mirror(): class DialogOperator(bpy.types.Operator): bl_idname = "object.dialog_operator" bl_label = "Copy Mirror Weight - WARNING USE LOCAL AXES" enum_Axis = EnumProperty(name="On Which Axis?", default='X', items = [('Z', 'Z axis', 'Z'),('Y', 'Y axis', 'Y'),('X', 'X axis', 'X')]) enum_Way = EnumProperty(name="Which Way?", default='normal', items = [('reverse', '(-) to (+)', 'reverse'),('normal', '(+) to (-)', 'normal')]) enum_Pattern = EnumProperty(name="Which Pattern?", default='1', items = [('4', '_l and _r', '4'),('3', '_L and _R', '3'),('2', '.l and .r', '2'),('1', '.L and .R', '1')]) special_pattern = BoolProperty(name="or... Use my own patter") left_side = StringProperty(name="My own Patter, Left Side",default=".Left") right_side = StringProperty(name="My own Patter, Right Side",default=".Right") tolerance = FloatProperty(name="Tolerance", min=0, max=100, precision=3, default=0.001) def execute(self, context): copy_mirror_weight(self.enum_Axis,self.enum_Way,self.enum_Pattern,self.special_pattern,self.left_side,self.right_side,self.tolerance) return {'FINISHED'} def invoke(self, context, event): return context.window_manager.invoke_props_dialog(self) bpy.utils.register_class(DialogOperator) # Invoke the dialog when loading bpy.ops.object.dialog_operator('INVOKE_DEFAULT') window_mirror()
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się