Render.ru
Поддержать

Изменение свойств материалов

Александр Якушев

Активный участник
Рейтинг
7
Здравствуйте!
Извините, если повторюсь. Можете поделиться способами изменения различных свойств материалов?
Постараюсь начать.
1. Скрип, который включает карты во вьюпорте:
( 
m = getclassinstances CoronaMtl
join m (getclassinstances standardmaterial) 
join m (getclassinstances  VrayMtl) 
	
if m.count ==0 do return 0 
local SwithState=m[1].showInViewport 
for i in m do 
( 
	try(showTextureMap i i.texmapDiffuse true)catch()
	try(showTextureMap i true)catch()
) 
)
код заимствованный с showTextureMap, добавил еще короновские материалы
2. Скрипт меняет каналы карт:

rollout test "Material Editor. Active Slot." width:220 height:40
(spinner sp_map_channel "Map Channel:" range:[1, 99, 1] pos:[5,10] scale:1 fieldwidth:50 type:#integer
button btn_apply "Apply" pos:[150,7]; on btn_apply pressed do
(maps = getClassInstances bitmaptexture target:meditMaterials[activeMeditSlot]
for m in maps do m.coords.mapChannel=sp_map_channel.value )); createdialog test
3. Здесь заготовка скрипта для поиска карт в сцене:
-- tested in 3DMax 2014
(
rollout MapsFinder "MapsFinder"
(
--Variables Declerations
--------------------------------
global FindMat = #()
global FindMatName = #()

--Function
---------------------------------

--Interface
--------	
dropDownList ddl1 "Select type map:" items:#("ColorCorrect", "Color Edge", "Checker", "Color_Correction", "Cellular") selection:1
button bnFind "Analyze" width:300 
listbox ListMat "Please use DoubleClick for getting mat:"  height:43
button bnGetMat "Get materials to MatEditor" width:150  across:2
button bnSelObj "Select all objects " width:150 
-------------------
)
--createDialog MapsFinder
MapsFinder_float = newRolloutFloater "MapsFinder" 350 730 
addRollout MapsFinder MapsFinder_float
)
Пытался доработать, но все время спотыкаюсь. Если получится, постараюсь все-таки добить.
Какие полезные функции еще можно добавить ?

Помогите систематизировать различные способы обращения и перебора свойств материалов(также врэеевских, короновских) плз.
В каких случаях лучше использовать numsubs, getNumSubTexmaps, getSubTexmap и т.д.?

Александр Якушев

Активный участник
Рейтинг
7
Всем привет еще раз. Постараюсь упростить вопрос.
Не подскажете, как можно выделить материал по карте.
Вот, к примеру, собираю карты colorcorrect
asd = getclassinstances ColorCorrect
возвращает, к примеру, такой массив
#(Map #3:ColorCorrect, Map #5:ColorCorrect, Map #7:ColorCorrect)
Вот, хотелось бы, получить массив материалов, имеющих эти карты. Есть ли какой-нибудь простой способ? Или только перебор всех материалом с проверкой на наличие colorcorrect?

igorznag

Мастер
Рейтинг
103
Александр ЯкушевИли только перебор всех материалом с проверкой на наличие colorcorrect?
Почему вас не устраивает вариант с перебором всех материалов?
asd=for m in scenematerials where (getclassinstances ColorCorrect target:m).count>0 collect m

Александр Якушев

