Render.ru

Размещение цепочки на сплайне.

INCUS

Знаток
Рейтинг
29
#1
Всем привет..
Давно хотел спросить и сегодня созрел.
Цепочка из, допустим, костей > SplineIK Solver > указываю на сплайн (Окружность, ровная, итераций хватает..)
Пожалуйста, кто-нибудь, скажите почему кости криво размещаются на сплайне, т.е, не совсем пивотами ?
Почему это происходит, и как это победить ?
При анимации по кругу заметен общий люфт.
 

Вложения

Deruz

Мастер
Рейтинг
96
#2
Первый наводящий вопрос; На фига это нужно?

Т.е. какова цель такого создания?
Может можно проще организовать... :)
 

INCUS

Знаток
Рейтинг
29
#3
Ну, как нафига?
А цепь велосипедная ? две шестерёнки..как положено...делаешь, делаешь, а тут, ётить, вот такое на выходе.
 

Deruz

Мастер
Рейтинг
96
#4
Всё это иначе делается и кости там на фиг не нужны!
Учите мат-часть. :)

P.S. Кости лишь там, где деформация сетки - остальное иначе.
 

INCUS

Знаток
Рейтинг
29
#5
На мат часть мне указывать не нужно.
Я просто прошу ответить на вопрос, который я задал.
Кости я выбрал как пример для простоты и показательности проблемы моего вопроса.
Подобная хрень происходит и в случае со слинкованной геометрией.
 

INCUS

Знаток
Рейтинг
29
#7
Делать - ничё. Просто, или подсказать как с такой "болтанкой" бороться,
или успокоить меня и сказать, что это в максе традиционно и не стоит мозгопара.
 

Вложения

igorznag

Мастер
Рейтинг
103
#8
А цепь велосипедная ? две шестерёнки..как положено.
Попробуйте анимировать велосипедную цепь с помощью Path Constraint и LookAt Constraint.
Или такой способ тоже не подходит для этой задачи? Похожая задача есть в этом уроке.
 

INCUS

Знаток
Рейтинг
29
#9
Спасибо за участие. Подходить-то подходит...есть у меня эта книга в бумаге вместе с диском, на котором есть этот трак от танка...
Всё нормуль, ничего не болтает.
Но, всё это сложновато, по сравнению с заявленной простотой использования Spline IK Solver.
Мне удобнее допускать своё незнание , чем неполноценность инструмента, который специально под это заточен.
Хотелось бы от него увидеть сухую немецкую точность.
 

igorznag

Мастер
Рейтинг
103
#10
Подходить-то подходит. Но, всё это сложновато ...
В чем именно состоит сложность? Попробуйте выполнить этот простой пример:
Создаем один сплайн 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
 

INCUS

Знаток
Рейтинг
29
#11
Большое спасибо за скрипт. Однозначно пригодится. Но...
Понимаешь, именно из-за того, что траки в твоём скрипте не находятся в иерархии как кости, мы тоже получаем на резких поворотах сплайна вот такие недочёты.
Когда путь прямой, между траками одно расстояние, а на повороте, хоть и малозаметно, но уже другое.
 

Вложения

Рейтинг
82
#12
Расстояние между поинтами разное отсюда и просветы .Будет скрипт выравнивающий расстояние между любым количеством поинтов на сплайне с любой формой всё будет работать нормально.Есть однако мысль использовать MassFx для таких целей так как вышеперечисленных способах не учитывается естественный провис сочленений (хоть цепи хоть трака) между движущимися элементами (опорными катками танков к примеру).
 

igorznag

Мастер
Рейтинг
103
#13
получаем на резких поворотах сплайна вот такие недочёты
Попробуйте такой вариант:
Создаем один сплайн 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
 
Рейтинг
82
#14
Ё-!.Только за то,что напечатал столько уже можно сказать ОГРОМНОЕ СПАСИБО!Война и мир.Жаль,что времени нет и в плотную заняться и всё проверить(но скрипт скачал).Спасибо!
 

INCUS

Знаток
Рейтинг
29
#15
iqorznaq
Ну, да, ..съезд/разъезд уже стал меньше намного...
Но скрипток дуже макс подвешивает...
Выделил бокс и сплайн и запустил как велено...поставил Count=23 - во вьюпорте 0,5 фпс(Seg Length = 25mm) ........а на трекбаре ползун скачет аж через 25 кадров. Видно как Макс покрывается потом.
Делаю Seg Length = 10, и жму Play, ....Макс на время делается недоступным, а потом восстанавливается без всякого проигрывания, как буд-то его ни очём сейчас не попросили. Не тянет он что-то.
Проц у меня четырёхголовый, правда, и памяти 8 г,.. Win7 64x. Max 2013.
 

monah_62

Пользователь сайта
Рейтинг
2
#16
И у меня такая же проблема присоеденяюсь... Все таки хотелось узнать из -за чего это происходит и как с этим бороться!?
 

INCUS

Знаток
Рейтинг
29
#18
http://www.youtube.com/watch?v=UTWCt2yYwIc
Почему - то "Левшу" вспомнил....
Chin@man , мы в этой теме не учим танцевать саму блоху. Мы тут обсуждаем какой выбрать шрифт для надписи на гвоздиках к подковам, которыми блоха подкована.
 

INCUS

Знаток
Рейтинг
29
#19
http://www.youtube.com/watch?v=UTWCt2yYwIc
Почему - то "Левшу" вспомнил....
Chin@man , мы в этой теме не учим танцевать саму блоху. Мы тут обсуждаем какой выбрать шрифт для надписи на гвоздиках к подковам, которыми блоха подкована.
 
Сверху