# HG changeset patch # User Radek Brich # Date 1211230744 -7200 # Node ID 64638385798a6dbb3671ebbd2bf30ccc0d157e2d # Parent 2a853d284a6adc731c5eb54ebc4ffc6319d6480d add sections about demos to README update doxygen comments diff -r 2a853d284a6a -r 64638385798a DEVNOTES --- a/DEVNOTES Thu May 15 19:15:57 2008 +0200 +++ b/DEVNOTES Mon May 19 22:59:04 2008 +0200 @@ -1,19 +1,3 @@ -Classes -------- - -vector.h -- vector of three scalars, also used for colour -matrix.h -- matrix class, currently not used -quaternion.h -- quaternion class for camera rotation - -container.h -- container for shapes, base class for octree and kd-tree -octree.h -- Octree space subdivision structure for acceleration of ray-shape intersection search -kdtree.h -- KdTree space subdivision structure - -scene.h -- scene objects: Ray, Light, Camera and shapes -raytracer.h -- ray tracer class -common.h -- Float definition (float/double) and some helper functions - - Container Usage --------------- (Container|Octree|KdTree) top; diff -r 2a853d284a6a -r 64638385798a README --- a/README Thu May 15 19:15:57 2008 +0200 +++ b/README Mon May 19 22:59:04 2008 +0200 @@ -15,8 +15,6 @@ /tests -- test programs for classes /tools -- auxiliary programs -Classes organization throughout header files is explained in DEVNOTES. - Building -------- @@ -37,7 +35,7 @@ ----------------------- Not all models are included in distribution. To download the large Stanford models, type 'scons download-models', which will download -end extract the archives to appropriate location. +and extract the archives to appropriate location. The download script uses 'tar' and 'wget' utilities. @@ -48,13 +46,79 @@ Pthreads -------- -Threads can be used to render rays paralelly. Arbitrary number +Threads are used to render rays paralelly. Arbitrary number of threads can be used. For Windows, get Pthreads library here: http://sources.redhat.com/pthreads-win32/ +Python Demos +------------ +All demos render images and write the result to PNG file +named with same base name as the script. +Scene is constructed using classes imported from pyrit +Python module. + +boxes.py + 512 cubes with reflections and refractions + 4x oversampling, two lights, octree + +bunny.py + glass bunny, ~70k polygons + 4x oversampling, two lights, kd-tree + +car.py + low poly car model, LWOB format + 9x oversampling, two lights, kd-tree + +spheres_shadow.py + three spheres, sharp shadows + 4x oversampling, two lights, kd-tree + +spheres_ao.py + three spheres, ambient occlussion + +spheres_glass.py + row of glass spheres + 4x oversampling, three lights, kd-tree + +render_nff.py [input.nff] [output.png] + renders nff files (http://tog.acm.org/resources/SPD/) + reads stdin if no args given + +triangles_*.py + older examples using OBJ file format + + +C++ Demos +--------- +Compiled interactive demos. Camera can move freely in the scene. + +realtime.exe + one hundred spheres with reflections + +realtime_bunny.exe + bunny model (it loads silently, so be patient) + +spheres_shadow.exe + "interactive" version of spheres_shadow.py + +textures.exe + demo of different texture mappings + + +Control keys: + + Up, Down, Left, Right look around + w/s forward, backward + c print camera coordinates + + spheres_shadow demo supports also: + r/t, f/g, v/b move the light (-x/+x, -y/+y, -z/+z) + z/x change camera focal length (-/+) + + License ------- This software is published under terms of MIT license. diff -r 2a853d284a6a -r 64638385798a TODO --- a/TODO Thu May 15 19:15:57 2008 +0200 +++ b/TODO Mon May 19 22:59:04 2008 +0200 @@ -8,7 +8,6 @@ * PlanarMap should allow to choose normal axis * 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 - * put everything into a namespace * stochastic oversampling * absorbtion of refracted rays in dense materials (can be computed using shape distance and some 'absorbance' constant) + * put everything into a namespace diff -r 2a853d284a6a -r 64638385798a demos/dragon.py --- a/demos/dragon.py Thu May 15 19:15:57 2008 +0200 +++ b/demos/dragon.py Mon May 19 22:59:04 2008 +0200 @@ -25,6 +25,7 @@ top.optimize() sampler = DefaultSampler(800, 600) +sampler.setOversample(1) rt.setSampler(sampler) rt.render() sampler.getPixmap().writePNG('dragon.png') diff -r 2a853d284a6a -r 64638385798a demos/render_nff.py --- a/demos/render_nff.py Thu May 15 19:15:57 2008 +0200 +++ b/demos/render_nff.py Mon May 19 22:59:04 2008 +0200 @@ -1,8 +1,12 @@ #!/usr/bin/python -# read nff data from standart input and render image to render_nff.png -# see http://tog.acm.org/resources/SPD/ -# cylinders are not implemented +# Usage: render_nff.py [scene.nff] [output.png] +# reads scene from nff file and render it to PNG file +# if no output file name is given, it makes one from input name +# reads from stdin by default + +# see http://tog.acm.org/resources/SPD/ for nff format description +# cylinders are currently not implemented from pyrit import * from math import pi diff -r 2a853d284a6a -r 64638385798a include/common.h --- a/include/common.h Thu May 15 19:15:57 2008 +0200 +++ b/include/common.h Mon May 19 22:59:04 2008 +0200 @@ -59,18 +59,27 @@ #define NORETURN __attribute__((noreturn)) #endif -/* verbosity level: -0: only errors and warnings (E, W) -1: major status messages (*) -2: minor status, progress (-) -3: debug messages (D) -4: thread debug -default = 2 -*/ +/** + * verbosity level + * + * - 0: only errors and warnings (E, W) + * - 1: major status messages (*) + * - 2: minor status, progress (-) + * - 3: debug messages (D) + * - 4: thread debug + * + * default is 2 + */ extern int pyrit_verbosity; +/** + * print status or debugging message + * @param[in] vlevel verbosity level of the message + * @see pyrit_verbosity + */ void dbgmsg(const int vlevel, const char *format, ...); +/** template for minimum of three numbers */ template const Type &min3(const Type &a, const Type &b, const Type &c) { if (a <= b) @@ -89,6 +98,7 @@ } } +/** template for maximum of three numbers */ template const Type &max3(const Type &a, const Type &b, const Type &c) { if (a >= b) @@ -107,6 +117,7 @@ } } +/** trim whitespace from beginning and end of string */ inline void trim(string& s) { const char *ws = " \n"; diff -r 2a853d284a6a -r 64638385798a include/container.h --- a/include/container.h Thu May 15 19:15:57 2008 +0200 +++ b/include/container.h Mon May 19 22:59:04 2008 +0200 @@ -35,7 +35,10 @@ using namespace std; /** - * general container + * General container for shapes. + * + * Does very simple intersection test: + * all shapes are tested and the nearest intersection is returned. */ class Container { @@ -47,21 +50,36 @@ Container(): bbox(), shapes() {}; virtual ~Container() {}; + /** add pointer to shape to the container */ virtual void addShape(const Shape* aShape); //void addShapeNoExtend(const Shape* aShape) { shapes.push_back(aShape); }; + + /** + * find nearest intersection with shapes in container + * @param[in] origin_shape this shape should be avoided from the test + * @param[in] ray the ray + * @param[out] nearest_distance the nearest allowd distance of intersection; + * it is updated when closer intersection is found + * @return intersected shape or NULL if no intersection was found + */ virtual const Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray, Float &nearest_distance); - virtual void optimize() {}; - - ShapeList & getShapes() { return shapes; }; - - virtual ostream & dump(ostream &st) const; - + /** intersect with whole ray packet */ #ifndef NO_SIMD virtual void packet_intersection(const Shape* const* origin_shapes, const RayPacket &rays, Float *nearest_distances, const Shape** nearest_shapes); #endif + + /** build acceleration structures */ + virtual void optimize() {}; + + /** get reference to the shape list */ + ShapeList & getShapes() { return shapes; }; + + /** write textual representation of the acceleration structure + * and shapes in list to the stream */ + virtual ostream & dump(ostream &st) const; }; #endif diff -r 2a853d284a6a -r 64638385798a include/kdtree.h --- a/include/kdtree.h Thu May 15 19:15:57 2008 +0200 +++ b/include/kdtree.h Mon May 19 22:59:04 2008 +0200 @@ -55,20 +55,27 @@ KdNode() { shapes = new ShapeList(); assert((flags & 3) == 0); setLeaf(); }; ~KdNode(); + /** mark this node as leaf */ void setLeaf() { flags |= 3; }; bool isLeaf() const { return (flags & 3) == 3; }; + /** set split axis (this removes leaf flag) */ void setAxis(int aAxis) { flags &= ~3; flags |= aAxis; }; int getAxis() const { return flags & 3; }; + /** set split position (leaf) */ void setSplit(Float aSplit) { split = aSplit; }; const Float& getSplit() const { return split; }; + /** set children (non-leaf) */ void setChildren(KdNode *node) { children = node; assert((flags & 3) == 0); }; KdNode* getLeftChild() const { return (KdNode*)((size_t)children & ~3); }; KdNode* getRightChild() const { return (KdNode*)(((size_t)children & ~3) + 16); }; + /** get shape list of the leaf node*/ ShapeList* getShapes() const { return (ShapeList*)((size_t)shapes & ~3); }; + + /** add shape to shape list */ void addShape(const Shape* aShape) { getShapes()->push_back(aShape); }; }; @@ -85,9 +92,14 @@ void recursive_build(KdNode *node, const BBox &bbox, int maxdepth); void recursive_load(istream &st, KdNode *node); public: + /** default constructor, maximum depth is set to 32 */ KdTree(): Container(), mempool(64), root(NULL), max_depth(32), built(false) {}; + + /** constructor which allows to se maximum tree depth (cannot be changed later) */ KdTree(int maxdepth): Container(), mempool(64), root(NULL), max_depth(maxdepth), built(false) {}; ~KdTree() { if (root) delete root; }; + + /** add shape pointer to the container */ void addShape(const Shape* aShape) { Container::addShape(aShape); built = false; }; const Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray, Float &nearest_distance); @@ -96,6 +108,8 @@ Float *nearest_distances, const Shape **nearest_shapes); #endif void optimize() { build(); }; + + /** build the tree (alias for 'optimize') */ void build(); bool isBuilt() const { return built; }; KdNode *getRootNode() const { return root; }; diff -r 2a853d284a6a -r 64638385798a include/material.h --- a/include/material.h Thu May 15 19:15:57 2008 +0200 +++ b/include/material.h Mon May 19 22:59:04 2008 +0200 @@ -44,6 +44,8 @@ { public: virtual ~Texture() {}; + + /** evaluate texture colour in the point of space */ virtual Colour evaluate(const Vector &point) = 0; }; @@ -54,6 +56,8 @@ { public: virtual ~ColourMap() {}; + + /** map float value to colour */ virtual Colour map(const Float &val) = 0; }; @@ -107,9 +111,23 @@ Vector center; Float invsize; public: + /** + * texture map constructor + * @param[in] acenter central point of texture mapping + * @param[in] size Size of the texture. + * One world space unit is mapped to one texture size + * divided by this number. + */ TextureMap(const Vector &acenter, const Float &size): center(acenter), invsize(1.0f/size) {}; virtual ~TextureMap() {}; + + /** + * map 3D space point to 2D u,v coordinates + * @param[in] point a point in 3D space + * @param[out] u horizontal texture coordinate + * @param[out] v vertical texture coordinate + */ virtual void map(const Vector &point, Float &u, Float &v) const = 0; }; @@ -309,12 +327,24 @@ refract_index = 1.3f; } + /** set Phong parameters */ void setPhong(const Float amb, const Float dif, const Float spec, const Float shin) { ambient = amb; diffuse = dif; specular = spec; shininess = shin; }; + + /** set fraction of light to be reflected */ void setReflectivity(const Float refl) { reflectivity = refl; }; + + /** set fraction of light to be refracted + * @param[in] trans the transmissivity amount + * @param[in] rinde index of refraction + */ void setTransmissivity(const Float trans, const Float rindex) { transmissivity = trans; refract_index = rindex; }; + + /** allow triangle smoothing */ void setSmooth(int sm) { smooth = sm; }; + + /** set the texture */ void setTexture(Texture *tex) { texture = tex; }; }; diff -r 2a853d284a6a -r 64638385798a include/octree.h --- a/include/octree.h Thu May 15 19:15:57 2008 +0200 +++ b/include/octree.h Mon May 19 22:59:04 2008 +0200 @@ -77,14 +77,23 @@ const int max_depth; bool built; public: + /** default constructor, + * maximum depth of tree is set to 10 */ Octree() : Container(), root(NULL), max_depth(10), built(false) {}; + + /** constructor + * @param[in] maxdepth maximum depth of the tree */ Octree(int maxdepth) : Container(), root(NULL), max_depth(maxdepth), built(false) {}; ~Octree() { if (root) delete root; }; void addShape(const Shape* aShape) { Container::addShape(aShape); built = false; }; const Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray, Float &nearest_distance); void optimize() { build(); }; + + /** build the octree + * this is alias of optimize() */ void build(); + void save(ostream &str, OctreeNode *node = NULL) {}; void load(istream &str, OctreeNode *node = NULL) {}; }; diff -r 2a853d284a6a -r 64638385798a include/pixmap.h --- a/include/pixmap.h Thu May 15 19:15:57 2008 +0200 +++ b/include/pixmap.h Mon May 19 22:59:04 2008 +0200 @@ -67,11 +67,19 @@ void setData(Float *afdata, int aw, int ah) { fdata = afdata; w = aw; h = ah; }; + + /** get colour of pixel x,y */ const Colour &get(int x, int y) const { return data[y*w + x]; }; const int &getWidth() const { return w; }; const int &getHeight() const { return h; }; + + /** get pixmap data as array of floats */ Float*& getFloatData() { return fdata; }; + + /** get pixmap data as array of chars */ unsigned char *getCharData() const; + + /** write pixmap data to PNG file */ int writePNG(const char *fname) const; }; diff -r 2a853d284a6a -r 64638385798a include/raytracer.h --- a/include/raytracer.h Thu May 15 19:15:57 2008 +0200 +++ b/include/raytracer.h Mon May 19 22:59:04 2008 +0200 @@ -42,26 +42,49 @@ */ class Raytracer { - Container *top; - Sampler *sampler; - Camera *camera; - vector lights; - Colour bg_colour; + Container *top; /**< container with shapes */ + Sampler *sampler; /**< active sampler */ + Camera *camera; /**< active camera */ + vector lights; /**< array of lights in the scene */ + Colour bg_colour; /**< background colour */ + + /* ambient occlussion parameters */ Float ao_distance, ao_angle; int ao_samples; - int num_threads; - int max_depth; - bool use_packets; + int num_threads; /**< number of threads to use for rendering */ + int max_depth; /**< maximum depth of recursion */ + bool use_packets; /**< allow ray packet tracing */ + + /* private helper variables */ 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; + /** + * Hammersley spherical point distribution function + * http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html + * @param[in] i sample index + * @param[in] n number of samples + * @param[in] extent angle of dispersion + * @param[in] normal central direction vector + */ Vector SphereDistribute(int i, int n, Float extent, const Vector &normal); + + /** + * shader implementing Phong lighting model + * @param[in] P point of intersection + * @param[in] N normal in intersect. point + * @param[in] R direction of reflected ray + * @param[in] V direction to the viewer + * @return colour of the surface + */ Colour PhongShader(const Shape *shape, const Vector &P, const Vector &N, const Vector &V); + + /** light scattering function */ void lightScatter(const Ray &ray, const Shape *shape, int depth, const Vector &P, const Vector &normal, bool from_inside, Colour &col); @@ -71,6 +94,7 @@ void raytracePacket(RayPacket &rays, Colour *results); #endif + /** main function of the ray tracing worker */ NORETURN static void *raytrace_worker(void *d); public: @@ -90,21 +114,40 @@ pthread_cond_destroy (&worker_ready_cond); } + /** start the rendering process */ void render(); + + /** ray trace one ray */ Colour raytrace(Ray &ray, int depth, const Shape *origin_shape); + + /** add shape to container */ void addShape(Shape *shape) { top->addShape(shape); }; + + /** add light to scene */ void addLight(Light *light) { lights.push_back(light); }; + + /** set active sampler */ void setSampler(Sampler *sampl) { sampler = sampl; }; Sampler *&getSampler() { return sampler; }; + + /** set active camera */ void setCamera(Camera *cam) { camera = cam; }; Camera *&getCamera() { return camera; }; + + /** set active container */ void setTop(Container *atop) { top = atop; }; Container *&getTop() { return top; }; + /** set background colour */ void setBgColour(const Colour &bg) { bg_colour = bg; }; + + /** set maximum depth of recursion */ void setMaxDepth(int newdepth) { max_depth = newdepth; }; + /** set ambient occlusion parameters */ void ambientOcclusion(int samples, Float distance, Float angle); + + /** set number of threads to use for rendering */ void setThreads(int num) { num_threads = num; }; }; diff -r 2a853d284a6a -r 64638385798a include/raytracermodule.h --- a/include/raytracermodule.h Thu May 15 19:15:57 2008 +0200 +++ b/include/raytracermodule.h Mon May 19 22:59:04 2008 +0200 @@ -1,5 +1,6 @@ -/* - * raytracermodule.h: raytracer module for Python +/** + * @file raytracermodule.h + * @brief Ray tracer module for Python * * This file is part of Pyrit Ray Tracer. * diff -r 2a853d284a6a -r 64638385798a include/scene.h --- a/include/scene.h Thu May 15 19:15:57 2008 +0200 +++ b/include/scene.h Mon May 19 22:59:04 2008 +0200 @@ -76,7 +76,7 @@ #endif /** - * General camera + * Standard ray tracing camera */ class Camera { @@ -84,8 +84,12 @@ Float F; public: Camera(): eye(0,0,10), p(0,0,-1), u(-1,0,0), v(0,1,0), F(2*tan(PI/8)) {}; + + /** Position + p,u,v constructor */ Camera(const Vector &C, const Vector &ap, const Vector &au, const Vector &av): eye(C), p(ap), u(au), v(av), F(2*tan(PI/8)) {}; + + /** Look-at constructor */ Camera(const Vector &from, const Vector &lookat, const Vector &up): eye(from), F(2*tan(PI/8)) { @@ -104,21 +108,37 @@ const Vector &getu() const { return u; }; const Vector &getv() const { return v; }; const Float &getF() const { return F; }; + void setEye(const Vector &aeye) { eye = aeye; }; void setp(const Vector &ap) { p = ap; }; void setu(const Vector &au) { u = au; }; void setv(const Vector &av) { v = av; }; + + /** set "screen plane" size + * @param[in] F height of the screen plane */ void setF(const Float &aF) { F = aF; }; + + /** set camera's angle of view (in radians) */ void setAngle(const Float angle) { F = 2*tan(angle/2); }; + + /** rotate camera using a quaternion */ void rotate(const Quaternion &q); + + /** translate the camera in its direction + * @param[in] fw size of forward step + * @param[in] left size of left step + * @param[in] up size of up step + */ void move(const Float fw, const Float left, const Float up); + /** make the ray from screen sample according the camera's parameters */ const Ray makeRay(const Sample &samp) const { Vector dir = normalize(p - (u*samp.x + v*samp.y)*F); return Ray(eye, dir); }; + /** same as makeRay but for ray packet */ #ifndef NO_SIMD void makeRayPacket(const Sample *samples, RayPacket &rays) const { @@ -188,6 +208,8 @@ 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) {}; + + /** allow shadows from this light */ void castShadows(int cast) { cast_shadows = cast; }; }; @@ -206,7 +228,17 @@ Float w() const { return H.x-L.x; }; Float h() const { return H.y-L.y; }; Float d() const { return H.z-L.z; }; + + /** + * intersect ray with the bounding box + * @param[in] ray the ray + * @param[out] a distance of first intersection + * @param[out] b distance of second intersection + * @return true if ray intersects bbox + */ bool intersect(const Ray &ray, Float &a, Float &b) const; + + /** same as intersect() but for ray packets */ #ifndef NO_SIMD mfloat4 intersect_packet(const RayPacket &rays, mfloat4 &a, mfloat4 &b) const; #endif diff -r 2a853d284a6a -r 64638385798a include/shapes.h --- a/include/shapes.h Thu May 15 19:15:57 2008 +0200 +++ b/include/shapes.h Mon May 19 22:59:04 2008 +0200 @@ -44,7 +44,7 @@ #endif /** - * shape + * abstract shape class */ class Shape { @@ -54,9 +54,18 @@ Shape() {}; virtual ~Shape() {}; - // first intersection point + /** + * intersect ray with sphere + * @param[in] ray the ray + * @param[in] dist maximum allowed distance of intersection + * @param[out] dist distance of the intersection if found, unchanged otherwise + * @return true if ray intersects the sphere + */ virtual bool intersect(const Ray &ray, Float &dist) const = 0; + /** + * same as intersect, but for ray packets + */ #ifndef NO_SIMD virtual mfloat4 intersect_packet(const RayPacket &rays, mfloat4 &dists) const { @@ -69,17 +78,19 @@ }; #endif - // all intersections (only for CSG) + /** get all intersections -- not needed nor used currently */ virtual bool intersect_all(const Ray &ray, Float dist, vector &allts) const = 0; - // intersection with AABB + /** test intersection with bounding box */ virtual bool intersect_bbox(const BBox &bbox) const = 0; - // normal at point P + /** get surface normal at point P */ virtual const Vector normal(const Vector &P) const = 0; + /** get bounding box of this shape */ virtual BBox get_bbox() const = 0; + /** write textual representation of the shape to stream */ virtual ostream & dump(ostream &st) const = 0; }; @@ -103,17 +114,20 @@ center(acenter), radius(aradius), sqr_radius(aradius*aradius), inv_radius(1.0f/aradius) { material = amaterial; } + bool intersect(const Ray &ray, Float &dist) const; +#ifndef NO_SIMD + mfloat4 intersect_packet(const RayPacket &rays, mfloat4 &dists) const; +#endif bool intersect_all(const Ray &ray, Float dist, vector &allts) const; bool intersect_bbox(const BBox &bbox) const; const Vector normal(const Vector &P) const { return (P - center) * inv_radius; }; BBox get_bbox() const; + const Vector getCenter() const { return center; }; Float getRadius() const { return radius; }; + ostream & dump(ostream &st) const; -#ifndef NO_SIMD - mfloat4 intersect_packet(const RayPacket &rays, mfloat4 &dists) const; -#endif }; /** @@ -132,16 +146,18 @@ material = amaterial; }; bool intersect(const Ray &ray, Float &dist) const; +#ifndef NO_SIMD + mfloat4 intersect_packet(const RayPacket &rays, mfloat4 &dists) const; +#endif bool intersect_all(const Ray &ray, Float dist, vector &allts) const { return false; }; bool intersect_bbox(const BBox &bbox) const; const Vector normal(const Vector &P) const; BBox get_bbox() const { return BBox(L, H); }; + const Vector getL() const { return L; }; const Vector getH() const { return H; }; + ostream & dump(ostream &st) const; -#ifndef NO_SIMD - mfloat4 intersect_packet(const RayPacket &rays, mfloat4 &dists) const; -#endif }; /** @@ -219,17 +235,21 @@ Triangle() {}; Triangle(Vertex *aA, Vertex *aB, Vertex *aC, Material *amaterial); bool intersect(const Ray &ray, Float &dist) const; +#if !defined(NO_SIMD) && defined(TRI_BARI_PRE) + mfloat4 intersect_packet(const RayPacket &rays, mfloat4 &dists) const; +#endif bool intersect_all(const Ray &ray, Float dist, vector &allts) const {return false;}; bool intersect_bbox(const BBox &bbox) const; const Vector normal(const Vector &P) const { return (material->smooth ? smooth_normal(P) : N); }; + BBox get_bbox() const; + + /** get real normal of the triangle */ const Vector getNormal() const { return N; }; - BBox get_bbox() const; + ostream & dump(ostream &st) const; -#if !defined(NO_SIMD) && defined(TRI_BARI_PRE) - mfloat4 intersect_packet(const RayPacket &rays, mfloat4 &dists) const; -#endif }; +/** template for triangle arrays, currently not used */ template class Array { T *array; diff -r 2a853d284a6a -r 64638385798a include/simd.h --- a/include/simd.h Thu May 15 19:15:57 2008 +0200 +++ b/include/simd.h Mon May 19 22:59:04 2008 +0200 @@ -72,11 +72,13 @@ #define mShuffle3 _MM_SHUFFLE(3,3,3,3) #define mshuffle _mm_shuffle_ps +/** select values from a and b according to mask (a if mask is 1, b if mask is 0) */ inline const mfloat4 mselect(const mfloat4& mask, const mfloat4& a, const mfloat4& b) { return _mm_or_ps(_mm_and_ps(mask, a), _mm_andnot_ps(mask, b)); } +/** fast power function */ inline const mfloat4 mfastpow(const mfloat4& base, const mfloat4& exponent) { __m128 denom = _mm_mul_ps(exponent, base); diff -r 2a853d284a6a -r 64638385798a models/lwo/Nissan300ZX.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/models/lwo/Nissan300ZX.txt Mon May 19 22:59:04 2008 +0200 @@ -0,0 +1,2 @@ +This model comes from DMI Car 3D Models collection. +http://dmi.chez-alice.fr/models1.html diff -r 2a853d284a6a -r 64638385798a src/raytracermodule.cc --- a/src/raytracermodule.cc Thu May 15 19:15:57 2008 +0200 +++ b/src/raytracermodule.cc Mon May 19 22:59:04 2008 +0200 @@ -914,8 +914,9 @@ } -//=========================== Vertex Object (abstract) =========================== +//=========================== Vertex Object =========================== +static PyObject *Vertex_Constructor(PyObject* self, PyObject* args, PyObject *kwd); static void Vertex_Destructor(PyObject* self); static PyMethodDef VertexMethods[] = { @@ -935,6 +936,32 @@ 0 /* tp_init */ ); +static PyObject* Vertex_Constructor(PyObject* self, PyObject* args, PyObject *kwd) +{ + VertexObject *v; + static char *kwdlist[] = {"vector", NULL}; + PyObject *TVer = NULL; + Float vx, vy, vz; + + if (!PyArg_ParseTupleAndKeywords(args, kwd, "O", kwdlist, &TVer)) + return NULL; + + if (TVer->ob_type == &VertexType) + { + v = PyObject_New(VertexObject, &VertexType); + v->vertex = new Vertex(*((VertexObject*)TVer)->vertex); + } + else + { + if (!PyArg_ParseTuple(TVer, "fff", &vx, &vy, &vz)) + return NULL; + + v = PyObject_New(VertexObject, &VertexType); + v->vertex = new Vertex(Vector(vx, vy, vz)); + } + return (PyObject*)v; +} + static void Vertex_Destructor(PyObject* self) { delete ((VertexObject *)self)->vertex;