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/=
--- 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?
--- 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<Vector3> vertices;
+ vector<NormalVertex*> vertices;
+ vector<Vector3> normals;
+ vector<int> 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;
--- 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
--- 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)
--- 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)
--- 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()
--- 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()
--- 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 <vector>
+#include <typeinfo>
#include "noise.h"
#include "vector.h"
@@ -156,7 +157,7 @@
virtual bool intersect_all(const Ray &ray, Float dist, vector<Float> &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<Float> &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<Float> &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<NormalVertex*>(A)->N;
+ const Vector3 &NB = static_cast<NormalVertex*>(B)->N;
+ const Vector3 &NC = static_cast<NormalVertex*>(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<Float> &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;
};
--- 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)
{
--- 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;
}
--- 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;
--- 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,
--- 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;
};