3D Engineering

...Лучшее из общего.

  • Увеличить размер шрифта
  • Размер шрифта по умолчанию
  • Уменьшить размер шрифта

Вероятно многие из читателей этой статьи сталкивались с выражением ...

Вероятно, многие из читателей этой статьи сталкивались с выражением или понятием «Быть специалистом в своей области». И то насколько это соответствовало действительности, повышало или наоборот понижало авторитет того, о ком шла в данный момент речь. И пожалуй всегда считалось и считается по сей день престижным иметь статус хорошего или даже отличного специалиста в своей области. Окончить какой либо престижный ВУЗ и получить документальное подтверждением в виде диплома, где есть даже такая графа как «специальность», что дает в свою очередь право считать себя специалистом, если там что-либо написано. Специалисты требуются на работу, специалисты востребованы во всех областях. И если вы именно тот, кем себя считаете, то беспокоиться на счет отсутствия работы или востребованности у вас нет никаких оснований. Равно как нет оснований переживать за завтрашний день. Но это скорее как следствие, чем данность этого понятия. Ведь само по себе наличие статуса «специалист» вас не накормит и не оденет.

Вроде бы все правильно и вроде бы так и должно быть, принимая при этом факт, что и есть к чему стремиться и есть чего желать. И совсем не хотелось бы нарушать этой идиллии размеренного течения чередования событий внося, какой то не совсем понятный тон попытками взглянуть на этот вопрос с несколько иной стороны. Говоря военным языком дестабилизировать устоявшееся понятие этого вопроса. Но все-таки с вашего позволения мне и хотелось бы этим заняться, в надежде повернуть софит, направленный на этот вопрос немного с другой стороны. Претендуя при этом на некоторое приближение к объективности рассматриваемого вопроса.

И для начала, мне хотелось бы попросить вас назвать какого либо специалиста из любой области. А так как я и сам являюсь архитектором, чем кстати горжусь, то наверное правильнее было попросить вас назвать несколько имен из области архитектуры. Трудно? Хотя я думаю, вы наверняка сразу и с легкостью назвали несколько известных имен на вскидку. Так ли это? Давайте попробуем уточнить вопрос. На ваш взгляд был ли Ф. Шехтель специалистом? А как насчет Гауди? Растрелли? А мастер, подаривший миру Собор парижской богоматери или собор в Кельне? И еще многие другие жемчужины коллекции архитектурных шедевров и памятников. Ну вот я кажется и проговорился. Ключевым словом и понятием во всех этих вопросах было и есть понятие «мастер», хотя понятие «мастер» несколько ассоциируется с некоторым поползновением в область ремеслиничества, что кстати не так уж и противоречит данной теме. Наверное, все таки правильнее было бы заменить понятие «мастер» на «творец» или «создатель». Или же на что-то более демократичное для современного времени, например понятия «автор». «Автор проекта». Замечаете, что применительно к области архитектуры существует понятие как «автор проекта» так и понятие «главный специалист». Если  авторство принадлежит создателю, то кто же в таком случае специалист? Разве специалисту не под силу осуществление подобных задач? Ответ наверное снова спрячется в заданном ранее вопросе, где нужно было назвать известного специалиста в какой либо области. Согласитесь было бы парадоксально сказать «специалист создавший Успенский собор» или «специалист Шехтель разработавший проект особняка». Безусловно, все они были специалистами в своей области, но назвать их таковыми было бы просто кощунственно. А почему? Наверное, потому что существует разница между тем быть «специалистом» или быть «мастером», «творцом» или если хотите «автором».

Я думаю сейчас самое время попытаться дать определение такому понятию как кто же такой специалист. «Специалист» это человек, применяющий на практике полученные ранее знания и навыки. То есть, выражаясь простым и понятным языком «специалист» подобно роботу в которого была заложена программа выполняет свою работу с точностью до своей квалификации. «Высококлассный специалист» выполняет работу с минимальными погрешностями. А специалист более низкого ранга может позволять себе более широкий диапазон погрешностей. Что конечно же в конце концов сказывается на его имидже. Это как устаревшая модель компьютера, которая справляется только с текстовыми программами. Для графики же нужен более современный и более мощный компьютер. Да и задач современному компьютеру приходится решать во много раз больше, чем компьютеру десятилетней давности. Так же и со специалистами. Более современный и более коммуникабельный специалист сейчас в почете и в моде. Ведь приходится решать столько программ и поставленных задач, что не многие справляются. А если есть потребность быть впереди планеты всей, то нужно выкладываться на полную катушку.

