Здравствуйте! Есть два одинаковых объекта, повернутых относительно друг друга. К ним применен resetXform(пример в файле temp1.zip) Как совместить произвольно повернутый объект с оригиналом?
Нашел в нете способ, немного подредактировал (алгоритм, примерно такой - применяем для повернутого объекта что-то вроде Normal Align, затем поворачиваем его на нужный угол в плоскости полигона):
(
fn angle2Vec v1 v2 = acos (dot (normalize v1) (normalize v2))
fn RotatePivotOnly obj index=
(
rot = (matrixFromNormal (getFaceNormal obj index)*obj.transform ) as quat
rotValInv=inverse rot
animate off in coordsys local obj.rotation*=RotValInv
obj.objectoffsetrot*=RotValInv
obj.objectoffsetpos*=RotValInv
)
f = 1
mainObj = $MainObj
tempObj = $TempObj
faceNormM = getFaceNormal mainObj f
faceNormT = getFaceNormal tempObj f
faceCentM = meshop.getFaceCenter mainObj f
faceCentT = meshop.getFaceCenter tempObj f
tempObj.pivot = faceCentT
ResetXForm tempObj
convertToMesh tempObj
mainObj.pivot = faceCentM
ResetXForm mainObj
convertToMesh mainObj
RotatePivotOnly tempObj f
RotatePivotOnly mainObj f
tempObj.transform = matrixFromNormal faceNormM
tempObj.pos = faceCentM
vecVertT = getVert tempObj ((meshop.getVertsUsingFace tempObj f) as array)[1]
vecVertM = getVert mainObj ((meshop.getVertsUsingFace mainObj f) as array)[1]
faceNormM = getFaceNormal mainObj f
faceNormT = getFaceNormal tempObj f
faceCentM = meshop.getFaceCenter mainObj f
faceCentT = meshop.getFaceCenter tempObj f
theCrossV = cross (normalize (vecVertT - faceCentT)) faceNormT -- nujno dlya korrektirovki napravleniya vrasheniya
ug = angle2Vec (vecVertT - faceCentT) (vecVertM - faceCentM)
ugKorYZ = if (dot theCrossV faceNormT) >= 0 then ug else -ug
tempObj.transform = rotateZmatrix ugKorYZ*tempObj.transform
)
но способ не точный получился, чем дальше от совмещаемых треугольников, тем больше разброс (1.jpg) Собственно визуально, кажется простая задача. Надо просто выставить объект по трем точкам. Как это сделать?) Подскажите, пожалуйста!
(
fn AlignPivotTo Obj Trgt =
(
-- Get matrix from object
if classOf Trgt != matrix3 then Trgt = Trgt.transform
-- Store child transforms
local ChldTms = in coordSys Trgt ( for Chld in Obj.children collect Chld.transform )
-- Current offset transform matrix
local TmScale = scaleMatrix Obj.objectOffsetScale
local TmRot = Obj.objectOffsetRot as matrix3
local TmPos = transMatrix Obj.objectOffsetPos
local TmOffset = TmScale * TmRot * TmPos
-- New offset transform matrix
TmOffset *= obj.transform * inverse Trgt
-- Apply matrix
Obj.transform = Trgt
-- Restore offsets
Obj.objectOffsetPos = TmOffset.translation
Obj.objectOffsetRot = TmOffset.rotation
Obj.objectOffsetScale = TmOffset.scale
-- Restore child transforms
for i = 1 to Obj.children.count do Obj.children[i].transform = ChldTms[i] * inverse Trgt * Obj.transform
)
fn localMatrix p1 p2 p3 =
(
v1 = p1 - p3 -- вектор по одной стороне треугольника
v2 = p2 - p3 -- вектор по другой стороне
e1 = normalize( cross v1 v2) -- первый орт как нормализованное векторное произведение v1 и v2
e2 = normalize( cross e1 v1)
e3 = normalize( cross e1 e2)
mat3 = matrix3 1 -- создание стандартной матрицы
mat3[1] = e1
mat3[2] = e2
mat3[3] = e3
mat3[4] = p1
return mat3
)
mainObj = $MainObj
tempObj = $TempObj
NumV = tempObj.numverts -- количество вершин объекта
-- выберем три разные вершины объекта
p1 = 1
p2 = tempObj.numverts/2 as integer
p3 = tempObj.numverts
--строим по ним локальные матрицы
-- можно использовать функцию matrixFromNormal, но она глючит из-за поворотов фэйсов
theMt = localMatrix (getVert tempObj p1) (getVert tempObj p2) (getVert tempObj p3)
theMm = localMatrix (getVert mainObj p1) (getVert mainObj p2) (getVert mainObj p3)
AlignPivotTo tempObj theMt -- совмещаем пивот перемещаемого объекта по локальной матрице theMt
tempObj.transform = theMm -- совмещаем перемещаемый объект с локальной матрицей theMm основного объекта
tempObj.pivot = mainObj.pivot
)
тут, конечно надо еще доработать - исключить случаи, когда локальная матрица может обнуляться.
Функцию AlignPivotTo нарыл в нете. Работает отлично, только вот смысл преобразований в ней немного не понятен. Поясните, знающие люди, пожалуйста. Можно ли эту функцию как-то оптимизировать, убрать лишнее? Зачем в ней scaleMatrix используется и т.д. и т.п???В общем случае, может быть подскажете, как просто совместить пивот с новой матрицей???
Что-то вроде obj1.transform = obj2.transform, только для пивота объекта?
Может быть не прав, но, по моему, в функции слишком много лишних преобразований. Мне кажется есть путь попроще, что-то вроде obj1.transform = obj2.transform, только для pivot.
Чем меньше преобразований, тем выше точность и скорость. Предполагаю использовать для поиска одинаковой неинстансной геометрии в сцене и замены на инстансную. В сцене может быть несколько десятков тысяч объектов. Важно иметь максимально оптимизированный код для ускорения обработки.
Все прекрасно выполняет на первой итерации. Но если, после создания боксов, pivot Box001 сдвинуть(повернуть) и заново выполнить AlignPivotTo b1 b2.transform, то вместо того, чтобы pivot Box001 вернуться в исходное положение(b2.transform), начинает прыгать сам Box001 непонятным образом. Где подвох???
Извините, ошибку понял, только вот как от этих скачков избавиться????
Вот только не очень понятен смысл этого преобразования:
TmOffset *= obj.transform * inverse Trgt
кто в матрицах понимает, поясните пожалуйста.
И еще - не хватает точности(2014-07-21 19-31.png) Может быть проблема из-за ограничений float? Можно ли как-то повысить точность?
Доступ к резюме доступен только по пакетному доступу HR менеджерам зарегистрированных компаний. Узнать о вариантах корпоративных пакетов можно по ссылке.
Александр Якушев
Нашел в нете способ, немного подредактировал (алгоритм, примерно такой - применяем для повернутого объекта что-то вроде Normal Align, затем поворачиваем его на нужный угол в плоскости полигона):
( fn angle2Vec v1 v2 = acos (dot (normalize v1) (normalize v2)) fn RotatePivotOnly obj index= ( rot = (matrixFromNormal (getFaceNormal obj index)*obj.transform ) as quat rotValInv=inverse rot animate off in coordsys local obj.rotation*=RotValInv obj.objectoffsetrot*=RotValInv obj.objectoffsetpos*=RotValInv ) f = 1 mainObj = $MainObj tempObj = $TempObj faceNormM = getFaceNormal mainObj f faceNormT = getFaceNormal tempObj f faceCentM = meshop.getFaceCenter mainObj f faceCentT = meshop.getFaceCenter tempObj f tempObj.pivot = faceCentT ResetXForm tempObj convertToMesh tempObj mainObj.pivot = faceCentM ResetXForm mainObj convertToMesh mainObj RotatePivotOnly tempObj f RotatePivotOnly mainObj f tempObj.transform = matrixFromNormal faceNormM tempObj.pos = faceCentM vecVertT = getVert tempObj ((meshop.getVertsUsingFace tempObj f) as array)[1] vecVertM = getVert mainObj ((meshop.getVertsUsingFace mainObj f) as array)[1] faceNormM = getFaceNormal mainObj f faceNormT = getFaceNormal tempObj f faceCentM = meshop.getFaceCenter mainObj f faceCentT = meshop.getFaceCenter tempObj f theCrossV = cross (normalize (vecVertT - faceCentT)) faceNormT -- nujno dlya korrektirovki napravleniya vrasheniya ug = angle2Vec (vecVertT - faceCentT) (vecVertM - faceCentM) ugKorYZ = if (dot theCrossV faceNormT) >= 0 then ug else -ug tempObj.transform = rotateZmatrix ugKorYZ*tempObj.transform )но способ не точный получился, чем дальше от совмещаемых треугольников, тем больше разброс (1.jpg) Собственно визуально, кажется простая задача. Надо просто выставить объект по трем точкам. Как это сделать?) Подскажите, пожалуйста!Вложения
igorznag
Александр Якушев
Александр Якушев
( fn AlignPivotTo Obj Trgt = ( -- Get matrix from object if classOf Trgt != matrix3 then Trgt = Trgt.transform -- Store child transforms local ChldTms = in coordSys Trgt ( for Chld in Obj.children collect Chld.transform ) -- Current offset transform matrix local TmScale = scaleMatrix Obj.objectOffsetScale local TmRot = Obj.objectOffsetRot as matrix3 local TmPos = transMatrix Obj.objectOffsetPos local TmOffset = TmScale * TmRot * TmPos -- New offset transform matrix TmOffset *= obj.transform * inverse Trgt -- Apply matrix Obj.transform = Trgt -- Restore offsets Obj.objectOffsetPos = TmOffset.translation Obj.objectOffsetRot = TmOffset.rotation Obj.objectOffsetScale = TmOffset.scale -- Restore child transforms for i = 1 to Obj.children.count do Obj.children[i].transform = ChldTms[i] * inverse Trgt * Obj.transform ) fn localMatrix p1 p2 p3 = ( v1 = p1 - p3 -- вектор по одной стороне треугольника v2 = p2 - p3 -- вектор по другой стороне e1 = normalize( cross v1 v2) -- первый орт как нормализованное векторное произведение v1 и v2 e2 = normalize( cross e1 v1) e3 = normalize( cross e1 e2) mat3 = matrix3 1 -- создание стандартной матрицы mat3[1] = e1 mat3[2] = e2 mat3[3] = e3 mat3[4] = p1 return mat3 ) mainObj = $MainObj tempObj = $TempObj NumV = tempObj.numverts -- количество вершин объекта -- выберем три разные вершины объекта p1 = 1 p2 = tempObj.numverts/2 as integer p3 = tempObj.numverts --строим по ним локальные матрицы -- можно использовать функцию matrixFromNormal, но она глючит из-за поворотов фэйсов theMt = localMatrix (getVert tempObj p1) (getVert tempObj p2) (getVert tempObj p3) theMm = localMatrix (getVert mainObj p1) (getVert mainObj p2) (getVert mainObj p3) AlignPivotTo tempObj theMt -- совмещаем пивот перемещаемого объекта по локальной матрице theMt tempObj.transform = theMm -- совмещаем перемещаемый объект с локальной матрицей theMm основного объекта tempObj.pivot = mainObj.pivot )тут, конечно надо еще доработать - исключить случаи, когда локальная матрица может обнуляться.Функцию AlignPivotTo нарыл в нете. Работает отлично, только вот смысл преобразований в ней немного не понятен. Поясните, знающие люди, пожалуйста. Можно ли эту функцию как-то оптимизировать, убрать лишнее? Зачем в ней scaleMatrix используется и т.д. и т.п???В общем случае, может быть подскажете, как просто совместить пивот с новой матрицей???
Что-то вроде obj1.transform = obj2.transform, только для пивота объекта?
igorznag
Александр Якушев
Чем меньше преобразований, тем выше точность и скорость. Предполагаю использовать для поиска одинаковой неинстансной геометрии в сцене и замены на инстансную. В сцене может быть несколько десятков тысяч объектов. Важно иметь максимально оптимизированный код для ускорения обработки.
Александр Якушев
Вот оптимизированный код:
( fn AlignPivotTo Obj Trgt = ( -- New offset transform matrix TmOffset = obj.transform -- запоминаем исходное положение -- Apply matrix Obj.transform = Trgt -- выставляем объект по новой матрице -- Restore offsets -- смещаем только объект в исходное положение (без pivot) Obj.objectOffsetPos = TmOffset.translation Obj.objectOffsetRot = TmOffset.rotation --Obj.objectOffsetScale = TmOffset.scale ) b1 = box pos:(random [-100, -100, -100] [100,100,100]) wirecolor:green rotate b1 (eulerAngles (random -360 360) (random -360 360) (random -360 360)) b2 = box pos:(random [-100, -100, -100] [100,100,100]) wirecolor:red rotate b2 (eulerAngles (random -360 360) (random -360 360) (random -360 360)) AlignPivotTo b1 b2.transform )Все прекрасно выполняет на первой итерации. Но если, после создания боксов, pivot Box001 сдвинуть(повернуть) и заново выполнить AlignPivotTo b1 b2.transform, то вместо того, чтобы pivot Box001 вернуться в исходное положение(b2.transform), начинает прыгать сам Box001 непонятным образом. Где подвох???Извините, ошибку понял, только вот как от этих скачков избавиться????
Александр Якушев
fn AlignPivotTo Obj Trgt = ( -- Current offset transform matrix TmScale = scaleMatrix Obj.objectOffsetScale TmRot = Obj.objectOffsetRot as matrix3 TmPos = transMatrix Obj.objectOffsetPos TmOffset = TmScale * TmRot * TmPos -- New offset transform matrix TmOffset *= obj.transform * inverse Trgt -- Apply matrix Obj.transform = Trgt -- Restore offsets Obj.objectOffsetPos = TmOffset.translation Obj.objectOffsetRot = TmOffset.rotation Obj.objectOffsetScale = TmOffset.scale )Вот только не очень понятен смысл этого преобразования:кто в матрицах понимает, поясните пожалуйста.
И еще - не хватает точности(2014-07-21 19-31.png) Может быть проблема из-за ограничений float? Можно ли как-то повысить точность?
Вложения