# HG changeset patch # User Radek Brich # Date 1208170310 -7200 # Node ID 303583d2fb97f3bc6262d12630fd831c4854ddd4 # Parent 2c154aad7f33216c2ce6f3a66cfb77677015bb47 move "smooth" attribute from Triangle to Material lwo reader enhancements - implement more chunk types, support for smoothing flag and SMAN (smoothing max. angle) diff -r 2c154aad7f33 -r 303583d2fb97 ccdemos/common_ply.h --- a/ccdemos/common_ply.h Sat Apr 12 02:02:45 2008 +0200 +++ b/ccdemos/common_ply.h Mon Apr 14 12:51:50 2008 +0200 @@ -59,7 +59,6 @@ f >> v1 >> v2 >> v3; face = new Triangle(vertices.at(v1), vertices.at(v3), vertices.at(v2), mat); rt.addshape(face); - face->setSmooth(); normals.at(v1) += face->getNormal(); vertex_face_num.at(v1)++; diff -r 2c154aad7f33 -r 303583d2fb97 ccdemos/realtime_bunny.cc --- a/ccdemos/realtime_bunny.cc Sat Apr 12 02:02:45 2008 +0200 +++ b/ccdemos/realtime_bunny.cc Mon Apr 14 12:51:50 2008 +0200 @@ -22,6 +22,7 @@ //rt.addlight(&light2); Material mat(Colour(0.9, 0.9, 0.9)); + mat.setSmooth(true); load_ply(rt, "../models/ply/bunny/bun_zipper.ply", &mat, Vector3(-29,29,29), Vector3(-1,-3,0)); rt.setCamera(&cam); diff -r 2c154aad7f33 -r 303583d2fb97 ccdemos/realtime_dragon.cc --- a/ccdemos/realtime_dragon.cc Sat Apr 12 02:02:45 2008 +0200 +++ b/ccdemos/realtime_dragon.cc Mon Apr 14 12:51:50 2008 +0200 @@ -22,6 +22,7 @@ //rt.addlight(&light2); Material mat(Colour(0.9, 0.9, 0.9)); + mat.setSmooth(true); load_ply(rt, "../models/ply/dragon/dragon_vrip.ply", &mat, Vector3(-29,29,-29), Vector3(0,-3.6,0)); rt.setCamera(&cam); diff -r 2c154aad7f33 -r 303583d2fb97 demos/buddha.py --- a/demos/buddha.py Sat Apr 12 02:02:45 2008 +0200 +++ b/demos/buddha.py Mon Apr 14 12:51:50 2008 +0200 @@ -9,8 +9,9 @@ rt = Raytracer() mat = Material(colour=(0.9, 0.9, 0.9)) +mat.setSmooth(True) LoadStanfordPlyFile(rt, "../models/ply/happy/happy_vrip_res2.ply", - mat, smooth=True, scale=20.0, trans=(0,-3,0)) + mat, scale=20.0, trans=(0,-3,0)) light = Light(position=(-5.0, 2.0, 8.0), colour=(0.9, 0.3, 0.6)) rt.addlight(light) diff -r 2c154aad7f33 -r 303583d2fb97 demos/bunny.py --- a/demos/bunny.py Sat Apr 12 02:02:45 2008 +0200 +++ b/demos/bunny.py Mon Apr 14 12:51:50 2008 +0200 @@ -12,8 +12,9 @@ mat = Material(colour=(0.9, 0.9, 0.9)) mat.setTransmissivity(0.8) +mat.setSmooth(True) LoadStanfordPlyFile(rt, "../models/ply/bunny/bun_zipper.ply", - mat, smooth=True, scale=(-29.0, 29.0, 29.0), trans=(-1,-2.5,-3)) + mat, scale=(-29.0, 29.0, 29.0), trans=(-1,-2.5,-3)) mat0 = Material(colour=(0.1, 0.2, 0.6)) box1 = Box(L=(-20.0, -1.7, -20.0), H=(20.0, -1.5, 20.0), material=mat0) diff -r 2c154aad7f33 -r 303583d2fb97 demos/car.py --- a/demos/car.py Sat Apr 12 02:02:45 2008 +0200 +++ b/demos/car.py Mon Apr 14 12:51:50 2008 +0200 @@ -7,16 +7,17 @@ rt = Raytracer() -cam = Camera(eye=(0.,5.,8.)) -rotx=0.3 +cam = Camera(eye=(0.,2.,8.)) +rotx=0.15 cam.rotate((cos(rotx),-sin(rotx),0.,0.)) rt.setcamera(cam) -mat = Material(colour=(0.9, 0.9, 0.9)) -LoadLightwaveLwoFile(rt, "../models/lwo/Nissan300ZX.lwo", mat, smooth=False, scale=0.4) +LoadLightwaveLwoFile(rt, "../models/lwo/Nissan300ZX.lwo", scale=0.4, trans=(-0.2,0,0.3)) -light = Light(position=(-5.0, 10.0, 8.0), colour=(0.9, 0.9, 0.9)) -rt.addlight(light) +light1 = Light(position=(-5.0, 20.0, 8.0), colour=(0.9, 0.9, 0.9)) +rt.addlight(light1) +light2 = Light(position=(5.0, 10.0, 10.0), colour=(0.9, 0.7, 0.7)) +rt.addlight(light2) imagesize = (800, 600) data = rt.render(imagesize) diff -r 2c154aad7f33 -r 303583d2fb97 demos/dragon.py --- a/demos/dragon.py Sat Apr 12 02:02:45 2008 +0200 +++ b/demos/dragon.py Mon Apr 14 12:51:50 2008 +0200 @@ -9,8 +9,9 @@ rt = Raytracer() mat = Material(colour=(0.9, 0.9, 0.9)) +mat.setSmooth(True) LoadStanfordPlyFile(rt, "../models/ply/dragon/dragon_vrip_res2.ply", - mat, smooth=True, scale=(-29.0, 29.0, -29.0), trans=(0.0, -3.6, 0.0)) + mat, scale=(-29.0, 29.0, -29.0), trans=(0.0, -3.6, 0.0)) light1 = Light(position=(-5.0, 2.0, 8.0), colour=(0.9, 0.3, 0.2)) rt.addlight(light1) 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) diff -r 2c154aad7f33 -r 303583d2fb97 demos/plyreader.py --- a/demos/plyreader.py Sat Apr 12 02:02:45 2008 +0200 +++ b/demos/plyreader.py Mon Apr 14 12:51:50 2008 +0200 @@ -2,7 +2,7 @@ from raytracer import Triangle, NormalVertex -def LoadStanfordPlyFile(rt, filename, mat, smooth, scale=(1,1,1), trans=(0,0,0)): +def LoadStanfordPlyFile(rt, filename, mat, scale=(1,1,1), trans=(0,0,0)): if (type(scale) == float or type(scale) == int): scale = (scale,)*3 vertices = [] @@ -44,8 +44,6 @@ for i in range(3): normals[int(x)][i] += n[i] vertex_face_num[int(x)] += 1 - if (smooth): - face.setSmooth() rt.addshape(face) face_num -= 1 diff -r 2c154aad7f33 -r 303583d2fb97 include/scene.h --- a/include/scene.h Sat Apr 12 02:02:45 2008 +0200 +++ b/include/scene.h Mon Apr 14 12:51:50 2008 +0200 @@ -132,12 +132,13 @@ { public: Colour colour; + Texture *texture; Float ambient, diffuse, specular, shininess; // Phong constants Float reflectivity; // how much reflective is the surface Float transmissivity, refract_index; // part of light which can be refracted; index of refraction - Texture *texture; + bool smooth; // triangle smoothing - Material(const Colour &acolour): colour(acolour), texture(NULL) + Material(const Colour &acolour): colour(acolour), texture(NULL), smooth(false) { ambient = 0.2; diffuse = 0.8; @@ -153,6 +154,7 @@ void setReflectivity(const Float refl) { reflectivity = refl; }; void setTransmissivity(const Float trans, const Float rindex) { transmissivity = trans; refract_index = rindex; }; + void setSmooth(bool sm) { smooth = sm; }; }; /** @@ -247,6 +249,7 @@ { public: Vector3 N; + NormalVertex(const NormalVertex *v): Vertex(v->P), N(v->N) {}; NormalVertex(const Vector3 &aP): Vertex(aP) {}; NormalVertex(const Vector3 &aP, const Vector3 &aN): Vertex(aP), N(aN) {}; const Vector3 &getNormal() { return N; }; @@ -271,7 +274,6 @@ Float pla[6], plb[6], plc[6]; #endif Vector3 N; - bool smooth; const Vector3 smooth_normal(const Vector3 &P) const { #ifdef TRI_BARI_PRE @@ -300,11 +302,8 @@ bool intersect(const Ray &ray, Float &dist) const; bool intersect_all(const Ray &ray, Float dist, vector &allts) const {return false;}; bool intersect_bbox(const BBox &bbox) const; - const Vector3 normal(const Vector3 &P) const { return (smooth ? smooth_normal(P) : N); }; + const Vector3 normal(const Vector3 &P) const { return (material->smooth ? smooth_normal(P) : N); }; const Vector3 getNormal() const { return N; }; - void setSmooth() { smooth = true; };//(typeid(*A) == typeid(*B) == typeid(*C) == typeid(NormalVertex)); }; - void setFlat() { smooth = false; }; - bool getSmooth() const { return smooth; }; BBox get_bbox() const; }; diff -r 2c154aad7f33 -r 303583d2fb97 src/raytracermodule.cc --- a/src/raytracermodule.cc Sat Apr 12 02:02:45 2008 +0200 +++ b/src/raytracermodule.cc Mon Apr 14 12:51:50 2008 +0200 @@ -248,6 +248,7 @@ static PyObject *Material_setPhong(PyObject* self, PyObject* args); static PyObject *Material_setReflectivity(PyObject* self, PyObject* args); static PyObject *Material_setTransmissivity(PyObject* self, PyObject* args); +static PyObject *Material_setSmooth(PyObject* self, PyObject* args); static PyTypeObject MaterialType = { PyObject_HEAD_INIT(NULL) @@ -272,6 +273,7 @@ {"setPhong", (PyCFunction)Material_setPhong, METH_VARARGS, "Set ambient, diffuse, specular and shininess Phong model constants."}, {"setReflectivity", (PyCFunction)Material_setReflectivity, METH_VARARGS, "Set reflectivity."}, {"setTransmissivity", (PyCFunction)Material_setTransmissivity, METH_VARARGS, "Set transmissivity and refraction index."}, + {"setSmooth", (PyCFunction)Material_setSmooth, METH_VARARGS, "Set triangle smoothing."}, {NULL, NULL} }; @@ -345,6 +347,20 @@ return Py_None; } +static PyObject* Material_setSmooth(PyObject* self, PyObject* args) +{ + int smooth; + + if (!PyArg_ParseTuple(args, "i", &smooth)) + return NULL; + + ((MaterialObject *)self)->material->setSmooth(smooth); + + Py_INCREF(Py_None); + return Py_None; +} + + //=========================== NormalVertex Object =========================== typedef struct { @@ -389,19 +405,27 @@ PyObject *TNor = NULL; Float vx, vy, vz, nx=0, ny=0, nz=0; - if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!|O!", kwdlist, - &PyTuple_Type, &TVer, &PyTuple_Type, &TNor)) - return NULL; - - if (!PyArg_ParseTuple(TVer, "fff", &vx, &vy, &vz)) + if (!PyArg_ParseTupleAndKeywords(args, kwd, "O|O!", kwdlist, + &TVer, &PyTuple_Type, &TNor)) return NULL; - if (TNor) - if (!PyArg_ParseTuple(TNor, "fff", &nx, &ny, &nz)) + if (!TNor && TVer->ob_type == &NormalVertexType) + { + v = PyObject_New(NormalVertexObject, &NormalVertexType); + v->nvertex = new NormalVertex(((NormalVertexObject*)TVer)->nvertex); + } + else + { + if (!PyArg_ParseTuple(TVer, "fff", &vx, &vy, &vz)) return NULL; - v = PyObject_New(NormalVertexObject, &NormalVertexType); - v->nvertex = new NormalVertex(Vector3(vx, vy, vz), Vector3(nx, ny, nz)); + if (TNor) + if (!PyArg_ParseTuple(TNor, "fff", &nx, &ny, &nz)) + return NULL; + + v = PyObject_New(NormalVertexObject, &NormalVertexType); + v->nvertex = new NormalVertex(Vector3(vx, vy, vz), Vector3(nx, ny, nz)); + } return (PyObject*)v; } @@ -580,7 +604,6 @@ static void Triangle_Destructor(PyObject* self); static PyObject *Triangle_Getattr(PyObject *self, char *name); static PyObject *Triangle_getNormal(PyObject* self, PyObject* args); -static PyObject *Triangle_setSmooth(PyObject* self, PyObject* args); static PyTypeObject TriangleType = { PyObject_HEAD_INIT(NULL) @@ -603,7 +626,6 @@ static PyMethodDef TriangleMethods[] = { {"getNormal", (PyCFunction)Triangle_getNormal, METH_NOARGS, "Get normal of whole triangle."}, - {"setSmooth", (PyCFunction)Triangle_setSmooth, METH_NOARGS, "Set the triangle smooth."}, {NULL, NULL} }; @@ -649,13 +671,6 @@ return obj; } -static PyObject* Triangle_setSmooth(PyObject* self, PyObject* args) -{ - ((TriangleObject *)self)->triangle->setSmooth(); - Py_INCREF(Py_None); - return Py_None; -} - //=========================== Raytracer Object =========================== typedef struct { diff -r 2c154aad7f33 -r 303583d2fb97 src/scene.cc --- a/src/scene.cc Sat Apr 12 02:02:45 2008 +0200 +++ b/src/scene.cc Mon Apr 14 12:51:50 2008 +0200 @@ -307,7 +307,7 @@ #endif Triangle::Triangle(Vertex *aA, Vertex *aB, Vertex *aC, Material *amaterial) - : smooth(false), A(aA), B(aB), C(aC) + : A(aA), B(aB), C(aC) { material = amaterial;