И тут у меня снова возникает вопрос. Как долго может выдержать специалист, навесивший на себя столько сложных задач? Он все решает и решает, делает и делает, а реальных результатов этого добиться все сложнее, потому что появляются все более современные и более мощные модели специалистов. Знакомая картина? Возвращаясь в область проектирования, если 7-10 лет назад человек знающий Автокад или Архикад был на вес золота, то сейчас практически все владеют многими программами, которые сложнее и мощнее. Специалисты того времени просто уже становятся металлоломом. Если конечно не пытаются бежать в ногу со временем, пока есть силы. А когда силы закончатся, что будет? Не очень веселая картина, правда? Тем более, что это ожидает каждого вне зависимости от степени и квалификации.

А теперь давайте представим на мгновенье Федора Осиповича Шехтеля за компьютером. Как он стремится догонять время, ставя себе всякие апгрейды и модификации. Как он пытается с наибольшей реалистичностью передать падающую тень от люстры отраженную в паркете. Представили? Улыбнулись? Мне кажется это так же можно отнести в раздел «абсурд» или «нонсенс». И знаете почему? Потому что мастера своего дела выше подобных вещей. И даже если бы в то время существовал мощнейший компьютер с навороченными программами, ничего бы у него не получилось, если бы он старался быть не тем кем должен.

Итак, можно предположить некоторое сравнение. «Специалист» все время пытается бежать в ногу со временем, применяя знания и навыки, полученные в этом же времени. Иначе как бы нашли себе работу компьютерщики и программисты в прошлом. И копьеносцы или рыцари в будущем. Он как машина, соответствующая веянию и требованию современности. Но как ни крути, и как бы не был совершенен этот механизм, он все же винтик в общей системе. Специалист совершенно необходимый человек на производстве, образовании, спорте, в общем, во всех областях и отраслях где требуется конвеерное применение знаний. И если принимать во внимание конвеерность рабочего проектирования, то специалист этой области то же очень и очень необходим. Но суть механизма и его главная беда, это то, что его легко заменить на другой аналогичный или более совершенный. Можно собрать себе команду из отличных специалистов как из конструктора. И каждый при этом станет выполнять свою работу. Пусть очень хорошо, но все таки только свою. Специалист ВК не сможет сделать проект ОВ. Ландшафтник не сделает интерьера. Как быть в этом случае? Если каждый начнет выполнять только то, что умеет. Каких положительных результатов можно добиться в этом случае?  Это как электромясорубка, которая все вращается и вращается, вне зависимости от того есть ли в ней что-либо или нет. Она выполняет свою работу и этим все сказано. Я думаю подобными «мясорубками», которые просто выполняют свои работу, забиты 99% проектных институтов. А все почему? Наверное, потому что в свое время было поставлено на конвейер производство специалистов выполняющих свою работу таким же специалистом, который выполнял свою. Похоже на какой то фантастический фильм, где всеми управляют роботы. Но ведь этим и объясняется время, которое принято называть «застоем». Все работали, все что то выполняли, функционировали одним словом. А в результате положительного было очень мало. Не говоря конечно о спорте. Здесь были самые выдающиеся достижения, потому что специалисты этой области были «накручены» тренировками и методиками, что для этой области просто незаменимо. Но о спорте нужно говорить отдельно и поэтому вернемся к нашей с вами области. Где как вы помните, мы остановились на мысли «Можно собрать себе команду из отличных специалистов как из конструктора». И что все механизмы работаю каждый по-своему. И что бы все это работало взаимосвязано здесь и появляется «главный специалист», который управляет этими механизмами поменьше. Но беда в том, что ни главный специалист, ни какой либо другой не могут быть «автором». Потому что быть «автором» никто и никогда не научит. Здесь нет методики, как стать автором. Нет, конечно методики есть, но эффективность подобных  совсем не воодушевляет. Все специалисты работают, а автор творит. И как раз в этом и заключается полезность специалиста. Дать возможность Автору заниматься, тем чем он должен, в то время как специалист выполняет всю рутинную работу. Группа специалистов это собранные воедино механизмы подобно машине, а автор это водитель, который управляет ими по своему усмотрению.

