4
Name: 'TrueSpace (.cob)...'
7
Tooltip: 'Import TrueSpace Object File Format (.cob)'
10
__author__ = "Anthony D'Agostino (Scorpius)"
11
__url__ = ("blender", "elysiun",
12
"Author's homepage, http://www.redrival.com/scorpius")
13
__version__ = "Part of IOSuite 0.5"
16
This script imports TrueSpace files to Blender
18
TrueSpace is a commercial modeling and rendering application. The .cob
19
file format is composed of 'chunks,' is well defined, and easy to read and
20
write. It's very similar to LightWave's lwo format.
23
Execute this script from the "File->Import" menu and choose a TrueSpace
27
Meshes only. Supports UV Coordinates. COB files in ascii format can't be
31
Materials, and Vertex Color info will be ignored.
34
Triangulation of convex polygons works fine, and uses a very simple
35
fanning algorithm. Convex polygons (i.e., shaped like the letter "U")
36
require a different algorithm, and will be triagulated incorrectly.
39
There are a few differences between how Blender & TrueSpace represent
40
their objects' transformation matrices. Blender simply uses a 4x4 matrix,
41
and trueSpace splits it into the following two fields.
43
For the 'Local Axes' values: The x, y, and z-axis represent a simple
44
rotation matrix. This is equivalent to Blender's object matrix before
45
it was combined with the object's scaling matrix. Dividing each value by
46
the appropriate scaling factor (and transposing at the same time)
47
produces the original rotation matrix.
49
For the 'Current Position' values: This is equivalent to Blender's
50
object matrix except that the last row is omitted and the xyz location
51
is used in the last column. Binary format uses a 4x3 matrix, ascii
52
format uses a 4x4 matrix.
54
For Cameras: The matrix here gets a little confusing, and I'm not sure of
58
# $Id: truespace_import.py,v 1.6 2005/03/21 05:26:52 ianwill Exp $
60
# +---------------------------------------------------------+
61
# | Copyright (c) 2001 Anthony D'Agostino |
62
# | http://www.redrival.com/scorpius |
63
# | scorpius@netzero.com |
65
# | Released under the Blender Artistic Licence (BAL) |
66
# | Import Export Suite v0.5 |
67
# +---------------------------------------------------------+
68
# | Read and write Caligari trueSpace File Format (*.cob) |
69
# +---------------------------------------------------------+
71
import Blender, meshtools
72
import struct, chunk, os, cStringIO, time
74
# =======================
75
# === COB Chunk Class ===
76
# =======================
77
class CobChunk(chunk.Chunk):
78
def __init__(self, file, align = 0, bigendian = 0, inclheader = 0): #$ COB
80
self.align = align # whether to align to word (2-byte) boundaries
86
self.chunkname = file.read(4)
87
if len(self.chunkname) < 4:
89
self.major_ver, = struct.unpack(strflag+'h', file.read(2)) #$ COB
90
self.minor_ver, = struct.unpack(strflag+'h', file.read(2)) #$ COB
91
self.chunk_id, = struct.unpack(strflag+'l', file.read(4)) #$ COB
92
self.parent_id, = struct.unpack(strflag+'l', file.read(4)) #$ COB
94
self.chunksize = struct.unpack(strflag+'l', file.read(4))[0]
98
self.chunksize = self.chunksize - 20 #$ COB
101
self.offset = self.file.tell()
107
# ============================
108
# === Read COB File Header ===
109
# ============================
110
def read_header(file):
111
magic, = struct.unpack("<9s", file.read(9))
112
version, = struct.unpack("<6s", file.read(6))
113
format, = struct.unpack("<1c", file.read(1))
114
endian, = struct.unpack("<2s", file.read(2))
115
misc, = struct.unpack("13s", file.read(13))
116
newline, = struct.unpack("<1B", file.read(1))
119
# ========================================
120
# === Read PolH (Polygonal Data) Chunk ===
121
# ========================================
122
def read_polh(chunk):
123
data = cStringIO.StringIO(chunk.read())
124
oname = read_ObjectName(data)
125
local = read_LocalAxes(data)
126
crpos = read_CurrentPosition(data)
127
verts = read_VertexList(data)
128
uvcoords = read_UVCoords(data)
129
faces, facesuv = read_FaceList(data, chunk)
130
return verts, faces, oname, facesuv, uvcoords
132
# === Read Object Name ===
133
def read_ObjectName(data):
134
dupecount, namelen = struct.unpack("<hh", data.read(4))
135
objname = data.read(namelen)
136
if objname == '': objname = 'NoName'
137
if dupecount > 0: objname = objname + ', ' + `dupecount`
140
# === Read Local Axes ===
141
def read_LocalAxes(data):
142
location = struct.unpack("<fff", data.read(12))
145
row = struct.unpack("<fff", data.read(12))
146
#print "% f % f % f" % row
147
rotation_matrix.append(list(row))
149
rotation_matrix = meshtools.transpose(rotation_matrix)
151
# === Read Current Position ===
152
def read_CurrentPosition(data):
153
transformation_matrix=[]
155
row = struct.unpack("<ffff", data.read(16))
156
#print "% f % f % f % f" % row
157
transformation_matrix.append(list(row))
160
# === Read Vertex List ===
161
def read_VertexList(data):
163
numverts, = struct.unpack("<l", data.read(4))
164
for i in range(numverts):
165
if not i%100 and meshtools.show_progress:
166
Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts")
167
x, y, z = struct.unpack("<fff", data.read(12))
168
verts.append((y, -x, z))
171
# === Read UV Vertex List ===
172
def read_UVCoords(data):
174
numuvcoords, = struct.unpack("<l", data.read(4))
175
for i in range(numuvcoords):
176
if not i%100 and meshtools.show_progress:
177
Blender.Window.DrawProgressBar(float(i)/numuvcoords, "Reading UV Coords")
178
uv = struct.unpack("<ff", data.read(8))
181
#print "num uvcoords:", len(uvcoords)
182
#for i in range(len(uvcoords)): print "%.4f, %.4f" % uvcoords[i]
185
# === Read Face List ===
186
def read_FaceList(data, chunk):
187
faces = [] ; facesuv = []
188
numfaces, = struct.unpack("<l", data.read(4))
189
for i in range(numfaces):
190
if not i%100 and meshtools.show_progress:
191
Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces")
193
face_flags, numfaceverts = struct.unpack("<Bh", data.read(3))
195
if (face_flags & 0x08) == 0x08:
196
print "face #" + `i-1` + " contains a hole."
199
data.read(2) # Material Index
201
facev = [] ; faceuv = []
202
for j in range(numfaceverts):
203
index, uvidx = struct.unpack("<ll", data.read(8))
204
facev.append(index); faceuv.append(uvidx)
205
facev.reverse() ; faceuv.reverse()
206
faces.append(facev) ; facesuv.append(faceuv)
208
if chunk.minor_ver == 6:
209
DrawFlags, RadiosityQuality = struct.unpack("<lh", data.read(6))
210
if chunk.minor_ver == 8:
211
DrawFlags, = struct.unpack("<l", data.read(4))
213
return faces , facesuv
215
# =============================
216
# === Read trueSpace Format ===
217
# =============================
220
file = open(filename, "rb")
223
if read_header(file) == 'A':
224
print "Can't read ASCII format"
229
cobchunk = CobChunk(file)
232
if cobchunk.chunkname == "PolH":
233
verts, faces, objname, facesuv, uvcoords = read_polh(cobchunk)
234
meshtools.create_mesh(verts, faces, objname, facesuv, uvcoords)
237
object = Blender.Object.GetSelected()
238
obj = Blender.Object.Get(objname)
240
obj.rot = meshtools.mat2euler(rotation_matrix)
241
obj.size = (transformation_matrix[0][0]/rotation_matrix[0][0],
242
transformation_matrix[1][1]/rotation_matrix[1][1],
243
transformation_matrix[2][2]/rotation_matrix[2][2])
249
Blender.Window.DrawProgressBar(1.0, '') # clear progressbar
252
seconds = " in %.2f %s" % (end-start, "seconds")
253
message = "Successfully imported " + os.path.basename(filename) + seconds
254
meshtools.print_boxed(message)
255
#print "objname :", objname
256
#print "numverts:", len(verts)
257
#print "numfaces:", len(faces)
259
def fs_callback(filename):
262
Blender.Window.FileSelector(fs_callback, "Import COB")