58
|
1 |
# LightWave .lwo file loader
|
|
2 |
|
|
3 |
from struct import *
|
|
4 |
from raytracer import Triangle, NormalVertex
|
|
5 |
|
|
6 |
def read_int4(f):
|
|
7 |
return unpack('>i', f.read(4))[0]
|
|
8 |
|
|
9 |
def read_int2(f):
|
|
10 |
return unpack('>h', f.read(2))[0]
|
|
11 |
|
|
12 |
def read_float4(f):
|
|
13 |
return unpack('>f', f.read(4))[0]
|
|
14 |
|
|
15 |
def read_string(f):
|
|
16 |
res = ''
|
|
17 |
b = f.read(1)
|
|
18 |
l = 1
|
|
19 |
while ( b != '\0' ):
|
|
20 |
res += b
|
|
21 |
b = f.read(1)
|
|
22 |
l += 1
|
|
23 |
if (l % 2 != 0):
|
|
24 |
f.read(1)
|
|
25 |
l += 1
|
|
26 |
return (res,l)
|
|
27 |
|
|
28 |
def read_chunk(f):
|
|
29 |
ID = f.read(4)
|
|
30 |
if (ID == ''):
|
|
31 |
return ('',0)
|
|
32 |
size = read_int4(f)
|
|
33 |
return (ID, size)
|
|
34 |
|
|
35 |
def read_subchunk(f):
|
|
36 |
ID = f.read(4)
|
|
37 |
size = read_int2(f)
|
|
38 |
return (ID, size)
|
|
39 |
|
|
40 |
def read_lwo(filename):
|
|
41 |
points = []
|
|
42 |
faces = []
|
|
43 |
tags = []
|
|
44 |
surfaces = []
|
|
45 |
f = file(filename)
|
|
46 |
(ID,size) = read_chunk(f)
|
|
47 |
form = f.read(4)
|
|
48 |
if (ID != 'FORM' or form != 'LWOB'):
|
|
49 |
print 'not lwo file'
|
|
50 |
return
|
|
51 |
(ID,size) = read_chunk(f)
|
|
52 |
while (ID != ''):
|
|
53 |
#print ID,size
|
|
54 |
if (ID == 'PNTS'):
|
|
55 |
while (size > 0):
|
|
56 |
p1 = read_float4(f)
|
|
57 |
p2 = read_float4(f)
|
|
58 |
p3 = read_float4(f)
|
|
59 |
points.append((p1,p2,p3))
|
|
60 |
size -= 12
|
|
61 |
elif (ID == 'SRFS'):
|
|
62 |
while (size > 0):
|
|
63 |
(s,l) = read_string(f)
|
|
64 |
size -= l
|
|
65 |
tags.append(s)
|
|
66 |
elif (ID == 'POLS'):
|
|
67 |
while (size > 0):
|
|
68 |
vertex_count = read_int2(f)
|
|
69 |
size -= 2
|
|
70 |
inds = []
|
|
71 |
for i in range(vertex_count):
|
|
72 |
index = read_int2(f)
|
|
73 |
inds.append(index)
|
|
74 |
size -= 2
|
|
75 |
surf = read_int2(f)
|
|
76 |
size -= 2
|
|
77 |
faces.append((inds[0], inds[1], inds[2], surf))
|
|
78 |
i = 0
|
|
79 |
while (vertex_count > 3):
|
|
80 |
faces.append((inds[0], inds[2+i], inds[3+i], surf))
|
|
81 |
vertex_count -= 1
|
|
82 |
i += 1
|
|
83 |
elif (ID == 'SURF'):
|
|
84 |
(name,l) = read_string(f)
|
|
85 |
size -= l
|
|
86 |
surf = {}
|
|
87 |
while (size > 0):
|
|
88 |
(subID,subsize) = read_subchunk(f)
|
|
89 |
size -= 6
|
|
90 |
if (subID == 'COLR'):
|
|
91 |
col = f.read(subsize)
|
|
92 |
surf['color'] = (unpack('BBB',col[:3]))
|
|
93 |
else:
|
|
94 |
print "Warning:", subID,"("+str(subsize),"B) ignored"
|
|
95 |
f.read(subsize)
|
|
96 |
size -= subsize
|
|
97 |
surfaces.append(surf)
|
|
98 |
else:
|
|
99 |
print "Warning:", ID,"("+str(size),"B) ignored"
|
|
100 |
f.read(size)
|
|
101 |
(ID,size) = read_chunk(f)
|
|
102 |
return (points, faces, tags, surfaces)
|
|
103 |
|
|
104 |
def LoadLightwaveLwoFile(rt, filename, defmat, smooth, scale=(1,1,1), trans=(0,0,0)):
|
|
105 |
if (type(scale) == float or type(scale) == int):
|
|
106 |
scale = (scale,)*3
|
|
107 |
(points, faces, tags, surfaces) = read_lwo(filename)
|
|
108 |
|
|
109 |
vertices = []
|
|
110 |
normals = []
|
|
111 |
vertex_face_num = []
|
|
112 |
|
|
113 |
for point in points:
|
|
114 |
v0 = scale[0]*point[0] + trans[0]
|
|
115 |
v1 = scale[1]*point[1] + trans[1]
|
|
116 |
v2 = scale[2]*point[2] + trans[2]
|
|
117 |
vertices.append(NormalVertex((v2,v1,v0)))
|
|
118 |
normals.append([0.,0.,0.])
|
|
119 |
vertex_face_num.append(0)
|
|
120 |
|
|
121 |
|
|
122 |
for f in faces:
|
|
123 |
v = [vertices[x] for x in f[0:3]]
|
|
124 |
surf = f[3]
|
|
125 |
mat = defmat
|
|
126 |
face = Triangle(v[0], v[1], v[2], mat)
|
|
127 |
n = face.getNormal()
|
|
128 |
for x in f[0:3]:
|
|
129 |
for i in range(3):
|
|
130 |
normals[x][i] += n[i]
|
|
131 |
vertex_face_num[x] += 1
|
|
132 |
if (smooth):
|
|
133 |
face.setSmooth()
|
|
134 |
rt.addshape(face)
|
|
135 |
|
|
136 |
# interpolate normals at vertices
|
|
137 |
num = 0
|
|
138 |
for vf in vertex_face_num:
|
|
139 |
if (vertex_face_num[num] > 0):
|
|
140 |
for i in range(3):
|
|
141 |
normals[num][i] /= vertex_face_num[num]
|
|
142 |
vertices[num].setNormal(tuple(normals[num]))
|
|
143 |
num += 1
|