Render.ru

Скрипт для Орбит саб-обджект

Рейтинг
47
#1
Вообще то, это просьба о написании скрипта.

Может кто то сваяет, если будет желание и возможность.

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

Цель скрипта:

Сделать в максе так что б при выделении каждого последующего объекта (полигона , ребра, вертекса) именно он один становился центром вращения. И что б при снятии выделения со всего, даже с модели, центр вращения оставался на месте последнего выделенного полигона.

На рендер.ру есть такой скрипт написанный Deniseich 0-1 в MEL для MAYA и он великолепно работает, сам проверял. (Создавал полоску деленную на 50 полигонов, выделял 1 и вокруг него все и летало, добавлял к нему 50 и все вращалось вокруг 50. При нажатии F (Максовское Z) выделенные полигоны максимально приближаются занимая большую площадь экрана, при этом центр вращения переносится на 25-полигон (середина между 1-м и 50-м). Стоит деселектнуть и вновь выделит 1-й, и центр вращения вновь на нем, при том что он выделен вместе с 50-м. )
 
Рейтинг
47
#2
Что ж вижу у людей ни желания ни времени :) Попробую своими силами и маленькими шагами.
Просматривая максовский хелп, наткнулся на любопытную функцию. "boolean"viewport.zoomPerspective "float" - в поле float устанавливается удаление вида, от центра выделенного объекта или его подобъекта (полигона.)К сожалению я не нашел функцию которая показывала бы удаление от выделенного полигона в окне перспективы на данный момент.

Вопрос: Подскажите пожалуйста каким образом можно получить эти данные. Пробовал Getviewport.zoomPerspective () и viewport.GetzoomPerspective (), все не срабатывает.

Идея скрипта:
1 Через Get получаю число на которое удален вид перспективы от полигона (допустим 150). Присваиваю его какой то переменной.
2 "zoom extents Selected" – Этим переношу опорную точку вращения на выделенный полигон и приближаю.
3 viewport.zoomPerspective (150.0 или переменная) – отдаляю на тоже расстояния что было до zoom extents Selected
4 completeredraw() – Перерисовывает вид.

Цель скрипта:
При выделении полигона (ребра, вертекса), на него будет переносится центр вращения, а вид из окна перспективы оставаться на том же месте (БЕЗ приближения), при этом полигон (ребро, вертекс)переместится в центр окна.

Ps: Скрипт рассчитан на работу в режиме Orbit, и не Орбит саб-обджект!!! Кстати это попытка повторить еще один скрипт написанный Deniseich 0-1 в MEL для MAYA.
 
Рейтинг
47
#3
Все, вопрос снят, НАШЕЛ!!!

viewport.getFocalDistance()

Конечный работающий скрипт выглядит так:

a = viewport.getFocalDistance()
macros.run "Chernega" "zoomSelected" --Это мой видоизмененный скрипт!!! Здесь должен быть обычный Зоом Экстентс Селектед.
viewport.zoomPerspective (a)
completeredraw()
 
Рейтинг
47
#4
Ну что ж первая часть пути успешно пройдена. Осталась вторая, заключительная.

И собственными силами, без знающих людей мне уже не обойтись.

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

Цель скрипта:

Прошу знающих людей написать код, который позволял бы при выделении 1-го и 50-го полигона, задействовать скрипт таким образом, что бы центр вращения и в центра экрана переносился 50-й полигон. Потом что б через контрол добавить к выделению 3-полигон, запустить скрипт, и центром вращения и экрана являлся 3-й. При это выделено будет 3 полигона 1, 50, 3.

PS: Ответьте хоть кто то, а то это больше похоже на мой персональный блог, нежели на тему форума :)
 

Savin Denis

Модератор форума
Команда форума
Рейтинг
138
#5
Да совсем немного не дописал )

Лови свой скрипт, хотя в максе есть замечательный хоткей

Код:
global last_sel_Obj
global last_sel_Level
global last_sel_Elem

