Перейти к содержанию
  • Здравствуйте, гость! 

    Чтобы вы могли использовать все функции нашего портала, а именно создавать сообщения, скачивать вложения и т.д., вам необходимо зарегистрироваться. Если вы уже зарегистрированные, то войдите в систему. Если у вас есть какие-либо сложности с регистрацией или ваш логин не срабатывает, то свяжитесь с нами через контактную форму, которую вы найдёте внизу каждой страницы. 

Magnus

Ориентация пивота по вектору нормали

Рекомендуемые сообщения

Magnus

Здравствуйте, подскажите пожалуйста, как развернуть пивот по направлению вектора нормали выбранного полигона через питон? Центрую оси нормально, нахожу вектор нормали полигона, а дальше ...
 

Спойлер

 


import c4d
from c4d import utils

def CenterAxis(obj, normal_vector):
    bBoxCenter = obj.GetMp()

    objMg = obj.GetMg()
    objPos = objMg.off
    objV1 = objMg.v1
    objV2 = objMg.v2
    objV3 = objMg.v3

    rot = obj.GetAbsRot()
    rotOrder = obj.GetRotationOrder()

    #HBPRotation = utils.VectorToHPB(normal_vector)

    rotM = utils.HPBToMatrix(rot,rotOrder)
    newCenter = bBoxCenter * rotM + objPos
    offsetV =  - bBoxCenter

    allPts = obj.GetAllPoints()
    for i in xrange(len(allPts)):
        obj.SetPoint(i,allPts[i] + offsetV)

    obj.Message(c4d.MSG_UPDATE)
    newMg = c4d.Matrix(newCenter,objV1,objV2,objV3)
    obj.SetMg(newMg)

def NormalVector(obj):
    polSel = obj.GetPolygonS()
    polSel.DeselectAll()
    polSel.Select(0)

    pol_nb = obj.GetPolygonCount()
    polSel_nor = c4d.Vector(0, 0, 0)

    for i, sel in enumerate(polSel.GetAll(pol_nb)):
        if not sel: continue
        pol = obj.GetPolygon(i)
        posA = obj.GetPoint(pol.a)
        posB = obj.GetPoint(pol.b)
        posC = obj.GetPoint(pol.c)
        posD = obj.GetPoint(pol.d)
        v1 = posA - posC
        v2 = posB - posD
        v3 = v1.Cross(v2)
        polSel_nor += v3

    polSel_nor.Normalize()
    return polSel_nor

def main():
    obj = doc.GetActiveObject()
    doc.StartUndo()
    doc.AddUndo(c4d.UNDOTYPE_CHANGE, obj)

    CenterAxis(obj, NormalVector(obj))

    doc.EndUndo()
    c4d.EventAdd()
if __name__=='__main__':
    main()

 

 

 

 

Изменено пользователем Magnus

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
zero21

а дальше находишь матрицу поворота нормали относительно нового базиса и применяешь к текущему объекту или можно попробовать найти обратную матрицу нормали... не знаю есть ли в синеме готовые решения, надо смотреть в мануале

Изменено пользователем zero21

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Magnus

Вроде и документацию по матрицам почитал, и все равно не догоняю - у меня теперь объект разворачивается, хотя и смотрит относительно выбранного полигона, а его пивот нет.

Спойлер

 


import c4d
from c4d import gui, utils, Vector

def NormalVector(obj):
    polSel = obj.GetPolygonS()
    polSel.DeselectAll()
    polSel.Select(0)

    pol_nb = obj.GetPolygonCount()
    polSel_nor = c4d.Vector(0, 0, 0)

    for i, sel in enumerate(polSel.GetAll(pol_nb)):
        if not sel: continue
        pol = obj.GetPolygon(i)
        posA = obj.GetPoint(pol.a)
        posB = obj.GetPoint(pol.b)
        posC = obj.GetPoint(pol.c)
        posD = obj.GetPoint(pol.d)
        v1 = posA - posC
        v2 = posB - posD
        v3 = v1.Cross(v2)
        polSel_nor += v3

    polSel_nor.Normalize()
    rotOrder = obj.GetRotationOrder()
    rotR = utils.HPBToMatrix(polSel_nor,rotOrder)
    return rotR

