На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! Правила раздела "Программирование графики"
1) Данный раздел предназначен для обсуждения проблем, возникающих при программировании задач, связанных с чтением, сохранением, обработкой, созданием, отрисовкой графической информации (в том числе - 3D [OpenGL, Direct3D] и анимации [в т.ч. VFW, DirectShow, OpenDML]).
Флэш обсуждают здесь!.

2) Если вы хотите получить совет для конкретной платформы/языка программирования, обязательно укажите их в вопросе.

3) Уважаемые новички! Мы приветствуем Ваше желание научить всех посетителей раздела правильному программированию. Но огромная просьба, перед тем, как писать поучения в старых (последний ответ - "старее" месяца, а особенно, если вопрошавший не появляется на форуме уже не первый месяц, в чем можно убедиться в его профиле) темах, хорошо подумать, будет ли кому-нибудь, кроме Вас cамих, это интересно.



Ваше мнение о модераторах: user posted imageBarazuk, user posted imageOpenGL, user posted imageMikle
Модераторы: OpenGL, barazuk, Mikle
  
> Правильная трансформация нормалей.
Есть модель, состоящая из вертексов, и есть матрица преобразования этой модели. Необходимо преобразовать и зашить обратно в модель позиции и нормали.
Задачу можно упростить:
Предположим, что трансформация, задаваемая матрицей - это комбинация поворотов, скейлов и переносов, без перспективных искажений, то есть m14, m24 и m34 равны нулю.

D3DXVec3TransformNormal не подходит, если матрица включает не только переносы и повороты, но и скейл. Нормализация нормалей после D3DXVec3TransformNormal - тоже не панацея, даже в результате чистого скейла нормали меняют направление (и должны менять, но не так, как меняют тут).
Переносы от других преобразований отделяются легко, это m41, m42 и m43.
Фактически D3DXVec3TransformNormal, умножая вектор на матрицу 3*3 (входящую в состав матрицы 4*4), уже игнорирует переносы, но эта матрица 3*3 содержит повороты и скейлы в смешанном виде, элементы m11, m22 и m33 зависят и от скейлов, и от поворотов.

Я решил эту задачу, отказавшись от D3DXVec3TransformNormal:
ExpandedWrap disabled
    Public Sub Transform(Norm As D3DVECTOR, M As D3DMATRIX)
      Dim V0 As D3DVECTOR
      Dim V1 As D3DVECTOR
      Dim V2 As D3DVECTOR
     
      V1 = Vec3(Rnd, Rnd, Rnd)
      D3DXVec3Cross V1, V1, Norm
      D3DXVec3Cross V2, V1, Norm
      D3DXVec3TransformCoord V0, Vec3(0, 0, 0), M
      D3DXVec3TransformCoord V1, V1, M
      D3DXVec3TransformCoord V2, V2, M
      D3DXVec3Subtract V1, V1, V0
      D3DXVec3Subtract V2, V2, V0
      D3DXVec3Cross Norm, V2, V1
      D3DXVec3Normalize Norm, Norm
    End Sub


Длинновато, но работает правильно, единственное - есть опасность, что случайный вектор Vec3(Rnd, Rnd, Rnd) окажется сонаправленным с исходным. Вероятность мала, но есть.
Как проще (без if-оф) получить случайный вектор, гарантированно не сонаправленный данному? Направленный в противоположную стороны тоже считается сонаправленным.
Может есть вариант по-проще?
M
Тема отображена в разделе(ах): Алгоритмы
Сообщение на автоудалении
Есть такой подход для генерации перпендикулярного вектора в 3D:

Выбрать максимальный по амплитуде компонент из (dx, dy, dz). Пусть это будет dy. Записать на его место следующий в циклическом порядке, а сам компонент - на следующее место, изменив знак. Третий компонент обнулить.

Т.е. результат будет (0, dz, -dy)
Цитата MBo @
Есть такой подход для генерации перпендикулярного вектора в 3D

Длинно, два if-а, потом ещё определять понятие "следующий", что тоже без if-ов трудно представить.
Я заменил:
ExpandedWrap disabled
    V1 = Vec3(Rnd, Rnd, Rnd)

на:
ExpandedWrap disabled
    If Abs(Norm.x) < Abs(Norm.y) Then
      V1 = Vec3(1, 0, 0)
    Else
      V1 = Vec3(0, 1, 0)
    End If

Наверное, это самый простой вариант.
Но остаётся в силе вопрос - в целом я задачу решил оптимально, или можно проще?
Сообщение отредактировано: Mikle -
Цитата
Нормали трансформируют транспонированной инверсной матрицей.

Всего-то нужно было сделать так:
ExpandedWrap disabled
    Public Sub Transform(Norm As D3DVECTOR, M As D3DMATRIX)
      Dim M1 As D3DMATRIX
     
      D3DXMatrixInverse M1, M
      D3DXMatrixTranspose M1, M1
      D3DXVec3TransformNormal Norm, Norm, M
      D3DXVec3Normalize Norm, Norm
    End Sub
Сообщение отредактировано: Mikle -
Цитата MBo @
Есть такой подход для генерации перпендикулярного вектора в 3D:
Что-то не то. Вектор получается не нормальный к поверхности.
Цитата Mikle @
Всего-то нужно было сделать так:
Похоже не так просто подсказку найти оказалось (4 часа прошло) Вообще-то матрица преобразования нормалей получается умножением почти тех же матриц, как и матрица преобразования координат, но выбрасываются сдвиги, и вместо масштабных используются их обратные (что насчёт перспективного преобразования, не помню).
Так что на всякий случай проверь, всегда ли правильная нормаль получается.
Всё написанное выше это всего лишь моё мнение, возможно ошибочное.
>Что-то не то. Вектор получается не нормальный к поверхности.
Это вектор, перпендикулярный данному
Цитата amk @
Вообще-то матрица преобразования нормалей получается умножением почти тех же матриц, как и матрица преобразования координат, но выбрасываются сдвиги, и вместо масштабных используются их обратные (что насчёт перспективного преобразования, не помню)

Но для этого нужно иметь эти исходные трансформации по отдельности.
Цитата amk @
Похоже не так просто подсказку найти оказалось (4 часа прошло)

Я не привык долго искать. То, что нашёл по первым трём ссылкам, касалось преобразования параметров источника света вместо нормалей модели, это всё правильно, но этим я пользовался и раньше, а сейчас не тот случай.
Поэтому я по привычке сел и написал свой велосипед, и он таки оказался правильным, но не оптимальным.
Цитата amk @
Так что на всякий случай проверь, всегда ли правильная нормаль получается.

В моём первом решении - всегда. В последнем результаты для всех видов трансформаций не проверял, но это общепринятый метод, который я в своё время просто умудрился пропустить.
Сообщение отредактировано: Mikle -
1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
0 пользователей:


[ Script Execution time: 0,1040 ]   [ 21 queries used ]   [ Generated: 25.03.17, 23:42 GMT ]