cleaned Texture interface pyrit
authorRadek Brich <radek.brich@devl.cz>
Sat, 29 Dec 2007 13:53:33 +0100
branchpyrit
changeset 42 fbdeb3e04543
parent 41 c1080cb5bd6d
child 43 0b8b968b42d1
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
.bzrignore
ccdemos/Makefile
ccdemos/textures.cc
include/scene.h
src/kdtree.cc
src/octree.cc
src/raytracer.cc
src/scene.cc
--- 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
--- 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
--- /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);
+	}
+}
--- 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;
--- 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)
 		{
--- 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()
--- 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;
--- 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;