# HG changeset patch # User Radek Brich # Date 1197193526 -3600 # Node ID b4e09433934a7f51c662aee298c273133f59bb9d # Parent 33f95441790e3494f484747d571aa21f1c3fdfa4 refraction updated demo.py and bunny.py to present new feature python binding for material settings diff -r 33f95441790e -r b4e09433934a TODO --- a/TODO Sat Dec 08 16:02:37 2007 +0100 +++ b/TODO Sun Dec 09 10:45:26 2007 +0100 @@ -1,11 +1,17 @@ +Bugs +==== + * concurrent read? (concurrent write should not occur) + +Future Plans +============ * kd-tree: - optimize structures - optimize construction: do not use bounding boxes of shapes, instead implement box-shape intersection - save/load + * uniform grid, octree + * textures (3D procedural, pixmaps later) * update Python binding: Camera, new classes - * more complex demos * namespace - * refractions, glass New Classes? ============ diff -r 33f95441790e -r b4e09433934a demos/bunny.py --- a/demos/bunny.py Sat Dec 08 16:02:37 2007 +0100 +++ b/demos/bunny.py Sun Dec 09 10:45:26 2007 +0100 @@ -6,19 +6,31 @@ import sys sys.path.append(open('ModulePath').read().strip()) -from raytracer import Raytracer, Light, Sphere, Triangle, NormalVertex, Material +from raytracer import Raytracer, Light, Box, Triangle, NormalVertex, Material from plyreader import LoadStanfordPlyFile import Image rt = Raytracer() +#rt.ambientocclusion(samples=100, distance=16.0, angle=0.5) + mat = Material(colour=(0.9, 0.9, 0.9)) +mat.setTransmissivity(0.8) LoadStanfordPlyFile(rt, "../models/bunny/bun_zipper.ply", - mat, smooth=True, scale=(-29.0, 29.0, 29.0), trans=(-1,-3,-3)) + mat, smooth=True, scale=(-29.0, 29.0, 29.0), trans=(-1,-2.5,-3)) + +mat0 = Material(colour=(0.1, 0.2, 0.9)) +box1 = Box(L=(-20.0, -1.7, -20.0), H=(20.0, -1.5, 20.0), material=mat0) +rt.addshape(box1) -light = Light(position=(-5.0, 2.0, 10.0), colour=(0.9, 0.3, 0.6)) +mat1 = Material(colour=(0.2, 0.8, 0.4)) +mat1.setReflectivity(0.0) +box2 = Box(L=(-20.0, -20.0, -10.0), H=(20.0, 20.0, -12.0), material=mat1) +rt.addshape(box2) + +light = Light(position=(-5.0, 3.0, 10.0), colour=(0.9, 0.3, 0.6)) rt.addlight(light) -light2 = Light(position=(4.0, -3.0, 10.0), colour=(0.2, 0.9, 0.5)) +light2 = Light(position=(4.0, 1.0, 10.0), colour=(0.2, 0.9, 0.5)) rt.addlight(light2) imagesize = (800, 600) diff -r 33f95441790e -r b4e09433934a demos/demo.py --- a/demos/demo.py Sat Dec 08 16:02:37 2007 +0100 +++ b/demos/demo.py Sun Dec 09 10:45:26 2007 +0100 @@ -9,35 +9,38 @@ rt = Raytracer() -light1 = Light(position=(0.0, 5.0, -3.0), colour=(0.9, 0.3, 0.6)) +light1 = Light(position=(0.0, 4.0, -3.0), colour=(0.9, 0.3, 0.6)) rt.addlight(light1) #light2 = SphericalLight(position=(-2.0, 5.0, 1.0), radius=3.0, colour=(0.7, 1.0, 0.3)) -light2 = Light(position=(-2.0, -5.0, -1.0), colour=(0.7, 1.0, 0.3)) +light2 = Light(position=(-2.0, -4.0, -1.0), colour=(0.7, 1.0, 0.3)) +rt.addlight(light2) + +light2 = Light(position=(2.0, 5.0, 1.0), colour=(0.8, 0.9, 1.0)) rt.addlight(light2) mat0 = Material(colour=(0.1, 0.2, 0.9)) -box = Box(L=(-20.0, -1.2, -20.0), H=(20.0, -1.0, 20.0), material=mat0) +box = Box(L=(-20.0, -2.2, -20.0), H=(20.0, -2.0, 20.0), material=mat0) rt.addshape(box) mat1 = Material(colour=(1.0, 0.2, 0.1)) -bigsphere = Sphere(centre=(2.0, 2.0, -5.0), radius=2.5, material=mat1) +mat1.setReflectivity(0.7) +bigsphere = Sphere(centre=(2.0, 1.0, -5.0), radius=2.5, material=mat1) # reflection=0.6) rt.addshape(bigsphere) mat2 = Material(colour=(0.1, 0.7, 1.0)) -smallsphere = Sphere(centre=(-5.5, 1.5, -8.0), radius=2.0, material=mat2) +smallsphere = Sphere(centre=(-5.5, 0.5, -8.0), radius=2.0, material=mat2) # reflection=1.0, diffuse=0.1) rt.addshape(smallsphere) -mat3 = Material(colour=(0.9, 0.9, 0.1)) -tinysphere = Sphere(centre=(-0.5, 0.0, -2.0), radius=0.5, material=mat3) -# reflection=1.0, diffuse=0.1) -rt.addshape(tinysphere) - -#for i in range(100): -# sph=Sphere((-5.5+i/10.0, -0.5, 7.0), 2.0) -# rt.addshape(sph) +mat3 = Material(colour=(0.9, 0.9, 1.0)) +mat3.setPhong(0.2, 1.0, 0.2) +mat3.setTransmissivity(0.9) +mat3.setReflectivity(0.0) +for i in range(10): + sph = Sphere(centre=(-5.0+i, -1.5, -4.0), radius=0.5, material=mat3) + rt.addshape(sph) rendersize = (800, 600) data = rt.render(rendersize) diff -r 33f95441790e -r b4e09433934a include/raytracer.h --- a/include/raytracer.h Sat Dec 08 16:02:37 2007 +0100 +++ b/include/raytracer.h Sun Dec 09 10:45:26 2007 +0100 @@ -39,7 +39,7 @@ Vector3 SphereDistribute(int i, int n, Float extent, Vector3 &normal); public: Raytracer(): top(NULL), camera(NULL), lights(), bg_colour(0.0, 0.0, 0.0), - ao_samples(0), num_threads(4), subsample(8), max_depth(4) {}; + ao_samples(0), num_threads(2), subsample(8), max_depth(3) {}; void render(int w, int h, Float *buffer); Colour raytrace(Ray &ray, int depth, Shape *origin_shape); void addshape(Shape *shape) { top->addShape(shape); }; diff -r 33f95441790e -r b4e09433934a include/scene.h --- a/include/scene.h Sat Dec 08 16:02:37 2007 +0100 +++ b/include/scene.h Sun Dec 09 10:45:26 2007 +0100 @@ -128,19 +128,26 @@ { public: Float ambient, diffuse, specular, shininess; // Phong constants - Float reflection; // how much reflectife is the surface - Float refraction; // refraction index - Float transmitivity; + Float reflectivity; // how much reflective is the surface + Float transmissivity, refract_index; // part of light which can be refracted; index of refraction Texture texture; Material(const Colour &acolour) { texture.colour = acolour; - ambient = 0.1; - diffuse = 0.5; - specular = 0.1; + ambient = 0.2; + diffuse = 0.8; + specular = 0.2; shininess = 0.5; - reflection = 0.5; + reflectivity = 0.2; + transmissivity = 0.0; + refract_index = 1.3; } + + void setPhong(const Float amb, const Float dif, const Float spec, const Float shin) + { ambient = amb; diffuse = dif; specular = spec; shininess = shin; }; + void setReflectivity(const Float refl) { reflectivity = refl; }; + void setTransmissivity(const Float trans, const Float rindex) + { transmissivity = trans; refract_index = rindex; }; }; class Shape diff -r 33f95441790e -r b4e09433934a src/raytracer.cc --- a/src/raytracer.cc Sat Dec 08 16:02:37 2007 +0100 +++ b/src/raytracer.cc Sun Dec 09 10:45:26 2007 +0100 @@ -99,13 +99,19 @@ if (nearest_shape == NULL) { return bg_colour; } else { - Colour acc = Colour(); + Colour col = Colour(); Vector3 P = ray.o + ray.dir * nearest_distance; // point of intersection Vector3 normal = nearest_shape->normal(P); + bool from_inside = false; + // make shapes double sided if (dot(normal, ray.dir) > 0.0) + { normal = - normal; - acc = PhongShader_ambient(*nearest_shape->material, P); + from_inside = true; + } + + col = PhongShader_ambient(*nearest_shape->material, P); vector::iterator light; for (light = lights.begin(); light != lights.end(); light++) { @@ -123,22 +129,66 @@ // shading function Vector3 R = L - 2.0 * L_dot_N * normal; - acc += PhongShader_calculate(*nearest_shape->material, + col += PhongShader_calculate(*nearest_shape->material, P, normal, R, ray.dir, **light); } } - // reflection - Vector3 newdir = ray.dir - 2.0 * dot(ray.dir, normal) * normal; - if (depth < max_depth && nearest_shape->material->reflection > 0.01) { - Ray newray = Ray(P, newdir); - Colour refl_col = raytrace(newray, depth + 1, nearest_shape); - acc += nearest_shape->material->reflection * refl_col; + if (depth < max_depth) + { + Colour trans_col, refl_col; + Float trans = nearest_shape->material->transmissivity; + Float refl = nearest_shape->material->reflectivity; + const Float cos_i = - dot(normal, ray.dir); + + // reflection + if (refl > 0.01) + { + Vector3 newdir = ray.dir + 2.0 * cos_i * normal; + Ray newray = Ray(P, newdir); + refl_col = raytrace(newray, depth + 1, nearest_shape); + } + + // refraction + if (trans > 0.01) + { + Float n, n1, n2; + if (from_inside) + { + n1 = nearest_shape->material->refract_index; + n2 = 1.0; + n = n1; + } + else + { + n1 = 1.0; + n2 = nearest_shape->material->refract_index; + n = 1.0 / n2; + } + const Float sin2_t = n*n * (1 - cos_i*cos_i); + if (sin2_t >= 1.0) + { + // totally reflected + refl += trans; + trans = 0; + } + else + { + const Float cos_t = sqrtf(1 - sin2_t); + const Float Rdiv = 1.0/(n1*cos_i + n2*cos_t); + const Float Rper = (n1*cos_i - n2*cos_t)*Rdiv; + const Float Rpar = (n2*cos_i - n1*cos_t)*Rdiv; + const Float R = (Rper*Rper + Rpar*Rpar)/2; + refl += R*trans; + trans = (1-R)*trans; + Vector3 newdir = n * ray.dir + (n*cos_i - cos_t) * normal; + Ray newray = Ray(P, newdir); + trans_col = raytrace(newray, depth + 1, nearest_shape); + } + } + col = (1-refl-trans)*col + refl*refl_col + trans*trans_col; } - // refraction - /* ... */ - // ambient occlusion if (ao_samples) { @@ -154,10 +204,10 @@ miss += dist / ao_distance; } Float ao_intensity = miss / ao_samples; - acc = acc * ao_intensity; + col = col * ao_intensity; } - return acc; + return col; } } diff -r 33f95441790e -r b4e09433934a src/raytracermodule.cc --- a/src/raytracermodule.cc Sat Dec 08 16:02:37 2007 +0100 +++ b/src/raytracermodule.cc Sun Dec 09 10:45:26 2007 +0100 @@ -104,6 +104,9 @@ static PyObject *Material_Constructor(PyObject* self, PyObject* args, PyObject *kwd); static void Material_Destructor(PyObject* self); static PyObject *Material_Getattr(PyObject *self, char *name); +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 PyTypeObject MaterialType = { PyObject_HEAD_INIT(NULL) @@ -125,6 +128,9 @@ }; static PyMethodDef MaterialMethods[] = { + {"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."}, {NULL, NULL} }; @@ -159,6 +165,45 @@ return Py_FindMethod(MaterialMethods, self, name); } +static PyObject *Material_setPhong(PyObject* self, PyObject* args) +{ + Float amb, dif, spec, shin = 0.5; + + if (!PyArg_ParseTuple(args, "fff|f", &amb, &dif, &spec, &shin)) + return NULL; + + ((MaterialObject *)self)->material->setPhong(amb, dif, spec, shin); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *Material_setReflectivity(PyObject* self, PyObject* args) +{ + Float refl; + + if (!PyArg_ParseTuple(args, "f", &refl)) + return NULL; + + ((MaterialObject *)self)->material->setReflectivity(refl); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *Material_setTransmissivity(PyObject* self, PyObject* args) +{ + Float trans, rindex = 1.3; + + if (!PyArg_ParseTuple(args, "f|f", &trans, &rindex)) + return NULL; + + ((MaterialObject *)self)->material->setTransmissivity(trans, rindex); + + Py_INCREF(Py_None); + return Py_None; +} + //=========================== NormalVertex Object =========================== typedef struct { @@ -555,7 +600,7 @@ if (!PyArg_ParseTuple(args, "(ii)", &w, &h)) return NULL; - printf("[pyrit] Raytracing...\n"); + printf("[pyrit] Running ray tracer\n"); ((RaytracerObject *)self)->raytracer->getTop()->optimize(); data = (Float *) malloc(w*h*3*sizeof(Float)); ((RaytracerObject *)self)->raytracer->render(w, h, data); @@ -565,7 +610,7 @@ } // convert data to char - printf("[pyrit] Converting image data (float to char)...\n"); + printf("[pyrit] Converting image data (float to char)\n"); chardata = (char *) malloc(w*h*3); Float *d = data; for (char *c = chardata; c != chardata + w*h*3; c++, d++) { diff -r 33f95441790e -r b4e09433934a src/scene.cc --- a/src/scene.cc Sat Dec 08 16:02:37 2007 +0100 +++ b/src/scene.cc Sun Dec 09 10:45:26 2007 +0100 @@ -207,7 +207,6 @@ : smooth(false), A(aA), B(aB), C(aC) { material = amaterial; - material->reflection = 0; const Vector3 c = B->P - A->P; const Vector3 b = C->P - A->P;