def main():
    doc.StartUndo()
    doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)

    bBoxCenter    = op.GetMp()
    mg_pos        = op.GetMg().off
    nrm_mg        = NormalVector(op)
    nrm_mg_V1     = nrm_mg.v1
    nrm_mg_V2     = nrm_mg.v2
    nrm_mg_V3     = nrm_mg.v3

    rot           = op.GetAbsRot()
    rotOrder      = op.GetRotationOrder()
    rotR          = utils.HPBToMatrix(rot,rotOrder)
    new_Center    = bBoxCenter * rotR + mg_pos
    new_mg        = c4d.Matrix(new_Center,nrm_mg_V1,nrm_mg_V2,nrm_mg_V3)

    points        = op.GetAllPoints()
    for i in xrange(len(points)):
        op.SetPoint(i,points + -bBoxCenter)

    op.Message(c4d.MSG_UPDATE)
    op.SetMg(new_mg)

    doc.EndUndo()
    c4d.EventAdd()
if __name__=='__main__':
    main()

 

 

Изменено пользователем Magnus

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Magnus

Расположить оси вдоль нормали нужного полигона удалось, однако повернуть в нужном направлении (центр одной образующих полигон граней) не выходит.

import c4d
from c4d import Vector, Matrix, utils

def PolygonCenter(obj, polygons, points):
        polygons_center = [c4d.Vector()] * obj.GetPolygonCount()
        center = c4d.Vector()

        for i, polygon in enumerate(polygons):
            if polygon.c != polygon.d :
                center = (points[polygon.a] + points[polygon.b] + points[polygon.c] + points[polygon.d]) / 4.
            else :
                center = (points[polygon.a] + points[polygon.b] + points[polygon.c]) / 3.
            polygons_center[i] = center

        return polygons_center

def Normal(obj, polygon, points):
    normal = (points[polygon.a] - points[polygon.c]).Cross(points[polygon.b] - points[polygon.d])
    normal.Normalize()
    return normal

def Axis(obj, parent):
    if parent:      m_obj = obj.GetMl()
    else:           m_obj = obj.GetMg()
    points          = obj.GetAllPoints()
    point_c         = obj.GetPointCount()
    polygon         = obj.GetPolygon(0)
    polygons        = obj.GetAllPolygons()
    polygon_n       = Normal(obj, polygon, points)

    #direction       = (points[polygon.a] - points[polygon.b])
    #polygon_n       = (direction.Dot(polygon_n)) - direction

    polygon_n       = utils.VectorToHPB(polygon_n)
    mat             = utils.HPBToMatrix(polygon_n, obj.GetRotationOrder()) * m_obj
    mat.off         = m_obj.off + PolygonCenter(obj, polygons, points)[0]

    m         = ~mat * m_obj
    for i in xrange(point_c):
        points[i] = m.Mul(points[i])

    obj.SetAllPoints(points)

    if parent : obj.SetMl(mat)
    else : obj.SetMg(mat)
    obj.Message(c4d.MSG_UPDATE)

def main():
    doc.StartUndo()
    objlist = doc.GetActiveObjects(True)

    for obj in objlist:
        if obj.GetType() != c4d.Opolygon : continue
        if obj.GetUp() is None: parent = False
        else: parent = True

        doc.AddUndo(c4d.UNDOTYPE_CHANGE, obj)
        Axis(obj, parent)

    doc.EndUndo()
    c4d.EventAdd()
if __name__=='__main__':
    main()

Подскажите пожалуйста, где я ошибся.

Спойлер

 

1.JPG

2.JPG

 

 

Изменено пользователем Magnus

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

×

Важная информация

Мы разместили cookie-файлы на ваше устройство, чтобы помочь сделать этот сайт лучше. Вы можете изменить свои настройки cookie-файлов, или продолжить без изменения настроек.