Render.ru

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

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

Активный участник
Рейтинг
7
#1
Здравствуйте!
Извините, если повторюсь. Можете поделиться способами изменения различных свойств материалов?
Постараюсь начать.
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
#2
Всем привет еще раз. Постараюсь упростить вопрос.
Не подскажете, как можно выделить материал по карте.
Вот, к примеру, собираю карты colorcorrect
Код:
asd = getclassinstances ColorCorrect
возвращает, к примеру, такой массив
Код:
#(Map #3:ColorCorrect, Map #5:ColorCorrect, Map #7:ColorCorrect)
Вот, хотелось бы, получить массив материалов, имеющих эти карты. Есть ли какой-нибудь простой способ? Или только перебор всех материалом с проверкой на наличие colorcorrect?
 

igorznag

Мастер
Рейтинг
103
#3

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

Активный участник
Рейтинг
7
#4
Спасибо 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
#5
Продолжаю тему. Не подскажете как лучше поменять, к примеру, параметр 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
#6
Пример для карты 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
#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
тогда срабатывает, но на сложных миксовых картах уже не добирается до блюра. Помоги разобраться, пожалуйста.
 

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

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

igorznag

Мастер
Рейтинг
103
#12
Не подскажете, можно ли как-то использовать подобный код?
Да, можно.
Код:
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
#14
Опять застрял. Все отлично, только на короновских матах не работает. Не могу понять в чем причина.Стандартные и вирейские спокойно переваривает.
Вот код:
Код:
-- 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
#15
Еще одна проблема. Как сделать материалы инстансными из копий в мультисабе?.

В мультиматериале есть одинаковые неинстансные материалы. Написал код для поиска копий и замены их инстансами, но, почему-то, не работает:
Код:
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
#16
Код:
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
#18
Немножко не по теме, но все же.
Не подскажете, возможно ли выделить объекты в сцене не по материалу а по конкретной карте в материале?
К примеру, у нас несколько материалов с разными Cellular. Надо выделить объеты по конкретному Cellular.
 
Сверху