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