diff -r 2c154aad7f33 -r 303583d2fb97 demos/lworeader.py --- a/demos/lworeader.py Sat Apr 12 02:02:45 2008 +0200 +++ b/demos/lworeader.py Mon Apr 14 12:51:50 2008 +0200 @@ -1,5 +1,6 @@ # LightWave .lwo file loader +from math import * from struct import * from raytracer import Triangle, NormalVertex, Material @@ -46,7 +47,7 @@ (ID,size) = read_chunk(f) form = f.read(4) if (ID != 'FORM' or form != 'LWOB'): - print 'not lwo file' + print 'unknown format' return (ID,size) = read_chunk(f) while (ID != ''): @@ -74,10 +75,18 @@ size -= 2 surf = read_int2(f) size -= 2 - faces.append((inds[0], inds[1], inds[2], surf)) + if surf < 0: + # detail polygons + surf = abs(surf) + count = read_int2(f) + size -= 2 + # ... FIXME + #print size, vertex_count + if vertex_count >= 3: + faces.append([inds[0], inds[1], inds[2], surf]) i = 0 while (vertex_count > 3): - faces.append((inds[0], inds[2+i], inds[3+i], surf)) + faces.append([inds[0], inds[2+i], inds[3+i], surf]) vertex_count -= 1 i += 1 elif (ID == 'SURF'): @@ -90,29 +99,101 @@ if (subID == 'COLR'): col = f.read(subsize) surf['color'] = (unpack('BBB',col[:3])) + elif (subID == 'FLAG'): + flags = read_int2(f) + surf['luminous'] = (flags >> 0) & 1; + surf['outline'] = (flags >> 1) & 1; + surf['smooth'] = (flags >> 2) & 1; + surf['color-highlights'] = (flags >> 3) & 1; + surf['color-filter'] = (flags >> 4) & 1; + surf['opaque-edge'] = (flags >> 5) & 1; + surf['transparent-edge'] = (flags >> 6) & 1; + surf['sharp-terminator'] = (flags >> 7) & 1; + surf['double-sided'] = (flags >> 8) & 1; + surf['additive'] = (flags >> 9) & 1; + + # Base Shading (float) + elif (subID == 'VDIF'): + surf['diffuse'] = read_float4(f) + elif (subID == 'VSPC'): + surf['specular'] = read_float4(f) + elif (subID == 'VRFL'): + surf['reflection'] = read_float4(f) + elif (subID == 'VTRN'): + surf['transparency'] = read_float4(f) + + # Base Shading (short) + elif (subID == 'DIFF'): + if not surf.has_key('diffuse'): + surf['diffuse'] = read_int2(f)/255. + elif (subID == 'SPEC'): + if not surf.has_key('specular'): + surf['specular'] = read_int2(f)/255. + elif (subID == 'REFL'): + if not surf.has_key('reflection'): + surf['reflection'] = read_int2(f)/255. + elif (subID == 'TRAN'): + if not surf.has_key('transparency'): + surf['transparency'] = read_int2(f)/255. + + elif (subID == 'RIND'): + surf['refractive-index'] = read_float4(f) + elif (subID == 'GLOS'): + surf['glossiness'] = read_int2(f) + elif (subID == 'SMAN'): + surf['smoothing-max-angle'] = read_float4(f) else: - print "Warning:", subID,"("+str(subsize),"B) ignored" + print "Warning: SURF sub chunk", subID,"("+str(subsize),"B) ignored" f.read(subsize) size -= subsize surfaces.append(surf) else: - print "Warning:", ID,"("+str(size),"B) ignored" + print "Warning: chunk", ID,"("+str(size),"B) ignored" f.read(size) (ID,size) = read_chunk(f) return (points, faces, tags, surfaces) -def LoadLightwaveLwoFile(rt, filename, defmat, smooth, scale=(1,1,1), trans=(0,0,0)): +def dot(a,b): + sum = 0 + for i in range(min(len(a),len(b))): + sum += a[i]*b[i] + return sum + +def LoadLightwaveLwoFile(rt, filename, scale=(1,1,1), trans=(0,0,0)): if (type(scale) == float or type(scale) == int): scale = (scale,)*3 (points, faces, tags, surfaces) = read_lwo(filename) vertices = [] normals = [] - vertex_face_num = [] + vertex_faces = [] materials = [] for surf in surfaces: mat = Material(colour=tuple(float(x)/255. for x in surf['color'])) + if surf.has_key('smooth'): + mat.setSmooth(surf['smooth']) + diff = 1. + if surf.has_key('diffuse'): + diff = surf['diffuse'] + spec = 0. + if surf.has_key('specular'): + spec = surf['specular'] + gloss = 1.0 + if surf.has_key('glossiness'): + gloss = surf['glossiness'] + mat.setPhong(0.1, diff, spec, gloss) + refl = 0. + if surf.has_key('reflection'): + refl = surf['reflection'] + mat.setReflectivity(refl) + transp = 0. + if surf.has_key('transparency'): + transp = surf['transparency'] + rindex = 1.0 + if surf.has_key('refractive-index'): + rindex = surf['refractive-index'] + mat.setTransmissivity(transp, rindex) materials.append(mat) for point in points: @@ -121,26 +202,77 @@ v2 = scale[2]*point[2] + trans[2] vertices.append(NormalVertex((v2,v1,v0))) normals.append([0.,0.,0.]) - vertex_face_num.append(0) + vertex_faces.append([]) for f in faces: - v = [vertices[x] for x in f[0:3]] - matidx = f[3]-1 - face = Triangle(v[0], v[1], v[2], materials[matidx]) - n = face.getNormal() for x in f[0:3]: - for i in range(3): - normals[x][i] += n[i] - vertex_face_num[x] += 1 - if (smooth): - face.setSmooth() - rt.addshape(face) + vertex_faces[x].append(f) # interpolate normals at vertices num = 0 - for vf in vertex_face_num: - if (vertex_face_num[num] > 0): + for vfaces in vertex_faces: + vert = vertices[num] + edges = {} + N = [0,0,0] + for f in vfaces: + for fvert in f[0:3]: + if edges.has_key(str(fvert)): + edges[str(fvert)].append(f) + else: + edges[str(fvert)] = [f] + for f in vfaces: + vv = [vertices[x] for x in f[0:3]] + fN = Triangle(vv[0], vv[1], vv[2], materials[f[3]-1]).getNormal() for i in range(3): - normals[num][i] /= vertex_face_num[num] - vertices[num].setNormal(tuple(normals[num])) + N[i] += fN[i] + surf = surfaces[f[3]-1] + if not surf.has_key('smoothing-max-angle'): + continue + fNvert = list(fN) + Ncount = 1 + copy_vertex = False + for fvert in f[0:3]: + for ef in edges[str(fvert)]: + if ef == f: + continue + # f - ref. face; ef - other face + vv = [vertices[x] for x in ef[0:3]] + efN = Triangle(vv[0], vv[1], vv[2], materials[ef[3]-1]).getNormal() + d = dot(fN, efN) + if d > 1: + d = 1 + if d < -1: + d = -1 + if acos(d) < surf['smoothing-max-angle']: + for i in range(3): + fNvert[i] += efN[i] + Ncount += 1 + else: + copy_vertex = True + # here fNvert is normal for num'th vertex in face f + if copy_vertex: + for i in range(3): + fNvert[i] /= Ncount + new_vert = NormalVertex(vert) + new_vert.setNormal(tuple(fNvert)) + f.append(f[0]) + f.append(f[1]) + f.append(f[2]) + vertices.append(new_vert) + for i in range(3): + if f[i] == num: + f[i+4] = len(vertices)-1 + if (len(vfaces) > 0): + for i in range(3): + N[i] /= len(vfaces) + vertices[num].setNormal(tuple(N)) num += 1 + + for f in faces: + if len(f) > 4: + v = [vertices[x] for x in f[4:7]] + else: + v = [vertices[x] for x in f[0:3]] + matidx = f[3]-1 + face = Triangle(v[0], v[1], v[2], materials[matidx]) + rt.addshape(face)