Левая резьба.

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

В принципе история достаточно простецкая. Но на безрыбье и рак рыба.

Все начинается с вопроса, который я люблю задавать на интервью, ежели кто-то в резюме напишет про знакомство с 3D графикой. Прошу я реализовать умножение на перспективную ( та которая gluPerspective ) матрицу. На HLSL или на ассемблере. В матрице перспективы всего четыре элемента нетривиальны, поэтому есть надежда реализовать умножение на нее за одну-две команды ( кто сможет за одну команду – возьмите с полки пирожок ). И потратить всего одну – две константы вершинных шейдеров, которые постоянны на время рисования сцены.

Есть у нас объект. Хочется перегнать его в пространство камеры ( достаточно матрицы 3×4, трех констант шейдера ), там выполнять все вычисления, связанные с освещением. Ежели объект скелетно анимированный – то достатчно загнать в root transform матрицу относительно камеры, далее взять композицию локальных преобазований костей. В результате получим скелет в пространстве камеры, который прямо возьмем и загоним в константы шейдера. Без всяких дополнительных матричных умножений.

Красиво и просто. Я размял пальцы и загнал всю эту красоту в шейдеры проекта. Первым делом обнаружилось, что в матрице есть scale. И для корректного лайтинга надо нормализовать нормаль ( наверное, можно делать нормалям rescale, но тогда надо куда-то per-object коэффициент засовывать ). Впрочем это мелочь.

Прожил я с этой технологией ниппель довольно долго. Обнаружилось, что высокому уровню вынь-да-положь ( чтобы персонаж головой крутил да смотрел на врагов ) понадобились положения костей во время анимации. А так как кости находятся в пространстве камеры, то для преобразования в мировые координаты их надо подкрутить. Код высокого уровня был щедро приправлен матричными умножениями и вроде зажил.

Потом руки дошли до отражений. Пальцы что-то там сами писали, потом я посмотрел на код задумчиво и увидел, что для кастомной камеры мне надо пересчитывать анимации заново, засунув в root transform новую матрицу. А код высокого уровня уже брал матрицы в пространстве камеры…

Потом в тех же отражениях я как бы случайно заметил, что не работает frustrum clip с кастомной ближней плоскостью. Точнее, работать он работает, но перспективная матрица потеряла всю свою красоту и тривиальность… Пришлось использовать дополнительную плоскость отсечения.

В принципе, в конце концов все зажило.

А вывод очень простой – если режешь левую резьбу на гайке – будь готов резать такую же резьбу на всех болтах.