--- 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;
--- 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.
--- 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
--- 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')
--- 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
--- 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<typename Type> 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<typename Type> 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";
--- 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
--- 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; };
--- 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; };
};
--- 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) {};
};
--- 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;
};
--- 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<Light*> lights;
- Colour bg_colour;
+ Container *top; /**< container with shapes */
+ Sampler *sampler; /**< active sampler */
+ Camera *camera; /**< active camera */
+ vector<Light*> 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; };
};
--- 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.
*
--- 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
--- 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<Float> &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<Float> &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<Float> &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<Float> &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 T> class Array
{
T *array;
--- 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);
--- /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
--- 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;