Как вы думаете Главный архитектор «специалист» или «автор»? Я думаю, что он специалист, осознавший свое авторство. У него хватило силы и развитости вырваться и стать вне этой механизированной системы. Иначе он был бы просто архитектор 1-2, или какого нибудь еще разряда, которые день ото дня выполняет поставленные им задачи, настолько насколько они это умеют и настолько насколько их этому обучили. По-другому в области проектирования быть просто нельзя. Можно быть просто автором или творцом произведения в области поэзии, живописи и музыки. То есть там, где творенья автора создаются только лишь для эстетического восприятия. В архитектуре нельзя создавать произведения только для эстетического восприятия. Этим кстати и объясняется мое несколько неприятие методов «зализывания» подачи проекта. Ведь суть проекта в его правильности и целесообразности, а не качестве рендера. Но сейчас это к делу не относится и поэтому, говоря о рафинированном авторстве в области архитектуре, говорить, что архитектор это только автор совершенно нельзя. Конечно он специалист, потому что использует полученные знания и навыки. И в то же время он и автор, потому что нарушает эти механизмы, выходя за пределы системы и становясь при этом вне времени. А находиться вне времени, он может ровно настолько, насколько живы его произведения или упоминания о них. Если помните, еще до недавнего времени существовали семь чудес света, которые были известны мне еще с детства. Но я был совершенно обескуражен узнав, что этих чудес света попросту не осталось за исключением единиц. И если бы были упоминания об авторе этих чудес, то они пережили бы сами творенья и конечно самого автора. Удивительно, но иногда память живее, чем камень. И наоборот. Невольно начинаешь при этом задумываться о постоянстве или непостоянстве дел своих. И о том насколько может откликнуться через время то, что было создано тобой.

Но вернемся все же к понятию «специалист». Хотя мне кажется, вы уже увидели разницу между «специалистом» и «автором». И казалось бы, на этом можно было бы остановиться, но в начале этой статьи я заявил о том, что постараюсь быть объективным в данном вопросе, а сейчас получается, что понятие «специализм» освещен несколько в негативном свете. Что конечно же соответствует действительности, но не соответствует целостному восприятию. А таковое заключается в том, как это не парадоксально, «автором» не должны быть все. Именно поэтому автор это автор. Представьте, к примеру, что если бы все были авторами. Кто тогда стал бы работать и выполнять рутинную работу, которую так хорошо выполняют специалисты. Я думаю, в этом случае прогресс состоял бы только из теории. Теории о том, как хорошо было бы жить, если бы кто-то сделал, то, что было задумано. И так до скончания веков. Но такого к счастью нет и не должно быть. Хотя, наверное, процветающая Америка на полпути к этому и держится и работает только за счет приезжих эмигрантов. Правда, начинать по этому поводу дискуссию мне бы сейчас не хотелось.

И наконец подытоживая свое рассуждение по этому вопросу хотелось добавить следующее: В каждом проектировщике есть и «автор» и «специалист», и то насколько один сильнее другого выражается в том состоянии, в котором вы сейчас находитесь. Если на рабочем месте вас гложет невыраженность ваших идей и замыслов, то прислушайтесь, наверняка это «автор» хочет вырваться наружу. Или же наоборот, если вам интересно размеренное ожидание окончания рабочего дня, а от вас требуют каких то свершений, то это просто «специалист», который сидит внутри не желает «напрягаться» ни по какому поводу. И то и другое это вы, а вот как бы вы подписались под своим проектом «автор» или «специалист» подскажет тот, кто сильнее, внутри вас. Хотите стать специалистом. Вы уверенны?...

Руслан Гарипов. Автор книги «Рабочий проект от и до»
Персональный сайт www.visual-form.ru
 

Архив статей

 сен   Октябрь 2019   ноя

ВПВСЧПС
   1  2  3  4  5
  6  7  8  9101112
13141516171819
20212223242526
2728293031 
Julianna Willis Technology

Случайная новость

Почти все видели стерео картинки, я, например, помню в школе у нас были тетрадки, на обложке которых были напечатаны непонятные каракули. Но если посмотреть на них «правильно» - эти каракули обретали объем. Не у всех получалось увидеть их сразу, кому это было просто, а кто так и не смог. Есть несколько рекомендаций как достигнуть иллюзию объема: смотреть «сквозь» картинку или приложить ее вплотную к носу и медленно отводить.