fn setViewportPos pos =
(
	local vTM = Inverse(getViewTM())	
	local  Fd = viewport.getFocalDistance()	
	vTM.position	 = 	(pos * Inverse vTM + [0,0,1] * Fd) * vTM	
	viewport.setTM (Inverse(vTM))
	completeredraw()		
)


deleteAllChangeHandlers  id:#OrbitVieportControll
when select $ changes id:#OrbitVieportControll obj do 
(
	if (try classof obj == Editable_Poly catch (false)) do 
	(
		local selLevel = obj.GetEPolySelLevel()
		local curSel = obj.GetSelection (selLevel);
		if curSel == undefined do curSel = #{}
		local selLast = curSel
		if last_sel_Obj != obj or  last_sel_Level != selLevel then 
		(
			last_sel_Obj = obj			
			last_sel_Level = selLevel
			last_sel_Elem = curSel		
		)  else
		        selLast = curSel -  last_sel_Elem

		local elmLast = 0
		for i in selLast  while elmLast==0 do elmLast=i

		last_sel_Elem = copy curSel
		if  elmLast > 0 do  
			case selLevel of 
			(
				#face: 	   (setViewportPos  (polyop.getFaceCenter obj  elmLast))
				#vertex:	   (setViewportPos  (polyop.getVert obj elmLast))
				#edge:      (setViewportPos  (ev = polyop.getEdgeVerts obj elmLast;  (polyop.getVert obj ev[1] + polyop.getVert obj ev[2])/2.))
			)	
	)
)
PS. Orbit в максе должен стоять в режиме вращения вокруг центра вьюпорта (точки фокуса).
 
Рейтинг
47
#6
Благодарю за реагирование, но это не совсем то. Быть может у меня не четко получилось изложил цель.


Сейчас:

Создаю 2- цилиндра, выделяю один из них, нажимаю кнопку со скриптом, и НИЧЕГО не происходит. После чего вхожу в режим редактирования полигонов, и экран начинает скакать как безумный за КАЖДЫМ следующим выделенным полигоном. Без всякого ЗАПУСКА скриптов!!!


Хотелось бы:

Устанавливаю скрипт на кнопку Z.
Создаю 2 объекта по краям экрана (Поли, мэшь, едит сплайн). Выделяю один из них, Z, он переносится без приближения в центр экрана и становится центром вращения. Вхожу в режим редактирования полигонов, выделяю один полигон (ничего не происходит!), кручу, верчу, зумирую. Z и он переносится без приближения в середину экрана становясь центром вращения. Добавляю к выделению второй и третий полигоны, кручу, верчу, зумирую. Z и третий(последний добавленный) становится в центре всего.

Скрипт которым я пользуюсь , не смотря на свою примитивность, хорошо справляется с задачей (работая со всеми видами classof $). Единственный недостаток (на мой взгляд) – при выделении нескольких саб объектов он производит все нужные действия относительно их общего центра, а не последнего выделенного.

(
a = viewport.getFocalDistance()
max tool zoomextents
viewport.zoomPerspective (a)
completeredraw()
)

Ps: Я бы с радостью подредактировал предоставленный скрипт, но мои познания для этого ничтожно малы :)
 

Savin Denis

Модератор форума
Команда форума
Рейтинг
138
#7
Извини перестарался чуть, сейчас скрипт после запуска автоматически отлавливает твою работу с точками, гранями и фэйсами EditablePoly объекта.

Но никто не мешает его повесить на кнопку.
Просто замени:
Код:
deleteAllChangeHandlers id:#OrbitVieportControll
when select $ changes id:#OrbitVieportControll obj do
(
На:
Код:
(
local obj = $selection[1]
Работу с (Объектами , мэшь, едит сплайн) делаешь по аналогии.


Обманывать то не хорошо =))



PS Ты так и не ответил чем тебя макрос Pan Viewport не устроил ?
По крайне мере он универсальный =)
 