Активный участник
Рейтинг
7
Спасибо igorznag!!! Очень лаконично и просто!
Если вас не затруднит, оцените код, может быть избавите от "детских" ошибок.
На радостях вот дописал скрипт:
-- tested in 3DMax 2014
(
rollout MapsFinder "MapsFinder"
(
--Variables Declerations
--------------------------------
global FindMat = #()
global FindMatName = #()

--Function
---------------------------------
fn theAllMat = 
(		
		local allMat = #()
		allMat = scenematerials
		for i in meditMaterials do appendIfUnique allMat i
		for i in objects do if i.material != undefined do appendIfUnique allMat i.material
		return allMat
	)
	
fn find_ColorCorrect mat =
	(
		for m in theAllMat() where (getclassinstances ColorCorrect target:m).count>0 do 
		(
			if (appendIfUnique FindMat m)== true do append FindMatName m.name
			)
	)
		
		
fn find_Checker mat =
	(
		for m in theAllMat() where (getclassinstances Checker target:m).count>0 do 
		(
			if (appendIfUnique FindMat m)== true do append FindMatName m.name
			)
	)

fn find_Color_Edge mat = 
	(
		for m in theAllMat() where (getclassinstances Color_Edge target:m).count>0 do 
		(
			if (appendIfUnique FindMat m)== true do append FindMatName m.name
			)
	)
fn find_Color_Correction mat = 
	(
		for m in theAllMat() where (getclassinstances Color_Correction target:m).count>0 do 
		(
			if (appendIfUnique FindMat m)== true do append FindMatName m.name
			)
	)
fn find_Cellular mat = 
	(
		for m in theAllMat() where (getclassinstances Cellular target:m).count>0 do 
		(
			if (appendIfUnique FindMat m)== true do append FindMatName m.name
			)
	)	
	
--Interface
--------	

dropDownList ddl1 "Select type map:" items:#("ColorCorrect", "Color Edge", "Checker", "Color_Correction", "Cellular") selection:1

button bnFind "Analyze" width:300 

listbox ListMat "Please use DoubleClick for getting mat:"  height:43
		
button bnGetMat "Get materials to MatEditor" width:150  across:2
button bnSelObj "Select all objects " width:150 
		
		
-------------------
	on bnFind pressed do 
	(	
		FindMat = #()
		FindMatName = #()
		
		if ListMat.items != 0 do ListMat.items = #()
		
		case ddl1.selection of 
		(
			1: find_ColorCorrect m 
			2: find_Color_Edge m 
			3: find_Checker m
			4: find_Color_Correction m 
			4: find_Cellular m
		)
	
		if FindMat.count != 0 then ListMat.items = FindMatName
	)
--------------------	
	on bnGetMat pressed do 
	(	
		try(
			for i = 1 to FindMat.count do meditmaterials[medit.GetActiveMtlSlot() + i - 1]   = FindMat[i]
			)catch()
	)
-------------------
	on bnSelObj pressed do
	(
		local NeedObj = #()
		for m in FindMat do join NeedObj (refs.dependentNodes m)
		select NeedObj
		)
	
	
	on ListMat doubleClicked i do
	(
		for m in FindMat do
			if m.name == (ListMat.items[i]) do meditmaterials[medit.GetActiveMtlSlot()]  = m
		)

)
--createDialog MapsFinder
MapsFinder_float = newRolloutFloater "MapsFinder" 350 730 
addRollout MapsFinder MapsFinder_float
)

Александр Якушев

Активный участник
Рейтинг
7
Продолжаю тему. Не подскажете как лучше поменять, к примеру, параметр blur только в слоте Diffuse, с учетом того, что там могут быть смешанные карты произвольной глубины(вроде микс в миксе с colorcorrect и т.д)
Как можно сюда прикрутить рекурсивную функцию, например:
fn recMatBlurDiffuse mat  blurVal=
(
    if mat != undefined do
    (
        if iskindof mat texturemap do mat.coords.blur = blurVal
        if mat.numsubs != 0 do for i = 1 to mat.numsubs do recMatBlurDiffuse mat[i]  blurVal
        )
    )   
for i in theAllMat() do recMatBlurDiffuse i  0.5
или такой вариант
for i in getclassinstances Bitmaptexture do try(i.coords.blur = 0.4)catch()
Проблема в том, что данные способы меняют параметр blur везде где можно. Как можно их ограничить слотом diffuse или другими?

igorznag

Мастер
Рейтинг
103
Пример для карты Diffuse материала Standard:
fn recMapBlurDiffuse mat blurVal=
(
if mat != undefined do
(
if iskindof mat Bitmaptexture do mat.coords.blur = blurVal
if mat.numsubs != 0 do for i = 1 to mat.numsubs do recMapBlurDiffuse mat[i] blurVal
)
)

fn recMatBlurDiffuse mat blurVal=
(
if mat != undefined do
(
if findString (mat as string) "Diffuse_Color__Map"==9 do recMapBlurDiffuse mat blurVal
if mat.numsubs != 0 do for i = 1 to mat.numsubs do recMatBlurDiffuse mat[i] blurVal
)
)

for i in scenematerials do recMatBlurDiffuse i  0.5

Александр Якушев

Активный участник
Рейтинг
7
Спасибо igorznag за помощь, но немного не работает. Если строку
if findString (mat as string) "Diffuse_Color__Map"==9 do recMapBlurDiffuse mat blurVal
немного поменять на
if findString (mat as string) "Diffuse_Color__Map"==9 do mat.coords.blur = blurVal
тогда срабатывает, но на сложных миксовых картах уже не добирается до блюра. Помоги разобраться, пожалуйста.

igorznag

Мастер
Рейтинг
103
Спасибо igorznag за помощь, но немного не работает. Помоги разобраться, пожалуйста.
Я не знаю как вам помочь. У меня все работает нормально.

igorznag

Мастер
Рейтинг
103
Александр ЯкушевПрилагаю скриншот ошибки. Помогите разобраться, пожалуйста.
Почему вы скопировали только часть кода из сообщения 6?
Нужно скопировать обе функции: recMatBlurDiffuse и recMapBlurDiffuse.

Александр Якушев