Немного теории.

Как человек воспринимает объем?  Чем ближе расположен рассматриваемый объект, тем больше наблюдатель «сводит» глаза. Т.о. если рассматриваемый объект расположен на бесконечно удаленном расстоянии, то глаза будут смотреть на него «параллельно».

Рис.1

Теперь рассмотрим как достигнуть иллюзию объема на плоской картинке. Итак, у нас имеется человек с двумя глазами (рис.1): левый глаз O1 и правый O2,а так же плоскость проекции стерео изображения D1D2. Пусть рассматриваемый объект B расположен на расстоянии h от наблюдателя. Тогда для того чтоб «увидеть» его на картинке необходимо совпадение рисунка в точках B1 и B2. Получается мы держим перед собой плоский рисунок и смотрим как бы «сквозь» него. Левый глаз видит точку B1, правый B2, изображения для них на листе совпадают и создается иллюзия того, что на самом деле мы видим объект B, расположенный за плоскостью листа. Т.о. чем больше расстояние между точками B1 и B2,в которых совпадает изображение, тем «дальше» воспринимается объект B.

Теперь выведем пару расчетных формул, которые пригодятся для просчета стерео изображения. Пусть a – расстояние между глазами, H – расстояние до максимально удаленного объекта, h – расстояние до объекта h_max – расстояние от максимально удаленного объекта до плоскости проекции стерео изображения. Из подобия треугольников BB1B2 и BO1O2 следует B1B2/BE= O1O2/BF. B1B2=d , O1O2=a, BF=h, BE=BF-EF, EF=AF-AE=H-h_max, BE=h-(H-h_max). Итого d/(h-H+h_max))=a/h.

Пожалуй теории пока достаточно, можно перейти к практике. Для этого понадобится Photoshop и 3dsMAX. В Photoshop’е создадим текстуру, из которой в последствии будет построено стерео изображение. Несколько рекомендаций: чем больше на текстуре деталей, тем лучше получиться окончательный вариант (с однотонными вообще ничего не получиться); высота текстуры должна совпадать с высотой изображения (поэтому сразу надо определить размер финального стерео изображения); а ширина зависит от того, где вы собираетесь в дальнейшем использовать полученную картинку. На рис.1 величина d_max как раз соответствует ширине текстуры, поэтому в реальности (на экране монитора или после распечатки) она не должна превышать расстояния между глазами a. В тоже время чем больше пикселей по ширине будет в исходной текстуре, тем более качественным получиться окончательный результат. У меня получилась вот такая текстура:

 
Рис.2

Ширина ее 100 пикселей, а высота 600 (в итоге рассчитываю получить стерео изображение размером 800 на 600 пикселей). Хотя лучше сделать ее так, чтоб она тайлилась по горизонтали. Далее создаем или открывает любой 3D-объект в MAX’е. Я для этого использовал модель осы:

 
Рис.3

Для результата не пригодятся ни материалы, ни сторонние рендеры, ни источники света. Поэтому если все это имеется в сцене, то назначаем на все стандартный материал, удаляем все источники света и используем Default Scanline Renderer. Теперь можно приступить к написанию скрипта. Для этого в меню Max’а выбираем MAXScript->New Script и откроется окно редактирование скриптов. Наш скрипт будет иметь свой собственный интерфейс. Это можно реализовать двумя способами: на панели Utilites или в отдельном окне. Выберем первый вариант и создадим новую скрипт-утилиту:

utility stereoImg "Stereo Image"

-- утилита создания стерео изображения

(

)

Сохраним ее с названием stereoImg.ms и отправим ее на просчет. Для этого надо в меню редактора скриптов выбрать Tools->Evaluate All или нажать комбинацию клавиш Ctrl+E. После этого наша утилита приобрела свой интерфейс (рис.4) и единственное что можно с ней сделать – это открыть и закрыть.

 
Рис.4

Разберем что же мы сделали: utility – зарезервированное слово с помощью которого создаются новые скрипт-утилиты, stereoImg – имя переменной, с помощью которой можно осуществлять контроль над утилитой, “Stereo Image” – символьная строка, именно она отображается в списке утилит (рис.4-3), далее в круглых скобках идет тело утилиты. Более подробную информацию по созданию скрипт-утилит и MAXScript’у можно найти в файле помощи MAX’а (в основном меню Help->MAXScript Reference). Для добавления комментариев используется «--», после него компилятор игнорирует все символы до конца строки . Пора наполнить нашу утилиту кнопками и другими элементами пользовательского интерфейса. Будем ориентироваться на следующий вариант:

 
Рис.5