Рейтинг
47
#8
Большое спасибо. Уже пользуюсь скриптом.
Внес в него немного изменений, что б он работал со всеми типами объектов (вклинил свой код).


Усмотрел один недостаток, описывать долго, так что сделал видео (со звуком):
http://www.youtube.com/watch?v=5LJ0weS9ZVo


По поводу Pan Viewport.
Видимо в заблуждение ввело название темы «Орбит саб-обджект». И действительно если работать в нем при выделении под объектов они становятся центром вращения и достаточно нажать I что бы их оцентровать. Но со второго сообщения речь ведется о скрипте работающем в Orbit, а не Орбит саб-обджект. И в этом случае Pan Viewport не имеет смысла, так как он выводит на центр ту точку над которой находится курсор, но не переносит точку вращении.
 

Savin Denis

Модератор форума
Команда форума
Рейтинг
138
#9
Ух-ты видео здорово, а пиво где ?



Так бы вечерком глянул. )


По поводу Pan Viewport. Да не центрирует по глубине.
 
Рейтинг
47
#10
Для тех кто хочет пользоваться скриптом, и не желает проделывать операции описанные выше на форуме, вот код:


Код:
macroScript View_Center_Rot
	category:"Какую захотите"


(
	global last_sel_Obj 
	global last_sel_Level 
	global last_sel_Elem 

	fn setViewportPos pos = 
	( 
	local vTM = Inverse(getViewTM()) 
	local Fd = viewport.getFocalDistance() 
	vTM.position = (pos * Inverse vTM + [0,0,1] * Fd) * vTM 
	viewport.setTM (Inverse(vTM)) 
	completeredraw() 
	) 


( 
local obj = $selection[1]
	( 
	if (try classof obj == Editable_Poly catch (false)) do 
	( 
	local selLevel = obj.GetEPolySelLevel() 
	local curSel = obj.GetSelection (selLevel); 
	if curSel == undefined do curSel = #{} 
	if last_sel_Obj != obj or last_sel_Level != selLevel then 
	( 
	last_sel_Obj = obj 
	last_sel_Level = selLevel 
	last_sel_Elem = curSel 
	) 

	local selLast = curSel - last_sel_Elem 
	local elmLast = 0 
	for i in selLast while elmLast==0 do elmLast=i 

	last_sel_Elem = copy curSel 
	if elmLast > 0 do 
	case selLevel of 
	( 
	#face: (setViewportPos (polyop.getFaceCenter obj elmLast)) 
	#vertex: (setViewportPos (polyop.getVert obj elmLast)) 
	#edge: (setViewportPos (ev = polyop.getEdgeVerts obj elmLast; (polyop.getVert obj ev[1] + polyop.getVert obj ev[2])/2.)) 
	) 
	) 
	)
)


function ViewCenterRot = (	a = viewport.getFocalDistance() 
				max tool zoomextents 
				viewport.zoomPerspective (a) 
				completeredraw() 
			)

case of
(
( classof $ != Editable_Poly): ViewCenterRot ()

( elmLast < 1) : ViewCenterRot ()
)

)

ВАЖНО:
Скрипт рассчитан на работу в режиме Orbit (вращения вокруг центра вьюпорта (точки фокуса)), а не Орбит саб-обджект!!!

В чем суть:
Людям, быстренько просматривающим все темы форумов в поисках готовых скриптов и желающих понять в чем смысл этого: прочтите абзацы (Цель скрипта) в 1, 2, 4 сообщениях. (в полной мере указанным способом скрипт работает с объектами Poly)

Недостаток:
В сообщении 8 на видео. (На видео представлено самое критичное и экстремальное использование скрипта, в основном скрипт справляется с задачей)
 

igorznag

