Notifications
Clear all

[Closed] Quick way to search OBJ files?

In Max when you go to import an OBJ file a window pops up showing the names of all the meshs in it, and it does this very quickly. In Maxscript I’m doing the same thing by opening the obj ( openFile objPath mode:“r” ) and then using skipToString objFile “g ” , but I find it is several times slower then Maxs actual OBJ importer. Does anyone know of a faster way to get the mesh names using maxscript?

9 Replies

Not sure if you need to select which objects to import, but if you just want to import everything in the obj I believe you can use this:
importFile importPath #noPrompt missingExtFilesAction:#logmsg using:OBJIMP quiet:true

Well I actually just want to get the mesh and material names from the obj file, I don’t want to import them.

you could try regex



(
	gc();t1=timestamp();hf = heapfree
		
	txt = (dotNetClass "system.io.file").readalltext @"C:\Users\User\Documents\3dsmax\export\tmp.obj"

	format "Time: %sec. Mem: %\n" ((timestamp()-t1)/1000 as float) (hf-heapfree)
	pattern = "g\s+(\w+)\r\n(usemtl\s+(\w+))\r\n"

	-- re_options = dotNet.combineEnums (dotNetClass "System.Text.RegularExpressions.RegexOptions").multiline (dotNetClass "System.Text.RegularExpressions.RegexOptions").IgnoreCase
	
	matches = (dotNetClass "System.Text.RegularExpressions.RegEx").Matches txt pattern -- re_options
	
	
	for i=0 to matches.count-1 do
	(
		format "%:%\n" ((matches.item i).groups.item 1).value ((matches.item i).groups.item 3).value
		
	)	
		

	format "Time: %sec. Mem: %\n" ((timestamp()-t1)/1000 as float) (hf-heapfree)
)	

Hey Serejah, thanks for taking the time to post that, it’s much faster then what I was using before! I do have a question about it though; is it possible to find out where in the txt each match comes from? Like what line or character number they are from? I can’t be sure how many materials each mesh will have, but if I have their position in the file I can determine which and how many are assigned to each mesh.

Sure. You can either use Show method in listener or check msdn

it will be not the same quick as using regex but good enough, and it will give you line’s index:
(
t = timestamp()
h = heapfree

local ss = (dotNetClass "system.io.file").readalllines @"C:\Users\user\Documents\3dsmax\export\test.obj"

line = 0
pattern = "g *"
data = for s in ss collect
(
	line += 1
	if matchpattern s pattern:pattern then #(line, substring s 3 -1)
	else dontcollect
)

format "time:% heap:%\n" (timestamp() - t) (h - heapfree)
data

)

code format doesn’t work for me right…

if you need a material info – it’s the next to geometry name (“g *”) line

i would make a c# assembly on the fly to make it faster and to save memory. there are many examples on this forum how to do it

take care when reading objs, lots of crazy formatings are out there

matlib statements can occur anywhere in the file
also multiple matlibs are possible
defined in separate lines or in a single matlib-tag with multiple names

in each group “g” there are tags called usemtl “name”
this name refers to a material in any of the specified matlibs
name is absulte or relative in double-quotes or not

only collect mat-names for a specific group “g”

fun part:
this groups can occur multiple times in an obj
so, parts of a mesh here, another part there, vert-indices spread all over the place
collecting the materials for each group can get tricky

and…
there might be no group tag in the whole obj
this is the “default”-group which you see sometimes when importing into max

there are also “o”-tags, which would be the real start of an object
but over some 20++ years every app is using “g”, so max’s importer does the same

gw