Итак, список необходимых элементов: две группы Texture и Render. В группе Texture имеется метка, в которой будет отображаться информация о текстуре, и кнопка, запускающая диалог открытия файла с текстурой. В группе Render – спиннер (определяет ширину рендера), метка (информация о высоте рендера), спиннер (качество стерео изображения), индикатор процесса, кнопка выбора объекта и «самая главная» кнопка запускающая скрипт на просчет. Для этого в тело утилиты надо добавить следующие строки:

    fn fltr_cam obj = superClassOf obj == camera -- функция возвращает истину если obj камера (для фильтра выбора)

    group "Texture:"

   -- параметры текстуры

   (

       label l_T_img "no texture" -- информация о размере

       button b_T_img "Load texture bitmap" -- загрузка текстуры

   )

   group "Render:"

   -- параметры рендеринга

   (

       spinner s_R_w "width:" range:[0,1500,0] type:#integer width:82 across:2 -- ширина

       label l_R_h "height:0" -- высота

       spinner s_R_prec "quality of stereo image" range:[1,10,4] type:#integer width:80 align:#right -- качество стерео изображения

       progressBar prb_R_status value:0 -- прогресс рендера

       pickbutton pb_R_cam "Pick camera" filter:fltr_cam across:2 -- выбор камеры

       button b_R_stereo ""  -- запуск рендера

   )

Здесь: group – зарезервированное слово для создание группы, после него следует название группы, и в круглых скобках элементы группы; label – для создания метки, потом название переменной для управления меткой и срока (выводимый на форму текст); button – для создания кнопки, потом название переменной для управления кнопкой и строка (отображается на кнопке). Это основная структура для создания элементов пользовательского интерфейса. Но некоторые элементы имеют так же дополнительные параметры. Для spinner’а – range:точка в 3d-пространстве> (первая координата определяет нижний предел изменения значения, вторая – верхний, третья – начальное значение), type:#integer (тип значения – целое число, так же может принимать значение #float – вещественное число и #worldunits – число в размерности текущих координат MAX’а). Для progressBarvalue:первоначальное значение>. Для pickbuttonfilter:ссылка на функцию фильтра>, функция фильтра имеет один параметр – объект и возвращает true, если объект может быть выбран, и false в противном случае. Для определение такой функции используется зарезервированное слово fn потом идет название функции, параметр и после «=» логическое выражение, которое возвращает функция. Параметры width:, across: и align: могут использоваться при создании любых элементов и отвечают за компоновку элементов на форме: первый – ширина (если требуется отличная от создаваемой по умолчанию), второй – количество элементов в одной строке (по умолчанию каждый новый элемент создается в новой строке), третий – выравнивание.

В самом начале тела утилиты (перед описанием пользовательских элементов) определим локальные переменные, необходимые для создания стерео изображения:

    -- определение локальных переменных

   local T_img = undefined -- текстура

   local width, height, d_max -- ширина и высота рендера, ширина текстуры

Осталось прописать обработчики событий от элементов пользовательского интерфейса. Описание всех событий должно быть следующим образом: onимя элемента> название события> список аргументов>do(обработка события>). Для начала опишем поведение MAX’а на нажатие кнопки загрузки текстуры. Что должно происходить:  открыться окно диалога выбора файла, после выбора файла текстуры она загружается в MAX, выводиться на форму информация о размере текстуры и ее название, далее инициируются локальные переменные и настраиваются глобальные параметры рендера.

    on b_T_img pressed do

   -- загрузка текстуры

   (

       T_file_name = getOpenFileName types:"bitmap(*.bmp)|*.bmp" -- диалог открытия файла

       if T_file_name != undefined then -- если все файл бы выбран

       (

           T_img = openBitMap (T_file_name) -- загрузка картинки

           b_T_img.caption = filenameFromPath T_file_name -- на кнопку имя файла картинки

           l_T_img.caption = "width: " + (T_img.width as String) + " height:" + (T_img.height as String) -- вывести информацию о картинке

           d_max = T_img.width -- обновление всех локальных переменных

           height = T_img.height

           width = 4*height/3 as Integer -- определение ширины рендера так чтоб в итоге получились пропорции 3:4

           s_R_w.value = width -- отображение информации о разрешении рендера

           l_R_h.caption = "height:" + height as String

           renderWidth = width -- настройка глобальных параметров рендера (ширина, высота)

           renderHeight = height

       )

   )

