[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?
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.
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