Мастер
Рейтинг
103
#11
Недостаток:
В сообщении 8 на видео. (На видео представлено самое критичное и экстремальное использование скрипта,
Привет Александр. Попробуй так. Скачать скрипт можно здесь
Выдели любой объект или подобъект объекта EditablePoly.
 
Рейтинг
47
#12
Огромное спасибо! Работает!

Но все объекты не поли (эдит мешь, сплайны, примитивы с модификаторами), центрирует относительно их Pivota (это несущественно. Большинство времени работаю в поли). Так что добавил:

Код:
(
global igorznag_last_sel_Obj, igorznag_last_sel_Level, igorznag_last_sel_Elem, igorznag_selLastDelta  
_____________________________________________________________

	if ( classof $ != Editable_Poly)
		then
			(	a = viewport.getFocalDistance() 
				max tool zoomextents 
				viewport.zoomPerspective (a) 
				completeredraw() 
			)
		else
			(
/* И нормальненько */
_____________________________________________________________
	
fn setViewportPos pos = 
(

Весь остальной код

)
Есть правда несколько непонятностей (не сильно важных):
1 Когда выделяешь полигоны не через контрол +щелчок, а областью (сразу несколько), Макс Лисинэр выдает - $.EditablePoly.SetSelection #Face #{1..96}. В этом блоке ведь тоже есть последний выделенный (96). А скрипт при запуске не срабатывает.
2 В коде не вписан подобъект (5) Element – так что с ним тоже не срабатывает.

По большому счету, все поставленные цели при создании этой темы, выполнены.
Всем спасибо!
 
Рейтинг
47
#13
Похоже я ПОГАРЯЧИЛСЯ, назвав недостаток с выделением сразу нескольких подобъектов НЕСУЩЕСТВЕННЫМ. Как оказывается, это очень серьезно ограничивает скрипт.

Не срабатывает:
1 При выделении нескольких подобъектов областью (сразу несколько).
2 После применения Loop, Ring
3 После применения Grow, Shrink
4 Пи конвертации из одного подобъекта в другой (с преобразованием выделения)

После выполнения вышеприведенных действий, нужно добавить еще одно выделение (либо с одного из существующих сбросить, и вновь выделить ), только после этого происходит центрирование.
 

igorznag

Мастер
Рейтинг
103
#14
В скрипте из поста 5 добавил только возможность которая описывается на видео.
Код:
global last_sel_Obj 
global last_sel_Level 
global last_sel_Elem 

fn setViewportPos pos = 
(
vTM = Inverse(getViewTM());viewPt = vTM.row4; viewDir = -vTM.row3; 
max tool zoomextents; 
vTM2 = Inverse(getViewTM()); viewPt2 = vTM2.row4; 
a=pos-viewPt; b=viewDir;p=dot a b; a=viewPt2-viewPt; temp_p=dot a b
if(temp_p>0)then
(
c=freecamera();c.transform=vTM;c.fov=getViewFOV();
dist=abs p;c.baseobject.targetDistance=dist
viewport.setCamera c; completeredraw();delete c; 
viewport.setType #view_persp_user; vTM = Inverse(getViewTM()) 
Fd = p; vTM.position=pos-(-vTM.row3)*Fd; viewport.setTM (Inverse(vTM)) 
)
)


( 
local obj = $selection[1] 
if (try classof obj == Editable_Poly catch (false)) do 
( 
local selLevel = obj.GetEPolySelLevel() 
local curSel = obj.GetSelection (selLevel); 
if curSel == undefined do curSel = #{} 
if last_sel_Obj != obj or last_sel_Level != selLevel then 
( 
last_sel_Obj = obj 
last_sel_Level = selLevel 
last_sel_Elem = curSel 
) 

local selLast = curSel - last_sel_Elem 
local elmLast = 0 
for i in selLast while elmLast==0 do elmLast=i 

last_sel_Elem = copy curSel 
if elmLast > 0 do 
case selLevel of 
( 
#face: 
(
faceSel=polyOp.getFaceSelection obj;
polyOp.setFaceSelection obj elmLast;
setViewportPos (polyop.getFaceCenter obj elmLast)
polyOp.setFaceSelection obj faceSel; completeredraw() 
) 
#vertex: 
(
vertSel=polyOp.getVertSelection obj;
polyOp.setVertSelection obj elmLast;
setViewportPos (polyop.getVert obj elmLast)
polyOp.setVertSelection obj vertSel; completeredraw() 
) 
#edge: 
(
edgeSel=polyOp.getEdgeSelection obj;
polyOp.setEdgeSelection obj elmLast;
setViewportPos (ev = polyop.getEdgeVerts obj elmLast; (polyop.getVert obj ev[1] + polyop.getVert obj ev[2])/2.)
polyOp.setEdgeSelection obj edgeSel; completeredraw() 
) 
) 
) 
)
 
Рейтинг
47
#15
Я прошу прощения за то, что начинаю злоупотреблять желанием помочь, но до того что бы я пустился в пляс и пару дней улыбался как идиот осталось совсем не много.

В этом скрипте, так же как и в коде из сообщения 5, есть несколько недостатков:
1) Он рассчитан на работу только с Poly
2) Когда не включены сабобъекты, выбранный Poly не центрируется
3) Когда выделяешь первый к примеру полигон, скрипт не действует. Начинает работать только после добавления еще одного полигона либо выделения другого. Потом с этим объектом работает нормально. При выборе другого все повторяется.
4) Нельзя для переноса точки вращения использовать одни и теже выделенные сабобъекты. К примеру: выделенный полигон можно использовать только раз, что бы скрипт сработал, в следующий раз нужно либо добавлять к выделению, либо выделять новый полигон.

