Jump to content

Post Processing An Export?


Atom

Recommended Posts

HI All,

 

I am trying to add the usemtl tag after every group inside a OBJ file that the ROP Output generates. The Houdini exporter does not seem to support this feature of the OBJ file format.

 

This simple fixup script does the job ok.

# Add a default material for each group.
# Run after .OBJ export.

file_name_in = r"C:\Users\Developer\Desktop\my_mesh.obj"
file_name_out = r"C:\Users\Developer\Desktop\my_mesh_mat.obj"
with open(file_name_in, 'r') as f:
    lines = f.read().splitlines()   # Remove slash n character at the end of each line.
f.close()

mat_count=1
new_lines = []
 
for line in lines:
    new_lines.append(line)
    ary = line.split(' ')
    if ary[0] == 'g':
        # Detected a goup.
        mat_name = "mat_%d" % mat_count
        mat_count +=1
        new_lines.append("usemtl %s" % mat_name)

f = open(file_name_out, 'w')
for line in new_lines:
  f.write("%s\n" % line)
f.close()

So the question is how do I leverage the PostFrame Script event of the ROP Output node?

I would need to somehow pass the frame # to the script. I have never used args* in python yet.

 

Does anyone have tips on how to accomplish this task?

 

Thanks

Edited by Atom
  • Like 1
Link to comment
Share on other sites

Ok, this is my first venture into using those Pre/Post script fields. There is a browse button and I browse to my external .py script but this just produces an error when I click Save To Disk because it is trying to process the file name to the script as code. I give up on that and just press CTRL-E in the field and type in a multi line python script. Remember to change the Language from Hscript to Python for your chosen field.

 

I place this code in the Post-Write Script field:

import hou
import os

node = hou.pwd()
file_name_in = node.evalParm('sopoutput')
s = os.path.splitext(file_name_in)[0]
file_name_out = "%s_mat.obj" % s

print file_name_in, file_name_out

with open(file_name_in, 'r') as f:
    lines = f.read().splitlines()   # Remove slash n character at the end of each line.
f.close()

mat_count=1
new_lines = []
 
for line in lines:
    ary = line.split(' ')
    if ary[0] == 'g':
        # Detected a group.
        if mat_count == 1:
            # The first g token should actually be an o token with the object name.
            new_lines.append("o %s" % node.parent())
        else:
            new_lines.append(line)
            mat_name = "mat_%d" % mat_count
            new_lines.append("usemtl %s" % mat_name)
        mat_count +=1
    else:
        new_lines.append(line)

f = open(file_name_out, 'w')
for line in new_lines:
  f.write("%s\n" % line)
f.close()

os.remove(file_name_in)
#os.rename(file_name_out, file_name_in)


This code does almost everything I wanted. The last line is intended to rename the newly created file to the same name in the Output File field in the node panel. But it does not work and errors out. My guess is that Houdini is still holding some file handle to the original name until after Post-Render thus I can not rename my new file to the same name as the original. I can delete it however...? Edited by Atom
Link to comment
Share on other sites

I wondered about that, but I am dealing with a sequence. I assumed Post-Render was after the entire sequence was done. In that case I would not have the correct $F to construct a filename.

 

Does Post-Render fire after every frame or after the end of all render/exports?

Link to comment
Share on other sites

Ok, I see what you mean, I could fetch the parms from the Start/End/Inc and run a clean up script at the end.

I managed to simplify the code and this seems to work.
By simply adding a usemtl after each g token, other 3D packages can import this and create a material for the groups.
 

Place this code in a Post-Write Script field of a ROP Output Driver and change Hscript to Python. This code will write a new repaired OBJ file with a PREFIX to the file name and erase the original.

# Add a default material for each group.
# Run after .OBJ export.

import os

PRE_FIX = "ap"                                          # Pick your own prefix token here.
node = hou.pwd()                                        # Get the node this code is running under.
file_name_in = node.evalParm('sopoutput')               # Fetch the name from the ROP Output panel.
the_path = os.path.dirname(file_name_in)                # Get the path.
the_name = os.path.basename(file_name_in)               # Get the name.
name_only = os.path.splitext(the_name)[0]               # Remove the file extension.
s = "%s_%s.obj" % (PRE_FIX,name_only)                   # Construct a new name that uses the PREFIX.
file_name_out = os.path.join(the_path, s)

with open(file_name_in, 'r') as f:
    lines = f.read().splitlines()   # Remove slash n character at the end of each line.
f.close()

mat_count=0
new_lines = []
for line in lines:
    ary = line.split(' ')
    if ary[0] == 'g':
        if mat_count > 0:
            # Detected a goup.
            new_lines.append(line)
            mat_name = "mat_%d" % mat_count
            new_lines.append("usemtl %s" % mat_name)
        mat_count +=1
    else:
        new_lines.append(line)
        
f = open(file_name_out, 'w')
for line in new_lines:
  f.write("%s\n" % line)
f.close()

os.remove(file_name_in)
Edited by Atom
Link to comment
Share on other sites

  • 3 years later...

Thanks Atom, this script is really useful!

I've introduced a feature, which introduces constant material names via group names.

It's a simple hack to the wavefront exporter, but it works once you prepare groups to be able to transfer material names. I'll leave it here, if someone find it useful or wants to improve it.

Best

Manuel

 

## Add a default material for each group and specific material names for specific groups
# Run after .OBJ export.

import os

PRE_FIX = "hobj"                                        # Pick your own prefix token here.
node = hou.pwd()                                        # Get the node this code is running under.
file_name_in = node.evalParm('sopoutput')               # Fetch the name from the ROP Output panel.
the_path = os.path.dirname(file_name_in)                # Get the path.
the_name = os.path.basename(file_name_in)               # Get the name.
name_only = os.path.splitext(the_name)[0]               # Remove the file extension.
s = "%s_%s.obj" % (PRE_FIX,name_only)                   # Construct a new name that uses the PREFIX.
file_name_out = os.path.join(the_path, s)

with open(file_name_in, 'r') as f:
    lines = f.read().splitlines()   # Remove slash n character at the end of each line.
f.close()

mat_count=0
new_lines = []
for line in lines:
    ary = line.split(' ')   
    if ary[0] == 'g':
        if mat_count > 0:               # Detected a group.
            gr_nm=ary[1]                # check group name
            if gr_nm[0:4] == 'hmt_':    # Pick another material prefix token here.
                new_lines.append(line)
                mat_name = gr_nm
                new_lines.append("usemtl %s" % mat_name)
            else:        
                new_lines.append(line)
                mat_name = "mat_%d" % mat_count
                new_lines.append("usemtl %s" % mat_name)
        mat_count +=1
    else:
        new_lines.append(line)
        
f = open(file_name_out, 'w')
for line in new_lines:
  f.write("%s\n" % line)
f.close()

os.remove(file_name_in)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...