Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillian Padovani Germano <wpgermano@gmail.com>2005-12-19 20:21:55 +0300
committerWillian Padovani Germano <wpgermano@gmail.com>2005-12-19 20:21:55 +0300
commitad579abf00bd1cd11082bd362513a28c14b8287f (patch)
tree96b76db45fab1e0aaabc5966385c916bf26d5e89 /release/scripts/3ds_import.py
parentf9b2a189fa4312f3d2c7306232a406f445329a73 (diff)
Scripts:
Final (?) updates for 2.40 :) : - Bob Holcomb sent a better version of his 3ds importer - Added doc info to bvh2arm: links to doc and mocap tute from author Jean-Baptiste Perin - Alessandro Pirovano improved the Lightwave importer. - Mikael Lagre updated the collada scripts (fixed a bug with camera lens value) - Adam Saltsman improved the wings importer (ongoing work with his pal Toastie). - Anthony D'Agostino GPL'd his scripts (used Blender's BAL license previously) Thanks to all script authors for their work, interest and kindness. Again, Tom (LetterRip) has played an important part in this, thanks and welcome :).
Diffstat (limited to 'release/scripts/3ds_import.py')
-rw-r--r--release/scripts/3ds_import.py832
1 files changed, 473 insertions, 359 deletions
diff --git a/release/scripts/3ds_import.py b/release/scripts/3ds_import.py
index 6bd81c2606d..017ec74123f 100644
--- a/release/scripts/3ds_import.py
+++ b/release/scripts/3ds_import.py
@@ -4,21 +4,30 @@
Name: '3D Studio (.3ds)...'
Blender: 237
Group: 'Import'
-Tooltip: 'Import from 3DS file format (.3ds).'
+Tooltip: 'Import from 3DS file format. (.3ds)'
"""
__author__ = ["Bob Holcomb", "Richard Lärkäng", "Damien McGinnes", "Campbell Barton"]
__url__ = ("blender", "elysiun", "http://www.gametutorials.com")
-__version__ = "0.82"
+__version__ = "0.92"
__bpydoc__ = """\
3ds Importer
-This script imports a 3ds file and the materials into blender for editing.
+This script imports a 3ds file and the materials into Blender for editing.
-Loader is based on 3ds loader from www.gametutorials.com(Thanks DigiBen).
+Loader is based on 3ds loader from www.gametutorials.com (Thanks DigiBen).
+
+Changes:
+
+0.92<br>
+- Added support for diffuse, alpha, spec, bump maps in a single material
+
+0.9<br>
+- Reorganized code into object/material block functions<br>
+- Use of Matrix() to copy matrix data<br>
+- added support for material transparency<br>
-Changes:<br>
0.81a (fork- not 0.9) Campbell Barton 2005-06-08<br>
- Simplified import code<br>
- Never overwrite data<br>
@@ -27,7 +36,7 @@ Changes:<br>
0.81 Damien McGinnes 2005-01-09<br>
- handle missing images better<br>
-
+
0.8 Damien McGinnes 2005-01-08<br>
- copies sticky UV coords to face ones<br>
- handles images better<br>
@@ -35,9 +44,11 @@ Changes:<br>
"""
+# $Id$
+#
# ***** BEGIN GPL LICENSE BLOCK *****
#
-# Script copyright (C) Bob Holcomb
+# Script copyright (C) Bob Holcomb
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -56,88 +67,85 @@ Changes:<br>
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
+
# Importing modules
import Blender
-from Blender import NMesh, Scene, Object, Material, Image
+from Blender import NMesh, Scene, Object, Material, Image, Texture
import sys, struct, string
import os
-#this script imports uvcoords as sticky vertex coords
-#this parameter enables copying these to face uv coords
-#which shold be more useful.
-
+######################################################
+# Data Structures
+######################################################
+#----- Primary Chunk,
+PRIMARY = long("0x4D4D",16) # should be aat the beginning of each file
+VERSION = long("0x0002",16) #This gives the version of the .3ds file
+EDITOR_BLOCK = long("0x3D3D",16) #this is the Editor Data block, contains objects, materials
+KEYFRAME_BLOCK = long("0xB000",16) #This is the header for all of the key frame info
+
+#------ sub defines of EDITOR_BLOCK
+MATERIAL_BLOCK = long("0xAFFF",16) #This stores the Material info
+OBJECT_BLOCK = long("0x4000",16) #This stores the Object,Camera,Light
+
+#------ sub defines of OBJECT_BLOCK
+OBJECT_MESH = long("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_CAMERA = long("0x4700",16) # This lets un know we are reading a camera object
+
+#------ sub defines of OBJECT_MESH
+MESH_VERTICES = long("0x4110",16) # The objects vertices
+MESH_FACES = long("0x4120",16) # The objects faces
+MESH_MATERIAL = long("0x4130",16) # This is found if the object has a material, either texture map or color
+MESH_UV = long("0x4140",16) # The UV texture coordinates
+MESH_TRANS_MATRIX = long("0x4160",16) # The Object Matrix
+MESH_COLOR = long("0x4165",16) # The color of the object
+MESH_TEXTURE_INFO = long("0x470",16) # Info about the Object Texture
+
+#------ sub defines of OBJECT_CAMERA
+CAMERA_CONE = long("0x4710",16) # The camera see cone
+CAMERA_RANGES = long("0x4720",16) # The camera range values
+
+#------ sub defines of OBJECT_LIGHT
+LIGHT_SPOTLIGHT = long("0x4610",16) # A spotlight
+LIGHT_ATTENUATE = long("0x4625",16) # Light attenuation values
+
+
+#------ sub defines of MATERIAL_BLOCK
+MAT_NAME = long("0xA000",16) # This holds the material name
+MAT_AMBIENT = long("0xA010",16) # Ambient color of the object/material
+MAT_DIFFUSE = long("0xA020",16) # This holds the color of the object/material
+MAT_SPECULAR = long("0xA030",16) # SPecular color of the object/material
+MAT_SHINESS = long("0xA040",16) # ??
+MAT_TRANSPARENCY= long("0xA050",16) # Transparency value of material
+MAT_SELF_ILLUM = long("0xA080",16) # Self Illumination value of material
+MAT_WIRE = long("0xA085",16) # Only render's wireframe
+
+MAT_TEXTURE_MAP = long("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_OPACITY_MAP = long("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_BUMP_MAP = long("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
+#lots more to add here for maps
-#===========================================================================#
-# Returns unique name of object/mesh (stops overwriting existing meshes) #
-#===========================================================================#
-def getUniqueName(name):
- newName = name
- uniqueInt = 0
- while 1:
- try:
- ob = Object.Get(newName)
- # Okay, this is working, so lets make a new name
- newName = '%s.%d' % (name, uniqueInt)
- uniqueInt +=1
- except AttributeError:
- if newName not in NMesh.GetNames():
- return newName
- else:
- newName = '%s.%d' % (name, uniqueInt)
- uniqueInt +=1
+######################################################
+# Globals
+######################################################
+TEXTURE_DICT={}
+MATERIAL_DICT={}
######################################################
-# Data Structures
+# Chunk Class
######################################################
-
-#Some of the chunks that we will see
-#----- Primary Chunk, at the beginning of each file
-PRIMARY= long("0x4D4D",16)
-
-#------ Main Chunks
-OBJECTINFO = long("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
-EDITKEYFRAME= long("0xB000",16); #This is the header for all of the key frame info
-
-#------ sub defines of OBJECTINFO
-MATERIAL=45055 #0xAFFF // This stored the texture info
-OBJECT=16384 #0x4000 // This stores the faces, vertices, etc...
-
-#>------ sub defines of MATERIAL
-MATNAME = long("0xA000",16); # This holds the material name
-MATAMBIENT = long("0xA010",16); # Ambient color of the object/material
-MATDIFFUSE = long("0xA020",16); # This holds the color of the object/material
-MATSPECULAR = long("0xA030",16); # SPecular color of the object/material
-MATSHINESS = long("0xA040",16); # ??
-MATMAP = long("0xA200",16); # This is a header for a new material
-MATMAPFILE = long("0xA300",16); # This holds the file name of the texture
-
-#>------ sub defines of OBJECT
-OBJECT_MESH = long("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_CAMERA= long("0x4700",16); # This lets un know we are reading a camera object
-
-#>------ sub defines of CAMERA
-OBJECT_CAM_RANGES= long("0x4720",16); # The camera range values
-
-#>------ sub defines of OBJECT_MESH
-OBJECT_VERTICES = long("0x4110",16); # The objects vertices
-OBJECT_FACES = long("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_UV = long("0x4140",16); # The UV texture coordinates
-OBJECT_TRANS_MATRIX = long("0x4160",16); # The Object Matrix
-
-#the chunk class
class chunk:
ID=0
length=0
bytes_read=0
- #we don't read in the bytes_read, we compute that
binary_format="<HI"
def __init__(self):
@@ -146,378 +154,484 @@ class chunk:
self.bytes_read=0
def dump(self):
- print "ID: ", self.ID
print "ID in hex: ", hex(self.ID)
print "length: ", self.length
print "bytes_read: ", self.bytes_read
+######################################################
+# Helper functions
+######################################################
def read_chunk(file, chunk):
- temp_data=file.read(struct.calcsize(chunk.binary_format))
- data=struct.unpack(chunk.binary_format, temp_data)
- chunk.ID=data[0]
- chunk.length=data[1]
- #update the bytes read function
- chunk.bytes_read=6
-
- #if debugging
- #chunk.dump()
+ temp_data=file.read(struct.calcsize(chunk.binary_format))
+ data=struct.unpack(chunk.binary_format, temp_data)
+ chunk.ID=data[0]
+ chunk.length=data[1]
+ chunk.bytes_read=6
+
+def skip_to_end(file, skip_chunk):
+ buffer_size=skip_chunk.length-skip_chunk.bytes_read
+ binary_format=str(buffer_size)+"c"
+ temp_data=file.read(struct.calcsize(binary_format))
+ skip_chunk.bytes_read+=buffer_size
def read_string(file):
s=""
index=0
- #print "reading a string"
- #read in the characters till we get a null character
+ #read the first character
temp_data=file.read(1)
data=struct.unpack("c", temp_data)
s=s+(data[0])
- #print "string: ",s
+ #read in the characters till we get a null character
while(ord(s[index])!=0):
index+=1
temp_data=file.read(1)
data=struct.unpack("c", temp_data)
s=s+(data[0])
- #print "string: ",s
-
- #remove the null character from the string
- the_string=s[:-1]
+ the_string=s[:-1] #remove the null character from the string
return str(the_string)
-######################################################
-# IMPORT
-######################################################
-def process_next_object_chunk(file, previous_chunk):
- new_chunk=chunk()
- temp_chunk=chunk()
-
- while (previous_chunk.bytes_read<previous_chunk.length):
- #read the next chunk
- read_chunk(file, new_chunk)
-
+def getUniqueName(name):
+ newName = name
+ uniqueInt = 0
+ while 1:
+ try:
+ ob = Object.Get(newName)
+ # Okay, this is working, so lets make a new name
+ newName = '%s.%d' % (name, uniqueInt)
+ uniqueInt +=1
+ except AttributeError:
+ if newName not in NMesh.GetNames():
+ return newName
+ else:
+ newName = '%s.%d' % (name, uniqueInt)
+ uniqueInt +=1
-def process_next_chunk(file, previous_chunk, new_object_list):
- contextObName = None
- #contextLamp = None
- contextMaterial = None
- contextMatrix = Blender.Mathutils.Matrix(); contextMatrix.identity()
- contextMesh = None
-
- TEXDICT={}
- MATDICT={}
+def add_texture_to_material(image, texture, material, mapto):
+ if mapto=="DIFFUSE":
+ map=Texture.MapTo.COL
+ elif mapto=="SPECULAR":
+ map=Texture.MapTo.SPEC
+ elif mapto=="OPACITY":
+ map=Texture.MapTo.ALPHA
+ elif mapto=="BUMP":
+ map=Texture.MapTo.NOR
+ else:
+ print "/tError: Cannot map to ", mapto
+ return
- objectList = [] # Keep a list of imported objects.
+ texture.setImage(image)
+ texture_list=material.getTextures()
+ index=0
+ for tex in texture_list:
+ if tex==None:
+ material.setTexture(index,texture,Texture.TexCo.OBJECT,map)
+ return
+ else:
+ index+=1
+ if index>10:
+ print "/tError: Cannot add diffuse map. Too many textures"
+######################################################
+# Process an object (tri-mesh, Camera, or Light)
+######################################################
+def process_object_block(file, previous_chunk, object_list):
# Localspace variable names, faster.
- STRUCT_SIZE_1CHAR = struct.calcsize("c")
STRUCT_SIZE_2FLOAT = struct.calcsize("2f")
STRUCT_SIZE_3FLOAT = struct.calcsize("3f")
STRUCT_SIZE_UNSIGNED_SHORT = struct.calcsize("H")
STRUCT_SIZE_4UNSIGNED_SHORT = struct.calcsize("4H")
STRUCT_SIZE_4x3MAT = struct.calcsize("ffffffffffff")
+ #spare chunks
+ new_chunk=chunk()
+ temp_chunk=chunk()
- def putContextMesh(myContextMesh):
- INV_MAT = Blender.Mathutils.CopyMat(contextMatrix)
- INV_MAT.invert()
- contextMesh.transform(INV_MAT)
- objectList.append(NMesh.PutRaw(contextMesh))
- objectList[-1].name = contextObName
- objectList[-1].setMatrix(contextMatrix)
+ global TEXURE_DICT
+ global MATERIAL_DICT
+ #don't know which one we're making, so let's have a place for one of each
+ new_mesh=None
+ new_light=None
+ new_camera=None
+
+ #all objects have a name (first thing)
+ tempName = str(read_string(file))
+ obj_name = getUniqueName( tempName )
+ previous_chunk.bytes_read += (len(tempName)+1)
- #a spare chunk
- new_chunk=chunk()
- temp_chunk=chunk()
-
- #loop through all the data for this chunk (previous chunk) and see what it is
while (previous_chunk.bytes_read<previous_chunk.length):
- #read the next chunk
- #print "reading a chunk"
read_chunk(file, new_chunk)
+
+ if (new_chunk.ID==OBJECT_MESH):
+ new_mesh=Blender.NMesh.New(obj_name)
+ while (new_chunk.bytes_read<new_chunk.length):
+ read_chunk(file, temp_chunk)
+
+ if (temp_chunk.ID==MESH_VERTICES):
+ temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
+ data=struct.unpack("H", temp_data)
+ temp_chunk.bytes_read+=2
+ num_verts=data[0]
+ for counter in range (num_verts):
+ temp_data=file.read(STRUCT_SIZE_3FLOAT)
+ temp_chunk.bytes_read += STRUCT_SIZE_3FLOAT
+ data=struct.unpack("3f", temp_data)
+ v=NMesh.Vert(data[0],data[1],data[2])
+ new_mesh.verts.append(v)
+
+ elif (temp_chunk.ID==MESH_FACES):
+ temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
+ data=struct.unpack("H", temp_data)
+ temp_chunk.bytes_read+=2
+ num_faces=data[0]
+ for counter in range(num_faces):
+ temp_data=file.read(STRUCT_SIZE_4UNSIGNED_SHORT)
+ temp_chunk.bytes_read += STRUCT_SIZE_4UNSIGNED_SHORT #4 short ints x 2 bytes each
+ data=struct.unpack("4H", temp_data)
+ #insert the mesh info into the faces, don't worry about data[3] it is a 3D studio thing
+ f = NMesh.Face( [new_mesh.verts[data[i]] for i in xrange(3)] )
+ f.uv = [ tuple(new_mesh.verts[data[i]].uvco[:2]) for i in xrange(3) ]
+ new_mesh.faces.append(f)
+
+ elif (temp_chunk.ID==MESH_MATERIAL):
+ material_name=""
+ material_name=str(read_string(file))
+ temp_chunk.bytes_read += len(material_name)+1 # remove 1 null character.
+ material_found=0
+ for mat in Material.Get():
+ if(mat.name==material_name):
+ if len(new_mesh.materials) >= 15:
+ print "\tCant assign more than 16 materials per mesh, keep going..."
+ break
+ else:
+ meshHasMat = 0
+ for myMat in new_mesh.materials:
+ if myMat.name == mat.name:
+ meshHasMat = 1
+ if meshHasMat == 0:
+ new_mesh.addMaterial(mat)
+ material_found=1
+ #figure out what material index this is for the mesh
+ for mat_counter in range(len(new_mesh.materials)):
+ if new_mesh.materials[mat_counter].name == material_name:
+ mat_index=mat_counter
+ break # get out of this for loop so we don't accidentally set material_found back to 0
+ else:
+ material_found=0
+
+ if material_found == 1:
+ #read the number of faces using this material
+ temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
+ data=struct.unpack("H", temp_data)
+ temp_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT
+ num_faces_using_mat=data[0]
+ #list of faces using mat
+ for face_counter in range(num_faces_using_mat):
+ temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
+ temp_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT
+ data=struct.unpack("H", temp_data)
+ new_mesh.faces[data[0]].materialIndex = mat_index
+ try:
+ mname = MATERIAL_DICT[mat.name]
+ new_mesh.faces[data[0]].image = TEXTURE_DICT[mname]
+ except:
+ continue
+ else:
+ #read past the information about the material you couldn't find
+ skip_to_end(file,temp_chunk)
+
+ elif (new_chunk.ID == MESH_UV):
+ temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
+ data=struct.unpack("H", temp_data)
+ temp_chunk.bytes_read+=2
+ num_uv=data[0]
+
+ for counter in range(num_uv):
+ temp_data=file.read(STRUCT_SIZE_2FLOAT)
+ temp_chunk.bytes_read += STRUCT_SIZE_2FLOAT #2 float x 4 bytes each
+ data=struct.unpack("2f", temp_data)
+ #insert the insert the UV coords in the vertex data
+ new_mesh.verts[counter].uvco = data
+
+ elif (new_chunk.ID == MESH_TRANS_MATRIX):
+ temp_data=file.read(STRUCT_SIZE_4x3MAT)
+ data = list( struct.unpack("ffffffffffff", temp_data) )
+ temp_chunk.bytes_read += STRUCT_SIZE_4x3MAT
+ new_matrix = Blender.Mathutils.Matrix(\
+ data[:3] + [0],\
+ data[3:6] + [0],\
+ data[6:9] + [0],\
+ data[9:] + [1])
+ new_mesh.setMatrix(new_matrix)
+ else:
+ skip_to_end(file, temp_chunk)
+
+ new_chunk.bytes_read+=temp_chunk.bytes_read
+
+ elif (new_chunk.ID==OBJECT_LIGHT):
+ skip_to_end(file,new_chunk)
- #is it a Version chunk?
- if (new_chunk.ID==VERSION):
- #print "found a VERSION chunk"
- #read in the version of the file
- #it's an unsigned short (H)
- temp_data=file.read(struct.calcsize("I"))
- data=struct.unpack("I", temp_data)
- version=data[0]
- 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
- if (version>3):
- print "\tNon-Fatal Error: Version greater than 3, may not load correctly: ", version
-
- #is it an object info chunk?
- elif (new_chunk.ID==OBJECTINFO):
- # print "found an OBJECTINFO chunk"
- process_next_chunk(file, new_chunk, new_object_list)
+ elif (new_chunk.ID==OBJECT_CAMERA):
+ skip_to_end(file,new_chunk)
- #keep track of how much we read in the main chunk
- new_chunk.bytes_read+=temp_chunk.bytes_read
-
- #is it an object chunk?
- elif (new_chunk.ID==OBJECT):
- # print "found an OBJECT chunk"
- tempName = str(read_string(file))
- contextObName = getUniqueName( tempName )
- new_chunk.bytes_read += (len(tempName)+1)
+ else: #don't know what kind of object it is
+ skip_to_end(file,new_chunk)
- #is it a material chunk?
- elif (new_chunk.ID==MATERIAL):
- # print "found a MATERIAL chunk"
- contextMaterial = Material.New()
+ if new_mesh!=None:
+ object_list.append(NMesh.PutRaw(new_mesh))
+ if new_light!=None:
+ object_list.append(new_light)
+ if new_camera!=None:
+ object_list.append(new_camera)
- elif (new_chunk.ID==MATNAME):
- # print "Found a MATNAME chunk"
+ previous_chunk.bytes_read+=new_chunk.bytes_read
+
+######################################################
+# Process a Material
+######################################################
+def process_material_block(file, previous_chunk):
+ # Localspace variable names, faster.
+ STRUCT_SIZE_3BYTE = struct.calcsize("3B")
+ STRUCT_SIZE_UNSIGNED_SHORT = struct.calcsize("H")
+
+ #spare chunks
+ new_chunk=chunk()
+ temp_chunk=chunk()
+
+ global TEXURE_DICT
+ global MATERIAL_DICT
+
+ new_material=Blender.Material.New()
+
+ while (previous_chunk.bytes_read<previous_chunk.length):
+ #read the next chunk
+ read_chunk(file, new_chunk)
+
+ if (new_chunk.ID==MAT_NAME):
material_name=""
material_name=str(read_string(file))
-
- #plus one for the null character that ended the string
- new_chunk.bytes_read+=(len(material_name)+1)
-
- contextMaterial.setName(material_name)
- MATDICT[material_name] = contextMaterial.name
+ new_chunk.bytes_read+=(len(material_name)+1) #plus one for the null character that ended the string
+ new_material.setName(material_name)
+ MATERIAL_DICT[material_name] = new_material.name
- elif (new_chunk.ID==MATAMBIENT):
- # print "Found a MATAMBIENT chunk"
-
+ elif (new_chunk.ID==MAT_AMBIENT):
read_chunk(file, temp_chunk)
- temp_data=file.read(struct.calcsize("3B"))
+ temp_data=file.read(STRUCT_SIZE_3BYTE)
data=struct.unpack("3B", temp_data)
temp_chunk.bytes_read+=3
- contextMaterial.mirCol = [float(col)/255 for col in data] # data [0,1,2] == rgb
+ new_material.mirCol = [float(col)/255 for col in data] # data [0,1,2] == rgb
new_chunk.bytes_read+=temp_chunk.bytes_read
- elif (new_chunk.ID==MATDIFFUSE):
- # print "Found a MATDIFFUSE chunk"
-
+ elif (new_chunk.ID==MAT_DIFFUSE):
read_chunk(file, temp_chunk)
- temp_data=file.read(struct.calcsize("3B"))
+ temp_data=file.read(STRUCT_SIZE_3BYTE)
data=struct.unpack("3B", temp_data)
temp_chunk.bytes_read+=3
- contextMaterial.rgbCol = [float(col)/255 for col in data] # data [0,1,2] == rgb
+ new_material.rgbCol = [float(col)/255 for col in data] # data [0,1,2] == rgb
new_chunk.bytes_read+=temp_chunk.bytes_read
- elif (new_chunk.ID==MATSPECULAR):
- # print "Found a MATSPECULAR chunk"
-
+ elif (new_chunk.ID==MAT_SPECULAR):
read_chunk(file, temp_chunk)
- temp_data=file.read(struct.calcsize("3B"))
+ temp_data=file.read(STRUCT_SIZE_3BYTE)
data=struct.unpack("3B", temp_data)
temp_chunk.bytes_read+=3
-
- contextMaterial.specCol = [float(col)/255 for col in data] # data [0,1,2] == rgb
+ new_material.specCol = [float(col)/255 for col in data] # data [0,1,2] == rgb
new_chunk.bytes_read+=temp_chunk.bytes_read
- elif (new_chunk.ID==MATMAP):
- # print "Found a MATMAP chunk"
- pass # This chunk has no data
-
- elif (new_chunk.ID==MATMAPFILE):
- # print "Found a MATMAPFILE chunk"
- texture_name=""
- texture_name=str(read_string(file))
- try:
- img = Image.Load(texture_name)
- TEXDICT[contextMaterial.name]=img
- except IOError:
- fname = os.path.join( os.path.dirname(FILENAME), texture_name)
- try:
- img = Image.Load(fname)
- TEXDICT[contextMaterial.name]=img
- except IOError:
- print "\tERROR: failed to load image ",texture_name
- TEXDICT[contextMaterial.name] = None # Dummy
+ elif (new_chunk.ID==MAT_TEXTURE_MAP):
+ new_texture=Blender.Texture.New('Diffuse')
+ new_texture.setType('Image')
+ while (new_chunk.bytes_read<new_chunk.length):
+ read_chunk(file, temp_chunk)
+
+ if (temp_chunk.ID==MAT_MAP_FILENAME):
+ texture_name=""
+ texture_name=str(read_string(file))
+ try:
+ img = Image.Load(texture_name)
+ TEXTURE_DICT[new_material.name]=img
+ except IOError:
+ fname = os.path.join( os.path.dirname(FILENAME), texture_name)
+ try:
+ img = Image.Load(fname)
+ TEXTURE_DICT[new_material.name]=img
+ except IOError:
+ print "\tERROR: failed to load image ",texture_name
+ TEXTURE_DICT[new_material.name] = None # Dummy
+ img=Blender.Image.New(fname,1,1,24) #blank image
+ new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed
- #plus one for the null character that gets removed
- new_chunk.bytes_read += (len(texture_name)+1)
-
-
- elif (new_chunk.ID==OBJECT_MESH):
- # print "Found an OBJECT_MESH chunk"
- if contextMesh != None: # Write context mesh if we have one.
- putContextMesh(contextMesh)
-
- contextMesh = NMesh.New()
-
- # Reset matrix
- contextMatrix = Blender.Mathutils.Matrix(); contextMatrix.identity()
+ else:
+ skip_to_end(file, temp_chunk)
+
+ new_chunk.bytes_read+=temp_chunk.bytes_read
- elif (new_chunk.ID==OBJECT_VERTICES):
- # print "Found an OBJECT_VERTICES chunk"
- #print "object_verts: length: ", new_chunk.length
- temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
- data=struct.unpack("H", temp_data)
- new_chunk.bytes_read+=2
- num_verts=data[0]
- # print "number of verts: ", num_verts
- for counter in range (num_verts):
- temp_data=file.read(STRUCT_SIZE_3FLOAT)
- new_chunk.bytes_read += STRUCT_SIZE_3FLOAT #12: 3 floats x 4 bytes each
- data=struct.unpack("3f", temp_data)
- v=NMesh.Vert(data[0],data[1],data[2])
- contextMesh.verts.append(v)
- #print "object verts: bytes read: ", new_chunk.bytes_read
-
- elif (new_chunk.ID==OBJECT_FACES):
- # print "Found an OBJECT_FACES chunk"
- #print "object faces: length: ", new_chunk.length
- temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
- data=struct.unpack("H", temp_data)
- new_chunk.bytes_read+=2
- num_faces=data[0]
- #print "number of faces: ", num_faces
-
- for counter in range(num_faces):
- temp_data=file.read(STRUCT_SIZE_4UNSIGNED_SHORT)
- new_chunk.bytes_read += STRUCT_SIZE_4UNSIGNED_SHORT #4 short ints x 2 bytes each
- data=struct.unpack("4H", temp_data)
+ #add the map to the material in the right channel
+ add_texture_to_material(img, new_texture, new_material, "DIFFUSE")
- #insert the mesh info into the faces, don't worry about data[3] it is a 3D studio thing
- f = NMesh.Face( [contextMesh.verts[data[i]] for i in xrange(3) ] )
- f.uv = [ tuple(contextMesh.verts[data[i]].uvco[:2]) for i in xrange(3) ]
- contextMesh.faces.append(f)
- #print "object faces: bytes read: ", new_chunk.bytes_read
-
- elif (new_chunk.ID==OBJECT_MATERIAL):
- # print "Found an OBJECT_MATERIAL chunk"
- material_name=""
- material_name=str(read_string(file))
- new_chunk.bytes_read += len(material_name)+1 # remove 1 null character.
-
- #look up the material in all the materials
- material_found=0
- for mat in Material.Get():
+ elif (new_chunk.ID==MAT_SPECULAR_MAP):
+ new_texture=Blender.Texture.New('Specular')
+ new_texture.setType('Image')
+ while (new_chunk.bytes_read<new_chunk.length):
+ read_chunk(file, temp_chunk)
- #found it, add it to the mesh
- if(mat.name==material_name):
- if len(contextMesh.materials) >= 15:
- print "\tCant assign more than 16 materials per mesh, keep going..."
- break
- else:
- meshHasMat = 0
- for myMat in contextMesh.materials:
- if myMat.name == mat.name:
- meshHasMat = 1
-
- if meshHasMat == 0:
- contextMesh.addMaterial(mat)
- material_found=1
-
- #figure out what material index this is for the mesh
- for mat_counter in range(len(contextMesh.materials)):
- if contextMesh.materials[mat_counter].name == material_name:
- mat_index=mat_counter
- #print "material index: ",mat_index
-
-
- break # get out of this for loop so we don't accidentally set material_found back to 0
+ if (temp_chunk.ID==MAT_MAP_FILENAME):
+ texture_name=""
+ texture_name=str(read_string(file))
+ try:
+ img = Image.Load(texture_name)
+ TEXTURE_DICT[new_material.name]=img
+ except IOError:
+ fname = os.path.join( os.path.dirname(FILENAME), texture_name)
+ try:
+ img = Image.Load(fname)
+ TEXTURE_DICT[new_material.name]=img
+ except IOError:
+ print "\tERROR: failed to load image ",texture_name
+ TEXTURE_DICT[new_material.name] = None # Dummy
+ img=Blender.Image.New(fname,1,1,24) #blank image
+ new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed
else:
- material_found=0
- # print "Not matching: ", mat.name, " and ", material_name
-
- if material_found == 1:
- contextMaterial = mat
- #read the number of faces using this material
- temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
- data=struct.unpack("H", temp_data)
- new_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT
- num_faces_using_mat=data[0]
-
- #list of faces using mat
- for face_counter in range(num_faces_using_mat):
- temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
- new_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT
- data=struct.unpack("H", temp_data)
- contextMesh.faces[data[0]].materialIndex = mat_index
-
+ skip_to_end(file, temp_chunk)
+
+ new_chunk.bytes_read+=temp_chunk.bytes_read
+
+ #add the map to the material in the right channel
+ add_texture_to_material(img, new_texture, new_material, "SPECULAR")
+
+ elif (new_chunk.ID==MAT_OPACITY_MAP):
+ new_texture=Blender.Texture.New('Opacity')
+ new_texture.setType('Image')
+ while (new_chunk.bytes_read<new_chunk.length):
+ read_chunk(file, temp_chunk)
+
+ if (temp_chunk.ID==MAT_MAP_FILENAME):
+ texture_name=""
+ texture_name=str(read_string(file))
try:
- mname = MATDICT[contextMaterial.name]
- contextMesh.faces[data[0]].image = TEXDICT[mname]
- except:
- continue
- else:
- #read past the information about the material you couldn't find
- #print "Couldn't find material. Reading past face material info"
- buffer_size=new_chunk.length-new_chunk.bytes_read
- binary_format=str(buffer_size)+"c"
- temp_data=file.read(struct.calcsize(binary_format))
- new_chunk.bytes_read+=buffer_size
-
- #print "object mat: bytes read: ", new_chunk.bytes_read
+ img = Image.Load(texture_name)
+ TEXTURE_DICT[new_material.name]=img
+ except IOError:
+ fname = os.path.join( os.path.dirname(FILENAME), texture_name)
+ try:
+ img = Image.Load(fname)
+ TEXTURE_DICT[new_material.name]=img
+ except IOError:
+ print "\tERROR: failed to load image ",texture_name
+ TEXTURE_DICT[new_material.name] = None # Dummy
+ img=Blender.Image.New(fname,1,1,24) #blank image
+ new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed
+ else:
+ skip_to_end(file, temp_chunk)
+
+ new_chunk.bytes_read+=temp_chunk.bytes_read
- elif (new_chunk.ID == OBJECT_UV):
- # print "Found an OBJECT_UV chunk"
- temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
- data=struct.unpack("H", temp_data)
- new_chunk.bytes_read+=2
- num_uv=data[0]
+ #add the map to the material in the right channel
+ add_texture_to_material(img, new_texture, new_material, "OPACITY")
- for counter in range(num_uv):
- temp_data=file.read(STRUCT_SIZE_2FLOAT)
- new_chunk.bytes_read += STRUCT_SIZE_2FLOAT #2 float x 4 bytes each
- data=struct.unpack("2f", temp_data)
+ elif (new_chunk.ID==MAT_BUMP_MAP):
+ new_texture=Blender.Texture.New('Bump')
+ new_texture.setType('Image')
+ while (new_chunk.bytes_read<new_chunk.length):
+ read_chunk(file, temp_chunk)
- #insert the insert the UV coords in the vertex data
- contextMesh.verts[counter].uvco = data
-
- elif (new_chunk.ID == OBJECT_TRANS_MATRIX):
- # print "Found an OBJECT_TRANS_MATRIX chunk"
+ if (temp_chunk.ID==MAT_MAP_FILENAME):
+ texture_name=""
+ texture_name=str(read_string(file))
+ try:
+ img = Image.Load(texture_name)
+ TEXTURE_DICT[new_material.name]=img
+ except IOError:
+ fname = os.path.join( os.path.dirname(FILENAME), texture_name)
+ try:
+ img = Image.Load(fname)
+ TEXTURE_DICT[new_material.name]=img
+ except IOError:
+ print "\tERROR: failed to load image ",texture_name
+ TEXTURE_DICT[new_material.name] = None # Dummy
+ img=Blender.Image.New(fname,1,1,24) #blank image
+ new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed
+ else:
+ skip_to_end(file, temp_chunk)
+
+ new_chunk.bytes_read+=temp_chunk.bytes_read
+
+ #add the map to the material in the right channel
+ add_texture_to_material(img, new_texture, new_material, "BUMP")
- temp_data=file.read(STRUCT_SIZE_4x3MAT)
- data = list( struct.unpack("ffffffffffff", temp_data) )
- new_chunk.bytes_read += STRUCT_SIZE_4x3MAT
+ elif (new_chunk.ID==MAT_TRANSPARENCY):
+ read_chunk(file, temp_chunk)
+ temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
+ data=struct.unpack("H", temp_data)
+ temp_chunk.bytes_read+=2
+ new_material.setAlpha(1-(float(data[0])/100))
+ new_chunk.bytes_read+=temp_chunk.bytes_read
- contextMatrix = Blender.Mathutils.Matrix(\
- data[:3] + [0],\
- data[3:6] + [0],\
- data[6:9] + [0],\
- data[9:] + [1])
+ else:
+ skip_to_end(file,new_chunk)
-
-
- else: #(new_chunk.ID!=VERSION or new_chunk.ID!=OBJECTINFO or new_chunk.ID!=OBJECT or new_chunk.ID!=MATERIAL):
- # print "skipping to end of this chunk"
- buffer_size=new_chunk.length-new_chunk.bytes_read
- binary_format=str(buffer_size)+"c"
- temp_data=file.read(struct.calcsize(binary_format))
- new_chunk.bytes_read+=buffer_size
-
+ previous_chunk.bytes_read+=new_chunk.bytes_read
- #update the previous chunk bytes read
- previous_chunk.bytes_read += new_chunk.bytes_read
- #print "Bytes left in this chunk: ", previous_chunk.length-previous_chunk.bytes_read
+######################################################
+# process a main chunk
+######################################################
+def process_main_chunk(file,previous_chunk,new_object_list):
- # FINISHED LOOP
- # There will be a number of objects still not added
- if contextMesh != None:
- putContextMesh(contextMesh)
+ #spare chunks
+ new_chunk=chunk()
+ temp_chunk=chunk()
+
+ #Go through the main chunk
+ while (previous_chunk.bytes_read<previous_chunk.length):
+ read_chunk(file, new_chunk)
+
+ if (new_chunk.ID==VERSION):
+ temp_data=file.read(struct.calcsize("I"))
+ data=struct.unpack("I", temp_data)
+ version=data[0]
+ new_chunk.bytes_read+=4 #read the 4 bytes for the version number
+ if (version>3): #this loader works with version 3 and below, but may not with 4 and above
+ print "\tNon-Fatal Error: Version greater than 3, may not load correctly: ", version
+
+ elif (new_chunk.ID==EDITOR_BLOCK):
+ while(new_chunk.bytes_read<new_chunk.length):
+ read_chunk(file, temp_chunk)
+ if (temp_chunk.ID==MATERIAL_BLOCK):
+ process_material_block(file, temp_chunk)
+ elif (temp_chunk.ID==OBJECT_BLOCK):
+ process_object_block(file, temp_chunk,new_object_list)
+ else:
+ skip_to_end(file,temp_chunk)
+
+ new_chunk.bytes_read+=temp_chunk.bytes_read
+ else:
+ skip_to_end(file,new_chunk)
- for ob in objectList:
- ob.sel = 1
+ previous_chunk.bytes_read+=new_chunk.bytes_read
+#***********************************************
+# main entry point for loading 3ds files
+#***********************************************
def load_3ds (filename):
+ current_chunk=chunk()
+ print "--------------------------------"
print 'Importing "%s"' % filename
-
- time1 = Blender.sys.time()
+ time1 = Blender.sys.time() #for timing purposes
+ file=open(filename,"rb")
+ new_object_list = []
global FILENAME
FILENAME=filename
- current_chunk=chunk()
- file=open(filename,"rb")
-
- #here we go!
- # print "reading the first chunk"
- new_object_list = []
read_chunk(file, current_chunk)
+
if (current_chunk.ID!=PRIMARY):
print "\tFatal Error: Not a valid 3ds file: ", filename
file.close()
return
-
- process_next_chunk(file, current_chunk, new_object_list)
+
+ process_main_chunk(file, current_chunk, new_object_list)
# Select all new objects.
for ob in new_object_list: ob.sel = 1