Render.ru

Два skin modifier в один.

firsak

Активный участник
Рейтинг
5
#1
Есть несколько mesh'ев. У каждого свой модификатор skin. Вроде бы простая задача: объединить все объекты в один и сохранить при этом skin и все bone weights. Но у присоединяемых объектов всегда сбрасываются все данные в модификаторе skin. Как быть?
 

Vertalet

Активный участник
Рейтинг
5
#2
ниче неполучитса.... смотря какой обьект ... может с помощью хелперов как нить обьедени
 

firsak

Активный участник
Рейтинг
5
#3
Тогда это полный идиотизм. Элементарная вроде фича. Должна быть по сути дела.
 

Chebu

Знаток
Рейтинг
59
#4
Писал скрипт для объединения двух объектов с модификатором скин в один.

примечания: кости не должны совпадать по именам, иначе будут глюки.

код:

Код:
macroscript mergeSkinObjects
category:"AndreyK"
(
	fn fnMergeSkinObjects objectsList refFrame = 
	(
		ObjSkinVertices = #()
		bonesList = #()
			
		struct sSkinVertex (bonesCount,bonesID,bonesWeight)
			
		--1
		setCommandPanelTaskMode #modify

		bonesOffset = 0
		for obj in objectsList do
		(
			select obj
			
			skinMod = undefined
			for i=1 to obj.modifiers.count do
			(
				if (classof obj.modifiers[i] == Skin) do skinMod = obj.modifiers[i]
			)				
			
			if(skinMod != undefined) then
			(
				--modPanel.setCurrentObject skinMod
				vertices_count = skinOps.GetNumberVertices skinMod 
				
				for i = 1 to vertices_count do
				(
					newSkinVertex = sSkinVertex 0 #() #()
					newSkinVertex.bonesCount =  skinOps.getVertexWeightCount skinMod i
					for j = 1 to newSkinVertex.bonesCount do
					(
						Append newSkinVertex.bonesID ((skinOps.getVertexWeightBoneID skinMod i j)+bonesOffset)
						Append newSkinVertex.bonesWeight ( skinOps.getVertexWeight skinMod i j )
					)
					append ObjSkinVertices newSkinVertex
				)
				
				bones_count = skinOps.GetNumberBones skinMod
				bonesOffset += bones_count
				
				for i = 1 to bones_count do
				(
					appendifunique bonesList (skinOps.GetBoneName skinMod i 0)
				)
			)--	if(skinMod != undefined)
			else deleteItem objectsList (findItem objectsList obj)
		)--for obj in objectsList

		--2
		at time refFrame 
		(
			skinobj = box prefix:"skinobj_"
			convertto skinobj editable_poly
			polyop.deleteVerts skinobj #{1..8}

			for newElement in objectsList do
			(
				polyop.attach skinobj newElement
			)

		--3
			skinMod = skin()
			addModifier skinobj skinMod
			skinMod.bone_limit = 4 --todo - find maximum bone_limit in all objects
			skinMod.weightAllVertices = false

			select skinobj
			setCommandPanelTaskMode #modify
			--modPanel.setCurrentObject skinMod


			for BoneName in BonesList do
			(
				skinOps.addbone skinMod (GetNodeByName(BoneName)) 1
			)
			
			skinOps.Invalidate skinMod 0
			
			skinOps.SelectBone skinMod 1
			
			--4
			vertices_count = skinOps.GetNumberVertices skinMod
				
			for i = 1 to vertices_count do
			(
					skinOps.SetVertexWeights skinMod i ObjSkinVertices[i].bonesID[1] 1
					skinOps.SetVertexWeights skinMod i ObjSkinVertices[i].bonesID ObjSkinVertices[i].bonesWeight
			)
		)--at time refFrame 
	)--fn fnMergeSkinObjects
	
	on execute do
	(
		objectsList = selection as array
		
		if(objectsList.count>0) do
		try
		(
			fnMergeSkinObjects objectsList 0
		)
		catch()
	)
)--macroscript
 

firsak

Активный участник
Рейтинг
5
#5
Писал скрипт для объединения двух объектов с модификатором скин в один.

примечания: кости не должны совпадать по именам, иначе будут глюки.
О. Практически оно. Спасибо, работает! Но блин, у меня как раз объекты с одинаковыми костями... У вертексов с одинаковыми костями веса пропадают. Реально ли доработать скрипт?
 

Chebu

