# HG changeset patch # User Radek Brich # Date 1198932813 -3600 # Node ID fbdeb3e04543f04f3e76420a15651f03c4ba4d2b # Parent c1080cb5bd6dd20fc4b1d16f24c5473c19ae032d cleaned Texture interface new C++ demo: textures slightly adjusted SAH for kd-tree slightly optimized kd-tree building -- moved termination cond. so it's tested before recursion minor sphere intersection optimization diff -r c1080cb5bd6d -r fbdeb3e04543 .bzrignore --- a/.bzrignore Tue Dec 18 12:36:01 2007 +0100 +++ b/.bzrignore Sat Dec 29 13:53:33 2007 +0100 @@ -6,6 +6,7 @@ ccdemos/realtime ccdemos/realtime_dragon ccdemos/realtime_bunny +ccdemos/textures models/bunny models/happy models/dragon diff -r c1080cb5bd6d -r fbdeb3e04543 ccdemos/Makefile --- a/ccdemos/Makefile Tue Dec 18 12:36:01 2007 +0100 +++ b/ccdemos/Makefile Sat Dec 29 13:53:33 2007 +0100 @@ -21,17 +21,19 @@ $(CXX) -o $@ $(ROOT)/bin/$(RTLIBS)/*.o $< image.o $(LDFLAGS) $(SDL_LDFLAGS) -lpng ### Targets ### -all: realtime realtime_dragon realtime_bunny spheres_shadow +all: realtime realtime_dragon realtime_bunny spheres_shadow textures realtime: realtime.o $(RTLIBS) image.o realtime_dragon: realtime_dragon.o $(RTLIBS) image.o realtime_bunny: realtime_bunny.o $(RTLIBS) image.o spheres_shadow: spheres_shadow.o $(RTLIBS) image.o +textures: textures.o $(RTLIBS) image.o realtime.o: realtime.cc common_sdl.h realtime_dragon.o: realtime_dragon.cc common_sdl.h common_ply.h realtime_bunny.o: realtime_bunny.cc common_sdl.h common_ply.h spheres_shadow.o: spheres_shadow.cc common_sdl.h +textures.o: textures.cc common_sdl.h libs-float: $(MAKE) -C ../src libs-float @@ -43,7 +45,7 @@ $(CXX) -c -o $@ $*.c clean: - rm -f spheres_shadow realtime realtime_dragon realtime_bunny *.o + rm -f realtime realtime_dragon realtime_bunny spheres_shadow textures *.o distclean: clean rm -rf *.png diff -r c1080cb5bd6d -r fbdeb3e04543 ccdemos/textures.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ccdemos/textures.cc Sat Dec 29 13:53:33 2007 +0100 @@ -0,0 +1,285 @@ +#include "raytracer.h" +#include "octree.h" + +#include "image.h" +#include "common_sdl.h" + +Camera cam; +Light light(Vector3(-2.0, 10.0, -2.0), Colour(0.9, 0.9, 0.9)); + +Float lx, ly, lz, cf; + + +/*class CloudTexture: public Texture +{ + Vector3 centre; +public: + Colour evaluate(Vector3 point) + { + Float sum = 0.0; + for (int i = 1; i < 5; i++) + sum += fabsf(perlin(point.x*i, point.y*i, point.z*i))/i; + Float value = sinf(point.x + sum)/2 + 0.5; + return Colour(value, value*0.5, value*0.5); + }; +};*/ + +void texture2D(Float u, Float v, Float &r, Float &g, Float &b) +{ + // checkers + r = fabs((int)(u*4.4)%2 + (int)(v*4.4)%2 - 1); + g=r; b=r; +} + +class PlanarMapTexture: public Texture +{ + Vector3 centre; +public: + PlanarMapTexture(Vector3 acentre): centre(acentre) {}; + Colour evaluate(Vector3 point) + { + point = point - centre; + Float u = 1000+point.x; + Float v = 1000+point.y; + Float r,g,b; + texture2D(u,v, r,g,b); + return Colour(r, g, b); + }; +}; + +class CubicMapTexture: public Texture +{ + Vector3 centre; +public: + CubicMapTexture(Vector3 acentre): centre(acentre) {}; + Colour evaluate(Vector3 point) + { + point = point - centre; + Float u,v; + if (fabs(point.x) > fabs(point.y)) + { + if (fabs(point.x) > fabs(point.z)) + { + u = point.y; + v = point.z; + } + else + { + u = point.x; + v = point.y; + } + } + else + { + if (fabs(point.y) > fabs(point.z)) + { + u = point.x; + v = point.z; + } + else + { + u = point.x; + v = point.y; + } + } + u += 1000; + v += 1000; + Float r,g,b; + texture2D(u,v, r,g,b); + return Colour(r, g, b); + }; +}; + +class CylinderMapTexture: public Texture +{ + Vector3 centre; +public: + CylinderMapTexture(Vector3 acentre): centre(acentre) {}; + Colour evaluate(Vector3 point) + { + point = point - centre; + + Float u,v; + v = 1000+point.y; + u = M_PI + atan2(point.z, point.x); + + Float r,g,b; + texture2D(u,v, r,g,b); + return Colour(r, g, b); + }; +}; + +class SphereMapTexture: public Texture +{ + Vector3 centre; +public: + SphereMapTexture(Vector3 acentre): centre(acentre) {}; + Colour evaluate(Vector3 point) + { + point = point - centre; + + Float u,v; + v = acos(point.y / point.mag()); + u = M_PI + atan2(point.z, point.x); + + Float r,g,b; + texture2D(u,v, r,g,b); + return Colour(r, g, b); + }; +}; + +void update_callback() +{ + if (lx != 0.0) + light.pos.x += lx; + if (ly != 0.0) + light.pos.y += ly; + if (lz != 0.0) + light.pos.z += lz; + if (cf != 0.0) + cam.f += cf; +} + +void key_callback(int key, int down) +{ + switch (key) + { + case SDLK_r: + lx = -0.1 * down; + break; + case SDLK_t: + lx = +0.1 * down; + break; + case SDLK_f: + ly = -0.1 * down; + break; + case SDLK_g: + ly = +0.1 * down; + break; + case SDLK_v: + lz = -0.1 * down; + break; + case SDLK_b: + lz = +0.1 * down; + break; + + case SDLK_z: + cf = -0.02 * down; + break; + case SDLK_x: + cf = +0.02 * down; + break; + } +} + +int main(int argc, char **argv) +{ + Raytracer rt; + rt.setOversample(0); + rt.setSubsample(8); + + Octree top; + rt.setTop(&top); + + rt.addlight(&light); + light.castShadows(false); + + Material mat0a(Colour(0.7, 0.7, 0.7)); + mat0a. setReflectivity(0.0); + Box box(Vector3(-12.0, -1.2, -20.0), Vector3(12.0, -1.0, 0.0), &mat0a); + rt.addshape(&box); + + Material mat0b(Colour(0.1, 0.7, 0.8)); + mat0b.setReflectivity(0.7); + Box box2(Vector3(-12.0, -1.2, -10.0), Vector3(12.0, 10.0, -10.2), &mat0b); + rt.addshape(&box2); + + // spheres + Material mat1(Colour(1.0, 1.0, 1.0)); + mat1.texture = new PlanarMapTexture(Vector3(4.0, 2.0, -7.0)); + Sphere sphere1(Vector3(4.0, 2.0, -7.0), 1.0, &mat1); + rt.addshape(&sphere1); + + Material mat2(Colour(1.0, 1.0, 1.0)); + mat2.texture = new CubicMapTexture(Vector3(1.0, 2.0, -7.0)); + Sphere sphere2(Vector3(1.0, 2.0, -7.0), 1.0, &mat2); + rt.addshape(&sphere2); + + Material mat3(Colour(1.0, 1.0, 1.0)); + mat3.texture = new CylinderMapTexture(Vector3(-2.0, 2.0, -7.0)); + Sphere sphere3(Vector3(-2.0, 2.0, -7.0), 1.0, &mat3); + rt.addshape(&sphere3); + + Material mat4(Colour(1.0, 1.0, 1.0)); + mat4.texture = new SphereMapTexture(Vector3(-5.0, 2.0, -7.0)); + Sphere sphere4(Vector3(-5.0, 2.0, -7.0), 1.0, &mat4); + rt.addshape(&sphere4); + + // cubes + Material mat5(Colour(1.0, 1.0, 1.0)); + mat5.texture = new PlanarMapTexture(Vector3(4.0, 0.0, -7.0)); + Box cube1(Vector3(4.0, 0.0, -7.0)-1.0, Vector3(4.0, 0.0, -7.0)+1.0, &mat5); + rt.addshape(&cube1); + + Material mat6(Colour(1.0, 1.0, 1.0)); + mat6.texture = new CubicMapTexture(Vector3(1.0, 0.0, -7.0)); + Box cube2(Vector3(1.0, 0.0, -7.0)-1.0, Vector3(1.0, 0.0, -7.0)+1.0, &mat6); + rt.addshape(&cube2); + + Material mat7(Colour(1.0, 1.0, 1.0)); + mat7.texture = new CylinderMapTexture(Vector3(-2.0, 0.0, -7.0)); + Box cube3(Vector3(-2.0, 0.0, -7.0)-1.0, Vector3(-2.0, 0.0, -7.0)+1.0, &mat7); + rt.addshape(&cube3); + + Material mat8(Colour(1.0, 1.0, 1.0)); + mat8.texture = new SphereMapTexture(Vector3(-5.0, 0.0, -7.0)); + Box cube4(Vector3(-5.0, 0.0, -7.0)-1.0, Vector3(-5.0, 0.0, -7.0)+1.0, &mat8); + rt.addshape(&cube4); + + mat1.setReflectivity(0); + mat2.setReflectivity(0); + mat3.setReflectivity(0); + mat4.setReflectivity(0); + mat5.setReflectivity(0); + mat6.setReflectivity(0); + mat7.setReflectivity(0); + mat8.setReflectivity(0); + + top.optimize(); + + cam.setEye(Vector3(-0.530505, 11.0964, 11.2208)); + cam.p = Vector3(-4.18144e-08, -0.461779, -0.886995); + cam.u = Vector3(-1, 0, 6.3393e-11); + cam.v = Vector3(3.19387e-08, 0.886995, -0.461779); + rt.setCamera(&cam); + + w = 1024; + h = 600; + + /* run interactive mode */ + loop_sdl(rt, cam, update_callback, key_callback); + + /* render image */ + if (argc == 2 && !strcmp(argv[1], "-r")) + { + pyrit_verbosity = 2; + Float *fdata = (Float *) malloc(w*h*3*sizeof(Float)); + rt.setOversample(2); + rt.setSubsample(1); + rt.render(w, h, fdata); + + struct image *img; + new_image(&img, w, h, 3); + + Float *fd = fdata; + for (char *cd = img->data; cd != img->data + w*h*3; cd++, fd++) { + if (*fd > 1.0) + *cd = 255; + else + *cd = (unsigned char)(*fd * 255.0); + } + free(fdata); + save_png("textures.png", img); + destroy_image(&img); + } +} diff -r c1080cb5bd6d -r fbdeb3e04543 include/scene.h --- a/include/scene.h Tue Dec 18 12:36:01 2007 +0100 +++ b/include/scene.h Sat Dec 29 13:53:33 2007 +0100 @@ -82,27 +82,20 @@ class Texture { public: - Colour colour; - Colour evaluate(Vector3 point) - { - Float sum = 0.0; - for (int i = 1; i < 5; i++) - sum += fabsf(perlin(point.x*i, point.y*i, point.z*i))/i; - Float value = sinf(point.x + sum)/2 + 0.5; - return Colour(value*colour.r, value*colour.g, value*colour.b); - }; + virtual Colour evaluate(Vector3 point) = 0; }; class Material { public: + Colour colour; 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; + Texture *texture; - Material(const Colour &acolour) { - texture.colour = acolour; + Material(const Colour &acolour): colour(acolour), texture(NULL) + { ambient = 0.2; diffuse = 0.8; specular = 0.2; diff -r c1080cb5bd6d -r fbdeb3e04543 src/kdtree.cc --- a/src/kdtree.cc Tue Dec 18 12:36:01 2007 +0100 +++ b/src/kdtree.cc Sat Dec 29 13:53:33 2007 +0100 @@ -162,7 +162,7 @@ // choose best split pos const Float K = 1.4; // constant, K = cost of traversal / cost of ray-triangle intersection - Float SAV = 2*(bbox.w()*bbox.h() + bbox.w()*bbox.d() + bbox.h()*bbox.d()); // surface area of node + Float SAV = (bbox.w()*bbox.h() + bbox.w()*bbox.d() + bbox.h()*bbox.d()); // surface area of node Float cost = SAV * (K + shapes->size()); // initial cost = non-split cost bool leaf = true; BBox lbb = bbox; @@ -172,9 +172,9 @@ // calculate SAH cost of this split lbb.H.cell[axis] = spl->pos; rbb.L.cell[axis] = spl->pos; - Float SAL = 2*(lbb.w()*lbb.h() + lbb.w()*lbb.d() + lbb.h()*lbb.d()); - Float SAR = 2*(rbb.w()*rbb.h() + rbb.w()*rbb.d() + rbb.h()*rbb.d()); - Float splitcost = K + SAL/SAV*(K+spl->lnum) + SAR/SAV*(K+spl->rnum); + Float SAL = (lbb.w()*lbb.h() + lbb.w()*lbb.d() + lbb.h()*lbb.d()); + Float SAR = (rbb.w()*rbb.h() + rbb.w()*rbb.d() + rbb.h()*rbb.d()); + Float splitcost = K*SAV + SAL*(K+spl->lnum) + SAR*(K+spl->rnum); if (splitcost < cost) { diff -r c1080cb5bd6d -r fbdeb3e04543 src/octree.cc --- a/src/octree.cc Tue Dec 18 12:36:01 2007 +0100 +++ b/src/octree.cc Sat Dec 29 13:53:33 2007 +0100 @@ -17,9 +17,6 @@ void OctreeNode::subdivide(BBox bbox, int maxdepth) { - if (maxdepth <= 0 || shapes->size() <= 4) - return; - // make children children = new OctreeNode[8]; @@ -69,7 +66,8 @@ // recursive subdivision for (int i = 0; i < 8; i++) - children[i].subdivide(childbb[i], maxdepth-1); + if (maxdepth > 1 && getChild(i)->shapes->size() > 4) + children[i].subdivide(childbb[i], maxdepth-1); } void Octree::build() diff -r c1080cb5bd6d -r fbdeb3e04543 src/raytracer.cc --- a/src/raytracer.cc Tue Dec 18 12:36:01 2007 +0100 +++ b/src/raytracer.cc Sat Dec 29 13:53:33 2007 +0100 @@ -59,7 +59,11 @@ // P is point of intersection, N normal in this point Colour PhongShader_ambient(Material &mat, Vector3 &P) { - Colour col = mat.texture.colour; //mat.texture.evaluate(P); + Colour col; + if (mat.texture) + col = mat.texture->evaluate(P); + else + col = mat.colour; // ambient return mat.ambient * col; @@ -80,7 +84,11 @@ Float L_dot_N = dot(L, N); Float R_dot_V = dot(R, V); - Colour col = mat.texture.colour; //mat.texture.evaluate(P); + Colour col; + if (mat.texture) + col = mat.texture->evaluate(P); + else + col = mat.colour; // diffuse I = mat.diffuse * col * light.colour * L_dot_N; diff -r c1080cb5bd6d -r fbdeb3e04543 src/scene.cc --- a/src/scene.cc Tue Dec 18 12:36:01 2007 +0100 +++ b/src/scene.cc Sat Dec 29 13:53:33 2007 +0100 @@ -95,10 +95,10 @@ bool Sphere::intersect(const Ray &ray, Float &dist) const { Vector3 V = ray.o - center; - register Float d = -dot(V, ray.dir); + register Float d = dot(V, ray.dir); register Float Det = d * d - (dot(V,V) - sqr_radius); if (Det > 0) { - d -= sqrtf(Det); + d = -d - sqrtf(Det); if (d > 0 && d < dist) { dist = d;