Определим вид, который мы желаем получит на стерео изображении. Для этого нам понадобиться камера. Если в сцене уже имеются камеры с «нужным» видом – отлично, можно использовать их. Если нет, то необходимо создать камеру. Проще всего перейти к виду Perspective, где выбрать необходимый ракурс. После чего создать камеру из вида: в главном меню Create->Cameras->CreateCameraFromView или Crtl+C. Вспомним теорию, там были такие параметры как H – расстояние до максимально удаленного объекта и h_max – расстояние от плоскости проецирования до максимально удаленного объекта. Чтоб не вводить их вручную, будем брать их из свойства камеры, а именно из Clipping Planes. Выберем необходимую камеру, на панели Modify раскроем свиток Parameters, ставим галочку возле Clip Manually. Осталось только настроить Near Clip и Far Clip. Плоскость Near Clip соответствует плоскости проекции стерео изображения, а Far Clip – расстояние до максимально удаленного объекта. Рекомендации: объекты, по которым будет строиться стерео изображение, должна располагаться между Far Clip и Near Clip, Near Clip равно приблизительно половине Far Clip, объекты должны быть расположены подальше от Near Clip и вплотную к Far Clip. Хотя можно этим пренебречь и в дальнейшем экспериментировать с Clipping Planes, для получения более желаемого результата. Т.о. вид настроен, осталось «объяснить» скрипту, что мы будем работать с этой камерой, для этого напишем обработчик нажатия кнопки выбора камеры:

    on pb_R_cam picked cam do

   -- выбор камеры

   (

       pb_R_cam.caption = pb_R_cam.object.name -- на кнопку имя камеры

   )

После этого ссылка на камеру содержится в pb_R_cam.object.Так же необходимо скрипту отреагировать на изменение пользователем ширины рендера:

    on s_R_w changed val do

   -- обработка изменения ширины рендера

   (

       width = s_R_w.value

       renderWidth = width

   )

