demos/lworeader.py
branchpyrit
changeset 58 cfe98f5c0ae9
child 59 64e456ab823d
equal deleted inserted replaced
57:1e92c21b9a61 58:cfe98f5c0ae9
       
     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