Активный участник
Рейтинг
7
😕 Вот я слепой. Не заметил разницы между recMatBlurDiffuse и recMapBlurDiffuse ) Спасибо, все заработало! Еще небольшой вопрос. Не подскажете, можно ли как-то использовать подобный код?
for i in getclassinstances Bitmaptexture do try(i.coords.blur = 0.4)catch()
В общем, что-бы максимально оптимизировать функцию.

igorznag

Мастер
Рейтинг
103
Не подскажете, можно ли как-то использовать подобный код?
Да, можно.
fn recMatBlurDiffuse mat blurVal=
(
if mat != undefined do
(
if findString (mat as string) "Diffuse_Color__Map"==9 do
for i in getclassinstances Bitmaptexture target:mat do try(i.coords.blur = blurVal)catch()
if mat.numsubs != 0 do for i = 1 to mat.numsubs do recMatBlurDiffuse mat[i] blurVal
)
)

for i in scenematerials do recMatBlurDiffuse i  0.5

Александр Якушев

Активный участник
Рейтинг
7
Опять застрял. Все отлично, только на короновских матах не работает. Не могу понять в чем причина.Стандартные и вирейские спокойно переваривает.
Вот код:
-- tested in 3DMax 2014
try destroyDialog editBlur catch()
rollout editBlur "EditBlurMat"
(
--function
fn theAllMat =
(       
        local allMat = #()
        allMat = scenematerials
        for i in meditMaterials do appendIfUnique allMat i
        for i in objects do if i.material != undefined do appendIfUnique allMat i.material
        allMat
    )
fn recMatBlurDiffuse mat blurVal nameMap =
(
    if mat != undefined do
    (
    if (findString (mat as string) nameMap == 9 or findString (mat as string) nameMap == 16) do try(for i in getclassinstances Bitmaptexture target:mat do i.coords.blur = blurVal)catch()
    if mat.numsubs != 0 do for i = 1 to mat.numsubs do recMatBlurDiffuse mat[i] blurVal nameMap
    )
)
--Interface
dropDownList ddl1 "" items:#("Diffuse", "Reflection", "Refraction", \
    "Bump", "Displacement", "Opacity") selection:1 across:3
spinner theBlurVal "Blur:" range:[0,40, 1] type:#float
button addToList  "Add to list"   
listbox ListMap ""  height:4
button theGo "Execute"
       
-------------------
global theListData = #()
on execute editBlur do theListData = #()
on addToList  pressed do
(
    ListMap.items = append ListMap.items  (ddl1.selected + "  blur - " + (theBlurVal.value as string))
    append theListData    #(ddl1.selected, theBlurVal.value)
    )   
on theGo pressed do
    for mat in theAllMat() do    for i in theListData do recMatBlurDiffuse mat i[2] i[1]
)
createDialog editBlur width:280
Если убрать в строчке try(for i in getclassinstances Bitmaptexture target:mat do i.coords.blur = blurVal)catch() - try()catch(), то выдает такую ошибку -- No "map" function for undefined <<
Даже если вместо recMatBlurDiffuse использовать вариант из сообщения 6, все равно на короновских не срабатывает.
Текст "findString (mat as string) nameMap == 16", как раз для короновского материала - "SubAnim:usemap_diffuse". igorznag помоги плз.

Александр Якушев

Активный участник
Рейтинг
7
Еще одна проблема. Как сделать материалы инстансными из копий в мультисабе?.

В мультиматериале есть одинаковые неинстансные материалы. Написал код для поиска копий и замены их инстансами, но, почему-то, не работает:
fn compareMat m1 m2 =
(
    try(if m1.diffuseMap.fileName == m2.diffuseMap.fileName then return 1 else return 0)catch(return 0)
    )
 
    theMatArray = getclassinstances Standardmaterial
    for i = 1 to theMatArray.count do
        for j = 1 to theMatArray.count do
            if i != j do if (compareMat theMatArray[i] theMatArray[j]) == 1 do theMatArray[i] = theMatArray[j]
https://yadi.sk/i/hJDGsDmVZR8bR - скрин с примером мультимата

igorznag

Мастер
Рейтинг
103
fn compareMat m1 m2 =
(
    try(if m1.diffuseMap.fileName == m2.diffuseMap.fileName then return 1 else return 0)catch(return 0)
    )
 
    theMatArray = getclassinstances Standardmaterial
    for i = 1 to theMatArray.count do
        for j = 1 to theMatArray.count do
            if i != j do if (compareMat theMatArray[i] theMatArray[j]) == 1 do replaceInstances theMatArray[i] theMatArray[j]

Александр Якушев

Активный участник
Рейтинг
7
Немножко не по теме, но все же.
Не подскажете, возможно ли выделить объекты в сцене не по материалу а по конкретной карте в материале?
К примеру, у нас несколько материалов с разными Cellular. Надо выделить объеты по конкретному Cellular.