Знаток
Рейтинг
59
#6
у вас в обоих мешах присутствуют одни и те же кости, или это разные кости с одинаковыми именами?
 

firsak

Активный участник
Рейтинг
5
#7
Chebu,

Одни и те же кости. Разных костей с одинаковыми именами нет.



Допустим, имеем: 3 объекта. верхняя губа, нижняя губа, голова.

Поставил keyframe на 50-м кадре (открыл рот).



Выделяю губы, жму на кнопку mergeSkinObjects (голову не трогаю), получаю:

У нижней губы исчезают почти все bone weights. Undo.



Теперь уже выделяю все три объекта, жму mergeSkinObjects, результат:



Все объекты - editable poly, с одним модификатором (skin).


Юзаю 3ds max 2008 x64. Куда копать?
 

Chebu

Знаток
Рейтинг
59
#9
firsak, пробуйте:

Код:
macroscript mergeSkinObjects
category:"AndreyK"
(
	fn fnMergeSkinObjects objectsList refFrame = 
	(
		ObjSkinVertices = #()
		bonesList = #()
			
		struct sSkinVertex (bonesCount,bonesID,bonesWeight)
			
		--1
		setCommandPanelTaskMode #modify

		bonesOffset = 0
		for obj in objectsList do
		(
			select obj
			
			skinMod = undefined
			for i=1 to obj.modifiers.count do
			(
				if (classof obj.modifiers[i] == Skin) do skinMod = obj.modifiers[i]
			)				
			
			if(skinMod != undefined) then
			(
				--modPanel.setCurrentObject skinMod
				vertices_count = skinOps.GetNumberVertices skinMod 
				
				for i = 1 to vertices_count do
				(
					newSkinVertex = sSkinVertex 0 #() #()
					newSkinVertex.bonesCount =  skinOps.getVertexWeightCount skinMod i
					for j = 1 to newSkinVertex.bonesCount do
					(
						Append newSkinVertex.bonesID ((skinOps.getVertexWeightBoneID skinMod i j)+bonesOffset)
						Append newSkinVertex.bonesWeight ( skinOps.getVertexWeight skinMod i j )
					)
					append ObjSkinVertices newSkinVertex
				)
				
				bones_count = skinOps.GetNumberBones skinMod
				bonesOffset += bones_count
				
				for i = 1 to bones_count do
				(
					append bonesList (skinOps.GetBoneName skinMod i 0)
				)
			)--	if(skinMod != undefined)
			else deleteItem objectsList (findItem objectsList obj)
		)--for obj in objectsList

		--2
		at time refFrame 
		(
			skinobj = box prefix:"skinobj_"
			convertto skinobj editable_poly
			polyop.deleteVerts skinobj #{1..8}

			for newElement in objectsList do
			(
				polyop.attach skinobj newElement
			)

		--3
			skinMod = skin()
			addModifier skinobj skinMod
			skinMod.bone_limit = 4 --todo - find maximum bone_limit in all objects
			skinMod.weightAllVertices = false

			select skinobj
			setCommandPanelTaskMode #modify
			--modPanel.setCurrentObject skinMod


			for BoneName in BonesList do
			(
				skinOps.addbone skinMod (GetNodeByName(BoneName)) 1
			)
			
			skinOps.Invalidate skinMod 0
			
			skinOps.SelectBone skinMod 1
			
			--4
			vertices_count = skinOps.GetNumberVertices skinMod
				
			for i = 1 to vertices_count do
			(
					skinOps.SetVertexWeights skinMod i ObjSkinVertices[i].bonesID[1] 1
					skinOps.SetVertexWeights skinMod i ObjSkinVertices[i].bonesID ObjSkinVertices[i].bonesWeight
			)
		)--at time refFrame 
	)--fn fnMergeSkinObjects
	
	on execute do
	(
		objectsList = for obj in selection where (superclassof obj ==GeometryClass) collect obj
		
		if(objectsList.count>0) do
		try
		(
			fnMergeSkinObjects objectsList 0
		)
		catch()
	)
)--macroscript
 

firsak

Активный участник
Рейтинг
5
#10
Едрён батон.
Работает ведь!
Большое спасибо, Chebu.

Только почему то старый скрипт присосался к Максу, несмотря на то, что я старый *.mcr удалил и заменил на новый. Так и висит под категорией AndreyK. Поэтому сначала запускался старый скрипт. Думал, опять не повезло. Пришлось в доработанном скрипте категорию переименовать в AndreyK2. Странно.


