1. Пользоваться форумом на планшетах и телефонах стало удобнее благодаря Tapatalk

Найти Разницу Между Гранями(моделей)

Тема в разделе "Общие вопросы", создана пользователем LighFusion, 1 авг 2015.

Модераторы: Артер
  1. LighFusion

    LighFusion Пользователь сайта

    С нами с:
    27.12.2014
    Сообщения:
    13
    Симпатии:
    0
    Баллы:
    2
    Приветствую, очень интересует возможно ли найти разницу между границами двух моделей.
    Красной линией отмечена сочетание граней - черной модели, с белой,
    http://i.imgur.com/7qNojYS.png?2, это грудь модели http://i.imgur.com/8LN8hfG.png?1 , и изначально черная модель выходила за грани белой модели, http://i.imgur.com/Yyb8vOC.png?1, и мне пришлось вручную - при помощи манипуляций Кости(Груди)Передвинуть/подогнать(На глаз) ее на положение граней белой модели, т.к. общая форма черной модели должна соотвествовать белой.
    Вопрос в том как - можно вычислить эту разницу(И через что), если она имеется, между 1 моделью и 2 моделью, и ввести полученное значение в XYZ Кости, по сути автоматизировать все те манипуляции которые делаются "на глаз".

    Надеюсь более мене подробно описал ?Прошу сильно не закидывать ....
     
  2. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Вы можете попробовать это сделать с помощью MaxScript.
    То есть, с помощью способа проб и ошибок, скрипт будет выполнять подгонку одной модели к другой.
    Чем больше будет количество проб, тем больше потребуется времени и тем точнее будет результат.
    Каким способом вы передвигали Кость (Груди)? Вы использовали инструмент Select and Move?
    Кость-груди имеет родителя в виде кости?
    Какие именно манипуляции вы совершали над кости-груди: передвигание, вращение, масштабирование?
    Почему вы хотите автоматизировать эти манипуляции? Вы тратите много времени на эти манипуляции? Вас не устраивает полученный результат?
     
  3. LighFusion

    LighFusion Пользователь сайта

    С нами с:
    27.12.2014
    Сообщения:
    13
    Симпатии:
    0
    Баллы:
    2
    Если через MaxScript то с чем именно ?

    Кость Груди - я масштабировал по Y Координат.

    Автоматизировать я хочу потому что другого варианта особо нету, поскольку моделей где-то около 100, и подогнать их надо к 1ой единственной, в ручную это очень долго может занять(+ не точность, может возникнуть).
     
  4. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Вы масштабировали Кость Груди в мировой или локальной системе координат?
    Для вас обязательно масштабировать кость, а не саму модель?
    Допустим, что у нас есть 2 модели без костей.
    Объясните подробно ваш алгоритм подгонки одной модели к другой с помощью Scale.
    Вас устраивает как работает скрипт RealSizeTB?

    Попробуйте сначала объяснить алгоритм для простого примера.
    В новой сцене в начале координат создаем одну сферу и один чайник.
    Выравниваем центр Body чайника к Pivot-у чайника.
    Устанавливаем для сферы и чайника одинаковый радиус, например 20.
    Конвертируем сферу и чайник в Editable Poly.
    Масштабируем сферу по оси X на 200%.

    Теперь нужно подогнать Body чайника под размер "сферы" по оси X.
    Запускаем скрипт RealSizeTB.
    Выделяем полигоны Body чайника и прячем остальные полигоны.
    Выделяем "сферу" и копируем её размер по оси X.
    Выделяем чайник и вставляем размер сферы по оси X.
    Показываем все полигоны чайника.

     
  5. LighFusion

    LighFusion Пользователь сайта

    С нами с:
    27.12.2014
    Сообщения:
    13
    Симпатии:
    0
    Баллы:
    2
    В вашем примере - в принципе так оно и нужно, только с поправкой на то что модель масштабировать необходимо через кость.
    Я записал пример этого всего на видео

    Сам метод работает через Bounding Box, возможно ли это решить как то иначе ? получив значение положения XYZ, самой дальней вершины(по ОСИ ХYZ) относительно центра, поскольку с bounding box, возникает проблема т.к. некоторые части второй модели(К примеру Ноги) не имеются у первой модели, и ввиду этого Bounding Box первой заходит за рамки - и дальнейшее вычисление становиться неправильным. Ну и на сколько я понял те значения - которые получаются при вычитании BBox1-BBox2=x, нужно приумножать на 10, т.е. 5.6*10=56, и масштабировать именно по оси X, а не по всем сторонам.
     
  6. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Вы можете мне предоставить пару ваших моделей с костями, чтобы я смог тестировать скрипт?
    Если да, тогда сохраните для 3d max 2010.
    Если нет, тогда я продолжу задавать вопросы:
    Кость всегда находится в центре модели по оси X?
    Спасибо что качество видео не 240p.
    Сохраняйте видеo с качеством 720p, если есть возможность.
    Значение дальней вершины вы получаете так: b.max
    Значение центра можно получить так: b.center
    Значение дальней вершины относительно центра будет так: b.max-b.center
    Вас устраивает такое значение?
    Мне интересно узнать, как вы поняли, что нужно приумножать на 10.
    Может быть нужно приумножать на 9 или 11?
    Может быть нужно приумножать на 100/(BBox1/2)=100/(19,7802/2)=100/9,8901=10,1111?
     
  7. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Я написал скрипт для вашего простого примера с боксами и кости.
    Проверьте если скрипт работает правильно.
    Теперь объясните алгоритм для сложного примера.
    Код:
    try destroydialog igorznag_adjust_scale catch()
    rollout igorznag_adjust_scale "Adjust Scale X"
    (
    fn gemetry_filt obj = superclassof obj == GeometryClass and classof obj != BoneGeometry
    fn bone_filt obj = classof obj == BoneGeometry
    pickbutton pb_master "Pick Master Object" filter:gemetry_filt width:100
    pickbutton pb_slave "Pick Slave Object" filter:gemetry_filt width:100
    pickbutton pb_bone "Pick Bone Object"filter:bone_filt width:100
    button btn_apply "Apply";
    on pb_master picked obj do pb_master.caption=obj.name
    on pb_slave picked obj do pb_slave.caption=obj.name
    on pb_bone picked obj do pb_bone.caption=obj.name  
    on btn_apply pressed do
    (
        master_obj=pb_master.object;slave_obj=pb_slave.object;bone_obj=pb_bone.object;
        if isvalidnode master_obj and  isvalidnode slave_obj and  isvalidnode bone_obj then
        (
            if master_obj!=slave_obj then
            (
                bone_obj.scale=[1,1,1]
                master_offset=master_obj.max.x-bone_obj.pos.x
                slave_offset=slave_obj.max.x-bone_obj.pos.x
                offset_x=1.0*master_offset/slave_offset
                undo on (scale bone_obj [offset_x,1,1])
            )--if master_obj!=slave_obj then
        )--if isvalidnode master_obj a
    )--on btn_apply pressed do
    ); createdialog igorznag_adjust_scale
     
  8. LighFusion

    LighFusion Пользователь сайта

    С нами с:
    27.12.2014
    Сообщения:
    13
    Симпатии:
    0
    Баллы:
    2
    Спасибо огромное, будет с чего начать !
    Пример сцены https://mega.co.nz/#!10Jk0byJ!Ef60M4LgYPuOP460jSL22dE36044tJOjkaM0sBa2jlw и внутри модели в FBX
    Вся сложность, заключается в том что форма моделей, более специфична(ввиду того что это тело), ии загвоздка в том чтобы постепенно от первой кости - которая к примеру контролирует таз - Bip01Pelvis, производить манипуляции через скрипт(предварительно отключив иерархию, дочерних костей Bip01Pelvis), и после успешной манипуляции(подгонки модели 1 под модель 2), продолжить тот же процесс костью которая идет выше Bip01Pelvis, то есть Bip01Spine(В примере сцены это видно).

    И еще один возможный нюанс, связан с те что кость возможно необходимо предварительно сдвинуть по одной из ОСИ XYZ, ввиду того что у сложных моделей(как в сцене- с телами) кости задействуют не половину модели(Как в примере с Боксом)а всю часть туловища/спины/шеи/живота и тд. По сему - возникает вопрос, возможно ли манипулировать таким образом чтобы вначале передвинуть По ОСИ XYZ модель 1, на грань модели 2 и далее сделать уже масштабирование по XYZ(Я думаю я смогу записать пример на видео, используя тот скрипт что вы мне дали, уже с более подобным примером), не ручаюсь что будет 720, не пойму точно почему видео портиться, но возможно исправлю.
    Спасибо еще раз что дали такой обширный ответ, я уж думал подобное не кому не будет интересно =) .
     
  9. LighFusion

    LighFusion Пользователь сайта

    С нами с:
    27.12.2014
    Сообщения:
    13
    Симпатии:
    0
    Баллы:
    2
    Небольшой - Апдейт !
    - несколько дней провозился( -- Off с этой погодой нереально настроиться...), но так и не смог решить основную загвоздку - более сложные модели - у которых вершины весов - образуют сложную модель, разница Bounding Box'ov, а точнее офсет - который между ними получается, как значение, не дает точного результата при массштабировании кости по оси X. Я записал весь процесс на видео.


    Есть еще одна загвоздка(точнее это вся та же проблема) - опять же связанна с более сложной структурой скиннинга(у сложных моделей - типа тел) - скрипт массштабирует гораздо больше чем нужно, выходя за рамки, и опять же - непонятно какова идея этого кода
    master_obj.max.x-bone_obj.pos.x
    1.0*master_offset/slave_offset

     
  10. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Давайте я попробую решить эту загвозку.
    Я понял, что вам нужно, но не понял полностью как вы вручную это делаете на глаз.
    Больше не нужно объяснять алгоритм с помощью цифр.
    Давайте вы будете усложнять простой пример с боксами, а я попробую написать соответствующий скрипт.
    Вы будете объяснять как вы делаете подгонку боксов вручную на глаз.
    Может быть с 10 раза получиться написать подходящий скрипт.
    Я написал скрипт для случая с боксами, который у вас на видео.
    Код:
    try destroydialog igorznag_adjust_scale catch()
    rollout igorznag_adjust_scale "2 Adjust Scale X"
    (
    fn gemetry_filt obj = superclassof obj == GeometryClass and classof obj != BoneGeometry
    fn bone_filt obj = classof obj == BoneGeometry
    pickbutton pb_master "Pick Master Object" filter:gemetry_filt width:100
    pickbutton pb_slave "Pick Slave Object" filter:gemetry_filt width:100
    pickbutton pb_bone "Pick Bone Object" width:100 filter:bone_filt
    button btn_apply "Apply";
    on pb_master picked obj do pb_master.caption=obj.name
    on pb_slave picked obj do pb_slave.caption=obj.name
    on pb_bone picked obj do pb_bone.caption=obj.name 
    on btn_apply pressed do
    (
        master_obj=pb_master.object;slave_obj=pb_slave.object;bone_obj=pb_bone.object;
        if isvalidnode master_obj and  isvalidnode slave_obj and  isvalidnode bone_obj then
        (
            if master_obj!=slave_obj then
            (
                master_length_x=master_obj.max.x-master_obj.min.x
                slave_length_x=slave_obj.max.x-slave_obj.min.x
                rescale_x=1.0*master_length_x/slave_length_x
                undo on
                (
                    scale bone_obj [rescale_x,1,1]
                    bone_obj.pos.x+=master_obj.center.x-slave_obj.center.x
                )
            )--if master_obj!=slave_obj then
        )--if isvalidnode master_obj a
    )--on btn_apply pressed do
    ); createdialog igorznag_adjust_scale
     
  11. LighFusion

    LighFusion Пользователь сайта

    С нами с:
    27.12.2014
    Сообщения:
    13
    Симпатии:
    0
    Баллы:
    2
    Попытался немного подробнее объяснить на боксах, в чем заключается проблема


    Пробовал новый скрипт, толи я что-то не так делаю, толи он немного под другое настроен, но результат не тот, ввиду того что Master Object меньше чем Slave Object, а Scale( с примером от боксов) заточен наоборот, что Master Object больше а Slae Object Меньше.
     
  12. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Нет никакой проблемы. Я прекрасно понял, что вам нужно.
    Я же просил, чтобы вы не объясняли мне эти цифры.
    Вам не надоели эти цифры?

    5,39 оригинальный размер белой брони
    1,37 это длина - которой не достает до черной брони
    если просто сложить 5,39+1,37=6,76 и это в принципе дает нужный результат

    Чтобы это отразить в масштабировании через кость, нужно разделить длину черной брони на длину белой брони.
    6,76/5,39=1,25
    Это можно увидеть в коде последнего скрипта.

    Если взять примерно такой же отрезок и прикрепить его к кости, значение 1,37 для масштабирования не будет давать нужного результата.
    А правильным резултатом будет 6,76/5,39=1,25
    Разница 1,37-1,25=0,12 не имеет никакого смысла и она никому не нужна.

    То есть, если сделать Бокс-Master меньше чем Бокс-Slave, тогда последний скрипт работает неправильно?
    Давайте сначала разберемся с боксами, а потом перейдем к брони.
     
  13. LighFusion

    LighFusion Пользователь сайта

    С нами с:
    27.12.2014
    Сообщения:
    13
    Симпатии:
    0
    Баллы:
    2
    Так спасибо еще раз теперь я понял всю суть и зачем / Делить, в принципе скрипт работает на отлично, еще раз спасибо!
    Но проблема основная проблема от этого не решается, подгонка брони через скрипт(автоматически) все еще далека от того что требуется.
    В первую очередь остается загкозвдка с тем чтобы расположить на панели скрипта, своего рода иерархию скелета
    примерно подобным образом
    Код:
                                    Upper | Body
             
                     Left Arm <=       |Neck|        =>Right Arm
                                          |
                                       Spine2
                                          |
                                       Spine1
                                          |
                                       Spine
                                          |
                              <=     Bip01Pelvis     =>
                      Left Leg                |           Right Leg
    
                                                    |        
                                                    |        
                                                    |         
                      Left Calf                |           Right Calf
                                                    |        
                                                    |        
                                                    |        
                      Left Foot                |           Right Foot
    Наверное примерно как в Motion Builder(там примерно такое же есть), но я не уверен стоит ли создавать кнопки Pick(выбора)(чтобы установить скелет из сцены), либо сделать обычные button и устанавливать кости по имени(как они есть, для каждой кнопки.
    Ну и самое основное тут - ползунки/кнопки По Передвижению/Врашению - костей, в процентом соотношении, то есть 1-3% это 101-103, 10% это 110 для массштабирования, для scale -3% от начальной величины 90 - будет 87.
    Я конечно возможно предлагаю не самый умный способ, может он и тупой(буду очень рад если получиться что-то сделать по серьезнее) не прибегая к таким способам, но этот способ - так сказать, напролом ! Он должен повторять то что я делаю в ручную(Подгонку), одной брони к другой.
    Но вернусь я обратно к этой тулзе, необходимо чтобы весь этот процесс был более менее автоматичен, то есть к примеру сначало идет смешение bip01Pelvis, в зависимости от Lenght Obj1/Obj2, далее идет небольшое массштабирование Bip01Pelvis, и если нужно Врашение по Y, вот тут я не очень понимаю, задать это на глаз(то есть с CheckBox изначально) либо как это отмерять требуется ли наклон брони или нет., ну а далее примерно тоже самое но уже с теми костями которые идут выше, а потом уже руки и ноги.
     
    Последнее редактирование: 9 авг 2015
  14. LighFusion

    LighFusion Пользователь сайта

    С нами с:
    27.12.2014
    Сообщения:
    13
    Симпатии:
    0
    Баллы:
    2
    Вообще основная загвоздка в том чтобы - скрывать нужные части тела(Брони), руки,ноги, чтоб к примеру был виден только пояс, как это возможно сделать через скрипт, чтобы уже потом можно было его применять.
     
    Последнее редактирование: 9 авг 2015
  15. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Видео пример.
    Для объекта Slave можно сделать так: Выделяем нужную кость.
    Запускаем скрипт. В новом окне нажимаем кнопку "Show Selected Bone".
    Код:
    try destroydialog show_hide_by_bone catch()
    rollout show_hide_by_bone "Bone Geometry"
    (
        button btn_show_selected_bone "Show Selected Bone"
        button btn_hide_all "Hide All Geometry"
        button btn_show_all "Show All Geometry"
        on btn_show_selected_bone pressed do
        (
            undo on
        (
            if selection.count==1 then
            (
                bone_obj=selection[1]
                if classof bone_obj==BoneGeometry then
                (
                    bones_identic_name=getNodeByName bone_obj.name all:true
                    if bones_identic_name.count==1 then
                    (
                        old_selection=selection as array
                        for obj in objects do
                        (
                            skin_m=undefined
                            if obj.modifiers.count==1 then
                            (if classof obj.modifiers[1]==skin then skin_m=obj.modifiers[1])
                            if obj.modifiers.count==2 then
                            (
                                if classof obj.modifiers[2]==skin and obj.modifiers[1].name=="igorznag_bone_show" then 
                                skin_m=obj.modifiers[2]
                            )--if obj.modifiers.count==2 then
                            if skin_m!=undefined then
                            (
                                select obj
                                if obj.modifiers.count==1 then 
                                (
                                    m=Edit_Poly(); m.name="igorznag_bone_show"
                                    modPanel.addModToSelection  m
                                )--if obj.modifiers.count==1 then 
                                skin_m=obj.modifiers[2]
                                max modify mode
                                modPanel.setCurrentObject skin_m
                               
                                nv = skinOps.GetNumberVertices skin_m
                                vert_a=#()
                                for i = 1 to nv do
                                (
                                    nw = skinOps.GetVertexWeightCount skin_m i
                                    for j=1 to nw do
                                    (
                                        BoneID = skinOps.GetVertexWeightBoneID skin_m i j
                                        Weight = skinOps.GetVertexWeight skin_m i j
                                        if Weight> 0 then
                                        (
                                            bsid=skinOps.GetVertexWeightBoneID skin_m i j
                                            bn=skinOps.GetBoneName skin_m bsid 0
                                            if bn==bone_obj.name then append  vert_a i
                                        )--if Weight> 0 then
                                    )--for j=1 to nw do
                                )--for i = 1 to nv do
                               
                                modPanel.setCurrentObject (obj.modifiers[1])
                                vert_a=vert_a as bitarray
                                obj.modifiers[1].SetEPolySelLevel  #face
                                obj.modifiers[1].ButtonOp #UnhideAllFace  
                                fs=obj.modifiers[1].GetSelection #Face 
                                obj.modifiers[1].Select  #face fs invert:true
    
                                obj.modifiers[1].SetEPolySelLevel  #Vertex
                                obj.modifiers[1].ButtonOp #UnhideAllVertex  
                                vs=obj.modifiers[1].GetSelection #Vertex 
                                obj.modifiers[1].Select  #Vertex vs invert:true
                                obj.modifiers[1].Select  #Vertex vert_a
                                obj.modifiers[1].ConvertSelection #Vertex #Face requireAll:true
    
                                obj.modifiers[1].SetEPolySelLevel  #face
                                obj.modifiers[1].ButtonOp #UnhideAllFace  
                                obj.modifiers[1].ButtonOp #HideUnselectedFace
                                obj.modifiers[1].SetEPolySelLevel  #Object
                                completeredraw()
                            )--if skin_m!=undefined then
                        )--for obj in objects do
                        clearSelection(); select old_selection;
                        completeredraw()
                    )--if bones_identic_name.count==1 then
                )--if classof bone_obj==BoneGeometry then
            )--if selection.count==1 then
        )--undo on
        )--on btn_show_selected_bone pressed do
           
        on btn_hide_all pressed do
        (
            undo on
        (
            old_selection=selection as array
            for obj in objects do
            (
                skin_m=undefined
                if obj.modifiers.count==1 then
                (if classof obj.modifiers[1]==skin then skin_m=obj.modifiers[1])
                if obj.modifiers.count==2 then
                (
                    if classof obj.modifiers[2]==skin and obj.modifiers[1].name=="igorznag_bone_show" then 
                    skin_m=obj.modifiers[2]
                )--if obj.modifiers.count==2 then
                if skin_m!=undefined then
                (
                    select obj; max modify mode
                    if obj.modifiers.count==1 then 
                    (
                        m=Edit_Poly(); m.name="igorznag_bone_show"
                        modPanel.addModToSelection  m
                    )--if obj.modifiers.count==1 then
                    modPanel.setCurrentObject (obj.modifiers[1])
                    obj.modifiers[1].SetEPolySelLevel  #face
                    obj.modifiers[1].ButtonOp #HideUnselectedFace
                    obj.modifiers[1].ButtonOp #HideFace
                    obj.modifiers[1].SetEPolySelLevel  #Object
                )--if skin_m!=undefined then
            )--for obj in objects do
            clearSelection(); select old_selection;
            completeredraw()
        )--undo on
        )--on btn_hide_all pressed do
       
        on btn_show_all pressed do
        (
            undo on
        (
            old_selection=selection as array
            for obj in objects do
            (
                if obj.modifiers.count==2 then
                (
                    if obj.modifiers[1].name=="igorznag_bone_show" then deletemodifier obj 1
                )--if obj.modifiers.count==2 then
            )--for obj in objects do
            clearSelection(); select old_selection;
            completeredraw()
        )--undo on
        )--on btn_show_all pressed do
    );createdialog show_hide_by_bone
     
  16. LighFusion

    LighFusion Пользователь сайта

    С нами с:
    27.12.2014
    Сообщения:
    13
    Симпатии:
    0
    Баллы:
    2
    Вот это просто афигенно, как будет $ на кошельке - обязательно скину немного - выручили капец просто !
     
Модераторы: Артер

Поделиться этой страницей