Всем привет..
Давно хотел спросить и сегодня созрел.
Цепочка из, допустим, костей > SplineIK Solver > указываю на сплайн (Окружность, ровная, итераций хватает..)
Пожалуйста, кто-нибудь, скажите почему кости криво размещаются на сплайне, т.е, не совсем пивотами ?
Почему это происходит, и как это победить ?
При анимации по кругу заметен общий люфт.
На мат часть мне указывать не нужно.
Я просто прошу ответить на вопрос, который я задал.
Кости я выбрал как пример для простоты и показательности проблемы моего вопроса.
Подобная хрень происходит и в случае со слинкованной геометрией.
Делать - ничё. Просто, или подсказать как с такой "болтанкой" бороться,
или успокоить меня и сказать, что это в максе традиционно и не стоит мозгопара.
INCUSА цепь велосипедная ? две шестерёнки..как положено.
Попробуйте анимировать велосипедную цепь с помощью Path Constraint и LookAt Constraint.
Или такой способ тоже не подходит для этой задачи? Похожая задача есть в этом уроке.
Спасибо за участие. Подходить-то подходит...есть у меня эта книга в бумаге вместе с диском, на котором есть этот трак от танка...
Всё нормуль, ничего не болтает.
Но, всё это сложновато, по сравнению с заявленной простотой использования Spline IK Solver.
Мне удобнее допускать своё незнание , чем неполноценность инструмента, который специально под это заточен.
Хотелось бы от него увидеть сухую немецкую точность.
INCUSПодходить-то подходит. Но, всё это сложновато ...
В чем именно состоит сложность? Попробуйте выполнить этот простой пример:
Создаем один сплайн Circle и конвертируем его в Editable Spline.
Создаем один чайник Teapot. Выделяем сплайн и чайник.
Запускаем скрипт. В новом окне нажимаем кнопку Apply.
Анимируем % Along Path чайника, который находится в начале сплайна.
try (destroydialog igorznag_path_lookat) catch()
rollout igorznag_path_lookat "Chain. Path. LookAt."
(
--gui
radiobuttons rb_cs "" labels:#("Count:", "Spacing:") pos:[5,5] columns:1
spinner sp_count "" range:[2,1e9,10] fieldWidth:60 type:#integer pos:[65,5]
spinner sp_spacing "" range:[0,1e9,0] fieldWidth:60 type:#worldunits pos:[65,22]
checkbox chb_taf "Flip. Object LookAt Axis = X" pos:[5,42]
radiobuttons rb_stoa "Object Upnode Axis" labels:#("Y", "Z") pos:[5,60]
checkbox chb_stoaf "Flip" pos:[80,77]
label lbl_info "Spline Upnode Axis = Z" pos:[5,95]
button btn_apply "Apply" pos:[140,60] width:60 height:50
button btn_update "Update" pos:[145,10]
--functions
fn update_cs =
(
if(selection.count==2)then
(
spline_path=undefined; obj=undefined;
spline_types=#(SplineShape,line);cl1=classof selection[1];cl2=classof selection[2]
if(finditem spline_types cl1!=0 and finditem spline_types cl2==0)then
(spline_path=selection[1];obj=selection[2])
if(finditem spline_types cl2!=0 and finditem spline_types cl1==0)then
(spline_path=selection[2];obj=selection[1])
if(spline_path!=undefined)then
(
if numSplines spline_path==1 then
(
spline_length=0; sl_a=getSegLengths spline_path 1
if(sl_a.count>0)then spline_length=sl_a[sl_a.count]
if rb_cs.state==1 then sp_spacing.value=1.0*spline_length/sp_count.value
if rb_cs.state==2 then
(
if(sp_spacing.value>0)then
(
v=int(1.0*spline_length/sp_spacing.value)
if v<2 then v=2; sp_count.value=v
)--if(sp_spacing.value>0)then
else sp_count.value=2
)--if rb_cs.state==2 then
)--if numSplines spline_path==1 then
)--if(spline_path!=undefined)then
)--if(selection.count==2)then
)--fn update_cs =
--events
on btn_apply pressed do
(
if(selection.count==2)then
(
spline_path=undefined; obj=undefined;
spline_types=#(SplineShape,line);cl1=classof selection[1];cl2=classof selection[2]
if(finditem spline_types cl1!=0 and finditem spline_types cl2==0)then
(spline_path=selection[1];obj=selection[2])
if(finditem spline_types cl2!=0 and finditem spline_types cl1==0)then
(spline_path=selection[2];obj=selection[1])
if(spline_path!=undefined)then
(
if numSplines spline_path==1 then
(
undo on
(
with animate off
(
objs_temp_a=#(); objs_count=sp_count.value
script_continue=true
if objs_count>1000 then script_continue=queryBox "Continue?" title:"Count is a big number!"
if(script_continue==true)then
(
for i=1 to objs_count do
(
maxOps.cloneNodes obj cloneType:#instance newNodes:&n
append objs_temp_a n[1];
)--for i=1 to objs_count do
d=undefined
for i=1 to objs_temp_a.count do
(
if i==1 then
(
objs_temp_a[i].pos.controller = Path_Constraint()
c=objs_temp_a[i].pos.controller; c.path=spline_path
c.percent.controller=bezier_float();
setBeforeORT c.percent.controller #cycle
setAfterORT c.percent.controller #cycle
--
d=dummy();d.pos.controller=Path_Constraint()
c=d.pos.controller;c.path=spline_path
setBeforeORT c.percent.controller #cycle
setAfterORT c.percent.controller #cycle
c.percent.controller = float_script()
c.percent.controller.AddObject "obj1_percent" objs_temp_a[1].pos.controller.percent.controller
c.percent.controller.script="obj1_percent.value"
)--if(i==1)then
if i>1 then
(
objs_temp_a[i].pos.controller=Path_Constraint()
c=objs_temp_a[i].pos.controller;c.path=spline_path
setBeforeORT c.percent.controller #cycle
setAfterORT c.percent.controller #cycle
c.percent.controller = float_script()
c.percent.controller.AddObject "obj1_percent" objs_temp_a[1].pos.controller.percent.controller
c.percent.controller.script="obj1_percent.value+"+(((1.0/objs_count)*(i-1)) as string)
)--if i>1 then
objs_temp_a[i].rotation.controller = LookAt_Constraint();
c=objs_temp_a[i].rotation.controller
c.target_axis=0;c.lookat_vector_length=0;c.target_axisFlip=chb_taf.checked
objs_temp_a[i].rotation.controller.upnode_world = off
objs_temp_a[i].rotation.controller.pickUpNode=spline_path
c.upnode_ctrl=1;c.StoUP_axis=rb_stoa.state;c.StoUP_axisFlip=chb_stoaf.checked;
c.upnode_axis=2
if(i<objs_temp_a.count)then c.appendTarget objs_temp_a[i+1] 100
if(i==objs_temp_a.count)then c.appendTarget d 100
)--for i=1 to objs_temp_a.count do
select objs_temp_a; selectMore d
redrawViews()
)--if(script_continue==true)then
)--with animate off
)--undo off
)--if numSplines spline_path==1then
)--if(spline_path!=undefined)then
)--if(selection.count==2)then
)--on btn_apply pressed do
--
on igorznag_path_lookat open do
(
sp_spacing.enabled=false
update_cs()
)--on igorznag_path_lookat open do
--
on rb_cs changed arg do
(
sp_count.enabled=true;sp_spacing.enabled=true
if(arg==1)then sp_spacing.enabled=false
if(arg==2)then sp_count.enabled=false
update_cs()
)--on rb_cs changed arg do
--
on sp_count entered do update_cs()
on sp_spacing entered do update_cs()
on btn_update pressed do update_cs()
); createdialog igorznag_path_lookat 210 115
Большое спасибо за скрипт. Однозначно пригодится. Но...
Понимаешь, именно из-за того, что траки в твоём скрипте не находятся в иерархии как кости, мы тоже получаем на резких поворотах сплайна вот такие недочёты.
Когда путь прямой, между траками одно расстояние, а на повороте, хоть и малозаметно, но уже другое.
Расстояние между поинтами разное отсюда и просветы .Будет скрипт выравнивающий расстояние между любым количеством поинтов на сплайне с любой формой всё будет работать нормально.Есть однако мысль использовать MassFx для таких целей так как вышеперечисленных способах не учитывается естественный провис сочленений (хоть цепи хоть трака) между движущимися элементами (опорными катками танков к примеру).
INCUSполучаем на резких поворотах сплайна вот такие недочёты
Попробуйте такой вариант:
Создаем один сплайн Circle и конвертируем его в Editable Spline.
Создаем один чайник Teapot. Выделяем сплайн и чайник.
Запускаем скрипт. В новом окне нажимаем кнопку Apply.
Анимируем % Along Path чайника, который находится в начале сплайна.
Чем меньше Seg Length, тем меньше недочетов и тем больше вычислений.
Seg Length работает также, как Seg Length в модификаторе Normalize Spline.
Скрипт проверяет только половину длины сплайна и ищет подходящее место.
Объект Dummy и Plane являются вспомогательными и не нужно их удалять.
try (destroydialog igorznag_spline_ik) catch()
rollout igorznag_spline_ik "SplineIK"
(
--gui
spinner sp_count "Count:" range:[2,1e9,10] fieldWidth:60 type:#integer pos:[32,5]
spinner sp_spacing "Spacing:" range:[0,1e9,10] fieldWidth:60 type:#worldunits pos:[21,22]
spinner sp_precision "Seg Length:" range:[0,1e9,1] fieldWidth:60 type:#worldunits pos:[5,40]
checkbox chb_taf "Flip. Object LookAt Axis = X" pos:[5,57]
radiobuttons rb_stoa "Object Upnode Axis" labels:#("Y", "Z") pos:[5,75]
checkbox chb_stoaf "Flip" pos:[80,92]
label lbl_info "Spline Upnode Axis = Z" pos:[5,110]
button btn_apply "Apply" pos:[130,75] width:50 height:50
--events
on btn_apply pressed do
(
if(selection.count==2)then
(
spline_path=undefined; obj=undefined;
spline_types=#(SplineShape,line);cl1=classof selection[1];cl2=classof selection[2]
if(finditem spline_types cl1!=0 and finditem spline_types cl2==0)then
(spline_path=selection[1];obj=selection[2])
if(finditem spline_types cl2!=0 and finditem spline_types cl1==0)then
(spline_path=selection[2];obj=selection[1])
if(spline_path!=undefined)then
(
if numSplines spline_path==1 then
(
undo on
(
with animate off
(
len=curveLength spline_path 1
if(sp_precision.value>0 and sp_precision.value<sp_spacing.value)then
if(sp_precision.value<len and sp_spacing.value<len)then
(
spline_path.optimize=false;spline_path.adaptive=false;spline_path.steps=100;
objs_temp_a=#(); objs_count=sp_count.value
for i=1 to objs_count do
(
maxOps.cloneNodes obj cloneType:#instance newNodes:&n
append objs_temp_a n[1];
)--for i=1 to objs_count do
--
d=plane();d.name="igorznag_splineIK";
d.width=0;d.length=0;d.widthsegs=1;d.lengthsegs=1;
d.pos.controller=Position_Constraint()
c=d.pos.controller;c.constraints.appendTarget objs_temp_a[1] 100
d_end=dummy();d_end.pos.controller=position_xyz();
--
for i=1 to objs_temp_a.count do
(
if(i==1)then
(
objs_temp_a[i].pos.controller=Path_Constraint()
c=objs_temp_a[i].pos.controller;c.path=spline_path
c.percent.controller=linear_float();
setBeforeORT c.percent.controller #cycle
setAfterORT c.percent.controller #cycle
)
if(i>1)then objs_temp_a[i].pos.controller=position_xyz();
objs_temp_a[i].rotation.controller = LookAt_Constraint();
c=objs_temp_a[i].rotation.controller
c.target_axis=0;c.lookat_vector_length=0;c.target_axisFlip=chb_taf.checked
objs_temp_a[i].rotation.controller.upnode_world = off
objs_temp_a[i].rotation.controller.pickUpNode=spline_path
c.upnode_ctrl=1;c.StoUP_axis=rb_stoa.state;c.StoUP_axisFlip=chb_stoaf.checked;
c.upnode_axis=2
if(i<objs_temp_a.count)then c.appendTarget objs_temp_a[i+1] 100
if(i==objs_temp_a.count)then c.appendTarget d_end 100
)--for i=1 to objs_temp_a.count do
--script
d.rotation.controller=rotation_script()
c=d.rotation.controller
setBeforeORT c #cycle; setAfterORT c #cycle
c.AddObject "igorznag_spline_path" spline_path
c.AddObject "igorznag_dummy_end" d_end.pos.controller
for i=1 to objs_temp_a.count do
c.AddObject ("igorznag_obj"+(i as string)) objs_temp_a[i].pos.controller
str=""
str+="with animate off ( try (";str+="\n"
str+="spacing="+(sp_spacing.value as string);str+="\n"
str+="precision="+(sp_precision.value as string);str+="\n"
str+="len=curveLength igorznag_spline_path 1";str+="\n"
str+="if(len>0)then";str+="\n"
str+="(";str+="\n"
str+="vert_coord_offset=igorznag_obj1.value";str+="\n"
str+="temp_percent=nearestPathParam igorznag_spline_path 1 vert_coord_offset";str+="\n"
str+="temp_precision_offset=(pathToLengthParam igorznag_spline_path 1 temp_percent)*len";str+="\n"
for i=2 to objs_temp_a.count do
(
str+="temp_precision=0;temp_precision_global=temp_precision_offset;";str+="\n"
str+="dist_min=1e9;vert_coord=vert_coord_offset;";str+="\n"
str+="while temp_precision < len/2.0 do";str+="\n"
str+="(";str+="\n"
str+="t=1.0*temp_precision_global/len";str+="\n"
str+="vert_coord_temp=lengthInterp igorznag_spline_path 1 t";str+="\n"
str+="dist_temp=abs((distance vert_coord_temp vert_coord)-spacing)";str+="\n"
str+="if(dist_temp<dist_min)then";str+="\n"
str+="(";str+="\n"
str+="dist_min=dist_temp;";str+="\n"
str+="temp_precision_offset=temp_precision_global";str+="\n"
str+="vert_coord_offset=vert_coord_temp";str+="\n"
str+=")";str+="\n"
str+="temp_precision+=precision";str+="\n"
str+="temp_precision_global+=precision";str+="\n"
str+="if(temp_precision_global>len)then temp_precision_global-=len";str+="\n"
str+=")--while";str+="\n"
str+="igorznag_obj"+(i as string)+".value=vert_coord_offset";str+="\n"
)--for i=2 to 2 do--objs_temp_a.count do
--d_end
str+="temp_precision=0;temp_precision_global=temp_precision_offset;";str+="\n"
str+="dist_min=1e9;vert_coord=vert_coord_offset;";str+="\n"
str+="while temp_precision < len/2.0 do";str+="\n"
str+="(";str+="\n"
str+="t=1.0*temp_precision_global/len";str+="\n"
str+="vert_coord_temp=lengthInterp igorznag_spline_path 1 t";str+="\n"
str+="dist_temp=abs((distance vert_coord_temp vert_coord)-spacing)";str+="\n"
str+="if(dist_temp<dist_min)then";str+="\n"
str+="(";str+="\n"
str+="dist_min=dist_temp;";str+="\n"
str+="temp_precision_offset=temp_precision_global";str+="\n"
str+="vert_coord_offset=vert_coord_temp";str+="\n"
str+=")";str+="\n"
str+="temp_precision+=precision";str+="\n"
str+="temp_precision_global+=precision";str+="\n"
str+="if(temp_precision_global>len)then temp_precision_global-=len";str+="\n"
str+=")--while";str+="\n"
str+="igorznag_dummy_end.value=vert_coord_offset";str+="\n"
--d_end
str+="print \"da\"";str+="\n"
str+=")--if(precision<spacing and ";str+="\n"
str+=")catch (quat 0 0 0 1))--try with animate off";str+="\n"
str+="quat 0 0 0 1";
c.script=str
--
select objs_temp_a; selectmore d; selectmore d_end
redrawViews()
)--if(sp_precision.value<len and sp_spacing.value<len)then
)--with animate off
)--undo off
)--if numSplines spline_path==1then
)--if(spline_path!=undefined)then
)--if(selection.count==2)then
)--on btn_apply pressed do
--
); createdialog igorznag_spline_ik 190 135
Ё-!.Только за то,что напечатал столько уже можно сказать ОГРОМНОЕ СПАСИБО!Война и мир.Жаль,что времени нет и в плотную заняться и всё проверить(но скрипт скачал).Спасибо!
iqorznaq
Ну, да, ..съезд/разъезд уже стал меньше намного...
Но скрипток дуже макс подвешивает...
Выделил бокс и сплайн и запустил как велено...поставил Count=23 - во вьюпорте 0,5 фпс(Seg Length = 25mm) ........а на трекбаре ползун скачет аж через 25 кадров. Видно как Макс покрывается потом.
Делаю Seg Length = 10, и жму Play, ....Макс на время делается недоступным, а потом восстанавливается без всякого проигрывания, как буд-то его ни очём сейчас не попросили. Не тянет он что-то.
Проц у меня четырёхголовый, правда, и памяти 8 г,.. Win7 64x. Max 2013.
Почему - то "Левшу" вспомнил....
Chin@man , мы в этой теме не учим танцевать саму блоху. Мы тут обсуждаем какой выбрать шрифт для надписи на гвоздиках к подковам, которыми блоха подкована.
Почему - то "Левшу" вспомнил....
Chin@man , мы в этой теме не учим танцевать саму блоху. Мы тут обсуждаем какой выбрать шрифт для надписи на гвоздиках к подковам, которыми блоха подкована.
Доступ к резюме доступен только по пакетному доступу HR менеджерам зарегистрированных компаний. Узнать о вариантах корпоративных пакетов можно по ссылке.
INCUS
Давно хотел спросить и сегодня созрел.
Цепочка из, допустим, костей > SplineIK Solver > указываю на сплайн (Окружность, ровная, итераций хватает..)
Пожалуйста, кто-нибудь, скажите почему кости криво размещаются на сплайне, т.е, не совсем пивотами ?
Почему это происходит, и как это победить ?
При анимации по кругу заметен общий люфт.
Вложения
Deruz
Т.е. какова цель такого создания?
Может можно проще организовать... 🙂
INCUS
А цепь велосипедная ? две шестерёнки..как положено...делаешь, делаешь, а тут, ётить, вот такое на выходе.
Deruz
Учите мат-часть. 🙂
P.S. Кости лишь там, где деформация сетки - остальное иначе.
INCUS
Я просто прошу ответить на вопрос, который я задал.
Кости я выбрал как пример для простоты и показательности проблемы моего вопроса.
Подобная хрень происходит и в случае со слинкованной геометрией.
Deruz
INCUS
или успокоить меня и сказать, что это в максе традиционно и не стоит мозгопара.
Вложения
igorznag
Или такой способ тоже не подходит для этой задачи? Похожая задача есть в этом уроке.
INCUS
Всё нормуль, ничего не болтает.
Но, всё это сложновато, по сравнению с заявленной простотой использования Spline IK Solver.
Мне удобнее допускать своё незнание , чем неполноценность инструмента, который специально под это заточен.
Хотелось бы от него увидеть сухую немецкую точность.
igorznag
Создаем один сплайн Circle и конвертируем его в Editable Spline.
Создаем один чайник Teapot. Выделяем сплайн и чайник.
Запускаем скрипт. В новом окне нажимаем кнопку Apply.
Анимируем % Along Path чайника, который находится в начале сплайна.
try (destroydialog igorznag_path_lookat) catch() rollout igorznag_path_lookat "Chain. Path. LookAt." ( --gui radiobuttons rb_cs "" labels:#("Count:", "Spacing:") pos:[5,5] columns:1 spinner sp_count "" range:[2,1e9,10] fieldWidth:60 type:#integer pos:[65,5] spinner sp_spacing "" range:[0,1e9,0] fieldWidth:60 type:#worldunits pos:[65,22] checkbox chb_taf "Flip. Object LookAt Axis = X" pos:[5,42] radiobuttons rb_stoa "Object Upnode Axis" labels:#("Y", "Z") pos:[5,60] checkbox chb_stoaf "Flip" pos:[80,77] label lbl_info "Spline Upnode Axis = Z" pos:[5,95] button btn_apply "Apply" pos:[140,60] width:60 height:50 button btn_update "Update" pos:[145,10] --functions fn update_cs = ( if(selection.count==2)then ( spline_path=undefined; obj=undefined; spline_types=#(SplineShape,line);cl1=classof selection[1];cl2=classof selection[2] if(finditem spline_types cl1!=0 and finditem spline_types cl2==0)then (spline_path=selection[1];obj=selection[2]) if(finditem spline_types cl2!=0 and finditem spline_types cl1==0)then (spline_path=selection[2];obj=selection[1]) if(spline_path!=undefined)then ( if numSplines spline_path==1 then ( spline_length=0; sl_a=getSegLengths spline_path 1 if(sl_a.count>0)then spline_length=sl_a[sl_a.count] if rb_cs.state==1 then sp_spacing.value=1.0*spline_length/sp_count.value if rb_cs.state==2 then ( if(sp_spacing.value>0)then ( v=int(1.0*spline_length/sp_spacing.value) if v<2 then v=2; sp_count.value=v )--if(sp_spacing.value>0)then else sp_count.value=2 )--if rb_cs.state==2 then )--if numSplines spline_path==1 then )--if(spline_path!=undefined)then )--if(selection.count==2)then )--fn update_cs = --events on btn_apply pressed do ( if(selection.count==2)then ( spline_path=undefined; obj=undefined; spline_types=#(SplineShape,line);cl1=classof selection[1];cl2=classof selection[2] if(finditem spline_types cl1!=0 and finditem spline_types cl2==0)then (spline_path=selection[1];obj=selection[2]) if(finditem spline_types cl2!=0 and finditem spline_types cl1==0)then (spline_path=selection[2];obj=selection[1]) if(spline_path!=undefined)then ( if numSplines spline_path==1 then ( undo on ( with animate off ( objs_temp_a=#(); objs_count=sp_count.value script_continue=true if objs_count>1000 then script_continue=queryBox "Continue?" title:"Count is a big number!" if(script_continue==true)then ( for i=1 to objs_count do ( maxOps.cloneNodes obj cloneType:#instance newNodes:&n append objs_temp_a n[1]; )--for i=1 to objs_count do d=undefined for i=1 to objs_temp_a.count do ( if i==1 then ( objs_temp_a[i].pos.controller = Path_Constraint() c=objs_temp_a[i].pos.controller; c.path=spline_path c.percent.controller=bezier_float(); setBeforeORT c.percent.controller #cycle setAfterORT c.percent.controller #cycle -- d=dummy();d.pos.controller=Path_Constraint() c=d.pos.controller;c.path=spline_path setBeforeORT c.percent.controller #cycle setAfterORT c.percent.controller #cycle c.percent.controller = float_script() c.percent.controller.AddObject "obj1_percent" objs_temp_a[1].pos.controller.percent.controller c.percent.controller.script="obj1_percent.value" )--if(i==1)then if i>1 then ( objs_temp_a[i].pos.controller=Path_Constraint() c=objs_temp_a[i].pos.controller;c.path=spline_path setBeforeORT c.percent.controller #cycle setAfterORT c.percent.controller #cycle c.percent.controller = float_script() c.percent.controller.AddObject "obj1_percent" objs_temp_a[1].pos.controller.percent.controller c.percent.controller.script="obj1_percent.value+"+(((1.0/objs_count)*(i-1)) as string) )--if i>1 then objs_temp_a[i].rotation.controller = LookAt_Constraint(); c=objs_temp_a[i].rotation.controller c.target_axis=0;c.lookat_vector_length=0;c.target_axisFlip=chb_taf.checked objs_temp_a[i].rotation.controller.upnode_world = off objs_temp_a[i].rotation.controller.pickUpNode=spline_path c.upnode_ctrl=1;c.StoUP_axis=rb_stoa.state;c.StoUP_axisFlip=chb_stoaf.checked; c.upnode_axis=2 if(i<objs_temp_a.count)then c.appendTarget objs_temp_a[i+1] 100 if(i==objs_temp_a.count)then c.appendTarget d 100 )--for i=1 to objs_temp_a.count do select objs_temp_a; selectMore d redrawViews() )--if(script_continue==true)then )--with animate off )--undo off )--if numSplines spline_path==1then )--if(spline_path!=undefined)then )--if(selection.count==2)then )--on btn_apply pressed do -- on igorznag_path_lookat open do ( sp_spacing.enabled=false update_cs() )--on igorznag_path_lookat open do -- on rb_cs changed arg do ( sp_count.enabled=true;sp_spacing.enabled=true if(arg==1)then sp_spacing.enabled=false if(arg==2)then sp_count.enabled=false update_cs() )--on rb_cs changed arg do -- on sp_count entered do update_cs() on sp_spacing entered do update_cs() on btn_update pressed do update_cs() ); createdialog igorznag_path_lookat 210 115INCUS
Понимаешь, именно из-за того, что траки в твоём скрипте не находятся в иерархии как кости, мы тоже получаем на резких поворотах сплайна вот такие недочёты.
Когда путь прямой, между траками одно расстояние, а на повороте, хоть и малозаметно, но уже другое.
Вложения
diwian diwian
igorznag
Создаем один сплайн Circle и конвертируем его в Editable Spline.
Создаем один чайник Teapot. Выделяем сплайн и чайник.
Запускаем скрипт. В новом окне нажимаем кнопку Apply.
Анимируем % Along Path чайника, который находится в начале сплайна.
Чем меньше Seg Length, тем меньше недочетов и тем больше вычислений.
Seg Length работает также, как Seg Length в модификаторе Normalize Spline.
Скрипт проверяет только половину длины сплайна и ищет подходящее место.
Объект Dummy и Plane являются вспомогательными и не нужно их удалять.
try (destroydialog igorznag_spline_ik) catch() rollout igorznag_spline_ik "SplineIK" ( --gui spinner sp_count "Count:" range:[2,1e9,10] fieldWidth:60 type:#integer pos:[32,5] spinner sp_spacing "Spacing:" range:[0,1e9,10] fieldWidth:60 type:#worldunits pos:[21,22] spinner sp_precision "Seg Length:" range:[0,1e9,1] fieldWidth:60 type:#worldunits pos:[5,40] checkbox chb_taf "Flip. Object LookAt Axis = X" pos:[5,57] radiobuttons rb_stoa "Object Upnode Axis" labels:#("Y", "Z") pos:[5,75] checkbox chb_stoaf "Flip" pos:[80,92] label lbl_info "Spline Upnode Axis = Z" pos:[5,110] button btn_apply "Apply" pos:[130,75] width:50 height:50 --events on btn_apply pressed do ( if(selection.count==2)then ( spline_path=undefined; obj=undefined; spline_types=#(SplineShape,line);cl1=classof selection[1];cl2=classof selection[2] if(finditem spline_types cl1!=0 and finditem spline_types cl2==0)then (spline_path=selection[1];obj=selection[2]) if(finditem spline_types cl2!=0 and finditem spline_types cl1==0)then (spline_path=selection[2];obj=selection[1]) if(spline_path!=undefined)then ( if numSplines spline_path==1 then ( undo on ( with animate off ( len=curveLength spline_path 1 if(sp_precision.value>0 and sp_precision.value<sp_spacing.value)then if(sp_precision.value<len and sp_spacing.value<len)then ( spline_path.optimize=false;spline_path.adaptive=false;spline_path.steps=100; objs_temp_a=#(); objs_count=sp_count.value for i=1 to objs_count do ( maxOps.cloneNodes obj cloneType:#instance newNodes:&n append objs_temp_a n[1]; )--for i=1 to objs_count do -- d=plane();d.name="igorznag_splineIK"; d.width=0;d.length=0;d.widthsegs=1;d.lengthsegs=1; d.pos.controller=Position_Constraint() c=d.pos.controller;c.constraints.appendTarget objs_temp_a[1] 100 d_end=dummy();d_end.pos.controller=position_xyz(); -- for i=1 to objs_temp_a.count do ( if(i==1)then ( objs_temp_a[i].pos.controller=Path_Constraint() c=objs_temp_a[i].pos.controller;c.path=spline_path c.percent.controller=linear_float(); setBeforeORT c.percent.controller #cycle setAfterORT c.percent.controller #cycle ) if(i>1)then objs_temp_a[i].pos.controller=position_xyz(); objs_temp_a[i].rotation.controller = LookAt_Constraint(); c=objs_temp_a[i].rotation.controller c.target_axis=0;c.lookat_vector_length=0;c.target_axisFlip=chb_taf.checked objs_temp_a[i].rotation.controller.upnode_world = off objs_temp_a[i].rotation.controller.pickUpNode=spline_path c.upnode_ctrl=1;c.StoUP_axis=rb_stoa.state;c.StoUP_axisFlip=chb_stoaf.checked; c.upnode_axis=2 if(i<objs_temp_a.count)then c.appendTarget objs_temp_a[i+1] 100 if(i==objs_temp_a.count)then c.appendTarget d_end 100 )--for i=1 to objs_temp_a.count do --script d.rotation.controller=rotation_script() c=d.rotation.controller setBeforeORT c #cycle; setAfterORT c #cycle c.AddObject "igorznag_spline_path" spline_path c.AddObject "igorznag_dummy_end" d_end.pos.controller for i=1 to objs_temp_a.count do c.AddObject ("igorznag_obj"+(i as string)) objs_temp_a[i].pos.controller str="" str+="with animate off ( try (";str+="\n" str+="spacing="+(sp_spacing.value as string);str+="\n" str+="precision="+(sp_precision.value as string);str+="\n" str+="len=curveLength igorznag_spline_path 1";str+="\n" str+="if(len>0)then";str+="\n" str+="(";str+="\n" str+="vert_coord_offset=igorznag_obj1.value";str+="\n" str+="temp_percent=nearestPathParam igorznag_spline_path 1 vert_coord_offset";str+="\n" str+="temp_precision_offset=(pathToLengthParam igorznag_spline_path 1 temp_percent)*len";str+="\n" for i=2 to objs_temp_a.count do ( str+="temp_precision=0;temp_precision_global=temp_precision_offset;";str+="\n" str+="dist_min=1e9;vert_coord=vert_coord_offset;";str+="\n" str+="while temp_precision < len/2.0 do";str+="\n" str+="(";str+="\n" str+="t=1.0*temp_precision_global/len";str+="\n" str+="vert_coord_temp=lengthInterp igorznag_spline_path 1 t";str+="\n" str+="dist_temp=abs((distance vert_coord_temp vert_coord)-spacing)";str+="\n" str+="if(dist_temp<dist_min)then";str+="\n" str+="(";str+="\n" str+="dist_min=dist_temp;";str+="\n" str+="temp_precision_offset=temp_precision_global";str+="\n" str+="vert_coord_offset=vert_coord_temp";str+="\n" str+=")";str+="\n" str+="temp_precision+=precision";str+="\n" str+="temp_precision_global+=precision";str+="\n" str+="if(temp_precision_global>len)then temp_precision_global-=len";str+="\n" str+=")--while";str+="\n" str+="igorznag_obj"+(i as string)+".value=vert_coord_offset";str+="\n" )--for i=2 to 2 do--objs_temp_a.count do --d_end str+="temp_precision=0;temp_precision_global=temp_precision_offset;";str+="\n" str+="dist_min=1e9;vert_coord=vert_coord_offset;";str+="\n" str+="while temp_precision < len/2.0 do";str+="\n" str+="(";str+="\n" str+="t=1.0*temp_precision_global/len";str+="\n" str+="vert_coord_temp=lengthInterp igorznag_spline_path 1 t";str+="\n" str+="dist_temp=abs((distance vert_coord_temp vert_coord)-spacing)";str+="\n" str+="if(dist_temp<dist_min)then";str+="\n" str+="(";str+="\n" str+="dist_min=dist_temp;";str+="\n" str+="temp_precision_offset=temp_precision_global";str+="\n" str+="vert_coord_offset=vert_coord_temp";str+="\n" str+=")";str+="\n" str+="temp_precision+=precision";str+="\n" str+="temp_precision_global+=precision";str+="\n" str+="if(temp_precision_global>len)then temp_precision_global-=len";str+="\n" str+=")--while";str+="\n" str+="igorznag_dummy_end.value=vert_coord_offset";str+="\n" --d_end str+="print \"da\"";str+="\n" str+=")--if(precision<spacing and ";str+="\n" str+=")catch (quat 0 0 0 1))--try with animate off";str+="\n" str+="quat 0 0 0 1"; c.script=str -- select objs_temp_a; selectmore d; selectmore d_end redrawViews() )--if(sp_precision.value<len and sp_spacing.value<len)then )--with animate off )--undo off )--if numSplines spline_path==1then )--if(spline_path!=undefined)then )--if(selection.count==2)then )--on btn_apply pressed do -- ); createdialog igorznag_spline_ik 190 135diwian diwian
INCUS
Ну, да, ..съезд/разъезд уже стал меньше намного...
Но скрипток дуже макс подвешивает...
Выделил бокс и сплайн и запустил как велено...поставил Count=23 - во вьюпорте 0,5 фпс(Seg Length = 25mm) ........а на трекбаре ползун скачет аж через 25 кадров. Видно как Макс покрывается потом.
Делаю Seg Length = 10, и жму Play, ....Макс на время делается недоступным, а потом восстанавливается без всякого проигрывания, как буд-то его ни очём сейчас не попросили. Не тянет он что-то.
Проц у меня четырёхголовый, правда, и памяти 8 г,.. Win7 64x. Max 2013.
monah_62
Подмастерье Йода (Сhin@man)
INCUS
Chin@man , мы в этой теме не учим танцевать саму блоху. Мы тут обсуждаем какой выбрать шрифт для надписи на гвоздиках к подковам, которыми блоха подкована.
INCUS
Chin@man , мы в этой теме не учим танцевать саму блоху. Мы тут обсуждаем какой выбрать шрифт для надписи на гвоздиках к подковам, которыми блоха подкована.
diwian diwian