- ran 2to3 on export_3ds.py, import_3ds.py and export_x3d.py

- added operators and menu items for ^
This commit is contained in:
Arystanbek Dyussenov 2009-08-10 13:49:55 +00:00
parent d1f22f6ce3
commit 675936b42c
5 changed files with 291 additions and 192 deletions

@ -46,14 +46,17 @@ from the lib3ds project (http://lib3ds.sourceforge.net/) sourcecode.
# Importing modules # Importing modules
###################################################### ######################################################
import Blender import struct
import bpy import bpy
from BPyMesh import getMeshFromObject
from BPyObject import getDerivedObjects # import Blender
try: # from BPyMesh import getMeshFromObject
import struct # from BPyObject import getDerivedObjects
except: # try:
struct = None # import struct
# except:
# struct = None
# So 3ds max can open files, limit names to 12 in length # So 3ds max can open files, limit names to 12 in length
# this is verry annoying for filenames! # this is verry annoying for filenames!
@ -85,58 +88,58 @@ def sane_name(name):
#Some of the chunks that we will export #Some of the chunks that we will export
#----- Primary Chunk, at the beginning of each file #----- Primary Chunk, at the beginning of each file
PRIMARY= long("0x4D4D",16) PRIMARY= int("0x4D4D",16)
#------ Main Chunks #------ Main Chunks
OBJECTINFO = long("0x3D3D",16); #This gives the version of the mesh and is found right before the material and object information OBJECTINFO = int("0x3D3D",16); #This gives the version of the mesh and is found right before the material and object information
VERSION = long("0x0002",16); #This gives the version of the .3ds file VERSION = int("0x0002",16); #This gives the version of the .3ds file
KFDATA = long("0xB000",16); #This is the header for all of the key frame info KFDATA = int("0xB000",16); #This is the header for all of the key frame info
#------ sub defines of OBJECTINFO #------ sub defines of OBJECTINFO
MATERIAL=45055 #0xAFFF // This stored the texture info MATERIAL=45055 #0xAFFF // This stored the texture info
OBJECT=16384 #0x4000 // This stores the faces, vertices, etc... OBJECT=16384 #0x4000 // This stores the faces, vertices, etc...
#>------ sub defines of MATERIAL #>------ sub defines of MATERIAL
MATNAME = long("0xA000",16); # This holds the material name MATNAME = int("0xA000",16); # This holds the material name
MATAMBIENT = long("0xA010",16); # Ambient color of the object/material MATAMBIENT = int("0xA010",16); # Ambient color of the object/material
MATDIFFUSE = long("0xA020",16); # This holds the color of the object/material MATDIFFUSE = int("0xA020",16); # This holds the color of the object/material
MATSPECULAR = long("0xA030",16); # SPecular color of the object/material MATSPECULAR = int("0xA030",16); # SPecular color of the object/material
MATSHINESS = long("0xA040",16); # ?? MATSHINESS = int("0xA040",16); # ??
MATMAP = long("0xA200",16); # This is a header for a new material MATMAP = int("0xA200",16); # This is a header for a new material
MATMAPFILE = long("0xA300",16); # This holds the file name of the texture MATMAPFILE = int("0xA300",16); # This holds the file name of the texture
RGB1= long("0x0011",16) RGB1= int("0x0011",16)
RGB2= long("0x0012",16) RGB2= int("0x0012",16)
#>------ sub defines of OBJECT #>------ sub defines of OBJECT
OBJECT_MESH = long("0x4100",16); # This lets us know that we are reading a new object OBJECT_MESH = int("0x4100",16); # This lets us know that we are reading a new object
OBJECT_LIGHT = long("0x4600",16); # This lets un know we are reading a light object OBJECT_LIGHT = int("0x4600",16); # This lets un know we are reading a light object
OBJECT_CAMERA= long("0x4700",16); # This lets un know we are reading a camera object OBJECT_CAMERA= int("0x4700",16); # This lets un know we are reading a camera object
#>------ sub defines of CAMERA #>------ sub defines of CAMERA
OBJECT_CAM_RANGES= long("0x4720",16); # The camera range values OBJECT_CAM_RANGES= int("0x4720",16); # The camera range values
#>------ sub defines of OBJECT_MESH #>------ sub defines of OBJECT_MESH
OBJECT_VERTICES = long("0x4110",16); # The objects vertices OBJECT_VERTICES = int("0x4110",16); # The objects vertices
OBJECT_FACES = long("0x4120",16); # The objects faces OBJECT_FACES = int("0x4120",16); # The objects faces
OBJECT_MATERIAL = long("0x4130",16); # This is found if the object has a material, either texture map or color OBJECT_MATERIAL = int("0x4130",16); # This is found if the object has a material, either texture map or color
OBJECT_UV = long("0x4140",16); # The UV texture coordinates OBJECT_UV = int("0x4140",16); # The UV texture coordinates
OBJECT_TRANS_MATRIX = long("0x4160",16); # The Object Matrix OBJECT_TRANS_MATRIX = int("0x4160",16); # The Object Matrix
#>------ sub defines of KFDATA #>------ sub defines of KFDATA
KFDATA_KFHDR = long("0xB00A",16); KFDATA_KFHDR = int("0xB00A",16);
KFDATA_KFSEG = long("0xB008",16); KFDATA_KFSEG = int("0xB008",16);
KFDATA_KFCURTIME = long("0xB009",16); KFDATA_KFCURTIME = int("0xB009",16);
KFDATA_OBJECT_NODE_TAG = long("0xB002",16); KFDATA_OBJECT_NODE_TAG = int("0xB002",16);
#>------ sub defines of OBJECT_NODE_TAG #>------ sub defines of OBJECT_NODE_TAG
OBJECT_NODE_ID = long("0xB030",16); OBJECT_NODE_ID = int("0xB030",16);
OBJECT_NODE_HDR = long("0xB010",16); OBJECT_NODE_HDR = int("0xB010",16);
OBJECT_PIVOT = long("0xB013",16); OBJECT_PIVOT = int("0xB013",16);
OBJECT_INSTANCE_NAME = long("0xB011",16); OBJECT_INSTANCE_NAME = int("0xB011",16);
POS_TRACK_TAG = long("0xB020",16); POS_TRACK_TAG = int("0xB020",16);
ROT_TRACK_TAG = long("0xB021",16); ROT_TRACK_TAG = int("0xB021",16);
SCL_TRACK_TAG = long("0xB022",16); SCL_TRACK_TAG = int("0xB022",16);
def uv_key(uv): def uv_key(uv):
return round(uv.x, 6), round(uv.y, 6) return round(uv.x, 6), round(uv.y, 6)
@ -343,12 +346,12 @@ class _3ds_named_variable(object):
def dump(self,indent): def dump(self,indent):
if (self.value!=None): if (self.value!=None):
spaces="" spaces=""
for i in xrange(indent): for i in range(indent):
spaces+=" "; spaces+=" ";
if (self.name!=""): if (self.name!=""):
print spaces, self.name, " = ", self.value print(spaces, self.name, " = ", self.value)
else: else:
print spaces, "[unnamed]", " = ", self.value print(spaces, "[unnamed]", " = ", self.value)
#the chunk class #the chunk class
@ -408,9 +411,9 @@ class _3ds_chunk(object):
Dump is used for debugging purposes, to dump the contents of a chunk to the standard output. Dump is used for debugging purposes, to dump the contents of a chunk to the standard output.
Uses the dump function of the named variables and the subchunks to do the actual work.''' Uses the dump function of the named variables and the subchunks to do the actual work.'''
spaces="" spaces=""
for i in xrange(indent): for i in range(indent):
spaces+=" "; spaces+=" ";
print spaces, "ID=", hex(self.ID.value), "size=", self.get_size() print(spaces, "ID=", hex(self.ID.value), "size=", self.get_size())
for variable in self.variables: for variable in self.variables:
variable.dump(indent+1) variable.dump(indent+1)
for subchunk in self.subchunks: for subchunk in self.subchunks:
@ -555,11 +558,11 @@ def remove_face_uv(verts, tri_list):
# initialize a list of UniqueLists, one per vertex: # initialize a list of UniqueLists, one per vertex:
#uv_list = [UniqueList() for i in xrange(len(verts))] #uv_list = [UniqueList() for i in xrange(len(verts))]
unique_uvs= [{} for i in xrange(len(verts))] unique_uvs= [{} for i in range(len(verts))]
# for each face uv coordinate, add it to the UniqueList of the vertex # for each face uv coordinate, add it to the UniqueList of the vertex
for tri in tri_list: for tri in tri_list:
for i in xrange(3): for i in range(3):
# store the index into the UniqueList for future reference: # store the index into the UniqueList for future reference:
# offset.append(uv_list[tri.vertex_index[i]].add(_3ds_point_uv(tri.faceuvs[i]))) # offset.append(uv_list[tri.vertex_index[i]].add(_3ds_point_uv(tri.faceuvs[i])))
@ -589,7 +592,7 @@ def remove_face_uv(verts, tri_list):
pt = _3ds_point_3d(vert.co) # reuse, should be ok pt = _3ds_point_3d(vert.co) # reuse, should be ok
uvmap = [None] * len(unique_uvs[i]) uvmap = [None] * len(unique_uvs[i])
for ii, uv_3ds in unique_uvs[i].itervalues(): for ii, uv_3ds in unique_uvs[i].values():
# add a vertex duplicate to the vertex_array for every uv associated with this vertex: # add a vertex duplicate to the vertex_array for every uv associated with this vertex:
vert_array.add(pt) vert_array.add(pt)
# add the uv coordinate to the uv array: # add the uv coordinate to the uv array:
@ -607,7 +610,7 @@ def remove_face_uv(verts, tri_list):
# Make sure the triangle vertex indices now refer to the new vertex list: # Make sure the triangle vertex indices now refer to the new vertex list:
for tri in tri_list: for tri in tri_list:
for i in xrange(3): for i in range(3):
tri.offset[i]+=index_list[tri.vertex_index[i]] tri.offset[i]+=index_list[tri.vertex_index[i]]
tri.vertex_index= tri.offset tri.vertex_index= tri.offset
@ -655,7 +658,7 @@ def make_faces_chunk(tri_list, mesh, materialDict):
# obj_material_faces[tri.mat].add(_3ds_short(i)) # obj_material_faces[tri.mat].add(_3ds_short(i))
face_chunk.add_variable("faces", face_list) face_chunk.add_variable("faces", face_list)
for mat_name, mat_faces in unique_mats.itervalues(): for mat_name, mat_faces in unique_mats.values():
obj_material_chunk=_3ds_chunk(OBJECT_MATERIAL) obj_material_chunk=_3ds_chunk(OBJECT_MATERIAL)
obj_material_chunk.add_variable("name", mat_name) obj_material_chunk.add_variable("name", mat_name)
obj_material_chunk.add_variable("face_list", mat_faces) obj_material_chunk.add_variable("face_list", mat_faces)
@ -677,7 +680,7 @@ def make_faces_chunk(tri_list, mesh, materialDict):
obj_material_faces[tri.mat].add(_3ds_short(i)) obj_material_faces[tri.mat].add(_3ds_short(i))
face_chunk.add_variable("faces", face_list) face_chunk.add_variable("faces", face_list)
for i in xrange(n_materials): for i in range(n_materials):
obj_material_chunk=_3ds_chunk(OBJECT_MATERIAL) obj_material_chunk=_3ds_chunk(OBJECT_MATERIAL)
obj_material_chunk.add_variable("name", obj_material_names[i]) obj_material_chunk.add_variable("name", obj_material_names[i])
obj_material_chunk.add_variable("face_list", obj_material_faces[i]) obj_material_chunk.add_variable("face_list", obj_material_faces[i])
@ -862,7 +865,7 @@ def make_kf_obj_node(obj, name_to_id):
return kf_obj_node return kf_obj_node
""" """
import BPyMessages # import BPyMessages
def save_3ds(filename, context): def save_3ds(filename, context):
'''Save the Blender scene to a 3ds file.''' '''Save the Blender scene to a 3ds file.'''
# Time the export # Time the export
@ -871,16 +874,16 @@ def save_3ds(filename, context):
filename += '.3ds' filename += '.3ds'
# XXX # XXX
# if not BPyMessages.Warning_SaveOver(filename): # if not BPyMessages.Warning_SaveOver(filename):
# return # return
# XXX # XXX
time1 = bpy.sys.time() time1 = bpy.sys.time()
# time1= Blender.sys.time() # time1= Blender.sys.time()
# Blender.Window.WaitCursor(1) # Blender.Window.WaitCursor(1)
sce = context.scene sce = context.scene
# sce= bpy.data.scenes.active # sce= bpy.data.scenes.active
# Initialize the main chunk (primary): # Initialize the main chunk (primary):
primary = _3ds_chunk(PRIMARY) primary = _3ds_chunk(PRIMARY)
@ -948,7 +951,7 @@ def save_3ds(filename, context):
f.mat = 0 f.mat = 0
# Make material chunks for all materials used in the meshes: # Make material chunks for all materials used in the meshes:
for mat_and_image in materialDict.itervalues(): for mat_and_image in materialDict.values():
object_info.add_subchunk(make_material_chunk(mat_and_image[0], mat_and_image[1])) object_info.add_subchunk(make_material_chunk(mat_and_image[0], mat_and_image[1]))
# Give all objects a unique ID and build a dictionary from object name to object id: # Give all objects a unique ID and build a dictionary from object name to object id:
@ -1011,15 +1014,44 @@ def save_3ds(filename, context):
# Debugging only: report the exporting time: # Debugging only: report the exporting time:
Blender.Window.WaitCursor(0) Blender.Window.WaitCursor(0)
print "3ds export time: %.2f" % (Blender.sys.time() - time1) print("3ds export time: %.2f" % (Blender.sys.time() - time1))
# Debugging only: dump the chunk hierarchy: # Debugging only: dump the chunk hierarchy:
#primary.dump() #primary.dump()
if __name__=='__main__': # if __name__=='__main__':
if struct: # if struct:
Blender.Window.FileSelector(save_3ds, "Export 3DS", Blender.sys.makename(ext='.3ds')) # Blender.Window.FileSelector(save_3ds, "Export 3DS", Blender.sys.makename(ext='.3ds'))
else: # else:
Blender.Draw.PupMenu("Error%t|This script requires a full python installation") # Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
# save_3ds('/test_b.3ds') # # save_3ds('/test_b.3ds')
class EXPORT_OT_3ds(bpy.types.Operator):
'''
3DS Exporter
'''
__idname__ = "export.3ds"
__label__ = 'Export 3DS'
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
__props__ = [
bpy.props.StringProperty(attr="filename", name="File Name", description="File name used for exporting the 3DS file", maxlen= 1024, default= ""),
]
def execute(self, context):
raise Exception("Not doing anything yet.")
return ('FINISHED',)
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self.__operator__)
return ('RUNNING_MODAL',)
def poll(self, context): # Poll isnt working yet
print("Poll")
return context.active_object != None
bpy.ops.add(EXPORT_OT_3ds)