Осталось обработать последнее событие – нажатие «самой главной» кнопки. Опять придется заняться теорией на основе полученной ранее формулы: d/(h-H+h_max))=a/h. Здесь a, H и h_max – констаны. Последние две получаються из Clipping Planes камеры. Определим a, для этого подставим вместо h величину H – крайний случай, когда объект находиться на максимальном расстоянии. Отсюда a=d_max*H/h_max. И последняя формула: d=a*(h-H+h_max)/h – по ней вычисляется расстояние между точками d, изображения в которых совпадают, для того чтоб создавалась иллюзия, что рассматриваемый объект расположен на расстоянии h от наблюдателя.

    on b_R_stereo pressed do

   -- просчет стерео изображения

   (

       -- рендер глубины

       DOF_img = render camera:pb_R_cam.object outputwidth:width outputheight:height channels:#(#zDepth)

       unDisplay DOF_img

       -- создание битмапы для будущего стерео изображения

       OUT_img = bitmap (width+d_max) height color:black

       -- заполнение первой полосы текстурой

       for x = 0 to (d_max-1)do

       (

           for y = 0 to (height-1) do

           (

               c =(getPixels T_img [x,y] 1)[1] -- берем пиксель из текстуры

               setPixels OUT_img [x,y] #(c) -- и вставляем в будущее стерео изображение

           )

           prb_R_status.value =(100 * x / d_max)as integer -- обновление прогресса текущей операции

       )

       prb_R_status.value = 0

       -- отрисовка стерео изображения

       H = pb_R_cam.object.farclip -- расстояние от глаз до максимальной глубины

       h_max = pb_R_cam.object.farclip - pb_R_cam.object.nearclip -- расстояние от плоскости проецирования до макс. глубины

       a = d_max*H/h_max -- расстояние между глазами

       -- построчное построение стерео изображения

       for y = 0 to (height - 1)do

       (

           for x = 0 to (width - 1) do

           (

               -- берем из рендера глубины расстояние от камеры до ближайшей точки

               dist = - (getChannel DOF_img [x,y] #zDepth)[1]

               if dist > H then dist = H -- не должно быть больше макс. глубины

               d =(a*(dist+h_max-H)/(dist)+.5)as integer -- вычисляем расстояние на котором должны совпадать пиксели стерео изображения

               setPixels OUT_img [x+d_max,y](getPixels OUT_img [x+d_max-d,y] 1) -- и дубируем пиксели согласно этому расстоянию

           )

           prb_R_status.value =(100 * y / height) as integer

       )

       prb_R_status.value = 0

       display OUT_img -- открываем окно с финальным стерео изображением

   )

Рассмотрим подробнее принцып работы обработчика нажатия «самой главной» кнопки. В переменную DOF_img сохраняется ссылка на рендер из выбранной камеры. Параметр channels:массив каналов> метода render указывает какие каналы необходимо отрендерить дополнительно, в нашем случае обязателен только один канал: #zDepth - расстояние от камеры до места пересечения объекта с лучом, выходящим из камеры и проходящим через заданную точку рендера h (в скрипте – это переменная dist). Метод unDisplay ссылка на изображение> закрывает окно с изображением, если оно открыто, этот метод противоположен display ссылка на изображение>. Затем создается новое изображение шириной большей, чем ширина рендера на ширину текстуры и слева заполняется полосой текстуры (рис.6).

 
Рис.6

Потом идет построчное сканирование канала глубины (с проверкой на то, чтоб расстояние не превысило Far Clip камеры). На основе этой величины h (в скрипте dist) и полученных ранее формул вычисляется расстояние между повторяющимися пикселами. Таким образом идет построение стерео изображения, попутно обновляется прогресс вычислений. И в конце концов на экран выводиться окончательный результат (рис.7).

 
Рис.7

Ниже приведен полный листинг скрипт-утилиты с некоторыми улучшениями:

utility stereoImg "Stereo Image"

-- утилита создания стерео изображения

(

   -- определение локальных переменных

   local T_img = undefined -- текстура

   local width, height, d_max -- ширина и высота рендера, ширина текстуры

   fn fltr_cam obj = superClassOf obj == camera -- функция возвращает истину если obj камера (для фильтра выбора)

   group "Texture:"

   -- параметры текстуры

   (

       label l_T_img "no texture" -- информация о размере

       button b_T_img "Load texture bitmap" -- загрузка текстуры

   )

   group "Render:"

   -- параметры рендеринга

   (

       spinner s_R_w "width:" range:[0,1500,0] type:#integer width:82 across:2 -- ширина

       label l_R_h "height:0" -- высота

       spinner s_R_prec "quality of stereo image" range:[1,10,4] type:#integer width:80 align:#right -- качество стерео изображения

       progressBar prb_R_status value:0 -- прогресс рендера

       pickbutton pb_R_cam "Pick camera" filter:fltr_cam across:2 -- выбор камеры

       button b_R_stereo ""  -- запуск рендера

   )

   on b_T_img pressed do

   -- загрузка текстуры

   (

       T_file_name = getOpenFileName types:"bitmap(*.bmp)|*.bmp" -- диалог открытия файла

       if T_file_name != undefined then -- если все файл бы выбран

       (

           T_img = openBitMap (T_file_name) -- загрузка картинки

           b_T_img.caption = filenameFromPath T_file_name -- на кнопку имя файла картинки

           l_T_img.caption = "width: " + (T_img.width as String) + " height:" + (T_img.height as String) -- вывести информацию о картинке

           d_max = T_img.width -- обновление всех локальных переменных

           height = T_img.height

           width = 4*height/3 as Integer -- определение ширины рендера так чтоб в итоге получились пропорции 3:4

           s_R_w.value = width -- отображение информации о разрешении рендера

           l_R_h.caption = "height:" + height as String

           renderWidth = width -- настройка глобальных параметров рендера (ширина, высота)

           renderHeight = height

       )

   )

   on pb_R_cam picked cam do

   -- выбор камеры

   (

       pb_R_cam.caption = pb_R_cam.object.name -- на кнопку имя камеры

   )

   on s_R_w changed val do

   -- обработка изменения ширины рендера

   (

       width = s_R_w.value

       renderWidth = width

   )

   on b_R_stereo pressed do

   -- просчет стерео изображения

   (

       if (height == undefined) or (width == 0) then

       (

           messageBox "No texture or invalid size"

           return 0

       )

       if pb_R_cam.object == undefined then

       (

           messageBox "Pick camera first"

           return 0

       )

       -- рендер глубины

       DOF_img = render camera:pb_R_cam.object outputwidth:width outputheight:height channels:#(#zDepth)

       unDisplay DOF_img

       -- создание битмапы для будущего "расширенного" стерео изображения

       -- причем ширина умножается на точность

       prec = s_R_prec.value -- точность (коэф. качества)

       OUT_img = bitmap ((width+d_max)*prec) height color:black

       -- заполнение первой полосы текстурой

       for x = 0 to (d_max-1)do

       (

           for y = 0 to (height-1) do

           for i = 0 to (prec-1) do

           (

               c1 =(getPixels T_img [x,y] 1)[1] -- берем пиксель из текстуры

               c2 = (getPixels T_img [x+1,y] 1)[1]

               if c2 == undefined then c2 = (getPixels T_img [0,y] 1)[1]

               c = c1*(1.*(prec-i)/prec)+ c2*(1.*i/prec) -- линейно сглаживаем растяжение

               setPixels OUT_img [x*prec+i,y] #(c) -- и вставляем в будущее стерео изображение

           )

           prb_R_status.value =(100 * x / d_max)as integer -- обновление прогресса текущей операции

       )

       prb_R_status.value = 0

       -- отрисовка "расширенного" стерео изображения

       H = pb_R_cam.object.farclip -- расстояние от глаз до максимальной глубины

       h_max = pb_R_cam.object.farclip - pb_R_cam.object.nearclip -- расстояние от плоскости проецирования до макс. глубины

       a = d_max*H/h_max -- расстояние между глазами

       -- построчное построение стерео изображения ("расширенное")

       for y = 0 to (height - 1) do

       (

           for x = 0 to (width - 1) do

           for dx = 0 to (prec - 1) do

           (

               -- берем из рендера глубины расстояние от камеры до ближайшей точки (тут тоже идет линейное сглаживание)

               dist = (- (getChannel DOF_img [x,y] #zDepth)[1]*(prec-dx) - (getChannel DOF_img [x,y] #zDepth)[1]*dx)/prec

               if dist > H then dist = H -- не должно быть больше макс. глубины

               d =(prec*a*(dist+h_max-H)/(dist)+.5)as integer -- вычисляем расстояние на котором должны совпадать пиксели стерео изображения

               setPixels OUT_img [x*prec+dx+d_max*prec,y](getPixels OUT_img [x*prec+dx+d,y] 1) -- и дубируем пиксели согласно этому расстоянию

           )

           prb_R_status.value =(100 * y / height) as integer

       )

       prb_R_status.value = 0

       -- получение из "расширенного" "нормальное" стерео изображение

       FIN_img = bitmap (width+d_max) height color:black -- создание битмапы для финального стерео изображения

       for y = 0 to (height - 1) do

       (

           for x = 0 to (width + d_max - 1) do

           (

               c = black

               for i = 0 to (prec-1) do

                   c +=(getPixels OUT_img [x*prec+i,y] 1)[1]/prec -- получение сренего арифметического цвета

               setPixels FIN_img [x,y] #(c) -- и сохранение его в финальное стрео изображение

           )

           prb_R_status.value =(100 * y / height) as integer

       )

       prb_R_status.value = 0

       display FIN_img -- открываем окно с финальным стерео изображением

   )

)

Изменение здесь только в алгоритме просчета стерео изображения. Добавилась проверка «от дурака»: просчет не начнется, если не была выбрана текстура и камера. Так же тут был реализован алгоритм «улучшенного» расчета стерео изображения с использованием спиннера «качество». В двух словах в чем это заключается: изображение сначала линейно растягивается и просчет ведется тоже «растянуто», а потом полученный результат сжимается до первоначального размера. Разницу можно увидеть на рис.7, рис.8, рис.9.

 
рис.8

 
рис.9

На рис.7 качество выставлено в единицу, а на рис.8 и рис.9 – 4 и 8 соответственно. Конечно чем выше качество, тем больше время просчета.

Вот и все. Теперь у нас имеется скрипт-утилита, с помощью которой можно из любого 3D-объекта получить стерео изображение. Очень надеюсь что урок был понятен (для этого надо дружить с геометрией :) и полезен (по крайней мере тем, что можно действительно посмотреть свои модели «в объеме»).

далее