Вот наглядно.

Все эти недостатки устранил добавлением к коду нескольких примитивных строк (сообщение 10)

Код:
function ViewCenterRot = ( a = viewport.getFocalDistance() 
max tool zoomextents 
viewport.zoomPerspective (a) 
completeredraw() 
) 

case of 
( 
( classof $ != Editable_Poly): ViewCenterRot () 

( elmLast < 1) : ViewCenterRot () 
)
Благодаря этому все недостатки практически исправлялись:

1) Он рассчитан на работу только с Poly
Срабатывал со всем: каркасные, сплайновые, нурбсовые.
2) Когда не включены сабобъекты, выбранный Poly не центрируется
Срабатывала function ViewCenterRot, и все работало
3) Когда выделяешь первый к примеру полигон, скрипт не действует. Начинает работать только после добавления еще одного полигона либо выделения другого. Потом с этим объектом работает нормально. При выборе другого все повторяется.
Получается, когда был выбран Первый полигон, срабатывала function ViewCenterRot. Если же выделялось несколько, срабатывал основной скрипт (перенося точку вращения на последний выделенный сабобъект)
4) Нельзя для переноса точки вращения использовать одни и теже выделенные сабобъекты. К примеру: выделенный полигон можно использовать только раз, что бы скрипт сработал, в следующий раз нужно либо добавлять к выделению, либо выделять новый полигон.
Если скрипт к выделенному полигону запускался повторно, срабатывала function ViewCenterRot. Если полигонов было несколько, центр вращения переносился на середину всех выделенных полигонов.


И вот, наконец вопрос:
Поскольку предложенный выше код исправляет неудобство, описанное в видео (сообщение 8), можно ли модернизировать function ViewCenterRot. Что бы в ней не использовались viewport.getFocalDistance() и viewport.zoomPerspective (). То есть что бы эта функция делала то что и делает, но без какого либо зумирования вьюпорта.

Тогда ее можно будет точно также вклинить в конце кода и скрипт будет готов
 

igorznag

Мастер
Рейтинг
103
#16
Код:
global last_sel_Obj 
global last_sel_Level 
global last_sel_Elem 

