В качестве идеи для написания был взят урок по MEL Игоря Леводянского, от исходного кода не осталось ничего, все было переписано заново с нуля.
//посвящается всем, кто работает в Maya, скрипт предназначен для создания террэйна (b не только) всего за несколько кликов мыши
//комплект состоит из двух скриптов первый из которых умеет разбивать мэш ориентируяь на текстуру
//содержащую карту разбиения, а вторая строить поверхность по карте высот
//вместо бампа или дисплэйса
//Скрипт умеет работать как целиком с объектом, так и с го частью
//часть один, разбивающая
//небольшая инстркция:
//1) необходимо назначить на нужный фэйс/фэйсы карту разбиения (это текстура содержащая только черный и белый цвет
//белый соответствует местам, где необходимо получить разбиение)
//2)проверте имя файла текстуры если это не "file1", то неообходимо в строке 112
//заменить "file1" на имя вашего файла текстуры(имеется в виду имя нода "file"), либо изменить имя вашего файла текстуры на "file1"
//3) Крайне желательно сделать PlanarMap относительно нужной оси чтобы UV-кординаты
//равномерно распределились по всей поверхности фэйса/фэйсов, иначем ожно получить неожиданные результаты
//4)выделить нужные фэйсы
//4)все вроде...
//...а если после первого запуска ничего не произошло, то значт что все UV-кординаты вернули черный цвет
//в таком случае необхлдимо руками с помощью команды polySubdivideFacet -dv 1 -m 0 -ch 1; разбить фэйсы
//ну или если не омандой, то через меню EditMesh->AddDivision, настройках необходимо поставить
//division levels - 1, а Mode - quads, на мой взгляд командой быстрее...
//переменная-счетчик для цикла
int $mas_global_i = 0;
//для начала создаем основную переменную отвечающую за количество повторов цикла
int $mas_global_counter = 1;
//теперь спросим пользователя о желаемом количестве повторов цикла
string $text;
string $result = `promptDialog
-title "Количетво проходов"
-message "Введте количество повторов цикла \n(первый раз можно поставить около 4-6, \nдалее не ркомендуется ставить более одного так \nкак может возникнуть нехватка памяти) не забываем сохраняться
) \nзначение по дефолту равно 1 (веденное значение должно быть целым числом 1 2 3...):"
-button "OK" -button "Cancel"
-sf true
-defaultButton "OK" -cancelButton "Cancel"
-dismissString "Cancel"`;
if ($result == "OK")
{
$mas_global_counter = `promptDialog -query -text`;
}
//далее пошел основной код это корневой цикл количество проходов которого мы и задавали в самом начале
for ($mas_global_i = 0; $mas_global_i<$mas_global_counter;$mas_global_i++)
{
//конвертируем выделенный фэйсы в связанные с ними UV-координаты
ConvertSelectionToUVs;
//в этом массиве у нас будут храниться все UV-кординаты вернувшие "нечерный цвет"
string $mas_face_uv[];
//здесь будут находится все выделенные UV-координаты
string $all[];
//здесь будут храниться номера UV-координат вернувших "нечерный цвет"
int $mas_uv_num[];
//здесь - имя выделенного объекта
string $mas_nameOBj[];
//это временная переменная содержащая имя UV-кординаты целиком
string $mas_temp[];
//счетчики для циклов
int $mas_i;
int $mas_k;
//помещаем все выделенные UV-коорднаты в один массив
$all = `ls -sl`;
//это первый основной подцикл, итогом его работы будет массив номеров выделенных UV-кординат
for ($mas_i = 0; $mas_i < size($all); $mas_i++)
{
//создаем новый масив в который помещаем имя выделенной UV-кординаты/координат
string $mas_name_uv[];
select -r $all[$mas_i];
$mas_name_uv = `ls -sl`;
//разбиваем это имя несколько раз в случае если этот элемент содержит информацию
//о вылелении нескольких UV-кординат, то находим промежуточные значения
//например pCube.map[5:8] нужно получить промежуточные значени 6 и 7
tokenize $mas_name_uv[0] "[" $mas_name_uv;
//здесь получили имя объкта, записали его в переменную
$mas_nameOBj[0] = $mas_name_uv[0];
//разбиваем дальше
tokenize $mas_nameOBj[0] "." $mas_nameOBj;
tokenize $mas_name_uv[1] ":" $mas_name_uv;
//получаем номера первой и последней UV-кординаты записываем в переменные
//используя автопреобразоваие типов получим из значений типа string значения типа int
//Maya в этом месте ругнется парой варнингов
int $mas_max_uv = $mas_name_uv[1];
int $mas_min_uv = $mas_name_uv[0];
//далее проверяем если максимальное значение равно нулю то текущий элемент массива
//содержит информации тольо об одной UV-кординате, значит нужное нам значение
//находитсся в переменной содержащей минимальное значение добавляем ее к массиву
if ($mas_max_uv == 0)
{
//в таком исполнении команда добавляет элемент к существующему массиву
$mas_uv_num[size($mas_uv_num)] = $mas_min_uv;
}
//если же нам все-таки надо найти промежуточные значения, то запускается эта часть
//словного оператора if
else
{
//добавляем к массиву максимальное значение, а то потом оно потеряется
$mas_uv_num[size($mas_uv_num)] = $mas_max_uv;
}
//а здесь находим промежуточные значения цикл будет работать до тех пор пока
//минимальное значение не будет равно максимальному
while ($mas_min_uv != $mas_max_uv && $mas_max_uv > 0)
{
//отнимем у текущего максимального значения единицу
$mas_max_uv--;
//добавим получившееся число к массиву и проверим на соответствие условию
$mas_uv_num[size($mas_uv_num)] = $mas_max_uv;
}
}
//это второй основной подцикл который находит UV-кординаты вернувшие нечерный цвет
for ($mas_k=0; $mas_k<size($mas_uv_num); $mas_k++)
{
//выделяем первую UV-кординату
select ($mas_nameOBj[0]+".map[" + $mas_uv_num[$mas_k]+ "]");
//получаем координаты данной UV
float $uvNum[] = `polyEditUV -q `;
//создаем две переменные в которые и помещаем полученные координаты
float $Ucoord;
float $Vcoord;
$Ucoord = $uvNum[0];
$Vcoord = $uvNum[1];
//проверяем на "нечерность" данный участок текстуры перед запуском проверте
//чтобы имя файла текстуры назначенного на поверхность было "file1" лиюо замените
//в этой строке "file1" на имя вашего файла
float $cFl_1[0] = `colorAtPoint -u $Ucoord -v $Vcoord file1`;
//в случае если цвет черный команда "colorAtPoint" вернет 0
if ( $cFl_1[0]!= 0)
{
//запишем получившееся имя UV-кординаты в переменную
$mas_temp = `ls -sl`;
//добавим к массиву
$mas_face_uv[size($mas_face)] = $mas_temp[0];
}
}
//выделим массив UV-кординат вернувших нечерный цвет
select -r $mas_face_uv;
//конвертируем выделение в фэйсы
ConvertSelectionToFaces;
//разобъем выделенные фэйсы
polySubdivideFacet -dv 1 -m 0 -ch 1;
//уберем за собой мусор очистив массивы
clear $mas_face_uv;
clear $mas_uv_num;
clear $mas_uv_num;
clear $all;
clear $mas_nameOBj;
}
//часть два поднимающая
//здесь подробного описания не будет так как все ужеесть в опиании первой части,
//остановлюсь только на местах, где что-то изменилось
ConvertSelectionToUVs;
string $mas_face[];
string $all[];
int $mas_uv_num[];
string $mas_nameOBj[];
string $mas_temp[];
//массив содержищий значения высот точек
float $mas_hight[];
int $mas_i;
int $mas_k;
int $mas_j;
//переменная отвечабщая за коэффицент высоты
float $mas_index = 1;
string $text;
string $result = `promptDialog
-title "Множитель высоты"
-message "Введте коэффициент высоты (по дефолту белый = 1, черный = 0, коэффициент = 1):"
-button "OK" -button "Cancel"
-defaultButton "OK" -cancelButton "Cancel"
-dismissString "Cancel"`;
if ($result == "OK")
{
$mas_index = `promptDialog -query -text`;
}
$all = `ls -sl`;
for ($mas_i = 0; $mas_i < size($all); $mas_i++)
{
string $mas_name_uv[];
select -r $all[$mas_i];
$mas_name_uv = `ls -sl`;
tokenize $mas_name_uv[0] "[" $mas_name_uv;
$mas_nameOBj[0] = $mas_name_uv[0];
tokenize $mas_nameOBj[0] "." $mas_nameOBj;
tokenize $mas_name_uv[1] ":" $mas_name_uv;
int $mas_max_uv = $mas_name_uv[1];
int $mas_min_uv = $mas_name_uv[0];
if ($mas_max_uv == 0)
{
$mas_uv_num[size($mas_uv_num)] = $mas_min_uv;
}
else
{
$mas_uv_num[size($mas_uv_num)] = $mas_max_uv;
}
while ($mas_min_uv != $mas_max_uv && $mas_max_uv > 0)
{
$mas_max_uv--;
$mas_uv_num[size($mas_uv_num)] = $mas_max_uv;
}
}
for ($mas_k=0; $mas_k<size($mas_uv_num); $mas_k++)
{
select ($mas_nameOBj[0]+".map[" + $mas_uv_num[$mas_k]+ "]");
float $uvNum[] = `polyEditUV -q `;
float $Ucoord;
float $Vcoord;
$Ucoord = $uvNum[0];
$Vcoord = $uvNum[1];
float $cFl_1[0] = `colorAtPoint -u $Ucoord -v $Vcoord file1`;
if ( $cFl_1[0]!= 0)
{
$mas_temp = `ls -sl`;
//здесь в первый массив записывается имя UV-кординаты, а во второй соответствующая ей высота умноженная на коэффициент
$mas_face[size($mas_face)] = $mas_temp[0];
$mas_hight[size($mas_hight)] = $cFl_1[0]*$mas_index;
}
}
//этот цикл по очереди выделяет точки вернувшие нечерный цвет после чего смещает их вверх с учетом коэффициента
for ($mas_j= 0; $mas_j<size($mas_face); $mas_j++)
{
//выделил UV-кординату
select -r $mas_face[$mas_j];
//конвертировал выделение в Vertex
ConvertSelectionToVertices;
//сместил вверх на соответствующее значение
move -r 0 $mas_hight[$mas_j] 0 ;
}
//уберем мусор
clear $mas_face;
clear $mas_uv_num;
clear $mas_uv_num;
clear $all;
clear $mas_nameOBj;
clear $mas_hight;
Благодарю за внимание
Если скрипт кому-то пригодится есть несколько мыслей по его модернизации, но пока мне самому это не надо, но если попросите сделаю, в частности уберется необходимость в замене имени файла.
Если возникли проблемы с использованием, опять же пишите
//посвящается всем, кто работает в Maya, скрипт предназначен для создания террэйна (b не только) всего за несколько кликов мыши
//комплект состоит из двух скриптов первый из которых умеет разбивать мэш ориентируяь на текстуру
//содержащую карту разбиения, а вторая строить поверхность по карте высот
//вместо бампа или дисплэйса
//Скрипт умеет работать как целиком с объектом, так и с го частью
//часть один, разбивающая
//небольшая инстркция:
//1) необходимо назначить на нужный фэйс/фэйсы карту разбиения (это текстура содержащая только черный и белый цвет
//белый соответствует местам, где необходимо получить разбиение)
//2)проверте имя файла текстуры если это не "file1", то неообходимо в строке 112
//заменить "file1" на имя вашего файла текстуры(имеется в виду имя нода "file"), либо изменить имя вашего файла текстуры на "file1"
//3) Крайне желательно сделать PlanarMap относительно нужной оси чтобы UV-кординаты
//равномерно распределились по всей поверхности фэйса/фэйсов, иначем ожно получить неожиданные результаты
//4)выделить нужные фэйсы
//4)все вроде...
//...а если после первого запуска ничего не произошло, то значт что все UV-кординаты вернули черный цвет
//в таком случае необхлдимо руками с помощью команды polySubdivideFacet -dv 1 -m 0 -ch 1; разбить фэйсы
//ну или если не омандой, то через меню EditMesh->AddDivision, настройках необходимо поставить
//division levels - 1, а Mode - quads, на мой взгляд командой быстрее...
//переменная-счетчик для цикла
int $mas_global_i = 0;
//для начала создаем основную переменную отвечающую за количество повторов цикла
int $mas_global_counter = 1;
//теперь спросим пользователя о желаемом количестве повторов цикла
string $text;
string $result = `promptDialog
-title "Количетво проходов"
-message "Введте количество повторов цикла \n(первый раз можно поставить около 4-6, \nдалее не ркомендуется ставить более одного так \nкак может возникнуть нехватка памяти) не забываем сохраняться
-button "OK" -button "Cancel"
-sf true
-defaultButton "OK" -cancelButton "Cancel"
-dismissString "Cancel"`;
if ($result == "OK")
{
$mas_global_counter = `promptDialog -query -text`;
}
//далее пошел основной код это корневой цикл количество проходов которого мы и задавали в самом начале
for ($mas_global_i = 0; $mas_global_i<$mas_global_counter;$mas_global_i++)
{
//конвертируем выделенный фэйсы в связанные с ними UV-координаты
ConvertSelectionToUVs;
//в этом массиве у нас будут храниться все UV-кординаты вернувшие "нечерный цвет"
string $mas_face_uv[];
//здесь будут находится все выделенные UV-координаты
string $all[];
//здесь будут храниться номера UV-координат вернувших "нечерный цвет"
int $mas_uv_num[];
//здесь - имя выделенного объекта
string $mas_nameOBj[];
//это временная переменная содержащая имя UV-кординаты целиком
string $mas_temp[];
//счетчики для циклов
int $mas_i;
int $mas_k;
//помещаем все выделенные UV-коорднаты в один массив
$all = `ls -sl`;
//это первый основной подцикл, итогом его работы будет массив номеров выделенных UV-кординат
for ($mas_i = 0; $mas_i < size($all); $mas_i++)
{
//создаем новый масив в который помещаем имя выделенной UV-кординаты/координат
string $mas_name_uv[];
select -r $all[$mas_i];
$mas_name_uv = `ls -sl`;
//разбиваем это имя несколько раз в случае если этот элемент содержит информацию
//о вылелении нескольких UV-кординат, то находим промежуточные значения
//например pCube.map[5:8] нужно получить промежуточные значени 6 и 7
tokenize $mas_name_uv[0] "[" $mas_name_uv;
//здесь получили имя объкта, записали его в переменную
$mas_nameOBj[0] = $mas_name_uv[0];
//разбиваем дальше
tokenize $mas_nameOBj[0] "." $mas_nameOBj;
tokenize $mas_name_uv[1] ":" $mas_name_uv;
//получаем номера первой и последней UV-кординаты записываем в переменные
//используя автопреобразоваие типов получим из значений типа string значения типа int
//Maya в этом месте ругнется парой варнингов
int $mas_max_uv = $mas_name_uv[1];
int $mas_min_uv = $mas_name_uv[0];
//далее проверяем если максимальное значение равно нулю то текущий элемент массива
//содержит информации тольо об одной UV-кординате, значит нужное нам значение
//находитсся в переменной содержащей минимальное значение добавляем ее к массиву
if ($mas_max_uv == 0)
{
//в таком исполнении команда добавляет элемент к существующему массиву
$mas_uv_num[size($mas_uv_num)] = $mas_min_uv;
}
//если же нам все-таки надо найти промежуточные значения, то запускается эта часть
//словного оператора if
else
{
//добавляем к массиву максимальное значение, а то потом оно потеряется
$mas_uv_num[size($mas_uv_num)] = $mas_max_uv;
}
//а здесь находим промежуточные значения цикл будет работать до тех пор пока
//минимальное значение не будет равно максимальному
while ($mas_min_uv != $mas_max_uv && $mas_max_uv > 0)
{
//отнимем у текущего максимального значения единицу
$mas_max_uv--;
//добавим получившееся число к массиву и проверим на соответствие условию
$mas_uv_num[size($mas_uv_num)] = $mas_max_uv;
}
}
//это второй основной подцикл который находит UV-кординаты вернувшие нечерный цвет
for ($mas_k=0; $mas_k<size($mas_uv_num); $mas_k++)
{
//выделяем первую UV-кординату
select ($mas_nameOBj[0]+".map[" + $mas_uv_num[$mas_k]+ "]");
//получаем координаты данной UV
float $uvNum[] = `polyEditUV -q `;
//создаем две переменные в которые и помещаем полученные координаты
float $Ucoord;
float $Vcoord;
$Ucoord = $uvNum[0];
$Vcoord = $uvNum[1];
//проверяем на "нечерность" данный участок текстуры перед запуском проверте
//чтобы имя файла текстуры назначенного на поверхность было "file1" лиюо замените
//в этой строке "file1" на имя вашего файла
float $cFl_1[0] = `colorAtPoint -u $Ucoord -v $Vcoord file1`;
//в случае если цвет черный команда "colorAtPoint" вернет 0
if ( $cFl_1[0]!= 0)
{
//запишем получившееся имя UV-кординаты в переменную
$mas_temp = `ls -sl`;
//добавим к массиву
$mas_face_uv[size($mas_face)] = $mas_temp[0];
}
}
//выделим массив UV-кординат вернувших нечерный цвет
select -r $mas_face_uv;
//конвертируем выделение в фэйсы
ConvertSelectionToFaces;
//разобъем выделенные фэйсы
polySubdivideFacet -dv 1 -m 0 -ch 1;
//уберем за собой мусор очистив массивы
clear $mas_face_uv;
clear $mas_uv_num;
clear $mas_uv_num;
clear $all;
clear $mas_nameOBj;
}
//часть два поднимающая
//здесь подробного описания не будет так как все ужеесть в опиании первой части,
//остановлюсь только на местах, где что-то изменилось
ConvertSelectionToUVs;
string $mas_face[];
string $all[];
int $mas_uv_num[];
string $mas_nameOBj[];
string $mas_temp[];
//массив содержищий значения высот точек
float $mas_hight[];
int $mas_i;
int $mas_k;
int $mas_j;
//переменная отвечабщая за коэффицент высоты
float $mas_index = 1;
string $text;
string $result = `promptDialog
-title "Множитель высоты"
-message "Введте коэффициент высоты (по дефолту белый = 1, черный = 0, коэффициент = 1):"
-button "OK" -button "Cancel"
-defaultButton "OK" -cancelButton "Cancel"
-dismissString "Cancel"`;
if ($result == "OK")
{
$mas_index = `promptDialog -query -text`;
}
$all = `ls -sl`;
for ($mas_i = 0; $mas_i < size($all); $mas_i++)
{
string $mas_name_uv[];
select -r $all[$mas_i];
$mas_name_uv = `ls -sl`;
tokenize $mas_name_uv[0] "[" $mas_name_uv;
$mas_nameOBj[0] = $mas_name_uv[0];
tokenize $mas_nameOBj[0] "." $mas_nameOBj;
tokenize $mas_name_uv[1] ":" $mas_name_uv;
int $mas_max_uv = $mas_name_uv[1];
int $mas_min_uv = $mas_name_uv[0];
if ($mas_max_uv == 0)
{
$mas_uv_num[size($mas_uv_num)] = $mas_min_uv;
}
else
{
$mas_uv_num[size($mas_uv_num)] = $mas_max_uv;
}
while ($mas_min_uv != $mas_max_uv && $mas_max_uv > 0)
{
$mas_max_uv--;
$mas_uv_num[size($mas_uv_num)] = $mas_max_uv;
}
}
for ($mas_k=0; $mas_k<size($mas_uv_num); $mas_k++)
{
select ($mas_nameOBj[0]+".map[" + $mas_uv_num[$mas_k]+ "]");
float $uvNum[] = `polyEditUV -q `;
float $Ucoord;
float $Vcoord;
$Ucoord = $uvNum[0];
$Vcoord = $uvNum[1];
float $cFl_1[0] = `colorAtPoint -u $Ucoord -v $Vcoord file1`;
if ( $cFl_1[0]!= 0)
{
$mas_temp = `ls -sl`;
//здесь в первый массив записывается имя UV-кординаты, а во второй соответствующая ей высота умноженная на коэффициент
$mas_face[size($mas_face)] = $mas_temp[0];
$mas_hight[size($mas_hight)] = $cFl_1[0]*$mas_index;
}
}
//этот цикл по очереди выделяет точки вернувшие нечерный цвет после чего смещает их вверх с учетом коэффициента
for ($mas_j= 0; $mas_j<size($mas_face); $mas_j++)
{
//выделил UV-кординату
select -r $mas_face[$mas_j];
//конвертировал выделение в Vertex
ConvertSelectionToVertices;
//сместил вверх на соответствующее значение
move -r 0 $mas_hight[$mas_j] 0 ;
}
//уберем мусор
clear $mas_face;
clear $mas_uv_num;
clear $mas_uv_num;
clear $all;
clear $mas_nameOBj;
clear $mas_hight;
Благодарю за внимание
Если скрипт кому-то пригодится есть несколько мыслей по его модернизации, но пока мне самому это не надо, но если попросите сделаю, в частности уберется необходимость в замене имени файла.
Если возникли проблемы с использованием, опять же пишите