# HG changeset patch # User Radek Brich # Date 1209727667 -7200 # Node ID 9d66d323c354c2b01b23b16f94898d8402fe9857 # Parent f6a72eb996317e53bc4972ccb30abeef7d45d97e packetize Phong shader new scons config options: simd=(yes|no) - allow/suppress explicit SSE force_flags=(yes|no) - force use of specified flags instead of autodetected profile=(yes|no) - enable gcc's profiling (-pg option) check for pthread.h header, don't try to build without it add fourth Vector3 component for better memory aligning rename Vector3 to Vector partialy SSE-ize Vector class (only fully vertical operations) build static lib and python module in distinctive directories to avoid collision of library file names on some platforms diff -r f6a72eb99631 -r 9d66d323c354 SConstruct --- a/SConstruct Tue Apr 29 23:31:08 2008 +0200 +++ b/SConstruct Fri May 02 13:27:47 2008 +0200 @@ -30,14 +30,17 @@ """) import os, sys -env = Environment(ENV = {'PATH' : os.environ['PATH']}) +env = Environment() #(ENV = {'PATH' : os.environ['PATH']}) Decider('MD5-timestamp') opt = Options(['.optioncache']) opt.AddOptions( BoolOption('intelc', 'use Intel C++ Compiler, if available', True), + BoolOption('simd', 'allow SSE intrinsics', True), ('precision', 'floating point number precision (single/double)', "single"), ('flags', 'add additional compiler flags', ""), + BoolOption('force_flags', "use only flags specified by 'flags' option (do not autodetect arch/sse flags)", False), + BoolOption('profile', "enable gcc's profiling support (-pg)", False), ) if env['PLATFORM'] == 'win32': opt.AddOptions( @@ -120,12 +123,18 @@ if cc == 'intelc': add_flags += cpuflags_intelc + ' ' +if conf.env['force_flags']: + add_flags = conf.env['flags'] + ' ' +else: + add_flags += conf.env['flags'] + ' ' + if conf.env['precision'] == 'double': add_flags += '-DPYRIT_DOUBLE ' elif cc == 'gcc': add_flags += '-fsingle-precision-constant ' -add_flags += conf.env['flags'] +if not conf.env['simd']: + add_flags += '-DNO_SSE ' if cc == 'intelc': conf.env.Append(CCFLAGS="-O3 -w1 " + add_flags) @@ -143,17 +152,25 @@ conf.env.Append(CCFLAGS='-DHAVE_PNG') conf.env.Append(LIBS=['png']) +if not conf.CheckCHeader('pthread.h'): + print 'Error: Cannot build without pthread.' + Exit(1) + if conf.env['PLATFORM'] == 'win32': conf.env.Append(LIBS=["pthreadGC2"]) else: conf.env.Append(CCFLAGS="-pthread ") +if conf.env['profile'] and cc == 'gcc': + conf.env.Append(CCFLAGS="-pg", LINKFLAGS="-pg") + env = conf.Finish() ### build targets -(lib, pymodule) = SConscript('src/SConscript', build_dir='build/lib', duplicate=0, exports='env') +lib = SConscript('src/SConscript', build_dir='build/lib', duplicate=0, exports={'env':env,'buildmodule':False}) +pymodule = SConscript('src/SConscript', build_dir='build/pymodule', duplicate=0, exports={'env':env,'buildmodule':True}) SConscript('ccdemos/SConscript', build_dir='build/ccdemos', duplicate=0, exports='env lib') SConscript('demos/SConscript', exports='pymodule') @@ -163,6 +180,8 @@ SConscript('models/SConscript') +env.Alias('libs', ['static-lib', 'python-module']) + env.Alias('docs', Command('docs/html', [], 'doxygen')) env.Clean('docs', ['docs/html']) diff -r f6a72eb99631 -r 9d66d323c354 TODO --- a/TODO Tue Apr 29 23:31:08 2008 +0200 +++ b/TODO Fri May 02 13:27:47 2008 +0200 @@ -4,9 +4,11 @@ Future Plans ============ + * Python binding for material.h classes + * Container should implement Shape interface to allow building hierarchies + * Container should allow local space transformations * generalization: Camera "shader" (ray generator), surface shader and maybe light & background shaders - * namespace - * Python binding for all classes + * put everything into a namespace * stochastic oversampling * absorbtion of refracted rays in dense materials (can be computed using shape distance and some 'absorbance' constant) * implement efficient AABB-ray intersection using Plucker coordinates diff -r f6a72eb99631 -r 9d66d323c354 ccdemos/SConscript --- a/ccdemos/SConscript Tue Apr 29 23:31:08 2008 +0200 +++ b/ccdemos/SConscript Fri May 02 13:27:47 2008 +0200 @@ -4,7 +4,12 @@ myenv.Prepend(LIBS=['pyrit']) sdlenv = myenv.Clone() -sdlenv.ParseConfig('sh sdl-config --cflags --libs') +try: + sdlenv.ParseConfig('sh sdl-config --cflags --libs') +except: + print "SDL not found, some demos will not built." + myenv.Alias('cc-demos', None) + Return() l = [] l.append( sdlenv.Program(['realtime.cc']) ) diff -r f6a72eb99631 -r 9d66d323c354 ccdemos/common_ply.h --- a/ccdemos/common_ply.h Tue Apr 29 23:31:08 2008 +0200 +++ b/ccdemos/common_ply.h Fri May 02 13:27:47 2008 +0200 @@ -2,10 +2,10 @@ #include #include -void load_ply(Raytracer &rt, const char *filename, Material *mat, Vector3 scale, Vector3 transp) +void load_ply(Raytracer &rt, const char *filename, Material *mat, Vector scale, Vector transp) { vector vertices; - vector normals; + vector normals; vector vertex_face_num; ifstream f(filename); string token = "a"; @@ -31,7 +31,7 @@ } // read vertices - Vector3 P; + Vector P; int num = vertex_num; while (num--) { @@ -40,7 +40,7 @@ P.y = scale.y*P.y + transp.y; P.z = scale.z*P.z + transp.z; vertices.push_back(new NormalVertex(P)); - normals.push_back(Vector3()); + normals.push_back(Vector()); vertex_face_num.push_back(0); f.ignore(1000,'\n'); } diff -r f6a72eb99631 -r 9d66d323c354 ccdemos/realtime.cc --- a/ccdemos/realtime.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/ccdemos/realtime.cc Fri May 02 13:27:47 2008 +0200 @@ -14,21 +14,21 @@ rt.setMaxDepth(3); rt.setTop(&top); - Light light1(Vector3(2.0, -5.0, -5.0), Colour(0.7, 0.3, 0.6)); + Light light1(Vector(2.0, -5.0, -5.0), Colour(0.7, 0.3, 0.6)); light1.castShadows(false); rt.addLight(&light1); - Light light2(Vector3(-2.0, 10.0, 2.0), Colour(0.4, 0.6, 0.3)); + Light light2(Vector(-2.0, 10.0, 2.0), Colour(0.4, 0.6, 0.3)); light2.castShadows(false); rt.addLight(&light2); Material mat_sph(Colour(1.0, 1.0, 1.0)); for (int y=0; y<10; y++) for (int x=0; x<10; x++) - rt.addShape(new Sphere(Vector3(x*2-10, (Float)rand()/RAND_MAX*5.0, y*2-10), 0.45, &mat_sph)); + rt.addShape(new Sphere(Vector(x*2-10, (Float)rand()/RAND_MAX*5.0, y*2-10), 0.45, &mat_sph)); rt.setCamera(&cam); - cam.setEye(Vector3(0,0,10)); + cam.setEye(Vector(0,0,10)); top.optimize(); diff -r f6a72eb99631 -r 9d66d323c354 ccdemos/realtime_bunny.cc --- a/ccdemos/realtime_bunny.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/ccdemos/realtime_bunny.cc Fri May 02 13:27:47 2008 +0200 @@ -13,20 +13,20 @@ rt.setMaxDepth(0); rt.setTop(&top); - Light light1(Vector3(-5.0, 2.0, 8.0), Colour(0.9, 0.3, 0.6)); + Light light1(Vector(-5.0, 2.0, 8.0), Colour(0.9, 0.3, 0.6)); light1.castShadows(false); rt.addLight(&light1); - //Light light2(Vector3(-2.0, 10.0, 2.0), Colour(0.4, 0.6, 0.3)); + //Light light2(Vector(-2.0, 10.0, 2.0), Colour(0.4, 0.6, 0.3)); //light2.castShadows(false); //rt.addLight(&light2); Material mat(Colour(0.9, 0.9, 0.9)); mat.setSmooth(true); - load_ply(rt, "../models/ply/bunny/bun_zipper.ply", &mat, Vector3(-29,29,29), Vector3(-1,-3,0)); + load_ply(rt, "../models/ply/bunny/bun_zipper.ply", &mat, Vector(-29,29,29), Vector(-1,-3,0)); rt.setCamera(&cam); - cam.setEye(Vector3(0,0,10)); + cam.setEye(Vector(0,0,10)); top.optimize(); diff -r f6a72eb99631 -r 9d66d323c354 ccdemos/realtime_dragon.cc --- a/ccdemos/realtime_dragon.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/ccdemos/realtime_dragon.cc Fri May 02 13:27:47 2008 +0200 @@ -14,13 +14,13 @@ rt.setMaxDepth(0); rt.setTop(&top); rt.setCamera(&cam); - cam.setEye(Vector3(0,0,10)); + cam.setEye(Vector(0,0,10)); - Light light1(Vector3(-5.0, 2.0, 8.0), Colour(0.9, 0.3, 0.6)); + Light light1(Vector(-5.0, 2.0, 8.0), Colour(0.9, 0.3, 0.6)); light1.castShadows(false); rt.addLight(&light1); - //Light light2(Vector3(-2.0, 10.0, 2.0), Colour(0.4, 0.6, 0.3)); + //Light light2(Vector(-2.0, 10.0, 2.0), Colour(0.4, 0.6, 0.3)); //light2.castShadows(false); //rt.addlight(&light2); @@ -34,7 +34,7 @@ if (!fin) { load_ply(rt, "../models/ply/dragon/dragon_vrip.ply", - &mat, Vector3(-29,29,-29), Vector3(0,-3.6,0)); + &mat, Vector(-29,29,-29), Vector(0,-3.6,0)); top.optimize(); } else diff -r f6a72eb99631 -r 9d66d323c354 ccdemos/spheres_shadow.cc --- a/ccdemos/spheres_shadow.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/ccdemos/spheres_shadow.cc Fri May 02 13:27:47 2008 +0200 @@ -4,7 +4,7 @@ #include "common_sdl.h" Camera cam; -Light light(Vector3(-2.0, 10.0, -2.0), Colour(0.9, 0.9, 0.9)); +Light light(Vector(-2.0, 10.0, -2.0), Colour(0.9, 0.9, 0.9)); Float lx, ly, lz, cf; @@ -67,34 +67,34 @@ Material mat0a(Colour(0.7, 0.7, 0.7)); mat0a. setReflectivity(0.0); - Box box(Vector3(-10.0, -1.2, -20.0), Vector3(10.0, -1.0, 0.0), &mat0a); + Box box(Vector(-10.0, -1.2, -20.0), Vector(10.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(-10.0, -1.2, -20.0), Vector3(10.0, 10.0, -20.2), &mat0b); + Box box2(Vector(-10.0, -1.2, -20.0), Vector(10.0, 10.0, -20.2), &mat0b); rt.addShape(&box2); Material mat1(Colour(1.0, 0.0, 0.0)); - Sphere bigsphere(Vector3(3.0, 2.0, -7.0), 3.0, &mat1); + Sphere bigsphere(Vector(3.0, 2.0, -7.0), 3.0, &mat1); rt.addShape(&bigsphere); Material mat2(Colour(0.0, 1.0, 0.0)); - Sphere smallsphere(Vector3(-5.5, 1.5, -8.0), 2.0, &mat2); + Sphere smallsphere(Vector(-5.5, 1.5, -8.0), 2.0, &mat2); rt.addShape(&smallsphere); Material mat3(Colour(0.0, 0.0, 1.0)); mat3.setReflectivity(0.1); mat3.setTransmissivity(0.8, 1.5); - Sphere tinysphere(Vector3(-1.2, 0.0, -2.0), 0.7, &mat3); + Sphere tinysphere(Vector(-1.2, 0.0, -2.0), 0.7, &mat3); rt.addShape(&tinysphere); top.optimize(); - cam.setEye(Vector3(-2.28908, 4.30992, 12.3051)); - cam.p = Vector3(0.0988566, -0.139543, -0.985269); - cam.u = Vector3(-0.995004, 0, -0.0998334); - cam.v = Vector3(0.0139311, 0.990216, -0.138846); + cam.setEye(Vector(-2.28908, 4.30992, 12.3051)); + cam.p = Vector(0.0988566, -0.139543, -0.985269); + cam.u = Vector(-0.995004, 0, -0.0998334); + cam.v = Vector(0.0139311, 0.990216, -0.138846); rt.setCamera(&cam); w = 800; diff -r f6a72eb99631 -r 9d66d323c354 ccdemos/textures.cc --- a/ccdemos/textures.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/ccdemos/textures.cc Fri May 02 13:27:47 2008 +0200 @@ -1,10 +1,10 @@ #include "raytracer.h" -#include "octree.h" +#include "kdtree.h" #include "common_sdl.h" -Camera cam(Vector3(0.,6.,6.), Vector3(0.,2.,-7.), Vector3(0.,0.,-1.)); -Light light(Vector3(-2.0, 10.0, -2.0), Colour(0.9, 0.9, 0.9)); +Camera cam(Vector(0.,6.,6.), Vector(0.,2.,-7.), Vector(0.,0.,-1.)); +Light light(Vector(-2.0, 10.0, -2.0), Colour(0.9, 0.9, 0.9)); Float lx, ly, lz, cf; @@ -56,7 +56,7 @@ { Raytracer rt; - Octree top; + KdTree top; rt.setCamera(&cam); rt.setTop(&top); @@ -65,12 +65,12 @@ 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); + Box box(Vector(-12.0, -1.2, -20.0), Vector(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); + Box box2(Vector(-12.0, -1.2, -10.0), Vector(12.0, 10.0, -10.2), &mat0b); rt.addShape(&box2); Float bounds[] = {0.3, 0.6, 1.1}; @@ -79,44 +79,44 @@ // spheres Material mat1(Colour(1.0, 1.0, 1.0)); - mat1.texture = new CheckersTexture(new PlanarMap(Vector3(-4.5, 2.0, -7.0), 0.48), &cmap); - Sphere sphere1(Vector3(-4.5, 2.0, -7.0), 1.0, &mat1); + mat1.texture = new CheckersTexture(new PlanarMap(Vector(-4.5, 2.0, -7.0), 0.48), &cmap); + Sphere sphere1(Vector(-4.5, 2.0, -7.0), 1.0, &mat1); rt.addShape(&sphere1); Material mat2(Colour(1.0, 1.0, 1.0)); - mat2.texture = new CheckersTexture(new CubicMap(Vector3(-1.5, 2.0, -7.0), 0.48), &cmap); - Sphere sphere2(Vector3(-1.5, 2.0, -7.0), 1.0, &mat2); + mat2.texture = new CheckersTexture(new CubicMap(Vector(-1.5, 2.0, -7.0), 0.48), &cmap); + Sphere sphere2(Vector(-1.5, 2.0, -7.0), 1.0, &mat2); rt.addShape(&sphere2); Material mat3(Colour(1.0, 1.0, 1.0)); - mat3.texture = new CheckersTexture(new CylinderMap(Vector3(1.5, 2.0, -7.0), 0.48), &cmap); - Sphere sphere3(Vector3(1.5, 2.0, -7.0), 1.0, &mat3); + mat3.texture = new CheckersTexture(new CylinderMap(Vector(1.5, 2.0, -7.0), 0.48), &cmap); + Sphere sphere3(Vector(1.5, 2.0, -7.0), 1.0, &mat3); rt.addShape(&sphere3); Material mat4(Colour(1.0, 1.0, 1.0)); - mat4.texture = new CheckersTexture(new SphereMap(Vector3(4.5, 2.0, -7.0), 0.48), &cmap); - Sphere sphere4(Vector3(4.5, 2.0, -7.0), 1.0, &mat4); + mat4.texture = new CheckersTexture(new SphereMap(Vector(4.5, 2.0, -7.0), 0.48), &cmap); + Sphere sphere4(Vector(4.5, 2.0, -7.0), 1.0, &mat4); rt.addShape(&sphere4); // cubes Material mat5(Colour(1.0, 1.0, 1.0)); - mat5.texture = new CheckersTexture(new PlanarMap(Vector3(-4.5, 0.0, -7.0), 0.48), &cmap); - Box cube1(Vector3(-4.5, 0.0, -7.0)-1.0, Vector3(-4.5, 0.0, -7.0)+1.0, &mat5); + mat5.texture = new CheckersTexture(new PlanarMap(Vector(-4.5, 0.0, -7.0), 0.48), &cmap); + Box cube1(Vector(-4.5, 0.0, -7.0)-1.0, Vector(-4.5, 0.0, -7.0)+1.0, &mat5); rt.addShape(&cube1); Material mat6(Colour(1.0, 1.0, 1.0)); - mat6.texture = new CheckersTexture(new CubicMap(Vector3(-1.5, 0.0, -7.0), 0.48), &cmap); - Box cube2(Vector3(-1.5, 0.0, -7.0)-1.0, Vector3(-1.5, 0.0, -7.0)+1.0, &mat6); + mat6.texture = new CheckersTexture(new CubicMap(Vector(-1.5, 0.0, -7.0), 0.48), &cmap); + Box cube2(Vector(-1.5, 0.0, -7.0)-1.0, Vector(-1.5, 0.0, -7.0)+1.0, &mat6); rt.addShape(&cube2); Material mat7(Colour(1.0, 1.0, 1.0)); - mat7.texture = new CheckersTexture(new CylinderMap(Vector3(1.5, 0.0, -7.0), 0.48), &cmap); - Box cube3(Vector3(1.5, 0.0, -7.0)-1.0, Vector3(1.5, 0.0, -7.0)+1.0, &mat7); + mat7.texture = new CheckersTexture(new CylinderMap(Vector(1.5, 0.0, -7.0), 0.48), &cmap); + Box cube3(Vector(1.5, 0.0, -7.0)-1.0, Vector(1.5, 0.0, -7.0)+1.0, &mat7); rt.addShape(&cube3); Material mat8(Colour(1.0, 1.0, 1.0)); - mat8.texture = new CheckersTexture(new SphereMap(Vector3(4.5, 0.0, -7.0), 0.48), &cmap); - Box cube4(Vector3(4.5, 0.0, -7.0)-1.0, Vector3(4.5, 0.0, -7.0)+1.0, &mat8); + mat8.texture = new CheckersTexture(new SphereMap(Vector(4.5, 0.0, -7.0), 0.48), &cmap); + Box cube4(Vector(4.5, 0.0, -7.0)-1.0, Vector(4.5, 0.0, -7.0)+1.0, &mat8); rt.addShape(&cube4); mat1.setReflectivity(0); diff -r f6a72eb99631 -r 9d66d323c354 include/common.h --- a/include/common.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/common.h Fri May 02 13:27:47 2008 +0200 @@ -33,9 +33,6 @@ #include #include -// SSE intrinsics -#include - using namespace std; #ifdef PYRIT_DOUBLE @@ -48,13 +45,27 @@ # define Inf FLT_MAX #endif +#ifndef NO_SSE +// SSE intrinsics +#include + const __m128 mZero = _mm_set_ps1(0.); const __m128 mOne = _mm_set_ps1(1.); +const __m128 mTwo = _mm_set_ps1(2.); const __m128 mEps = _mm_set_ps1(Eps); const __m128 mMEps = _mm_set_ps1(-Eps); const __m128 mInf = _mm_set_ps1(Inf); const __m128 mAllSet = _mm_cmplt_ps(mZero, mOne); +inline const __m128 _mm_fastpow(const __m128& base, const __m128& exponent) +{ + __m128 denom = _mm_mul_ps( exponent, base); + denom = _mm_sub_ps( exponent, denom); + denom = _mm_add_ps( base, denom); + return _mm_mul_ps( base, _mm_rcp_ps(denom)); +} +#endif + /* verbosity level: 0: only errors (E) 1: major status messages (*) diff -r f6a72eb99631 -r 9d66d323c354 include/container.h --- a/include/container.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/container.h Fri May 02 13:27:47 2008 +0200 @@ -3,7 +3,7 @@ * * This file is part of Pyrit Ray Tracer. * - * Copyright 2007 Radek Brich + * Copyright 2007, 2008 Radek Brich * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,14 +48,17 @@ //void addShapeNoExtend(Shape* aShape) { shapes.push_back(aShape); }; virtual Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray, Float &nearest_distance); - virtual void packet_intersection(const Shape **origin_shapes, const RayPacket &rays, - Float *nearest_distances, Shape **nearest_shapes); virtual void optimize() {}; ShapeList & getShapes() { return shapes; }; virtual ostream & dump(ostream &st); + +#ifndef NO_SSE + virtual void packet_intersection(const Shape **origin_shapes, const RayPacket &rays, + Float *nearest_distances, Shape **nearest_shapes); +#endif }; #endif diff -r f6a72eb99631 -r 9d66d323c354 include/kdtree.h --- a/include/kdtree.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/kdtree.h Fri May 02 13:27:47 2008 +0200 @@ -86,8 +86,10 @@ void addShape(Shape* aShape) { Container::addShape(aShape); built = false; }; Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray, Float &nearest_distance); +#ifndef NO_SSE void packet_intersection(const Shape **origin_shapes, const RayPacket &rays, Float *nearest_distances, Shape **nearest_shapes); +#endif void optimize() { build(); }; void build(); bool isBuilt() const { return built; }; diff -r f6a72eb99631 -r 9d66d323c354 include/material.h --- a/include/material.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/material.h Fri May 02 13:27:47 2008 +0200 @@ -43,7 +43,7 @@ { public: virtual ~Texture() {}; - virtual Colour evaluate(const Vector3 &point) = 0; + virtual Colour evaluate(const Vector &point) = 0; }; /** @@ -103,13 +103,13 @@ class TextureMap { protected: - Vector3 center; + Vector center; Float invsize; public: - TextureMap(const Vector3 &acenter, const Float &size): + TextureMap(const Vector &acenter, const Float &size): center(acenter), invsize(1./size) {}; virtual ~TextureMap() {}; - virtual void map(const Vector3 &point, Float &u, Float &v) = 0; + virtual void map(const Vector &point, Float &u, Float &v) = 0; }; /** @@ -118,11 +118,11 @@ class PlanarMap: public TextureMap { public: - PlanarMap(const Vector3 &acenter, const Float &size): + PlanarMap(const Vector &acenter, const Float &size): TextureMap(acenter, size) {}; - void map(const Vector3 &point, Float &u, Float &v) + void map(const Vector &point, Float &u, Float &v) { - const Vector3 p = point - center; + const Vector p = point - center; u = p.x*invsize; v = p.y*invsize; }; @@ -134,11 +134,11 @@ class CubicMap: public TextureMap { public: - CubicMap(const Vector3 &acenter, const Float &size): + CubicMap(const Vector &acenter, const Float &size): TextureMap(acenter, size) {}; - void map(const Vector3 &point, Float &u, Float &v) + void map(const Vector &point, Float &u, Float &v) { - const Vector3 p = point - center; + const Vector p = point - center; if (fabs(p.x) > fabs(p.y)) { if (fabs(p.x) > fabs(p.z)) @@ -188,11 +188,11 @@ class CylinderMap: public TextureMap { public: - CylinderMap(const Vector3 &acenter, const Float &size): + CylinderMap(const Vector &acenter, const Float &size): TextureMap(acenter, size) {}; - void map(const Vector3 &point, Float &u, Float &v) + void map(const Vector &point, Float &u, Float &v) { - const Vector3 p = point - center; + const Vector p = point - center; u = ( M_PI + atan2(p.z, p.x) ) * invsize; v = p.y * invsize; }; @@ -204,11 +204,11 @@ class SphereMap: public TextureMap { public: - SphereMap(const Vector3 &acenter, const Float &size): + SphereMap(const Vector &acenter, const Float &size): TextureMap(acenter, size) {}; - void map(const Vector3 &point, Float &u, Float &v) + void map(const Vector &point, Float &u, Float &v) { - const Vector3 p = point - center; + const Vector p = point - center; u = ( M_PI + atan2(p.z, p.x) ) * invsize; v = acos(p.y / p.mag()) * invsize; }; @@ -234,7 +234,7 @@ public: ImageTexture(TextureMap *tmap, Pixmap *image): Texture2D(tmap), pixmap(image) {}; - Colour evaluate(const Vector3 &point) + Colour evaluate(const Vector &point) { Float u,v; map->map(point, u,v); @@ -255,7 +255,7 @@ public: CheckersTexture(TextureMap *tmap, ColourMap *cmap): Texture2D(tmap), colourmap(cmap) {}; - Colour evaluate(const Vector3 &point) + Colour evaluate(const Vector &point) { Float u,v, val; map->map(point, u,v); @@ -274,7 +274,7 @@ public: CloudTexture(const Float &adetail, ColourMap *cmap): detail(adetail), colourmap(cmap) {}; - Colour evaluate(const Vector3 &point) + Colour evaluate(const Vector &point) { Float sum = 0.0; for (int i = 1; i < detail; i++) diff -r f6a72eb99631 -r 9d66d323c354 include/matrix.h --- a/include/matrix.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/matrix.h Fri May 02 13:27:47 2008 +0200 @@ -3,7 +3,7 @@ * * This file is part of Pyrit Ray Tracer. * - * Copyright 2006, 2007 Radek Brich + * Copyright 2006, 2007, 2008 Radek Brich * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -98,9 +98,9 @@ friend Matrix operator*(const Float &f, Matrix &m) { return m * f; }; // product of matrix and vector - Vector3 operator*(const Vector3 &v) + Vector operator*(const Vector &v) { - Vector3 u = Vector3(); + Vector u = Vector(); u.x = data[0][0] * v.x + data[0][1] * v.y + data[0][2] * v.z + data[0][3] * v.w; u.y = data[1][0] * v.x + data[1][1] * v.y + data[1][2] * v.z + data[1][3] * v.w; u.z = data[2][0] * v.x + data[2][1] * v.y + data[2][2] * v.z + data[2][3] * v.w; @@ -108,7 +108,7 @@ return u; } - friend Matrix operator*(const Vector3 &v, Matrix &m) { return m * v; }; + friend Matrix operator*(const Vector &v, Matrix &m) { return m * v; }; }; #endif diff -r f6a72eb99631 -r 9d66d323c354 include/quaternion.h --- a/include/quaternion.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/quaternion.h Fri May 02 13:27:47 2008 +0200 @@ -3,7 +3,7 @@ * * This file is part of Pyrit Ray Tracer. * - * Copyright 2007 Radek Brich + * Copyright 2007, 2008 Radek Brich * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -44,9 +44,9 @@ Quaternion(): a(0), b(0), c(0), d(0) {}; Quaternion(const Float aa, const Float ab, const Float ac, const Float ad): a(aa), b(ab), c(ac), d(ad) {}; - Quaternion(const Vector3& v): a(0), b(v.x), c(v.y), d(v.z) {}; + Quaternion(const Vector& v): a(0), b(v.x), c(v.y), d(v.z) {}; - Vector3 toVector() { return Vector3(b, c, d); }; + Vector toVector() { return Vector(b, c, d); }; Quaternion normalize() { diff -r f6a72eb99631 -r 9d66d323c354 include/raytracer.h --- a/include/raytracer.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/raytracer.h Fri May 02 13:27:47 2008 +0200 @@ -39,7 +39,7 @@ struct RenderrowData { Raytracer *rt; int w; - Vector3 eye, dfix, dx, dy; + Vector eye, dfix, dx, dy; Float *iter; }; @@ -59,17 +59,22 @@ int max_depth; bool use_packets; - Vector3 SphereDistribute(int i, int n, Float extent, Vector3 &normal); - Sample *sample_queue; int sample_queue_pos, sample_queue_size, sample_queue_count; bool end_of_samples; pthread_mutex_t sample_queue_mutex, sampler_mutex; pthread_cond_t sample_queue_cond, worker_ready_cond; - Colour shader_evalulate(const Ray &ray, int depth, Shape *origin_shape, - Float nearest_distance, Shape *nearest_shape); + Vector SphereDistribute(int i, int n, Float extent, const Vector &normal); + Colour PhongShader(const Shape *shape, + const Vector &P, const Vector &N, const Vector &V); + void lightScatter(const Ray &ray, const Shape *shape, int depth, + const Vector &P, const Vector &normal, bool from_inside, Colour &col); +#ifndef NO_SSE + VectorPacket PhongShader_packet(const Shape **shapes, + const VectorPacket &P, const VectorPacket &N, const VectorPacket &V); void raytracePacket(RayPacket &rays, Colour *results); +#endif static void *raytrace_worker(void *d); public: Raytracer(): top(NULL), camera(NULL), lights(), bg_colour(0., 0., 0.), @@ -89,7 +94,7 @@ } void render(); - Colour raytrace(Ray &ray, int depth, Shape *origin_shape); + Colour raytrace(Ray &ray, int depth, const Shape *origin_shape); void addShape(Shape *shape) { top->addShape(shape); }; void addLight(Light *light) { lights.push_back(light); }; void setSampler(Sampler *sampl) { sampler = sampl; }; diff -r f6a72eb99631 -r 9d66d323c354 include/scene.h --- a/include/scene.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/scene.h Fri May 02 13:27:47 2008 +0200 @@ -41,12 +41,13 @@ class Ray { public: - Vector3 o, dir; + Vector o, dir; Ray(): o(), dir() {}; - Ray(const Vector3 &ao, const Vector3 &adir): + Ray(const Vector &ao, const Vector &adir): o(ao), dir(adir) {}; }; +#ifndef NO_SSE /** * packet of 4 rays */ @@ -55,14 +56,19 @@ public: VectorPacket o, dir; + RayPacket(): o(), dir() {}; + RayPacket(const VectorPacket &ao, const VectorPacket &adir): + o(ao), dir(adir) {}; + // index operator - get a ray Ray operator[](int i) const { return Ray( - Vector3(o.x[i], o.y[i], o.z[i]), - Vector3(dir.x[i], dir.y[i], dir.z[i])); + Vector(o.x[i], o.y[i], o.z[i]), + Vector(dir.x[i], dir.y[i], dir.z[i])); }; }; +#endif /** * a camera @@ -70,31 +76,32 @@ class Camera { public: - Vector3 eye, p, u, v; + Vector eye, p, u, v; Float F; Camera(): eye(0,0,10), p(0,0,-1), u(-1,0,0), v(0,1,0), F(2.*tan(M_PI/8.)) {}; - Camera(const Vector3 &C, const Vector3 &ap, const Vector3 &au, const Vector3 &av): + Camera(const Vector &C, const Vector &ap, const Vector &au, const Vector &av): eye(C), p(ap), u(au), v(av), F(2.*tan(M_PI/8.)) {}; - Camera(const Vector3 &from, const Vector3 &lookat, const Vector3 &up): + Camera(const Vector &from, const Vector &lookat, const Vector &up): eye(from), F(2.*tan(M_PI/8.)) { p = lookat - from; u = cross(up, p); p.normalize(); u.normalize(); v = cross(p, u); }; - void setEye(const Vector3 &aeye) { eye = aeye; }; + void setEye(const Vector &aeye) { eye = aeye; }; void setAngle(const Float angle) { F = 2.*tan(angle/2.); }; void rotate(const Quaternion &q); void move(const Float fw, const Float left, const Float up); Ray makeRay(Sample &samp) { - Vector3 dir = p - (u*samp.x + v*samp.y)*F; + Vector dir = p - (u*samp.x + v*samp.y)*F; dir.normalize(); return Ray(eye, dir); }; +#ifndef NO_SSE void makeRayPacket(Sample *samples, RayPacket &rays) { __m128 m1x,m1y,m1z; @@ -145,6 +152,7 @@ rays.dir.normalize(); }; +#endif }; /** @@ -153,13 +161,13 @@ class Light { public: - Vector3 pos; + Vector pos; Colour colour; bool cast_shadows; Light(): - pos(Vector3(0,0,0)), colour(Colour(1,1,1)), cast_shadows(true) {}; - Light(const Vector3 &position, const Colour &acolour): + pos(Vector(0,0,0)), colour(Colour(1,1,1)), cast_shadows(true) {}; + Light(const Vector &position, const Colour &acolour): pos(position), colour(acolour), cast_shadows(true) {}; void castShadows(bool cast) { cast_shadows = cast; }; }; @@ -170,15 +178,17 @@ class BBox { public: - Vector3 L; - Vector3 H; + Vector L; + Vector H; BBox(): L(), H() {}; - BBox(const Vector3 aL, const Vector3 aH): L(aL), H(aH) {}; + BBox(const Vector aL, const Vector aH): L(aL), H(aH) {}; Float w() { return H.x-L.x; }; Float h() { return H.y-L.y; }; Float d() { return H.z-L.z; }; bool intersect(const Ray &ray, Float &a, Float &b); +#ifndef NO_SSE __m128 intersect_packet(const RayPacket &rays, __m128 &a, __m128 &b); +#endif }; #endif diff -r f6a72eb99631 -r 9d66d323c354 include/serialize.h --- a/include/serialize.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/serialize.h Fri May 02 13:27:47 2008 +0200 @@ -52,6 +52,6 @@ ostream & operator<<(ostream &st, Shape &o); ostream & operator<<(ostream &st, Vertex &o); ostream & operator<<(ostream &st, Container &o); -istream & operator>>(istream &st, Vector3 &v); +istream & operator>>(istream &st, Vector &v); #endif diff -r f6a72eb99631 -r 9d66d323c354 include/shapes.h --- a/include/shapes.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/shapes.h Fri May 02 13:27:47 2008 +0200 @@ -55,6 +55,7 @@ // first intersection point virtual bool intersect(const Ray &ray, Float &dist) const = 0; +#ifndef NO_SSE virtual __m128 intersect_packet(const RayPacket &rays, __m128 &dists) { __m128 results; @@ -64,6 +65,7 @@ ((int*)&results)[3] = intersect(rays[3], ((float*)&dists)[3]) ? -1 : 0; return results; }; +#endif // all intersections (only for CSG) virtual bool intersect_all(const Ray &ray, Float dist, vector &allts) const = 0; @@ -72,7 +74,7 @@ virtual bool intersect_bbox(const BBox &bbox) const = 0; // normal at point P - virtual const Vector3 normal(const Vector3 &P) const = 0; + virtual const Vector normal(const Vector &P) const = 0; virtual BBox get_bbox() const = 0; @@ -89,25 +91,27 @@ */ class Sphere: public Shape { - Vector3 center; + Vector center; Float radius; Float sqr_radius; Float inv_radius; public: - Sphere(const Vector3 &acenter, const Float aradius, Material *amaterial): + Sphere(const Vector &acenter, const Float aradius, Material *amaterial): center(acenter), radius(aradius), sqr_radius(aradius*aradius), inv_radius(1.0f/aradius) { material = amaterial; } bool intersect(const Ray &ray, Float &dist) const; - __m128 intersect_packet(const RayPacket &rays, __m128 &dists); bool intersect_all(const Ray &ray, Float dist, vector &allts) const; bool intersect_bbox(const BBox &bbox) const; - const Vector3 normal(const Vector3 &P) const { return (P - center) * inv_radius; }; + const Vector normal(const Vector &P) const { return (P - center) * inv_radius; }; BBox get_bbox() const; - const Vector3 getCenter() const { return center; }; + const Vector getCenter() const { return center; }; Float getRadius() const { return radius; }; ostream & dump(ostream &st) const; +#ifndef NO_SSE + __m128 intersect_packet(const RayPacket &rays, __m128 &dists); +#endif }; /** @@ -115,10 +119,10 @@ */ class Box: public Shape { - Vector3 L; - Vector3 H; + Vector L; + Vector H; public: - Box(const Vector3 &aL, const Vector3 &aH, Material *amaterial): L(aL), H(aH) + Box(const Vector &aL, const Vector &aH, Material *amaterial): L(aL), H(aH) { for (int i = 0; i < 3; i++) if (L.cell[i] > H.cell[i]) @@ -126,14 +130,16 @@ material = amaterial; }; bool intersect(const Ray &ray, Float &dist) const; - __m128 intersect_packet(const RayPacket &rays, __m128 &dists); bool intersect_all(const Ray &ray, Float dist, vector &allts) const { return false; }; bool intersect_bbox(const BBox &bbox) const; - const Vector3 normal(const Vector3 &P) const; + const Vector normal(const Vector &P) const; BBox get_bbox() const { return BBox(L, H); }; - const Vector3 getL() const { return L; }; - const Vector3 getH() const { return H; }; + const Vector getL() const { return L; }; + const Vector getH() const { return H; }; ostream & dump(ostream &st) const; +#ifndef NO_SSE + __m128 intersect_packet(const RayPacket &rays, __m128 &dists); +#endif }; /** @@ -142,8 +148,8 @@ class Vertex { public: - Vector3 P; - Vertex(const Vector3 &aP): P(aP) {}; + Vector P; + Vertex(const Vector &aP): P(aP) {}; virtual ~Vertex() {}; virtual ostream & dump(ostream &st) const; }; @@ -154,12 +160,12 @@ class NormalVertex: public Vertex { public: - Vector3 N; + Vector N; NormalVertex(const NormalVertex *v): Vertex(v->P), N(v->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; }; + NormalVertex(const Vector &aP): Vertex(aP) {}; + NormalVertex(const Vector &aP, const Vector &aN): Vertex(aP), N(aN) {}; + const Vector &getNormal() { return N; }; + void setNormal(const Vector &aN) { N = aN; }; ostream & dump(ostream &st) const; }; @@ -180,13 +186,13 @@ #ifdef TRI_PLUCKER Float pla[6], plb[6], plc[6]; #endif - Vector3 N; - const Vector3 smooth_normal(const Vector3 &P) const + Vector N; + const Vector smooth_normal(const Vector &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; + const Vector &NA = static_cast(A)->N; + const Vector &NB = static_cast(B)->N; + const Vector &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]; @@ -194,7 +200,7 @@ 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); + Vector n = NA + u * (NB - NA) + v * (NC - NA); n.normalize(); return n; #else @@ -207,15 +213,15 @@ Triangle() {}; Triangle(Vertex *aA, Vertex *aB, Vertex *aC, Material *amaterial); bool intersect(const Ray &ray, Float &dist) const; -#ifdef TRI_BARI_PRE - __m128 intersect_packet(const RayPacket &rays, __m128 &dists); -#endif bool intersect_all(const Ray &ray, Float dist, vector &allts) const {return false;}; bool intersect_bbox(const BBox &bbox) const; - const Vector3 normal(const Vector3 &P) const { return (material->smooth ? smooth_normal(P) : N); }; - const Vector3 getNormal() const { return N; }; + const Vector normal(const Vector &P) const { return (material->smooth ? smooth_normal(P) : N); }; + const Vector getNormal() const { return N; }; BBox get_bbox() const; ostream & dump(ostream &st) const; +#if not defined(NO_SSE) and defined(TRI_BARI_PRE) + __m128 intersect_packet(const RayPacket &rays, __m128 &dists); +#endif }; template class Array diff -r f6a72eb99631 -r 9d66d323c354 include/vector.h --- a/include/vector.h Tue Apr 29 23:31:08 2008 +0200 +++ b/include/vector.h Fri May 02 13:27:47 2008 +0200 @@ -1,5 +1,5 @@ /* - * vector.h: Vector3 class with Colour alias + * vector.h: Vector class with Colour alias * * This file is part of Pyrit Ray Tracer. * @@ -37,145 +37,177 @@ /** * three cell vector */ -class Vector3 +class Vector { public: // data union { - struct { - Float x, y, z; - }; - struct { - Float r, g, b; - }; - Float cell[3]; +#ifndef NO_SSE + __m128 mps; +#endif + Float cell[4]; + struct { Float x, y, z, w; }; + struct { Float r, g, b, a; }; }; // constructors - Vector3(): x(0.0f), y(0.0f), z(0.0f) {}; - Vector3(Float ax, Float ay, Float az): x(ax), y(ay), z(az) {}; +#ifndef NO_SSE + Vector(__m128 m): mps(m) {}; +#endif + Vector(): x(0.0f), y(0.0f), z(0.0f), w(1.0) {}; + Vector(Float ax, Float ay, Float az): x(ax), y(ay), z(az), w(1.0) {}; // index operator const Float &operator[](int index) const { return cell[index]; }; - bool operator==(Vector3 &v) const { return x==v.x && y==v.y && z==v.z; }; + bool operator==(Vector &v) const { return x==v.x && y==v.y && z==v.z; }; // normalize - Vector3 normalize() + Vector normalize() { - Float f = 1.0f / mag(); - x *= f; - y *= f; - z *= f; + const Float f = 1.0f / mag(); + *this *= f; return *this; }; // get normalized copy - friend Vector3 normalize(Vector3 &v) + friend Vector normalize(const Vector &v) { const Float f = 1.0f / v.mag(); return v * f; }; // square magnitude, magnitude - Float mag2() const { return x * x + y * y + z * z; }; + Float mag2() const { return dot(*this, *this); }; Float mag() const { return sqrtf(mag2()); }; // negative - Vector3 operator-() const { return Vector3(-x, -y, -z); }; + Vector operator-() const { return Vector(-x, -y, -z); }; // accumulate - Vector3 operator+=(const Vector3 &v) + Vector operator+=(const Vector &v) { +#ifdef NO_SSE x += v.x; y += v.y; z += v.z; +#else + mps = _mm_add_ps(mps, v.mps); +#endif return *this; }; - // cut - Vector3 operator/=(const Float &f) + // multiply + Vector operator*=(const Float &f) { - x /= f; - y /= f; - z /= f; + x *= f; + y *= f; + z *= f; + return *this; + }; + + + // cut + Vector operator/=(const Float &f) + { + Float finv = 1./f; + x *= finv; + y *= finv; + z *= finv; return *this; }; // sum - friend Vector3 operator+(const Vector3 &a, const Vector3 &b) + friend Vector operator+(const Vector &a, const Vector &b) { - return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); +#ifdef NO_SSE + return Vector(a.x + b.x, a.y + b.y, a.z + b.z); +#else + return Vector(_mm_add_ps(a.mps, b.mps)); +#endif }; // difference - friend Vector3 operator-(const Vector3 &a, const Vector3 &b) + friend Vector operator-(const Vector &a, const Vector &b) { - return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); +#ifdef NO_SSE + return Vector(a.x - b.x, a.y - b.y, a.z - b.z); +#else + return Vector(_mm_sub_ps(a.mps, b.mps)); +#endif }; // dot product - friend Float dot(const Vector3 &a, const Vector3 &b) + friend Float dot(const Vector &a, const Vector &b) { return a.x * b.x + a.y * b.y + a.z * b.z; }; // cross product - friend Vector3 cross(const Vector3 &a, const Vector3 &b) + friend Vector cross(const Vector &a, const Vector &b) { - return Vector3(a.y * b.z - a.z * b.y, + return Vector(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); }; // product of vector and scalar - friend Vector3 operator*(const Vector3 &v, const Float &f) + friend Vector operator*(const Vector &v, const Float &f) { - return Vector3(f * v.x, f * v.y, f * v.z); + return Vector(f * v.x, f * v.y, f * v.z); }; - friend Vector3 operator*(const Float &f, const Vector3 &v) + friend Vector operator*(const Float &f, const Vector &v) { return v * f; }; // scalar division - friend Vector3 operator/(const Vector3 &v, const Float &f) + friend Vector operator/(const Vector &v, const Float &f) { - return Vector3(v.x / f, v.y / f, v.z / f); + const Float finv = 1./f; + return Vector(v.x * finv, v.y * finv, v.z * finv); }; - friend Vector3 operator/(const Float &f, const Vector3 &v) + friend Vector operator/(const Float &f, const Vector &v) { - return Vector3(f / v.x, f / v.y, f / v.z); +#ifdef NO_SSE + return Vector(f / v.x, f / v.y, f / v.z); +#else + return Vector(_mm_div_ps(_mm_set_ps1(f), v.mps)); +#endif }; // vector plus scalar - friend Vector3 operator+(const Vector3 &v, const Float &f) + friend Vector operator+(const Vector &v, const Float &f) { - return Vector3(v.x + f, v.y + f, v.z + f); + return Vector(v.x + f, v.y + f, v.z + f); }; // vector minus scalar - friend Vector3 operator-(const Vector3 &v, const Float &f) + friend Vector operator-(const Vector &v, const Float &f) { - return Vector3(v.x - f, v.y - f, v.z - f); + return Vector(v.x - f, v.y - f, v.z - f); }; // cell by cell product (only usable for colours) - friend Vector3 operator*(const Vector3 &a, const Vector3 &b) + friend Vector operator*(const Vector &a, const Vector &b) { - return Vector3(a.x * b.x, a.y * b.y, a.z * b.z); +#ifdef NO_SSE + return Vector(a.x * b.x, a.y * b.y, a.z * b.z); +#else + return Vector(_mm_mul_ps(a.mps, b.mps)); +#endif }; // write - friend ostream & operator<<(ostream &st, const Vector3 &v) + friend ostream & operator<<(ostream &st, const Vector &v) { return st << "(" << v.x << "," << v.y << "," << v.z << ")"; }; // read - friend istream & operator>>(istream &st, Vector3 &v) + friend istream & operator>>(istream &st, Vector &v) { char s[10]; st.getline(s, 10, '('); @@ -189,8 +221,9 @@ }; }; -typedef Vector3 Colour; +typedef Vector Colour; +#ifndef NO_SSE class VectorPacket { public: @@ -211,12 +244,17 @@ VectorPacket() {}; VectorPacket(__m128 ax, __m128 ay, __m128 az): mx(ax), my(ay), mz(az) {}; - VectorPacket(const Vector3 &v): + VectorPacket(const Vector &v): mx(_mm_set_ps1(v.x)), my(_mm_set_ps1(v.y)), mz(_mm_set_ps1(v.z)) {}; - Vector3 getVector(int i) const + Vector getVector(int i) const { - return Vector3(x[i], y[i], z[i]); + return Vector(x[i], y[i], z[i]); + }; + + void setVector(int i, const Vector &v) + { + x[i] = v.x; y[i] = v.y; z[i] = v.z; }; void normalize() @@ -234,6 +272,39 @@ mz = _mm_mul_ps(mz, m); }; + // accumulate + VectorPacket operator+=(const VectorPacket &v) + { + mx = _mm_add_ps(mx, v.mx); + my = _mm_add_ps(my, v.my); + mz = _mm_add_ps(mz, v.mz); + return *this; + }; + + // add to non-masked components + VectorPacket selectiveAdd(__m128 mask, const VectorPacket &v) + { + mx = _mm_or_ps(_mm_and_ps(mask, _mm_add_ps(mx, v.mx)), + _mm_andnot_ps(mask, mx)); + my = _mm_or_ps(_mm_and_ps(mask, _mm_add_ps(my, v.my)), + _mm_andnot_ps(mask, my)); + mz = _mm_or_ps(_mm_and_ps(mask, _mm_add_ps(mz, v.mz)), + _mm_andnot_ps(mask, mz)); + return *this; + }; + + // add scalar to non-masked components + VectorPacket selectiveAdd(__m128 mask, const __m128 m) + { + mx = _mm_or_ps(_mm_and_ps(mask, _mm_add_ps(mx, m)), + _mm_andnot_ps(mask, mx)); + my = _mm_or_ps(_mm_and_ps(mask, _mm_add_ps(my, m)), + _mm_andnot_ps(mask, my)); + mz = _mm_or_ps(_mm_and_ps(mask, _mm_add_ps(mz, m)), + _mm_andnot_ps(mask, mz)); + return *this; + }; + // dot product friend __m128 dot(const VectorPacket &a, const VectorPacket &b) { @@ -275,6 +346,15 @@ _mm_div_ps(m, v.mz)); }; + // cell by cell product (only usable for colours) + friend VectorPacket operator*(const VectorPacket &a, const VectorPacket &b) + { + return VectorPacket( + _mm_mul_ps(a.mx, b.mx), + _mm_mul_ps(a.my, b.my), + _mm_mul_ps(a.mz, b.mz)); + }; + // write to character stream friend ostream & operator<<(ostream &st, const VectorPacket &v) { @@ -283,5 +363,6 @@ }; }; +#endif #endif diff -r f6a72eb99631 -r 9d66d323c354 src/SConscript --- a/src/SConscript Tue Apr 29 23:31:08 2008 +0200 +++ b/src/SConscript Fri May 02 13:27:47 2008 +0200 @@ -1,6 +1,6 @@ -Import('env') -env.Append(CPPPATH = '#include') +Import('env buildmodule') +env = env.Clone(CPPPATH = '#include') pyenv = env.Clone() if env['PLATFORM'] == 'win32': import sys @@ -26,17 +26,16 @@ objs.append( env.Object(src) ) shared_objs.append( env.SharedObject(src) ) -pymodule = pyenv.SharedLibrary('pyrit', - ['raytracermodule.cc']+shared_objs, - SHLIBPREFIX = '', - CCFLAGS = '$CCFLAGS -Wno-write-strings') - -lib = env.StaticLibrary('pyrit', objs) - -env.Alias('objs', objs) -env.Alias('static-lib', lib) -env.Alias('shared-objs', shared_objs) -env.Alias('python-module', pymodule) -env.Alias('libs', ['static-lib', 'python-module']) - -Return('lib pymodule') +if buildmodule: + pymodule = pyenv.SharedLibrary('pyrit', + ['raytracermodule.cc']+shared_objs, + SHLIBPREFIX = '', + CCFLAGS = '$CCFLAGS -Wno-write-strings') + env.Alias('shared-objs', shared_objs) + env.Alias('python-module', pymodule) + Return('pymodule') +else: + lib = env.StaticLibrary('pyrit', objs) + env.Alias('objs', objs) + env.Alias('static-lib', lib) + Return('lib') diff -r f6a72eb99631 -r 9d66d323c354 src/container.cc --- a/src/container.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/src/container.cc Fri May 02 13:27:47 2008 +0200 @@ -3,7 +3,7 @@ * * This file is part of Pyrit Ray Tracer. * - * Copyright 2007 Radek Brich + * Copyright 2007, 2008 Radek Brich * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,7 +34,7 @@ if (shapes.size() == 0) { /* initialize bounding box */ bbox = aShape->get_bbox(); - const Vector3 E(e, e, e); + const Vector E(e, e, e); bbox = BBox(bbox.L - E, bbox.H + E); } else { /* adjust bounding box */ @@ -60,6 +60,7 @@ return nearest_shape; } +#ifndef NO_SSE void Container::packet_intersection(const Shape **origin_shapes, const RayPacket &rays, Float *nearest_distances, Shape **nearest_shapes) { @@ -67,6 +68,7 @@ nearest_shapes[i] = nearest_intersection(origin_shapes[i], rays[i], nearest_distances[i]); } +#endif ostream & Container::dump(ostream &st) { diff -r f6a72eb99631 -r 9d66d323c354 src/kdtree.cc --- a/src/kdtree.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/src/kdtree.cc Fri May 02 13:27:47 2008 +0200 @@ -3,7 +3,7 @@ * * This file is part of Pyrit Ray Tracer. * - * Copyright 2006, 2007 Radek Brich + * Copyright 2006, 2007, 2008 Radek Brich * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -54,7 +54,7 @@ { KdNode* node; /* pointer to far child */ Float t; /* the entry/exit signed distance */ - Vector3 pb; /* the coordinates of entry/exit point */ + Vector pb; /* the coordinates of entry/exit point */ int prev; }; @@ -150,7 +150,7 @@ // export kd-tree as .obj for visualization // this would be hard to reconstruct later static ofstream F("kdtree.obj"); - Vector3 v; + Vector v; static int f=0; v.cell[axis] = node->getSplit(); v.cell[(axis+1)%3] = bounds.L.cell[(axis+1)%3]; @@ -239,7 +239,7 @@ Float splitVal; int axis; static const int mod3[] = {0,1,2,0,1}; - const Vector3 invdir = 1 / ray.dir; + const Vector invdir = 1 / ray.dir; while (node) { /* loop until a leaf is found */ @@ -328,6 +328,7 @@ return NULL; } +#ifndef NO_SSE // stack element for kd-tree traversal (packet version) struct StackElem4 { @@ -514,6 +515,7 @@ /* ray leaves the scene */ } +#endif ostream & operator<<(ostream &st, KdNode &node) { diff -r f6a72eb99631 -r 9d66d323c354 src/octree.cc --- a/src/octree.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/src/octree.cc Fri May 02 13:27:47 2008 +0200 @@ -3,7 +3,7 @@ * * This file is part of Pyrit Ray Tracer. * - * Copyright 2007 Radek Brich + * Copyright 2007, 2008 Radek Brich * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -170,8 +170,8 @@ # define tzm st_cur->tzm int a = 0; - Vector3 ro(ray.o); - Vector3 rdir(ray.dir); + Vector ro(ray.o); + Vector rdir(ray.dir); if (rdir.x < 0.0) { diff -r f6a72eb99631 -r 9d66d323c354 src/raytracer.cc --- a/src/raytracer.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/src/raytracer.cc Fri May 02 13:27:47 2008 +0200 @@ -34,7 +34,7 @@ // Hammersley spherical point distribution // http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html -Vector3 Raytracer::SphereDistribute(int i, int n, Float extent, Vector3 &normal) +Vector Raytracer::SphereDistribute(int i, int n, Float extent, const Vector &normal) { Float p, t, st, phi, phirad; int kk; @@ -67,23 +67,7 @@ y = xx*sin(q) + yy*cos(q); z = zz; - return Vector3(x, y, z); -} - -// ---- tyto dve funkce budou v budouci verzi metody objektu PhongShader - -// calculate shader function -// P is point of intersection, N normal in this point -Colour PhongShader_ambient(const Material &mat, const Vector3 &P) -{ - Colour col; - if (mat.texture) - col = mat.texture->evaluate(P); - else - col = mat.colour; - - // ambient - return mat.ambient * col; + return Vector(x, y, z); } /* @@ -92,82 +76,138 @@ R direction of reflected ray, V direction to the viewer */ -Colour PhongShader_calculate(const Material &mat, - const Vector3 &P, const Vector3 &N, const Vector3 &R, const Vector3 &V, - const Light &light) +Colour Raytracer::PhongShader(const Shape *shape, + const Vector &P, const Vector &N, const Vector &V) { - Colour I = Colour(); - Vector3 L = light.pos - P; - L.normalize(); - Float L_dot_N = dot(L, N); - Float R_dot_V = dot(R, V); - - Colour col; - if (mat.texture) - col = mat.texture->evaluate(P); - else - col = mat.colour; - - // diffuse - I = mat.diffuse * col * light.colour * L_dot_N; + Colour col, acc; + Material * const &mat = shape->material; - // specular - if (R_dot_V > 0) - I += mat.specular * light.colour * powf(R_dot_V, mat.shininess); - return I; -} + if (mat->texture) + col = mat->texture->evaluate(P); + else + col = mat->colour; -Colour Raytracer::shader_evalulate(const Ray &ray, int depth, Shape *origin_shape, - Float nearest_distance, Shape *nearest_shape) -{ - 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; - from_inside = true; - } - - col = PhongShader_ambient(*nearest_shape->material, P); + // ambient + acc = mat->ambient * col; vector::iterator light; - for (light = lights.begin(); light != lights.end(); light++) { - Vector3 jo, L = (*light)->pos - P; // direction vector to light - L.normalize(); - Float L_dot_N = dot(L, normal); - if (L_dot_N > 0) { + for (light = lights.begin(); light != lights.end(); light++) + { + const Vector L = normalize((*light)->pos - P); // direction vector to light + const Float L_dot_N = dot(L, N); + if (L_dot_N > 0) + { // test if this light is occluded (sharp shadows) if ((*light)->cast_shadows) { - Ray shadow_ray = Ray(P, L); + const Ray shadow_ray = Ray(P, L); Float dist = FLT_MAX; - if (top->nearest_intersection(nearest_shape, shadow_ray, dist)) + if (top->nearest_intersection(shape, shadow_ray, dist)) continue; } - // shading function - Vector3 R = L - 2.0 * L_dot_N * normal; - col += PhongShader_calculate(*nearest_shape->material, - P, normal, R, ray.dir, **light); + const Vector R = L - 2.0 * L_dot_N * N; + const Float R_dot_V = dot(R, V); + + // diffuse + acc += mat->diffuse * col * (*light)->colour * L_dot_N; + + // specular + if (R_dot_V > 0) + acc += mat->specular * (*light)->colour * powf(R_dot_V, mat->shininess); } } + return acc; +} + +#ifndef NO_SSE +VectorPacket Raytracer::PhongShader_packet(const Shape **shapes, + const VectorPacket &P, const VectorPacket &N, const VectorPacket &V) +{ + VectorPacket acc, colour; + union { __m128 ambient; float ambient_f[4]; }; + union { __m128 diffuse; float diffuse_f[4]; }; + union { __m128 specular; float specular_f[4]; }; + union { __m128 shininess; float shininess_f[4]; }; + + for (int i = 0; i < 4; i++) + if (shapes[i] == NULL) + { + ambient_f[i] = 0; + diffuse_f[i] = 0; + specular_f[i] = 0; + shininess_f[i] = 0; + } + else + { + Material * const &mat = shapes[i]->material; + if (mat->texture) + colour.setVector(i, mat->texture->evaluate(P.getVector(i))); + else + colour.setVector(i, mat->colour); + ambient_f[i] = mat->ambient; + diffuse_f[i] = mat->diffuse; + specular_f[i] = mat->specular; + shininess_f[i] = mat->shininess; + } + + // ambient + acc = colour * ambient; + + Shape **shadow_shapes; + vector::iterator light; + for (light = lights.begin(); light != lights.end(); light++) + { + // direction vector to light + VectorPacket L = VectorPacket((*light)->pos) - P; + L.normalize(); + const __m128 L_dot_N = dot(L, N); + __m128 valid = _mm_cmpgt_ps(L_dot_N, mZero); + + // test if this light is occluded (sharp shadows) + if ((*light)->cast_shadows) + { + const RayPacket shadow_rays = RayPacket(P, L); + union { __m128 dists; float dists_f[4]; }; + dists = mInf; + top->packet_intersection(shapes, shadow_rays, + dists_f, shadow_shapes); + valid = _mm_and_ps(valid, _mm_cmpeq_ps(dists, mInf)); + } + + const VectorPacket R = L - N * _mm_mul_ps(mTwo, L_dot_N); + const __m128 R_dot_V = dot(R, V); + + // diffuse + acc.selectiveAdd(valid, + colour * VectorPacket((*light)->colour) * _mm_mul_ps(diffuse, L_dot_N)); + + // specular + valid = _mm_and_ps(valid, _mm_cmpgt_ps(R_dot_V, mZero)); + __m128 spec = _mm_mul_ps(_mm_mul_ps(specular, _mm_set_ps1((*light)->colour.r)), + _mm_fastpow(R_dot_V, shininess)); + acc.selectiveAdd(valid, spec); + } + return acc; +} +#endif + +void Raytracer::lightScatter(const Ray &ray, const Shape *shape, int depth, + const Vector &P, const Vector &normal, bool from_inside, Colour &col) +{ if (depth < max_depth) { Colour trans_col, refl_col; - Float trans = nearest_shape->material->transmissivity; - Float refl = nearest_shape->material->reflectivity; + Float trans = shape->material->transmissivity; + Float refl = 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; + Vector newdir = ray.dir + 2.0 * cos_i * normal; Ray newray = Ray(P, newdir); - refl_col = raytrace(newray, depth + 1, nearest_shape); + refl_col = raytrace(newray, depth + 1, shape); } // refraction @@ -176,14 +216,14 @@ Float n, n1, n2; if (from_inside) { - n1 = nearest_shape->material->refract_index; + n1 = shape->material->refract_index; n2 = 1.0; n = n1; } else { n1 = 1.0; - n2 = nearest_shape->material->refract_index; + n2 = shape->material->refract_index; n = 1.0 / n2; } const Float sin2_t = n*n * (1 - cos_i*cos_i); @@ -202,7 +242,7 @@ 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; + Vector newdir = n * ray.dir + (n*cos_i - cos_t) * normal; Ray newray = Ray(P + 0.001*newdir, newdir); trans_col = raytrace(newray, depth + 1, NULL); } @@ -211,14 +251,15 @@ } // ambient occlusion - if (!from_inside && ao_samples) + if (ao_samples && !from_inside) { Float miss = 0; - for (int i = 0; i < ao_samples; i++) { - Vector3 dir = SphereDistribute(i, ao_samples, ao_angle, normal); + for (int i = 0; i < ao_samples; i++) + { + Vector dir = SphereDistribute(i, ao_samples, ao_angle, normal); Ray ao_ray = Ray(P, dir); Float dist = ao_distance; - Shape *shape_in_way = top->nearest_intersection(nearest_shape, ao_ray, dist); + Shape *shape_in_way = top->nearest_intersection(shape, ao_ray, dist); if (shape_in_way == NULL) miss += 1.0; else @@ -227,11 +268,9 @@ Float ao_intensity = miss / ao_samples; col = col * ao_intensity; } - - return col; } -Colour Raytracer::raytrace(Ray &ray, int depth, Shape *origin_shape) +Colour Raytracer::raytrace(Ray &ray, int depth, const Shape *origin_shape) { Float nearest_distance = Inf; Shape *nearest_shape = top->nearest_intersection(origin_shape, ray, nearest_distance); @@ -239,23 +278,83 @@ if (nearest_shape == NULL) return bg_colour; else - return shader_evalulate(ray, depth, origin_shape, nearest_distance, nearest_shape); + { + const Vector P = ray.o + ray.dir * nearest_distance; // point of intersection + Vector normal = nearest_shape->normal(P); + bool from_inside = false; + + // make shapes double sided + if (dot(normal, ray.dir) > 0.0) + { + normal = - normal; + from_inside = true; + } + + // shading function + Colour col = PhongShader(nearest_shape, P, normal, ray.dir); + lightScatter(ray, nearest_shape, depth, P, normal, from_inside, col); + return col; + } } +#ifndef NO_SSE void Raytracer::raytracePacket(RayPacket &rays, Colour *results) { - Float nearest_distances[4] = {Inf,Inf,Inf,Inf}; + union { + float nearest_distances[4]; + __m128 m_nearest_distances; + }; + __m128 mask; Shape *nearest_shapes[4]; static const Shape *origin_shapes[4] = {NULL, NULL, NULL, NULL}; + m_nearest_distances = mInf; + mask = mAllSet; + top->packet_intersection(origin_shapes, rays, nearest_distances, nearest_shapes); + mask = _mm_cmpneq_ps(m_nearest_distances, mInf); + if (!_mm_movemask_ps(mask)) + { + for (int i = 0; i < 4; i++) + results[i] = bg_colour; + return; + } + + const VectorPacket P = rays.o + rays.dir * m_nearest_distances; // point of intersection + + VectorPacket normal; + for (int i = 0; i < 4; i++) + if (nearest_shapes[i] != NULL) + normal.setVector(i, nearest_shapes[i]->normal(P.getVector(i))); + + // make shapes double sided + __m128 from_inside = _mm_cmpgt_ps(dot(normal, rays.dir), mZero); + normal.mx = _mm_or_ps(_mm_and_ps(from_inside, _mm_sub_ps(mZero, normal.mx)), + _mm_andnot_ps(from_inside, normal.mx)); + normal.my = _mm_or_ps(_mm_and_ps(from_inside, _mm_sub_ps(mZero, normal.my)), + _mm_andnot_ps(from_inside, normal.my)); + normal.mz = _mm_or_ps(_mm_and_ps(from_inside, _mm_sub_ps(mZero, normal.mz)), + _mm_andnot_ps(from_inside, normal.mz)); + + // shading function + VectorPacket pres = + PhongShader_packet(const_cast(nearest_shapes), P, normal, rays.dir); + //pres.mx = _mm_or_ps(_mm_and_ps(mask, pres.mx), _mm_andnot_ps(mask, _mm_set_ps1(bg_colour.r))); + //pres.my = _mm_or_ps(_mm_and_ps(mask, pres.my), _mm_andnot_ps(mask, _mm_set_ps1(bg_colour.g))); + //pres.mz = _mm_or_ps(_mm_and_ps(mask, pres.mz), _mm_andnot_ps(mask, _mm_set_ps1(bg_colour.b))); + for (int i = 0; i < 4; i++) - if (nearest_shapes[i] == NULL) - results[i] = bg_colour; + if (nearest_shapes[i] != NULL) + { + results[i] = pres.getVector(i); + lightScatter(rays[i], nearest_shapes[i], 0, + P.getVector(i), normal.getVector(i), (_mm_movemask_ps(from_inside)>>i)&1, + results[i]); + } else - results[i] = shader_evalulate(rays[i], 0, NULL, - nearest_distances[i], nearest_shapes[i]); + results[i] = bg_colour; } +#endif void *Raytracer::raytrace_worker(void *d) { @@ -265,8 +364,10 @@ Colour my_colours[my_queue_size]; int my_count; Ray ray; +#ifndef NO_SSE RayPacket rays; const bool can_use_packets = (rt->use_packets && rt->sampler->packetableSamples()); +#endif for (;;) { pthread_mutex_lock(&rt->sample_queue_mutex); @@ -306,6 +407,7 @@ pthread_mutex_unlock(&rt->sample_queue_mutex); // do the work +#ifndef NO_SSE if (can_use_packets) { // packet ray tracing @@ -317,6 +419,7 @@ } } else +#endif { // single ray tracing for (int i = 0; i < my_count; i++) diff -r f6a72eb99631 -r 9d66d323c354 src/raytracermodule.cc --- a/src/raytracermodule.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/src/raytracermodule.cc Fri May 02 13:27:47 2008 +0200 @@ -122,7 +122,7 @@ return NULL; v = PyObject_New(LightObject, &LightType); - v->light = new Light(Vector3(px, py, pz), Colour(cr, cg, cb)); + v->light = new Light(Vector(px, py, pz), Colour(cr, cg, cb)); return (PyObject*)v; } @@ -222,11 +222,11 @@ v = PyObject_New(CameraObject, &CameraType); if (TLookAt) - v->camera = new Camera(Vector3(ex, ey, ez), - Vector3(lax, lay, laz), Vector3(upx, upy, upz)); + v->camera = new Camera(Vector(ex, ey, ez), + Vector(lax, lay, laz), Vector(upx, upy, upz)); else - v->camera = new Camera(Vector3(ex, ey, ez), - Vector3(px, py, pz), Vector3(ux, uy, uz), Vector3(vx, vy, vz)); + v->camera = new Camera(Vector(ex, ey, ez), + Vector(px, py, pz), Vector(ux, uy, uz), Vector(vx, vy, vz)); return (PyObject*)v; } @@ -248,7 +248,7 @@ if (!PyArg_ParseTuple(TEye, "fff", &ex, &ey, &ez)) return NULL; - ((CameraObject *)self)->camera->setEye(Vector3(ex, ey, ez)); + ((CameraObject *)self)->camera->setEye(Vector(ex, ey, ez)); Py_INCREF(Py_None); return Py_None; @@ -455,7 +455,7 @@ return NULL; v = PyObject_New(NormalVertexObject, &NormalVertexType); - v->nvertex = new NormalVertex(Vector3(vx, vy, vz), Vector3(nx, ny, nz)); + v->nvertex = new NormalVertex(Vector(vx, vy, vz), Vector(nx, ny, nz)); } return (PyObject*)v; } @@ -477,7 +477,7 @@ if (!PyArg_ParseTuple(TNor, "fff", &nx, &ny, &nz)) return NULL; - ((NormalVertexObject *)self)->nvertex->setNormal(Vector3(nx,ny,nz).normalize()); + ((NormalVertexObject *)self)->nvertex->setNormal(Vector(nx,ny,nz).normalize()); Py_INCREF(Py_None); return Py_None; @@ -567,7 +567,7 @@ { PyObject *obj; - Vector3 N = ((Triangle*)((TriangleObject *)self)->shape.shape)->getNormal(); + Vector N = ((Triangle*)((TriangleObject *)self)->shape.shape)->getNormal(); obj = Py_BuildValue("(fff)", N.x, N.y, N.z); return obj; @@ -614,7 +614,7 @@ return NULL; v = PyObject_New(SphereObject, &SphereType); - v->shape.shape = new Sphere(Vector3(cx, cy, cz), radius, material->material); + v->shape.shape = new Sphere(Vector(cx, cy, cz), radius, material->material); Py_INCREF(material); return (PyObject*)v; } @@ -664,7 +664,7 @@ return NULL; v = PyObject_New(BoxObject, &BoxType); - v->shape.shape = new Box(Vector3(lx, ly, lz), Vector3(hx, hy, hz), material->material); + v->shape.shape = new Box(Vector(lx, ly, lz), Vector(hx, hy, hz), material->material); Py_INCREF(material); return (PyObject*)v; } diff -r f6a72eb99631 -r 9d66d323c354 src/scene.cc --- a/src/scene.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/src/scene.cc Fri May 02 13:27:47 2008 +0200 @@ -53,15 +53,15 @@ x = 2*( (t8 + t10)*p.x + (t6 - t4)*p.y + (t3 + t7)*p.z ) + p.x; y = 2*( (t4 + t6)*p.x + (t5 + t10)*p.y + (t9 - t2)*p.z ) + p.y; z = 2*( (t7 - t3)*p.x + (t2 + t9)*p.y + (t5 + t8)*p.z ) + p.z; - p = Vector3(x,y,z); + p = Vector(x,y,z); x = 2*( (t8 + t10)*u.x + (t6 - t4)*u.y + (t3 + t7)*u.z ) + u.x; y = 2*( (t4 + t6)*u.x + (t5 + t10)*u.y + (t9 - t2)*u.z ) + u.y; z = 2*( (t7 - t3)*u.x + (t2 + t9)*u.y + (t5 + t8)*u.z ) + u.z; - u = Vector3(x,y,z); + u = Vector(x,y,z); x = 2*( (t8 + t10)*v.x + (t6 - t4)*v.y + (t3 + t7)*v.z ) + v.x; y = 2*( (t4 + t6)*v.x + (t5 + t10)*v.y + (t9 - t2)*v.z ) + v.y; z = 2*( (t7 - t3)*v.x + (t2 + t9)*v.y + (t5 + t8)*v.z ) + v.z; - v = Vector3(x,y,z); + v = Vector(x,y,z); p.normalize(); u.normalize(); v.normalize(); @@ -108,6 +108,7 @@ return true; } +#ifndef NO_SSE // rewrite of BBox::intersect for ray packets __m128 BBox::intersect_packet(const RayPacket &rays, __m128 &a, __m128 &b) { @@ -149,3 +150,4 @@ b = tfar; return mask; } +#endif diff -r f6a72eb99631 -r 9d66d323c354 src/serialize.cc --- a/src/serialize.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/src/serialize.cc Fri May 02 13:27:47 2008 +0200 @@ -68,7 +68,7 @@ // Vertex if (s.compare("(v") == 0) { - Vector3 P; + Vector P; st >> P; getline(st, s, ')'); vertices.push_back(new Vertex(P)); @@ -79,7 +79,7 @@ // NormalVertex if (s.compare("(vn") == 0) { - Vector3 P,N; + Vector P,N; st >> P; getline(st, s, ','); st >> N; @@ -105,7 +105,7 @@ // box if (s.compare("(box") == 0) { - Vector3 L,H; + Vector L,H; st >> L; getline(st, s, ','); st >> H; @@ -116,7 +116,7 @@ // Sphere if (s.compare("(sphere") == 0) { - Vector3 center; + Vector center; Float radius; st >> center; getline(st, s, ','); diff -r f6a72eb99631 -r 9d66d323c354 src/shapes.cc --- a/src/shapes.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/src/shapes.cc Fri May 02 13:27:47 2008 +0200 @@ -29,7 +29,7 @@ bool Sphere::intersect(const Ray &ray, Float &dist) const { - Vector3 V = ray.o - center; + Vector V = ray.o - center; register Float d = -dot(V, ray.dir); register Float Det = d * d - (dot(V,V) - sqr_radius); register Float t1,t2; @@ -54,6 +54,7 @@ return false; } +#ifndef NO_SSE __m128 Sphere::intersect_packet(const RayPacket &rays, __m128 &dists) { VectorPacket V = rays.o - VectorPacket(center); @@ -79,13 +80,14 @@ dists = _mm_or_ps(_mm_and_ps(mask, newdists), _mm_andnot_ps(mask, dists)); return mask; } +#endif /* if there should be CSG sometimes, this may be needed... */ bool Sphere::intersect_all(const Ray &ray, Float dist, vector &allts) const { //allts = new vector(); - Vector3 V = ((Ray)ray).o - center; + Vector V = ((Ray)ray).o - center; Float Vd = - dot(V, ray.dir); Float Det = Vd * Vd - (dot(V,V) - sqr_radius); @@ -175,6 +177,7 @@ return false; } +#ifndef NO_SSE __m128 Box::intersect_packet(const RayPacket &rays, __m128 &dists) { register __m128 tnear = mZero; @@ -215,6 +218,7 @@ dists = _mm_or_ps(_mm_and_ps(mask, tnear), _mm_andnot_ps(mask, dists)); return mask; } +#endif bool Box::intersect_bbox(const BBox &bbox) const { @@ -224,10 +228,10 @@ H.z > bbox.L.z && L.z < bbox.H.z); } -const Vector3 Box::normal(const Vector3 &P) const +const Vector Box::normal(const Vector &P) const { - register Vector3 l = P - L; - register Vector3 h = H - P; + register Vector l = P - L; + register Vector h = H - P; if (l.x < h.x) h.x = -1; @@ -273,7 +277,7 @@ } #ifdef TRI_PLUCKER -inline void Plucker(const Vector3 &p, const Vector3 &q, Float* pl) +inline void Plucker(const Vector &p, const Vector &q, Float* pl) { pl[0] = p.x*q.y - q.x*p.y; pl[1] = p.x*q.z - q.x*p.z; @@ -294,8 +298,8 @@ { material = amaterial; - const Vector3 c = B->P - A->P; - const Vector3 b = C->P - A->P; + const Vector c = B->P - A->P; + const Vector b = C->P - A->P; N = cross(c, b); N.normalize(); @@ -363,8 +367,8 @@ #if defined(TRI_BARI) || defined(TRI_BARI_PRE) static const int modulo3[5] = {0,1,2,0,1}; - const Vector3 &O = ray.o; - const Vector3 &D = ray.dir; + const Vector &O = ray.o; + const Vector &D = ray.dir; register const int u = modulo3[k+1]; register const int v = modulo3[k+2]; #endif @@ -392,8 +396,8 @@ #ifdef TRI_BARI // original barycentric coordinates based intesection // not optimized, just for reference - const Vector3 c = B - A; - const Vector3 b = C - A; + const Vector c = B - A; + const Vector b = C - A; // distance test const Float t = - dot( (O-A), N) / dot(D,N); if (t < Eps || t > dist) @@ -415,7 +419,7 @@ #endif } -#ifdef TRI_BARI_PRE +#if not defined(NO_SSE) and defined(TRI_BARI_PRE) __m128 Triangle::intersect_packet(const RayPacket &rays, __m128 &dists) { static const int modulo3[5] = {0,1,2,0,1}; @@ -463,14 +467,14 @@ bool Triangle::intersect_bbox(const BBox &bbox) const { - const Vector3 boxcenter = (bbox.L+bbox.H)*0.5; - const Vector3 boxhalfsize = (bbox.H-bbox.L)*0.5; - const Vector3 v0 = A->P - boxcenter; - const Vector3 v1 = B->P - boxcenter; - const Vector3 v2 = C->P - boxcenter; - const Vector3 e0 = v1-v0; - const Vector3 e1 = v2-v1; - const Vector3 e2 = v0-v2; + const Vector boxcenter = (bbox.L+bbox.H)*0.5; + const Vector boxhalfsize = (bbox.H-bbox.L)*0.5; + const Vector v0 = A->P - boxcenter; + const Vector v1 = B->P - boxcenter; + const Vector v2 = C->P - boxcenter; + const Vector e0 = v1-v0; + const Vector e1 = v2-v1; + const Vector e2 = v0-v2; Float fex = fabsf(e0.x); Float fey = fabsf(e0.y); @@ -569,7 +573,7 @@ if(min>boxhalfsize.z || max<-boxhalfsize.z) return false; /* test if the box intersects the plane of the triangle */ - Vector3 vmin,vmax; + Vector vmin,vmax; Float v; for(int q=0;q<3;q++) { diff -r f6a72eb99631 -r 9d66d323c354 tests/vector.cc --- a/tests/vector.cc Tue Apr 29 23:31:08 2008 +0200 +++ b/tests/vector.cc Fri May 02 13:27:47 2008 +0200 @@ -3,11 +3,11 @@ int main() { { - /* Vector3 */ - Vector3 a(1, 2, 3); - cout << "=== Vector3 test ===" << endl; + /* Vector */ + Vector a(1, 2, 3); + cout << "=== Vector test ===" << endl; cout << "a = " << a << endl; - Vector3 b(2, 3, 2); + Vector b(2, 3, 2); cout << "b = " << b << endl; cout << "a + b = " << a + b << endl;