# HG changeset patch # User Radek Brich # Date 1197113865 -3600 # Node ID ffe83ca074f3416af55c205d32f2a487a1f86ae8 # Parent e9bb83c2b8b928a11da374647634d69b0e37d88f smooth triangles (aka Phong shading) extend Python binding to support vertex normals and smooth triangles make bunny.py and realtime_dragon smooth, and fix other demos for new triangle constructor add Vector::operator/= diff -r e9bb83c2b8b9 -r ffe83ca074f3 TODO --- a/TODO Fri Dec 07 16:39:42 2007 +0100 +++ b/TODO Sat Dec 08 12:37:45 2007 +0100 @@ -2,9 +2,8 @@ - optimize structures - optimize construction: do not use bounding boxes of shapes, instead implement box-shape intersection - save/load - * update Python binding, Camera, new classes + * update Python binding: Camera, new classes * more complex demos - * check/update triangle routines * namespace New Classes? diff -r e9bb83c2b8b9 -r ffe83ca074f3 ccdemos/realtime_dragon.cc --- a/ccdemos/realtime_dragon.cc Fri Dec 07 16:39:42 2007 +0100 +++ b/ccdemos/realtime_dragon.cc Sat Dec 08 12:37:45 2007 +0100 @@ -13,7 +13,9 @@ void load_ply(const char *filename, Material *mat, Float scale) { - vector vertices; + vector vertices; + vector normals; + vector vertex_face_num; ifstream f(filename); string token = "a"; if (!f.is_open()) @@ -37,19 +39,22 @@ } // read vertices - Vector3 v; - while (vertex_num--) + Vector3 P; + int num = vertex_num; + while (num--) { - f >> v.x >> v.y >> v.z; - v.x = -scale*v.x; - v.y = scale*v.y - 3.6; - v.z = -scale*v.z; - vertices.push_back(v); + f >> P.x >> P.y >> P.z; + P.x = -scale*P.x; + P.y = scale*P.y - 3.6; + P.z = -scale*P.z; + vertices.push_back(new NormalVertex(P)); + normals.push_back(Vector3()); + vertex_face_num.push_back(0); } // read faces Triangle *face; - int num, v1, v2, v3; + int v1, v2, v3; while (face_num--) { f >> num; @@ -61,6 +66,21 @@ f >> v1 >> v2 >> v3; face = new Triangle(vertices.at(v1), vertices.at(v2), vertices.at(v3), mat); rt.addshape(face); + face->setSmooth(); + + normals.at(v1) += face->getNormal(); + vertex_face_num.at(v1)++; + normals.at(v2) += face->getNormal(); + vertex_face_num.at(v2)++; + normals.at(v3) += face->getNormal(); + vertex_face_num.at(v3)++; + } + + for (int i; i < vertex_num; i++) + { + normals.at(i) /= vertex_face_num.at(i); + normals.at(i).normalize(); + vertices.at(i)->N = normals.at(i); } f.close(); @@ -119,7 +139,7 @@ /* initialize raytracer and prepare scene */ render_buffer = (Float *) malloc(w*h*3*sizeof(Float)); - rt.setThreads(2); + rt.setThreads(1); rt.setMaxDepth(3); KdTree top; diff -r e9bb83c2b8b9 -r ffe83ca074f3 demos/buddha.py --- a/demos/buddha.py Fri Dec 07 16:39:42 2007 +0100 +++ b/demos/buddha.py Sat Dec 08 12:37:45 2007 +0100 @@ -36,7 +36,7 @@ if (tokens[0] != "3"): print "ply warning: faces of %d vertices not supported" % tokens[0] f = [vertices[int(x)] for x in tokens[1:4]] - face = Triangle(f[0], f[1], f[2], mat) + face = Triangle(NormalVertex(f[0]), NormalVertex(f[1]), NormalVertex(f[2]), mat) rt.addshape(face) face_num -= 1 diff -r e9bb83c2b8b9 -r ffe83ca074f3 demos/bunny.py --- a/demos/bunny.py Fri Dec 07 16:39:42 2007 +0100 +++ b/demos/bunny.py Sat Dec 08 12:37:45 2007 +0100 @@ -6,11 +6,13 @@ import sys sys.path.append(open('ModulePath').read().strip()) -from raytracer import Raytracer, Light, Sphere, Triangle, Material +from raytracer import Raytracer, Light, Sphere, Triangle, NormalVertex, Material import Image def LoadStanfordPlyFile(rt, mat, filename, scale): vertices = [] + normals = [] + vertex_face_num = [] fp = file(filename) # read header tokens = (0,) @@ -23,27 +25,45 @@ face_num = int(tokens[2]) # read vertices - while (vertex_num): + num = vertex_num + while (num): tokens = fp.readline().split() v = [scale*float(x) for x in tokens[0:3]] v[0] = -v[0]-1 v[1] = v[1]-3 - vertices.append(tuple(v)) - vertex_num -= 1 + vertices.append(NormalVertex(tuple(v))) + normals.append([0.,0.,0.]) + vertex_face_num.append(0) + num -= 1 # read faces while (face_num): tokens = fp.readline().split() if (tokens[0] != "3"): print "ply warning: faces of %d vertices not supported" % tokens[0] - f = [vertices[int(x)] for x in tokens[1:4]] - face = Triangle(f[0], f[2], f[1], mat) + v = [vertices[int(x)] for x in tokens[1:4]] + face = Triangle(v[0], v[2], v[1], mat) + n = face.getNormal() + for x in tokens[1:4]: + for i in range(3): + normals[int(x)][i] += n[i] + vertex_face_num[int(x)] += 1 + face.setSmooth() rt.addshape(face) face_num -= 1 + # interpolate normals at vertices + num = 0 + while (num < vertex_num): + if (vertex_face_num[num] > 0): + for i in range(3): + normals[num][i] /= vertex_face_num[num] + vertices[num].setNormal(tuple(normals[num])) + num += 1 + rt = Raytracer() mat = Material(colour=(0.9, 0.9, 0.9)) -LoadStanfordPlyFile(rt, mat, "../models/bunny/bun_zipper_res3.ply", 29.0) +LoadStanfordPlyFile(rt, mat, "../models/bunny/bun_zipper.ply", 29.0) light = Light(position=(-5.0, 2.0, 10.0), colour=(0.9, 0.3, 0.6)) rt.addlight(light) diff -r e9bb83c2b8b9 -r ffe83ca074f3 demos/dragon.py --- a/demos/dragon.py Fri Dec 07 16:39:42 2007 +0100 +++ b/demos/dragon.py Sat Dec 08 12:37:45 2007 +0100 @@ -38,13 +38,13 @@ if (tokens[0] != "3"): print "ply warning: faces of %d vertices not supported" % tokens[0] f = [vertices[int(x)] for x in tokens[1:4]] - face = Triangle(f[0], f[1], f[2], mat) + face = Triangle(NormalVertex(f[0]), NormalVertex(f[1]), NormalVertex(f[2]), mat) rt.addshape(face) face_num -= 1 rt = Raytracer() mat = Material(colour=(0.9, 0.9, 0.9)) -LoadStanfordPlyFile(rt, mat, "../models/dragon/dragon_vrip_res4.ply", 29.0) +LoadStanfordPlyFile(rt, mat, "../models/dragon/dragon_vrip_res2.ply", 29.0) light1 = Light(position=(-5.0, 2.0, 8.0), colour=(0.9, 0.3, 0.2)) rt.addlight(light1) diff -r e9bb83c2b8b9 -r ffe83ca074f3 demos/triangles_monkey.py --- a/demos/triangles_monkey.py Fri Dec 07 16:39:42 2007 +0100 +++ b/demos/triangles_monkey.py Sat Dec 08 12:37:45 2007 +0100 @@ -19,7 +19,7 @@ vertices.append(tuple(v)) if ln[0] == "f": f = [vertices[int(x)-1] for x in ln[1:4]] - face = Triangle(f[0], f[1], f[2], mat) + face = Triangle(NormalVertex(f[0]), NormalVertex(f[1]), NormalVertex(f[2]), mat) rt.addshape(face) rt = Raytracer() diff -r e9bb83c2b8b9 -r ffe83ca074f3 demos/triangles_sphere.py --- a/demos/triangles_sphere.py Fri Dec 07 16:39:42 2007 +0100 +++ b/demos/triangles_sphere.py Sat Dec 08 12:37:45 2007 +0100 @@ -3,7 +3,7 @@ import sys sys.path.append(open('ModulePath').read().strip()) -from raytracer import Raytracer, Light, Sphere, Triangle, Material +from raytracer import Raytracer, Light, Sphere, Triangle, NormalVertex, Material import Image def LoadWavefrontObjFile(rt, mat, filename): @@ -19,7 +19,7 @@ vertices.append(tuple(v)) if ln[0] == "f": f = [vertices[int(x)-1] for x in ln[1:4]] - face = Triangle(f[0], f[1], f[2], mat) + face = Triangle(NormalVertex(f[0]), NormalVertex(f[1]), NormalVertex(f[2]), mat) rt.addshape(face) rt = Raytracer() diff -r e9bb83c2b8b9 -r ffe83ca074f3 include/scene.h --- a/include/scene.h Fri Dec 07 16:39:42 2007 +0100 +++ b/include/scene.h Sat Dec 08 12:37:45 2007 +0100 @@ -9,6 +9,7 @@ #define SCENE_H #include +#include #include "noise.h" #include "vector.h" @@ -156,7 +157,7 @@ virtual bool intersect_all(const Ray &ray, Float dist, vector &allts) const = 0; // normal at point P - virtual Vector3 normal(Vector3 &P) const = 0; + virtual const Vector3 normal(const Vector3 &P) const = 0; virtual BBox get_bbox() const = 0; }; @@ -178,7 +179,7 @@ center(acenter), radius(aradius) { material = amaterial; } bool intersect(const Ray &ray, Float &dist) const; bool intersect_all(const Ray &ray, Float dist, vector &allts) const; - Vector3 normal(Vector3 &P) const { return (P - center) * inv_radius; }; + const Vector3 normal(const Vector3 &P) const { return (P - center) * inv_radius; }; BBox get_bbox() const; }; @@ -196,10 +197,28 @@ }; bool intersect(const Ray &ray, Float &dist) const; bool intersect_all(const Ray &ray, Float dist, vector &allts) const { return false; }; - Vector3 normal(Vector3 &P) const; + const Vector3 normal(const Vector3 &P) const; BBox get_bbox() const { return BBox(L, H); }; }; +class Vertex +{ +public: + Vector3 P; + Vertex(const Vector3 &aP): P(aP) {}; +}; + +class NormalVertex: public Vertex +{ +public: + Vector3 N; + NormalVertex(const Vector3 &aP): Vertex(aP) {}; + NormalVertex(const Vector3 &aP, const Vector3 &aN): Vertex(aP), N(aN) {}; + const Vector3 &getNormal() { return N; }; + void setNormal(const Vector3 &aN) { N = aN; }; +}; + + class Triangle: public Shape { #ifdef TRI_BARI_PRE @@ -214,13 +233,39 @@ #ifdef TRI_PLUCKER Float pla[6], plb[6], plc[6]; #endif + Vector3 N; + bool smooth; + const Vector3 smooth_normal(const Vector3 &P) const + { +#ifdef TRI_BARI_PRE + const Vector3 &NA = static_cast(A)->N; + const Vector3 &NB = static_cast(B)->N; + const Vector3 &NC = static_cast(C)->N; + static const int modulo3[5] = {0,1,2,0,1}; + register const int ku = modulo3[k+1]; + register const int kv = modulo3[k+2]; + const Float pu = P[ku] - A->P[ku]; + const Float pv = P[kv] - A->P[kv]; + const Float u = pv * bnu + pu * bnv; + const Float v = pu * cnv + pv * cnu; + Vector3 n = NA + u * (NB - NA) + v * (NC - NA); + n.normalize(); + return n; +#else + return N; // not implemented for other algorithms +#endif + }; public: - Vector3 A, B, C, N; + Vertex *A, *B, *C; - Triangle(const Vector3 &aA, const Vector3 &aB, const Vector3 &aC, Material *amaterial); + Triangle(Vertex *aA, Vertex *aB, Vertex *aC, Material *amaterial); bool intersect(const Ray &ray, Float &dist) const; bool intersect_all(const Ray &ray, Float dist, vector &allts) const {return false;}; - Vector3 normal(Vector3 &) const { return N; }; + const Vector3 normal(const Vector3 &P) const { return (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 e9bb83c2b8b9 -r ffe83ca074f3 include/vector.h --- a/include/vector.h Fri Dec 07 16:39:42 2007 +0100 +++ b/include/vector.h Sat Dec 08 12:37:45 2007 +0100 @@ -69,6 +69,15 @@ return *this; }; + // cut + Vector3 operator/=(const Float &f) + { + x /= f; + y /= f; + z /= f; + return *this; + }; + // sum friend Vector3 operator+(const Vector3 &a, const Vector3 &b) { diff -r e9bb83c2b8b9 -r ffe83ca074f3 src/container.cc --- a/src/container.cc Fri Dec 07 16:39:42 2007 +0100 +++ b/src/container.cc Sat Dec 08 12:37:45 2007 +0100 @@ -3,29 +3,29 @@ void Container::addShape(Shape* aShape) { - shapes.push_back(aShape); - if (shapes.size() == 0) { - /* initialize bounding box */ - bbox = aShape->get_bbox(); - } else { - /* adjust bounding box */ - BBox shapebb = aShape->get_bbox(); - if (shapebb.L.x < bbox.L.x) bbox.L.x = shapebb.L.x; - if (shapebb.L.y < bbox.L.y) bbox.L.y = shapebb.L.y; - if (shapebb.L.z < bbox.L.z) bbox.L.z = shapebb.L.z; - if (shapebb.H.x > bbox.H.x) bbox.H.x = shapebb.H.x; - if (shapebb.H.y > bbox.H.y) bbox.H.y = shapebb.H.y; - if (shapebb.H.z > bbox.H.z) bbox.H.z = shapebb.H.z; - } + shapes.push_back(aShape); + if (shapes.size() == 0) { + /* initialize bounding box */ + bbox = aShape->get_bbox(); + } else { + /* adjust bounding box */ + BBox shapebb = aShape->get_bbox(); + if (shapebb.L.x < bbox.L.x) bbox.L.x = shapebb.L.x; + if (shapebb.L.y < bbox.L.y) bbox.L.y = shapebb.L.y; + if (shapebb.L.z < bbox.L.z) bbox.L.z = shapebb.L.z; + if (shapebb.H.x > bbox.H.x) bbox.H.x = shapebb.H.x; + if (shapebb.H.y > bbox.H.y) bbox.H.y = shapebb.H.y; + if (shapebb.H.z > bbox.H.z) bbox.H.z = shapebb.H.z; + } }; Shape *Container::nearest_intersection(const Shape *origin_shape, const Ray &ray, Float &nearest_distance) { - Shape *nearest_shape = NULL; - ShapeList::iterator shape; - for (shape = shapes.begin(); shape != shapes.end(); shape++) - if (*shape != origin_shape && (*shape)->intersect(ray, nearest_distance)) - nearest_shape = *shape; - return nearest_shape; + Shape *nearest_shape = NULL; + ShapeList::iterator shape; + for (shape = shapes.begin(); shape != shapes.end(); shape++) + if (*shape != origin_shape && (*shape)->intersect(ray, nearest_distance)) + nearest_shape = *shape; + return nearest_shape; } diff -r e9bb83c2b8b9 -r ffe83ca074f3 src/kdtree.cc --- a/src/kdtree.cc Fri Dec 07 16:39:42 2007 +0100 +++ b/src/kdtree.cc Sat Dec 08 12:37:45 2007 +0100 @@ -183,13 +183,13 @@ return; } -#if 0 +#if 1 // export kd-tree as .obj for visualization // this would be hard to reconstruct later static ofstream F("kdtree.obj"); Vector3 v; static int f=0; - v.cell[axis] = splitpos->pos; + v.cell[axis] = split; v.cell[(axis+1)%3] = bbox.L.cell[(axis+1)%3]; v.cell[(axis+2)%3] = bbox.L.cell[(axis+2)%3]; F << "v " << v.x << " " << v.y << " " << v.z << endl; diff -r e9bb83c2b8b9 -r ffe83ca074f3 src/raytracermodule.cc --- a/src/raytracermodule.cc Fri Dec 07 16:39:42 2007 +0100 +++ b/src/raytracermodule.cc Sat Dec 08 12:37:45 2007 +0100 @@ -139,8 +139,9 @@ &PyTuple_Type, &TCol)) return NULL; - if (!PyArg_ParseTuple(TCol, "fff", &cr, &cg, &cb)) - return NULL; + if (TCol) + if (!PyArg_ParseTuple(TCol, "fff", &cr, &cg, &cb)) + return NULL; v = PyObject_New(MaterialObject, &MaterialType); v->material = new Material(Colour(cr, cg, cb)); @@ -158,6 +159,94 @@ return Py_FindMethod(MaterialMethods, self, name); } +//=========================== NormalVertex Object =========================== + +typedef struct { + PyObject_HEAD + NormalVertex *nvertex; +} NormalVertexObject; + +static PyObject *NormalVertex_Constructor(PyObject* self, PyObject* args, PyObject *kwd); +static void NormalVertex_Destructor(PyObject* self); +static PyObject *NormalVertex_Getattr(PyObject *self, char *name); +static PyObject *NormalVertex_setNormal(PyObject* self, PyObject* args); + +static PyTypeObject NormalVertexType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "NormalVertex", /*tp_name*/ + sizeof(NormalVertexObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + NormalVertex_Destructor, /*tp_dealloc*/ + 0, /*tp_print*/ + NormalVertex_Getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ +}; + +static PyMethodDef NormalVertexMethods[] = { + {"setNormal", (PyCFunction)NormalVertex_setNormal, METH_VARARGS, "Set normal of this vertex."}, + {NULL, NULL} +}; + +static PyObject* NormalVertex_Constructor(PyObject* self, PyObject* args, PyObject *kwd) +{ + NormalVertexObject *v; + static char *kwdlist[] = {"vector", "normal", NULL}; + PyObject *TVer = NULL; + 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)) + return NULL; + + 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; +} + +static void NormalVertex_Destructor(PyObject* self) +{ + delete ((NormalVertexObject *)self)->nvertex; + PyObject_Del(self); +} + +static PyObject *NormalVertex_Getattr(PyObject *self, char *name) +{ + return Py_FindMethod(NormalVertexMethods, self, name); +} + +static PyObject *NormalVertex_setNormal(PyObject* self, PyObject* args) +{ + PyObject *TNor = NULL; + Float nx, ny, nz; + + if (!PyArg_ParseTuple(args, "O!", &PyTuple_Type, &TNor)) + return NULL; + + if (!PyArg_ParseTuple(TNor, "fff", &nx, &ny, &nz)) + return NULL; + + ((NormalVertexObject *)self)->nvertex->setNormal(Vector3(nx,ny,nz).normalize()); + + Py_INCREF(Py_None); + return Py_None; +} + //=========================== Sphere Object =========================== typedef struct { @@ -298,12 +387,14 @@ typedef struct { PyObject_HEAD - Triangle *shape; + Triangle *triangle; } TriangleObject; static PyObject *Triangle_Constructor(PyObject* self, PyObject* args, PyObject *kwd); 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) @@ -325,6 +416,8 @@ }; 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} }; @@ -333,33 +426,25 @@ TriangleObject *v; MaterialObject *material; static char *kwdlist[] = {"A", "B", "C", "material", NULL}; - PyObject *A = NULL, *B = NULL, *C = NULL; - Float ax, ay, az, bx, by, bz, cx, cy, cz; + NormalVertexObject *A, *B, *C; if (!PyArg_ParseTupleAndKeywords(args, kwd, "O!O!O!O!", kwdlist, - &PyTuple_Type, &A, &PyTuple_Type, &B, &PyTuple_Type, &C, + &NormalVertexType, &A, &NormalVertexType, &B, &NormalVertexType, &C, &MaterialType, &material)) return NULL; - if (!PyArg_ParseTuple(A, "fff", &ax, &ay, &az)) - return NULL; - - if (!PyArg_ParseTuple(B, "fff", &bx, &by, &bz)) - return NULL; - - if (!PyArg_ParseTuple(C, "fff", &cx, &cy, &cz)) - return NULL; - v = PyObject_New(TriangleObject, &TriangleType); - v->shape = new Triangle(Vector3(ax, ay, az), Vector3(bx, by, bz), - Vector3(cx, cy, cz), material->material); + v->triangle = new Triangle(A->nvertex, B->nvertex, C->nvertex, material->material); Py_INCREF(material); + Py_INCREF(A); + Py_INCREF(B); + Py_INCREF(C); return (PyObject*)v; } static void Triangle_Destructor(PyObject* self) { - delete ((TriangleObject *)self)->shape; + delete ((TriangleObject *)self)->triangle; PyObject_Del(self); } @@ -368,6 +453,23 @@ return Py_FindMethod(TriangleMethods, self, name); } +static PyObject* Triangle_getNormal(PyObject* self, PyObject* args) +{ + PyObject *obj; + + Vector3 N = ((TriangleObject *)self)->triangle->getNormal(); + + obj = Py_BuildValue("(fff)", N.x, N.y, N.z); + 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 { @@ -532,6 +634,8 @@ METH_VARARGS | METH_KEYWORDS, "Light source object constructor."}, {"Material", (PyCFunction) Material_Constructor, METH_VARARGS | METH_KEYWORDS, "Material object constructor."}, + {"NormalVertex", (PyCFunction) NormalVertex_Constructor, + METH_VARARGS | METH_KEYWORDS, "NormalVertex object constructor."}, {"Sphere", (PyCFunction) Sphere_Constructor, METH_VARARGS | METH_KEYWORDS, "Sphere object constructor."}, {"Box", (PyCFunction) Box_Constructor, diff -r e9bb83c2b8b9 -r ffe83ca074f3 src/scene.cc --- a/src/scene.cc Fri Dec 07 16:39:42 2007 +0100 +++ b/src/scene.cc Sat Dec 08 12:37:45 2007 +0100 @@ -165,7 +165,7 @@ return false; } -Vector3 Box::normal(Vector3 &P) const +const Vector3 Box::normal(const Vector3 &P) const { Vector3 N; for (int i = 0; i < 3; i++) @@ -203,22 +203,22 @@ } #endif -Triangle::Triangle(const Vector3 &aA, const Vector3 &aB, const Vector3 &aC, Material *amaterial) - : A(aA), B(aB), C(aC) +Triangle::Triangle(Vertex *aA, Vertex *aB, Vertex *aC, Material *amaterial) + : smooth(false), A(aA), B(aB), C(aC) { material = amaterial; material->reflection = 0; - const Vector3 c = B - A; - const Vector3 b = C - A; + const Vector3 c = B->P - A->P; + const Vector3 b = C->P - A->P; - N = -cross(c, b); + N = cross(c, b); N.normalize(); #ifdef TRI_PLUCKER - Plucker(B,C,pla); - Plucker(C,A,plb); - Plucker(A,B,plc); + Plucker(B->P,C->P,pla); + Plucker(C->P,A->P,plb); + Plucker(A->P,B->P,plc); #endif #if defined(TRI_BARI) || defined(TRI_BARI_PRE) @@ -244,7 +244,7 @@ Float krec = 1.0 / N[k]; nu = N[u] * krec; nv = N[v] * krec; - nd = dot(N, A) * krec; + nd = dot(N, A->P) * krec; // first line equation Float reci = 1.0f / (b[u] * c[v] - b[v] * c[u]); @@ -269,7 +269,7 @@ const bool side2 = Side(plr, plc) >= 0.0; if (side0 != side2) return false; - const Float t = - dot( (ray.o-A), N) / dot(ray.dir,N); + const Float t = - dot( (ray.o - A->P), N) / dot(ray.dir,N); if(t <= Eps || t >= dist) return false; dist = t; @@ -289,15 +289,15 @@ if (t >= dist || t < Eps) return false; - const Float hu = O[u] + t * D[u] - A[u]; - const Float hv = O[v] + t * D[v] - A[v]; + const Float hu = O[u] + t * D[u] - A->P[u]; + const Float hv = O[v] + t * D[v] - A->P[v]; const Float beta = hv * bnu + hu * bnv; if (beta < 0.) return false; const Float gamma = hu * cnv + hv * cnu; - if (gamma < 0. || beta + gamma > 1) + if (gamma < 0. || beta + gamma > 1.) return false; dist = t; @@ -333,19 +333,19 @@ BBox Triangle::get_bbox() const { BBox bbox = BBox(); - bbox.L = A; - if (B.x < bbox.L.x) bbox.L.x = B.x; - if (C.x < bbox.L.x) bbox.L.x = C.x; - if (B.y < bbox.L.y) bbox.L.y = B.y; - if (C.y < bbox.L.y) bbox.L.y = C.y; - if (B.z < bbox.L.z) bbox.L.z = B.z; - if (C.z < bbox.L.z) bbox.L.z = C.z; - bbox.H = A; - if (B.x > bbox.H.x) bbox.H.x = B.x; - if (C.x > bbox.H.x) bbox.H.x = C.x; - if (B.y > bbox.H.y) bbox.H.y = B.y; - if (C.y > bbox.H.y) bbox.H.y = C.y; - if (B.z > bbox.H.z) bbox.H.z = B.z; - if (C.z > bbox.H.z) bbox.H.z = C.z; + bbox.L = A->P; + if (B->P.x < bbox.L.x) bbox.L.x = B->P.x; + if (C->P.x < bbox.L.x) bbox.L.x = C->P.x; + if (B->P.y < bbox.L.y) bbox.L.y = B->P.y; + if (C->P.y < bbox.L.y) bbox.L.y = C->P.y; + if (B->P.z < bbox.L.z) bbox.L.z = B->P.z; + if (C->P.z < bbox.L.z) bbox.L.z = C->P.z; + bbox.H = A->P; + if (B->P.x > bbox.H.x) bbox.H.x = B->P.x; + if (C->P.x > bbox.H.x) bbox.H.x = C->P.x; + if (B->P.y > bbox.H.y) bbox.H.y = B->P.y; + if (C->P.y > bbox.H.y) bbox.H.y = C->P.y; + if (B->P.z > bbox.H.z) bbox.H.z = B->P.z; + if (C->P.z > bbox.H.z) bbox.H.z = C->P.z; return bbox; };