fn setViewportPos pos = 
(
vTM = Inverse(getViewTM());viewPt = vTM.row4; viewDir = -vTM.row3; 
max tool zoomextents; 
vTM2 = Inverse(getViewTM()); viewPt2 = vTM2.row4; 
a=pos-viewPt; b=viewDir;p=dot a b; a=viewPt2-viewPt; temp_p=dot a b
if(temp_p>0)then
(
c=freecamera();c.transform=vTM;c.fov=getViewFOV();
dist=abs p;c.baseobject.targetDistance=dist
viewport.setCamera c; completeredraw();delete c; completeredraw();
vTM = Inverse(getViewTM()) 
Fd = p; vTM.position=pos-(-vTM.row3)*Fd; viewport.setTM (Inverse(vTM)) 
)
)

fn ViewCenterRot = 
(
vTM = Inverse(getViewTM()); viewFOV=getViewFOV(); viewFD=gw.getFocalDist();
max tool zoomextents; 
vTM2 = Inverse(getViewTM()); viewPt2 = vTM2.row4; viewDir2 = -vTM.row3; 
viewFD2=gw.getFocalDist();focal_pos=viewPt2+(normalize viewDir2)*viewFD2
c=freecamera();c.transform=vTM;c.fov=viewFOV;c.baseobject.targetDistance=viewFD;
viewport.setCamera c; completeredraw();delete c;completeredraw();
setViewportPos(focal_pos); completeredraw();
) 

( 
if(viewport.getType()==#view_persp_user)then
(
local obj = $selection[1] 
if (try classof obj == Editable_Poly catch (false)) do 
( 
local selLevel = obj.GetEPolySelLevel() 
local curSel = obj.GetSelection (selLevel); 
if curSel == undefined do curSel = #{} 
if last_sel_Obj != obj or last_sel_Level != selLevel then 
( 
last_sel_Obj = obj 
last_sel_Level = selLevel 
last_sel_Elem = curSel 
) 

local selLast = curSel - last_sel_Elem 
local elmLast = 0 
for i in selLast while elmLast==0 do elmLast=i 

last_sel_Elem = copy curSel 
if elmLast > 0 do 
case selLevel of 
( 
#face: 
(
faceSel=polyOp.getFaceSelection obj;
polyOp.setFaceSelection obj elmLast;
setViewportPos (polyop.getFaceCenter obj elmLast)
polyOp.setFaceSelection obj faceSel; completeredraw() 
) 
#vertex: 
(
vertSel=polyOp.getVertSelection obj;
polyOp.setVertSelection obj elmLast;
setViewportPos (polyop.getVert obj elmLast)
polyOp.setVertSelection obj vertSel; completeredraw() 
) 
#edge: 
(
edgeSel=polyOp.getEdgeSelection obj;
polyOp.setEdgeSelection obj elmLast;
setViewportPos (ev = polyop.getEdgeVerts obj elmLast; (polyop.getVert obj ev[1] + polyop.getVert obj ev[2])/2.)
polyOp.setEdgeSelection obj edgeSel; completeredraw() 
) 
)  
if(elmLast==0)then ViewCenterRot(); 
) 
if(classof $ != Editable_Poly)then ViewCenterRot () 
)
)
 
Рейтинг
47
#17
Как пел один культовый персонаж "Конец моим страданьям и разочарованьям", даже без горшочка с медом :)

На этом уже можно ставить точку.
Специально выдержал паузу, протестировал в деле, работает как часы.

Всем принимавшим участие с создании скрипта огромное спасибо.
 
Рейтинг
47
#18
Переустановил винду, поставил Х 64 и скрипт перестал нормально работать. Начал подробно вникать в скрипт и хотел уже писать автору с просьбой помочь, но все оказалось неприлично просто. Что бы скрипт работал как надо, нужно в правом нижнем углу выставлять "Зоом экстентс сэлектетд", а не "Зоом эктенс" (рис) И все опять работает как по маслу.
 

Вложения

Сверху