If you use this and find it does not work for you just post your obj file here and i will sort make it export and egg. OBJ format is non standard so bear with me as i get all bugs and new features added to it.
EDIT: LOL fixed one bug already!
""" by
.___..__ .___.___.___.__..__ . .
| [__)[__ [__ [__ | |[__)|\/|
| | \[___[___| |__|| \| |
obj2egg.py [n##][b][t][s] filename1.obj ...
-n regenerate normals with # degree smoothing
exaple -n30 (normals at less 30 degrees will be smoothed)
-b make binarmals
-t make tangents
-s show in pview
licensed under WTFPL (http://sam.zoy.org/wtfpl/)
"""
from pandac.PandaModules import *
import math
def floats(flaot_list):
return [ float(number) for number in flaot_list]
def ints(int_list):
return [ int(number) for number in int_list]
def read_obj(filename):
file = open(filename)
egg = EggData()
meshName = ""
points = []
uvs = []
normals= []
faces = []
idx = 0
for line in file.readlines()+['o']:
line = line.strip()
if not line or "#" == line[0]:
continue
tokens = line.split()
if tokens:
if tokens[0] == "v":
points.append(floats(tokens[1:]))
elif tokens[0] == "vt":
uvs.append(floats(tokens[1:]))
elif tokens[0] == "vn":
normals.append(floats(tokens[1:]))
elif tokens[0] == "f":
face = []
for token in tokens[1:]:
face.append(ints(token.split("/")))
faces.append(face)
elif tokens[0] == "g" or tokens[0] == "o":
if meshName != "":
egn = EggGroup(meshName)
egg.addChild(egn)
evp = EggVertexPool(meshName)
egn.addChild(evp)
for face in faces:
ep = EggPolygon()
for vertex in face:
if len(vertex) == 3:
iPoint, iUv, iNormal = vertex
ev = EggVertex()
point = points[iPoint-1]
ev.setPos(Point3D(point[0],point[1],point[2]))
ev.setUv(Point2D(*uvs[iUv-1][0:2]))
ev.setNormal(Vec3D(*normals[iNormal-1]))
evp.addVertex(ev)
ep.addVertex(ev)
else:
print vertex
egn.addChild(ep)
if len(tokens) > 1 :
meshName = tokens[1]
return egg
if __name__ == "__main__":
import getopt
import sys,os
try:
opts, args = getopt.getopt(sys.argv[1:], "hn:bs", ["help","normals","binormals","show"])
except getopt.error, msg:
print msg
print __doc__
sys.exit(2)
show = False
for o, a in opts:
if o in ("-h", "--help"):
print __doc__
sys.exit(0)
elif o in ("-s", "--show"):
show = True
for infile in args:
try:
if ".obj" not in infile:
print "WARNING",infile,"does not look like a valid obj file"
continue
egg = read_obj(infile)
f, e = os.path.splitext(infile)
outfile = f+".egg"
for o, a in opts:
if o in ("-n", "--normals"):
egg.recomputeVertexNormals(float(a))
elif o in ("-b", "--binormals"):
egg.recomputeTangentBinormal(GlobPattern(""))
egg.removeUnusedVertices(GlobPattern(""))
egg.triangulatePolygons(EggData.TConvex & EggData.TPolygon)
egg.writeEgg(Filename(outfile))
if show:
os.system("pview "+outfile)
except Exception,e:
print e
my utility does not read mtl files which would contain texture. And obj files are not the best format. Converting it to an egg 1st is always a better option.
Updated the file for Bradamante
now can read textures and does not choke on missing normal input
from pandac.PandaModules import *
import math
def _float(i):
try:
return float(i)
except:
return 0
def floats(flaot_list):
return [ _float(number) for number in flaot_list]
def _int(i):
try:
return int(i)
except:
return 0
def ints(int_list):
return [ _int(number) for number in int_list]
def read_mtl(filename):
textures = {}
name = "default"
file = open(filename)
for line in file.readlines():
if not line or "#" == line[0]:
continue
tokens = line.split()
if tokens:
if tokens[0] == "newmtl":
name = tokens[1]
elif tokens[0] == "map_Kd":
textures[name] = tokens[1]
else:
print tokens
print textures
return textures
def read_obj(filename):
file = open(filename)
egg = EggData()
meshName = ""
textures = {}
texture = None
points = []
uvs = []
normals= []
faces = []
idx = 0
for line in file.readlines()+['o']:
line = line.strip()
if not line or "#" == line[0]:
continue
tokens = line.split()
if tokens:
if tokens[0] == "v":
points.append(floats(tokens[1:]))
elif tokens[0] == "vt":
uvs.append(floats(tokens[1:]))
elif tokens[0] == "vn":
normals.append(floats(tokens[1:]))
elif tokens[0] == "f":
face = []
for token in tokens[1:]:
face.append(ints(token.split("/")))
faces.append(face)
elif tokens[0] == "g" or tokens[0] == "o":
if meshName != "":
egn = EggGroup(meshName)
egg.addChild(egn)
if texture and texture in textures:
et = EggTexture(texture,textures[texture])
evp = EggVertexPool(meshName)
egn.addChild(evp)
for face in faces:
ep = EggPolygon()
if et: ep.addTexture(et)
for vertex in face:
if len(vertex) == 3:
iPoint, iUv, iNormal = vertex
ev = EggVertex()
point = points[iPoint-1]
ev.setPos(Point3D(point[0],point[1],point[2]))
ev.setUv(Point2D(*uvs[iUv-1][0:2]))
ev.setNormal(Vec3D(*normals[iNormal-1]))
evp.addVertex(ev)
ep.addVertex(ev)
else:
print vertex
egn.addChild(ep)
if len(tokens) > 1 :
meshName = tokens[1]
elif tokens[0] == "mtllib":
textures.update(read_mtl(tokens[1]))
elif tokens[0] == "usemtl":
texture = tokens[1]
else:
print tokens[0],"unkown"
return egg
if __name__ == "__main__":
import getopt
import sys,os
try:
opts, args = getopt.getopt(sys.argv[1:], "hn:bs", ["help","normals","binormals","show"])
except getopt.error, msg:
print msg
print __doc__
sys.exit(2)
show = False
for o, a in opts:
if o in ("-h", "--help"):
print __doc__
sys.exit(0)
elif o in ("-s", "--show"):
show = True
for infile in args:
if ".obj" not in infile:
print "WARNING",infile,"does not look like a valid obj file"
continue
egg = read_obj(infile)
f, e = os.path.splitext(infile)
outfile = f+".egg"
for o, a in opts:
if o in ("-n", "--normals"):
egg.recomputeVertexNormals(float(a))
elif o in ("-b", "--binormals"):
egg.recomputeTangentBinormal(GlobPattern(""))
egg.removeUnusedVertices(GlobPattern(""))
egg.triangulatePolygons(EggData.TConvex & EggData.TPolygon)
egg.writeEgg(Filename(outfile))
if show:
os.system("pview "+outfile)
Is there a new version of this wonderful little application?
I have used it a little to convert my files, but I sometimes have some problems with the result.
On one object I had two textures. But inside pview only one was used, on the whole model. I solved this by splitting the object into two, but still in the same file, and everything worked just fine. I then added a third object into the file and suddenly one texture was used everywhere again, although the file contained three objects.
It feels a bit random.
The models are done in Silo, might that be why?
Can’t post an example at the moment but will do once I have access to the files again.
Thankful for any help.
This looks like just what the doctor ordered. I’ve got an obj file I want to make into an egg, though I’ll admit it’s a bit non-standard and unfortunately this app, as is, doesn’t quite achieve what I’m looking for.
My obj is just a two point poly chain, so when you open it up it’s got some tags (v) for vertices and some tags (l) for lines. Unfortunately your app here doesn’t understand the lines, and the egg it outputs is empty.
All I really want is the vertices, with no other information.If the egg format can support 2 point polys then the lines would be nice, in case I can use them later, but they aren’t strictly necessary.
My goal is to make a bunch of vertices in my modeling app, Lightwave, and then import it into panda so I can put some other nodes at the locations of those vertices. Those nodes will be used for AI pathfinding. I don’t plan on using the vertices for anything more than their location data, I’ll just dump them when I have it. Do you think you could modify this sweet little app to shell out an egg full of vertices for me?
My obj file is here and the mtl is here, but it’s not the final one I’m going to use. I’m eventually hoping to have many of these files for many different maps in the game.
The program I found at the end of that link you just posted actually works fine, it outputs an egg with all the verts and the lines too. So thankfully I won’t have to wrack my poor artist brain, useless thing that it is, to get what I need. Thanks a bunch Treeform, this utility saves my arse.
I don’t know. I think panda3d has a native way to load obj files now.
You can in fact load .obj model files in Panda3D, starting from version 1.10. Just add `load-file-type p3assimp` to your config.prc file in the etc folder of your Panda3D installation, and you can then load .obj models using `model = self.loader.load_model("my_model.obj")` .```
From https://stackoverflow.com/a/53840204