blender/release/scripts/op/io_scene_3ds/import_3ds.py
Campbell Barton 7be25eba13 fix [#24712] 3ds_import fix
Rather then applying the proposed fix, enabling 'Apply Transform' works in almost all cases including the reported one.

There are some files that don't work with 'Apply Transform', which is why the option is worth keeping.

also remove unneeded calls to paint_facesel_test()
2010-11-15 00:07:38 +00:00

755 lines
28 KiB
Python

# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# Script copyright (C) Bob Holcomb
# Contributors: Bob Holcomb, Richard L?rk?ng, Damien McGinnes, Campbell Barton, Mario Lapin
import os
import time
import struct
from io_utils import load_image
import bpy
import mathutils
BOUNDS_3DS = []
######################################################
# Data Structures
######################################################
#Some of the chunks that we will see
#----- Primary Chunk, at the beginning of each file
PRIMARY = int('0x4D4D',16)
#------ Main Chunks
OBJECTINFO = 0x3D3D #This gives the version of the mesh and is found right before the material and object information
VERSION = 0x0002 #This gives the version of the .3ds file
EDITKEYFRAME= 0xB000 #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
#------ sub defines of MATERIAL_BLOCK
MAT_NAME = 0xA000 # This holds the material name
MAT_AMBIENT = 0xA010 # Ambient color of the object/material
MAT_DIFFUSE = 0xA020 # This holds the color of the object/material
MAT_SPECULAR = 0xA030 # SPecular color of the object/material
MAT_SHINESS = 0xA040 # ??
MAT_TRANSPARENCY= 0xA050 # Transparency value of material
MAT_SELF_ILLUM = 0xA080 # Self Illumination value of material
MAT_WIRE = 0xA085 # Only render's wireframe
MAT_TEXTURE_MAP = 0xA200 # This is a header for a new texture map
MAT_SPECULAR_MAP= 0xA204 # This is a header for a new specular map
MAT_OPACITY_MAP = 0xA210 # This is a header for a new opacity map
MAT_REFLECTION_MAP= 0xA220 # This is a header for a new reflection map
MAT_BUMP_MAP = 0xA230 # This is a header for a new bump map
MAT_MAP_FILEPATH = 0xA300 # This holds the file name of the texture
MAT_FLOAT_COLOR = 0x0010 #color defined as 3 floats
MAT_24BIT_COLOR = 0x0011 #color defined as 3 bytes
#>------ sub defines of OBJECT
OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object
OBJECT_LAMP = 0x4600 # This lets un know we are reading a light object
OBJECT_LAMP_SPOT = 0x4610 # The light is a spotloght.
OBJECT_LAMP_OFF = 0x4620 # The light off.
OBJECT_LAMP_ATTENUATE = 0x4625
OBJECT_LAMP_RAYSHADE = 0x4627
OBJECT_LAMP_SHADOWED = 0x4630
OBJECT_LAMP_LOCAL_SHADOW = 0x4640
OBJECT_LAMP_LOCAL_SHADOW2 = 0x4641
OBJECT_LAMP_SEE_CONE = 0x4650
OBJECT_LAMP_SPOT_RECTANGULAR = 0x4651
OBJECT_LAMP_SPOT_OVERSHOOT = 0x4652
OBJECT_LAMP_SPOT_PROJECTOR = 0x4653
OBJECT_LAMP_EXCLUDE = 0x4654
OBJECT_LAMP_RANGE = 0x4655
OBJECT_LAMP_ROLL = 0x4656
OBJECT_LAMP_SPOT_ASPECT = 0x4657
OBJECT_LAMP_RAY_BIAS = 0x4658
OBJECT_LAMP_INNER_RANGE = 0x4659
OBJECT_LAMP_OUTER_RANGE = 0x465A
OBJECT_LAMP_MULTIPLIER = 0x465B
OBJECT_LAMP_AMBIENT_LIGHT = 0x4680
OBJECT_CAMERA= 0x4700 # This lets un know we are reading a camera object
#>------ sub defines of CAMERA
OBJECT_CAM_RANGES= 0x4720 # The camera range values
#>------ sub defines of OBJECT_MESH
OBJECT_VERTICES = 0x4110 # The objects vertices
OBJECT_FACES = 0x4120 # The objects faces
OBJECT_MATERIAL = 0x4130 # This is found if the object has a material, either texture map or color
OBJECT_UV = 0x4140 # The UV texture coordinates
OBJECT_TRANS_MATRIX = 0x4160 # The Object Matrix
global scn
scn = None
#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):
self.ID = 0
self.length = 0
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)
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()
def read_string(file):
#read in the characters till we get a null character
s = b''
while True:
c = struct.unpack('<c', file.read(1))[0]
if c == b'\x00':
break
s += c
#print 'string: ',s
#remove the null character from the string
# print("read string", s)
return str(s, "utf-8", "replace"), len(s) + 1
######################################################
# 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 skip_to_end(file, skip_chunk):
buffer_size = skip_chunk.length - skip_chunk.bytes_read
binary_format='%ic' % buffer_size
temp_data = file.read(struct.calcsize(binary_format))
skip_chunk.bytes_read += buffer_size
def add_texture_to_material(image, texture, material, mapto):
#print('assigning %s to %s' % (texture, material))
if mapto not in ("COLOR", "SPECULARITY", "ALPHA", "NORMAL"):
print('/tError: Cannot map to "%s"\n\tassuming diffuse color. modify material "%s" later.' % (mapto, material.name))
mapto = "COLOR"
if image:
texture.image = image
mtex = material.texture_slots.add()
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_color_diffuse = False
if mapto == 'COLOR':
mtex.use_map_color_diffuse = True
elif mapto == 'SPECULARITY':
mtex.use_map_specular = True
elif mapto == 'ALPHA':
mtex.use_map_alpha = True
elif mapto == 'NORMAL':
mtex.use_map_normal = True
def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
#print previous_chunk.bytes_read, 'BYTES READ'
contextObName = None
contextLamp = [None, None] # object, Data
contextMaterial = None
contextMatrix_rot = None # Blender.mathutils.Matrix(); contextMatrix.identity()
#contextMatrix_tx = None # Blender.mathutils.Matrix(); contextMatrix.identity()
contextMesh_vertls = None # flat array: (verts * 3)
contextMesh_facels = None
contextMeshMaterials = {} # matname:[face_idxs]
contextMeshUV = None # flat array (verts * 2)
TEXTURE_DICT = {}
MATDICT = {}
# TEXMODE = Mesh.FaceModes['TEX']
# 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')
_STRUCT_SIZE_4x3MAT = struct.calcsize('fffffffffffff')
# STRUCT_SIZE_4x3MAT = calcsize('ffffffffffff')
# print STRUCT_SIZE_4x3MAT, ' STRUCT_SIZE_4x3MAT'
def putContextMesh(myContextMesh_vertls, myContextMesh_facels, myContextMeshMaterials):
bmesh = bpy.data.meshes.new(contextObName)
if myContextMesh_facels is None:
myContextMesh_facels = []
if myContextMesh_vertls:
bmesh.vertices.add(len(myContextMesh_vertls)//3)
bmesh.faces.add(len(myContextMesh_facels))
bmesh.vertices.foreach_set("co", myContextMesh_vertls)
eekadoodle_faces = []
for v1, v2, v3 in myContextMesh_facels:
eekadoodle_faces.extend([v3, v1, v2, 0] if v3 == 0 else [v1, v2, v3, 0])
bmesh.faces.foreach_set("vertices_raw", eekadoodle_faces)
if bmesh.faces and contextMeshUV:
bmesh.uv_textures.new()
uv_faces = bmesh.uv_textures.active.data[:]
else:
uv_faces = None
for mat_idx, (matName, faces) in enumerate(myContextMeshMaterials.items()):
if matName is None:
bmat = None
else:
bmat = MATDICT[matName][1]
img = TEXTURE_DICT.get(bmat.name)
bmesh.materials.append(bmat) # can be None
if uv_faces and img:
for fidx in faces:
bmesh.faces[fidx].material_index = mat_idx
uf = uv_faces[fidx]
uf.image = img
uf.use_image = True
else:
for fidx in faces:
bmesh.faces[fidx].material_index = mat_idx
if uv_faces:
for fidx, uf in enumerate(uv_faces):
face = myContextMesh_facels[fidx]
v1, v2, v3 = face
# eekadoodle
if v3 == 0:
v1, v2, v3 = v3, v1, v2
uf.uv1 = contextMeshUV[v1 * 2:(v1 * 2) + 2]
uf.uv2 = contextMeshUV[v2 * 2:(v2 * 2) + 2]
uf.uv3 = contextMeshUV[v3 * 2:(v3 * 2) + 2]
# always a tri
ob = bpy.data.objects.new(tempName, bmesh)
SCN.objects.link(ob)
'''
if contextMatrix_tx:
ob.setMatrix(contextMatrix_tx)
'''
if contextMatrix_rot:
ob.matrix_world = contextMatrix_rot
importedObjects.append(ob)
bmesh.update()
#a spare chunk
new_chunk = chunk()
temp_chunk = chunk()
CreateBlenderObject = False
def read_float_color(temp_chunk):
temp_data = file.read(struct.calcsize('3f'))
temp_chunk.bytes_read += 12
return [float(col) for col in struct.unpack('<3f', temp_data)]
def read_byte_color(temp_chunk):
temp_data = file.read(struct.calcsize('3B'))
temp_chunk.bytes_read += 3
return [float(col)/255 for col in struct.unpack('<3B', temp_data)] # data [0,1,2] == rgb
def read_texture(new_chunk, temp_chunk, name, mapto):
new_texture = bpy.data.textures.new(name, type='IMAGE')
img = None
while (new_chunk.bytes_read < new_chunk.length):
#print 'MAT_TEXTURE_MAP..while', new_chunk.bytes_read, new_chunk.length
read_chunk(file, temp_chunk)
if (temp_chunk.ID == MAT_MAP_FILEPATH):
texture_name, read_str_len = read_string(file)
img = TEXTURE_DICT[contextMaterial.name] = load_image(texture_name, dirname)
new_chunk.bytes_read += read_str_len #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
if img:
add_texture_to_material(img, new_texture, contextMaterial, mapto)
dirname = os.path.dirname(file.name)
#loop through all the data for this chunk (previous chunk) and see what it is
while (previous_chunk.bytes_read < previous_chunk.length):
#print '\t', previous_chunk.bytes_read, 'keep going'
#read the next chunk
#print 'reading a chunk'
read_chunk(file, new_chunk)
#is it a Version chunk?
if (new_chunk.ID == VERSION):
#print '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'))
version = struct.unpack('<I', temp_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 'elif (new_chunk.ID == OBJECTINFO):'
# print 'found an OBJECTINFO chunk'
process_next_chunk(file, new_chunk, importedObjects, IMAGE_SEARCH)
#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):
if CreateBlenderObject:
putContextMesh(contextMesh_vertls, contextMesh_facels, contextMeshMaterials)
contextMesh_vertls = []; contextMesh_facels = []
## preparando para receber o proximo objeto
contextMeshMaterials = {} # matname:[face_idxs]
contextMeshUV = None
#contextMesh.vertexUV = 1 # Make sticky coords.
# Reset matrix
contextMatrix_rot = None
#contextMatrix_tx = None
CreateBlenderObject = True
tempName, read_str_len = read_string(file)
contextObName = tempName
new_chunk.bytes_read += read_str_len
#is it a material chunk?
elif (new_chunk.ID == MATERIAL):
# print("read material")
#print 'elif (new_chunk.ID == MATERIAL):'
contextMaterial = bpy.data.materials.new('Material')
elif (new_chunk.ID == MAT_NAME):
#print 'elif (new_chunk.ID == MAT_NAME):'
material_name, read_str_len = read_string(file)
# print("material name", material_name)
#plus one for the null character that ended the string
new_chunk.bytes_read += read_str_len
contextMaterial.name = material_name.rstrip() # remove trailing whitespace
MATDICT[material_name]= (contextMaterial.name, contextMaterial)
elif (new_chunk.ID == MAT_AMBIENT):
#print 'elif (new_chunk.ID == MAT_AMBIENT):'
read_chunk(file, temp_chunk)
if (temp_chunk.ID == MAT_FLOAT_COLOR):
contextMaterial.mirror_color = read_float_color(temp_chunk)
# temp_data = file.read(struct.calcsize('3f'))
# temp_chunk.bytes_read += 12
# contextMaterial.mirCol = [float(col) for col in struct.unpack('<3f', temp_data)]
elif (temp_chunk.ID == MAT_24BIT_COLOR):
contextMaterial.mirror_color = read_byte_color(temp_chunk)
# temp_data = file.read(struct.calcsize('3B'))
# temp_chunk.bytes_read += 3
# contextMaterial.mirCol = [float(col)/255 for col in struct.unpack('<3B', temp_data)] # data [0,1,2] == rgb
else:
skip_to_end(file, temp_chunk)
new_chunk.bytes_read += temp_chunk.bytes_read
elif (new_chunk.ID == MAT_DIFFUSE):
#print 'elif (new_chunk.ID == MAT_DIFFUSE):'
read_chunk(file, temp_chunk)
if (temp_chunk.ID == MAT_FLOAT_COLOR):
contextMaterial.diffuse_color = read_float_color(temp_chunk)
# temp_data = file.read(struct.calcsize('3f'))
# temp_chunk.bytes_read += 12
# contextMaterial.rgbCol = [float(col) for col in struct.unpack('<3f', temp_data)]
elif (temp_chunk.ID == MAT_24BIT_COLOR):
contextMaterial.diffuse_color = read_byte_color(temp_chunk)
# temp_data = file.read(struct.calcsize('3B'))
# temp_chunk.bytes_read += 3
# contextMaterial.rgbCol = [float(col)/255 for col in struct.unpack('<3B', temp_data)] # data [0,1,2] == rgb
else:
skip_to_end(file, temp_chunk)
# print("read material diffuse color", contextMaterial.diffuse_color)
new_chunk.bytes_read += temp_chunk.bytes_read
elif (new_chunk.ID == MAT_SPECULAR):
#print 'elif (new_chunk.ID == MAT_SPECULAR):'
read_chunk(file, temp_chunk)
if (temp_chunk.ID == MAT_FLOAT_COLOR):
contextMaterial.specular_color = read_float_color(temp_chunk)
# temp_data = file.read(struct.calcsize('3f'))
# temp_chunk.bytes_read += 12
# contextMaterial.mirCol = [float(col) for col in struct.unpack('<3f', temp_data)]
elif (temp_chunk.ID == MAT_24BIT_COLOR):
contextMaterial.specular_color = read_byte_color(temp_chunk)
# temp_data = file.read(struct.calcsize('3B'))
# temp_chunk.bytes_read += 3
# contextMaterial.mirCol = [float(col)/255 for col in struct.unpack('<3B', temp_data)] # data [0,1,2] == rgb
else:
skip_to_end(file, temp_chunk)
new_chunk.bytes_read += temp_chunk.bytes_read
elif (new_chunk.ID == MAT_TEXTURE_MAP):
read_texture(new_chunk, temp_chunk, "Diffuse", "COLOR")
elif (new_chunk.ID == MAT_SPECULAR_MAP):
read_texture(new_chunk, temp_chunk, "Specular", "SPECULARITY")
elif (new_chunk.ID == MAT_OPACITY_MAP):
read_texture(new_chunk, temp_chunk, "Opacity", "ALPHA")
elif (new_chunk.ID == MAT_BUMP_MAP):
read_texture(new_chunk, temp_chunk, "Bump", "NORMAL")
elif (new_chunk.ID == MAT_TRANSPARENCY):
#print 'elif (new_chunk.ID == MAT_TRANSPARENCY):'
read_chunk(file, temp_chunk)
temp_data = file.read(STRUCT_SIZE_UNSIGNED_SHORT)
temp_chunk.bytes_read += 2
contextMaterial.alpha = 1-(float(struct.unpack('<H', temp_data)[0])/100)
new_chunk.bytes_read += temp_chunk.bytes_read
elif (new_chunk.ID == OBJECT_LAMP): # Basic lamp support.
temp_data = file.read(STRUCT_SIZE_3FLOAT)
x,y,z = struct.unpack('<3f', temp_data)
new_chunk.bytes_read += STRUCT_SIZE_3FLOAT
ob = bpy.data.objects.new("Lamp", bpy.data.lamps.new("Lamp"))
SCN.objects.link(ob)
contextLamp[1]= ob.data
# contextLamp[1]= bpy.data.lamps.new()
contextLamp[0]= ob
# contextLamp[0]= SCN_OBJECTS.new(contextLamp[1])
importedObjects.append(contextLamp[0])
#print 'number of faces: ', num_faces
#print x,y,z
contextLamp[0].location = (x, y, z)
# contextLamp[0].setLocation(x,y,z)
# Reset matrix
contextMatrix_rot = None
#contextMatrix_tx = None
#print contextLamp.name,
elif (new_chunk.ID == OBJECT_MESH):
# print 'Found an OBJECT_MESH chunk'
pass
elif (new_chunk.ID == OBJECT_VERTICES):
'''
Worldspace vertex locations
'''
# print 'elif (new_chunk.ID == OBJECT_VERTICES):'
temp_data = file.read(STRUCT_SIZE_UNSIGNED_SHORT)
num_verts = struct.unpack('<H', temp_data)[0]
new_chunk.bytes_read += 2
# print 'number of verts: ', num_verts
contextMesh_vertls = struct.unpack('<%df' % (num_verts * 3), file.read(STRUCT_SIZE_3FLOAT * num_verts))
new_chunk.bytes_read += STRUCT_SIZE_3FLOAT * num_verts
# dummyvert is not used atm!
#print 'object verts: bytes read: ', new_chunk.bytes_read
elif (new_chunk.ID == OBJECT_FACES):
# print 'elif (new_chunk.ID == OBJECT_FACES):'
temp_data = file.read(STRUCT_SIZE_UNSIGNED_SHORT)
num_faces = struct.unpack('<H', temp_data)[0]
new_chunk.bytes_read += 2
#print 'number of faces: ', num_faces
# print '\ngetting a face'
temp_data = file.read(STRUCT_SIZE_4UNSIGNED_SHORT * num_faces)
new_chunk.bytes_read += STRUCT_SIZE_4UNSIGNED_SHORT * num_faces #4 short ints x 2 bytes each
contextMesh_facels = struct.unpack('<%dH' % (num_faces * 4), temp_data)
contextMesh_facels = [contextMesh_facels[i - 3:i] for i in range(3, (num_faces * 4) + 3, 4)]
elif (new_chunk.ID == OBJECT_MATERIAL):
# print 'elif (new_chunk.ID == OBJECT_MATERIAL):'
material_name, read_str_len = read_string(file)
new_chunk.bytes_read += read_str_len # remove 1 null character.
temp_data = file.read(STRUCT_SIZE_UNSIGNED_SHORT)
num_faces_using_mat = struct.unpack('<H', temp_data)[0]
new_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT
temp_data = file.read(STRUCT_SIZE_UNSIGNED_SHORT * num_faces_using_mat)
new_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT * num_faces_using_mat
contextMeshMaterials[material_name]= struct.unpack("<%dH" % (num_faces_using_mat), temp_data)
#look up the material in all the materials
elif (new_chunk.ID == OBJECT_UV):
temp_data = file.read(STRUCT_SIZE_UNSIGNED_SHORT)
num_uv = struct.unpack('<H', temp_data)[0]
new_chunk.bytes_read += 2
temp_data = file.read(STRUCT_SIZE_2FLOAT * num_uv)
new_chunk.bytes_read += STRUCT_SIZE_2FLOAT * num_uv
contextMeshUV = struct.unpack('<%df' % (num_uv * 2), temp_data)
elif (new_chunk.ID == OBJECT_TRANS_MATRIX):
# How do we know the matrix size? 54 == 4x4 48 == 4x3
temp_data = file.read(STRUCT_SIZE_4x3MAT)
data = list( struct.unpack('<ffffffffffff', temp_data) )
new_chunk.bytes_read += STRUCT_SIZE_4x3MAT
contextMatrix_rot = mathutils.Matrix(\
data[:3] + [0],\
data[3:6] + [0],\
data[6:9] + [0],\
data[9:] + [1])
elif (new_chunk.ID == MAT_MAP_FILEPATH):
texture_name, read_str_len = read_string(file)
try:
TEXTURE_DICT[contextMaterial.name]
except:
#img = TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILEPATH)
img = TEXTURE_DICT[contextMaterial.name] = load_image(texture_name, dirname)
# img = TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILEPATH, PLACE_HOLDER=False, RECURSIVE=IMAGE_SEARCH)
new_chunk.bytes_read += read_str_len #plus one for the null character that gets removed
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='%ic' % buffer_size
temp_data = file.read(struct.calcsize(binary_format))
new_chunk.bytes_read += buffer_size
#update the previous chunk bytes read
# print 'previous_chunk.bytes_read += new_chunk.bytes_read'
# print previous_chunk.bytes_read, new_chunk.bytes_read
previous_chunk.bytes_read += new_chunk.bytes_read
## print 'Bytes left in this chunk: ', previous_chunk.length - previous_chunk.bytes_read
# FINISHED LOOP
# There will be a number of objects still not added
if CreateBlenderObject:
putContextMesh(contextMesh_vertls, contextMesh_facels, contextMeshMaterials)
def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, APPLY_MATRIX=True):
global SCN
# XXX
# if BPyMessages.Error_NoFile(filepath):
# return
print("importing 3DS: %r..." % (filepath), end="")
time1 = time.clock()
# time1 = Blender.sys.time()
current_chunk = chunk()
file = open(filepath, 'rb')
#here we go!
# print 'reading the first chunk'
read_chunk(file, current_chunk)
if (current_chunk.ID!=PRIMARY):
print('\tFatal Error: Not a valid 3ds file: %r' % filepath)
file.close()
return
# IMPORT_AS_INSTANCE = Blender.Draw.Create(0)
# IMPORT_CONSTRAIN_BOUNDS = Blender.Draw.Create(10.0)
# IMAGE_SEARCH = Blender.Draw.Create(1)
# APPLY_MATRIX = Blender.Draw.Create(0)
# Get USER Options
# pup_block = [\
# ('Size Constraint:', IMPORT_CONSTRAIN_BOUNDS, 0.0, 1000.0, 'Scale the model by 10 until it reacehs the size constraint. Zero Disables.'),\
# ('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),\
# ('Transform Fix', APPLY_MATRIX, 'Workaround for object transformations importing incorrectly'),\
# #('Group Instance', IMPORT_AS_INSTANCE, 'Import objects into a new scene and group, creating an instance in the current scene.'),\
# ]
# if PREF_UI:
# if not Blender.Draw.PupBlock('Import 3DS...', pup_block):
# return
# Blender.Window.WaitCursor(1)
# IMPORT_CONSTRAIN_BOUNDS = IMPORT_CONSTRAIN_BOUNDS.val
# # IMPORT_AS_INSTANCE = IMPORT_AS_INSTANCE.val
# IMAGE_SEARCH = IMAGE_SEARCH.val
# APPLY_MATRIX = APPLY_MATRIX.val
if IMPORT_CONSTRAIN_BOUNDS:
BOUNDS_3DS[:]= [1<<30, 1<<30, 1<<30, -1<<30, -1<<30, -1<<30]
else:
BOUNDS_3DS[:]= []
##IMAGE_SEARCH
scn = context.scene
# scn = bpy.data.scenes.active
SCN = scn
# SCN_OBJECTS = scn.objects
# SCN_OBJECTS.selected = [] # de select all
importedObjects = [] # Fill this list with objects
process_next_chunk(file, current_chunk, importedObjects, IMAGE_SEARCH)
# Link the objects into this scene.
# Layers = scn.Layers
# REMOVE DUMMYVERT, - remove this in the next release when blenders internal are fixed.
if APPLY_MATRIX:
for ob in importedObjects:
if ob.type == 'MESH':
me = ob.data
me.transform(ob.matrix_world.copy().invert())
# Done DUMMYVERT
"""
if IMPORT_AS_INSTANCE:
name = filepath.split('\\')[-1].split('/')[-1]
# Create a group for this import.
group_scn = Scene.New(name)
for ob in importedObjects:
group_scn.link(ob) # dont worry about the layers
grp = Blender.Group.New(name)
grp.objects = importedObjects
grp_ob = Object.New('Empty', name)
grp_ob.enableDupGroup = True
grp_ob.DupGroup = grp
scn.link(grp_ob)
grp_ob.Layers = Layers
grp_ob.sel = 1
else:
# Select all imported objects.
for ob in importedObjects:
scn.link(ob)
ob.Layers = Layers
ob.sel = 1
"""
if 0:
# if IMPORT_CONSTRAIN_BOUNDS!=0.0:
# Set bounds from objecyt bounding box
for ob in importedObjects:
if ob.type == 'MESH':
# if ob.type=='Mesh':
ob.makeDisplayList() # Why dosnt this update the bounds?
for v in ob.getBoundBox():
for i in (0,1,2):
if v[i] < BOUNDS_3DS[i]:
BOUNDS_3DS[i]= v[i] # min
if v[i] > BOUNDS_3DS[i + 3]:
BOUNDS_3DS[i + 3]= v[i] # min
# Get the max axis x/y/z
max_axis = max(BOUNDS_3DS[3]-BOUNDS_3DS[0], BOUNDS_3DS[4]-BOUNDS_3DS[1], BOUNDS_3DS[5]-BOUNDS_3DS[2])
# print max_axis
if max_axis < 1 << 30: # Should never be false but just make sure.
# Get a new scale factor if set as an option
SCALE = 1.0
while (max_axis * SCALE) > IMPORT_CONSTRAIN_BOUNDS:
SCALE/=10
# SCALE Matrix
SCALE_MAT = mathutils.Matrix.Scale(SCALE, 4)
for ob in importedObjects:
ob.matrix_world = ob.matrix_world * SCALE_MAT
# Done constraining to bounds.
# Select all new objects.
print(" done in %.4f sec." % (time.clock()-time1))
file.close()
def load(operator, context, filepath="", constrain_size=0.0, use_image_search=True, use_apply_transform=True):
load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=constrain_size, IMAGE_SEARCH=use_image_search, APPLY_MATRIX=use_apply_transform)
return {'FINISHED'}