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:
authorCampbell Barton <ideasman42@gmail.com>2006-05-14 07:11:55 +0400
committerCampbell Barton <ideasman42@gmail.com>2006-05-14 07:11:55 +0400
commitb817c78b0d5c7bd50ac4bf2c4b21751d61cc2342 (patch)
tree652dd6fec474dc44b9374ea58e970dca9b67237c /release
parent4a5826fa83f15dad702a65438b36ec6d1f0f30df (diff)
Applied patch 4188 with some modifications.
https://projects.blender.org/tracker/index.php?func=detail&aid=4188&group_id=9&atid=127 * Sped up export of UV coords, * Use Mesh instead of NMesh * Use BPyMesh GetMeshFromObject so correct object materials are exported as well as modifiers applied.
Diffstat (limited to 'release')
-rw-r--r--release/scripts/3ds_export.py212
1 files changed, 108 insertions, 104 deletions
diff --git a/release/scripts/3ds_export.py b/release/scripts/3ds_export.py
index 938afcd1bc6..9404e4b6642 100644
--- a/release/scripts/3ds_export.py
+++ b/release/scripts/3ds_export.py
@@ -9,7 +9,7 @@ Tooltip: 'Export to 3DS file format (.3ds).'
__author__ = ["Campbell Barton", "Bob Holcomb", "Richard Lärkäng", "Damien McGinnes", "Mark Stijnman"]
__url__ = ("blender", "elysiun", "http://www.gametutorials.com", "http://lib3ds.sourceforge.net/")
-__version__ = "0.90"
+__version__ = "0.90a"
__bpydoc__ = """\
3ds Exporter
@@ -47,10 +47,12 @@ from the lib3ds project (http://lib3ds.sourceforge.net/) sourcecode.
######################################################
import Blender
-from Blender import NMesh, Scene, Object, Material
+from Blender import Object, Material
+import BPyMesh
import struct
+
######################################################
# Data Structures
######################################################
@@ -127,6 +129,8 @@ def newFName(ext):
"""
return Blender.Get('filename')[: -len(Blender.Get('filename').split('.', -1)[-1]) ] + ext
+def uv_key(uv):
+ return round(uv.x, 6), round(uv.y, 6)
# size defines:
SZ_SHORT = 2
@@ -468,7 +472,7 @@ def make_material_chunk(material):
material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, material.specCol))
return material_chunk
-class tri:
+class tri_wrapper:
"""Class representing a triangle.
Used when converting faces to triangles"""
@@ -478,54 +482,22 @@ class tri:
# material index:
mat_index=None
# uv coordinates (used on blender faces that have face-uv)
- uvco=None
+ faceuvs=None
- def __init__(self, vindex=(0,0,0), mat=None, uvco=None):
- self.vertex_index = vindex
- self.mat = mat
- self.uvco = uvco
-
-class UniqueList:
- """A list that only allows unique items.
-
- Trying to add an item that is not unique will give you the index where the item is already located."""
- items=[]
-
- def __init__(self):
- self.items=[]
-
- def add(self, new_item):
- """Add an item to the list and return the index at which it is added.
-
- If the item is already in the list, the index of the existing item is returned."""
- found_index=None
- for i,item in enumerate(self.items):
- if (item==new_item):
- found_index = i
- break
- if found_index==None:
- found_index=len(self.items)
- self.items.append(new_item)
- return found_index
-
+ def __init__(self, vindex=(0,0,0), mat=None, faceuvs=None):
+ self.vertex_index= vindex
+ self.mat= mat
+ self.faceuvs= faceuvs
+ self.offset= [0, 0, 0] # offset indicies
def split_into_tri(face, do_uv=False):
- """Split a quad face into two triangles.
-
- The quad will be split along the shortest of its two diagonals."""
- if (face[0].co-face[2].co).length < (face[1].co-face[3].co).length:
- first_tri = tri((face[0].index, face[1].index, face[2].index), face.mat)
- second_tri = tri((face[2].index, face[3].index, face[0].index), face.mat)
- if (do_uv):
- first_tri.uvco = (face.uv[0], face.uv[1], face.uv[2])
- second_tri.uvco = (face.uv[2], face.uv[3], face.uv[0])
- else:
- first_tri = tri((face[0].index, face[1].index, face[3].index), face.mat)
- second_tri = tri((face[1].index, face[2].index, face[3].index), face.mat)
- if (do_uv):
- first_tri.uvco = (face.uv[0], face.uv[1], face.uv[3])
- second_tri.uvco = (face.uv[1], face.uv[2], face.uv[3])
- return first_tri, second_tri
+ """Split a quad face into two triangles"""
+ first_tri = tri_wrapper((face.v[0].index, face.v[1].index, face.v[2].index), face.mat)
+ second_tri = tri_wrapper((face.v[0].index, face.v[2].index, face.v[3].index), face.mat)
+ if (do_uv):
+ first_tri.faceuvs= uv_key(face.uv[0]), uv_key(face.uv[1]), uv_key(face.uv[2])
+ second_tri.faceuvs= uv_key(face.uv[0]), uv_key(face.uv[2]), uv_key(face.uv[3])
+ return [first_tri, second_tri]
def extract_triangles(mesh):
@@ -533,21 +505,18 @@ def extract_triangles(mesh):
If the mesh contains quads, they will be split into triangles."""
tri_list = []
- do_uv = mesh.hasFaceUV()
+ do_uv = mesh.faceUV
for face in mesh.faces:
- if len(face) > 2:
- num_fv = len(face)
+ num_fv = len(face.v)
if num_fv==3:
- new_tri = tri((face[0].index, face[1].index, face[2].index), face.mat)
+ new_tri = tri_wrapper((face.v[0].index, face.v[1].index, face.v[2].index), face.mat)
if (do_uv):
- new_tri.uvco = face.uv
+ new_tri.faceuvs= uv_key(face.uv[0]), uv_key(face.uv[1]), uv_key(face.uv[2])
tri_list.append(new_tri)
- elif num_fv==4: #it's a quad
- first_tri, second_tri = split_into_tri(face, do_uv)
- tri_list.append(first_tri)
- tri_list.append(second_tri)
+ else: #it's a quad
+ tri_list.extend( split_into_tri(face, do_uv) )
return tri_list
@@ -560,17 +529,23 @@ def remove_face_uv(verts, tri_list):
there are multiple uv coordinates per vertex."""
# initialize a list of UniqueLists, one per vertex:
- uv_list = [UniqueList() for i in xrange(len(verts))]
-
- offset_list = [ ]
+ #uv_list = [UniqueList() for i in xrange(len(verts))]
+ unique_uvs= [{} for i in xrange(len(verts))]
# for each face uv coordinate, add it to the UniqueList of the vertex
for tri in tri_list:
- offset = []
for i in xrange(3):
# store the index into the UniqueList for future reference:
- offset.append(uv_list[tri.vertex_index[i]].add(_3ds_point_uv(tri.uvco[i])))
- offset_list.append(offset)
+ # offset.append(uv_list[tri.vertex_index[i]].add(_3ds_point_uv(tri.faceuvs[i])))
+ context_uv_vert= unique_uvs[tri.vertex_index[i]]
+ uvkey= tri.faceuvs[i]
+ try:
+ offset_index, uv_3ds= context_uv_vert[uvkey]
+ except:
+ offset_index= len(context_uv_vert)
+ context_uv_vert[tri.faceuvs[i]]= offset_index, _3ds_point_uv(uvkey)
+ tri.offset[i]= offset_index
+
# At this point, each vertex has a UniqueList containing every uv coordinate that is associated with it
# only once.
@@ -582,18 +557,18 @@ def remove_face_uv(verts, tri_list):
index_list=[]
for i,vert in enumerate(verts):
index_list.append(vert_index)
- for uv in uv_list[i].items:
+ for ii, uv_3ds in unique_uvs[i].itervalues():
# add a vertex duplicate to the vertex_array for every uv associated with this vertex:
- vert_array.add(_3ds_point_3d(vert))
+ vert_array.add(_3ds_point_3d(vert.co))
# add the uv coordinate to the uv array:
- uv_array.add(uv)
+ uv_array.add(uv_3ds)
vert_index+=1
# Make sure the triangle vertex indices now refer to the new vertex list:
- for tri, offset in zip(tri_list, offset_list):
+ for tri in tri_list:
for i in xrange(3):
- offset[i]+=index_list[tri.vertex_index[i]]
- tri.vertex_index = offset
+ tri.offset[i]+=index_list[tri.vertex_index[i]]
+ tri.vertex_index= tri.offset
return vert_array, uv_array, tri_list
@@ -644,7 +619,7 @@ def make_mesh_chunk(mesh):
# Extract the triangles from the mesh:
tri_list = extract_triangles(mesh)
- if (mesh.hasFaceUV()):
+ if mesh.faceUV:
# Remove the face UVs and convert it to vertex UV:
vert_array, uv_array, tri_list = remove_face_uv(mesh.verts, tri_list)
else:
@@ -653,7 +628,7 @@ def make_mesh_chunk(mesh):
for vert in mesh.verts:
vert_array.add(_3ds_point_3d(vert.co))
# If the mesh has vertex UVs, create an array of UVs:
- if (mesh.hasVertexUV()):
+ if mesh.vertexUV:
uv_array = _3ds_array()
for vert in mesh.verts:
uv_array.add(_3ds_point_uv(vert.uvco))
@@ -709,16 +684,29 @@ def make_track_chunk(ID, obj):
# Next section should be repeated for every keyframe, but for now, animation is not actually supported.
track_chunk.add_variable("tcb_frame", _3ds_int(0))
track_chunk.add_variable("tcb_flags", _3ds_short())
- if ID==POS_TRACK_TAG:
- # position vector:
- track_chunk.add_variable("position", _3ds_point_3d(obj.getLocation()))
- elif ID==ROT_TRACK_TAG:
- # rotation (quaternion, angle first, followed by axis):
- q = obj.getEuler().toQuat()
- track_chunk.add_variable("rotation", _3ds_point_4d((q.angle, q.axis[0], q.axis[1], q.axis[2])))
- elif ID==SCL_TRACK_TAG:
- # scale vector:
- track_chunk.add_variable("scale", _3ds_point_3d(obj.getSize()))
+ if obj.getType()=='Empty':
+ if ID==POS_TRACK_TAG:
+ # position vector:
+ track_chunk.add_variable("position", _3ds_point_3d(obj.getLocation()))
+ elif ID==ROT_TRACK_TAG:
+ # rotation (quaternion, angle first, followed by axis):
+ q = obj.getEuler().toQuat()
+ track_chunk.add_variable("rotation", _3ds_point_4d((q.angle, q.axis[0], q.axis[1], q.axis[2])))
+ elif ID==SCL_TRACK_TAG:
+ # scale vector:
+ track_chunk.add_variable("scale", _3ds_point_3d(obj.getSize()))
+ else:
+ # meshes have their transformations applied before
+ # exporting, so write identity transforms here:
+ if ID==POS_TRACK_TAG:
+ # position vector:
+ track_chunk.add_variable("position", _3ds_point_3d((0.0,0.0,0.0)))
+ elif ID==ROT_TRACK_TAG:
+ # rotation (quaternion, angle first, followed by axis):
+ track_chunk.add_variable("rotation", _3ds_point_4d((0.0, 1.0, 0.0, 0.0)))
+ elif ID==SCL_TRACK_TAG:
+ # scale vector:
+ track_chunk.add_variable("scale", _3ds_point_3d((1.0, 1.0, 1.0)))
return track_chunk
@@ -786,8 +774,9 @@ def make_kf_obj_node(obj, name_to_id):
def save_3ds(filename):
"""Save the Blender scene to a 3ds file."""
# Time the export
- time1 = Blender.sys.time()
-
+ time1= Blender.sys.time()
+ scn= Blender.Scene.GetCurrent()
+
# Initialize the main chunk (primary):
primary = _3ds_chunk(PRIMARY)
# Add version chunk:
@@ -801,45 +790,55 @@ def save_3ds(filename):
# init main key frame data chunk:
kfdata = make_kfdata()
- # Make chunks for all materials in the scene:
- for material in Material.Get():
+ # Get all the supported objects selected in this scene:
+ ob_sel= Blender.Object.GetSelected()
+ #getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None):
+ mesh_objects = [ (ob, BPyMesh.getMeshFromObject(ob, None, True, False, scn)) for ob in ob_sel if ob.getType() == 'Mesh' ]
+ empty_objects = [ ob for ob in ob_sel if ob.getType() == 'Empty' ]
+
+ # Make a list of all materials used in the selected meshes (use a dictionary,
+ # each material is added once):
+ materials = {}
+ for ob, data in mesh_objects:
+ for m in data.materials:
+ try:
+ materials[m.name]
+ except:
+ materials[m.name]= m
+
+ # Make material chunks for all materials used in the meshes:
+ for material in materials.itervalues():
object_info.add_subchunk(make_material_chunk(material))
-
- # Get all the supported objects in this scene
- mesh_objects = [ ob for ob in Blender.Object.Get() if ob.getType() == 'Mesh' ]
- empty_objects = [ ob for ob in Blender.Object.Get() if ob.getType() == 'Empty' ]
-
- all_objects = mesh_objects + empty_objects
-
# Give all objects a unique ID and build a dictionary from object name to object id:
name_to_id = {}
- for i,obj in enumerate(all_objects):
- name_to_id[obj.getName()] = i
+ for ob, data in mesh_objects:
+ name_to_id[ob.name]= len(name_to_id)
+ for ob in empty_objects:
+ name_to_id[ob.name]= len(name_to_id)
# Create object chunks for all meshes:
- for obj in mesh_objects:
- #create a new object chunk
+ for ob, blender_mesh in mesh_objects:
+ # create a new object chunk
object_chunk = _3ds_chunk(OBJECT)
- #get the mesh data
- blender_mesh = obj.getData()
- blender_mesh.transform(obj.getMatrix())
+ # transform the mesh:
+ blender_mesh.transform(ob.matrixWorld)
- #set the object name
- object_chunk.add_variable("name", _3ds_string(obj.getName()))
+ # set the object name
+ object_chunk.add_variable("name", _3ds_string(ob.name))
# make a mesh chunk out of the mesh:
object_chunk.add_subchunk(make_mesh_chunk(blender_mesh))
object_info.add_subchunk(object_chunk)
# make a kf object node for the object:
- kfdata.add_subchunk(make_kf_obj_node(obj, name_to_id))
+ kfdata.add_subchunk(make_kf_obj_node(ob, name_to_id))
# Create chunks for all empties:
- for obj in empty_objects:
+ for ob in empty_objects:
# Empties only require a kf object node:
- kfdata.add_subchunk(make_kf_obj_node(obj, name_to_id))
+ kfdata.add_subchunk(make_kf_obj_node(ob, name_to_id))
# Add main object info chunk to primary chunk:
primary.add_subchunk(object_info)
@@ -859,6 +858,11 @@ def save_3ds(filename):
# Close the file:
file.close()
+ # Free memory
+ for ob, blender_mesh in mesh_objects:
+ blender_mesh.verts= None
+
+
# Debugging only: report the exporting time:
print "3ds export time: %.2f" % (Blender.sys.time() - time1)