Еще проблема.
Если объединенном с помощью скрипта меше опуститься уровнем ниже и сделать WELD вертексов, а затем вернуться обратно к skin, то веса у соединенных вертексов портятся. К примеру, у двух смежных вертексов такие веса:
Код:
0,400 Bone01
0,200 Bone02
0,200 Bone03
0,200 Bone04
А если их объединить, то получается бред:
Код:
0,308 Bone01
0,281 Bone01
0,206 Bone03
0,205 Bone02

Или:

было
Код:
0,700 Bone01
0,300 Bone02
стало
Код:
0,418 Bone01
0,275 Bone01
0,183 Bone02
0,124 Bone02
Насколько я понимаю, Max пытается усреднить значения. Но зачем их усреднять, если они идентичные? Все равно, что взять две единицы и попытаться их "усреднить". Идиотизм, короче.
Выход из проблемы нашел в использовании SkinUtilities.
То бишь, сначала соединяю все, что нужно с помощью скрипта от Chebu. Затем юзаю комманду Extract Skin Data To Mesh на полученном объекте. Потом делаю WELD всех вертексов (веса у смежных вертексов портятся). И в конце концов восстанавляваю правильные веса с помощью Import Skin Data From Mesh.
 

Chebu

Знаток
Рейтинг
59
#11
на здоровье.

Еще проблема.
Если объединенном с помощью скрипта меше опуститься уровнем ниже и сделать WELD вертексов, а затем вернуться обратно к skin, то веса у соединенных вертексов портятся.
теоретически, можно попробовать перед велдом снять в скине галку always deform, а после велда поставить обратно. save-load весов тоже может помочь.
 

firsak

Активный участник
Рейтинг
5
#12
Chebu, только что заметил кое-что еще.
При соединении нескольких объектов, дублируются envelope'ы. Допустим, три объекта, у каждого общая кость bone01. Соединяешь их - получаешь сразу три bone01 в списке модификатора skin. Одна из них нормальная, две остальные с нулевыми influences. Можете сделать, чтобы скрипт автоматом сносил лишние envelope'ы? Или может на что-то нажать можно? Кнопку remove zero weights вижу. Кнопку, типа, remove envelopes with zero influences не вижу. :(

Постоянно приходится отсоединять/присоединять объекты (ввиду особенности модели). Пустые envelope'ы плодятся в бешенном темпе.
 

firsak

Активный участник
Рейтинг
5
#14
firsak, поправлю в понедельник, когда до рабочего компьютера доберусь.
Нет ли каких-нибудь сподвижек в шлифовании скрипта? :) В принципе, и так уже хорош (не знаю, что бы я без него делал), но все же один баг присутствует (дублируются envelopes с разных объектов).
 

Chebu

Знаток
Рейтинг
59
#15
Прошу прощения, сейчас совсем не до этого. Когда будет время - отпишусь.
 

3dlub

Пользователь сайта
Рейтинг
2
#16
Есть несколько mesh'ев. У каждого свой модификатор skin. Вроде бы простая задача: объединить все объекты в один и сохранить при этом skin и все bone weights. Но у присоединяемых объектов всегда сбрасываются все данные в модификаторе skin. Как быть?
Есть немного странный способ, но работает на 100%
Скачиваете ActorX importer (скрипт для 3DMAX), и ActoX exporter (Плагин для 3D Max)
Устанавливате плагин, он появляется в утилитах.
Експортите сцену со всеми мешами и скинами. В файл формата PSK.
Далее очищаете сцену и импортите этот PSK с помощью скрипта ActorX importer.
Все! Сцена из одного меша. Все скины сохранены. Удачи.
 

INCUS

Знаток
Рейтинг
29
#18
А у меня, вроде, и без утилит получилось.
Weight Tool может скопировать в буфер веса выделенных вершин присоединяемого скина.
Так что, потом можно эту геометрию приаттачить к главной геометрии с главным скином и кости, ему же те добавить.
Отрыть уже этот главный Weight Tool, выделить те же вершины и, - paste.
Энвелопы, правда не сохраняются...наверное, из-за того, что у них свой копипаст.
 

Евгения Ремезова

Пользователь сайта
Рейтинг
2
#19
А можно поподробнее о ActorX importer? А то у меня не получается импортить, вываливается окно с ошибкой. Skin Utilities хорош для объединения двух мешей, но он не всегда корректно переносит веса.
 
Сверху