Notifications
Clear all

[Closed] superClassOf in multithreading

Perfect. Do you mean – as tag, I can send a material?

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

you can send whatever you want

fn workMaterial s e = 
(
	fn collectMats mat mats:#() fun: = 
	(
		if iskindof mat Material and (appendifunique mats mat) do for k=1 to getNumSubMtls mat where (m = getSubMtl mat k) != undefined do
		(
			if (appendifunique mats m) do fun mat mats:mats fun:fun
		)
		ok
	)
	val = e.Argument.value
	collectmats val.material mats:val.result fun:collectmats
	s.Dispose()
)

mythreads = #()
mythreads[1] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
mythreads[2] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
 
dotnet.addEventHandler myThreads[1] "DoWork" workMaterial
dotnet.addEventHandler myThreads[2] "DoWork" workMaterial
 
struct MaterialData(material, result = #())
	
ww[1] = MaterialData material:(multimaterial numsubs:(random 60 100)) 
myThreads[1].runworkerasync (dotnetmxsvalue ww[1])
ww[2] = MaterialData material:(multimaterial numsubs:(random 60 100)) 
myThreads[2].runworkerasync (dotnetmxsvalue ww[2])

while (myThreads[1].IsBusy or myThreads[2].IsBusy) and (not keyboard.escPressed) do ()
format "1 done:(%) - %
" ww[1].result.count ww[1]
format "2 done:(%) - %
" ww[2].result.count ww[2]

it’s an example how to run worker with arguments

Denis, I was very excited last night when I saw your vision in this matter, but I’m disappointed now when I see that it still crashes my max. Look what I came up to:


 
 (
 	local ww=#(#(),#()), subInMats=#()
 	local getSubmats, getSubmatsRecurse, capitalizeFirst, formatName
 	
 	struct matDef (mat, path)	
 	fn workMaterialD s e =
 	(
 		s.Dispose()
 		format "% thread Done. Results: %
" e.Result.value[1] e.Result.value[2]
 	)		
 		
 	fn workMaterial s e = 
 	(
 		val = e.Argument.value
 		fn capitalizeFirst str =
 			toUpper str[1] + subString str 2 -1
  
 		fn formatName mat index: =
 			if isKindOf mat TextureMap OR index == unsupplied then
 				capitalizeFirst ((classOf mat) as string) + "\\"
 			else (substituteString (substituteString (getSubTexmapSlotName mat index) " map" "")" Map" "") + "\\"
 		
 		fn getSubmatsRecurse mat matInst path:"" =
 		(	
 			for propName in (getPropNames mat) do
 			(
 				local prop = try(getProperty mat propname) catch ()
 				if isKindOf prop Material then
 					getSubmats prop path:path 	format:(capitalizeFirst (propname as string) + "\\" + formatName prop) thread:thread
 				else if classOf prop == ArrayParameter do
 				for sub = 1 to prop.count where isKindOf prop[sub] Material do 	
 					getSubmats prop[sub] path:path format:(formatName prop[sub]) thread:thread
 			)
 		)
 		
 		fn getSubmats mat path:"" format:"" =
 		(
 			local matInst = matDef mat:mat path:(path + format)
 			append subInMats matInst
 			getSubmatsRecurse mat matInst path:(path + format)
 			matInst
 		)
 		
 		fn workwiththismat thismat r:#() =
 		(
 			local subMatInsts = getSubmats thismat 
 			append r subMatInsts
 		)
 		workwiththismat val.material r:val.result
 		e.Result = dotnetmxsvalue #(val.thread, val.result)
 	)
 
 	mythreads = #()
 	mythreads[1] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
 	mythreads[2] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
 	 
 	dotnet.addEventHandler myThreads[1] "DoWork" workMaterial
 	dotnet.addEventHandler myThreads[2] "DoWork" workMaterial
 	
 	dotNet.addEventHandler mythreads[1]  "RunWorkerCompleted" workMaterialD
 	dotNet.addEventHandler mythreads[2]  "RunWorkerCompleted" workMaterialD
 	 
 	struct MaterialData(thread, material, result = #())
 		
 	ww[1] = MaterialData thread:1 material:(multimaterial numsubs:(random 60 100)) 
 	myThreads[1].runworkerasync (dotnetmxsvalue ww[1])
 	ww[2] = MaterialData thread:2 material:(multimaterial numsubs:(random 60 100)) 
 	myThreads[2].runworkerasync (dotnetmxsvalue ww[2])
 	OK
 )	
 
 

This is only the first part of my code, but smth went wrong already…

why do you call e.Argument in workMaterial if you don’t pass any?

because


while (myThreads[1].IsBusy or myThreads[2].IsBusy) and (not keyboard.escPressed) do ()
format "1 done:(%) - %
" ww[1].result.count ww[1]
format "2 done:(%) - %
" ww[2].result.count ww[2]

is creating an infinite loop and 3d max becomes not responding. I will send as result other information, here is just for me to see the result step by step.

If I replace this code:


 				if isKindOf prop Material then
 					 getSubmats prop path:path 	format:(capitalizeFirst (propname as string) + "\\" + formatName prop) thread:thread
 				 else if classOf prop == ArrayParameter do
 				 for sub = 1 to prop.count where isKindOf prop[sub] Material do 	
 					 getSubmats prop[sub] path:path format:(formatName prop[sub]) thread:thread

with


 				 if isKindOf prop Material then
 					print prop

then the sript doesn’t crash max

if you want to do everything faster:

fn capitalizeFirst str = 
(
	str[1] = toUpper str[1]
	str
)

why do you collect sub-materials searching in ArrayParameter props? does getSubMtl() not work for you for any reason?

i see in your code that in getSubmatsRecurse you call getSubmats, and in getSubmats you call getSubmatsRecurse… it should’t be like that

Do you mean like this:

(
	local ww=#(#(),#()), subInMats=#()
	local getSubmats, capitalizeFirst, formatName
	
	struct matDef (mat, path)	
	fn workMaterialD s e =
	(
		s.Dispose()
		format "% thread Done. Results: %
" e.Result.value[1] e.Result.value[2]
	)		
		
	fn workMaterial s e = 
	(
		val = e.Argument.value
		fn capitalizeFirst str = 
		(
			str[1] = toUpper str[1]
			str
		)
 
		fn formatName mat index: =
			if isKindOf mat TextureMap OR index == unsupplied then
				capitalizeFirst ((classOf mat) as string) + "\\"
			else (substituteString (substituteString (getSubTexmapSlotName mat index) " map" "")" Map" "") + "\\"
		
		fn getSubmats mat path:"" format:"" =
		(
			local matInst = matDef mat:mat path:(path + format)
			append subInMats matInst
			for propName in (getPropNames mat) do
			(
				local prop = try(getProperty mat propname) catch ()
				if isKindOf prop Material then
					getSubmats prop path:(path + format) 	format:(capitalizeFirst (propname as string) + "\\" + formatName prop) thread:thread
				else if classOf prop == ArrayParameter do
				for sub = 1 to prop.count where isKindOf prop[sub] Material do 	
					getSubmats prop[sub] path:(path + format) format:(formatName prop[sub]) thread:thread
			)
			matInst
		)
		
		fn workwiththismat thismat r:#() =
		(
			local subMatInsts = getSubmats thismat 
			append r subMatInsts
		)
		workwiththismat val.material r:val.result
		e.Result = dotnetmxsvalue #(val.thread, val.result)
	)

	mythreads = #()
	mythreads[1] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
	mythreads[2] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
	 
	dotnet.addEventHandler myThreads[1] "DoWork" workMaterial
	dotnet.addEventHandler myThreads[2] "DoWork" workMaterial
	
	dotNet.addEventHandler mythreads[1]  "RunWorkerCompleted" workMaterialD
	dotNet.addEventHandler mythreads[2]  "RunWorkerCompleted" workMaterialD
	 
	struct MaterialData(thread, material, result = #())
		
	ww[1] = MaterialData thread:1 material:(multimaterial numsubs:(random 60 100)) 
	myThreads[1].runworkerasync (dotnetmxsvalue ww[1])
	ww[2] = MaterialData thread:2 material:(multimaterial numsubs:(random 60 100)) 
	myThreads[2].runworkerasync (dotnetmxsvalue ww[2])
	OK
)	

anyway, it’s crashing max.

because I need to get all the material map tree, like here:

and without multithreading this code is working very very well, the only problem is that it takes long to calculate in big scenes.

Page 2 / 4