@ -913,7 +913,7 @@ class EXPORT_OT_obj(bpy.types.Operator):
# to the class instance from the operator settings before calling. # to the class instance from the operator settings before calling.
__props__ = [ __props__ = [
bpy.props.StringProperty(attr="filename", name="File Name", description="File name used for exporting the PLY file", maxlen= 1024, default= ""), bpy.props.StringProperty(attr="filename", name="File Name", description="File name used for exporting the OBJ file", maxlen= 1024, default= ""),
# context group # context group
bpy.props.BoolProperty(attr="use_selection", name="Selection Only", description="", default= False), bpy.props.BoolProperty(attr="use_selection", name="Selection Only", description="", default= False),

@ -53,22 +53,27 @@ Known issues:<br>
# Library dependancies # Library dependancies
#################################### ####################################
import Blender
from Blender import Object, Lamp, Draw, Image, Text, sys, Mesh
from Blender.Scene import Render
import math import math
import BPyObject
import BPyMesh import bpy
import Mathutils
# import Blender
# from Blender import Object, Lamp, Draw, Image, Text, sys, Mesh
# from Blender.Scene import Render
# import BPyObject
# import BPyMesh
# #
DEG2RAD=0.017453292519943295 DEG2RAD=0.017453292519943295
MATWORLD= Blender.Mathutils.RotationMatrix(-90, 4, 'x') MATWORLD= Mathutils.RotationMatrix(-90, 4, 'x')
#################################### ####################################
# Global Variables # Global Variables
#################################### ####################################
filename = Blender.Get('filename') filename = ""
# filename = Blender.Get('filename')
_safeOverwrite = True _safeOverwrite = True
extension = '' extension = ''
@ -109,7 +114,7 @@ class x3d_class:
import gzip import gzip
self.file = gzip.open(filename, "w") self.file = gzip.open(filename, "w")
except: except:
print "failed to import compression modules, exporting uncompressed" print("failed to import compression modules, exporting uncompressed")
self.filename = filename[:-1] # remove trailing z self.filename = filename[:-1] # remove trailing z
if self.file == None: if self.file == None:
@ -383,7 +388,7 @@ class x3d_class:
if nIFSCnt > 1: if nIFSCnt > 1:
self.writeIndented("<Group DEF=\"%s%s\">\n" % ("G_", meshName),1) self.writeIndented("<Group DEF=\"%s%s\">\n" % ("G_", meshName),1)
if sided.has_key('two') and sided['two'] > 0: if 'two' in sided and sided['two'] > 0:
bTwoSided=1 bTwoSided=1
else: else:
bTwoSided=0 bTwoSided=0
@ -414,8 +419,8 @@ class x3d_class:
if not matFlags & Blender.Material.Modes['TEXFACE']: if not matFlags & Blender.Material.Modes['TEXFACE']:
self.writeMaterial(mat, self.cleanStr(maters[0].name,''), world) self.writeMaterial(mat, self.cleanStr(maters[0].name,''), world)
if len(maters) > 1: if len(maters) > 1:
print "Warning: mesh named %s has multiple materials" % meshName print("Warning: mesh named %s has multiple materials" % meshName)
print "Warning: only one material per object handled" print("Warning: only one material per object handled")
#-- textures #-- textures
if mesh.faceUV: if mesh.faceUV:
@ -433,7 +438,7 @@ class x3d_class:
# user selected BOUNDS=1, SOLID=3, SHARED=4, or TEXTURE=5 # user selected BOUNDS=1, SOLID=3, SHARED=4, or TEXTURE=5
ifStyle="IndexedFaceSet" ifStyle="IndexedFaceSet"
# look up mesh name, use it if available # look up mesh name, use it if available
if self.meshNames.has_key(meshME): if meshME in self.meshNames:
self.writeIndented("<%s USE=\"ME_%s\">" % (ifStyle, meshME), 1) self.writeIndented("<%s USE=\"ME_%s\">" % (ifStyle, meshME), 1)
self.meshNames[meshME]+=1 self.meshNames[meshME]+=1
else: else:
@ -547,7 +552,7 @@ class x3d_class:
if self.writingtexture == 0: if self.writingtexture == 0:
self.file.write("\n\t\t\ttexCoordIndex=\"") self.file.write("\n\t\t\ttexCoordIndex=\"")
texIndxStr="" texIndxStr=""
for i in xrange(len(texIndexList)): for i in range(len(texIndexList)):
texIndxStr = texIndxStr + "%d, " % texIndexList[i] texIndxStr = texIndxStr + "%d, " % texIndexList[i]
if texIndexList[i]==-1: if texIndexList[i]==-1:
self.file.write(texIndxStr) self.file.write(texIndxStr)
@ -555,7 +560,7 @@ class x3d_class:
self.file.write("\"\n\t\t\t") self.file.write("\"\n\t\t\t")
else: else:
self.writeIndented("<TextureCoordinate point=\"", 1) self.writeIndented("<TextureCoordinate point=\"", 1)
for i in xrange(len(texCoordList)): for i in range(len(texCoordList)):
self.file.write("%s %s, " % (round(texCoordList[i][0],self.tp), round(texCoordList[i][1],self.tp))) self.file.write("%s %s, " % (round(texCoordList[i][0],self.tp), round(texCoordList[i][1],self.tp)))
self.file.write("\" />") self.file.write("\" />")
self.writeIndented("\n", -1) self.writeIndented("\n", -1)
@ -569,7 +574,7 @@ class x3d_class:
if face.col: if face.col:
c=face.col[0] c=face.col[0]
if self.verbose > 2: if self.verbose > 2:
print "Debug: face.col r=%d g=%d b=%d" % (c.r, c.g, c.b) print("Debug: face.col r=%d g=%d b=%d" % (c.r, c.g, c.b))
aColor = self.rgbToFS(c) aColor = self.rgbToFS(c)
self.file.write("%s, " % aColor) self.file.write("%s, " % aColor)
self.file.write("\" />") self.file.write("\" />")
@ -577,7 +582,7 @@ class x3d_class:
def writeMaterial(self, mat, matName, world): def writeMaterial(self, mat, matName, world):
# look up material name, use it if available # look up material name, use it if available
if self.matNames.has_key(matName): if matName in self.matNames:
self.writeIndented("<Material USE=\"MA_%s\" />\n" % matName) self.writeIndented("<Material USE=\"MA_%s\" />\n" % matName)
self.matNames[matName]+=1 self.matNames[matName]+=1
return; return;
@ -617,7 +622,7 @@ class x3d_class:
def writeImageTexture(self, image): def writeImageTexture(self, image):
name = image.name name = image.name
filename = image.filename.split('/')[-1].split('\\')[-1] filename = image.filename.split('/')[-1].split('\\')[-1]
if self.texNames.has_key(name): if name in self.texNames:
self.writeIndented("<ImageTexture USE=\"%s\" />\n" % self.cleanStr(name)) self.writeIndented("<ImageTexture USE=\"%s\" />\n" % self.cleanStr(name))
self.texNames[name] += 1 self.texNames[name] += 1
return return
@ -671,7 +676,7 @@ class x3d_class:
self.file.write("groundColor=\"%s %s %s\" " % (round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp))) self.file.write("groundColor=\"%s %s %s\" " % (round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp)))
self.file.write("skyColor=\"%s %s %s\" " % (round(sky0,self.cp), round(sky1,self.cp), round(sky2,self.cp))) self.file.write("skyColor=\"%s %s %s\" " % (round(sky0,self.cp), round(sky1,self.cp), round(sky2,self.cp)))
alltexture = len(alltextures) alltexture = len(alltextures)
for i in xrange(alltexture): for i in range(alltexture):
namemat = alltextures[i].name namemat = alltextures[i].name
pic = alltextures[i].getImage() pic = alltextures[i].getImage()
if (namemat == "back") and (pic != None): if (namemat == "back") and (pic != None):
@ -697,7 +702,7 @@ class x3d_class:
EXPORT_TRI= False,\ EXPORT_TRI= False,\
): ):
print "Info: starting X3D export to " + self.filename + "..." print("Info: starting X3D export to " + self.filename + "...")
self.writeHeader() self.writeHeader()
# self.writeScript() # self.writeScript()
self.writeNavigationInfo(scene) self.writeNavigationInfo(scene)
@ -771,7 +776,7 @@ class x3d_class:
self.texNames={} self.texNames={}
self.matNames={} self.matNames={}
self.indentLevel=0 self.indentLevel=0
print "Info: finished X3D export to %s\n" % self.filename print("Info: finished X3D export to %s\n" % self.filename)
def cleanStr(self, name, prefix='rsvd_'): def cleanStr(self, name, prefix='rsvd_'):
"""cleanStr(name,prefix) - try to create a valid VRML DEF name from object name""" """cleanStr(name,prefix) - try to create a valid VRML DEF name from object name"""
@ -815,7 +820,7 @@ class x3d_class:
else: else:
sidename='one' sidename='one'
if sided.has_key(sidename): if sidename in sided:
sided[sidename]+=1 sided[sidename]+=1
else: else:
sided[sidename]=1 sided[sidename]=1
@ -829,30 +834,30 @@ class x3d_class:
imageMap[faceName]=[face.image.name,sidename,face] imageMap[faceName]=[face.image.name,sidename,face]
if self.verbose > 2: if self.verbose > 2:
for faceName in imageMap.iterkeys(): for faceName in imageMap.keys():
ifs=imageMap[faceName] ifs=imageMap[faceName]
print "Debug: faceName=%s image=%s, solid=%s facecnt=%d" % \ print("Debug: faceName=%s image=%s, solid=%s facecnt=%d" % \
(faceName, ifs[0], ifs[1], len(ifs)-2) (faceName, ifs[0], ifs[1], len(ifs)-2))
return len(imageMap) return len(imageMap)
def faceToString(self,face): def faceToString(self,face):
print "Debug: face.flag=0x%x (bitflags)" % face.flag print("Debug: face.flag=0x%x (bitflags)" % face.flag)
if face.sel: if face.sel:
print "Debug: face.sel=true" print("Debug: face.sel=true")
print "Debug: face.mode=0x%x (bitflags)" % face.mode print("Debug: face.mode=0x%x (bitflags)" % face.mode)
if face.mode & Mesh.FaceModes.TWOSIDE: if face.mode & Mesh.FaceModes.TWOSIDE:
print "Debug: face.mode twosided" print("Debug: face.mode twosided")
print "Debug: face.transp=0x%x (enum)" % face.transp print("Debug: face.transp=0x%x (enum)" % face.transp)
if face.transp == Mesh.FaceTranspModes.SOLID: if face.transp == Mesh.FaceTranspModes.SOLID:
print "Debug: face.transp.SOLID" print("Debug: face.transp.SOLID")
if face.image: if face.image:
print "Debug: face.image=%s" % face.image.name print("Debug: face.image=%s" % face.image.name)
print "Debug: face.materialIndex=%d" % face.materialIndex print("Debug: face.materialIndex=%d" % face.materialIndex)
def getVertexColorByIndx(self, mesh, indx): def getVertexColorByIndx(self, mesh, indx):
c = None c = None
@ -867,12 +872,12 @@ class x3d_class:
return c return c
def meshToString(self,mesh): def meshToString(self,mesh):
print "Debug: mesh.hasVertexUV=%d" % mesh.vertexColors print("Debug: mesh.hasVertexUV=%d" % mesh.vertexColors)
print "Debug: mesh.faceUV=%d" % mesh.faceUV print("Debug: mesh.faceUV=%d" % mesh.faceUV)
print "Debug: mesh.hasVertexColours=%d" % mesh.hasVertexColours() print("Debug: mesh.hasVertexColours=%d" % mesh.hasVertexColours())
print "Debug: mesh.verts=%d" % len(mesh.verts) print("Debug: mesh.verts=%d" % len(mesh.verts))
print "Debug: mesh.faces=%d" % len(mesh.faces) print("Debug: mesh.faces=%d" % len(mesh.faces))
print "Debug: mesh.materials=%d" % len(mesh.materials) print("Debug: mesh.materials=%d" % len(mesh.materials))
def rgbToFS(self, c): def rgbToFS(self, c):
s="%s %s %s" % ( s="%s %s %s" % (
@ -924,7 +929,7 @@ class x3d_class:
self.indentLevel = self.indentLevel + inc self.indentLevel = self.indentLevel + inc
spaces="" spaces=""
for x in xrange(self.indentLevel): for x in range(self.indentLevel):
spaces = spaces + "\t" spaces = spaces + "\t"
self.file.write(spaces + s) self.file.write(spaces + s)
@ -1045,7 +1050,34 @@ def x3d_export_ui(filename):
######################################################### #########################################################
if __name__ == '__main__': # if __name__ == '__main__':
Blender.Window.FileSelector(x3d_export_ui,"Export X3D", Blender.Get('filename').replace('.blend', '.x3d')) # Blender.Window.FileSelector(x3d_export_ui,"Export X3D", Blender.Get('filename').replace('.blend', '.x3d'))
class EXPORT_OT_x3d(bpy.types.Operator):
'''
X3D Exporter
'''
__idname__ = "export.x3d"
__label__ = 'Export X3D'
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
__props__ = [
bpy.props.StringProperty(attr="filename", name="File Name", description="File name used for exporting the X3D file", maxlen= 1024, default= ""),
]
def execute(self, context):
raise Exception("Not doing anything yet.")
return ('FINISHED',)
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self.__operator__)
return ('RUNNING_MODAL',)
def poll(self, context): # Poll isnt working yet
print("Poll")
return context.active_object != None
bpy.ops.add(EXPORT_OT_x3d)

@ -125,26 +125,29 @@ Loader is based on 3ds loader from www.gametutorials.com (Thanks DigiBen).
# Importing modules # Importing modules
import Blender from struct import calcsize, unpack
import bpy import bpy
from Blender import Mesh, Object, Material, Image, Texture, Lamp, Mathutils
from Blender.Mathutils import Vector
import BPyImage
import BPyMessages # import Blender
# from Blender import Mesh, Object, Material, Image, Texture, Lamp, Mathutils
# from Blender.Mathutils import Vector
# import BPyImage
try: # import BPyMessages
from struct import calcsize, unpack
except: # try:
calcsize= unpack= None # from struct import calcsize, unpack
# except:
# calcsize= unpack= None
# If python version is less than 2.4, try to get set stuff from module # # If python version is less than 2.4, try to get set stuff from module
try: # try:
set # set
except: # except:
from sets import Set as set # from sets import Set as set
BOUNDS_3DS= [] BOUNDS_3DS= []
@ -167,12 +170,12 @@ def createBlenderTexture(material, name, image):
#Some of the chunks that we will see #Some of the chunks that we will see
#----- Primary Chunk, at the beginning of each file #----- Primary Chunk, at the beginning of each file
PRIMARY= long('0x4D4D',16) PRIMARY= int('0x4D4D',16)
#------ Main Chunks #------ Main Chunks
OBJECTINFO = long('0x3D3D',16); #This gives the version of the mesh and is found right before the material and object information OBJECTINFO = int('0x3D3D',16); #This gives the version of the mesh and is found right before the material and object information
VERSION = long('0x0002',16); #This gives the version of the .3ds file VERSION = int('0x0002',16); #This gives the version of the .3ds file
EDITKEYFRAME= long('0xB000',16); #This is the header for all of the key frame info EDITKEYFRAME= int('0xB000',16); #This is the header for all of the key frame info
#------ sub defines of OBJECTINFO #------ sub defines of OBJECTINFO
MATERIAL=45055 #0xAFFF // This stored the texture info MATERIAL=45055 #0xAFFF // This stored the texture info
@ -180,62 +183,62 @@ OBJECT=16384 #0x4000 // This stores the faces, vertices, etc...
#>------ sub defines of MATERIAL #>------ sub defines of MATERIAL
#------ sub defines of MATERIAL_BLOCK #------ sub defines of MATERIAL_BLOCK
MAT_NAME = long('0xA000',16) # This holds the material name MAT_NAME = int('0xA000',16) # This holds the material name
MAT_AMBIENT = long('0xA010',16) # Ambient color of the object/material MAT_AMBIENT = int('0xA010',16) # Ambient color of the object/material
MAT_DIFFUSE = long('0xA020',16) # This holds the color of the object/material MAT_DIFFUSE = int('0xA020',16) # This holds the color of the object/material
MAT_SPECULAR = long('0xA030',16) # SPecular color of the object/material MAT_SPECULAR = int('0xA030',16) # SPecular color of the object/material
MAT_SHINESS = long('0xA040',16) # ?? MAT_SHINESS = int('0xA040',16) # ??
MAT_TRANSPARENCY= long('0xA050',16) # Transparency value of material MAT_TRANSPARENCY= int('0xA050',16) # Transparency value of material
MAT_SELF_ILLUM = long('0xA080',16) # Self Illumination value of material MAT_SELF_ILLUM = int('0xA080',16) # Self Illumination value of material
MAT_WIRE = long('0xA085',16) # Only render's wireframe MAT_WIRE = int('0xA085',16) # Only render's wireframe
MAT_TEXTURE_MAP = long('0xA200',16) # This is a header for a new texture map MAT_TEXTURE_MAP = int('0xA200',16) # This is a header for a new texture map
MAT_SPECULAR_MAP= long('0xA204',16) # This is a header for a new specular map MAT_SPECULAR_MAP= int('0xA204',16) # This is a header for a new specular map
MAT_OPACITY_MAP = long('0xA210',16) # This is a header for a new opacity map MAT_OPACITY_MAP = int('0xA210',16) # This is a header for a new opacity map
MAT_REFLECTION_MAP= long('0xA220',16) # This is a header for a new reflection map MAT_REFLECTION_MAP= int('0xA220',16) # This is a header for a new reflection map
MAT_BUMP_MAP = long('0xA230',16) # This is a header for a new bump map MAT_BUMP_MAP = int('0xA230',16) # This is a header for a new bump map
MAT_MAP_FILENAME = long('0xA300',16) # This holds the file name of the texture MAT_MAP_FILENAME = int('0xA300',16) # This holds the file name of the texture
MAT_FLOAT_COLOR = long ('0x0010', 16) #color defined as 3 floats MAT_FLOAT_COLOR = int ('0x0010', 16) #color defined as 3 floats
MAT_24BIT_COLOR = long ('0x0011', 16) #color defined as 3 bytes MAT_24BIT_COLOR = int ('0x0011', 16) #color defined as 3 bytes
#>------ sub defines of OBJECT #>------ sub defines of OBJECT
OBJECT_MESH = long('0x4100',16); # This lets us know that we are reading a new object OBJECT_MESH = int('0x4100',16); # This lets us know that we are reading a new object
OBJECT_LAMP = long('0x4600',16); # This lets un know we are reading a light object OBJECT_LAMP = int('0x4600',16); # This lets un know we are reading a light object
OBJECT_LAMP_SPOT = long('0x4610',16); # The light is a spotloght. OBJECT_LAMP_SPOT = int('0x4610',16); # The light is a spotloght.
OBJECT_LAMP_OFF = long('0x4620',16); # The light off. OBJECT_LAMP_OFF = int('0x4620',16); # The light off.
OBJECT_LAMP_ATTENUATE = long('0x4625',16); OBJECT_LAMP_ATTENUATE = int('0x4625',16);
OBJECT_LAMP_RAYSHADE = long('0x4627',16); OBJECT_LAMP_RAYSHADE = int('0x4627',16);
OBJECT_LAMP_SHADOWED = long('0x4630',16); OBJECT_LAMP_SHADOWED = int('0x4630',16);
OBJECT_LAMP_LOCAL_SHADOW = long('0x4640',16); OBJECT_LAMP_LOCAL_SHADOW = int('0x4640',16);
OBJECT_LAMP_LOCAL_SHADOW2 = long('0x4641',16); OBJECT_LAMP_LOCAL_SHADOW2 = int('0x4641',16);
OBJECT_LAMP_SEE_CONE = long('0x4650',16); OBJECT_LAMP_SEE_CONE = int('0x4650',16);
OBJECT_LAMP_SPOT_RECTANGULAR= long('0x4651',16); OBJECT_LAMP_SPOT_RECTANGULAR= int('0x4651',16);
OBJECT_LAMP_SPOT_OVERSHOOT= long('0x4652',16); OBJECT_LAMP_SPOT_OVERSHOOT= int('0x4652',16);
OBJECT_LAMP_SPOT_PROJECTOR= long('0x4653',16); OBJECT_LAMP_SPOT_PROJECTOR= int('0x4653',16);
OBJECT_LAMP_EXCLUDE= long('0x4654',16); OBJECT_LAMP_EXCLUDE= int('0x4654',16);
OBJECT_LAMP_RANGE= long('0x4655',16); OBJECT_LAMP_RANGE= int('0x4655',16);
OBJECT_LAMP_ROLL= long('0x4656',16); OBJECT_LAMP_ROLL= int('0x4656',16);
OBJECT_LAMP_SPOT_ASPECT= long('0x4657',16); OBJECT_LAMP_SPOT_ASPECT= int('0x4657',16);
OBJECT_LAMP_RAY_BIAS= long('0x4658',16); OBJECT_LAMP_RAY_BIAS= int('0x4658',16);
OBJECT_LAMP_INNER_RANGE= long('0x4659',16); OBJECT_LAMP_INNER_RANGE= int('0x4659',16);
OBJECT_LAMP_OUTER_RANGE= long('0x465A',16); OBJECT_LAMP_OUTER_RANGE= int('0x465A',16);
OBJECT_LAMP_MULTIPLIER = long('0x465B',16); OBJECT_LAMP_MULTIPLIER = int('0x465B',16);
OBJECT_LAMP_AMBIENT_LIGHT = long('0x4680',16); OBJECT_LAMP_AMBIENT_LIGHT = int('0x4680',16);
OBJECT_CAMERA= long('0x4700',16); # This lets un know we are reading a camera object OBJECT_CAMERA= int('0x4700',16); # This lets un know we are reading a camera object
#>------ sub defines of CAMERA #>------ sub defines of CAMERA
OBJECT_CAM_RANGES= long('0x4720',16); # The camera range values OBJECT_CAM_RANGES= int('0x4720',16); # The camera range values
#>------ sub defines of OBJECT_MESH #>------ sub defines of OBJECT_MESH
OBJECT_VERTICES = long('0x4110',16); # The objects vertices OBJECT_VERTICES = int('0x4110',16); # The objects vertices
OBJECT_FACES = long('0x4120',16); # The objects faces OBJECT_FACES = int('0x4120',16); # The objects faces
OBJECT_MATERIAL = long('0x4130',16); # This is found if the object has a material, either texture map or color OBJECT_MATERIAL = int('0x4130',16); # This is found if the object has a material, either texture map or color
OBJECT_UV = long('0x4140',16); # The UV texture coordinates OBJECT_UV = int('0x4140',16); # The UV texture coordinates
OBJECT_TRANS_MATRIX = long('0x4160',16); # The Object Matrix OBJECT_TRANS_MATRIX = int('0x4160',16); # The Object Matrix
global scn global scn
scn= None scn= None
@ -255,10 +258,10 @@ class chunk:
self.bytes_read=0 self.bytes_read=0
def dump(self): def dump(self):
print 'ID: ', self.ID print('ID: ', self.ID)
print 'ID in hex: ', hex(self.ID) print('ID in hex: ', hex(self.ID))
print 'length: ', self.length print('length: ', self.length)
print 'bytes_read: ', self.bytes_read print('bytes_read: ', self.bytes_read)
def read_chunk(file, chunk): def read_chunk(file, chunk):
temp_data=file.read(calcsize(chunk.binary_format)) temp_data=file.read(calcsize(chunk.binary_format))
@ -309,13 +312,13 @@ def add_texture_to_material(image, texture, material, mapto):
elif mapto=='BUMP': elif mapto=='BUMP':
map=Texture.MapTo.NOR map=Texture.MapTo.NOR
else: else:
print '/tError: Cannot map to "%s"\n\tassuming diffuse color. modify material "%s" later.' % (mapto, material.name) print('/tError: Cannot map to "%s"\n\tassuming diffuse color. modify material "%s" later.' % (mapto, material.name))
map=Texture.MapTo.COL map=Texture.MapTo.COL
if image: texture.setImage(image) # double check its an image. if image: texture.setImage(image) # double check its an image.
free_tex_slots= [i for i, tex in enumerate( material.getTextures() ) if tex==None] free_tex_slots= [i for i, tex in enumerate( material.getTextures() ) if tex==None]
if not free_tex_slots: if not free_tex_slots:
print '/tError: Cannot add "%s" map. 10 Texture slots alredy used.' % mapto print('/tError: Cannot add "%s" map. 10 Texture slots alredy used.' % mapto)
else: else:
material.setTexture(free_tex_slots[0],texture,Texture.TexCo.UV,map) material.setTexture(free_tex_slots[0],texture,Texture.TexCo.UV,map)
@ -374,7 +377,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
myVertMapping = {} myVertMapping = {}
vertMappingIndex = 0 vertMappingIndex = 0
vertsToUse = [i for i in xrange(len(myContextMesh_vertls)) if faceVertUsers[i]] vertsToUse = [i for i in range(len(myContextMesh_vertls)) if faceVertUsers[i]]
myVertMapping = dict( [ (ii, i) for i, ii in enumerate(vertsToUse) ] ) myVertMapping = dict( [ (ii, i) for i, ii in enumerate(vertsToUse) ] )
tempName= '%s_%s' % (contextObName, matName) # matName may be None. tempName= '%s_%s' % (contextObName, matName) # matName may be None.
@ -423,7 +426,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
importedObjects.append(ob) importedObjects.append(ob)
bmesh.calcNormals() bmesh.calcNormals()
for matName, faces in myContextMeshMaterials.iteritems(): for matName, faces in myContextMeshMaterials.items():
makeMeshMaterialCopy(matName, faces) makeMeshMaterialCopy(matName, faces)
if len(materialFaces)!=len(myContextMesh_facels): if len(materialFaces)!=len(myContextMesh_facels):
@ -455,7 +458,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
new_chunk.bytes_read+= 4 #read the 4 bytes for the version number new_chunk.bytes_read+= 4 #read the 4 bytes for the version number
#this loader works with version 3 and below, but may not with 4 and above #this loader works with version 3 and below, but may not with 4 and above
if (version>3): if (version>3):
print '\tNon-Fatal Error: Version greater than 3, may not load correctly: ', version print('\tNon-Fatal Error: Version greater than 3, may not load correctly: ', version)
#is it an object info chunk? #is it an object info chunk?
elif (new_chunk.ID==OBJECTINFO): elif (new_chunk.ID==OBJECTINFO):
@ -684,7 +687,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
return temp_data return temp_data
#contextMesh.verts.extend( [Vector(),] ) # DUMMYVERT! - remove when blenders internals are fixed. #contextMesh.verts.extend( [Vector(),] ) # DUMMYVERT! - remove when blenders internals are fixed.
contextMesh_vertls= [getvert() for i in xrange(num_verts)] contextMesh_vertls= [getvert() for i in range(num_verts)]
#print 'object verts: bytes read: ', new_chunk.bytes_read #print 'object verts: bytes read: ', new_chunk.bytes_read
@ -702,7 +705,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
v1,v2,v3,dummy= unpack('<4H', temp_data) v1,v2,v3,dummy= unpack('<4H', temp_data)
return v1, v2, v3 return v1, v2, v3
contextMesh_facels= [ getface() for i in xrange(num_faces) ] contextMesh_facels= [ getface() for i in range(num_faces) ]
elif (new_chunk.ID==OBJECT_MATERIAL): elif (new_chunk.ID==OBJECT_MATERIAL):
@ -719,7 +722,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
new_chunk.bytes_read+= STRUCT_SIZE_UNSIGNED_SHORT new_chunk.bytes_read+= STRUCT_SIZE_UNSIGNED_SHORT
return unpack('<H', temp_data)[0] return unpack('<H', temp_data)[0]
contextMeshMaterials[material_name]= [ getmat() for i in xrange(num_faces_using_mat) ] contextMeshMaterials[material_name]= [ getmat() for i in range(num_faces_using_mat) ]
#look up the material in all the materials #look up the material in all the materials
@ -733,7 +736,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
new_chunk.bytes_read += STRUCT_SIZE_2FLOAT #2 float x 4 bytes each new_chunk.bytes_read += STRUCT_SIZE_2FLOAT #2 float x 4 bytes each
return Vector( unpack('<2f', temp_data) ) return Vector( unpack('<2f', temp_data) )
contextMeshUV= [ getuv() for i in xrange(num_uv) ] contextMeshUV= [ getuv() for i in range(num_uv) ]
elif (new_chunk.ID== OBJECT_TRANS_MATRIX): elif (new_chunk.ID== OBJECT_TRANS_MATRIX):
# How do we know the matrix size? 54 == 4x4 48 == 4x3 # How do we know the matrix size? 54 == 4x4 48 == 4x3
@ -825,7 +828,7 @@ def load_3ds(filename, PREF_UI= True):
if BPyMessages.Error_NoFile(filename): if BPyMessages.Error_NoFile(filename):
return return
print '\n\nImporting 3DS: "%s"' % (Blender.sys.expandpath(filename)) print('\n\nImporting 3DS: "%s"' % (Blender.sys.expandpath(filename)))
time1= Blender.sys.time() time1= Blender.sys.time()
@ -838,7 +841,7 @@ def load_3ds(filename, PREF_UI= True):
# print 'reading the first chunk' # print 'reading the first chunk'
read_chunk(file, current_chunk) read_chunk(file, current_chunk)
if (current_chunk.ID!=PRIMARY): if (current_chunk.ID!=PRIMARY):
print '\tFatal Error: Not a valid 3ds file: ', filename print('\tFatal Error: Not a valid 3ds file: ', filename)
file.close() file.close()
return return
@ -953,17 +956,17 @@ def load_3ds(filename, PREF_UI= True):
# Done constraining to bounds. # Done constraining to bounds.
# Select all new objects. # Select all new objects.
print 'finished importing: "%s" in %.4f sec.' % (filename, (Blender.sys.time()-time1)) print('finished importing: "%s" in %.4f sec.' % (filename, (Blender.sys.time()-time1)))
file.close() file.close()
Blender.Window.WaitCursor(0) Blender.Window.WaitCursor(0)
DEBUG= False DEBUG= False
if __name__=='__main__' and not DEBUG: # if __name__=='__main__' and not DEBUG:
if calcsize==None: # if calcsize==None:
Blender.Draw.PupMenu('Error%t|a full python installation not found') # Blender.Draw.PupMenu('Error%t|a full python installation not found')
else: # else:
Blender.Window.FileSelector(load_3ds, 'Import 3DS', '*.3ds') # Blender.Window.FileSelector(load_3ds, 'Import 3DS', '*.3ds')
# For testing compatibility # For testing compatibility
#load_3ds('/metavr/convert/vehicle/truck_002/TruckTanker1.3DS', False) #load_3ds('/metavr/convert/vehicle/truck_002/TruckTanker1.3DS', False)
@ -1005,3 +1008,32 @@ else:
print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME) print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME)
''' '''
class IMPORT_OT_3ds(bpy.types.Operator):
'''
3DS Importer
'''
__idname__ = "import.3ds"
__label__ = 'Import 3DS'
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
__props__ = [
bpy.props.StringProperty(attr="filename", name="File Name", description="File name used for importing the 3DS file", maxlen= 1024, default= ""),
]
def execute(self, context):
raise Exception("Not doing anything yet.")
return ('FINISHED',)
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self.__operator__)
return ('RUNNING_MODAL',)
def poll(self, context): # Poll isnt working yet
print("Poll")
return context.active_object != None
bpy.ops.add(IMPORT_OT_3ds)

@ -74,6 +74,7 @@ class INFO_MT_file_import(bpy.types.Menu):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
layout.itemO("import.3ds", text="3DS")
layout.itemO("import.obj", text="OBJ") layout.itemO("import.obj", text="OBJ")
class INFO_MT_file_export(bpy.types.Menu): class INFO_MT_file_export(bpy.types.Menu):
@ -83,9 +84,11 @@ class INFO_MT_file_export(bpy.types.Menu):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
layout.itemO("export.3ds", text="3DS")
layout.itemO("export.fbx", text="FBX") layout.itemO("export.fbx", text="FBX")
layout.itemO("export.obj", text="OBJ") layout.itemO("export.obj", text="OBJ")
layout.itemO("export.ply", text="PLY") layout.itemO("export.ply", text="PLY")
layout.itemO("export.x3d", text="X3D")
class INFO_MT_file_external_data(bpy.types.Menu): class INFO_MT_file_external_data(bpy.types.Menu):
__space_type__ = "USER_PREFERENCES" __space_type__ = "USER_PREFERENCES"