Господа, есть вопрос, который так или иначе мучает многих, при создании анимации. Допустим я создаю управляющий элемент - кнопку. При нажатии, заданные объекты располагаются в определенном месте пространства. С глобальными координатами все понятно. Вопрос такой - как задать им координаты и ориентацию относительно родительского объекта?
Вопросы по Max Script (всего понемногу)
- Автор темы Александр Чернега
- Дата создания
- Рейтинг
- 7
Здравствуйте!
Напишу тут, чтобы не флудить мелкими вопросами в темах.
Подскажите пожалуйста, можно ли ставить на паузу выполнение скрипта? Но не просто на паузу, в общем при переборе объектов в сцене надо к каждому объекту применить действия и подождать пока slider пробежит определенное количесво кадров и запишутся ключи анимации.
Как-то так:
Для одного объекта прекрасно все работает. Если объектов больше одного - то полный треш. Пытался с разных сторон проблему решить, но не силен в максскрипте.
Пытался функцию sleep использовать, но вешает не только запись анимации и таймер, но и сам макс в том числе.
Через глобальную переменную и while - тоже самое.
Может быть вообще не стой стороны надо заходить?
Помогите плз разобраться.
Напишу тут, чтобы не флудить мелкими вопросами в темах.
Подскажите пожалуйста, можно ли ставить на паузу выполнение скрипта? Но не просто на паузу, в общем при переборе объектов в сцене надо к каждому объекту применить действия и подождать пока slider пробежит определенное количесво кадров и запишутся ключи анимации.
Как-то так:
Код:
(
---------fn
fn CurentFrames tempFrame obj1 =
(
global theObj = obj1
global tempFrame2=tempFrame
rollout CFrames "Frames"
(
timer tclock "Timer" interval:20
label var01 ""
on tclock tick do
(
var01.text = slidertime as string
if slidertime >= tempFrame2 do
(
print slidertime
stopAnimation()
max time end
max tool animmode
convertToMesh theObj
destroydialog CFrames
)
)
)
createdialog CFrames
)
-----------fn
for i in objects do
(
local FR = 98f
addModifier i (edit_mesh())
max time start
max tool animmode
playAnimation immediateReturn:true
CurentFrames FR i
)
)
Пытался функцию sleep использовать, но вешает не только запись анимации и таймер, но и сам макс в том числе.
Через глобальную переменную и while - тоже самое.
Может быть вообще не стой стороны надо заходить?
Помогите плз разобраться.
Код:
global theObj_index, theObjs, obj_init=0
rollout CFrames "Frames"
(
timer tclock "Timer" interval:20 active:false
label var01 ""
on CFrames open do
(
theObj_index=1; theObjs=objects as array
if(theObjs.count>0)then tclock.active=true
else destroydialog CFrames
)--on CFrames open do
on tclock tick do
(
FR = 98f
if(obj_init==0)then
(
addModifier theObjs[theObj_index] (edit_mesh())
max time start
max tool animmode
playAnimation immediateReturn:true
obj_init=1
)--if(obj_init==0)then
else--if(obj_init==0)then
(
var01.text = theObjs[theObj_index].name;
var01.text +=" "+(slidertime as string)
if slidertime >= FR do
(
stopAnimation(); max time end
max tool animmode; convertToMesh theObjs[theObj_index]
theObj_index+=1;obj_init=0;
if(theObj_index>theObjs.count)then destroyDialog CFrames
)--if slidertime >= FR do
)--else--if(obj_init==0)then
)--on tclock tick do
); createdialog CFrames
- Рейтинг
- 7
Вроде оформился код, есть чем поделиться.
У скрипта довольно узкая специализация - преобразование людей анимы в эдит меш с поинткэшем для экономии ресурсов.
Всем спасибо за помощь, реально выручили.
У скрипта довольно узкая специализация - преобразование людей анимы в эдит меш с поинткэшем для экономии ресурсов.
Всем спасибо за помощь, реально выручили.
Код:
---------fn
fn RecordKeys =
(
max time start
max tool animmode
playAnimation immediateReturn:true
rollout CFrames "Frames"
(
timer tclock "Timer" interval:20
label var01 ""
on tclock tick do
(
var01.text = slidertime as string
if slidertime >= (animationRange.end-20) do
(
stopAnimation()
max tool animmode
animationRange = interval animationRange.start (animationRange.end - 20)
max time start
destroydialog CFrames
)
)--end tclock tick
)--end rollout CFrames
CreateDialog CFrames
) --end fn
---------fn
rollout An "Anima"
( --start rollout
local All_Anima = #()
local theFolderPathPC
--interfeis
group "Point Cache Options (SEl OBJ only):"
(
label lbl01 " --------- Custom Range -------- "
spinner thePC_Start "Start" range:[-10000,10000,0] fieldwidth:55 align:#right type:#integer across:2
spinner thePC_End "End" range:[-10000,10000,100] fieldwidth:55 align:#right type:#integer
spinner rand_thePC_Start "Random" range:[0,10000,0] fieldwidth:55 align:#right type:#integer across:2
spinner rand_thePC_End "Random" range:[0,10000,0] fieldwidth:55 align:#right type:#integer
button EnableCustomRanges "Enable Custom Ranges" width:220
spinner ShiftRange "Shift" range:[-10000,10000,0] fieldwidth:55 align:#right type:#integer across:2
spinner randShift "Random" range:[0,10000,0] fieldwidth:55 align:#right type:#integer
button ShiftCustomRanges "Shift Custom Ranges" width:220
label lbl02 " --------- Original Range -------- "
button EnableOriginalRanges "Enable Original Ranges" width:220
)
group "Output Path:"
(
button BrowsePC "Browse" width:100 height:20 align:#left across:2
editText PathPC text:"PointCache path..." align:#left readOnly:true
)
button AddEditMesh_Record "step 1: Add Edit Mesh and record keys" width:220 height:30 align:#center border:false
button SavePC1 "step 2: Save PoinCache local" width:220 height:30 align:#center border:false enabled:false
button SavePC2 "step 3: Save PoinCache global" width:220 height:30 align:#center border:false enabled:false
button DelStuff "step 4: Delete stuff" width:220 height:30 align:#center border:false enabled:false
button VisEdges "step 5: All Edges True" width:220 height:30 align:#center border:false enabled:false
progressbar DoIt_prog color:orange height:5
on BrowsePC pressed do
(
theFolderPathPC= getSavePath caption: "Pick folder" initialDir:"C:\\"
PathPC.text = theFolderPathPC as string
)
on AddEditMesh_Record pressed do
(
animationRange = interval animationRange.start (animationRange.end + 20)
SavePC1.enabled = true
All_Anima = #()
for i in objects do -- add anima objects to "all_anima"
(
if classOf i == AnimaObjectSubMesh do
(
append All_Anima i
i.name = uniquename "Actor_"
)
)--end add anima objects to "all_anima"
for i in All_Anima do -- add edit_mesh
(
local count_AObj = All_Anima.count
local theProgressBarCount =1
addModifier i (edit_mesh())
DoIt_prog.value = 100.*theProgressBarCount/count_AObj
theProgressBarCount = theProgressBarCount + 1
) --end add edit_mesh
RecordKeys()
DoIt_prog.value = 0
)--end AddEditMesh_Record pressed
on SavePC1 pressed do
(
local count_AObj = All_Anima.count
local theProgressBarCount =1
if theFolderPathPC != undefined then
(
for i in All_Anima do
(
addModifier i (Point_Cache ())
local thePC = i.modifiers["Point Cache"]
try(deleteFile (theFolderPathPC + "\\" + i.name + ".pc2"))catch()
thePC.filename = theFolderPathPC + "\\" + i.name + ".pc2"
cacheOps.RecordCache thePC
DoIt_prog.value = 100.*theProgressBarCount/count_AObj
theProgressBarCount = theProgressBarCount + 1
)--end for i in All_Anima
)else messageBox "Path is undefined!"
SavePC2.enabled = true
DoIt_prog.value = 0
)--end SavePC1
on SavePC2 pressed do
(
local count_AObj = All_Anima.count
local theProgressBarCount =1
if theFolderPathPC != undefined then
(
for i in All_Anima do
(
maxOps.CollapseNodeTo i 2 true
addModifier i (Point_CacheSpacewarpModifier ())
local thePC_WSM = i.modifiers["Point Cache Binding"]
try(deleteFile (theFolderPathPC + "\\" + i.name + "_WSM" + ".pc2"))catch()
thePC_WSM.filename = theFolderPathPC + "\\" + i.name + "_WSM" + ".pc2"
cacheOps.RecordCache thePC_WSM
DoIt_prog.value = 100.*theProgressBarCount/count_AObj
theProgressBarCount = theProgressBarCount + 1
)--end for i in All_Anima
)else messageBox "Path is undefined!"
DelStuff.enabled = true
DoIt_prog.value = 0
)--end SavePC2
on DelStuff pressed do
(
deleteKeys All_Anima #allKeys
for i in All_Anima do
(
maxOps.CollapseNodeTo i 2 true
)
VisEdges.enabled = true
)-- end on DelStuff pressed do
on VisEdges pressed do
(
for i in All_Anima do try(i.allEdges = true)catch()
)--end on VisEdges pressed do
on EnableCustomRanges pressed do
(
for i in selection do
(
try(
i.modifiers["Point Cache"].playbackType = 2
i.modifiers["Point Cache"].playbackStart = thePC_Start.value + (random -rand_thePC_Start.value rand_thePC_Start.value)
i.modifiers["Point Cache"].playbackEnd = thePC_End.value + (random -rand_thePC_End.value rand_thePC_End.value)
)catch()
try(
i.modifiers["Point Cache Binding"].playbackType = 2
i.modifiers["Point Cache Binding"].playbackStart = thePC_Start.value + (random -rand_thePC_Start.value rand_thePC_Start.value)
i.modifiers["Point Cache Binding"].playbackEnd = thePC_End.value + (random -rand_thePC_End.value rand_thePC_End.value)
)catch()
)
) -- end on EnableCustomRanges pressed do
on ShiftCustomRanges pressed do
(
for i in selection do
(
try(
i.modifiers["Point Cache"].playbackType = 2
local thePB_Start = i.modifiers["Point Cache"].playbackStart
local thePB_End = i.modifiers["Point Cache"].playbackEnd
i.modifiers["Point Cache"].playbackStart = thePB_Start + ShiftRange.value + (random -randShift.value randShift.value)
i.modifiers["Point Cache"].playbackEnd = thePB_End + ShiftRange.value + (random -randShift.value randShift.value)
)catch()
try(
i.modifiers["Point Cache Binding"].playbackType = 2
local thePB_Start = i.modifiers["Point Cache Binding"].playbackStart
local thePB_End = i.modifiers["Point Cache Binding"].playbackEnd
i.modifiers["Point Cache Binding"].playbackStart = thePB_Start + ShiftRange.value + (random -randShift.value randShift.value)
i.modifiers["Point Cache Binding"].playbackEnd = thePB_End + ShiftRange.value + (random -randShift.value randShift.value)
)catch()
)
) -- end on ShiftCustomRanges do
on EnableOriginalRanges pressed do
(
for i in selection do
(
try(
i.modifiers["Point Cache"].playbackType = 0
)catch()
try(
i.modifiers["Point Cache Binding"].playbackType = 0
)catch()
)
) -- end on EnableOriginalRanges pressed do
)--end rollout
createDialog An 250 445
- Рейтинг
- 31
кстати, как оцениваете перспективы python - как альтернативу maxscript'a???
Далее, вопрос можно разделить на две составляющие: техническую и идеологическую.
С технической стороной всё достаточно ясно. Из плюсов имеем: (1) более продвинутый, по сравнению с MaxScript, язык программирования и (2) богатую питонью библиотеку. Из минусов: достаточно корявая интеграция с 3ds max, со многими нигде не документированными подводными камнями. Мне также не понравилась привязка к Python 2.x. Логичнее было бы новую разработку привязывать к более новой (и синтаксически несовместимой с 2.х) версии 3.х.
С идеологической стороной - больше вопросов, чем ответов. Вопрос первый: "а оно надо?" Очевидный ответ: надо, если кто-то об этом не только задумался, но и даже реализовал. А если, как говорил Чапаю Петька, "посмотреть в мировом масштабе"? Imho - не надо. Сейчас, практически, ни кто не знает одного языка программирования (MaxScript), а тогда не будут знать два языка. И что толку? Используют MaxScript - сотни, пишут на нём - десятки, а знают досконально - единицы. Это при том, что используют 3ds max многие тысячи людей.
Вопрос второй: а так ли нужны те плюсы, которые мы получаем от Питона в Максе? Лично для меня ответ не очевиден. Регулярные выражения, доступ к базам данных, доступ к интернет-ресурсам, доступ к ресурсам ОС, многопоточные вычисления... Это всё круто, но зачем это в Максе? Нет, я допускаю, что кому-то (одному) понадобится импортировать в Макс некие данные из БД, но в остальных 99.9% случаев это не нужно. То же относится и к "продвинутости" самого языка: для задач, выполняемых MaxScript, его синтаксических конструкций и библиотеки функций вполне достаточно.
Следующее соображение: есть люди, которым не нравится MaxScript и они бы не отказались от альтернативы. (Я сам не в восторге от него.) Но жопа уже случилась. И причин две: (1) недостаточно качественное проектирование самого 3ds max, как программного продукта, и (2) решение принять в качестве скриптового языка MaxScript, а не встроить в Макс уже существующий язык (Perl, JavaScript, Ruby или тот же Python, хотя последнего, кажется, тогда ещё не было) со специфическими "максовскими" библиотеками. Эти две проблемы надо было решать тогда, а сейчас мы имеем то, что имеем. И выбраться из этого положения без полной переработки 3ds max, практически, невозможно. (И я очень сомневаюсь, что Autodesk пойдёт на такое.) Поэтому костыли в виде Питона погоды не сделают.
Так что на мой взгляд, разработка интересна только с академической точки зрения. А практические перспективы - сомнительны.
Я увлёкся MaxScript не так давно. Раньше писал на С++. Но разобраться с ним до мелочей жизни не хватит. Вот пишу я скрипт и произвожу булеву операцию. Вычитаемый объект исчезает, а оставшийся
объект теряет такие свойства как length, width. Теперь что изменять эти величины невозможно,
кроме как преобразования масштабированием? Но масштабирование (допустим полого ящика) увеличивает и толщину его стенок.Да и scale грубый метод, даже если я оперирую float. Есть ли у объекта какие ещё свойства для изменения размеров, а то я ничего не могу найти через инструкцию show.
объект теряет такие свойства как length, width. Теперь что изменять эти величины невозможно,
кроме как преобразования масштабированием? Но масштабирование (допустим полого ящика) увеличивает и толщину его стенок.Да и scale грубый метод, даже если я оперирую float. Есть ли у объекта какие ещё свойства для изменения размеров, а то я ничего не могу найти через инструкцию show.
произвожу булеву операцию
оставшийся объект теряет такие свойства как length, width
Есть ли у объекта какие ещё свойства для изменения размеров
оставшийся объект теряет такие свойства как length, width
Есть ли у объекта какие ещё свойства для изменения размеров
Код:
try destroydialog test catch()
rollout test "Test"
(
spinner sp_length "Length" type:#worldunits range:[0,1e9,0]
on test open do
(
b=box();b.length=51;b.width=100;b.height=50
s=sphere();s.radius=25;s.pos=[0,-25,0]
b.name="box_igorznag";s.name="sphere_igorznag"
bo=boolObj.createBooleanObject b
boolObj.setOperandB bo s 4 1
bo.box_igorznag.length.controller=bezier_float()
sp_length.controller=bo.box_igorznag.length.controller
select bo; completeRedraw();
)--on test open
); createdialog test
Здравствуйте. Подскажите как попроще сделать проверку и разделение элементов из одного массива по нескольким на основе каких либо условий, в данном случае по имени объекта? Ну или поправьте меня пжл, если я совсем неправильно это делаю, а то все мои познания в максскрипте до этого, да и в общем во всем связанном с программированием ограничивались простыми макросами в пару строк.
Вот такое пытаюсь использовать, но в итоге получаю многократное повторение одних и тех же элементов в полученных массивах. Так понимаю, что это из-за многократной проверки исходного массива с выделенными объектами, а другие способы пока у меня отказываются работать даже так.
Вот такое пытаюсь использовать, но в итоге получаю многократное повторение одних и тех же элементов в полученных массивах. Так понимаю, что это из-за многократной проверки исходного массива с выделенными объектами, а другие способы пока у меня отказываются работать даже так.
Код:
aSelection = selection as array
for i = 1 to aSelection.count do
(
if matchPattern aSelection[i].name pattern:"*1x*" == true then
append aSingle aSelection[i]
else
if matchPattern aSelection[i].name pattern:"*2x*" == true then
append aDouble aSelection[i]
else
if matchPattern aSelection[i].name pattern:"*3x*" == true then
append aTriple aSelection[i]
else
if matchPattern aSelection[i].name pattern:"*4x*" == true then
append aQuarter aSelection[i]
else
if matchPattern aSelection[i].name pattern:"*cx*" == true then
append aCorner aSelection[i]
Последнее редактирование:
похоже, это моя ошибка, особенно, если у Вас оно работает как надо) похоже где то я случайно эту функцию в цикл пустил, но никак не пойму где, перепроверю. В крайнем случае, просто обрежу полученные массивы после определенного индекса и буду использовать как есть.
А проверял банально, через вызов полученных массивов, ровно пять раз и повторялись...
Дополнение:
Ну да... Так и оказалось, и сразу все упростилось, спасибо за помощь, буду пытаться дописать эту штуковину, но возможно, до очередной глупой ошибки)
А проверял банально, через вызов полученных массивов, ровно пять раз и повторялись...
Дополнение:
Ну да... Так и оказалось, и сразу все упростилось, спасибо за помощь, буду пытаться дописать эту штуковину, но возможно, до очередной глупой ошибки)
Последнее редактирование:
Снова приветствую, опять с проблемой
В общем пытаюсь написать функцию, которая должна выстраивать комбинации элементов (объектов) из заданного массива в порядке элементов этого массива и значение элементов, которого означает номер набора, содержащего элементы подходящего типа.
Каждая комбинация должна записываться в ключи анимации, чтобы потом можно было срендерить все сразу.
Сложность заключается в проверках какой элемента в массиве является угловым, после которого все последующие элементы поворачиваются на 90 градусов и выстраиваются уже вдоль оси y.
не знаю, насколько понятно я объяснил, чего добиваюсь
если в кратце переменная aCombIndexes - массив с массивами, в котором каждый содержит комбинацию, состоящую из набора порядковых номеров элементов.
aAllElem - главный массив, содержащий упорядоченные по типу наборы элементов
aCopyIndx - массив содержащий неиспользуемые в текущей комбинации элементы, которые удвигаются за пределы камеры
Проблема в том, что нужные координаты присваиваются только угловому элементу.
Ощущение, что я как то совсем не с той стороны подхожу к задаче.
В общем пытаюсь написать функцию, которая должна выстраивать комбинации элементов (объектов) из заданного массива в порядке элементов этого массива и значение элементов, которого означает номер набора, содержащего элементы подходящего типа.
Каждая комбинация должна записываться в ключи анимации, чтобы потом можно было срендерить все сразу.
Сложность заключается в проверках какой элемента в массиве является угловым, после которого все последующие элементы поворачиваются на 90 градусов и выстраиваются уже вдоль оси y.
не знаю, насколько понятно я объяснил, чего добиваюсь
если в кратце переменная aCombIndexes - массив с массивами, в котором каждый содержит комбинацию, состоящую из набора порядковых номеров элементов.
aAllElem - главный массив, содержащий упорядоченные по типу наборы элементов
aCopyIndx - массив содержащий неиспользуемые в текущей комбинации элементы, которые удвигаются за пределы камеры
Проблема в том, что нужные координаты присваиваются только угловому элементу.
Код:
fn PositionInCombination aCombIndexes =
(
if aCombIndexes.count > 1 then
(
animationRange = interval animationRange.start (aCombIndexes.count-1) --set Time Range
animate on
for i = 1 to aCombIndexes.count do --for every combinations do
(
at time i-1 --loop for every frame starting from 0
(
CompArrays aCombIndexes[i]
for iId = 1 to aCopyIndx.count do
(
for f in aAllElem[aCopyIndx[iId]] do
(
f.pos = [-1000,-1000,0]
)
)
--fndItm = findItem aCombIndexes[i] 5
for iCmb = 1 to aCombIndexes[i].count do
(
if aCombIndexes[i][iCmb] == 5 and iCmb == 1 then
(
for f in aAllElem[aCombIndexes[i][iCmb]] do
(
f.pos = [72.5,72.5,0]
break
)
)
else
(
if iCmb == 1 then
(
for f in aAllElem[aCombIndexes[i][iCmb]] do
(
f.pos = [-128.0,72.5,0]
)
)
else
(
if aCombIndexes[i][iCmb] == 5 then
(
for f in aAllElem[aCombIndexes[i][iCmb]] do
(
f.pos.x = ((aAllElem[aCombIndexes[i][iCmb-1]][1].pos.x)+(GetLinearDimensions f 1)+(random -0.3 0.5))
f.pos.y = ((aAllElem[aCombIndexes[i][iCmb-1]][1].pos.y))
f.pos.z = 0
)
for iCmb = iCmb+1 to aCombIndexes[i].count do
(
for f in aAllElem[aCombIndexes[i][iCmb]] do
(
rotate f (angleAxis 90 z_axis)
f.pos.x = ((aAllElem[aCombIndexes[i][iCmb-1]][1].pos.x))
f.pos.y = ((aAllElem[aCombIndexes[i][iCmb-1]][1].pos.y)+(GetLinearDimensions f 2)+(random -0.3 0.5))
f.pos.z = 0
)
)
)
)
)
)
)
)
)
)
не знаю, насколько понятно я объяснил, чего добиваюсь
Проблема в том, что нужные координаты присваиваются только угловому элементу.
Ощущение, что я как то совсем не с той стороны подхожу к задаче.
ну ок, попробую. Да все это элементы создания комбинаций для стенок. Есть 36 отдельных объектов в сцене, имеющих каждый уникальное имя, подразделяющихся на пять типов, 4 различающихся по ширине, плюс угловой тип, который служит для создания угловой стенки. Нужно с помощью данной функции разместить объекты, основываясь на координатах первого элемента комбинации и ширине следующего объекта слева, если присутствует угол развернуть все последующие объекты на 90 градусов и продолжить выставлять координаты уже по другой оси. Для каждой комбинации записать ключи положения объектов
При вызове функции, в нее передается двухуровневый массив, содержащий список комбинаций. Функция должна проверить сколько элементов первого уровня в переданном массиве, установить интервал анимации в кадрах в соответствии с количеством элементов, проверить элементы массива второго уровня, в соответствии с которыми присвоить новые координаты объектам соответствующего типа (в случае с обычными элементами все просто, первому объекту универсальные координаты, всем последующим координаты в зависимости от его ширины), убрать неиспользуемые в текущей комбинации объекты, записать для объектов в комбинации ключевые кадры.
Дополнение:
Походу я переусложнил, вероятно надо распотрошить эту функцию на пару макросов или даже простых скриптиков в пару строк, да провести всю операцию в полуавтоматическом режиме... правда там еще была вторая часть скрипта, не хуже этой, но пока что с ней все было гладко)
При вызове функции, в нее передается двухуровневый массив, содержащий список комбинаций. Функция должна проверить сколько элементов первого уровня в переданном массиве, установить интервал анимации в кадрах в соответствии с количеством элементов, проверить элементы массива второго уровня, в соответствии с которыми присвоить новые координаты объектам соответствующего типа (в случае с обычными элементами все просто, первому объекту универсальные координаты, всем последующим координаты в зависимости от его ширины), убрать неиспользуемые в текущей комбинации объекты, записать для объектов в комбинации ключевые кадры.
Дополнение:
Походу я переусложнил, вероятно надо распотрошить эту функцию на пару макросов или даже простых скриптиков в пару строк, да провести всю операцию в полуавтоматическом режиме... правда там еще была вторая часть скрипта, не хуже этой, но пока что с ней все было гладко)
Последнее редактирование:
Кто по массивам шпарит, подскажите раздел в Help-е или черкните как отсортировать массив из Point3 #([x,y,z],[x,y,z],[x,y,z],...) по x или по y или по z. Охота добавить эстетики. А то раскидывает, конечно, как попало:
Код:
--a1 Куб, b1 мелкая Mesh (гора, предположим)
a1=$[1]; b1=$[2]
aGab=(a1.max.x-a1.min.x)
pv_b1=for i=1 to b1.verts.count collect b1.verts[i].pos
xpv_b1=for i=1 to pv_b1.count collect ((pv_b1[i][1]/aGab) as integer)*aGab
ypv_b1=for i=1 to pv_b1.count collect ((pv_b1[i][2]/aGab) as integer)*aGab
zpv_b1=for i=1 to pv_b1.count collect ((pv_b1[i][3]/aGab) as integer)*aGab
npv_b1=for i=1 to b1.verts.count collect [(xpv_b1[i]),(ypv_b1[i]),(zpv_b1[i])]
pa2=makeUniqueArray npv_b1
clearselection(); hide b1
for i=1 to pa2.count do
(
a2=copy a1 pos:(pa2[i]) parent:b1
max views redraw
)
unhide b1; select b1
Вложения
-
158,9 КБ Просмотров: 388
Последнее редактирование:
- Рейтинг
- 15
Функцию qsort смотри в хелпе.
как отсортировать массив из Point3 #([x,y,z],[x,y,z],[x,y,z],...) по x или по y или по z
Код:
(
fn sortPoint3ArrByAxis_fn v1 v2 axis: = -- axis: #x, #y, #z;
(
local v = case axis of
(
#x:(v1.x - v2.x)
#y:(v1.y - v2.y)
#z:(v1.z - v2.z)
)
case of
(
(v < 0):-1
(v > 0):1
default:0
)
)
local p3Arr = for i = 1 to 10 collect
(
random [-100,-100,-100] [100,100,100]
)
qsort p3Arr sortPoint3ArrByAxis_fn axis:#x
format "%\n" p3Arr
)