demos/lworeader.py
branchpyrit
changeset 69 303583d2fb97
parent 65 242839c6d27d
child 72 7c3f38dff082
equal deleted inserted replaced
68:2c154aad7f33 69:303583d2fb97
     1 # LightWave .lwo file loader
     1 # LightWave .lwo file loader
     2 
     2 
       
     3 from math import *
     3 from struct import *
     4 from struct import *
     4 from raytracer import Triangle, NormalVertex, Material
     5 from raytracer import Triangle, NormalVertex, Material
     5 
     6 
     6 def read_int4(f):
     7 def read_int4(f):
     7 	return unpack('>i', f.read(4))[0]
     8 	return unpack('>i', f.read(4))[0]
    44 	surfaces = []
    45 	surfaces = []
    45 	f = file(filename, 'rb')
    46 	f = file(filename, 'rb')
    46 	(ID,size) = read_chunk(f)
    47 	(ID,size) = read_chunk(f)
    47 	form = f.read(4)
    48 	form = f.read(4)
    48 	if (ID != 'FORM' or form != 'LWOB'):
    49 	if (ID != 'FORM' or form != 'LWOB'):
    49 		print 'not lwo file'
    50 		print 'unknown format'
    50 		return
    51 		return
    51 	(ID,size) = read_chunk(f)
    52 	(ID,size) = read_chunk(f)
    52 	while (ID != ''):
    53 	while (ID != ''):
    53 		#print ID,size
    54 		#print ID,size
    54 		if (ID == 'PNTS'):
    55 		if (ID == 'PNTS'):
    72 					index = read_int2(f)
    73 					index = read_int2(f)
    73 					inds.append(index)
    74 					inds.append(index)
    74 					size -= 2
    75 					size -= 2
    75 				surf = read_int2(f)
    76 				surf = read_int2(f)
    76 				size -= 2
    77 				size -= 2
    77 				faces.append((inds[0], inds[1], inds[2], surf))
    78 				if surf < 0:
       
    79 					# detail polygons
       
    80 					surf = abs(surf)
       
    81 					count = read_int2(f)
       
    82 					size -= 2
       
    83 					# ... FIXME
       
    84 				#print size, vertex_count
       
    85 				if vertex_count >= 3:
       
    86 					faces.append([inds[0], inds[1], inds[2], surf])
    78 				i = 0
    87 				i = 0
    79 				while (vertex_count > 3):
    88 				while (vertex_count > 3):
    80 					faces.append((inds[0], inds[2+i], inds[3+i], surf))
    89 					faces.append([inds[0], inds[2+i], inds[3+i], surf])
    81 					vertex_count -= 1
    90 					vertex_count -= 1
    82 					i += 1
    91 					i += 1
    83 		elif (ID == 'SURF'):
    92 		elif (ID == 'SURF'):
    84 			(name,l) = read_string(f)
    93 			(name,l) = read_string(f)
    85 			size -= l
    94 			size -= l
    88 				(subID,subsize) = read_subchunk(f)
    97 				(subID,subsize) = read_subchunk(f)
    89 				size -= 6
    98 				size -= 6
    90 				if (subID == 'COLR'):
    99 				if (subID == 'COLR'):
    91 					col = f.read(subsize)
   100 					col = f.read(subsize)
    92 					surf['color'] = (unpack('BBB',col[:3]))
   101 					surf['color'] = (unpack('BBB',col[:3]))
       
   102 				elif (subID == 'FLAG'):
       
   103 					flags = read_int2(f)
       
   104 					surf['luminous'] = (flags >> 0) & 1;
       
   105 					surf['outline'] = (flags >> 1) & 1;
       
   106 					surf['smooth'] = (flags >> 2) & 1;
       
   107 					surf['color-highlights'] = (flags >> 3) & 1;
       
   108 					surf['color-filter'] = (flags >> 4) & 1;
       
   109 					surf['opaque-edge'] = (flags >> 5) & 1;
       
   110 					surf['transparent-edge'] = (flags >> 6) & 1;
       
   111 					surf['sharp-terminator'] = (flags >> 7) & 1;
       
   112 					surf['double-sided'] = (flags >> 8) & 1;
       
   113 					surf['additive'] = (flags >> 9) & 1;
       
   114 
       
   115 				# Base Shading (float)
       
   116 				elif (subID == 'VDIF'):
       
   117 					surf['diffuse'] = read_float4(f)
       
   118 				elif (subID == 'VSPC'):
       
   119 					surf['specular'] = read_float4(f)
       
   120 				elif (subID == 'VRFL'):
       
   121 					surf['reflection'] = read_float4(f)
       
   122 				elif (subID == 'VTRN'):
       
   123 					surf['transparency'] = read_float4(f)
       
   124 
       
   125 				# Base Shading (short)
       
   126 				elif (subID == 'DIFF'):
       
   127 					if not surf.has_key('diffuse'):
       
   128 						surf['diffuse'] = read_int2(f)/255.
       
   129 				elif (subID == 'SPEC'):
       
   130 					if not surf.has_key('specular'):
       
   131 						surf['specular'] = read_int2(f)/255.
       
   132 				elif (subID == 'REFL'):
       
   133 					if not surf.has_key('reflection'):
       
   134 						surf['reflection'] = read_int2(f)/255.
       
   135 				elif (subID == 'TRAN'):
       
   136 					if not surf.has_key('transparency'):
       
   137 						surf['transparency'] = read_int2(f)/255.
       
   138 
       
   139 				elif (subID == 'RIND'):
       
   140 					surf['refractive-index'] = read_float4(f)
       
   141 				elif (subID == 'GLOS'):
       
   142 					surf['glossiness'] = read_int2(f)
       
   143 				elif (subID == 'SMAN'):
       
   144 					surf['smoothing-max-angle'] = read_float4(f)
    93 				else:
   145 				else:
    94 					print "Warning:", subID,"("+str(subsize),"B) ignored"
   146 					print "Warning: SURF sub chunk", subID,"("+str(subsize),"B) ignored"
    95 					f.read(subsize)
   147 					f.read(subsize)
    96 				size -= subsize
   148 				size -= subsize
    97 			surfaces.append(surf)
   149 			surfaces.append(surf)
    98 		else:
   150 		else:
    99 			print "Warning:", ID,"("+str(size),"B) ignored"
   151 			print "Warning: chunk", ID,"("+str(size),"B) ignored"
   100 			f.read(size)
   152 			f.read(size)
   101 		(ID,size) = read_chunk(f)
   153 		(ID,size) = read_chunk(f)
   102 	return (points, faces, tags, surfaces)
   154 	return (points, faces, tags, surfaces)
   103 
   155 
   104 def LoadLightwaveLwoFile(rt, filename, defmat, smooth, scale=(1,1,1), trans=(0,0,0)):
   156 def dot(a,b):
       
   157 	sum = 0
       
   158 	for i in range(min(len(a),len(b))):
       
   159 		sum += a[i]*b[i]
       
   160 	return sum
       
   161 
       
   162 def LoadLightwaveLwoFile(rt, filename, scale=(1,1,1), trans=(0,0,0)):
   105 	if (type(scale) == float or type(scale) == int):
   163 	if (type(scale) == float or type(scale) == int):
   106 		scale = (scale,)*3
   164 		scale = (scale,)*3
   107 	(points, faces, tags, surfaces) = read_lwo(filename)
   165 	(points, faces, tags, surfaces) = read_lwo(filename)
   108 
   166 
   109 	vertices = []
   167 	vertices = []
   110 	normals = []
   168 	normals = []
   111 	vertex_face_num = []
   169 	vertex_faces = []
   112 	materials = []
   170 	materials = []
   113 
   171 
   114 	for surf in surfaces:
   172 	for surf in surfaces:
   115 		mat = Material(colour=tuple(float(x)/255. for x in surf['color']))
   173 		mat = Material(colour=tuple(float(x)/255. for x in surf['color']))
       
   174 		if surf.has_key('smooth'):
       
   175 			mat.setSmooth(surf['smooth'])
       
   176 		diff = 1.
       
   177 		if surf.has_key('diffuse'):
       
   178 			diff = surf['diffuse']
       
   179 		spec = 0.
       
   180 		if surf.has_key('specular'):
       
   181 			spec = surf['specular']
       
   182 		gloss = 1.0
       
   183 		if surf.has_key('glossiness'):
       
   184 			gloss = surf['glossiness']
       
   185 		mat.setPhong(0.1, diff, spec, gloss)
       
   186 		refl = 0.
       
   187 		if surf.has_key('reflection'):
       
   188 			refl = surf['reflection']
       
   189 		mat.setReflectivity(refl)
       
   190 		transp = 0.
       
   191 		if surf.has_key('transparency'):
       
   192 			transp = surf['transparency']
       
   193 		rindex = 1.0
       
   194 		if surf.has_key('refractive-index'):
       
   195 			rindex = surf['refractive-index']
       
   196 		mat.setTransmissivity(transp, rindex)
   116 		materials.append(mat)
   197 		materials.append(mat)
   117 
   198 
   118 	for point in points:
   199 	for point in points:
   119 		v0 = scale[0]*point[0] + trans[0]
   200 		v0 = scale[0]*point[0] + trans[0]
   120 		v1 = scale[1]*point[1] + trans[1]
   201 		v1 = scale[1]*point[1] + trans[1]
   121 		v2 = scale[2]*point[2] + trans[2]
   202 		v2 = scale[2]*point[2] + trans[2]
   122 		vertices.append(NormalVertex((v2,v1,v0)))
   203 		vertices.append(NormalVertex((v2,v1,v0)))
   123 		normals.append([0.,0.,0.])
   204 		normals.append([0.,0.,0.])
   124 		vertex_face_num.append(0)
   205 		vertex_faces.append([])
   125 
   206 
   126 	for f in faces:
   207 	for f in faces:
   127 		v = [vertices[x] for x in f[0:3]]
   208 		for x in f[0:3]:
       
   209 			vertex_faces[x].append(f)
       
   210 
       
   211 	# interpolate normals at vertices
       
   212 	num = 0
       
   213 	for vfaces in vertex_faces:
       
   214 		vert = vertices[num]
       
   215 		edges = {}
       
   216 		N = [0,0,0]
       
   217 		for f in vfaces:
       
   218 			for fvert in f[0:3]:
       
   219 				if edges.has_key(str(fvert)):
       
   220 					edges[str(fvert)].append(f)
       
   221 				else:
       
   222 					edges[str(fvert)] = [f]
       
   223 		for f in vfaces:
       
   224 			vv = [vertices[x] for x in f[0:3]]
       
   225 			fN = Triangle(vv[0], vv[1], vv[2], materials[f[3]-1]).getNormal()
       
   226 			for i in range(3):
       
   227 				N[i] += fN[i]
       
   228 			surf = surfaces[f[3]-1]
       
   229 			if not surf.has_key('smoothing-max-angle'):
       
   230 				continue
       
   231 			fNvert = list(fN)
       
   232 			Ncount = 1
       
   233 			copy_vertex = False
       
   234 			for fvert in f[0:3]:
       
   235 				for ef in edges[str(fvert)]:
       
   236 					if ef == f:
       
   237 						continue
       
   238 					# f - ref. face; ef - other face
       
   239 					vv = [vertices[x] for x in ef[0:3]]
       
   240 					efN = Triangle(vv[0], vv[1], vv[2], materials[ef[3]-1]).getNormal()
       
   241 					d = dot(fN, efN)
       
   242 					if d > 1:
       
   243 						d = 1
       
   244 					if d < -1:
       
   245 						d = -1
       
   246 					if acos(d) < surf['smoothing-max-angle']:
       
   247 						for i in range(3):
       
   248 							fNvert[i] += efN[i]
       
   249 						Ncount += 1
       
   250 					else:
       
   251 						copy_vertex = True
       
   252 			# here fNvert is normal for num'th vertex in face f
       
   253 			if copy_vertex:
       
   254 				for i in range(3):
       
   255 					fNvert[i] /= Ncount
       
   256 				new_vert = NormalVertex(vert)
       
   257 				new_vert.setNormal(tuple(fNvert))
       
   258 				f.append(f[0])
       
   259 				f.append(f[1])
       
   260 				f.append(f[2])
       
   261 				vertices.append(new_vert)
       
   262 				for i in range(3):
       
   263 					if f[i] == num:
       
   264 						f[i+4] = len(vertices)-1
       
   265 		if (len(vfaces) > 0):
       
   266 			for i in range(3):
       
   267 				N[i] /= len(vfaces)
       
   268 		vertices[num].setNormal(tuple(N))
       
   269 		num += 1
       
   270 
       
   271 	for f in faces:
       
   272 		if len(f) > 4:
       
   273 			v = [vertices[x] for x in f[4:7]]
       
   274 		else:
       
   275 			v = [vertices[x] for x in f[0:3]]
   128 		matidx = f[3]-1
   276 		matidx = f[3]-1
   129 		face = Triangle(v[0], v[1], v[2], materials[matidx])
   277 		face = Triangle(v[0], v[1], v[2], materials[matidx])
   130 		n = face.getNormal()
       
   131 		for x in f[0:3]:
       
   132 			for i in range(3):
       
   133 				normals[x][i] += n[i]
       
   134 			vertex_face_num[x] += 1
       
   135 		if (smooth):
       
   136 			face.setSmooth()
       
   137 		rt.addshape(face)
   278 		rt.addshape(face)
   138 
       
   139 	# interpolate normals at vertices
       
   140 	num = 0
       
   141 	for vf in vertex_face_num:
       
   142 		if (vertex_face_num[num] > 0):
       
   143 			for i in range(3):
       
   144 				normals[num][i] /= vertex_face_num[num]
       
   145 		vertices[num].setNormal(tuple(normals[num]))
       
   146 		num += 1