├── README.md ├── images ├── all_in_one_256s.png ├── all_in_one_header.png ├── cornell_all.png ├── cornell_with_without_photon.png ├── dof_256s.png ├── final_scene.jpg ├── glossy_256s.png ├── material_file.png ├── noise_bump_256s.png ├── texturing_100s.png ├── texturing_bump_100s.png ├── txt_001_diff.jpg └── txt_002_bump.jpg ├── index.html └── sources ├── BLPatch.cpp ├── BLPatch.h ├── BVH.cpp ├── BVH.h ├── BoundingBox.cpp ├── BoundingBox.h ├── Box.cpp ├── Box.h ├── Camera.cpp ├── Camera.h ├── CellularStoneTexture.cpp ├── CellularStoneTexture.h ├── Console.cpp ├── Console.h ├── Image.cpp ├── Image.h ├── IntersectObjects.h ├── Makedefs ├── Makefile ├── Material.cpp ├── Material.h ├── Matrix4x4.h ├── Miro.h ├── MiroWindow.cpp ├── MiroWindow.h ├── MyBoost.h ├── Object.h ├── OpenGL.h ├── PFMLoader.cpp ├── PFMLoader.h ├── Perlin.cpp ├── Perlin.h ├── Phong.cpp ├── Phong.h ├── PhotonMap.cpp ├── PhotonMap.h ├── PointLight.h ├── Ray.h ├── SSE.cpp ├── SSE.h ├── SSEObject.h ├── Scene.cpp ├── Scene.h ├── Sphere.cpp ├── Sphere.h ├── Texture.cpp ├── Texture.h ├── Triangle.cpp ├── Triangle.h ├── TriangleMesh.cpp ├── TriangleMesh.h ├── TriangleMeshLoad.cpp ├── Vector3.h ├── Vector4.h ├── Worley.cpp ├── Worley.h ├── assignment1.cpp ├── assignment1.h ├── assignment2.cpp ├── assignment2.h ├── boost ├── threadpool.hpp └── threadpool │ ├── detail │ ├── future.hpp │ ├── locking_ptr.hpp │ ├── pool_core.hpp │ ├── scope_guard.hpp │ └── worker_thread.hpp │ ├── future.hpp │ ├── pool.hpp │ ├── pool_adaptors.hpp │ ├── scheduling_policies.hpp │ ├── shutdown_policies.hpp │ ├── size_policies.hpp │ └── task_adaptors.hpp ├── freeglut.h ├── freeglut_ext.h ├── freeglut_std.h ├── future.hpp ├── gl └── include │ └── GL │ ├── freeglut.h │ ├── freeglut_ext.h │ ├── freeglut_std.h │ └── glut.h ├── glut.h ├── locking_ptr.hpp ├── main.cpp ├── pool.hpp ├── pool_adaptors.hpp ├── pool_core.hpp ├── scheduling_policies.hpp ├── scope_guard.hpp ├── shutdown_policies.hpp ├── size_policies.hpp ├── task_adaptors.hpp ├── threadpool.hpp └── worker_thread.hpp /README.md: -------------------------------------------------------------------------------- 1 | #UC San Diego - Rendering Algorithms 2 | ####Authors: Fabrice Bascoulergue & Adrien Ecoffet 3 | 4 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/all_in_one_header.png) 5 |

6 | ##Depth of field 7 | One of the first algorithm we implemented is the Depth of field to render realistic scenes. To achieve that, our raytracer use to variables: 8 | - Focal length: The distance between the eye and the focused objects 9 | - Aperture size: Define the amount of blur effect applied on objects depending of their distance with the focal length 10 | 11 | Smooth shadow follow almost the same principle and are applied to the scene. 12 | 13 | Cellular texturing is applied on the floor to create the stone patterns. 14 | 15 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/dof_256s.png) 16 | 17 |

18 | ##Texturing and bump mapping 19 | ###UV Texture mapping 20 | We used flat projection to display images on a triangle mesh. The surface on the right is a triangle mesh with an ocean texture applied. The texture is defined by the following image: 21 | 22 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/txt_001_diff.jpg) 23 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/texturing_100s.png) 24 | 25 | ###Bump mapping 26 | The same image with bump mapping enabled. 27 | The bump map is defined by the following image: 28 | 29 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/txt_002_bump.jpg) 30 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/texturing_bump_100s.png) 31 | 32 | ###Noise: turbulence and bump mapping 33 | In order to render more realistic scenes with water, we implemented an other version of the bump mapping using noise and turbulence. 34 | Our raytracer use a specific percentage to define the importance of the bump on the surface, 0% has no effect on the normal and 100% generate a full bumped normal. 35 | The three spheres on the right share the same noise with turbulence but with different levels of bump noise (from left to right): 36 | - Bump from noise disabled 37 | - Bump with 20% importance 38 | - Bump with 40% importance 39 | 40 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/noise_bump_256s.png) 41 | 42 |

43 | ##Glossy reflection 44 | The image on the right show our implementation of the glossy reflection. 45 | From left to right we have: 46 | - Highly glossy sphere 47 | - Glossy sphere 48 | - Sphere without glossy reflection 49 | 50 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/glossy_256s.png) 51 | 52 |

53 | ##Photon mapping 54 | ###Global illumination 55 | We implemented the photon mapping and caustics to render global illumination: 56 | On the left, the scene is darker because the global illumination is disabled 57 | On the right, the same scene with global illumination 58 | 59 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/cornell_with_without_photon.png) 60 | 61 | ###Caustics 62 | The two spheres on those scenes on the right create caustics. 63 | Caustics are independent of the number of sample, that is why on the four images on the right, the caustic stay almost the same: 64 | - The global illumination make it brighter (with all the rest of the scene) 65 | - The caustic is a bit more precise with a lot more samples 66 | 67 | ###Sampling 68 | Here are some tests with different numbers of sample to show the importance of sampling with photon mapping: 69 | - Top left: 16 samples per pixel 70 | - Top right: 64 samples per pixel 71 | - Bottom left: 128 samples per pixel 72 | - Bottom right: 256 samples per pixel 73 | 74 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/cornell_all.png) 75 | 76 |

77 | ##Wavefront Obj and materials 78 | In order to render complex scenes with realistic materials like the cave (final image on the right), we improved the .obj file parser to also load the .mtl files with the materials. 79 | 80 | Those material files describe each features to enable and each parameters to apply on the triangles such as: 81 | - Ns: Specifies the specular exponent for the current material. 82 | - Ni: Specifies the index of refraction for the surface. 83 | - d: Opacity of the material. 84 | - Ka: Ambient color. 85 | - map_Kd: Texture to apply on the diffuse reflectivity of the material. 86 | - map_bump: Bump map to apply on the normals of the surface. 87 | - ... 88 | 89 | With this parser, we were able to create scenes with any 3D software (blender, 3ds max) and export them in the .obj format. 90 | The main challenge after that was to check manually for each material if all the properties were properly exported (and this is not often the case). 91 | 92 | ![Final render header](https://raw.githubusercontent.com/anhuin69/Raytracer/master/images/material_file.png) 93 | -------------------------------------------------------------------------------- /images/all_in_one_256s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/all_in_one_256s.png -------------------------------------------------------------------------------- /images/all_in_one_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/all_in_one_header.png -------------------------------------------------------------------------------- /images/cornell_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/cornell_all.png -------------------------------------------------------------------------------- /images/cornell_with_without_photon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/cornell_with_without_photon.png -------------------------------------------------------------------------------- /images/dof_256s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/dof_256s.png -------------------------------------------------------------------------------- /images/final_scene.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/final_scene.jpg -------------------------------------------------------------------------------- /images/glossy_256s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/glossy_256s.png -------------------------------------------------------------------------------- /images/material_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/material_file.png -------------------------------------------------------------------------------- /images/noise_bump_256s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/noise_bump_256s.png -------------------------------------------------------------------------------- /images/texturing_100s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/texturing_100s.png -------------------------------------------------------------------------------- /images/texturing_bump_100s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/texturing_bump_100s.png -------------------------------------------------------------------------------- /images/txt_001_diff.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/txt_001_diff.jpg -------------------------------------------------------------------------------- /images/txt_002_bump.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebascou/Raytracer/5f7fd9ec2fa7d178d0b9509e2bdbc74beb408551/images/txt_002_bump.jpg -------------------------------------------------------------------------------- /sources/BLPatch.cpp: -------------------------------------------------------------------------------- 1 | #include "BLPatch.h" 2 | #include "Ray.h" 3 | #include "Console.h" 4 | 5 | BLPatch::BLPatch() 6 | { 7 | } 8 | 9 | BLPatch::~BLPatch() 10 | { 11 | } 12 | 13 | void 14 | BLPatch::renderGL() 15 | { 16 | 17 | } 18 | 19 | ObjType BLPatch::type() const { return BLPATCH; } 20 | -------------------------------------------------------------------------------- /sources/BLPatch.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_BL_PATCH_H_INCLUDED 2 | #define CSE168_BL_PATCH_H_INCLUDED 3 | 4 | #include "Vector3.h" 5 | #include "Object.h" 6 | 7 | class BLPatch : public Object 8 | { 9 | public: 10 | BLPatch(); 11 | virtual ~BLPatch(); 12 | 13 | Vector3 & vertex(int i) {return m_verts[i];} 14 | const Vector3 & vertex(int i) const {return m_verts[i];} 15 | 16 | virtual void renderGL(); 17 | 18 | virtual ObjType type() const; 19 | 20 | virtual void *selfPtr() { return this; } 21 | protected: 22 | Vector3 m_verts[4]; 23 | }; 24 | 25 | #endif // CSE168_BL_PATCH_H_INCLUDED 26 | -------------------------------------------------------------------------------- /sources/BVH.cpp: -------------------------------------------------------------------------------- 1 | #include "BVH.h" 2 | #include "Ray.h" 3 | #include "Console.h" 4 | #include "Sphere.h" 5 | #include "Triangle.h" 6 | #include "Box.h" 7 | #include "BoundingBox.h" 8 | #include 9 | #include 10 | #include 11 | 12 | #define INF std::numeric_limits::infinity() 13 | 14 | #define CBOX 4.f 15 | #define CTRI 1.f 16 | #define SIZE_LEAF 8 17 | 18 | static float costNTris(int n) 19 | { 20 | return (n / 4 + (n % 4 != 0)) * CTRI; 21 | } 22 | 23 | static float cost(float areaA, int objA, float areaB, int objB, float areaCinv) 24 | { 25 | return 2 * CBOX + (areaA * costNTris(objA) + areaB * costNTris(objB)) * areaCinv; 26 | } 27 | 28 | void BVH::splitBox(AxisData const &data, BoundingBox &abox, BoundingBox &bbox, ObjectsWithBoxes::iterator begin, ObjectsWithBoxes::iterator end, float areaCinv, boost::function f) 29 | { 30 | Vector3 v(INF); 31 | abox.setA(v); 32 | bbox.setA(v); 33 | v.set(-INF); 34 | abox.setB(v); 35 | bbox.setB(v); 36 | int a = 0, b = 0; 37 | for (ObjectsWithBoxes::iterator it = begin; it != end;) 38 | { 39 | Vector3 const &min = it->min; 40 | Vector3 const &max = it->max; 41 | if (min[data.axis] > data.pos || (max[data.axis] > data.pos && max[data.axis] - data.pos > data.pos - min[data.axis])) 42 | { 43 | bbox.setA(bbox.getA().min(min)); 44 | bbox.setB(bbox.getB().max(max)); 45 | f(1, it, end); 46 | b++; 47 | continue; 48 | } 49 | else 50 | { 51 | abox.setA(abox.getA().min(min)); 52 | abox.setB(abox.getB().max(max)); 53 | f(0, it, end); 54 | a++; 55 | continue; 56 | } 57 | } 58 | } 59 | 60 | void BVH::buildLeaf(ObjectsWithBoxes::iterator begin, ObjectsWithBoxes::iterator end, BVH::BBoxNode *prev_node) 61 | { 62 | prev_node->objs = new std::vector(); 63 | prev_node->objs->resize(NB_OBJS); 64 | for (ObjectsWithBoxes::iterator it = begin; it != end; ++it) 65 | { 66 | (*prev_node->objs)[it->obj->type()].plain.push_back(it->obj->ptr()); 67 | } 68 | (*prev_node->objs)[TRIANGLE].sse_preprocessed = Triangle::preProcess((*prev_node->objs)[TRIANGLE].plain); 69 | } 70 | 71 | void BVH::recBuildBBox(ObjectsWithBoxes::iterator begin, ObjectsWithBoxes::iterator end, BVH::BBoxNode *prev_node, int depth) 72 | { 73 | if (end - begin <= SIZE_LEAF) 74 | { 75 | buildLeaf(begin, end, prev_node); 76 | return; 77 | } 78 | BoundingBox abox; 79 | BoundingBox bbox; 80 | float areaCinv = 1.f / prev_node->box.area(); 81 | AxisData minsplit; 82 | minsplit.axis = -1; 83 | minsplit.cost = INF; 84 | for (int axis = 0; axis < 3; ++axis) 85 | { 86 | AxisData data; 87 | data.lowest = prev_node->box.getA()[axis]; 88 | data.highest = prev_node->box.getB()[axis]; 89 | if (data.lowest > data.highest) 90 | std::swap(data.lowest, data.highest); 91 | data.interval = (data.highest - data.lowest) / 10; 92 | if (data.interval < EPSILON) 93 | continue; 94 | data.axis = axis; 95 | for (data.pos = data.lowest + data.interval; data.pos < data.highest; data.pos += data.interval) 96 | { 97 | int cnts[2] = {0, 0}; 98 | splitBox(data, abox, bbox, begin, end, areaCinv, [&](int n, ObjectsWithBoxes::iterator &it, ObjectsWithBoxes::iterator &) 99 | { 100 | cnts[n]++; 101 | ++it; 102 | }); 103 | data.cost = cost(abox.area(), cnts[0], bbox.area(), cnts[1], areaCinv); 104 | minsplit = std::min(minsplit, data); 105 | } 106 | } 107 | if (minsplit.axis == -1) 108 | { 109 | buildLeaf(begin, end, prev_node); 110 | return; 111 | } 112 | ObjectsWithBoxes::iterator middle = begin, last = begin + (end - begin - 1); 113 | splitBox(minsplit, abox, bbox, begin, end, areaCinv, [&](int n, ObjectsWithBoxes::iterator &it, ObjectsWithBoxes::iterator &curend) 114 | { 115 | if (n == 0) 116 | { 117 | ++it; 118 | ++middle; 119 | } 120 | else 121 | { 122 | std::swap(*it, *last); 123 | --last; 124 | curend = last + 1; 125 | } 126 | }); 127 | prev_node->a = new BBoxNode; 128 | prev_node->a->box = abox; 129 | prev_node->b = new BBoxNode; 130 | prev_node->b->box = bbox; 131 | if (1 << depth <= nCpus()) 132 | { 133 | boost::thread t([&]() {recBuildBBox(begin, middle, prev_node->a, depth + 1);}); 134 | recBuildBBox(middle, end, prev_node->b, depth + 1); 135 | t.join(); 136 | } 137 | else 138 | { 139 | recBuildBBox(begin, middle, prev_node->a, depth + 1); 140 | recBuildBBox(middle, end, prev_node->b, depth + 1); 141 | } 142 | } 143 | 144 | BoundingBox BVH::objectBox(ObjectsWithBoxes *objs) 145 | { 146 | Vector3 min = Vector3(INF, INF, INF); 147 | Vector3 max = Vector3(-INF, -INF, -INF); 148 | for (ObjectsWithBoxes::const_iterator it = objs->begin(); it != objs->end(); ++it) 149 | { 150 | min = min.min(it->min); 151 | max = max.max(it->max); 152 | } 153 | return BoundingBox(min, max); 154 | } 155 | 156 | void BVH::printHierarchy(BBoxNode *node, int ind) 157 | { 158 | printf("%f\n", node->box.area()); 159 | if (node->a && node->b) 160 | { 161 | printHierarchy(node->a, ind + 1); 162 | printHierarchy(node->b, ind + 1); 163 | } 164 | else 165 | printf("%f\n", (*node->objs)[TRIANGLE].plain.size()); 166 | } 167 | 168 | void 169 | BVH::build(Objects * objs) 170 | { 171 | // construct the bounding volume hierarchy 172 | 173 | ObjectsWithBoxes objs_boxes; 174 | std::transform(objs->begin(), objs->end(), std::back_inserter(objs_boxes), [](Object *o) -> ObjectWithBox 175 | { 176 | ObjectWithBox res; 177 | res.min = o->minVector(); 178 | res.max = o->maxVector(); 179 | res.obj = o; 180 | return res; 181 | }); 182 | 183 | m_root = new BBoxNode; 184 | m_root->box = objectBox(&objs_boxes); 185 | recBuildBBox(objs_boxes.begin(), objs_boxes.end(), m_root); 186 | //printHierarchy(m_root, 0); 187 | 188 | m_objects = objs; 189 | 190 | // OBSOLETE: start 191 | //m_categories_objects.resize(NB_OBJS); 192 | //for (size_t i = 0; i < m_objects->size(); ++i) 193 | //{ 194 | // m_categories_objects[(*m_objects)[i]->type()].plain.push_back((*m_objects)[i]->ptr()); 195 | //} 196 | //m_categories_objects[TRIANGLE].sse_preprocessed = Triangle::preProcess(m_categories_objects[TRIANGLE].plain); 197 | // OBSOLETE: stop 198 | 199 | m_intersect_fcts.resize(NB_OBJS); 200 | m_intersect_fcts[TRIANGLE] = &Triangle::doIntersect; 201 | m_intersect_fcts[SPHERE] = &Sphere::doIntersect; 202 | m_intersect_fcts[BOX] = &Box::doIntersect; 203 | } 204 | 205 | bool 206 | BVH::rec_intersect(BBoxNode *node, HitInfo& minHit, const Ray& ray, float tMin, float tMax) const 207 | { 208 | bool hit = false; 209 | HitInfo tempMinHit; 210 | minHit.t = MIRO_TMAX; 211 | 212 | if (node->a == NULL && node->b == NULL) 213 | { 214 | for (size_t i = 0; i < NB_OBJS; ++i) 215 | { 216 | if (m_intersect_fcts[i] && m_intersect_fcts[i]((*node->objs)[i], tempMinHit, ray, tMin, tMax) && tempMinHit.t < minHit.t) 217 | { 218 | minHit = tempMinHit; 219 | hit = true; 220 | } 221 | } 222 | 223 | } 224 | else 225 | { 226 | if (node->a && node->a->box.doIntersect(tempMinHit, ray, tMin, tMax)) 227 | { 228 | hit = rec_intersect(node->a, minHit, ray, tMin, tMax); 229 | } 230 | if (node->b && node->b->box.doIntersect(tempMinHit, ray, tMin, tMax)) 231 | { 232 | bool tmpHit = rec_intersect(node->b, tempMinHit, ray, tMin, tMax); 233 | if (tmpHit && (!hit || (hit && tempMinHit.t < minHit.t))) 234 | { 235 | minHit = tempMinHit; 236 | hit = true; 237 | } 238 | } 239 | } 240 | if (hit) 241 | { 242 | if (minHit.N.dot(ray.d) > 0) 243 | { 244 | minHit.N.negate(); 245 | } 246 | } 247 | return hit; 248 | } 249 | 250 | bool 251 | BVH::intersect(HitInfo& minHit, const Ray& ray, float tMin, float tMax) const 252 | { 253 | // Here you would need to traverse the BVH to perform ray-intersection 254 | // acceleration. For now we just intersect every object. 255 | 256 | bool hit = false; 257 | HitInfo tempMinHit; 258 | minHit.t = MIRO_TMAX; 259 | 260 | return rec_intersect(m_root, minHit, ray, tMin, tMax); 261 | } 262 | -------------------------------------------------------------------------------- /sources/BVH.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_BVH_H_INCLUDED 2 | #define CSE168_BVH_H_INCLUDED 3 | 4 | #include "Miro.h" 5 | #include "Object.h" 6 | #include "BoundingBox.h" 7 | #include "IntersectObjects.h" 8 | #include 9 | 10 | class BVH 11 | { 12 | public: 13 | void build(Objects * objs); 14 | 15 | bool intersect(HitInfo& result, const Ray& ray, 16 | float tMin = 0.0f, float tMax = MIRO_TMAX) const; 17 | 18 | protected: 19 | struct BBoxNode 20 | { 21 | BoundingBox box; 22 | std::vector *objs; 23 | BBoxNode *a; 24 | BBoxNode *b; 25 | 26 | BBoxNode() : a(0), b(0), objs(0) {} 27 | 28 | ~BBoxNode() { delete a; delete b; delete objs; } 29 | }; 30 | 31 | struct AxisData 32 | { 33 | float lowest; 34 | float highest; 35 | float interval; 36 | float pos; 37 | int axis; 38 | float cost; 39 | 40 | bool operator<(AxisData const &other) const 41 | { 42 | return cost < other.cost; 43 | } 44 | }; 45 | 46 | struct ObjectWithBox 47 | { 48 | Object *obj; 49 | Vector3 min, max; 50 | }; 51 | typedef std::vector ObjectsWithBoxes; 52 | 53 | void splitBox(AxisData const &data, BoundingBox &abox, BoundingBox &bbox, ObjectsWithBoxes::iterator begin, ObjectsWithBoxes::iterator end, float areaCinv, boost::function f); 54 | void buildLeaf(ObjectsWithBoxes::iterator begin, ObjectsWithBoxes::iterator end, BVH::BBoxNode *prev_node); 55 | 56 | void recBuildBBox(ObjectsWithBoxes::iterator begin, ObjectsWithBoxes::iterator end, BVH::BBoxNode *prev_node, int depth = 0); 57 | BoundingBox objectBox(ObjectsWithBoxes *objs); 58 | void printHierarchy(BBoxNode *node, int ind); 59 | 60 | Objects * m_objects; 61 | std::vector m_categories_objects; 62 | typedef bool (*Intersect)(IntersectObjects const &objects, HitInfo& result, 63 | const Ray& ray, float tMin, float tMax); 64 | std::vector m_intersect_fcts; 65 | 66 | BBoxNode *m_root; 67 | 68 | public: 69 | bool rec_intersect(BBoxNode *node, HitInfo& result, const Ray& ray, 70 | float tMin = 0.0f, float tMax = MIRO_TMAX) const; 71 | }; 72 | 73 | #endif // CSE168_BVH_H_INCLUDED 74 | -------------------------------------------------------------------------------- /sources/BoundingBox.cpp: -------------------------------------------------------------------------------- 1 | #include "BoundingBox.h" 2 | #include "Ray.h" 3 | #include 4 | 5 | BoundingBox::BoundingBox(const Vector3& a, const Vector3& b) : _a(a), _b(b) 6 | { 7 | } 8 | 9 | 10 | BoundingBox::~BoundingBox(void) 11 | { 12 | } 13 | 14 | bool BoundingBox::doIntersect(HitInfo &result, const Ray &ray, float tMin, float tMax) 15 | { 16 | Vector3 t1 = (_a - ray.o) / ray.d; 17 | Vector3 t2 = (_b - ray.o) / ray.d; 18 | 19 | float t_min = std::max(std::min(t1.x, t2.x), std::max(std::min(t1.y, t2.y), std::min(t1.z, t2.z))); 20 | float t_max = std::min(std::max(t1.x, t2.x), std::min(std::max(t1.y, t2.y), std::max(t1.z, t2.z))); 21 | 22 | if (t_max < 0 || t_min > t_max) 23 | return false; 24 | result.t = t_min < 0 ? t_max : t_min; 25 | return true; 26 | } 27 | 28 | float BoundingBox::area() const 29 | { 30 | Vector3 segments = (_a - _b).abs(); 31 | return (segments.x * segments.y + segments.x * segments.z + segments.y * segments.z) * 2; 32 | } 33 | -------------------------------------------------------------------------------- /sources/BoundingBox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Object.h" 3 | 4 | class BoundingBox 5 | { 6 | public: 7 | BoundingBox(const Vector3& a, const Vector3& b); 8 | BoundingBox() {} 9 | virtual ~BoundingBox(); 10 | 11 | bool doIntersect(HitInfo &, const Ray &, float, float); 12 | 13 | void setA(const Vector3 & v) {_a = v;} 14 | const Vector3& getA() const { return _a; } 15 | void setB(const Vector3 & v) {_b = v;} 16 | const Vector3& getB() const { return _b; } 17 | 18 | float area() const; 19 | 20 | protected: 21 | Vector3 _a; 22 | Vector3 _b; 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /sources/Box.cpp: -------------------------------------------------------------------------------- 1 | #include "Box.h" 2 | #include "Ray.h" 3 | 4 | Box::Box(const Vector3& a, const Vector3& b) : BoundingBox(a, b) 5 | { 6 | } 7 | 8 | 9 | Box::~Box(void) 10 | { 11 | } 12 | 13 | void Box::renderGL() 14 | { 15 | Vector3 v[16]; 16 | 17 | v[0] = Vector3(_a.x, _a.y, _a.z); 18 | v[1] = Vector3(_a.x + _b.x, _a.y, _a.z); 19 | v[2] = Vector3(_a.x + _b.x, _a.y, _a.z + _b.z); 20 | v[3] = Vector3(_a.x, _a.y, _a.z + _b.z); 21 | 22 | v[4] = Vector3(_a.x, _a.y, _a.z + _b.z); 23 | v[5] = Vector3(_a.x, _a.y + _b.y, _a.z + _b.z); 24 | v[6] = Vector3(_a.x, _a.y + _b.y, _a.z); 25 | v[7] = Vector3(_a.x, _a.y, _a.z); 26 | 27 | v[8] = Vector3(_a.x, _a.y + _b.y, _a.z); 28 | v[9] = Vector3(_a.x + _b.x, _a.y + _b.y, _a.z); 29 | v[10] = Vector3(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z); 30 | v[11] = Vector3(_a.x, _a.y + _b.y, _a.z + _b.z); 31 | 32 | v[12] = Vector3(_a.x + _b.x, _a.y, _a.z + _b.z); 33 | v[13] = Vector3(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z); 34 | v[14] = Vector3(_a.x + _b.x, _a.y + _b.y, _a.z); 35 | v[15] = Vector3(_a.x + _b.x, _a.y, _a.z); 36 | 37 | glBegin(GL_QUADS); 38 | for (int i = 0; i < 16; i++) 39 | glVertex3f(v[i].x, v[i].y, v[i].z); 40 | glEnd(); 41 | } 42 | 43 | bool Box::doIntersect(IntersectObjects const &objects, HitInfo& result, const Ray& ray, float tMin, float tMax) 44 | { 45 | bool hit = false; 46 | int idx = 0; 47 | 48 | for (int i = 0; i < objects.plain.size(); i++) 49 | { 50 | Box *cur = (Box*) objects.plain[i]; 51 | HitInfo cur_result; 52 | 53 | if (((BoundingBox*)cur)->doIntersect(cur_result, ray, tMin, tMax) && cur_result.t > tMin && cur_result.t < tMax) 54 | { 55 | result = cur_result; 56 | result.material = cur->m_material; 57 | hit = true; 58 | idx = i; 59 | } 60 | } 61 | if (hit == true) 62 | { 63 | result.P = ray.o + (ray.d * result.t); 64 | Vector3 p = (((Box*)objects.plain[idx])->getA() + ((Box*)objects.plain[idx])->getB()) / 2.f; 65 | p = result.P - p; 66 | 67 | if (std::abs(p.x) >= std::abs(p.y) && std::abs(p.x) >= std::abs(p.z)) 68 | { 69 | p.y = 0; 70 | p.z = 0; 71 | } 72 | else if (std::abs(p.y) >= std::abs(p.x) && std::abs(p.y) >= std::abs(p.z)) 73 | { 74 | p.x = 0; 75 | p.z = 0; 76 | } 77 | else 78 | { 79 | p.x = 0; 80 | p.y = 0; 81 | } 82 | p.normalize(); 83 | result.N = p; 84 | } 85 | return hit; 86 | } 87 | 88 | Vector3 Box::maxVector() const 89 | { 90 | return _a.max(_b); 91 | } 92 | 93 | Vector3 Box::minVector() const 94 | { 95 | return _a.min(_b); 96 | } 97 | -------------------------------------------------------------------------------- /sources/Box.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Object.h" 3 | #include "BoundingBox.h" 4 | 5 | class Box : public Object, public BoundingBox 6 | { 7 | public: 8 | Box(const Vector3& a, const Vector3& b); 9 | virtual ~Box(); 10 | 11 | void renderGL(); 12 | static bool doIntersect(IntersectObjects const &objects, HitInfo &, const Ray &, float, float); 13 | 14 | virtual ObjType type() const { return BOX; } 15 | 16 | virtual void *ptr() { return this; } 17 | 18 | virtual Vector3 minVector() const; 19 | virtual Vector3 maxVector() const; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /sources/Camera.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Miro.h" 4 | #include "Camera.h" 5 | #include "Image.h" 6 | #include "Scene.h" 7 | #include "Console.h" 8 | #include "OpenGL.h" 9 | 10 | Camera * g_camera = 0; 11 | 12 | static bool firstRayTrace = true; 13 | 14 | const float HalfDegToRad = DegToRad/2.0f; 15 | 16 | Camera::Camera() : 17 | m_renderer(RENDER_OPENGL), 18 | m_eye(0,0,0), 19 | m_viewDir(0,0,-1), 20 | m_up(0,1,0), 21 | m_lookAt(FLT_MAX, FLT_MAX, FLT_MAX), 22 | m_fov((45.)*(PI/180.)) 23 | { 24 | calcLookAt(); 25 | } 26 | 27 | 28 | Camera::~Camera() 29 | { 30 | 31 | } 32 | 33 | 34 | void 35 | Camera::click(Scene* pScene, Image* pImage) 36 | { 37 | calcLookAt(); 38 | static bool firstRayTrace = false; 39 | 40 | if (m_renderer == RENDER_OPENGL) 41 | { 42 | glDrawBuffer(GL_BACK); 43 | pScene->openGL(this); 44 | firstRayTrace = true; 45 | } 46 | else if (m_renderer == RENDER_RAYTRACE) 47 | { 48 | glMatrixMode(GL_PROJECTION); 49 | glLoadIdentity(); 50 | glMatrixMode(GL_MODELVIEW); 51 | glLoadIdentity(); 52 | 53 | glDrawBuffer(GL_FRONT); 54 | if (firstRayTrace) 55 | { 56 | pImage->clear(pScene->bgColor()); 57 | pScene->raytraceImage(this, g_image); 58 | firstRayTrace = false; 59 | } 60 | 61 | g_image->draw(); 62 | } 63 | } 64 | 65 | 66 | void 67 | Camera::calcLookAt() 68 | { 69 | // this is true when a "lookat" is not used in the config file 70 | if (m_lookAt.x != FLT_MAX) 71 | { 72 | setLookAt(m_lookAt); 73 | m_lookAt.set(FLT_MAX, FLT_MAX, FLT_MAX); 74 | } 75 | } 76 | 77 | 78 | void 79 | Camera::drawGL() 80 | { 81 | // set up the screen with our camera parameters 82 | glMatrixMode(GL_PROJECTION); 83 | glLoadIdentity(); 84 | gluPerspective(fov(), g_image->width()/(float)g_image->height(), 85 | 0.01, 10000); 86 | 87 | glMatrixMode(GL_MODELVIEW); 88 | glLoadIdentity(); 89 | Vector3 vCenter = eye() + viewDir(); 90 | gluLookAt(eye().x, eye().y, eye().z, 91 | vCenter.x, vCenter.y, vCenter.z, 92 | up().x, up().y, up().z); 93 | } 94 | 95 | 96 | Ray 97 | Camera::eyeRay(float x, float y, int imageWidth, int imageHeight) const 98 | { 99 | // first compute the camera coordinate system 100 | // ------------------------------------------ 101 | 102 | // wDir = e - (e+m_viewDir) = -m_vView 103 | const Vector3 wDir = Vector3(-m_viewDir).normalize(); 104 | const Vector3 uDir = cross(m_up, wDir).normalize(); 105 | const Vector3 vDir = cross(wDir, uDir); 106 | 107 | 108 | 109 | // next find the corners of the image plane in camera space 110 | // -------------------------------------------------------- 111 | 112 | const float aspectRatio = (float)imageWidth/(float)imageHeight; 113 | 114 | 115 | const float top = tan(m_fov*HalfDegToRad); 116 | const float right = aspectRatio*top; 117 | 118 | const float bottom = -top; 119 | const float left = -right; 120 | 121 | 122 | 123 | // transform x and y into camera space 124 | // ----------------------------------- 125 | 126 | const float imPlaneUPos = left + (right - left)*(((float)x+0.5f)/(float)imageWidth); 127 | const float imPlaneVPos = bottom + (top - bottom)*(((float)y+0.5f)/(float)imageHeight); 128 | 129 | return Ray(m_eye, (imPlaneUPos*uDir + imPlaneVPos*vDir - wDir).normalize()); 130 | } 131 | -------------------------------------------------------------------------------- /sources/Camera.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_CAMERA_H_INCLUDED 2 | #define CSE168_CAMERA_H_INCLUDED 3 | 4 | #include "Vector3.h" 5 | #include "Miro.h" 6 | #include "Ray.h" 7 | 8 | class Camera 9 | { 10 | public: 11 | Camera(); 12 | virtual ~Camera(); 13 | 14 | enum 15 | { 16 | RENDER_OPENGL = 0, 17 | RENDER_RAYTRACE = 1 18 | }; 19 | 20 | void click(Scene* pScene, Image* pImage); 21 | 22 | inline bool isOpenGL() const {return m_renderer == RENDER_OPENGL;} 23 | inline void setRenderer(int i) {m_renderer = i;} 24 | 25 | inline void setEye(float x, float y, float z); 26 | inline void setEye(const Vector3& eye); 27 | inline void setUp(float x, float y, float z); 28 | inline void setUp(const Vector3& up); 29 | inline void setViewDir(float x, float y, float z); 30 | inline void setViewDir(const Vector3& vd); 31 | inline void setLookAt(float x, float y, float z); 32 | inline void setLookAt(const Vector3& look); 33 | inline void setFOV(float fov) {m_fov = fov;} 34 | 35 | inline float fov() const {return m_fov;} 36 | inline const Vector3 & viewDir() const {return m_viewDir;} 37 | inline const Vector3 & lookAt() const {return m_lookAt;} 38 | inline const Vector3 & up() const {return m_up;} 39 | inline const Vector3 & eye() const {return m_eye;} 40 | 41 | Ray eyeRay(float x, float y, int imageWidth, int imageHeight) const; 42 | 43 | void drawGL(); 44 | 45 | private: 46 | 47 | void calcLookAt(); 48 | 49 | int m_renderer; 50 | 51 | // main screen params 52 | Vector3 m_eye; 53 | Vector3 m_up; 54 | Vector3 m_viewDir; 55 | Vector3 m_lookAt; 56 | float m_fov; 57 | }; 58 | 59 | extern Camera * g_camera; 60 | 61 | //-------------------------------------------------------- 62 | 63 | inline void Camera::setEye(float x, float y, float z) 64 | { 65 | Vector3 v(x, y, z); 66 | setEye(v); 67 | } 68 | 69 | inline void Camera::setEye(const Vector3& eye) 70 | { 71 | m_eye.set(eye); 72 | } 73 | 74 | inline void Camera::setUp(float x, float y, float z) 75 | { 76 | Vector3 v(x, y, z); 77 | setUp(v); 78 | } 79 | 80 | inline void Camera::setUp(const Vector3& up) 81 | { 82 | m_up.set(up); 83 | m_up.normalize(); 84 | } 85 | 86 | inline void Camera::setViewDir(float x, float y, float z) 87 | { 88 | Vector3 v(x, y, z); 89 | setViewDir(v); 90 | } 91 | 92 | inline void Camera::setViewDir(const Vector3& vd) 93 | { 94 | m_viewDir.set(vd); 95 | m_viewDir.normalize(); 96 | } 97 | 98 | inline void Camera::setLookAt(float x, float y, float z) 99 | { 100 | Vector3 v(x, y, z); 101 | setLookAt(v); 102 | } 103 | 104 | inline void Camera::setLookAt(const Vector3& vd) 105 | { 106 | Vector3 dir = vd - m_eye; 107 | setViewDir(dir); 108 | } 109 | 110 | #endif // CSE168_CAMERA_H_INCLUDED 111 | -------------------------------------------------------------------------------- /sources/CellularStoneTexture.cpp: -------------------------------------------------------------------------------- 1 | #include "CellularStoneTexture.h" 2 | #include "Ray.h" 3 | #include "Scene.h" 4 | #include "Perlin.h" 5 | #include "Worley.h" 6 | #include 7 | 8 | CellularStoneTexture::CellularStoneTexture(float tile_size, float sep_size, const Vector3& sep_color) 9 | { 10 | m_tile_size = 1.0f / tile_size; 11 | m_sep_delta = sep_size; 12 | m_tiles_colors.push_back(Vector3(0.6, 0.35, 0.19)); 13 | m_tiles_colors.push_back(Vector3(0.68, 0.41, 0.21)); 14 | m_tiles_colors.push_back(Vector3(0.82, 0.49, 0.35)); 15 | m_tiles_colors.push_back(Vector3(0.5, 0.33, 0.16)); 16 | m_tiles_colors.push_back(Vector3(0.42, 0.23, 0.14)); 17 | m_sep_color = sep_color; 18 | } 19 | 20 | CellularStoneTexture::~CellularStoneTexture() 21 | { 22 | } 23 | 24 | Vector3 25 | CellularStoneTexture::getTextureColorAt(const Vector3& pos) const 26 | { 27 | Vector3 color(m_sep_color); 28 | Vector3 npos(pos); 29 | 30 | float at[] = {npos.x * m_tile_size, npos.y * m_tile_size, npos.z * m_tile_size}; 31 | float F[m_max_order]; 32 | float delta[m_max_order][3]; 33 | unsigned int ID[m_max_order]; 34 | float noise_scale = 0.2f; 35 | float p_noise = 0; 36 | 37 | WorleyNoise::noise3D(at, m_max_order, F, delta, ID); 38 | if(F[2] - F[1] < -m_sep_delta || F[2] - F[1] > m_sep_delta) 39 | { 40 | color = m_tiles_colors[ID[1] % m_tiles_colors.size()] + m_tiles_colors[ID[0] % m_tiles_colors.size()]; 41 | npos *= 6; 42 | noise_scale = 0.05; 43 | p_noise = (PerlinNoise::noise(npos.x, npos.y, npos.z)); 44 | } 45 | else 46 | { 47 | npos *= 18; 48 | p_noise = (PerlinNoise::noise(npos.x, npos.y, npos.z)) + 0.6; 49 | } 50 | color = (1.0f - noise_scale) * color + noise_scale * p_noise; 51 | return color; 52 | } 53 | 54 | Vector3 55 | CellularStoneTexture::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const 56 | { 57 | return getTextureColorAt(hit.P); 58 | } 59 | -------------------------------------------------------------------------------- /sources/CellularStoneTexture.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_CELLULAR_STONE_TEXTURE_H_INCLUDED 2 | #define CSE168_CELLULAR_STONE_TEXTURE_H_INCLUDED 3 | 4 | #include "Material.h" 5 | #include 6 | 7 | class CellularStoneTexture : public Material 8 | { 9 | public: 10 | // tile_size: value between 0(small tiles) and 1(normal tiles) 11 | // sep_size: Separator between tiles (0.03 is a good value) 12 | CellularStoneTexture(float tile_size = 1.0f, float sep_size = 0.03f, const Vector3& sep_color = Vector3(0.9f)); 13 | virtual ~CellularStoneTexture(); 14 | 15 | virtual void preCalc() {} 16 | 17 | virtual Vector3 shade(const Ray& ray, const HitInfo& hit, 18 | const Scene& scene) const; 19 | 20 | protected: 21 | Vector3 getTextureColorAt(const Vector3& pos) const; 22 | 23 | protected: 24 | std::vector m_tiles_colors; 25 | float m_tile_size; 26 | static const int m_max_order = 3; 27 | float m_sep_delta; 28 | Vector3 m_sep_color; 29 | }; 30 | 31 | #endif // CSE168_CELLULAR_STONE_TEXTURE_H_INCLUDED 32 | -------------------------------------------------------------------------------- /sources/Console.cpp: -------------------------------------------------------------------------------- 1 | // you probably dont want to modify this file 2 | 3 | #include 4 | #include 5 | #include 6 | #include "Console.h" 7 | 8 | #ifdef WIN32 9 | #include 10 | //#include 11 | 12 | // disable useless warnings 13 | #pragma warning(disable:4996) 14 | #endif 15 | 16 | static char __internal_console_buffer__[8192] = {'\0'}; 17 | 18 | #define TEXT_NORMAL "\033[0m" 19 | #define TEXT_RED "\033[1;31m" 20 | #define TEXT_GREEN "\033[1;32m" 21 | #define TEXT_PINK "\033[1;35m" 22 | 23 | 24 | #ifdef WIN32 25 | static void cprintf(const char *s) { 26 | unsigned short attr = 0; 27 | int code = 0, state = 0; 28 | while (*s) { 29 | char ch = *s++; 30 | if (ch == 27) 31 | state = 1; 32 | else if (state == 1) { 33 | if (ch == '[') { 34 | state = 2; 35 | code = 0; 36 | } 37 | else 38 | state = 0; 39 | } 40 | else if (state == 2) { 41 | if (ch == ';' || ch == 'm') { // finished with this one 42 | fflush(stdout); 43 | switch (code) { 44 | case 0: attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; 45 | case 1: attr |= FOREGROUND_INTENSITY; break; 46 | case 3: attr |= COMMON_LVB_UNDERSCORE; break; 47 | case 7: attr |= COMMON_LVB_REVERSE_VIDEO; break; 48 | case 31: attr |= FOREGROUND_RED; break; 49 | case 32: attr |= FOREGROUND_GREEN; break; 50 | case 33: attr |= FOREGROUND_RED | FOREGROUND_GREEN; break; 51 | case 34: attr |= FOREGROUND_BLUE | FOREGROUND_INTENSITY; break; 52 | case 35: attr |= FOREGROUND_RED | FOREGROUND_BLUE; break; 53 | case 36: attr |= FOREGROUND_GREEN | FOREGROUND_BLUE; break; 54 | case 37: attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; 55 | case 38: attr |= FOREGROUND_BLUE | FOREGROUND_BLUE; break; 56 | case 41: attr |= BACKGROUND_INTENSITY | BACKGROUND_RED; break; 57 | case 42: attr |= BACKGROUND_INTENSITY | BACKGROUND_GREEN; break; 58 | case 43: attr |= BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN; break; 59 | case 44: attr |= BACKGROUND_INTENSITY | BACKGROUND_BLUE; break; 60 | case 45: attr |= BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE; break; 61 | case 46: attr |= BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE; break; 62 | case 47: attr |= BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; break; 63 | } 64 | code = 0; 65 | if (ch == 'm') { 66 | //setConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),attr); 67 | state = 0; 68 | } 69 | } 70 | else 71 | code = (code * 10) + (ch - '0'); // leading digit 72 | } else { 73 | putchar(ch); 74 | attr = 0; 75 | } 76 | } 77 | } 78 | #else 79 | #define cprintf printf 80 | #define _vsnprintf vsnprintf 81 | #endif 82 | 83 | void warning(const char *fmt,...) 84 | { 85 | va_list msg; 86 | va_start (msg, fmt); 87 | _vsnprintf(__internal_console_buffer__, 8191, fmt, msg); 88 | va_end (msg); 89 | 90 | cprintf(TEXT_PINK "warning: " TEXT_NORMAL); 91 | cprintf(__internal_console_buffer__); 92 | } 93 | 94 | void error(const char *fmt,...) 95 | { 96 | va_list msg; 97 | va_start (msg, fmt); 98 | _vsnprintf(__internal_console_buffer__, 8191, fmt, msg); 99 | va_end (msg); 100 | 101 | cprintf(TEXT_RED "error: " TEXT_NORMAL); 102 | cprintf(__internal_console_buffer__); 103 | } 104 | 105 | void debug(const char *fmt,...) 106 | { 107 | va_list msg; 108 | va_start (msg, fmt); 109 | _vsnprintf(__internal_console_buffer__, 8191, fmt, msg); 110 | va_end (msg); 111 | 112 | cprintf(TEXT_GREEN "debug: " TEXT_NORMAL); 113 | cprintf(__internal_console_buffer__); 114 | } 115 | 116 | void fatal(const char *fmt,...) 117 | { 118 | va_list msg; 119 | va_start (msg, fmt); 120 | _vsnprintf(__internal_console_buffer__, 8191, fmt, msg); 121 | va_end (msg); 122 | 123 | cprintf(TEXT_RED "fatal error: " TEXT_NORMAL); 124 | cprintf(__internal_console_buffer__); 125 | exit(-1); 126 | } 127 | 128 | /* 129 | cprintf(" Misc Options\n" 130 | "\033[7m Hi-Lite Font = \\033[7m \033[0m\n" 131 | "\033[4mUnderLine Font = \\033[4m \033[0m\n" 132 | "\033[0mBack To Normal = \\033[0m \033[0m\n\n" 133 | 134 | " Font Colors\n" 135 | "\033[40m\033[1;37m White = \\033[1;37m \033[0m\n" 136 | "\033[40m\033[1;30m Gray = \\033[1;30m \033[0m\n" 137 | "\033[40m\033[37m Light Gray = \\033[37m \033[0m\n" 138 | "\033[47m\033[30m Black = \\033[30m \033[0m\n" 139 | "\033[40m\033[31m Red = \\033[31m \033[0m\n" 140 | "\033[40m\033[1;31m Light Red = \\033[1;31m \033[0m\n" 141 | "\033[40m\033[32m Green = \\033[32m \033[0m\n" 142 | "\033[40m\033[1;32m Light Green = \\033[1;32m \033[0m\n" 143 | "\033[40m\033[33m Yellow = \\033[33m \033[0m\n" 144 | "\033[40m\033[1;33m Light Yellow = \\033[1;33m \033[0m\n" 145 | "\033[40m\033[34m Blue = \\033[34m \033[0m\n" 146 | "\033[40m\033[1;34m Light Blue = \\033[1;34m \033[0m\n" 147 | "\033[40m\033[35m Purple = \\033[35m \033[0m\n" 148 | "\033[40m\033[1;35m Pink = \\033[1;35m \033[0m\n" 149 | "\033[40m\033[36m Cyan = \\033[36m \033[0m\n" 150 | "\033[40m\033[1;36m Light Cyan = \\033[1;36m \033[0m\n" 151 | "\033[40m\033[0mBack To Normal = \\033[0m \033[0m\n"); 152 | 153 | cprintf("\n BackGround Colors\n" 154 | "\033[1;37m\033[40m Black = \\033[40m \033[0m\n" 155 | "\033[1;37m\033[41m Red = \\033[41m \033[0m\n" 156 | "\033[1;37m\033[42m Green = \\033[42m \033[0m\n" 157 | "\033[1;37m\033[43m Yellow = \\033[43m \033[0m\n" 158 | "\033[1;37m\033[44m Blue = \\033[44m \033[0m\n" 159 | "\033[1;37m\033[45m Purple = \\033[45m \033[0m\n" 160 | "\033[1;37m\033[46m Cyan = \\033[46m \033[0m\n" 161 | "\033[1;37m\033[47m Gray = \\033[47m \033[0m\n" 162 | "\033[1;30m\033[5;47m White = \\033[5;47m \033[0m\n"); 163 | cprintf("\033[1;37m\033[0mBack To Normal = \\033[0m \033[0m\n\n"); 164 | 165 | */ 166 | -------------------------------------------------------------------------------- /sources/Console.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_CONSOLE_H_INCLUDED 2 | 3 | void warning(const char *fmt,...); 4 | void error(const char *fmt,...); 5 | void debug(const char *fmt,...); 6 | void fatal(const char *fmt,...); 7 | 8 | #endif // CSE168_CONSOLE_H_INCLUDED 9 | -------------------------------------------------------------------------------- /sources/Image.cpp: -------------------------------------------------------------------------------- 1 | #include "Miro.h" 2 | #include "Image.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef WIN32 8 | // disable useless warnings 9 | #pragma warning(disable:4996) 10 | #endif 11 | 12 | Image * g_image = 0; 13 | 14 | Image::Image() 15 | { 16 | m_pixels = 0; 17 | m_width = 1; 18 | m_height = 1; 19 | } 20 | 21 | Image::~Image() 22 | { 23 | if (m_pixels) 24 | delete [] m_pixels; 25 | } 26 | 27 | void Image::resize(int width, int height) 28 | { 29 | if (m_pixels) 30 | delete [] m_pixels; 31 | m_pixels = 0; 32 | m_pixels = new Pixel[width*height]; 33 | memset(m_pixels, 0, width*height*sizeof(Pixel)); 34 | m_width = width; 35 | m_height = height; 36 | } 37 | 38 | void Image::clear(const Vector3& c) 39 | { 40 | // should be bg color 41 | for (int y=0; y255?255:(unsigned char)rMap; 51 | return c; 52 | } 53 | 54 | void Image::setPixel(int x, int y, const Vector3& p) 55 | { 56 | // do some tone mapping 57 | if (x >= 0 && x < m_width && y < m_height && y >= 0) 58 | { 59 | m_pixels[y*m_width+x].r = Map(p.x); 60 | m_pixels[y*m_width+x].g = Map(p.y); 61 | m_pixels[y*m_width+x].b = Map(p.z); 62 | } 63 | } 64 | 65 | void Image::setPixel(int x, int y, const Pixel& p) 66 | { 67 | // do some tone mapping 68 | if (x >= 0 && x < m_width && y < m_height && y >= 0) 69 | { 70 | m_pixels[y*m_width+x]= p; 71 | } 72 | } 73 | 74 | void Image::drawScanline(int y) 75 | { 76 | glRasterPos2f(-1, -1 + 2*y / (float)m_height); 77 | glDrawPixels(m_width, 1, GL_RGB, GL_UNSIGNED_BYTE, &m_pixels[y*m_width]); 78 | } 79 | 80 | void Image::draw() 81 | { 82 | for (int i = 0; i < m_height; i++) 83 | drawScanline(i); 84 | } 85 | 86 | void Image::writePPM(char* pcFile) 87 | { 88 | writePPM(pcFile, (unsigned char*)m_pixels, m_width, m_height); 89 | } 90 | 91 | void Image::writePPM(char *pcFile, unsigned char *data, int width, int height) 92 | { 93 | FILE *fp = fopen(pcFile, "wb"); 94 | if (!fp) 95 | fprintf(stderr, "Couldn't open PPM file %s for writing\n", pcFile); 96 | else 97 | { 98 | fprintf(fp, "P6\n"); 99 | fprintf(fp, "%d %d\n", width, height ); 100 | fprintf(fp, "255\n" ); 101 | 102 | // invert image 103 | int stride = width*3; 104 | for (int i = height-1; i >= 0; i--) 105 | fwrite(&data[stride*i], stride, 1, fp); 106 | fclose(fp); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /sources/Image.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_IMAGE_H_INCLUDED 2 | #define CSE168_IMAGE_H_INCLUDED 3 | 4 | #include "Vector3.h" 5 | 6 | class Image 7 | { 8 | public: 9 | struct Pixel 10 | { 11 | unsigned char r, g, b; 12 | Pixel(unsigned char ir, unsigned char ig, unsigned char ib) {set(ir, ig, ib);} 13 | Pixel() : r(0), g(0), b(0) {} 14 | void set(unsigned char ir, unsigned char ig, unsigned char ib) {r = ir; g = ig; b = ib;} 15 | }; 16 | 17 | Image(); 18 | ~Image(); 19 | 20 | void resize(int width, int height); 21 | void setPixel(int x, int y, const Vector3& p); 22 | void setPixel(int x, int y, const Pixel& p); 23 | 24 | void draw(); 25 | void drawScanline(int y); 26 | void clear(const Vector3& c); 27 | void writePPM(char* pcFile); // write data to a ppm image file 28 | void writePPM(char *pcName, unsigned char *data, int width, int height); 29 | 30 | unsigned char* getCharPixels() {return (unsigned char*)m_pixels;} 31 | int width() const {return m_width;} 32 | int height() const {return m_height;} 33 | 34 | private: 35 | Pixel* m_pixels; 36 | int m_width; 37 | int m_height; 38 | }; 39 | 40 | extern Image * g_image; 41 | 42 | #endif // CSE168_IMAGE_H_INCLUDED 43 | -------------------------------------------------------------------------------- /sources/IntersectObjects.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "SSEObject.h" 5 | 6 | struct IntersectObjects 7 | { 8 | IntersectObjects() : sse_preprocessed(0) {} 9 | 10 | void *sse_preprocessed; 11 | std::vector plain; 12 | }; 13 | -------------------------------------------------------------------------------- /sources/Makedefs: -------------------------------------------------------------------------------- 1 | MAKE = make 2 | AR = @ar 3 | CC = @clang++ 4 | MV = @mv 5 | RM = @rm -rf 6 | MKDIR = @mkdir 7 | MKDEP = @mkdep 8 | ECHO = @echo 9 | INCDIRS = -I/usr/X11R6/include 10 | #use the following LIBS line for GNU/Linux 11 | LIBS = -lm -lX11 -lXmu -lXi -lXext -lGL -lGLU -lglut -lboost_thread-mt -lboost_system-mt -lboost_exception-mt -lboost_timer-mt -lpthread -ljpeg 12 | #use this one instead for Mac OSX 13 | #LIBS = -lm -framework GLUT --lobjc -framework OpenGL 14 | LIBDIRS = -L. -L/usr/X11R6/lib 15 | LDFLAGS = $(LIBDIRS) $(LIBS) 16 | CFLAGS = $(INCDIRS) -march=native -std=c++11 -O3 \ 17 | -Wno-deprecated -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -g 18 | 19 | .SUFFIXES: .cpp .h .d .o 20 | 21 | .cpp.o: 22 | $(ECHO) "Compiling $<" 23 | $(CC) $(CFLAGS) -c -o $@ $< 24 | .d.o: 25 | $(ECHO) "Finding dependancies for $<" 26 | $(CC) $(CFLAGS) -MD -E $< 27 | 28 | SOURCES = $(wildcard *.cpp) 29 | OBJS = $(patsubst %.cpp, %.o, $(SOURCES)) 30 | DEPS = $(patsubst %.cpp, %.d, $(SOURCES)) 31 | 32 | clean: 33 | $(RM) core .deps *.o $(NAME) 34 | $(RM) lexer.cpp parse.cpp parse.cpp.h 35 | $(ECHO) "All clean!" 36 | 37 | deps: 38 | $(ECHO) "Finding dependancies in `pwd`..." 39 | $(RM) .deps 40 | $(CC) $(CFLAGS) -MD -E $(SOURCES) > /dev/null 41 | $(MKDIR) .deps 42 | $(MV) $(DEPS) .deps 43 | 44 | -------------------------------------------------------------------------------- /sources/Makefile: -------------------------------------------------------------------------------- 1 | NAME = miro 2 | 3 | all: $(NAME) 4 | 5 | include Makedefs 6 | SOURCES -= parse.cpp lexer.cpp 7 | OBJS -= parse.o lexer.o 8 | # 9 | # lexer.cpp: lexer.lex 10 | # $(ECHO) "Flex-ing lexer.lex" 11 | # $(FLEX) -o$@ lexer.lex 12 | # 13 | # parse.cpp: parse.y 14 | # $(ECHO) "Bison-ing parse.y" 15 | # $(BISON) -d -o $@ parse.y 16 | # @if [ -f parse.hpp ]; then \ 17 | # mv parse.hpp parse.cpp.h; \ 18 | # fi 19 | # @if [ -f parse.tab.hpp ]; then \ 20 | # mv parse.tab.hpp parse.cpp.h; \ 21 | # fi 22 | # @if [ -f parse.tab.h ]; then \ 23 | # mv parse.tab.h parse.cpp.h; \ 24 | # fi 25 | 26 | -include .deps/*.d 27 | 28 | $(NAME): $(OBJS) 29 | $(ECHO) "Linking $@..." 30 | $(CC) -o $@ *.o $(LIBS) $(LIBDIRS) #$(OBJS) 31 | $(ECHO) "Built $@!" 32 | 33 | -------------------------------------------------------------------------------- /sources/Material.cpp: -------------------------------------------------------------------------------- 1 | #include "Material.h" 2 | 3 | Material::Material() : m_castShadow(true) 4 | { 5 | m_color = Vector3(1, 1, 1); 6 | } 7 | 8 | Material::~Material() 9 | { 10 | } 11 | 12 | Vector3 13 | Material::shade(const Ray&, const HitInfo&, const Scene&) const 14 | { 15 | return m_color; 16 | } 17 | -------------------------------------------------------------------------------- /sources/Material.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_MATERIAL_H_INCLUDED 2 | #define CSE168_MATERIAL_H_INCLUDED 3 | 4 | #include "Miro.h" 5 | #include "Vector3.h" 6 | #include "PhotonMap.h" 7 | #include 8 | 9 | class Material 10 | { 11 | public: 12 | Material(); 13 | virtual ~Material(); 14 | 15 | virtual void preCalc() {} 16 | 17 | virtual Vector3 shade(const Ray& ray, const HitInfo& hit, 18 | const Scene& scene) const; 19 | 20 | virtual void shadePhoton(const Ray &ray, const HitInfo &hit, const Scene &scene, Vector3 const &power, Photon_map *map) const {throw std::runtime_error("Not implemented");} 21 | 22 | virtual bool castShadow() const {return m_castShadow;} 23 | virtual void setCastShadow(bool b) {m_castShadow = b;} 24 | 25 | virtual bool hasBump() const { return false; } 26 | 27 | protected: 28 | Vector3 m_color; 29 | bool m_castShadow; 30 | }; 31 | 32 | #endif // CSE168_MATERIAL_H_INCLUDED 33 | -------------------------------------------------------------------------------- /sources/Miro.h: -------------------------------------------------------------------------------- 1 | #ifndef __MIRO_H__ 2 | #define __MIRO_H__ 3 | #include 4 | #include 5 | #include 6 | 7 | using boost::shared_ptr; 8 | 9 | // #ifndef max 10 | // #define max(a,b) ((a>b)?a:b) 11 | // #endif 12 | 13 | const float MIRO_TMAX = 1e12f; 14 | const float epsilon = 0.001f; 15 | const float PI = 3.1415926535897932384626433832795028841972f; 16 | const float DegToRad = PI/180.0f; 17 | const float RadToDeg = 180.0f/PI; 18 | 19 | #include 20 | #include "OpenGL.h" 21 | #include 22 | #include 23 | 24 | class Ray; 25 | class HitInfo; 26 | 27 | class Object; 28 | class Sphere; 29 | class Triangle; 30 | class TriangleMesh; 31 | class Instance; 32 | 33 | class PointLight; 34 | 35 | class Camera; 36 | class Image; 37 | class Scene; 38 | class Material; 39 | class Photon_map; 40 | 41 | extern void ParseFile(FILE* fp); 42 | extern void initOpenGL(); 43 | extern Camera* g_camera; 44 | extern Scene* g_scene; 45 | extern Image* g_image; 46 | extern Photon_map* g_global_illum_map; 47 | extern Photon_map* g_caustics_map; 48 | 49 | extern boost::mt19937 g_rng; 50 | //extern boost::uniform_01 randone; 51 | 52 | inline float randone(const boost::mt19937& g_rng) 53 | { 54 | #ifdef WIN32 55 | unsigned int r; 56 | rand_s(&r); 57 | return ((float)r)/UINT_MAX; 58 | #else 59 | return drand48(); 60 | #endif 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /sources/MiroWindow.cpp: -------------------------------------------------------------------------------- 1 | #include "MiroWindow.h" 2 | #include "OpenGL.h" 3 | #include "Miro.h" 4 | #include "Camera.h" 5 | #include "Image.h" 6 | #include 7 | #include 8 | 9 | #define ANGFACT 1.0 10 | #define LEFT 4 11 | #define MIDDLE 2 12 | #define RIGHT 1 13 | 14 | #ifdef WIN32 15 | // disable useless warnings 16 | #pragma warning(disable:4996) 17 | #endif 18 | 19 | 20 | namespace 21 | { 22 | 23 | // Non-member functions used as proxy callbacks to our real C++ member functions 24 | MiroWindow *g_miroWindow; 25 | void display() {g_miroWindow->display();} 26 | void resize(int x,int y) {g_miroWindow->reshape(x,y);} 27 | void keyboard(unsigned char key, int x, int y) {g_miroWindow->keyboard(key,x,y);} 28 | void mouse(int btn,int state,int x,int y) {g_miroWindow->mouse(btn,state,x,y);} 29 | void motion(int x, int y) {g_miroWindow->motion(x,y);} 30 | 31 | } // namespace 32 | 33 | 34 | MiroWindow::MiroWindow(int * argc, char* argv[]) : 35 | m_scaleFact(0.1f), 36 | m_activeButton(0), 37 | m_mouseX(0), 38 | m_mouseY(0) 39 | { 40 | // Initialize GLUT 41 | glutInit(argc, argv); 42 | 43 | // Create the window 44 | glutInitWindowSize(g_image->width(), g_image->height()); 45 | glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 46 | glutInitWindowPosition(200, 200); 47 | glutCreateWindow("miro"); 48 | 49 | // Initialize some OpenGL state 50 | glClearColor(0.25f, 0.25f, 0.25f, 1); 51 | glDisable(GL_LIGHTING); 52 | glDisable(GL_TEXTURE_2D); 53 | glShadeModel(GL_SMOOTH); 54 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // draw outlines only 55 | } 56 | 57 | 58 | void 59 | MiroWindow::mainLoop() 60 | { 61 | // Setup callback functions 62 | g_miroWindow = this; 63 | glutDisplayFunc(::display); 64 | glutKeyboardFunc(::keyboard); 65 | glutMouseFunc(::mouse); 66 | glutMotionFunc(::motion); 67 | glutReshapeFunc(::resize); 68 | 69 | // Start the glut main loop, never returns 70 | glutMainLoop(); 71 | } 72 | 73 | 74 | void 75 | MiroWindow::display() 76 | { 77 | g_camera->click(g_scene, g_image); // take a snapshot of the scene 78 | 79 | glFinish(); // flush the openGL pipeline 80 | } 81 | 82 | 83 | void 84 | MiroWindow::motion(int x, int y) 85 | { 86 | int dx, dy; // change in mouse coordinates 87 | 88 | dx = x - m_mouseX; // change in mouse coords 89 | dy = y - m_mouseY; 90 | 91 | if (m_activeButton & LEFT) 92 | { 93 | float xfact = -ANGFACT*dy; 94 | float yfact = -ANGFACT*dx; 95 | // construct a coordinate system from up and viewdir 96 | Vector3 vRight = cross(g_camera->viewDir(), g_camera->up()); 97 | // now rotate everything 98 | Vector3 v = g_camera->viewDir(); 99 | v.rotate(xfact*PI/180., vRight); 100 | v.rotate(yfact*PI/180., g_camera->up()); 101 | g_camera->setViewDir(v); 102 | } 103 | 104 | m_mouseX = x; // new current position 105 | m_mouseY = y; 106 | 107 | glutPostRedisplay(); 108 | } 109 | 110 | 111 | void 112 | MiroWindow::mouse(int button, int state, int x, int y) 113 | { 114 | int b; // LEFT, MIDDLE, or RIGHT 115 | 116 | switch (button) 117 | { 118 | case GLUT_LEFT_BUTTON: 119 | b = LEFT; 120 | break; 121 | 122 | case GLUT_MIDDLE_BUTTON: 123 | b = MIDDLE; 124 | break; 125 | 126 | case GLUT_RIGHT_BUTTON: 127 | b = RIGHT; 128 | break; 129 | 130 | default: 131 | b = 0; 132 | } 133 | 134 | if (state == GLUT_DOWN) 135 | { 136 | m_mouseX = x; 137 | m_mouseY = y; 138 | m_activeButton |= b; /* set the proper bit */ 139 | } 140 | else 141 | m_activeButton &= ~b; /* clear the proper bit */ 142 | } 143 | 144 | void 145 | MiroWindow::keyboard(unsigned char key, int x, int y) 146 | { 147 | switch (key) 148 | { 149 | case 27: 150 | exit(0); 151 | break; 152 | 153 | case 'i': 154 | case 'I': 155 | { 156 | char str[1024]; 157 | sprintf(str, "miro_%d.ppm", time(0)); 158 | if (g_camera->isOpenGL()) 159 | { 160 | unsigned char* buf = new unsigned char[g_image->width()*g_image->height()*3]; 161 | glReadPixels(0, 0, g_image->width(), g_image->height(), 162 | GL_RGB, GL_UNSIGNED_BYTE, buf); 163 | g_image->writePPM(str, buf, g_image->width(), g_image->height()); 164 | } 165 | else 166 | { 167 | g_image->writePPM(str); 168 | } 169 | break; 170 | } 171 | 172 | case 'r': 173 | case 'R': 174 | g_camera->setRenderer(Camera::RENDER_RAYTRACE); 175 | break; 176 | 177 | case 'g': 178 | case 'G': 179 | g_camera->setRenderer(Camera::RENDER_OPENGL); 180 | break; 181 | 182 | case '+': 183 | m_scaleFact *= 1.5; 184 | break; 185 | 186 | case '-': 187 | m_scaleFact /= 1.5; 188 | break; 189 | 190 | case 'w': 191 | case 'W': 192 | g_camera->setEye(g_camera->eye() + m_scaleFact*g_camera->viewDir()); 193 | break; 194 | 195 | case 's': 196 | case 'S': 197 | g_camera->setEye(g_camera->eye() - m_scaleFact*g_camera->viewDir()); 198 | break; 199 | 200 | case 'q': 201 | case 'Q': 202 | g_camera->setEye(g_camera->eye() + m_scaleFact*g_camera->up()); 203 | break; 204 | 205 | case 'z': 206 | case 'Z': 207 | g_camera->setEye(g_camera->eye() - m_scaleFact*g_camera->up()); 208 | break; 209 | 210 | case 'a': 211 | case 'A': 212 | { 213 | Vector3 vRight = cross(g_camera->viewDir(), g_camera->up()); 214 | g_camera->setEye(g_camera->eye() - m_scaleFact*vRight); 215 | break; 216 | } 217 | 218 | case 'd': 219 | case 'D': 220 | { 221 | Vector3 vRight = cross(g_camera->viewDir(), g_camera->up()); 222 | g_camera->setEye(g_camera->eye() + m_scaleFact*vRight); 223 | break; 224 | } 225 | break; 226 | 227 | default: 228 | break; 229 | } 230 | printf("Eye: %f, %f, %f\n", g_camera->eye()[0], g_camera->eye()[1], g_camera->eye()[2]); 231 | 232 | glutPostRedisplay(); 233 | } 234 | 235 | 236 | void 237 | MiroWindow::reshape(int w, int h) 238 | { 239 | g_image->resize(w, h); 240 | glViewport(0, 0, w, h); 241 | g_camera->setRenderer(Camera::RENDER_OPENGL); 242 | glutPostRedisplay(); 243 | } 244 | 245 | -------------------------------------------------------------------------------- /sources/MiroWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_MIRO_GLUT_WINDOW_H_INCLUDED 2 | #define CSE168_MIRO_GLUT_WINDOW_H_INCLUDED 3 | 4 | class MiroWindow 5 | { 6 | public: 7 | MiroWindow(int * argc, char* argv[]); 8 | 9 | void mainLoop(); 10 | 11 | // GLUT Event handlers 12 | void display(); 13 | void reshape(int x, int y); 14 | void keyboard(unsigned char key, int x, int y); 15 | void mouse(int btn, int state, int x, int y); 16 | void motion(int x, int y); 17 | 18 | protected: 19 | float m_scaleFact; 20 | int m_activeButton; 21 | int m_mouseX, m_mouseY; 22 | }; 23 | 24 | #endif // CSE168_MIRO_GLUT_WINDOW_H_INCLUDED 25 | 26 | 27 | -------------------------------------------------------------------------------- /sources/MyBoost.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __GNUC__ 4 | #define LIKELY(cond) __builtin_expect(cond, 1) 5 | #define UNLIKELY(cond) __builtin_expect(cond, 0) 6 | #else 7 | #define LIKELY(cond) (cond) 8 | #define UNLIKELY(cond) (cond) 9 | #endif 10 | 11 | class Nothing {}; 12 | 13 | // member_if::type is the type if Cond is true, or a zero length array if Cond is false. 14 | // This way, if cond is false, you can declare a member that is unusable and takes 0 bytes. 15 | // Not standard: zero length arrays are "illegal", but work in GCC and Visual Studio (2012 at least). 16 | template 17 | struct member_if 18 | { 19 | typedef T type; 20 | }; 21 | 22 | template 23 | struct member_if<0, T> 24 | { 25 | typedef Nothing type[0]; 26 | }; 27 | -------------------------------------------------------------------------------- /sources/Object.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_OBJECT_H_INCLUDED 2 | #define CSE168_OBJECT_H_INCLUDED 3 | 4 | #include 5 | #include "Miro.h" 6 | #include "Material.h" 7 | #include "IntersectObjects.h" 8 | 9 | enum ObjType 10 | { 11 | SPHERE, 12 | TRIANGLE, 13 | BLPATCH, 14 | BOUNDING_BOX, 15 | BOX, 16 | NB_OBJS 17 | }; 18 | 19 | class ObjBundle; 20 | 21 | class Object 22 | { 23 | public: 24 | Object() {} 25 | virtual ~Object() {} 26 | 27 | void setMaterial(const Material* m) {m_material = m;} 28 | 29 | virtual void renderGL() {} 30 | virtual void preCalc() {} 31 | 32 | // Needs a static function that intersects a bunch of objects of the same type 33 | 34 | virtual ObjType type() const = 0; 35 | 36 | virtual void *ptr() = 0; 37 | 38 | virtual Vector3 minVector() const = 0; 39 | virtual Vector3 maxVector() const = 0; 40 | 41 | protected: 42 | const Material* m_material; 43 | }; 44 | 45 | typedef std::vector Objects; 46 | 47 | #endif // CSE168_OBJECT_H_INCLUDED 48 | -------------------------------------------------------------------------------- /sources/OpenGL.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_OPENGL_H_INCLUDED 2 | #define CSE168_OPENGL_H_INCLUDED 3 | 4 | // use the following on Windows or GNU/Linux 5 | #ifndef __APPLE__ 6 | 7 | #ifndef GLUT_BUILDING_LIB 8 | #define GLUT_BUILDING_LIB 9 | #endif // GLUT_BUILDING_LIB 10 | #include 11 | 12 | #else 13 | 14 | // use this on Mac OSX 15 | #include 16 | 17 | #endif 18 | 19 | #endif // CSE168_OPENGL_H_INCLUDED 20 | 21 | 22 | -------------------------------------------------------------------------------- /sources/PFMLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "PFMLoader.h" 2 | #include 3 | 4 | // define this to 1 if you are running on a big-endian machine (e.g. PPC Macs) 5 | // #if WORDS_BIGENDIAN 6 | 7 | namespace 8 | { 9 | 10 | inline void 11 | byteSwapFloat(float& f) 12 | { 13 | union {float f; unsigned char b[4];} u1, u2; 14 | 15 | u1.f = f; 16 | u2.b[0] = u1.b[3]; 17 | u2.b[1] = u1.b[2]; 18 | u2.b[2] = u1.b[1]; 19 | u2.b[3] = u1.b[0]; 20 | f = u2.f; 21 | } 22 | 23 | 24 | #if WORDS_BIGENDIAN 25 | // big endian system, need to swap bytes to convert into 26 | // external little-endian representation 27 | 28 | inline void littleEndianFloat(float& f) {byteSwapFloat (f);} 29 | inline void bigEndianFloat(float) {} 30 | 31 | #else 32 | 33 | // little endian, no need to swap 34 | inline void littleEndianFloat(float) {} 35 | inline void bigEndianFloat(float& f) {byteSwapFloat(f);} 36 | 37 | #endif 38 | 39 | } 40 | 41 | 42 | Vector3* 43 | readPFMImage(const char * filename, int * width, int * height) 44 | { 45 | FILE *infile = 0; 46 | float *lineBuffer = 0; 47 | Vector3 *img = 0; 48 | char junk; 49 | 50 | try 51 | { 52 | infile = fopen(filename, "rb"); 53 | if (!infile) 54 | throw std::runtime_error("cannot open file."); 55 | 56 | int a = fgetc(infile); 57 | int b = fgetc(infile); 58 | fgetc(infile); 59 | 60 | if ((a != 'P') || ((b != 'F') && (b != 'f'))) 61 | throw std::runtime_error("not a PFM image file."); 62 | 63 | b = (b == 'F'); // 'F' = RGB, 'f' = monochrome 64 | 65 | fscanf(infile, "%d %d%c", width, height, &junk); 66 | if ((*width <= 0) || (*height <= 0)) 67 | throw std::runtime_error("invalid width or height."); 68 | 69 | float scaleFactor; 70 | fscanf(infile, "%f%c", &scaleFactor, &junk); 71 | 72 | img = new Vector3[*width * *height]; 73 | 74 | a = *width * (b ? 3 : 1); 75 | lineBuffer = new float[a]; 76 | for (int y = 0; y < *height; ++y) 77 | { 78 | Vector3 *cur = &img[y * *width]; 79 | if (fread(lineBuffer, sizeof(float), a, infile) != (size_t) a) 80 | throw std::runtime_error("cannot read pixel data."); 81 | 82 | float *temp = lineBuffer; 83 | for (int x = 0; x < *width; x++) 84 | { 85 | if (b) 86 | { // color 87 | (*cur)[0] = *temp++; 88 | (*cur)[1] = *temp++; 89 | (*cur)[2] = *temp++; 90 | 91 | if (scaleFactor > 0.0) 92 | { 93 | bigEndianFloat((*cur)[0]); 94 | bigEndianFloat((*cur)[1]); 95 | bigEndianFloat((*cur)[2]); 96 | } 97 | else 98 | { 99 | littleEndianFloat((*cur)[0]); 100 | littleEndianFloat((*cur)[1]); 101 | littleEndianFloat((*cur)[2]); 102 | } 103 | } 104 | else 105 | { // black and white 106 | float c = *temp++; 107 | 108 | if (scaleFactor > 0.0) 109 | bigEndianFloat (c); 110 | else 111 | littleEndianFloat (c); 112 | 113 | (*cur)[0] = (*cur)[1] = (*cur)[2] = c; 114 | } 115 | cur++; 116 | } 117 | } 118 | 119 | delete [] lineBuffer; 120 | fclose(infile); 121 | 122 | return img; 123 | } 124 | catch (const std::exception &e) 125 | { 126 | printf("Unable to read image file \"%s\": %s", 127 | filename, e.what()); 128 | delete [] lineBuffer; 129 | delete [] img; 130 | if (infile) 131 | fclose (infile); 132 | return 0; 133 | } 134 | catch (...) 135 | { 136 | printf("Unable to read image file \"%s\".", filename); 137 | delete [] lineBuffer; 138 | delete [] img; 139 | if (infile) 140 | fclose (infile); 141 | return 0; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /sources/PFMLoader.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_PFM_LOADER_H_INCLUDED 2 | #define CSE168_PFM_LOADER_H_INCLUDED 3 | 4 | #include "Vector3.h" 5 | 6 | Vector3* readPFMImage(const char * filename, int * width, int * height); 7 | 8 | #endif // CSE168_PFM_LOADER_H_INCLUDED 9 | -------------------------------------------------------------------------------- /sources/Perlin.cpp: -------------------------------------------------------------------------------- 1 | #include "Perlin.h" 2 | 3 | const unsigned char PerlinNoise::p[512] = 4 | { 5 | 151,160,137, 91, 90, 15,131, 13,201, 95, 96, 53,194,233, 7,225, 6 | 140, 36,103, 30, 69,142, 8, 99, 37,240, 21, 10, 23,190, 6,148, 7 | 247,120,234, 75, 0, 26,197, 62, 94,252,219,203,117, 35, 11, 32, 8 | 57,177, 33, 88,237,149, 56, 87,174, 20,125,136,171,168, 68,175, 9 | 74,165, 71,134,139, 48, 27,166, 77,146,158,231, 83,111,229,122, 10 | 60,211,133,230,220,105, 92, 41, 55, 46,245, 40,244,102,143, 54, 11 | 65, 25, 63,161, 1,216, 80, 73,209, 76,132,187,208, 89, 18,169, 12 | 200,196,135,130,116,188,159, 86,164,100,109,198,173,186, 3, 64, 13 | 52,217,226,250,124,123, 5,202, 38,147,118,126,255, 82, 85,212, 14 | 207,206, 59,227, 47, 16, 58, 17,182,189, 28, 42,223,183,170,213, 15 | 119,248,152, 2, 44,154,163, 70,221,153,101,155,167, 43,172, 9, 16 | 129, 22, 39,253, 19, 98,108,110, 79,113,224,232,178,185,112,104, 17 | 218,246, 97,228,251, 34,242,193,238,210,144, 12,191,179,162,241, 18 | 81, 51,145,235,249, 14,239,107, 49,192,214, 31,181,199,106,157, 19 | 184, 84,204,176,115,121, 50, 45,127, 4,150,254,138,236,205, 93, 20 | 222,114, 67, 29, 24, 72,243,141,128,195, 78, 66,215, 61,156,180, 21 | 22 | 151,160,137, 91, 90, 15,131, 13,201, 95, 96, 53,194,233, 7,225, 23 | 140, 36,103, 30, 69,142, 8, 99, 37,240, 21, 10, 23,190, 6,148, 24 | 247,120,234, 75, 0, 26,197, 62, 94,252,219,203,117, 35, 11, 32, 25 | 57,177, 33, 88,237,149, 56, 87,174, 20,125,136,171,168, 68,175, 26 | 74,165, 71,134,139, 48, 27,166, 77,146,158,231, 83,111,229,122, 27 | 60,211,133,230,220,105, 92, 41, 55, 46,245, 40,244,102,143, 54, 28 | 65, 25, 63,161, 1,216, 80, 73,209, 76,132,187,208, 89, 18,169, 29 | 200,196,135,130,116,188,159, 86,164,100,109,198,173,186, 3, 64, 30 | 52,217,226,250,124,123, 5,202, 38,147,118,126,255, 82, 85,212, 31 | 207,206, 59,227, 47, 16, 58, 17,182,189, 28, 42,223,183,170,213, 32 | 119,248,152, 2, 44,154,163, 70,221,153,101,155,167, 43,172, 9, 33 | 129, 22, 39,253, 19, 98,108,110, 79,113,224,232,178,185,112,104, 34 | 218,246, 97,228,251, 34,242,193,238,210,144, 12,191,179,162,241, 35 | 81, 51,145,235,249, 14,239,107, 49,192,214, 31,181,199,106,157, 36 | 184, 84,204,176,115,121, 50, 45,127, 4,150,254,138,236,205, 93, 37 | 222,114, 67, 29, 24, 72,243,141,128,195, 78, 66,215, 61,156,180, 38 | }; 39 | -------------------------------------------------------------------------------- /sources/Perlin.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_PERLIN_H_INCLUDED 2 | #define CSE168_PERLIN_H_INCLUDED 3 | 4 | #include 5 | #include "Vector3.h" 6 | 7 | //! Perlin noise class 8 | /*! 9 | Based on Java reference implementation of: 10 | Improved Noise - Copyright 2002 Ken Perlin. 11 | 12 | (http://mrl.nyu.edu/~perlin/noise/) 13 | */ 14 | class PerlinNoise 15 | { 16 | public: 17 | static float noise(float x, float y, float z) 18 | { 19 | int X = int(floor(x)) & 255, 20 | Y = int(floor(y)) & 255, 21 | Z = int(floor(z)) & 255; 22 | 23 | x -= floor(x); 24 | y -= floor(y); 25 | z -= floor(z); 26 | float u = fade(x), 27 | v = fade(y), 28 | w = fade(z); 29 | 30 | int A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z, 31 | B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z; 32 | 33 | return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), 34 | grad(p[BA ], x-1, y , z )), 35 | lerp(u, grad(p[AB ], x , y-1, z ), 36 | grad(p[BB ], x-1, y-1, z ))), 37 | lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), 38 | grad(p[BA+1], x-1, y , z-1 )), 39 | lerp(u, grad(p[AB+1], x , y-1, z-1 ), 40 | grad(p[BB+1], x-1, y-1, z-1 )))); 41 | } 42 | static float turbulence(const Vector3& pos, int freq) 43 | { 44 | float turb = 0; 45 | 46 | for (int i = 1; i <= freq; i++) 47 | { 48 | turb += noise(pos.x * i, pos.y * i, pos.z * i) / i; 49 | } 50 | return turb; 51 | } 52 | 53 | private: 54 | static float fade(float t) {return t * t * t * (t * (t * 6 - 15) + 10);} 55 | static float lerp(float t, float a, float b) {return a + t * (b - a);} 56 | static float grad(int hash, float x, float y, float z) 57 | { 58 | int h = hash & 15; 59 | float u = h<8 ? x : y, 60 | v = h<4 ? y : h==12||h==14 ? x : z; 61 | return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); 62 | } 63 | 64 | static const unsigned char p[512]; 65 | }; 66 | 67 | #endif // CSE168_PERLIN_H_INCLUDED 68 | -------------------------------------------------------------------------------- /sources/Phong.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_LAMBERT_H_INCLUDED 2 | #define CSE168_LAMBERT_H_INCLUDED 3 | 4 | #include "Material.h" 5 | #include "Texture.h" 6 | #include "Ray.h" 7 | #include "Scene.h" 8 | #include "Perlin.h" 9 | 10 | class Phong : public Material 11 | { 12 | public: 13 | Phong(const Vector3 & diffuse, const Vector3 &specular, const Vector3 &ambient); 14 | Phong(shared_ptr kd, shared_ptr ks, const Vector3 &ambient); 15 | Phong(shared_ptr kd, const Vector3 &ambient = Vector3(0.f)); 16 | virtual ~Phong(); 17 | 18 | void setPhong(float f) {m_phong = f;} 19 | void setRefraction(float indice) {m_refr = indice;} 20 | void setIndirectLighting(bool value) {m_indirect = value;} 21 | 22 | virtual void preCalc() {} 23 | 24 | virtual Vector3 shade(const Ray& ray, const HitInfo& hit, 25 | const Scene& scene) const; 26 | virtual void shadePhoton(const Ray &ray, const HitInfo &hit, const Scene &scene, Vector3 const &power, Photon_map *map) const; 27 | 28 | void setTransparency(float tp) { m_tp = tp; } 29 | 30 | void setKa(const Vector3& ka) { m_ka = ka; } 31 | void setKs(const Vector3& ks) { m_ks = ks; } 32 | const Vector3& getKs() { return m_ks; } 33 | void setKd(const Vector3& kd) { m_kd = kd; } 34 | void setBm(float bm) { m_bm = bm; } 35 | void setGlossy(bool is_glossy) { m_is_glossy = true; } 36 | bool isGlossy() { return m_is_glossy; } 37 | void setBumpNoisy(float height, int turbulence = 1) { m_is_bump_noisy = true; m_bump_noise_height = height; m_bump_noise_turbulence = turbulence; } 38 | bool isBumpNoisy() { return m_is_bump_noisy; } 39 | void setIsBumpNoisy(bool is_noisy) { m_is_bump_noisy = is_noisy; } 40 | 41 | virtual bool hasBump() const {return m_texture_bump;} 42 | 43 | void setKaTexture(shared_ptr ka_texture) { m_texture_ka = ka_texture; } 44 | void setKsTexture(shared_ptr ks_texture) { m_texture_ks = ks_texture; } 45 | void setKdTexture(shared_ptr kd_texture) { m_texture_kd = kd_texture; } 46 | void setBumpTexture(shared_ptr bump_texture) { m_texture_bump = bump_texture; } 47 | 48 | protected: 49 | HitInfo bumpHit(HitInfo const &rhit) const; 50 | 51 | protected: 52 | shared_ptr m_texture_ka; 53 | shared_ptr m_texture_ks; 54 | shared_ptr m_texture_kd; 55 | shared_ptr m_texture_bump; 56 | 57 | Vector3 m_ka; 58 | Vector3 m_ks; // old: m_sp 59 | Vector3 m_kd; // old: m_dp 60 | float m_bm; 61 | 62 | float m_tp; 63 | float m_phong; 64 | float m_refr; 65 | 66 | bool m_indirect; 67 | bool m_is_glossy; 68 | 69 | bool m_is_bump_noisy; 70 | float m_bump_noise_height; 71 | int m_bump_noise_turbulence; 72 | }; 73 | 74 | #endif // CSE168_LAMBERT_H_INCLUDED 75 | -------------------------------------------------------------------------------- /sources/PhotonMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | /* This is the photon 10 | * The power is not compressed so the 11 | * size is 28 bytes 12 | */ 13 | //********************** 14 | typedef struct Photon { 15 | //********************** 16 | float pos[3]; // photon position 17 | short plane; // splitting plane for kd-tree 18 | unsigned char theta, phi; // incoming direction 19 | float power[3]; // photon power (uncompressed) 20 | } Photon; 21 | 22 | 23 | /* This structure is used only to locate the 24 | * nearest photons 25 | */ 26 | //****************************** 27 | typedef struct NearestPhotons { 28 | //****************************** 29 | int max; 30 | int found; 31 | int got_heap; 32 | float pos[3]; 33 | float *dist2; 34 | const Photon **index; 35 | } NearestPhotons; 36 | 37 | 38 | /* This is the Photon_map class 39 | */ 40 | //***************** 41 | class Photon_map { 42 | //***************** 43 | public: 44 | Photon_map( int max_phot ); 45 | ~Photon_map(); 46 | 47 | void store( 48 | const float power[3], // photon power 49 | const float pos[3], // photon position 50 | const float dir[3] ); // photon direction 51 | 52 | void scale_photon_power( 53 | const float scale ); // 1/(number of emitted photons) 54 | 55 | void balance(void); // balance the kd-tree (before use!) 56 | 57 | void irradiance_estimate( 58 | float irrad[3], // returned irradiance 59 | const float pos[3], // surface position 60 | const float normal[3], // surface normal at pos 61 | const float max_dist, // max distance to look for photons 62 | const int nphotons ) const; // number of photons to use 63 | 64 | void locate_photons( 65 | NearestPhotons *const np, // np is used to locate the photons 66 | const int index ) const; // call with index = 1 67 | 68 | void photon_dir( 69 | float *dir, // direction of photon (returned) 70 | const Photon *p ) const; // the photon 71 | 72 | void renderGL() const; 73 | 74 | bool isCaustics() const {return m_caustics;} 75 | void setCaustics(bool c) {m_caustics = c;} 76 | 77 | private: 78 | 79 | void balance_segment( 80 | Photon **pbal, 81 | Photon **porg, 82 | const int index, 83 | const int start, 84 | const int end ); 85 | 86 | void median_split( 87 | Photon **p, 88 | const int start, 89 | const int end, 90 | const int median, 91 | const int axis ); 92 | 93 | Photon *photons; 94 | 95 | int stored_photons; 96 | int half_stored_photons; 97 | int max_photons; 98 | int prev_scale; 99 | 100 | float costheta[256]; 101 | float sintheta[256]; 102 | float cosphi[256]; 103 | float sinphi[256]; 104 | 105 | float bbox_min[3]; // use bbox_min; 106 | float bbox_max[3]; // use bbox_max; 107 | bool m_caustics; 108 | }; 109 | 110 | // #include 111 | // #include 112 | // #include 113 | // #include 114 | // #include "Vector3.h" 115 | // #include "Miro.h" 116 | 117 | // struct Photon 118 | // { 119 | // Vector3 position; 120 | // Vector3 power; 121 | // Vector3 dir; 122 | // }; 123 | 124 | // class Photon_map 125 | // { 126 | // public: 127 | // Photon_map() : m_root(0) {} 128 | 129 | // void addPhoton(Photon const &ph) {m_photons.push_back(new Photon(ph));} 130 | 131 | // void build(); 132 | 133 | // void kNearest(Vector3 const &v, int k, std::vector &result) const; 134 | 135 | // void renderGL() const; 136 | 137 | // ~Photon_map() {delete m_root;} 138 | 139 | // private: 140 | // struct PhotonNode 141 | // { 142 | // Photon *photon; 143 | // PhotonNode *left; 144 | 145 | // PhotonNode() : photon(0), left(0) {} 146 | 147 | // ~PhotonNode() 148 | // { 149 | // delete photon; 150 | // if (left) 151 | // { 152 | // delete[] (PhotonNode*)((uintptr_t) left & ~3); 153 | // } 154 | // } 155 | // }; 156 | 157 | // typedef std::priority_queue, boost::function > Heap; 158 | // void tryInsertPhoton(Vector3 const &p, int k, Photon *photon, Heap &result) const; 159 | // void recKNearest(PhotonNode *node, Vector3 const &v, int k, Heap &result) const; 160 | // void recursiveBuild(PhotonNode *node, int axis, std::vector::iterator start, std::vector::iterator end); 161 | 162 | // std::vector m_photons; 163 | // PhotonNode *m_root; 164 | // }; 165 | -------------------------------------------------------------------------------- /sources/PointLight.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_POINTLIGHT_H_INCLUDED 2 | #define CSE168_POINTLIGHT_H_INCLUDED 3 | 4 | #include 5 | #include "Vector3.h" 6 | 7 | class PointLight 8 | { 9 | public: 10 | PointLight(): m_sphere(0), m_samples(1) {} 11 | void setPosition(const Vector3& v) {m_position = v;} 12 | void setColor(const Vector3& v) {m_color = v;} 13 | void setWattage(float f) {m_wattage = f;} 14 | void setBlur(float sphere, int samples) {m_sphere = sphere; m_samples = samples;} 15 | 16 | float wattage() const {return m_wattage;} 17 | const Vector3 & color() const {return m_color;} 18 | const Vector3& position() const {return m_position;} 19 | float sphere() const {return m_sphere;} 20 | int samples() const {return m_samples;} 21 | 22 | void preCalc() {} // use this if you need to 23 | 24 | protected: 25 | Vector3 m_position; 26 | Vector3 m_color; 27 | float m_wattage; 28 | float m_sphere; 29 | int m_samples; 30 | }; 31 | 32 | typedef std::vector Lights; 33 | 34 | #endif // CSE168_POINTLIGHT_H_INCLUDED 35 | -------------------------------------------------------------------------------- /sources/Ray.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_RAY_H_INCLUDED 2 | #define CSE168_RAY_H_INCLUDED 3 | 4 | #include "Vector3.h" 5 | #include 6 | 7 | #define MAX_RAY_ITER 6 8 | 9 | class Ray 10 | { 11 | public: 12 | Vector3 o, //!< Origin of ray 13 | d; //!< Direction of ray 14 | int iter; 15 | std::vector *refractionStack; 16 | int refractionIndex; 17 | bool seen_specular; // Only for photon map generation 18 | 19 | Ray() : o(), d(Vector3(0.0f,0.0f,1.0f)), iter(0), seen_specular(false) 20 | { 21 | // empty 22 | } 23 | 24 | Ray(const Vector3& o, const Vector3& d, int i = 0) : o(o), d(d), iter(i) 25 | { 26 | // empty 27 | } 28 | }; 29 | 30 | 31 | //! Contains information about a ray hit with a surface. 32 | /*! 33 | HitInfos are used by object intersection routines. They are useful in 34 | order to return more than just the hit distance. 35 | */ 36 | class HitInfo 37 | { 38 | public: 39 | float t; //!< The hit distance 40 | Vector3 P; //!< The hit point 41 | Vector3 N; //!< Shading normal vector 42 | const Material* material; //!< Material of the intersected object 43 | Vector3 tangent; 44 | float u; 45 | float v; 46 | 47 | //! Default constructor. 48 | explicit HitInfo(float t = 0.0f, 49 | const Vector3& P = Vector3(), 50 | const Vector3& N = Vector3(0.0f, 1.0f, 0.0f)) : 51 | t(t), P(P), N(N), material (0), u(0), v(0) 52 | { 53 | // empty 54 | } 55 | }; 56 | 57 | #endif // CSE168_RAY_H_INCLUDED 58 | -------------------------------------------------------------------------------- /sources/SSE.cpp: -------------------------------------------------------------------------------- 1 | #include "SSE.h" 2 | 3 | #ifdef _WIN32 4 | #include 5 | #define cpuid __cpuid 6 | #else 7 | void cpuid(int CPUInfo[4],int InfoType){ 8 | __asm__ __volatile__ ( 9 | "cpuid": 10 | "=a" (CPUInfo[0]), 11 | "=b" (CPUInfo[1]), 12 | "=c" (CPUInfo[2]), 13 | "=d" (CPUInfo[3]) : 14 | "a" (InfoType) 15 | ); 16 | } 17 | #endif 18 | 19 | SSE sse_info; 20 | 21 | SSE::SSE() : m_hasSSE(false) 22 | { 23 | int info[4]; 24 | cpuid(info, 0); 25 | int nIds = info[0]; 26 | if (nIds >= 1) 27 | { 28 | cpuid(info, 1); 29 | // This tests for SSE 4.1. We will probably only use SSE2, if so, change that later. 30 | m_hasSSE = (info[2] & ((int)1 << 19)) != 0; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sources/SSE.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "Miro.h" 6 | 7 | #if defined(WIN32) && defined(SSE) 8 | #define WSSEALIGN __declspec( align( 16 ) ) 9 | #else 10 | #define WSSEALIGN 11 | #endif 12 | 13 | inline int nCpus() 14 | { 15 | static int n = -1; 16 | if (n == -1) { 17 | #ifdef WIN32 18 | SYSTEM_INFO sysinfo; 19 | GetSystemInfo( &sysinfo ); 20 | 21 | n = sysinfo.dwNumberOfProcessors; 22 | #else 23 | n = sysconf( _SC_NPROCESSORS_ONLN ); 24 | #endif 25 | } 26 | return n; 27 | } 28 | 29 | #if defined(__GNUC__) && defined(SSE) 30 | #define GSSEALIGN __attribute__((aligned(16))) 31 | #else 32 | #define GSSEALIGN 33 | #endif 34 | 35 | inline float _mm_extract_ps1(__m128 a, int i) 36 | { 37 | union 38 | { 39 | __m128 m; 40 | float f[4]; 41 | } u; 42 | u.m = a; 43 | return u.f[i]; 44 | } 45 | 46 | inline int _mm_extract_int(__m128 a, int i) 47 | { 48 | union 49 | { 50 | __m128 m; 51 | int f[4]; 52 | } u; 53 | u.m = a; 54 | return u.f[i]; 55 | } 56 | 57 | class SSE 58 | { 59 | public: 60 | SSE(); 61 | 62 | bool hasSSE() const { return m_hasSSE; } 63 | 64 | private: 65 | bool m_hasSSE; 66 | }; 67 | 68 | extern SSE sse_info; 69 | -------------------------------------------------------------------------------- /sources/SSEObject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SSE.h" 4 | 5 | struct WSSEALIGN SSEVector4 6 | { 7 | __m128 x, y, z; 8 | } GSSEALIGN; 9 | 10 | class WSSEALIGN SSEObject 11 | { 12 | public: 13 | inline void *operator new[](size_t sz) { return _mm_malloc(sz, 16); } 14 | inline void *operator new(size_t sz) { return _mm_malloc(sz, 16); } 15 | inline void operator delete[](void *p) { if (p) _mm_free(p); } 16 | inline void operator delete(void *p) { if (p) _mm_free(p); } 17 | } GSSEALIGN; 18 | -------------------------------------------------------------------------------- /sources/Scene.cpp: -------------------------------------------------------------------------------- 1 | #include "boost/threadpool.hpp" 2 | #include "Miro.h" 3 | #include "Scene.h" 4 | #include "Camera.h" 5 | #include "Image.h" 6 | #include "Console.h" 7 | 8 | #include 9 | 10 | Scene * g_scene = 0; 11 | 12 | Scene::Scene() : m_bgColor(0.f), m_global_photons(400000), m_caustics_photons(400000), m_samples(1), m_cutoffs(0), m_focus_length(-1.f), m_lens(0.25f) {} 13 | 14 | void 15 | Scene::openGL(Camera *cam) 16 | { 17 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 18 | 19 | cam->drawGL(); 20 | 21 | // draw objects 22 | for (size_t i = 0; i < m_objects.size(); ++i) 23 | m_objects[i]->renderGL(); 24 | for (size_t i = 0; i < m_lights.size(); ++i) 25 | { 26 | glColor3f(1, 1, 0.2); 27 | glPushMatrix(); 28 | glTranslatef(m_lights[i]->position().x, m_lights[i]->position().y, m_lights[i]->position().z); 29 | glutSolidSphere(1, 10, 10); 30 | glPopMatrix(); 31 | glColor3f(1, 1, 1); 32 | } 33 | g_caustics_map->renderGL(); 34 | 35 | glutSwapBuffers(); 36 | } 37 | 38 | void Scene::sampleMap(Photon_map *map, int n_photons, float total_wattage) 39 | { 40 | Lights::iterator lit; 41 | std::vector refr_stack; 42 | int total = 0; 43 | for (lit = m_lights.begin(); lit != m_lights.end(); ++lit) 44 | { 45 | int photons = (*lit)->wattage() * n_photons / total_wattage; 46 | float power = (*lit)->wattage() / photons; 47 | for (int i = 0; i < photons; ++i) 48 | { 49 | if (total % 1000 == 0) 50 | { 51 | printf("%.2f%%\r", 100 * total / ((float) n_photons)); 52 | fflush(stdout); 53 | } 54 | total++; 55 | Ray ray; 56 | do 57 | { 58 | ray.d.x = 2*randone(g_rng) - 1; 59 | ray.d.y = 2*randone(g_rng) - 1; 60 | ray.d.z = 2*randone(g_rng) - 1; 61 | } while (ray.d.x*ray.d.x + ray.d.y*ray.d.y + ray.d.z*ray.d.z > 1); 62 | ray.d.normalize(); 63 | ray.o = (*lit)->position(); 64 | refr_stack.clear(); 65 | refr_stack.push_back(1.f); 66 | ray.refractionStack = &refr_stack; 67 | ray.refractionIndex = 0; 68 | HitInfo h; 69 | if (trace(h, ray)) 70 | h.material->shadePhoton(ray, h, *this, power * (*lit)->color(), map); 71 | } 72 | } 73 | printf("100.00%\n"); 74 | map->balance(); 75 | } 76 | 77 | void 78 | Scene::preCalc() 79 | { 80 | Objects::iterator it; 81 | for (it = m_objects.begin(); it != m_objects.end(); it++) 82 | { 83 | Object* pObject = *it; 84 | pObject->preCalc(); 85 | } 86 | Lights::iterator lit; 87 | float total_wattage = 0.f; 88 | for (lit = m_lights.begin(); lit != m_lights.end(); lit++) 89 | { 90 | PointLight* pLight = *lit; 91 | pLight->preCalc(); 92 | total_wattage += pLight->wattage(); 93 | } 94 | 95 | m_bvh.build(&m_objects); 96 | 97 | delete g_global_illum_map; 98 | g_global_illum_map = new Photon_map(m_global_photons); 99 | delete g_caustics_map; 100 | g_caustics_map = new Photon_map(m_caustics_photons); 101 | g_caustics_map->setCaustics(true); 102 | 103 | printf("Caustics map:\n"); 104 | sampleMap(g_caustics_map, m_caustics_photons, total_wattage); 105 | printf("Global illum map:\n"); 106 | sampleMap(g_global_illum_map, m_global_photons, total_wattage); 107 | } 108 | 109 | std::vector Scene::traceLine(Camera const *cam, Image const *img, int j) const 110 | { 111 | std::vector results(img->width()); 112 | Ray ray; 113 | HitInfo hitInfo; 114 | Vector3 shadeResult; 115 | std::vector refr_stack; 116 | std::vector colors(m_samples); 117 | for (int i = 0; i < img->width(); ++i) 118 | { 119 | for (int k = 0; k < m_samples; ++k) 120 | { 121 | ray = cam->eyeRay(i + (m_samples == 1 ? 0.5f : randone(g_rng) - 0.5f), j + (m_samples == 1 ? 0.5f : randone(g_rng) - 0.5f), img->width(), img->height()); 122 | if (m_focus_length >= 0.f) // if depth of field enabled 123 | { 124 | Vector3 focal_point = ray.o + m_focus_length * ray.d; 125 | Vector3 view_dir = cam->viewDir(); 126 | Vector3 d_vec(randone(g_rng) - 0.5f, randone(g_rng) - 0.5f, randone(g_rng) - 0.5f); 127 | d_vec.normalize(); 128 | d_vec = view_dir.cross(d_vec); 129 | 130 | ray.o += d_vec * randone(g_rng) * m_lens; 131 | ray.d = focal_point - ray.o; 132 | ray.d.normalize(); 133 | } 134 | 135 | refr_stack.clear(); 136 | refr_stack.push_back(1.f); 137 | ray.refractionStack = &refr_stack; 138 | ray.refractionIndex = 0; 139 | if (!results[i]) 140 | results[i] = new Vector3(); 141 | if (trace(hitInfo, ray)) 142 | { 143 | colors[k] = hitInfo.material->shade(ray, hitInfo, *this); 144 | } 145 | else 146 | { 147 | colors[k] = bgColor(); 148 | } 149 | *results[i] += colors[k]; 150 | } 151 | if (m_cutoffs > 0) 152 | { 153 | std::vector biggest(m_cutoffs, -1); 154 | for (int c = 0; c < m_cutoffs; ++c) 155 | { 156 | if (biggest[0] == -1 || colors[c].length2() > colors[biggest[0]].length2()) 157 | { 158 | biggest[0] = c; 159 | for (int k = 1; k < m_cutoffs; ++k) 160 | { 161 | if (biggest[k] == -1 || colors[biggest[k - 1]].length2() > colors[biggest[k]].length2()) 162 | std::swap(biggest[k - 1], biggest[k]); 163 | else 164 | break; 165 | } 166 | } 167 | } 168 | for (int k = 0; k < m_cutoffs; ++k) 169 | *results[i] -= colors[biggest[k]]; 170 | } 171 | if (results[i]) 172 | *results[i] /= m_samples - m_cutoffs; 173 | } 174 | return results; 175 | } 176 | 177 | void 178 | Scene::raytraceImage(Camera *cam, Image *img) 179 | { 180 | boost::timer::auto_cpu_timer t; 181 | boost::threadpool::pool threadpool(7);//nCpus() * 2); 182 | std::vector > * > tasks; 183 | std::vector > * > lines; 184 | 185 | // loop over all pixels in the image 186 | { 187 | for (int j = 0; j < img->height(); ++j) 188 | { 189 | tasks.push_back(new boost::packaged_task >(boost::bind(&Scene::traceLine, this, cam, img, j))); 190 | lines.push_back(new boost::unique_future >(tasks.back()->get_future())); 191 | boost::threadpool::schedule(threadpool, boost::bind(&boost::packaged_task >::operator(), tasks.back())); 192 | } 193 | printf("Rendering Progress: %.3f%%\r", 0.f); 194 | for (int j = 0; j < img->height(); ++j) 195 | { 196 | for (int i = 0; i < img->width(); ++i) 197 | { 198 | if (lines[j]->get()[i]) 199 | { 200 | img->setPixel(i, j, *lines[j]->get()[i]); 201 | delete lines[j]->get()[i]; 202 | } 203 | } 204 | img->drawScanline(j); 205 | if (j + 1 == img->height() || !lines[j + 1]->has_value()) 206 | glFinish(); 207 | printf("Rendering Progress: %.3f%%\r", j/float(img->height())*100.0f); 208 | fflush(stdout); 209 | } 210 | } 211 | printf("Rendering Progress: 100.000%\n"); 212 | debug("done Raytracing!\n"); 213 | } 214 | 215 | bool 216 | Scene::trace(HitInfo& minHit, const Ray& ray, float tMin, float tMax) const 217 | { 218 | return m_bvh.intersect(minHit, ray, tMin, tMax); 219 | } 220 | 221 | void 222 | Scene::setDepthOfField(float focus_length, float lens) 223 | { 224 | m_focus_length = focus_length; 225 | m_lens = lens; 226 | } 227 | -------------------------------------------------------------------------------- /sources/Scene.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_SCENE_H_INCLUDED 2 | #define CSE168_SCENE_H_INCLUDED 3 | 4 | #include "Miro.h" 5 | #include "Object.h" 6 | #include "PointLight.h" 7 | #include "BVH.h" 8 | 9 | class Camera; 10 | class Image; 11 | 12 | class Scene 13 | { 14 | public: 15 | Scene(); 16 | 17 | void addObject(Object* pObj) {m_objects.push_back(pObj);} 18 | const Objects* objects() const {return &m_objects;} 19 | 20 | void addLight(PointLight* pObj) {m_lights.push_back(pObj);} 21 | const Lights* lights() const {return &m_lights;} 22 | 23 | void preCalc(); 24 | void openGL(Camera *cam); 25 | 26 | inline void setBGColor(float x, float y, float z); 27 | inline void setBGColor(const Vector3& color); 28 | 29 | inline const Vector3 & bgColor() const {return m_bgColor;} 30 | 31 | inline void setSamples(int n) { m_samples = n; } 32 | inline int samples() const { return m_samples; } 33 | 34 | inline void setAntiAliasing(int a, int b) { m_samples = a * b; } 35 | 36 | inline void setCutoffs(int n) { m_cutoffs = n; } 37 | inline int cutoffs() const { return m_cutoffs; } 38 | 39 | void setDepthOfField(float focus_length, float lens = 1.0f); 40 | 41 | void raytraceImage(Camera *cam, Image *img); 42 | 43 | bool trace(HitInfo& minHit, const Ray& ray, 44 | float tMin = 0.0f, float tMax = MIRO_TMAX) const; 45 | 46 | protected: 47 | std::vector traceLine(Camera const *cam, Image const *img, int j) const; 48 | void sampleMap(Photon_map *map, int n_photons, float total_wattage); 49 | 50 | Vector3 m_bgColor; 51 | 52 | Objects m_objects; 53 | BVH m_bvh; 54 | Lights m_lights; 55 | int m_global_photons; 56 | int m_caustics_photons; 57 | 58 | int m_samples; 59 | int m_cutoffs; 60 | 61 | float m_focus_length; 62 | float m_lens; 63 | }; 64 | 65 | extern Scene * g_scene; 66 | 67 | inline void Scene::setBGColor(float x, float y, float z) 68 | { 69 | Vector3 v(x, y, z); 70 | setBGColor(v); 71 | } 72 | 73 | inline void Scene::setBGColor(const Vector3& vd) 74 | { 75 | m_bgColor.set(vd); 76 | } 77 | 78 | #endif // CSE168_SCENE_H_INCLUDED 79 | -------------------------------------------------------------------------------- /sources/Sphere.cpp: -------------------------------------------------------------------------------- 1 | #include "Sphere.h" 2 | #include "Ray.h" 3 | #include "Console.h" 4 | 5 | Sphere::Sphere() 6 | { 7 | } 8 | 9 | Sphere::~Sphere() 10 | { 11 | } 12 | 13 | void 14 | Sphere::renderGL() 15 | { 16 | glColor3f(1, 1, 1); 17 | glPushMatrix(); 18 | glTranslatef(m_center.x, m_center.y, m_center.z); 19 | glutWireSphere(m_radius, 20, 20); 20 | glPopMatrix(); 21 | } 22 | 23 | bool Sphere::doIntersect(IntersectObjects const &objs, HitInfo& result, const Ray& ray, 24 | float tMin, float tMax) 25 | { 26 | bool hit = false; 27 | for (int i = 0; i < objs.plain.size(); ++i) 28 | { 29 | Sphere *s = (Sphere *)objs.plain[i]; 30 | const Vector3 toO = ray.o - s->m_center; 31 | 32 | const float a = ray.d.length2(); 33 | const float b = dot(2*ray.d, toO); 34 | const float c = toO.length2() - s->m_radius*s->m_radius; 35 | 36 | const float discrim = b*b-4.0f*a*c; 37 | 38 | if (discrim < 0) 39 | { 40 | continue; // quadratic equation would yield imaginary numbers 41 | } 42 | 43 | const float sqrt_discrim = sqrt(discrim); 44 | 45 | // solve the quadratic equation 46 | const float t[2] = {(-b-sqrt_discrim)/(2.0f*a), (-b+sqrt_discrim)/(2.0f*a)}; 47 | 48 | // since we know that discrim >= 0, t[0] < t{1] 49 | // return the t closest to us that is within range 50 | if ((t[0] > tMin) && (t[0] < tMax)) 51 | { 52 | result.t = t[0]; 53 | } 54 | else if((t[1] > tMin) && (t[1] < tMax)) 55 | { 56 | result.t = t[1]; 57 | } 58 | else 59 | { 60 | // neither of the solutions are in the required range 61 | continue; 62 | } 63 | 64 | hit = true; 65 | 66 | tMax = result.t; 67 | result.P = ray.o + result.t*ray.d; 68 | result.N = (result.P-s->m_center); 69 | result.N.normalize(); 70 | result.material = s->m_material; 71 | } 72 | return hit; 73 | } 74 | 75 | Vector3 Sphere::maxVector() const 76 | { 77 | return m_center + Vector3(m_radius); 78 | } 79 | 80 | Vector3 Sphere::minVector() const 81 | { 82 | return m_center - Vector3(m_radius); 83 | } 84 | -------------------------------------------------------------------------------- /sources/Sphere.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_SPHERE_H_INCLUDED 2 | #define CSE168_SPHERE_H_INCLUDED 3 | 4 | #include "Vector3.h" 5 | #include "Object.h" 6 | #include "IntersectObjects.h" 7 | 8 | class Sphere : public Object 9 | { 10 | public: 11 | Sphere(); 12 | virtual ~Sphere(); 13 | 14 | void setCenter(const Vector3& v) {m_center = v;} 15 | void setRadius(const float f) {m_radius = f;} 16 | 17 | const Vector3& center() const {return m_center;} 18 | float radius() const {return m_radius;} 19 | 20 | virtual void renderGL(); 21 | static bool doIntersect(IntersectObjects const &objects, HitInfo& result, const Ray& ray, 22 | float tMin = 0.0f, float tMax = MIRO_TMAX); 23 | 24 | virtual ObjType type() const { return SPHERE; } 25 | virtual void *ptr() { return this; } 26 | 27 | virtual Vector3 minVector() const; 28 | virtual Vector3 maxVector() const; 29 | 30 | protected: 31 | Vector3 m_center; 32 | float m_radius; 33 | }; 34 | 35 | #endif // CSE168_SPHERE_H_INCLUDED 36 | -------------------------------------------------------------------------------- /sources/Texture.cpp: -------------------------------------------------------------------------------- 1 | #include "Texture.h" 2 | #include 3 | using namespace boost::gil; 4 | using boost::algorithm::clamp; 5 | 6 | Texture::Texture(const std::string& texture_path) 7 | { 8 | m_img_loaded = false; 9 | setTexturePath(texture_path); 10 | loadTexture(); 11 | } 12 | 13 | 14 | Texture::~Texture(void) 15 | { 16 | } 17 | 18 | void 19 | Texture::loadTexture() 20 | { 21 | if (m_texture_path.empty()) 22 | { 23 | m_img_loaded = false; 24 | return; 25 | } 26 | try 27 | { 28 | boost::gil::jpeg_read_image(m_texture_path, m_img); 29 | printf("[Texture] GIL: ('%s') texture map loaded\n", m_texture_path.c_str()); 30 | m_img_loaded = true; 31 | } 32 | catch (std::exception &e) 33 | { 34 | printf("[Texture] GIL: ('%s') %s\n", m_texture_path.c_str(), e.what()); 35 | m_img_loaded = false; 36 | } 37 | } 38 | 39 | void 40 | Texture::setTexturePath(const std::string& texture_path) 41 | { 42 | m_texture_path = texture_path; 43 | m_texture_path.erase(std::remove(m_texture_path.begin(), m_texture_path.end(), '\n'), m_texture_path.end()); 44 | m_texture_path.erase(std::remove(m_texture_path.begin(), m_texture_path.end(), '\r'), m_texture_path.end()); 45 | loadTexture(); 46 | } 47 | 48 | Vector3 49 | Texture::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const 50 | { 51 | if (m_img_loaded) 52 | { 53 | boost::gil::rgb8_pixel_t pixel = m_img._view((int) (fmodf(std::abs(hit.u), 1) * m_img.width()), (int) (fmodf(std::abs(hit.v), 1) * m_img.height())); 54 | return Vector3(pixel[0] / 255.f, pixel[1] / 255.f, pixel[2] / 255.f); 55 | } 56 | else 57 | return m_color; 58 | } 59 | 60 | Vector3 61 | Texture::getPixel(float u, float v, int x, int y) const 62 | { 63 | if (m_img_loaded) 64 | { 65 | int posx = fmodf(std::abs(u), 1) * m_img.width() + x; 66 | posx = (posx + m_img.width()) % m_img.width(); 67 | int posy = fmodf(std::abs(v), 1) * m_img.height() + y; 68 | posy = (posy + m_img.height()) %m_img.height(); 69 | boost::gil::rgb8_pixel_t pixel = m_img._view(posx, posy); 70 | return Vector3(pixel[0] / 255.f, pixel[1] / 255.f, pixel[2] / 255.f); 71 | } 72 | else 73 | { 74 | return m_color; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /sources/Texture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "material.h" 3 | #include "Ray.h" 4 | #include 5 | #include 6 | 7 | class Texture : 8 | public Material 9 | { 10 | public: 11 | Texture() { m_img_loaded = false; }; // A texture without a path is a basic material (one color) 12 | Texture(const std::string& texture_path); 13 | virtual ~Texture(void); 14 | 15 | virtual void preCalc() {} 16 | 17 | virtual Vector3 shade(const Ray& ray, const HitInfo& hit, 18 | const Scene& scene) const; 19 | void setTexturePath(const std::string& texture_path); 20 | const std::string& getTexturePath() { return m_texture_path; } 21 | Vector3 getPixel(float u, float v, int x, int y) const; 22 | 23 | protected: 24 | void loadTexture(); 25 | 26 | private: 27 | std::string m_texture_path; 28 | boost::gil::rgb8_image_t m_img; 29 | bool m_img_loaded; 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /sources/Triangle.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_TRIANGLE_H_INCLUDED 2 | #define CSE168_TRIANGLE_H_INCLUDED 3 | 4 | #include "SSE.h" 5 | #include "Object.h" 6 | #include "SSEObject.h" 7 | 8 | /* 9 | The Triangle class stores a pointer to a mesh and an index into its 10 | triangle array. The mesh stores all data needed by this Triangle. 11 | */ 12 | class Triangle : public Object 13 | { 14 | public: 15 | Triangle(TriangleMesh * m = 0, unsigned int i = 0); 16 | virtual ~Triangle(); 17 | 18 | void setIndex(unsigned int i) {m_index = i;} 19 | void setMesh(TriangleMesh* m) {m_mesh = m;} 20 | 21 | virtual void renderGL(); 22 | 23 | static bool doIntersect(IntersectObjects const &objects, HitInfo &, const Ray &, float, float); 24 | 25 | virtual ObjType type() const { return TRIANGLE; } 26 | virtual void *ptr() { return this; } 27 | static void * preProcess( std::vector &objects ); 28 | 29 | virtual Vector3 minVector() const; 30 | virtual Vector3 maxVector() const; 31 | 32 | protected: 33 | TriangleMesh* m_mesh; 34 | unsigned int m_index; 35 | }; 36 | 37 | #endif // CSE168_TRIANGLE_H_INCLUDED 38 | -------------------------------------------------------------------------------- /sources/TriangleMesh.cpp: -------------------------------------------------------------------------------- 1 | #include "TriangleMesh.h" 2 | #include "Triangle.h" 3 | #include "Scene.h" 4 | 5 | 6 | TriangleMesh::TriangleMesh() : 7 | m_normals(0), 8 | m_vertices(0), 9 | m_texCoords(0), 10 | m_normalIndices(0), 11 | m_vertexIndices(0), 12 | m_texCoordIndices(0) 13 | { 14 | 15 | } 16 | 17 | TriangleMesh::~TriangleMesh() 18 | { 19 | delete [] m_normals; 20 | delete [] m_vertices; 21 | delete [] m_texCoords; 22 | delete [] m_normalIndices; 23 | delete [] m_vertexIndices; 24 | delete [] m_texCoordIndices; 25 | } 26 | -------------------------------------------------------------------------------- /sources/TriangleMesh.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_TRIANGLE_MESH_H_INCLUDED 2 | #define CSE168_TRIANGLE_MESH_H_INCLUDED 3 | 4 | #include 5 | #include 6 | #include "Matrix4x4.h" 7 | #include "Material.h" 8 | 9 | class TriangleMesh 10 | { 11 | public: 12 | TriangleMesh(); 13 | ~TriangleMesh(); 14 | 15 | // load from an OBJ file 16 | bool load(char* file, const Matrix4x4& ctm = Matrix4x4()); 17 | 18 | // for single triangles 19 | void createSingleTriangle(); 20 | inline void setV1(const Vector3& v) {m_vertices[0] = v;} 21 | inline void setV2(const Vector3& v) {m_vertices[1] = v;} 22 | inline void setV3(const Vector3& v) {m_vertices[2] = v;} 23 | inline void setN1(const Vector3& n) {m_normals[0] = n;} 24 | inline void setN2(const Vector3& n) {m_normals[1] = n;} 25 | inline void setN3(const Vector3& n) {m_normals[2] = n;} 26 | 27 | struct TupleI3 28 | { 29 | unsigned int x, y, z; 30 | }; 31 | 32 | struct VectorR2 33 | { 34 | float x, y; 35 | 36 | VectorR2() {} 37 | VectorR2(float x, float y) : x(x), y(y) {} 38 | 39 | VectorR2 operator+(VectorR2 const &v) const {return VectorR2(x + v.x, y + v.y);} 40 | VectorR2 operator-(VectorR2 const &v) const {return VectorR2(x - v.x, y - v.y);} 41 | VectorR2 operator*(float f) const {return VectorR2(x * f, y * f);} 42 | }; 43 | 44 | Vector3* vertices() {return m_vertices;} 45 | Vector3* normals() {return m_normals;} 46 | VectorR2* uvs() {return m_texCoords;} 47 | Vector3* tangents() {return m_tangents;} 48 | TupleI3* tIndices() {return m_vertexIndices;} 49 | TupleI3* vIndices() {return m_vertexIndices;} 50 | TupleI3* nIndices() {return m_normalIndices;} 51 | TupleI3* uvIndices() {return m_texCoordIndices;} 52 | int numTris() {return m_numTris;} 53 | Material* getMaterialForId(int triangle_id); 54 | 55 | protected: 56 | void loadObj(FILE* fp, const Matrix4x4& ctm); 57 | void loadMtl(std::string file_name); 58 | 59 | std::map m_mtls; 60 | std::map > m_mtl_ids; 61 | 62 | Vector3* m_normals; 63 | Vector3* m_vertices; 64 | VectorR2* m_texCoords; 65 | Vector3* m_tangents; 66 | 67 | TupleI3* m_normalIndices; 68 | TupleI3* m_vertexIndices; 69 | TupleI3* m_texCoordIndices; 70 | unsigned int m_numTris; 71 | }; 72 | 73 | 74 | #endif // CSE168_TRIANGLE_MESH_H_INCLUDED 75 | -------------------------------------------------------------------------------- /sources/Vector4.h: -------------------------------------------------------------------------------- 1 | #ifndef CSE168_VECTOR4_H_INCLUDED 2 | #define CSE168_VECTOR4_H_INCLUDED 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef WIN32 9 | #pragma warning(disable:4305) // disable useless warnings 10 | #pragma warning(disable:4244) 11 | #endif 12 | 13 | 14 | class Vector4 15 | { 16 | 17 | public: 18 | float x, y, z, w; // The x & y & z & w coordinates. 19 | 20 | 21 | Vector4() : 22 | x(0), y(0), z(0), w(0) {} 23 | 24 | Vector4(float s) : 25 | x(s), y(s), z(s), w(1) {} 26 | 27 | Vector4(float x, float y, float z, float w) : 28 | x(x), y(y), z(z), w(w) {} 29 | 30 | Vector4(const Vector3& v) : x(v.x), y(v.y), z(v.z), w(1) {} 31 | 32 | 33 | //! Assignment operator. 34 | /*! 35 | Assigns the values from \a a to this Vector4. 36 | */ 37 | const Vector4 & operator=(const Vector4& a) {x = a.x; y = a.y; z = a.z; w = a.w; return *this;} 38 | 39 | //! Assignment operator. 40 | /*! 41 | Sets all components of this Vector4 to \a a. 42 | */ 43 | const Vector4 & operator=(float a) {x = y = z = w = a; return *this;} 44 | //@} 45 | 46 | void set(float a) {x = y = z = w = a;} 47 | void set(float a, float b, float c) {x = a; y = b; z = c;} 48 | void set(float a, float b, float c, float d) {x = a; y = b; z = c; w = d;} 49 | void set(const Vector4 v) {x = v.x; y = v.y; z = v.z; w = v.w;} 50 | 51 | 52 | //! Access operator. 53 | /*! 54 | Returns the ith component of the vector. 55 | \param i The component to return. 56 | \warning i must be either 0, 1, 2 or 3 in order to get expected results. 57 | */ 58 | float & operator[](int i) {return(&x)[i];} 59 | 60 | //! Constant access operator. 61 | /*! 62 | Returns the ith component of a constant vector. 63 | \param i The component to return. 64 | \warning i must be either 0, 1, 2 or 3 in order to get expected results. 65 | */ 66 | const float & operator[](int i) const {return(&x)[i];} 67 | 68 | 69 | 70 | //! Component-wise vector addition operator. 71 | Vector4 operator+(const Vector4& v) const 72 | { 73 | return Vector4(x + v.x, y + v.y, z + v.z, w + v.w); 74 | } 75 | 76 | //! Component-wise vector addition-assignment operator. 77 | const Vector4 & operator+=(const Vector4& v) 78 | { 79 | x += v.x; y += v.y; z += v.z; w += v.w; return *this; 80 | } 81 | 82 | //! Scalar addition-assignment operator. 83 | const Vector4 & operator+=(float a) {x += a; y += a; z += a; w += a; return *this;} 84 | //@} 85 | 86 | 87 | //! Component-wise vector subtraction operator. 88 | Vector4 operator-(const Vector4& v) const 89 | { 90 | return Vector4(x - v.x, y - v.y, z - v.z, w - v.w); 91 | } 92 | 93 | //! Component-wise vector subtraction-assignment operator. 94 | const Vector4 & operator-=(const Vector4& v) 95 | { 96 | x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; 97 | } 98 | 99 | //! Component-wise scalar subtraction assignment operator. 100 | const Vector4 & operator-=(float a) {x -= a; y -= a; z -= a; w -= w; return *this;} 101 | //@} 102 | 103 | 104 | //! Scalar multiplication operator. 105 | Vector4 operator*(float a) const {return Vector4(x * a, y * a, z * a, w * a);} 106 | 107 | //! Component-wise vector multiplication operator. 108 | Vector4 operator*(const Vector4& v) const 109 | { 110 | return Vector4(x * v.x, y * v.y, z * v.z, z * v.z); 111 | } 112 | 113 | //! Scalar multiplication-assignment operator. 114 | const Vector4 & operator*=(float a) {x *= a; y *= a; z *= a; w *= a; return *this;} 115 | 116 | //! Component-wise vector multiplication-assignment operator. 117 | const Vector4 & operator*=(const Vector4& v) 118 | { 119 | x *= v.x; y *= v.y; z *= v.z; z *= v.z; w *= v.w; return *this; 120 | } 121 | 122 | //! Negation operator. 123 | Vector4 operator-() const {return Vector4(-x, -y, -z, -w);} 124 | const Vector4 & negate() {x = -x; y = -y; z = -z; w = -w; return *this;} 125 | //@} 126 | 127 | 128 | //! Scalar division operator. 129 | Vector4 operator/(float a) const 130 | { 131 | float inv = float(1) / a; 132 | return Vector4(x * inv, y * inv, z * inv, w * inv); 133 | } 134 | 135 | //! Component-wise vector division operator. 136 | Vector4 operator/(const Vector4 & v) const 137 | { 138 | return Vector4(x / v.x, y / v.y, z / v.z, w / v.w); 139 | } 140 | 141 | //! Scalar division-assignment operator. 142 | const Vector4 & operator/=(float a) 143 | { 144 | float inv = float(1) / a; 145 | x *= inv; y *= inv; z *= inv; w *= inv; 146 | return *this; 147 | } 148 | 149 | //! Component-wise vector division-assignment operator. 150 | const Vector4 & operator/=(const Vector4 & v) 151 | { 152 | x /= v.x; y /= v.y; z /= v.z; w /= v.w; return *this; 153 | } 154 | 155 | 156 | //! Vector equivalence operator. 157 | /*! 158 | Tests to see if each component of \a v is equal to each component of 159 | this Vector4. 160 | */ 161 | bool operator==(const Vector4 & v) const 162 | { 163 | return(v.x == x && v.y == y && v.z == z && v.w == w); 164 | } 165 | 166 | //! Vector difference operator. 167 | /*! 168 | Tests to see if any component is different between the two Vector4s. 169 | */ 170 | bool operator!=(const Vector4 & v) const 171 | { 172 | return(v.x != x || v.y != y || v.z != z || v.w != w); 173 | } 174 | //@} 175 | 176 | 177 | //! Length2. 178 | /*! 179 | Returns the geometric length2 of the vector. 180 | */ 181 | float length2() const; 182 | 183 | //! Length. 184 | /*! 185 | Returns the geometric length of the vector. 186 | */ 187 | float length() const {return sqrtf(length2());} 188 | 189 | //! Normalizes the vector and return its length. 190 | /*! 191 | Scales each component of the vector in order to get unit 192 | length without changing direction. 193 | 194 | \return The length of the vector prior to normalization. 195 | */ 196 | float unitize() 197 | { 198 | float l = length(); 199 | *this /= l; 200 | return l; 201 | } 202 | 203 | //! Normalize a vector and return a reference to it. 204 | /*! 205 | Scales each component of the vector in order to get unit 206 | length without changing direction. 207 | 208 | \return A reference to the vector. 209 | */ 210 | const Vector4 & normalize() 211 | { 212 | return(*this /= length()); 213 | } 214 | 215 | //! Return a normalized copy of the vector. 216 | Vector4 normalized() const 217 | { 218 | return(*this / length()); 219 | } 220 | }; 221 | 222 | 223 | //! Multiply a scalar by a Vector4. 224 | inline Vector4 225 | operator*(float s, const Vector4 & v) 226 | { 227 | return Vector4(v.x * s, v.y * s, v.z * s, v.w * s); 228 | } 229 | 230 | 231 | //! The dot product of two Vector4. 232 | inline float 233 | dot(const Vector4& a, const Vector4& b) 234 | { 235 | return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; 236 | } 237 | 238 | 239 | inline float 240 | Vector4::length2() const 241 | { 242 | return dot(*this, *this); 243 | } 244 | 245 | 246 | inline std::ostream & 247 | operator<<(std::ostream& out, const Vector4& v) 248 | { 249 | return out << v.x << " " << v.y << " " << v.z << " " << v.w; 250 | } 251 | 252 | #endif // CSE168_VECTOR4_H_INCLUDED 253 | -------------------------------------------------------------------------------- /sources/Worley.h: -------------------------------------------------------------------------------- 1 | /*! 2 | Copyright 1994, 2002 by Steven Worley 3 | This software may be modified and redistributed without restriction 4 | provided this comment header remains intact in the source code. 5 | This code is provided with no warrantee, express or implied, for 6 | any purpose. 7 | 8 | A detailed description and application examples can be found in the 9 | 1996 SIGGRAPH paper "A Cellular Texture Basis Function" and 10 | especially in the 2002 book "Texturing and Modeling, a Procedural 11 | Approach, 3rd edition." There is also extra information on the web 12 | site http://www.worley.com/cellular.html . 13 | 14 | If you do find interesting uses for this tool, and especially if 15 | you enhance it, please drop me an email at steve@worley.com. 16 | */ 17 | #ifndef CSE168_WORLEY_H_INCLUDED 18 | #define CSE168_WORLEY_H_INCLUDED 19 | 20 | #include "Vector3.h" 21 | 22 | //! Worley noise class 23 | /*! 24 | An implementation of the key cellular texturing basis 25 | function. This function is hardwired to return an average F_1 value 26 | of 1.0. It returns the closest feature point distances 27 | F_1, F_2, .. F_n the vector delta to those points, and a 32 bit 28 | seed for each of the feature points. This function is not 29 | difficult to extend to compute alternative information such as 30 | higher order F values, to use the Manhattan distance metric, or 31 | other fun perversions. 32 | 33 | The input sample location. 34 | Smaller values compute faster. < 5, read the book to extend it. 35 | The output values of F_1, F_2, ..F[n] in F[0], F[1], F[n-1] 36 | The output vector difference between the sample point and the n-th 37 | closest feature point. Thus, the feature point's location is the 38 | hit point minus this value. The DERIVATIVE of F is the unit 39 | normalized version of this vector. 40 | The output 32 bit ID number which labels the feature point. This 41 | is useful for domain partitions, especially for coloring flagstone 42 | patterns. 43 | 44 | This implementation is tuned for speed in a way that any order > 5 45 | will likely have discontinuous artifacts in its computation of F5+. 46 | This can be fixed by increasing the internal points-per-cube 47 | density in the source code, at the expense of slower 48 | computation. The book lists the details of this tuning. 49 | */ 50 | class WorleyNoise 51 | { 52 | public: 53 | static float EuclidianDistanceFunc(Vector3 p1, Vector3 p2) 54 | { 55 | return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z); 56 | } 57 | // 1D 58 | static void noise1D(float at, int maxOrder, 59 | float *F, float (*delta), unsigned int *ID); 60 | 61 | // 2D 62 | static void noise2D(float at[2], int maxOrder, 63 | float *F, float (*delta)[2], unsigned int *ID); 64 | 65 | // 3D 66 | static void noise3D(float at[3], int maxOrder, 67 | float *F, float (*delta)[3], unsigned int *ID); 68 | }; 69 | 70 | #endif // CSE168_WORLEY_H_INCLUDED 71 | -------------------------------------------------------------------------------- /sources/assignment1.cpp: -------------------------------------------------------------------------------- 1 | #include "assignment1.h" 2 | #include 3 | #include 4 | #include "Miro.h" 5 | #include "Scene.h" 6 | #include "Camera.h" 7 | #include "Image.h" 8 | #include "Console.h" 9 | 10 | #include "PointLight.h" 11 | #include "TriangleMesh.h" 12 | #include "Triangle.h" 13 | #include "Sphere.h" 14 | #include "Phong.h" 15 | #include "CellularStoneTexture.h" 16 | 17 | void 18 | a1_makeBunnyScene() 19 | { 20 | g_camera = new Camera; 21 | g_scene = new Scene; 22 | g_image = new Image; 23 | 24 | g_image->resize(128, 128); 25 | 26 | // set up the camera 27 | g_scene->setBGColor(Vector3(0.0f, 0.0f, 0.2f)); 28 | g_camera->setEye(Vector3(-2, 3, 5)); 29 | g_camera->setLookAt(Vector3(-.5, 1, 0)); 30 | g_camera->setUp(Vector3(0, 1, 0)); 31 | g_camera->setFOV(45); 32 | 33 | // create and place a point light source 34 | PointLight * light = new PointLight; 35 | light->setPosition(Vector3(-3, 15, 3)); 36 | light->setColor(Vector3(1, 1, 1)); 37 | light->setWattage(500); 38 | g_scene->addLight(light); 39 | 40 | Phong* mat = new Phong(shared_ptr(new CellularStoneTexture(0.25)), 0.2); 41 | Phong* mat2 = new Phong(1, 0, 0.2); 42 | //mat = mat2; 43 | mat->setPhong(10); 44 | TriangleMesh * bunny = new TriangleMesh; 45 | bunny->load("bunny_smooth.obj"); 46 | 47 | // create all the triangles in the bunny mesh and add to the scene 48 | for (int i = 0; i < bunny->numTris(); ++i) 49 | { 50 | Triangle* t = new Triangle; 51 | t->setIndex(i); 52 | t->setMesh(bunny); 53 | t->setMaterial(mat); 54 | g_scene->addObject(t); 55 | } 56 | 57 | // create the floor triangle 58 | TriangleMesh * floor = new TriangleMesh; 59 | floor->createSingleTriangle(); 60 | floor->setV1(Vector3( 0, 0, 10)); 61 | floor->setV2(Vector3( 10, 0, -10)); 62 | floor->setV3(Vector3(-10, 0, -10)); 63 | floor->setN1(Vector3(0, 1, 0)); 64 | floor->setN2(Vector3(0, 1, 0)); 65 | floor->setN3(Vector3(0, 1, 0)); 66 | 67 | Triangle* t = new Triangle; 68 | t->setIndex(0); 69 | t->setMesh(floor); 70 | t->setMaterial(mat2); 71 | g_scene->addObject(t); 72 | 73 | // let objects do pre-calculations if needed 74 | g_scene->preCalc(); 75 | } 76 | 77 | void 78 | a1_makeTeapotScene() 79 | { 80 | g_camera = new Camera; 81 | g_scene = new Scene; 82 | g_image = new Image; 83 | 84 | g_image->resize(128, 128); 85 | 86 | // set up the camera 87 | g_scene->setBGColor(Vector3(0.8f, 0.8f, 1.f)); 88 | g_camera->setEye(Vector3(-2, 3, 5)); 89 | g_camera->setLookAt(Vector3(-.5, 1, 0)); 90 | g_camera->setUp(Vector3(0, 1, 0)); 91 | g_camera->setFOV(45); 92 | 93 | // create and place a point light source 94 | PointLight * light = new PointLight; 95 | light->setPosition(Vector3(10, 15, 10)); 96 | light->setColor(Vector3(1, 1, 1)); 97 | light->setBlur(0.6, 10); 98 | light->setWattage(500); 99 | g_scene->addLight(light); 100 | g_scene->setAntiAliasing(1, 1); 101 | 102 | Phong* mat = new Phong(shared_ptr(new CellularStoneTexture(0.2f)), 0.2); 103 | mat->setKd(0.8); 104 | mat->setKs(0); 105 | mat->setPhong(100); 106 | Phong* mat2 = new Phong(shared_ptr(new CellularStoneTexture(1.f)), Vector3(0.f)); 107 | mat2->setKd(0.8); 108 | mat2->setKs(0.2); 109 | mat2->setPhong(100); 110 | 111 | TriangleMesh * teapot = new TriangleMesh; 112 | teapot->load("teapot.obj"); 113 | 114 | // create all the triangles in the bunny mesh and add to the scene 115 | for (int i = 0; i < teapot->numTris(); ++i) 116 | { 117 | Triangle* t = new Triangle; 118 | t->setIndex(i); 119 | t->setMesh(teapot); 120 | t->setMaterial(mat); 121 | g_scene->addObject(t); 122 | } 123 | 124 | // create the floor triangle 125 | TriangleMesh * floor = new TriangleMesh; 126 | floor->createSingleTriangle(); 127 | floor->setV1(Vector3( 0, 0, 10)); 128 | floor->setV2(Vector3( 10, 0, -10)); 129 | floor->setV3(Vector3(-10, 0, -10)); 130 | floor->setN1(Vector3(0, 1, 0)); 131 | floor->setN2(Vector3(0, 1, 0)); 132 | floor->setN3(Vector3(0, 1, 0)); 133 | 134 | Triangle* t = new Triangle; 135 | t->setIndex(0); 136 | t->setMesh(floor); 137 | t->setMaterial(mat2); 138 | g_scene->addObject(t); 139 | 140 | Phong *transp = new Phong(1, 1, 0.0); 141 | transp->setKd(0.2); 142 | transp->setRefraction(1.3); 143 | transp->setTransparency(0.8); 144 | transp->setPhong(30); 145 | transp->setCastShadow(false); 146 | Sphere * sphere = new Sphere(); 147 | sphere->setCenter(Vector3(-1.0, 1.4, 0)); 148 | sphere->setRadius(0.8); 149 | sphere->setMaterial(transp); 150 | g_scene->addObject(sphere); 151 | 152 | // let objects do pre-calculations if needed 153 | g_scene->preCalc(); 154 | } 155 | 156 | void 157 | a1_makeSphereScene() 158 | { 159 | g_camera = new Camera; 160 | g_scene = new Scene; 161 | g_image = new Image; 162 | 163 | g_image->resize(128, 128); 164 | 165 | // set up the camera 166 | g_scene->setBGColor(Vector3(0.0f, 0.0f, 0.0f)); 167 | g_camera->setEye(Vector3(-2, 3, 5)); 168 | g_camera->setLookAt(Vector3(-.5, 1, 0)); 169 | g_camera->setUp(Vector3(0, 1, 0)); 170 | g_camera->setFOV(45); 171 | 172 | // create and place a point light source 173 | PointLight * light = new PointLight; 174 | light->setPosition(Vector3(-10, 10, 3)); 175 | light->setColor(Vector3(1, 1, 1)); 176 | light->setWattage(500); 177 | g_scene->addLight(light); 178 | g_scene->setBGColor(Vector3(0.8, 0.8, 1)); 179 | 180 | Material* mat = new Phong(Vector3(1.0f), 0, 0); 181 | 182 | TriangleMesh * sphere = new TriangleMesh; 183 | sphere->load("sphere.obj"); 184 | 185 | // create all the triangles in the bunny mesh and add to the scene 186 | for (int i = 0; i < sphere->numTris(); ++i) 187 | { 188 | Triangle* t = new Triangle; 189 | t->setIndex(i); 190 | t->setMesh(sphere); 191 | t->setMaterial(mat); 192 | g_scene->addObject(t); 193 | } 194 | 195 | // let objects do pre-calculations if needed 196 | g_scene->preCalc(); 197 | } 198 | 199 | void 200 | a1_makeTextureScene() 201 | { 202 | g_camera = new Camera; 203 | g_scene = new Scene; 204 | g_image = new Image; 205 | 206 | g_image->resize(800, 800); 207 | 208 | // set up the camera 209 | g_scene->setBGColor(Vector3(0.8f, 0.8f, 1.0f)); 210 | g_camera->setEye(Vector3(-1, 10, 10)); 211 | g_camera->setLookAt(Vector3(0, 0, 0)); 212 | g_camera->setUp(Vector3(0, 1, 0)); 213 | g_camera->setFOV(45); 214 | 215 | // create and place a point light source 216 | PointLight * light = new PointLight; 217 | light->setPosition(Vector3(-6, 12, 3)); 218 | light->setColor(Vector3(1, 1, 1)); 219 | light->setWattage(300); 220 | g_scene->addLight(light); 221 | 222 | Material* mat = new Phong(shared_ptr(new CellularStoneTexture()), 0.1); 223 | 224 | //Material* mat = new CellularStoneTexture(Vector3(.5f, .0f, .2f)); 225 | 226 | // create the floor triangle 227 | TriangleMesh * floor = new TriangleMesh; 228 | floor->createSingleTriangle(); 229 | floor->setV1(Vector3( 0, 0, 10)); 230 | floor->setV2(Vector3( 10, 0, -10)); 231 | floor->setV3(Vector3(-10, 0, -10)); 232 | floor->setN1(Vector3(0, 1, 0)); 233 | floor->setN2(Vector3(0, 1, 0)); 234 | floor->setN3(Vector3(0, 1, 0)); 235 | 236 | Triangle* t = new Triangle; 237 | t->setIndex(0); 238 | t->setMesh(floor); 239 | t->setMaterial(mat); 240 | g_scene->addObject(t); 241 | 242 | Sphere* sphere = new Sphere(); 243 | sphere->setMaterial(mat); 244 | sphere->setCenter(Vector3(0, 0, 0)); 245 | sphere->setRadius(2); 246 | g_scene->addObject(sphere); 247 | 248 | sphere = new Sphere(); 249 | sphere->setMaterial(mat); 250 | sphere->setCenter(Vector3(4, 0, 0)); 251 | sphere->setRadius(2); 252 | g_scene->addObject(sphere); 253 | 254 | // let objects do pre-calculations if needed 255 | g_scene->preCalc(); 256 | } 257 | -------------------------------------------------------------------------------- /sources/assignment1.h: -------------------------------------------------------------------------------- 1 | void a1_makeBunnyScene(); 2 | void a1_makeSphereScene(); 3 | void a1_makeTeapotScene(); 4 | void a1_makeTextureScene(); 5 | -------------------------------------------------------------------------------- /sources/assignment2.h: -------------------------------------------------------------------------------- 1 | void makeSpecialScene(); 2 | void makeBoxScene(); 3 | void makeTeapotScene(); 4 | void makeBunny1Scene(); 5 | void makeBunny20Scene(); 6 | void makeSponzaScene(); 7 | void makeFinalScene(); 8 | void makeDepthScene(); 9 | void makeGlossyScene(); 10 | void makeCornellScene(); 11 | void makeNoiseBumpScene(); 12 | void makeAllInOneScene(); 13 | -------------------------------------------------------------------------------- /sources/boost/threadpool.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Main include. 3 | * 4 | * This is the only file you have to include in order to use the 5 | * complete threadpool library. 6 | * 7 | * Copyright (c) 2005-2007 Philipp Henkel 8 | * 9 | * Use, modification, and distribution are subject to the 10 | * Boost Software License, Version 1.0. (See accompanying file 11 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 | * 13 | * http://threadpool.sourceforge.net 14 | * 15 | */ 16 | 17 | #ifndef THREADPOOL_HPP_INCLUDED 18 | #define THREADPOOL_HPP_INCLUDED 19 | 20 | #include "./threadpool/future.hpp" 21 | #include "./threadpool/pool.hpp" 22 | 23 | #include "./threadpool/pool_adaptors.hpp" 24 | #include "./threadpool/task_adaptors.hpp" 25 | 26 | 27 | #endif // THREADPOOL_HPP_INCLUDED 28 | 29 | -------------------------------------------------------------------------------- /sources/boost/threadpool/detail/future.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief TODO. 3 | * 4 | * TODO. 5 | * 6 | * Copyright (c) 2005-2007 Philipp Henkel 7 | * 8 | * Use, modification, and distribution are subject to the 9 | * Boost Software License, Version 1.0. (See accompanying file 10 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | * 12 | * http://threadpool.sourceforge.net 13 | * 14 | */ 15 | 16 | 17 | #ifndef THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED 18 | #define THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED 19 | 20 | 21 | #include "locking_ptr.hpp" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace boost { namespace threadpool { namespace detail 33 | { 34 | 35 | template 36 | class future_impl 37 | { 38 | public: 39 | typedef Result const & result_type; //!< Indicates the functor's result type. 40 | 41 | typedef Result future_result_type; //!< Indicates the future's result type. 42 | typedef future_impl future_type; 43 | 44 | private: 45 | volatile bool m_ready; 46 | volatile future_result_type m_result; 47 | 48 | mutable mutex m_monitor; 49 | mutable condition m_condition_ready; 50 | 51 | volatile bool m_is_cancelled; 52 | volatile bool m_executing; 53 | 54 | public: 55 | 56 | 57 | public: 58 | 59 | future_impl() 60 | : m_ready(false) 61 | , m_is_cancelled(false) 62 | { 63 | } 64 | 65 | bool ready() const volatile 66 | { 67 | return m_ready; 68 | } 69 | 70 | void wait() const volatile 71 | { 72 | const future_type* self = const_cast(this); 73 | mutex::scoped_lock lock(self->m_monitor); 74 | 75 | while(!m_ready) 76 | { 77 | self->m_condition_ready.wait(lock); 78 | } 79 | } 80 | 81 | 82 | bool timed_wait(boost::xtime const & timestamp) const 83 | { 84 | const future_type* self = const_cast(this); 85 | mutex::scoped_lock lock(self->m_monitor); 86 | 87 | while(!m_ready) 88 | { 89 | if(!self->m_condition_ready.timed_wait(lock, timestamp)) return false; 90 | } 91 | 92 | return true; 93 | } 94 | 95 | 96 | result_type operator()() const volatile 97 | { 98 | wait(); 99 | /* 100 | if( throw_exception_ != 0 ) 101 | { 102 | throw_exception_( this ); 103 | } 104 | */ 105 | 106 | return *(const_cast(&m_result)); 107 | } 108 | 109 | 110 | void set_value(future_result_type const & r) volatile 111 | { 112 | locking_ptr lockedThis(*this, m_monitor); 113 | if(!m_ready && !m_is_cancelled) 114 | { 115 | lockedThis->m_result = r; 116 | lockedThis->m_ready = true; 117 | lockedThis->m_condition_ready.notify_all(); 118 | } 119 | } 120 | /* 121 | template void set_exception() // throw() 122 | { 123 | m_impl->template set_exception(); 124 | } 125 | 126 | template void set_exception( char const * what ) // throw() 127 | { 128 | m_impl->template set_exception( what ); 129 | } 130 | */ 131 | 132 | 133 | bool cancel() volatile 134 | { 135 | if(!m_ready || m_executing) 136 | { 137 | m_is_cancelled = true; 138 | return true; 139 | } 140 | else 141 | { 142 | return false; 143 | } 144 | } 145 | 146 | 147 | bool is_cancelled() const volatile 148 | { 149 | return m_is_cancelled; 150 | } 151 | 152 | 153 | void set_execution_status(bool executing) volatile 154 | { 155 | m_executing = executing; 156 | } 157 | }; 158 | 159 | 160 | template< 161 | template class Future, 162 | typename Function 163 | > 164 | class future_impl_task_func 165 | { 166 | 167 | public: 168 | typedef void result_type; //!< Indicates the functor's result type. 169 | 170 | typedef Function function_type; //!< Indicates the function's type. 171 | typedef typename result_of::type future_result_type; //!< Indicates the future's result type. 172 | typedef Future future_type; //!< Indicates the future's type. 173 | 174 | // The task is required to be a nullary function. 175 | BOOST_STATIC_ASSERT(function_traits::arity == 0); 176 | 177 | // The task function's result type is required not to be void. 178 | BOOST_STATIC_ASSERT(!is_void::value); 179 | 180 | private: 181 | function_type m_function; 182 | shared_ptr m_future; 183 | 184 | public: 185 | future_impl_task_func(function_type const & function, shared_ptr const & future) 186 | : m_function(function) 187 | , m_future(future) 188 | { 189 | } 190 | 191 | void operator()() 192 | { 193 | if(m_function) 194 | { 195 | m_future->set_execution_status(true); 196 | if(!m_future->is_cancelled()) 197 | { 198 | // TODO future exeception handling 199 | m_future->set_value(m_function()); 200 | } 201 | m_future->set_execution_status(false); // TODO consider exceptions 202 | } 203 | } 204 | 205 | }; 206 | 207 | 208 | 209 | 210 | 211 | } } } // namespace boost::threadpool::detail 212 | 213 | #endif // THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED 214 | 215 | 216 | -------------------------------------------------------------------------------- /sources/boost/threadpool/detail/locking_ptr.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief The locking_ptr is smart pointer with a scoped locking mechanism. 3 | * 4 | * The class is a wrapper for a volatile pointer. It enables synchronized access to the 5 | * internal pointer by locking the passed mutex. 6 | * locking_ptr is based on Andrei Alexandrescu's LockingPtr. For more information 7 | * see article "volatile - Multithreaded Programmer's Best Friend" by A. Alexandrescu. 8 | * 9 | * 10 | * Copyright (c) 2005-2007 Philipp Henkel 11 | * 12 | * Use, modification, and distribution are subject to the 13 | * Boost Software License, Version 1.0. (See accompanying file 14 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 15 | * 16 | * http://threadpool.sourceforge.net 17 | * 18 | */ 19 | 20 | 21 | #ifndef THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED 22 | #define THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED 23 | 24 | #include 25 | #include 26 | 27 | 28 | namespace boost { namespace threadpool { namespace detail 29 | { 30 | 31 | /*! \brief Smart pointer with a scoped locking mechanism. 32 | * 33 | * This class is a wrapper for a volatile pointer. It enables synchronized access to the 34 | * internal pointer by locking the passed mutex. 35 | */ 36 | template 37 | class locking_ptr 38 | : private noncopyable 39 | { 40 | T* m_obj; //!< The instance pointer. 41 | Mutex & m_mutex; //!< Mutex is used for scoped locking. 42 | 43 | public: 44 | /// Constructor. 45 | locking_ptr(volatile T& obj, const volatile Mutex& mtx) 46 | : m_obj(const_cast(&obj)) 47 | , m_mutex(*const_cast(&mtx)) 48 | { 49 | // Lock mutex 50 | m_mutex.lock(); 51 | } 52 | 53 | 54 | /// Destructor. 55 | ~locking_ptr() 56 | { 57 | // Unlock mutex 58 | m_mutex.unlock(); 59 | } 60 | 61 | 62 | /*! Returns a reference to the stored instance. 63 | * \return The instance's reference. 64 | */ 65 | T& operator*() const 66 | { 67 | return *m_obj; 68 | } 69 | 70 | 71 | /*! Returns a pointer to the stored instance. 72 | * \return The instance's pointer. 73 | */ 74 | T* operator->() const 75 | { 76 | return m_obj; 77 | } 78 | }; 79 | 80 | 81 | } } } // namespace boost::threadpool::detail 82 | 83 | 84 | #endif // THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED 85 | 86 | -------------------------------------------------------------------------------- /sources/boost/threadpool/detail/scope_guard.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief TODO. 3 | * 4 | * TODO. 5 | * 6 | * Copyright (c) 2005-2007 Philipp Henkel 7 | * 8 | * Use, modification, and distribution are subject to the 9 | * Boost Software License, Version 1.0. (See accompanying file 10 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | * 12 | * http://threadpool.sourceforge.net 13 | * 14 | */ 15 | 16 | 17 | #ifndef THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED 18 | #define THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED 19 | 20 | 21 | 22 | #include 23 | 24 | 25 | namespace boost { namespace threadpool { namespace detail 26 | { 27 | 28 | // TODO documentation 29 | class scope_guard 30 | : private boost::noncopyable 31 | { 32 | function0 const m_function; 33 | bool m_is_active; 34 | 35 | public: 36 | scope_guard(function0 const & call_on_exit) 37 | : m_function(call_on_exit) 38 | , m_is_active(true) 39 | { 40 | } 41 | 42 | ~scope_guard() 43 | { 44 | if(m_is_active && m_function) 45 | { 46 | m_function(); 47 | } 48 | } 49 | 50 | void disable() 51 | { 52 | m_is_active = false; 53 | } 54 | }; 55 | 56 | 57 | 58 | 59 | 60 | 61 | } } } // namespace boost::threadpool::detail 62 | 63 | #endif // THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED 64 | 65 | 66 | -------------------------------------------------------------------------------- /sources/boost/threadpool/detail/worker_thread.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Thread pool worker. 3 | * 4 | * The worker thread instance is attached to a pool 5 | * and executes tasks of this pool. 6 | * 7 | * Copyright (c) 2005-2007 Philipp Henkel 8 | * 9 | * Use, modification, and distribution are subject to the 10 | * Boost Software License, Version 1.0. (See accompanying file 11 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 | * 13 | * http://threadpool.sourceforge.net 14 | * 15 | */ 16 | 17 | #ifndef THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED 18 | #define THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED 19 | 20 | 21 | #include "scope_guard.hpp" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | namespace boost { namespace threadpool { namespace detail 31 | { 32 | 33 | /*! \brief Thread pool worker. 34 | * 35 | * A worker_thread represents a thread of execution. The worker is attached to a 36 | * thread pool and processes tasks of that pool. The lifetime of the worker and its 37 | * internal boost::thread is managed automatically. 38 | * 39 | * This class is a helper class and cannot be constructed or accessed directly. 40 | * 41 | * \see pool_core 42 | */ 43 | template 44 | class worker_thread 45 | : public enable_shared_from_this< worker_thread > 46 | , private noncopyable 47 | { 48 | public: 49 | typedef Pool pool_type; //!< Indicates the pool's type. 50 | 51 | private: 52 | shared_ptr m_pool; //!< Pointer to the pool which created the worker. 53 | shared_ptr m_thread; //!< Pointer to the thread which executes the run loop. 54 | 55 | 56 | /*! Constructs a new worker. 57 | * \param pool Pointer to it's parent pool. 58 | * \see function create_and_attach 59 | */ 60 | worker_thread(shared_ptr const & pool) 61 | : m_pool(pool) 62 | { 63 | assert(pool); 64 | } 65 | 66 | 67 | /*! Notifies that an exception occurred in the run loop. 68 | */ 69 | void died_unexpectedly() 70 | { 71 | m_pool->worker_died_unexpectedly(this->shared_from_this()); 72 | } 73 | 74 | 75 | public: 76 | /*! Executes pool's tasks sequentially. 77 | */ 78 | void run() 79 | { 80 | scope_guard notify_exception(bind(&worker_thread::died_unexpectedly, this)); 81 | 82 | while(m_pool->execute_task()) {} 83 | 84 | notify_exception.disable(); 85 | m_pool->worker_destructed(this->shared_from_this()); 86 | } 87 | 88 | 89 | /*! Joins the worker's thread. 90 | */ 91 | void join() 92 | { 93 | m_thread->join(); 94 | } 95 | 96 | 97 | /*! Constructs a new worker thread and attaches it to the pool. 98 | * \param pool Pointer to the pool. 99 | */ 100 | static void create_and_attach(shared_ptr const & pool) 101 | { 102 | shared_ptr worker(new worker_thread(pool)); 103 | if(worker) 104 | { 105 | worker->m_thread.reset(new boost::thread(bind(&worker_thread::run, worker))); 106 | } 107 | } 108 | 109 | }; 110 | 111 | 112 | } } } // namespace boost::threadpool::detail 113 | 114 | #endif // THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED 115 | 116 | -------------------------------------------------------------------------------- /sources/boost/threadpool/future.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief TODO. 3 | * 4 | * TODO. 5 | * 6 | * Copyright (c) 2005-2007 Philipp Henkel 7 | * 8 | * Use, modification, and distribution are subject to the 9 | * Boost Software License, Version 1.0. (See accompanying file 10 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | * 12 | * http://threadpool.sourceforge.net 13 | * 14 | */ 15 | 16 | #ifndef THREADPOOL_FUTURE_HPP_INCLUDED 17 | #define THREADPOOL_FUTURE_HPP_INCLUDED 18 | 19 | 20 | 21 | #include "./detail/future.hpp" 22 | #include 23 | 24 | //#include "pool.hpp" 25 | //#include 26 | 27 | //#include 28 | 29 | 30 | namespace boost { namespace threadpool 31 | { 32 | 33 | /*! \brief Experimental. Do not use in production code. TODO. 34 | * 35 | * TODO Future 36 | * 37 | * \see TODO 38 | * 39 | */ 40 | 41 | 42 | template 43 | class future 44 | { 45 | private: 46 | shared_ptr > m_impl; 47 | 48 | public: 49 | typedef Result const & result_type; //!< Indicates the functor's result type. 50 | typedef Result future_result_type; //!< Indicates the future's result type. 51 | 52 | 53 | public: 54 | 55 | future() 56 | : m_impl(new detail::future_impl()) // TODO remove this 57 | { 58 | } 59 | 60 | // only for internal usage 61 | future(shared_ptr > const & impl) 62 | : m_impl(impl) 63 | { 64 | } 65 | 66 | bool ready() const 67 | { 68 | return m_impl->ready(); 69 | } 70 | 71 | void wait() const 72 | { 73 | m_impl->wait(); 74 | } 75 | 76 | bool timed_wait(boost::xtime const & timestamp) const 77 | { 78 | return m_impl->timed_wait(timestamp); 79 | } 80 | 81 | result_type operator()() // throw( thread::cancelation_exception, ... ) 82 | { 83 | return (*m_impl)(); 84 | } 85 | 86 | result_type get() // throw( thread::cancelation_exception, ... ) 87 | { 88 | return (*m_impl)(); 89 | } 90 | 91 | bool cancel() 92 | { 93 | return m_impl->cancel(); 94 | } 95 | 96 | bool is_cancelled() const 97 | { 98 | return m_impl->is_cancelled(); 99 | } 100 | }; 101 | 102 | 103 | 104 | 105 | 106 | template 107 | typename disable_if < 108 | is_void< typename result_of< Function() >::type >, 109 | future< typename result_of< Function() >::type > 110 | >::type 111 | schedule(Pool& pool, const Function& task) 112 | { 113 | typedef typename result_of< Function() >::type future_result_type; 114 | 115 | // create future impl and future 116 | shared_ptr > impl(new detail::future_impl); 117 | future res(impl); 118 | 119 | // schedule future impl 120 | pool.schedule(detail::future_impl_task_func(task, impl)); 121 | 122 | // return future 123 | return res; 124 | 125 | /* 126 | TODO 127 | if(pool->schedule(bind(&Future::run, future))) 128 | { 129 | return future; 130 | } 131 | else 132 | { 133 | // construct empty future 134 | return error_future; 135 | } 136 | */ 137 | } 138 | 139 | 140 | 141 | } } // namespace boost::threadpool 142 | 143 | #endif // THREADPOOL_FUTURE_HPP_INCLUDED 144 | 145 | -------------------------------------------------------------------------------- /sources/boost/threadpool/pool.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Thread pool core. 3 | * 4 | * This file contains the threadpool's core class: pool. 5 | * 6 | * Thread pools are a mechanism for asynchronous and parallel processing 7 | * within the same process. The pool class provides a convenient way 8 | * for dispatching asynchronous tasks as functions objects. The scheduling 9 | * of these tasks can be easily controlled by using customized schedulers. 10 | * 11 | * Copyright (c) 2005-2007 Philipp Henkel 12 | * 13 | * Use, modification, and distribution are subject to the 14 | * Boost Software License, Version 1.0. (See accompanying file 15 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 16 | * 17 | * http://threadpool.sourceforge.net 18 | * 19 | */ 20 | 21 | 22 | #ifndef THREADPOOL_POOL_HPP_INCLUDED 23 | #define THREADPOOL_POOL_HPP_INCLUDED 24 | 25 | #include 26 | 27 | #include "./detail/pool_core.hpp" 28 | 29 | #include "task_adaptors.hpp" 30 | 31 | #include "./detail/locking_ptr.hpp" 32 | 33 | #include "scheduling_policies.hpp" 34 | #include "size_policies.hpp" 35 | #include "shutdown_policies.hpp" 36 | 37 | 38 | 39 | /// The namespace threadpool contains a thread pool and related utility classes. 40 | namespace boost { namespace threadpool 41 | { 42 | 43 | 44 | 45 | /*! \brief Thread pool. 46 | * 47 | * Thread pools are a mechanism for asynchronous and parallel processing 48 | * within the same process. The pool class provides a convenient way 49 | * for dispatching asynchronous tasks as functions objects. The scheduling 50 | * of these tasks can be easily controlled by using customized schedulers. 51 | * A task must not throw an exception. 52 | * 53 | * A pool is DefaultConstructible, CopyConstructible and Assignable. 54 | * It has reference semantics; all copies of the same pool are equivalent and interchangeable. 55 | * All operations on a pool except assignment are strongly thread safe or sequentially consistent; 56 | * that is, the behavior of concurrent calls is as if the calls have been issued sequentially in an unspecified order. 57 | * 58 | * \param Task A function object which implements the operator 'void operator() (void) const'. The operator () is called by the pool to execute the task. Exceptions are ignored. 59 | * \param SchedulingPolicy A task container which determines how tasks are scheduled. It is guaranteed that this container is accessed only by one thread at a time. The scheduler shall not throw exceptions. 60 | * 61 | * \remarks The pool class is thread-safe. 62 | * 63 | * \see Tasks: task_func, prio_task_func 64 | * \see Scheduling policies: fifo_scheduler, lifo_scheduler, prio_scheduler 65 | */ 66 | template < 67 | typename Task = task_func, 68 | template class SchedulingPolicy = fifo_scheduler, 69 | template class SizePolicy = static_size, 70 | template class SizePolicyController = resize_controller, 71 | template class ShutdownPolicy = wait_for_all_tasks 72 | > 73 | class thread_pool 74 | { 75 | typedef detail::pool_core pool_core_type; 80 | shared_ptr m_core; // pimpl idiom 81 | shared_ptr m_shutdown_controller; // If the last pool holding a pointer to the core is deleted the controller shuts the pool down. 82 | 83 | public: // Type definitions 84 | typedef Task task_type; //!< Indicates the task's type. 85 | typedef SchedulingPolicy scheduler_type; //!< Indicates the scheduler's type. 86 | /* typedef thread_pool pool_type; //!< Indicates the thread pool's type. 90 | */ 91 | typedef SizePolicy size_policy_type; 92 | typedef SizePolicyController size_controller_type; 93 | 94 | 95 | public: 96 | /*! Constructor. 97 | * \param initial_threads The pool is immediately resized to set the specified number of threads. The pool's actual number threads depends on the SizePolicy. 98 | */ 99 | thread_pool(size_t initial_threads = 0) 100 | : m_core(new pool_core_type) 101 | , m_shutdown_controller(static_cast(0), bind(&pool_core_type::shutdown, m_core)) 102 | { 103 | size_policy_type::init(*m_core, initial_threads); 104 | } 105 | 106 | 107 | /*! Gets the size controller which manages the number of threads in the pool. 108 | * \return The size controller. 109 | * \see SizePolicy 110 | */ 111 | size_controller_type size_controller() 112 | { 113 | return m_core->size_controller(); 114 | } 115 | 116 | 117 | /*! Gets the number of threads in the pool. 118 | * \return The number of threads. 119 | */ 120 | size_t size() const 121 | { 122 | return m_core->size(); 123 | } 124 | 125 | 126 | /*! Schedules a task for asynchronous execution. The task will be executed once only. 127 | * \param task The task function object. It should not throw execeptions. 128 | * \return true, if the task could be scheduled and false otherwise. 129 | */ 130 | bool schedule(task_type const & task) 131 | { 132 | return m_core->schedule(task); 133 | } 134 | 135 | 136 | /*! Returns the number of tasks which are currently executed. 137 | * \return The number of active tasks. 138 | */ 139 | size_t active() const 140 | { 141 | return m_core->active(); 142 | } 143 | 144 | 145 | /*! Returns the number of tasks which are ready for execution. 146 | * \return The number of pending tasks. 147 | */ 148 | size_t pending() const 149 | { 150 | return m_core->pending(); 151 | } 152 | 153 | 154 | /*! Removes all pending tasks from the pool's scheduler. 155 | */ 156 | void clear() 157 | { 158 | m_core->clear(); 159 | } 160 | 161 | 162 | /*! Indicates that there are no tasks pending. 163 | * \return true if there are no tasks ready for execution. 164 | * \remarks This function is more efficient that the check 'pending() == 0'. 165 | */ 166 | bool empty() const 167 | { 168 | return m_core->empty(); 169 | } 170 | 171 | 172 | /*! The current thread of execution is blocked until the sum of all active 173 | * and pending tasks is equal or less than a given threshold. 174 | * \param task_threshold The maximum number of tasks in pool and scheduler. 175 | */ 176 | void wait(size_t task_threshold = 0) const 177 | { 178 | m_core->wait(task_threshold); 179 | } 180 | 181 | 182 | /*! The current thread of execution is blocked until the timestamp is met 183 | * or the sum of all active and pending tasks is equal or less 184 | * than a given threshold. 185 | * \param timestamp The time when function returns at the latest. 186 | * \param task_threshold The maximum number of tasks in pool and scheduler. 187 | * \return true if the task sum is equal or less than the threshold, false otherwise. 188 | */ 189 | bool wait(xtime const & timestamp, size_t task_threshold = 0) const 190 | { 191 | return m_core->wait(timestamp, task_threshold); 192 | } 193 | }; 194 | 195 | 196 | 197 | /*! \brief Fifo pool. 198 | * 199 | * The pool's tasks are fifo scheduled task_func functors. 200 | * 201 | */ 202 | typedef thread_pool fifo_pool; 203 | 204 | 205 | /*! \brief Lifo pool. 206 | * 207 | * The pool's tasks are lifo scheduled task_func functors. 208 | * 209 | */ 210 | typedef thread_pool lifo_pool; 211 | 212 | 213 | /*! \brief Pool for prioritized task. 214 | * 215 | * The pool's tasks are prioritized prio_task_func functors. 216 | * 217 | */ 218 | typedef thread_pool prio_pool; 219 | 220 | 221 | /*! \brief A standard pool. 222 | * 223 | * The pool's tasks are fifo scheduled task_func functors. 224 | * 225 | */ 226 | typedef fifo_pool pool; 227 | 228 | 229 | 230 | } } // namespace boost::threadpool 231 | 232 | #endif // THREADPOOL_POOL_HPP_INCLUDED 233 | -------------------------------------------------------------------------------- /sources/boost/threadpool/pool_adaptors.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Pool adaptors. 3 | * 4 | * This file contains an easy-to-use adaptor similar to a smart 5 | * pointer for the pool class. 6 | * 7 | * Copyright (c) 2005-2007 Philipp Henkel 8 | * 9 | * Use, modification, and distribution are subject to the 10 | * Boost Software License, Version 1.0. (See accompanying file 11 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 | * 13 | * http://threadpool.sourceforge.net 14 | * 15 | */ 16 | 17 | 18 | #ifndef THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED 19 | #define THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED 20 | 21 | #include 22 | 23 | 24 | namespace boost { namespace threadpool 25 | { 26 | 27 | 28 | // TODO convenience scheduling function 29 | /*! Schedules a Runnable for asynchronous execution. A Runnable is an arbitrary class with a run() 30 | * member function. This a convenience shorthand for pool->schedule(bind(&Runnable::run, task_object)). 31 | * \param 32 | * \param obj The Runnable object. The member function run() will be exectued and should not throw execeptions. 33 | * \return true, if the task could be scheduled and false otherwise. 34 | */ 35 | template 36 | bool schedule(Pool& pool, shared_ptr const & obj) 37 | { 38 | return pool->schedule(bind(&Runnable::run, obj)); 39 | } 40 | 41 | /*! Schedules a task for asynchronous execution. The task will be executed once only. 42 | * \param task The task function object. 43 | */ 44 | template 45 | typename enable_if < 46 | is_void< typename result_of< typename Pool::task_type() >::type >, 47 | bool 48 | >::type 49 | schedule(Pool& pool, typename Pool::task_type const & task) 50 | { 51 | return pool.schedule(task); 52 | } 53 | 54 | 55 | template 56 | typename enable_if < 57 | is_void< typename result_of< typename Pool::task_type() >::type >, 58 | bool 59 | >::type 60 | schedule(shared_ptr const pool, typename Pool::task_type const & task) 61 | { 62 | return pool->schedule(task); 63 | } 64 | 65 | 66 | } } // namespace boost::threadpool 67 | 68 | #endif // THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED 69 | 70 | 71 | -------------------------------------------------------------------------------- /sources/boost/threadpool/scheduling_policies.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Task scheduling policies. 3 | * 4 | * This file contains some fundamental scheduling policies for the pool class. 5 | * A scheduling policy is realized by a task container which controls the access to 6 | * the tasks. Fundamentally the container determines the order the tasks are processed 7 | * by the thread pool. 8 | * The task containers need not to be thread-safe because they are used by the pool 9 | * in thread-safe way. 10 | * 11 | * Copyright (c) 2005-2007 Philipp Henkel 12 | * 13 | * Use, modification, and distribution are subject to the 14 | * Boost Software License, Version 1.0. (See accompanying file 15 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 16 | * 17 | * http://threadpool.sourceforge.net 18 | * 19 | */ 20 | 21 | 22 | #ifndef THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED 23 | #define THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED 24 | 25 | 26 | #include 27 | #include 28 | 29 | #include "task_adaptors.hpp" 30 | 31 | namespace boost { namespace threadpool 32 | { 33 | 34 | /*! \brief SchedulingPolicy which implements FIFO ordering. 35 | * 36 | * This container implements a FIFO scheduling policy. 37 | * The first task to be added to the scheduler will be the first to be removed. 38 | * The processing proceeds sequentially in the same order. 39 | * FIFO stands for "first in, first out". 40 | * 41 | * \param Task A function object which implements the operator()(void). 42 | * 43 | */ 44 | template 45 | class fifo_scheduler 46 | { 47 | public: 48 | typedef Task task_type; //!< Indicates the scheduler's task type. 49 | 50 | protected: 51 | std::deque m_container; //!< Internal task container. 52 | 53 | 54 | public: 55 | /*! Adds a new task to the scheduler. 56 | * \param task The task object. 57 | * \return true, if the task could be scheduled and false otherwise. 58 | */ 59 | bool push(task_type const & task) 60 | { 61 | m_container.push_back(task); 62 | return true; 63 | } 64 | 65 | /*! Removes the task which should be executed next. 66 | */ 67 | void pop() 68 | { 69 | m_container.pop_front(); 70 | } 71 | 72 | /*! Gets the task which should be executed next. 73 | * \return The task object to be executed. 74 | */ 75 | task_type const & top() const 76 | { 77 | return m_container.front(); 78 | } 79 | 80 | /*! Gets the current number of tasks in the scheduler. 81 | * \return The number of tasks. 82 | * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty. 83 | */ 84 | size_t size() const 85 | { 86 | return m_container.size(); 87 | } 88 | 89 | /*! Checks if the scheduler is empty. 90 | * \return true if the scheduler contains no tasks, false otherwise. 91 | * \remarks Is more efficient than size() == 0. 92 | */ 93 | bool empty() const 94 | { 95 | return m_container.empty(); 96 | } 97 | 98 | /*! Removes all tasks from the scheduler. 99 | */ 100 | void clear() 101 | { 102 | m_container.clear(); 103 | } 104 | }; 105 | 106 | 107 | 108 | /*! \brief SchedulingPolicy which implements LIFO ordering. 109 | * 110 | * This container implements a LIFO scheduling policy. 111 | * The last task to be added to the scheduler will be the first to be removed. 112 | * LIFO stands for "last in, first out". 113 | * 114 | * \param Task A function object which implements the operator()(void). 115 | * 116 | */ 117 | template 118 | class lifo_scheduler 119 | { 120 | public: 121 | typedef Task task_type; //!< Indicates the scheduler's task type. 122 | 123 | protected: 124 | std::deque m_container; //!< Internal task container. 125 | 126 | public: 127 | /*! Adds a new task to the scheduler. 128 | * \param task The task object. 129 | * \return true, if the task could be scheduled and false otherwise. 130 | */ 131 | bool push(task_type const & task) 132 | { 133 | m_container.push_front(task); 134 | return true; 135 | } 136 | 137 | /*! Removes the task which should be executed next. 138 | */ 139 | void pop() 140 | { 141 | m_container.pop_front(); 142 | } 143 | 144 | /*! Gets the task which should be executed next. 145 | * \return The task object to be executed. 146 | */ 147 | task_type const & top() const 148 | { 149 | return m_container.front(); 150 | } 151 | 152 | /*! Gets the current number of tasks in the scheduler. 153 | * \return The number of tasks. 154 | * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty. 155 | */ 156 | size_t size() const 157 | { 158 | return m_container.size(); 159 | } 160 | 161 | /*! Checks if the scheduler is empty. 162 | * \return true if the scheduler contains no tasks, false otherwise. 163 | * \remarks Is more efficient than size() == 0. 164 | */ 165 | bool empty() const 166 | { 167 | return m_container.empty(); 168 | } 169 | 170 | /*! Removes all tasks from the scheduler. 171 | */ 172 | void clear() 173 | { 174 | m_container.clear(); 175 | } 176 | 177 | }; 178 | 179 | 180 | 181 | /*! \brief SchedulingPolicy which implements prioritized ordering. 182 | * 183 | * This container implements a scheduling policy based on task priorities. 184 | * The task with highest priority will be the first to be removed. 185 | * It must be possible to compare two tasks using operator<. 186 | * 187 | * \param Task A function object which implements the operator() and operator<. operator< must be a partial ordering. 188 | * 189 | * \see prio_thread_func 190 | * 191 | */ 192 | template 193 | class prio_scheduler 194 | { 195 | public: 196 | typedef Task task_type; //!< Indicates the scheduler's task type. 197 | 198 | protected: 199 | std::priority_queue m_container; //!< Internal task container. 200 | 201 | 202 | public: 203 | /*! Adds a new task to the scheduler. 204 | * \param task The task object. 205 | * \return true, if the task could be scheduled and false otherwise. 206 | */ 207 | bool push(task_type const & task) 208 | { 209 | m_container.push(task); 210 | return true; 211 | } 212 | 213 | /*! Removes the task which should be executed next. 214 | */ 215 | void pop() 216 | { 217 | m_container.pop(); 218 | } 219 | 220 | /*! Gets the task which should be executed next. 221 | * \return The task object to be executed. 222 | */ 223 | task_type const & top() const 224 | { 225 | return m_container.top(); 226 | } 227 | 228 | /*! Gets the current number of tasks in the scheduler. 229 | * \return The number of tasks. 230 | * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty. 231 | */ 232 | size_t size() const 233 | { 234 | return m_container.size(); 235 | } 236 | 237 | /*! Checks if the scheduler is empty. 238 | * \return true if the scheduler contains no tasks, false otherwise. 239 | * \remarks Is more efficient than size() == 0. 240 | */ 241 | bool empty() const 242 | { 243 | return m_container.empty(); 244 | } 245 | 246 | /*! Removes all tasks from the scheduler. 247 | */ 248 | void clear() 249 | { 250 | while(!m_container.empty()) 251 | { 252 | m_container.pop(); 253 | } 254 | } 255 | }; 256 | 257 | 258 | } } // namespace boost::threadpool 259 | 260 | 261 | #endif // THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED 262 | 263 | -------------------------------------------------------------------------------- /sources/boost/threadpool/shutdown_policies.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Shutdown policies. 3 | * 4 | * This file contains shutdown policies for thread_pool. 5 | * A shutdown policy controls the pool's behavior from the time 6 | * when the pool is not referenced any longer. 7 | * 8 | * Copyright (c) 2005-2007 Philipp Henkel 9 | * 10 | * Use, modification, and distribution are subject to the 11 | * Boost Software License, Version 1.0. (See accompanying file 12 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 13 | * 14 | * http://threadpool.sourceforge.net 15 | * 16 | */ 17 | 18 | 19 | #ifndef THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED 20 | #define THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED 21 | 22 | 23 | 24 | /// The namespace threadpool contains a thread pool and related utility classes. 25 | namespace boost { namespace threadpool 26 | { 27 | 28 | 29 | /*! \brief ShutdownPolicy which waits for the completion of all tasks 30 | * and the worker termination afterwards. 31 | * 32 | * \param Pool The pool's core type. 33 | */ 34 | template 35 | class wait_for_all_tasks 36 | { 37 | public: 38 | static void shutdown(Pool& pool) 39 | { 40 | pool.wait(); 41 | pool.terminate_all_workers(true); 42 | } 43 | }; 44 | 45 | 46 | /*! \brief ShutdownPolicy which waits for the completion of all active tasks 47 | * and the worker termination afterwards. 48 | * 49 | * \param Pool The pool's core type. 50 | */ 51 | template 52 | class wait_for_active_tasks 53 | { 54 | public: 55 | static void shutdown(Pool& pool) 56 | { 57 | pool.clear(); 58 | pool.wait(); 59 | pool.terminate_all_workers(true); 60 | } 61 | }; 62 | 63 | 64 | /*! \brief ShutdownPolicy which does not wait for any tasks or worker termination. 65 | * 66 | * This policy does not wait for any tasks. Nevertheless all active tasks will be processed completely. 67 | * 68 | * \param Pool The pool's core type. 69 | */ 70 | template 71 | class immediately 72 | { 73 | public: 74 | static void shutdown(Pool& pool) 75 | { 76 | pool.clear(); 77 | pool.terminate_all_workers(false); 78 | } 79 | }; 80 | 81 | } } // namespace boost::threadpool 82 | 83 | #endif // THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED 84 | -------------------------------------------------------------------------------- /sources/boost/threadpool/size_policies.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Size policies. 3 | * 4 | * This file contains size policies for thread_pool. A size 5 | * policy controls the number of worker threads in the pool. 6 | * 7 | * Copyright (c) 2005-2007 Philipp Henkel 8 | * 9 | * Use, modification, and distribution are subject to the 10 | * Boost Software License, Version 1.0. (See accompanying file 11 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 | * 13 | * http://threadpool.sourceforge.net 14 | * 15 | */ 16 | 17 | 18 | #ifndef THREADPOOL_SIZE_POLICIES_HPP_INCLUDED 19 | #define THREADPOOL_SIZE_POLICIES_HPP_INCLUDED 20 | 21 | 22 | 23 | /// The namespace threadpool contains a thread pool and related utility classes. 24 | namespace boost { namespace threadpool 25 | { 26 | 27 | /*! \brief SizePolicyController which provides no functionality. 28 | * 29 | * \param Pool The pool's core type. 30 | */ 31 | template 32 | struct empty_controller 33 | { 34 | empty_controller(typename Pool::size_policy_type&, shared_ptr) {} 35 | }; 36 | 37 | 38 | /*! \brief SizePolicyController which allows resizing. 39 | * 40 | * \param Pool The pool's core type. 41 | */ 42 | template< typename Pool > 43 | class resize_controller 44 | { 45 | typedef typename Pool::size_policy_type size_policy_type; 46 | reference_wrapper m_policy; 47 | shared_ptr m_pool; //!< to make sure that the pool is alive (the policy pointer is valid) as long as the controller exists 48 | 49 | public: 50 | resize_controller(size_policy_type& policy, shared_ptr pool) 51 | : m_policy(policy) 52 | , m_pool(pool) 53 | { 54 | } 55 | 56 | bool resize(size_t worker_count) 57 | { 58 | return m_policy.get().resize(worker_count); 59 | } 60 | }; 61 | 62 | 63 | /*! \brief SizePolicy which preserves the thread count. 64 | * 65 | * \param Pool The pool's core type. 66 | */ 67 | template 68 | class static_size 69 | { 70 | reference_wrapper m_pool; 71 | 72 | public: 73 | static void init(Pool& pool, size_t const worker_count) 74 | { 75 | pool.resize(worker_count); 76 | } 77 | 78 | static_size(Pool volatile & pool) 79 | : m_pool(pool) 80 | {} 81 | 82 | bool resize(size_t const worker_count) 83 | { 84 | return m_pool.get().resize(worker_count); 85 | } 86 | 87 | void worker_died_unexpectedly(size_t const new_worker_count) 88 | { 89 | m_pool.get().resize(new_worker_count + 1); 90 | } 91 | 92 | // TODO this functions are not called yet 93 | void task_scheduled() {} 94 | void task_finished() {} 95 | }; 96 | 97 | } } // namespace boost::threadpool 98 | 99 | #endif // THREADPOOL_SIZE_POLICIES_HPP_INCLUDED 100 | -------------------------------------------------------------------------------- /sources/boost/threadpool/task_adaptors.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Task adaptors. 3 | * 4 | * This file contains adaptors for task function objects. 5 | * 6 | * Copyright (c) 2005-2007 Philipp Henkel 7 | * 8 | * Use, modification, and distribution are subject to the 9 | * Boost Software License, Version 1.0. (See accompanying file 10 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | * 12 | * http://threadpool.sourceforge.net 13 | * 14 | */ 15 | 16 | 17 | #ifndef THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED 18 | #define THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | namespace boost { namespace threadpool 27 | { 28 | 29 | /*! \brief Standard task function object. 30 | * 31 | * This function object wraps a nullary function which returns void. 32 | * The wrapped function is invoked by calling the operator (). 33 | * 34 | * \see boost function library 35 | * 36 | */ 37 | typedef function0 task_func; 38 | 39 | 40 | 41 | 42 | /*! \brief Prioritized task function object. 43 | * 44 | * This function object wraps a task_func object and binds a priority to it. 45 | * prio_task_funcs can be compared using the operator < which realises a partial ordering. 46 | * The wrapped task function is invoked by calling the operator (). 47 | * 48 | * \see prio_scheduler 49 | * 50 | */ 51 | class prio_task_func 52 | { 53 | private: 54 | unsigned int m_priority; //!< The priority of the task's function. 55 | task_func m_function; //!< The task's function. 56 | 57 | public: 58 | typedef void result_type; //!< Indicates the functor's result type. 59 | 60 | public: 61 | /*! Constructor. 62 | * \param priority The priority of the task. 63 | * \param function The task's function object. 64 | */ 65 | prio_task_func(unsigned int const priority, task_func const & function) 66 | : m_priority(priority) 67 | , m_function(function) 68 | { 69 | } 70 | 71 | /*! Executes the task function. 72 | */ 73 | void operator() (void) const 74 | { 75 | if(m_function) 76 | { 77 | m_function(); 78 | } 79 | } 80 | 81 | /*! Comparison operator which realises a partial ordering based on priorities. 82 | * \param rhs The object to compare with. 83 | * \return true if the priority of *this is less than right hand side's priority, false otherwise. 84 | */ 85 | bool operator< (const prio_task_func& rhs) const 86 | { 87 | return m_priority < rhs.m_priority; 88 | } 89 | 90 | }; // prio_task_func 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | /*! \brief Looped task function object. 100 | * 101 | * This function object wraps a boolean thread function object. 102 | * The wrapped task function is invoked by calling the operator () and it is executed in regular 103 | * time intervals until false is returned. The interval length may be zero. 104 | * Please note that a pool's thread is engaged as long as the task is looped. 105 | * 106 | */ 107 | class looped_task_func 108 | { 109 | private: 110 | function0 m_function; //!< The task's function. 111 | unsigned int m_break_s; //!< Duration of breaks in seconds. 112 | unsigned int m_break_ns; //!< Duration of breaks in nano seconds. 113 | 114 | public: 115 | typedef void result_type; //!< Indicates the functor's result type. 116 | 117 | public: 118 | /*! Constructor. 119 | * \param function The task's function object which is looped until false is returned. 120 | * \param interval The minimum break time in milli seconds before the first execution of the task function and between the following ones. 121 | */ 122 | looped_task_func(function0 const & function, unsigned int const interval = 0) 123 | : m_function(function) 124 | { 125 | m_break_s = interval / 1000; 126 | m_break_ns = (interval - m_break_s * 1000) * 1000 * 1000; 127 | } 128 | 129 | /*! Executes the task function. 130 | */ 131 | void operator() (void) const 132 | { 133 | if(m_function) 134 | { 135 | if(m_break_s > 0 || m_break_ns > 0) 136 | { // Sleep some time before first execution 137 | xtime xt; 138 | #if BOOST_VERSION >= 105000 139 | xtime_get(&xt, TIME_UTC_); 140 | #else 141 | xtime_get(&xt, TIME_UTC); 142 | #endif 143 | xt.nsec += m_break_ns; 144 | xt.sec += m_break_s; 145 | thread::sleep(xt); 146 | } 147 | 148 | while(m_function()) 149 | { 150 | if(m_break_s > 0 || m_break_ns > 0) 151 | { 152 | xtime xt; 153 | #if BOOST_VERSION >= 105000 154 | xtime_get(&xt, TIME_UTC_); 155 | #else 156 | xtime_get(&xt, TIME_UTC); 157 | #endif 158 | xt.nsec += m_break_ns; 159 | xt.sec += m_break_s; 160 | thread::sleep(xt); 161 | } 162 | else 163 | { 164 | thread::yield(); // Be fair to other threads 165 | } 166 | } 167 | } 168 | } 169 | 170 | }; // looped_task_func 171 | 172 | 173 | } } // namespace boost::threadpool 174 | 175 | #endif // THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED 176 | 177 | -------------------------------------------------------------------------------- /sources/freeglut.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_H__ 2 | #define __FREEGLUT_H__ 3 | 4 | /* 5 | * freeglut.h 6 | * 7 | * The freeglut library include file 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #include "freeglut_std.h" 18 | #include "freeglut_ext.h" 19 | 20 | /*** END OF FILE ***/ 21 | 22 | #endif /* __FREEGLUT_H__ */ 23 | -------------------------------------------------------------------------------- /sources/future.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief TODO. 3 | * 4 | * TODO. 5 | * 6 | * Copyright (c) 2005-2007 Philipp Henkel 7 | * 8 | * Use, modification, and distribution are subject to the 9 | * Boost Software License, Version 1.0. (See accompanying file 10 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | * 12 | * http://threadpool.sourceforge.net 13 | * 14 | */ 15 | 16 | 17 | #ifndef THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED 18 | #define THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED 19 | 20 | 21 | #include "locking_ptr.hpp" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace boost { namespace threadpool { namespace detail 33 | { 34 | 35 | template 36 | class future_impl 37 | { 38 | public: 39 | typedef Result const & result_type; //!< Indicates the functor's result type. 40 | 41 | typedef Result future_result_type; //!< Indicates the future's result type. 42 | typedef future_impl future_type; 43 | 44 | private: 45 | volatile bool m_ready; 46 | volatile future_result_type m_result; 47 | 48 | mutable mutex m_monitor; 49 | mutable condition m_condition_ready; 50 | 51 | volatile bool m_is_cancelled; 52 | volatile bool m_executing; 53 | 54 | public: 55 | 56 | 57 | public: 58 | 59 | future_impl() 60 | : m_ready(false) 61 | , m_is_cancelled(false) 62 | { 63 | } 64 | 65 | bool ready() const volatile 66 | { 67 | return m_ready; 68 | } 69 | 70 | void wait() const volatile 71 | { 72 | const future_type* self = const_cast(this); 73 | mutex::scoped_lock lock(self->m_monitor); 74 | 75 | while(!m_ready) 76 | { 77 | self->m_condition_ready.wait(lock); 78 | } 79 | } 80 | 81 | 82 | bool timed_wait(boost::xtime const & timestamp) const 83 | { 84 | const future_type* self = const_cast(this); 85 | mutex::scoped_lock lock(self->m_monitor); 86 | 87 | while(!m_ready) 88 | { 89 | if(!self->m_condition_ready.timed_wait(lock, timestamp)) return false; 90 | } 91 | 92 | return true; 93 | } 94 | 95 | 96 | result_type operator()() const volatile 97 | { 98 | wait(); 99 | /* 100 | if( throw_exception_ != 0 ) 101 | { 102 | throw_exception_( this ); 103 | } 104 | */ 105 | 106 | return *(const_cast(&m_result)); 107 | } 108 | 109 | 110 | void set_value(future_result_type const & r) volatile 111 | { 112 | locking_ptr lockedThis(*this, m_monitor); 113 | if(!m_ready && !m_is_cancelled) 114 | { 115 | lockedThis->m_result = r; 116 | lockedThis->m_ready = true; 117 | lockedThis->m_condition_ready.notify_all(); 118 | } 119 | } 120 | /* 121 | template void set_exception() // throw() 122 | { 123 | m_impl->template set_exception(); 124 | } 125 | 126 | template void set_exception( char const * what ) // throw() 127 | { 128 | m_impl->template set_exception( what ); 129 | } 130 | */ 131 | 132 | 133 | bool cancel() volatile 134 | { 135 | if(!m_ready || m_executing) 136 | { 137 | m_is_cancelled = true; 138 | return true; 139 | } 140 | else 141 | { 142 | return false; 143 | } 144 | } 145 | 146 | 147 | bool is_cancelled() const volatile 148 | { 149 | return m_is_cancelled; 150 | } 151 | 152 | 153 | void set_execution_status(bool executing) volatile 154 | { 155 | m_executing = executing; 156 | } 157 | }; 158 | 159 | 160 | template< 161 | template class Future, 162 | typename Function 163 | > 164 | class future_impl_task_func 165 | { 166 | 167 | public: 168 | typedef void result_type; //!< Indicates the functor's result type. 169 | 170 | typedef Function function_type; //!< Indicates the function's type. 171 | typedef typename result_of::type future_result_type; //!< Indicates the future's result type. 172 | typedef Future future_type; //!< Indicates the future's type. 173 | 174 | // The task is required to be a nullary function. 175 | BOOST_STATIC_ASSERT(function_traits::arity == 0); 176 | 177 | // The task function's result type is required not to be void. 178 | BOOST_STATIC_ASSERT(!is_void::value); 179 | 180 | private: 181 | function_type m_function; 182 | shared_ptr m_future; 183 | 184 | public: 185 | future_impl_task_func(function_type const & function, shared_ptr const & future) 186 | : m_function(function) 187 | , m_future(future) 188 | { 189 | } 190 | 191 | void operator()() 192 | { 193 | if(m_function) 194 | { 195 | m_future->set_execution_status(true); 196 | if(!m_future->is_cancelled()) 197 | { 198 | // TODO future exeception handling 199 | m_future->set_value(m_function()); 200 | } 201 | m_future->set_execution_status(false); // TODO consider exceptions 202 | } 203 | } 204 | 205 | }; 206 | 207 | 208 | 209 | 210 | 211 | } } } // namespace boost::threadpool::detail 212 | 213 | #endif // THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED 214 | 215 | 216 | -------------------------------------------------------------------------------- /sources/gl/include/GL/freeglut.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_H__ 2 | #define __FREEGLUT_H__ 3 | 4 | /* 5 | * freeglut.h 6 | * 7 | * The freeglut library include file 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #include "freeglut_std.h" 18 | #include "freeglut_ext.h" 19 | 20 | /*** END OF FILE ***/ 21 | 22 | #endif /* __FREEGLUT_H__ */ 23 | -------------------------------------------------------------------------------- /sources/gl/include/GL/glut.h: -------------------------------------------------------------------------------- 1 | #ifndef __GLUT_H__ 2 | #define __GLUT_H__ 3 | 4 | /* 5 | * glut.h 6 | * 7 | * The freeglut library include file 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #include "freeglut_std.h" 18 | 19 | /*** END OF FILE ***/ 20 | 21 | #endif /* __GLUT_H__ */ 22 | -------------------------------------------------------------------------------- /sources/glut.h: -------------------------------------------------------------------------------- 1 | #ifndef __GLUT_H__ 2 | #define __GLUT_H__ 3 | 4 | /* 5 | * glut.h 6 | * 7 | * The freeglut library include file 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #include "freeglut_std.h" 18 | 19 | /*** END OF FILE ***/ 20 | 21 | #endif /* __GLUT_H__ */ 22 | -------------------------------------------------------------------------------- /sources/locking_ptr.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief The locking_ptr is smart pointer with a scoped locking mechanism. 3 | * 4 | * The class is a wrapper for a volatile pointer. It enables synchronized access to the 5 | * internal pointer by locking the passed mutex. 6 | * locking_ptr is based on Andrei Alexandrescu's LockingPtr. For more information 7 | * see article "volatile - Multithreaded Programmer's Best Friend" by A. Alexandrescu. 8 | * 9 | * 10 | * Copyright (c) 2005-2007 Philipp Henkel 11 | * 12 | * Use, modification, and distribution are subject to the 13 | * Boost Software License, Version 1.0. (See accompanying file 14 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 15 | * 16 | * http://threadpool.sourceforge.net 17 | * 18 | */ 19 | 20 | 21 | #ifndef THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED 22 | #define THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED 23 | 24 | #include 25 | #include 26 | 27 | 28 | namespace boost { namespace threadpool { namespace detail 29 | { 30 | 31 | /*! \brief Smart pointer with a scoped locking mechanism. 32 | * 33 | * This class is a wrapper for a volatile pointer. It enables synchronized access to the 34 | * internal pointer by locking the passed mutex. 35 | */ 36 | template 37 | class locking_ptr 38 | : private noncopyable 39 | { 40 | T* m_obj; //!< The instance pointer. 41 | Mutex & m_mutex; //!< Mutex is used for scoped locking. 42 | 43 | public: 44 | /// Constructor. 45 | locking_ptr(volatile T& obj, const volatile Mutex& mtx) 46 | : m_obj(const_cast(&obj)) 47 | , m_mutex(*const_cast(&mtx)) 48 | { 49 | // Lock mutex 50 | m_mutex.lock(); 51 | } 52 | 53 | 54 | /// Destructor. 55 | ~locking_ptr() 56 | { 57 | // Unlock mutex 58 | m_mutex.unlock(); 59 | } 60 | 61 | 62 | /*! Returns a reference to the stored instance. 63 | * \return The instance's reference. 64 | */ 65 | T& operator*() const 66 | { 67 | return *m_obj; 68 | } 69 | 70 | 71 | /*! Returns a pointer to the stored instance. 72 | * \return The instance's pointer. 73 | */ 74 | T* operator->() const 75 | { 76 | return m_obj; 77 | } 78 | }; 79 | 80 | 81 | } } } // namespace boost::threadpool::detail 82 | 83 | 84 | #endif // THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED 85 | 86 | -------------------------------------------------------------------------------- /sources/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Miro.h" 3 | #include "Scene.h" 4 | #include "Camera.h" 5 | #include "Image.h" 6 | #include "Console.h" 7 | 8 | #include "PointLight.h" 9 | #include "Sphere.h" 10 | #include "TriangleMesh.h" 11 | #include "Triangle.h" 12 | #include "Phong.h" 13 | #include "MiroWindow.h" 14 | #include "assignment1.h" 15 | #include "assignment2.h" 16 | 17 | boost::mt19937 g_rng; 18 | //boost::uniform_01 randone; 19 | 20 | void 21 | makeSpiralScene() 22 | { 23 | g_camera = new Camera; 24 | g_scene = new Scene; 25 | g_image = new Image; 26 | 27 | g_image->resize(512, 512); 28 | 29 | // set up the camera 30 | g_scene->setBGColor(Vector3(1.0f, 1.0f, 1.0f)); 31 | g_camera->setEye(Vector3(-5, 2, 3)); 32 | g_camera->setLookAt(Vector3(0, 0, 0)); 33 | g_camera->setUp(Vector3(0, 1, 0)); 34 | g_camera->setFOV(45); 35 | 36 | // create and place a point light source 37 | PointLight * light = new PointLight; 38 | light->setPosition(Vector3(-3, 15, 3)); 39 | light->setColor(Vector3(1, 1, 1)); 40 | light->setWattage(1000); 41 | g_scene->addLight(light); 42 | 43 | // create a spiral of spheres 44 | Material* mat = new Phong(Vector3(1.0f, 0.0f, 0.0f), 0, 0); 45 | const int maxI = 200; 46 | const float a = 0.15f; 47 | for (int i = 1; i < maxI; ++i) 48 | { 49 | float t = i/float(maxI); 50 | float theta = 4*PI*t; 51 | float r = a*theta; 52 | float x = r*cos(theta); 53 | float y = r*sin(theta); 54 | float z = 2*(2*PI*a - r); 55 | Sphere * sphere = new Sphere; 56 | sphere->setCenter(Vector3(x,y,z)); 57 | sphere->setRadius(r/10); 58 | sphere->setMaterial(mat); 59 | g_scene->addObject(sphere); 60 | } 61 | 62 | // let objects do pre-calculations if needed 63 | g_scene->preCalc(); 64 | } 65 | 66 | void 67 | makeLorenzScene() 68 | { 69 | g_camera = new Camera; 70 | g_scene = new Scene; 71 | g_image = new Image; 72 | 73 | g_image->resize(512, 512); 74 | 75 | // set up the camera 76 | g_scene->setBGColor(Vector3(1.0f, 1.0f, 1.0f)); 77 | g_camera->setEye(Vector3(-5, 2, 150)); 78 | g_camera->setLookAt(Vector3(0, 0, 0)); 79 | g_camera->setUp(Vector3(0, 1, 0)); 80 | g_camera->setFOV(45); 81 | 82 | // create and place a point light source 83 | PointLight * light = new PointLight; 84 | light->setPosition(Vector3(0, 0, 55)); 85 | light->setColor(Vector3(1, 1, 1)); 86 | light->setWattage(1000); 87 | g_scene->addLight(light); 88 | 89 | // create a spiral of spheres 90 | Material* mat = new Phong(Vector3(1.0f, 0.0f, 0.0f), 0, 0); 91 | const int maxI = 10000; 92 | const float a = 0.15f; 93 | const float pi = 28; 94 | const float theta = 10; 95 | const float beta = 8.0/3.0; 96 | const float dt = 0.02; 97 | float x = 0, y = 1, z = 1.05; 98 | float t = 0.01; 99 | float t2; 100 | float minx = -10000, miny = -10000, minz = -10000; 101 | for (int i = 1; i < maxI; ++i) 102 | { 103 | t = i * dt; 104 | t2 = (i % 100) / 100.0; 105 | float theta2 = 4*PI*t; 106 | float r = a*theta2; 107 | x += theta * (y - x) * dt; 108 | y += (x * (pi - z) - y) * dt; 109 | z += (x*y - beta*z)*dt; 110 | Sphere * sphere = new Sphere; 111 | sphere->setCenter(Vector3(x,y,z)); 112 | sphere->setRadius(0.005 * t); 113 | sphere->setMaterial(new Phong(Vector3((i % 100) / 100.0, 0.5 * (i % 30) / 30.0, ((i % 20) / 20.0)), 0, 0)); 114 | g_scene->addObject(sphere); 115 | if (x > minx) 116 | minx = x; 117 | if (y > miny) 118 | miny = y; 119 | if (z > minz) 120 | minz = z; 121 | } 122 | 123 | // let objects do pre-calculations if needed 124 | g_scene->preCalc(); 125 | } 126 | 127 | 128 | int 129 | main(int argc, char*argv[]) 130 | { 131 | srand(time(NULL)); 132 | // create a scene 133 | makeAllInOneScene(); 134 | 135 | MiroWindow miro(&argc, argv); 136 | miro.mainLoop(); 137 | 138 | return 0; // never executed 139 | } 140 | 141 | -------------------------------------------------------------------------------- /sources/pool.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Thread pool core. 3 | * 4 | * This file contains the threadpool's core class: pool. 5 | * 6 | * Thread pools are a mechanism for asynchronous and parallel processing 7 | * within the same process. The pool class provides a convenient way 8 | * for dispatching asynchronous tasks as functions objects. The scheduling 9 | * of these tasks can be easily controlled by using customized schedulers. 10 | * 11 | * Copyright (c) 2005-2007 Philipp Henkel 12 | * 13 | * Use, modification, and distribution are subject to the 14 | * Boost Software License, Version 1.0. (See accompanying file 15 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 16 | * 17 | * http://threadpool.sourceforge.net 18 | * 19 | */ 20 | 21 | 22 | #ifndef THREADPOOL_POOL_HPP_INCLUDED 23 | #define THREADPOOL_POOL_HPP_INCLUDED 24 | 25 | #include 26 | 27 | #include "./detail/pool_core.hpp" 28 | 29 | #include "task_adaptors.hpp" 30 | 31 | #include "./detail/locking_ptr.hpp" 32 | 33 | #include "scheduling_policies.hpp" 34 | #include "size_policies.hpp" 35 | #include "shutdown_policies.hpp" 36 | 37 | 38 | 39 | /// The namespace threadpool contains a thread pool and related utility classes. 40 | namespace boost { namespace threadpool 41 | { 42 | 43 | 44 | 45 | /*! \brief Thread pool. 46 | * 47 | * Thread pools are a mechanism for asynchronous and parallel processing 48 | * within the same process. The pool class provides a convenient way 49 | * for dispatching asynchronous tasks as functions objects. The scheduling 50 | * of these tasks can be easily controlled by using customized schedulers. 51 | * A task must not throw an exception. 52 | * 53 | * A pool is DefaultConstructible, CopyConstructible and Assignable. 54 | * It has reference semantics; all copies of the same pool are equivalent and interchangeable. 55 | * All operations on a pool except assignment are strongly thread safe or sequentially consistent; 56 | * that is, the behavior of concurrent calls is as if the calls have been issued sequentially in an unspecified order. 57 | * 58 | * \param Task A function object which implements the operator 'void operator() (void) const'. The operator () is called by the pool to execute the task. Exceptions are ignored. 59 | * \param SchedulingPolicy A task container which determines how tasks are scheduled. It is guaranteed that this container is accessed only by one thread at a time. The scheduler shall not throw exceptions. 60 | * 61 | * \remarks The pool class is thread-safe. 62 | * 63 | * \see Tasks: task_func, prio_task_func 64 | * \see Scheduling policies: fifo_scheduler, lifo_scheduler, prio_scheduler 65 | */ 66 | template < 67 | typename Task = task_func, 68 | template class SchedulingPolicy = fifo_scheduler, 69 | template class SizePolicy = static_size, 70 | template class SizePolicyController = resize_controller, 71 | template class ShutdownPolicy = wait_for_all_tasks 72 | > 73 | class thread_pool 74 | { 75 | typedef detail::pool_core pool_core_type; 80 | shared_ptr m_core; // pimpl idiom 81 | shared_ptr m_shutdown_controller; // If the last pool holding a pointer to the core is deleted the controller shuts the pool down. 82 | 83 | public: // Type definitions 84 | typedef Task task_type; //!< Indicates the task's type. 85 | typedef SchedulingPolicy scheduler_type; //!< Indicates the scheduler's type. 86 | /* typedef thread_pool pool_type; //!< Indicates the thread pool's type. 90 | */ 91 | typedef SizePolicy size_policy_type; 92 | typedef SizePolicyController size_controller_type; 93 | 94 | 95 | public: 96 | /*! Constructor. 97 | * \param initial_threads The pool is immediately resized to set the specified number of threads. The pool's actual number threads depends on the SizePolicy. 98 | */ 99 | thread_pool(size_t initial_threads = 0) 100 | : m_core(new pool_core_type) 101 | , m_shutdown_controller(static_cast(0), bind(&pool_core_type::shutdown, m_core)) 102 | { 103 | size_policy_type::init(*m_core, initial_threads); 104 | } 105 | 106 | 107 | /*! Gets the size controller which manages the number of threads in the pool. 108 | * \return The size controller. 109 | * \see SizePolicy 110 | */ 111 | size_controller_type size_controller() 112 | { 113 | return m_core->size_controller(); 114 | } 115 | 116 | 117 | /*! Gets the number of threads in the pool. 118 | * \return The number of threads. 119 | */ 120 | size_t size() const 121 | { 122 | return m_core->size(); 123 | } 124 | 125 | 126 | /*! Schedules a task for asynchronous execution. The task will be executed once only. 127 | * \param task The task function object. It should not throw execeptions. 128 | * \return true, if the task could be scheduled and false otherwise. 129 | */ 130 | bool schedule(task_type const & task) 131 | { 132 | return m_core->schedule(task); 133 | } 134 | 135 | 136 | /*! Returns the number of tasks which are currently executed. 137 | * \return The number of active tasks. 138 | */ 139 | size_t active() const 140 | { 141 | return m_core->active(); 142 | } 143 | 144 | 145 | /*! Returns the number of tasks which are ready for execution. 146 | * \return The number of pending tasks. 147 | */ 148 | size_t pending() const 149 | { 150 | return m_core->pending(); 151 | } 152 | 153 | 154 | /*! Removes all pending tasks from the pool's scheduler. 155 | */ 156 | void clear() 157 | { 158 | m_core->clear(); 159 | } 160 | 161 | 162 | /*! Indicates that there are no tasks pending. 163 | * \return true if there are no tasks ready for execution. 164 | * \remarks This function is more efficient that the check 'pending() == 0'. 165 | */ 166 | bool empty() const 167 | { 168 | return m_core->empty(); 169 | } 170 | 171 | 172 | /*! The current thread of execution is blocked until the sum of all active 173 | * and pending tasks is equal or less than a given threshold. 174 | * \param task_threshold The maximum number of tasks in pool and scheduler. 175 | */ 176 | void wait(size_t task_threshold = 0) const 177 | { 178 | m_core->wait(task_threshold); 179 | } 180 | 181 | 182 | /*! The current thread of execution is blocked until the timestamp is met 183 | * or the sum of all active and pending tasks is equal or less 184 | * than a given threshold. 185 | * \param timestamp The time when function returns at the latest. 186 | * \param task_threshold The maximum number of tasks in pool and scheduler. 187 | * \return true if the task sum is equal or less than the threshold, false otherwise. 188 | */ 189 | bool wait(xtime const & timestamp, size_t task_threshold = 0) const 190 | { 191 | return m_core->wait(timestamp, task_threshold); 192 | } 193 | }; 194 | 195 | 196 | 197 | /*! \brief Fifo pool. 198 | * 199 | * The pool's tasks are fifo scheduled task_func functors. 200 | * 201 | */ 202 | typedef thread_pool fifo_pool; 203 | 204 | 205 | /*! \brief Lifo pool. 206 | * 207 | * The pool's tasks are lifo scheduled task_func functors. 208 | * 209 | */ 210 | typedef thread_pool lifo_pool; 211 | 212 | 213 | /*! \brief Pool for prioritized task. 214 | * 215 | * The pool's tasks are prioritized prio_task_func functors. 216 | * 217 | */ 218 | typedef thread_pool prio_pool; 219 | 220 | 221 | /*! \brief A standard pool. 222 | * 223 | * The pool's tasks are fifo scheduled task_func functors. 224 | * 225 | */ 226 | typedef fifo_pool pool; 227 | 228 | 229 | 230 | } } // namespace boost::threadpool 231 | 232 | #endif // THREADPOOL_POOL_HPP_INCLUDED 233 | -------------------------------------------------------------------------------- /sources/pool_adaptors.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Pool adaptors. 3 | * 4 | * This file contains an easy-to-use adaptor similar to a smart 5 | * pointer for the pool class. 6 | * 7 | * Copyright (c) 2005-2007 Philipp Henkel 8 | * 9 | * Use, modification, and distribution are subject to the 10 | * Boost Software License, Version 1.0. (See accompanying file 11 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 | * 13 | * http://threadpool.sourceforge.net 14 | * 15 | */ 16 | 17 | 18 | #ifndef THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED 19 | #define THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED 20 | 21 | #include 22 | 23 | 24 | namespace boost { namespace threadpool 25 | { 26 | 27 | 28 | // TODO convenience scheduling function 29 | /*! Schedules a Runnable for asynchronous execution. A Runnable is an arbitrary class with a run() 30 | * member function. This a convenience shorthand for pool->schedule(bind(&Runnable::run, task_object)). 31 | * \param 32 | * \param obj The Runnable object. The member function run() will be exectued and should not throw execeptions. 33 | * \return true, if the task could be scheduled and false otherwise. 34 | */ 35 | template 36 | bool schedule(Pool& pool, shared_ptr const & obj) 37 | { 38 | return pool->schedule(bind(&Runnable::run, obj)); 39 | } 40 | 41 | /*! Schedules a task for asynchronous execution. The task will be executed once only. 42 | * \param task The task function object. 43 | */ 44 | template 45 | typename enable_if < 46 | is_void< typename result_of< typename Pool::task_type() >::type >, 47 | bool 48 | >::type 49 | schedule(Pool& pool, typename Pool::task_type const & task) 50 | { 51 | return pool.schedule(task); 52 | } 53 | 54 | 55 | template 56 | typename enable_if < 57 | is_void< typename result_of< typename Pool::task_type() >::type >, 58 | bool 59 | >::type 60 | schedule(shared_ptr const pool, typename Pool::task_type const & task) 61 | { 62 | return pool->schedule(task); 63 | } 64 | 65 | 66 | } } // namespace boost::threadpool 67 | 68 | #endif // THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED 69 | 70 | 71 | -------------------------------------------------------------------------------- /sources/scheduling_policies.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Task scheduling policies. 3 | * 4 | * This file contains some fundamental scheduling policies for the pool class. 5 | * A scheduling policy is realized by a task container which controls the access to 6 | * the tasks. Fundamentally the container determines the order the tasks are processed 7 | * by the thread pool. 8 | * The task containers need not to be thread-safe because they are used by the pool 9 | * in thread-safe way. 10 | * 11 | * Copyright (c) 2005-2007 Philipp Henkel 12 | * 13 | * Use, modification, and distribution are subject to the 14 | * Boost Software License, Version 1.0. (See accompanying file 15 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 16 | * 17 | * http://threadpool.sourceforge.net 18 | * 19 | */ 20 | 21 | 22 | #ifndef THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED 23 | #define THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED 24 | 25 | 26 | #include 27 | #include 28 | 29 | #include "task_adaptors.hpp" 30 | 31 | namespace boost { namespace threadpool 32 | { 33 | 34 | /*! \brief SchedulingPolicy which implements FIFO ordering. 35 | * 36 | * This container implements a FIFO scheduling policy. 37 | * The first task to be added to the scheduler will be the first to be removed. 38 | * The processing proceeds sequentially in the same order. 39 | * FIFO stands for "first in, first out". 40 | * 41 | * \param Task A function object which implements the operator()(void). 42 | * 43 | */ 44 | template 45 | class fifo_scheduler 46 | { 47 | public: 48 | typedef Task task_type; //!< Indicates the scheduler's task type. 49 | 50 | protected: 51 | std::deque m_container; //!< Internal task container. 52 | 53 | 54 | public: 55 | /*! Adds a new task to the scheduler. 56 | * \param task The task object. 57 | * \return true, if the task could be scheduled and false otherwise. 58 | */ 59 | bool push(task_type const & task) 60 | { 61 | m_container.push_back(task); 62 | return true; 63 | } 64 | 65 | /*! Removes the task which should be executed next. 66 | */ 67 | void pop() 68 | { 69 | m_container.pop_front(); 70 | } 71 | 72 | /*! Gets the task which should be executed next. 73 | * \return The task object to be executed. 74 | */ 75 | task_type const & top() const 76 | { 77 | return m_container.front(); 78 | } 79 | 80 | /*! Gets the current number of tasks in the scheduler. 81 | * \return The number of tasks. 82 | * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty. 83 | */ 84 | size_t size() const 85 | { 86 | return m_container.size(); 87 | } 88 | 89 | /*! Checks if the scheduler is empty. 90 | * \return true if the scheduler contains no tasks, false otherwise. 91 | * \remarks Is more efficient than size() == 0. 92 | */ 93 | bool empty() const 94 | { 95 | return m_container.empty(); 96 | } 97 | 98 | /*! Removes all tasks from the scheduler. 99 | */ 100 | void clear() 101 | { 102 | m_container.clear(); 103 | } 104 | }; 105 | 106 | 107 | 108 | /*! \brief SchedulingPolicy which implements LIFO ordering. 109 | * 110 | * This container implements a LIFO scheduling policy. 111 | * The last task to be added to the scheduler will be the first to be removed. 112 | * LIFO stands for "last in, first out". 113 | * 114 | * \param Task A function object which implements the operator()(void). 115 | * 116 | */ 117 | template 118 | class lifo_scheduler 119 | { 120 | public: 121 | typedef Task task_type; //!< Indicates the scheduler's task type. 122 | 123 | protected: 124 | std::deque m_container; //!< Internal task container. 125 | 126 | public: 127 | /*! Adds a new task to the scheduler. 128 | * \param task The task object. 129 | * \return true, if the task could be scheduled and false otherwise. 130 | */ 131 | bool push(task_type const & task) 132 | { 133 | m_container.push_front(task); 134 | return true; 135 | } 136 | 137 | /*! Removes the task which should be executed next. 138 | */ 139 | void pop() 140 | { 141 | m_container.pop_front(); 142 | } 143 | 144 | /*! Gets the task which should be executed next. 145 | * \return The task object to be executed. 146 | */ 147 | task_type const & top() const 148 | { 149 | return m_container.front(); 150 | } 151 | 152 | /*! Gets the current number of tasks in the scheduler. 153 | * \return The number of tasks. 154 | * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty. 155 | */ 156 | size_t size() const 157 | { 158 | return m_container.size(); 159 | } 160 | 161 | /*! Checks if the scheduler is empty. 162 | * \return true if the scheduler contains no tasks, false otherwise. 163 | * \remarks Is more efficient than size() == 0. 164 | */ 165 | bool empty() const 166 | { 167 | return m_container.empty(); 168 | } 169 | 170 | /*! Removes all tasks from the scheduler. 171 | */ 172 | void clear() 173 | { 174 | m_container.clear(); 175 | } 176 | 177 | }; 178 | 179 | 180 | 181 | /*! \brief SchedulingPolicy which implements prioritized ordering. 182 | * 183 | * This container implements a scheduling policy based on task priorities. 184 | * The task with highest priority will be the first to be removed. 185 | * It must be possible to compare two tasks using operator<. 186 | * 187 | * \param Task A function object which implements the operator() and operator<. operator< must be a partial ordering. 188 | * 189 | * \see prio_thread_func 190 | * 191 | */ 192 | template 193 | class prio_scheduler 194 | { 195 | public: 196 | typedef Task task_type; //!< Indicates the scheduler's task type. 197 | 198 | protected: 199 | std::priority_queue m_container; //!< Internal task container. 200 | 201 | 202 | public: 203 | /*! Adds a new task to the scheduler. 204 | * \param task The task object. 205 | * \return true, if the task could be scheduled and false otherwise. 206 | */ 207 | bool push(task_type const & task) 208 | { 209 | m_container.push(task); 210 | return true; 211 | } 212 | 213 | /*! Removes the task which should be executed next. 214 | */ 215 | void pop() 216 | { 217 | m_container.pop(); 218 | } 219 | 220 | /*! Gets the task which should be executed next. 221 | * \return The task object to be executed. 222 | */ 223 | task_type const & top() const 224 | { 225 | return m_container.top(); 226 | } 227 | 228 | /*! Gets the current number of tasks in the scheduler. 229 | * \return The number of tasks. 230 | * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty. 231 | */ 232 | size_t size() const 233 | { 234 | return m_container.size(); 235 | } 236 | 237 | /*! Checks if the scheduler is empty. 238 | * \return true if the scheduler contains no tasks, false otherwise. 239 | * \remarks Is more efficient than size() == 0. 240 | */ 241 | bool empty() const 242 | { 243 | return m_container.empty(); 244 | } 245 | 246 | /*! Removes all tasks from the scheduler. 247 | */ 248 | void clear() 249 | { 250 | while(!m_container.empty()) 251 | { 252 | m_container.pop(); 253 | } 254 | } 255 | }; 256 | 257 | 258 | } } // namespace boost::threadpool 259 | 260 | 261 | #endif // THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED 262 | 263 | -------------------------------------------------------------------------------- /sources/scope_guard.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief TODO. 3 | * 4 | * TODO. 5 | * 6 | * Copyright (c) 2005-2007 Philipp Henkel 7 | * 8 | * Use, modification, and distribution are subject to the 9 | * Boost Software License, Version 1.0. (See accompanying file 10 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | * 12 | * http://threadpool.sourceforge.net 13 | * 14 | */ 15 | 16 | 17 | #ifndef THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED 18 | #define THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED 19 | 20 | 21 | 22 | #include 23 | 24 | 25 | namespace boost { namespace threadpool { namespace detail 26 | { 27 | 28 | // TODO documentation 29 | class scope_guard 30 | : private boost::noncopyable 31 | { 32 | function0 const m_function; 33 | bool m_is_active; 34 | 35 | public: 36 | scope_guard(function0 const & call_on_exit) 37 | : m_function(call_on_exit) 38 | , m_is_active(true) 39 | { 40 | } 41 | 42 | ~scope_guard() 43 | { 44 | if(m_is_active && m_function) 45 | { 46 | m_function(); 47 | } 48 | } 49 | 50 | void disable() 51 | { 52 | m_is_active = false; 53 | } 54 | }; 55 | 56 | 57 | 58 | 59 | 60 | 61 | } } } // namespace boost::threadpool::detail 62 | 63 | #endif // THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED 64 | 65 | 66 | -------------------------------------------------------------------------------- /sources/shutdown_policies.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Shutdown policies. 3 | * 4 | * This file contains shutdown policies for thread_pool. 5 | * A shutdown policy controls the pool's behavior from the time 6 | * when the pool is not referenced any longer. 7 | * 8 | * Copyright (c) 2005-2007 Philipp Henkel 9 | * 10 | * Use, modification, and distribution are subject to the 11 | * Boost Software License, Version 1.0. (See accompanying file 12 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 13 | * 14 | * http://threadpool.sourceforge.net 15 | * 16 | */ 17 | 18 | 19 | #ifndef THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED 20 | #define THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED 21 | 22 | 23 | 24 | /// The namespace threadpool contains a thread pool and related utility classes. 25 | namespace boost { namespace threadpool 26 | { 27 | 28 | 29 | /*! \brief ShutdownPolicy which waits for the completion of all tasks 30 | * and the worker termination afterwards. 31 | * 32 | * \param Pool The pool's core type. 33 | */ 34 | template 35 | class wait_for_all_tasks 36 | { 37 | public: 38 | static void shutdown(Pool& pool) 39 | { 40 | pool.wait(); 41 | pool.terminate_all_workers(true); 42 | } 43 | }; 44 | 45 | 46 | /*! \brief ShutdownPolicy which waits for the completion of all active tasks 47 | * and the worker termination afterwards. 48 | * 49 | * \param Pool The pool's core type. 50 | */ 51 | template 52 | class wait_for_active_tasks 53 | { 54 | public: 55 | static void shutdown(Pool& pool) 56 | { 57 | pool.clear(); 58 | pool.wait(); 59 | pool.terminate_all_workers(true); 60 | } 61 | }; 62 | 63 | 64 | /*! \brief ShutdownPolicy which does not wait for any tasks or worker termination. 65 | * 66 | * This policy does not wait for any tasks. Nevertheless all active tasks will be processed completely. 67 | * 68 | * \param Pool The pool's core type. 69 | */ 70 | template 71 | class immediately 72 | { 73 | public: 74 | static void shutdown(Pool& pool) 75 | { 76 | pool.clear(); 77 | pool.terminate_all_workers(false); 78 | } 79 | }; 80 | 81 | } } // namespace boost::threadpool 82 | 83 | #endif // THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED 84 | -------------------------------------------------------------------------------- /sources/size_policies.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Size policies. 3 | * 4 | * This file contains size policies for thread_pool. A size 5 | * policy controls the number of worker threads in the pool. 6 | * 7 | * Copyright (c) 2005-2007 Philipp Henkel 8 | * 9 | * Use, modification, and distribution are subject to the 10 | * Boost Software License, Version 1.0. (See accompanying file 11 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 | * 13 | * http://threadpool.sourceforge.net 14 | * 15 | */ 16 | 17 | 18 | #ifndef THREADPOOL_SIZE_POLICIES_HPP_INCLUDED 19 | #define THREADPOOL_SIZE_POLICIES_HPP_INCLUDED 20 | 21 | 22 | 23 | /// The namespace threadpool contains a thread pool and related utility classes. 24 | namespace boost { namespace threadpool 25 | { 26 | 27 | /*! \brief SizePolicyController which provides no functionality. 28 | * 29 | * \param Pool The pool's core type. 30 | */ 31 | template 32 | struct empty_controller 33 | { 34 | empty_controller(typename Pool::size_policy_type&, shared_ptr) {} 35 | }; 36 | 37 | 38 | /*! \brief SizePolicyController which allows resizing. 39 | * 40 | * \param Pool The pool's core type. 41 | */ 42 | template< typename Pool > 43 | class resize_controller 44 | { 45 | typedef typename Pool::size_policy_type size_policy_type; 46 | reference_wrapper m_policy; 47 | shared_ptr m_pool; //!< to make sure that the pool is alive (the policy pointer is valid) as long as the controller exists 48 | 49 | public: 50 | resize_controller(size_policy_type& policy, shared_ptr pool) 51 | : m_policy(policy) 52 | , m_pool(pool) 53 | { 54 | } 55 | 56 | bool resize(size_t worker_count) 57 | { 58 | return m_policy.get().resize(worker_count); 59 | } 60 | }; 61 | 62 | 63 | /*! \brief SizePolicy which preserves the thread count. 64 | * 65 | * \param Pool The pool's core type. 66 | */ 67 | template 68 | class static_size 69 | { 70 | reference_wrapper m_pool; 71 | 72 | public: 73 | static void init(Pool& pool, size_t const worker_count) 74 | { 75 | pool.resize(worker_count); 76 | } 77 | 78 | static_size(Pool volatile & pool) 79 | : m_pool(pool) 80 | {} 81 | 82 | bool resize(size_t const worker_count) 83 | { 84 | return m_pool.get().resize(worker_count); 85 | } 86 | 87 | void worker_died_unexpectedly(size_t const new_worker_count) 88 | { 89 | m_pool.get().resize(new_worker_count + 1); 90 | } 91 | 92 | // TODO this functions are not called yet 93 | void task_scheduled() {} 94 | void task_finished() {} 95 | }; 96 | 97 | } } // namespace boost::threadpool 98 | 99 | #endif // THREADPOOL_SIZE_POLICIES_HPP_INCLUDED 100 | -------------------------------------------------------------------------------- /sources/task_adaptors.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Task adaptors. 3 | * 4 | * This file contains adaptors for task function objects. 5 | * 6 | * Copyright (c) 2005-2007 Philipp Henkel 7 | * 8 | * Use, modification, and distribution are subject to the 9 | * Boost Software License, Version 1.0. (See accompanying file 10 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | * 12 | * http://threadpool.sourceforge.net 13 | * 14 | */ 15 | 16 | 17 | #ifndef THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED 18 | #define THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | namespace boost { namespace threadpool 27 | { 28 | 29 | /*! \brief Standard task function object. 30 | * 31 | * This function object wraps a nullary function which returns void. 32 | * The wrapped function is invoked by calling the operator (). 33 | * 34 | * \see boost function library 35 | * 36 | */ 37 | typedef function0 task_func; 38 | 39 | 40 | 41 | 42 | /*! \brief Prioritized task function object. 43 | * 44 | * This function object wraps a task_func object and binds a priority to it. 45 | * prio_task_funcs can be compared using the operator < which realises a partial ordering. 46 | * The wrapped task function is invoked by calling the operator (). 47 | * 48 | * \see prio_scheduler 49 | * 50 | */ 51 | class prio_task_func 52 | { 53 | private: 54 | unsigned int m_priority; //!< The priority of the task's function. 55 | task_func m_function; //!< The task's function. 56 | 57 | public: 58 | typedef void result_type; //!< Indicates the functor's result type. 59 | 60 | public: 61 | /*! Constructor. 62 | * \param priority The priority of the task. 63 | * \param function The task's function object. 64 | */ 65 | prio_task_func(unsigned int const priority, task_func const & function) 66 | : m_priority(priority) 67 | , m_function(function) 68 | { 69 | } 70 | 71 | /*! Executes the task function. 72 | */ 73 | void operator() (void) const 74 | { 75 | if(m_function) 76 | { 77 | m_function(); 78 | } 79 | } 80 | 81 | /*! Comparison operator which realises a partial ordering based on priorities. 82 | * \param rhs The object to compare with. 83 | * \return true if the priority of *this is less than right hand side's priority, false otherwise. 84 | */ 85 | bool operator< (const prio_task_func& rhs) const 86 | { 87 | return m_priority < rhs.m_priority; 88 | } 89 | 90 | }; // prio_task_func 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | /*! \brief Looped task function object. 100 | * 101 | * This function object wraps a boolean thread function object. 102 | * The wrapped task function is invoked by calling the operator () and it is executed in regular 103 | * time intervals until false is returned. The interval length may be zero. 104 | * Please note that a pool's thread is engaged as long as the task is looped. 105 | * 106 | */ 107 | class looped_task_func 108 | { 109 | private: 110 | function0 m_function; //!< The task's function. 111 | unsigned int m_break_s; //!< Duration of breaks in seconds. 112 | unsigned int m_break_ns; //!< Duration of breaks in nano seconds. 113 | 114 | public: 115 | typedef void result_type; //!< Indicates the functor's result type. 116 | 117 | public: 118 | /*! Constructor. 119 | * \param function The task's function object which is looped until false is returned. 120 | * \param interval The minimum break time in milli seconds before the first execution of the task function and between the following ones. 121 | */ 122 | looped_task_func(function0 const & function, unsigned int const interval = 0) 123 | : m_function(function) 124 | { 125 | m_break_s = interval / 1000; 126 | m_break_ns = (interval - m_break_s * 1000) * 1000 * 1000; 127 | } 128 | 129 | /*! Executes the task function. 130 | */ 131 | void operator() (void) const 132 | { 133 | if(m_function) 134 | { 135 | if(m_break_s > 0 || m_break_ns > 0) 136 | { // Sleep some time before first execution 137 | xtime xt; 138 | #if BOOST_VERSION >= 105000 139 | xtime_get(&xt, TIME_UTC_); 140 | #else 141 | xtime_get(&xt, TIME_UTC); 142 | #endif 143 | xt.nsec += m_break_ns; 144 | xt.sec += m_break_s; 145 | thread::sleep(xt); 146 | } 147 | 148 | while(m_function()) 149 | { 150 | if(m_break_s > 0 || m_break_ns > 0) 151 | { 152 | xtime xt; 153 | #if BOOST_VERSION >= 105000 154 | xtime_get(&xt, TIME_UTC_); 155 | #else 156 | xtime_get(&xt, TIME_UTC); 157 | #endif 158 | xt.nsec += m_break_ns; 159 | xt.sec += m_break_s; 160 | thread::sleep(xt); 161 | } 162 | else 163 | { 164 | thread::yield(); // Be fair to other threads 165 | } 166 | } 167 | } 168 | } 169 | 170 | }; // looped_task_func 171 | 172 | 173 | } } // namespace boost::threadpool 174 | 175 | #endif // THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED 176 | 177 | -------------------------------------------------------------------------------- /sources/threadpool.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Main include. 3 | * 4 | * This is the only file you have to include in order to use the 5 | * complete threadpool library. 6 | * 7 | * Copyright (c) 2005-2007 Philipp Henkel 8 | * 9 | * Use, modification, and distribution are subject to the 10 | * Boost Software License, Version 1.0. (See accompanying file 11 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 | * 13 | * http://threadpool.sourceforge.net 14 | * 15 | */ 16 | 17 | #ifndef THREADPOOL_HPP_INCLUDED 18 | #define THREADPOOL_HPP_INCLUDED 19 | 20 | #include "./threadpool/future.hpp" 21 | #include "./threadpool/pool.hpp" 22 | 23 | #include "./threadpool/pool_adaptors.hpp" 24 | #include "./threadpool/task_adaptors.hpp" 25 | 26 | 27 | #endif // THREADPOOL_HPP_INCLUDED 28 | 29 | -------------------------------------------------------------------------------- /sources/worker_thread.hpp: -------------------------------------------------------------------------------- 1 | /*! \file 2 | * \brief Thread pool worker. 3 | * 4 | * The worker thread instance is attached to a pool 5 | * and executes tasks of this pool. 6 | * 7 | * Copyright (c) 2005-2007 Philipp Henkel 8 | * 9 | * Use, modification, and distribution are subject to the 10 | * Boost Software License, Version 1.0. (See accompanying file 11 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 | * 13 | * http://threadpool.sourceforge.net 14 | * 15 | */ 16 | 17 | #ifndef THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED 18 | #define THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED 19 | 20 | 21 | #include "scope_guard.hpp" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | namespace boost { namespace threadpool { namespace detail 31 | { 32 | 33 | /*! \brief Thread pool worker. 34 | * 35 | * A worker_thread represents a thread of execution. The worker is attached to a 36 | * thread pool and processes tasks of that pool. The lifetime of the worker and its 37 | * internal boost::thread is managed automatically. 38 | * 39 | * This class is a helper class and cannot be constructed or accessed directly. 40 | * 41 | * \see pool_core 42 | */ 43 | template 44 | class worker_thread 45 | : public enable_shared_from_this< worker_thread > 46 | , private noncopyable 47 | { 48 | public: 49 | typedef Pool pool_type; //!< Indicates the pool's type. 50 | 51 | private: 52 | shared_ptr m_pool; //!< Pointer to the pool which created the worker. 53 | shared_ptr m_thread; //!< Pointer to the thread which executes the run loop. 54 | 55 | 56 | /*! Constructs a new worker. 57 | * \param pool Pointer to it's parent pool. 58 | * \see function create_and_attach 59 | */ 60 | worker_thread(shared_ptr const & pool) 61 | : m_pool(pool) 62 | { 63 | assert(pool); 64 | } 65 | 66 | 67 | /*! Notifies that an exception occurred in the run loop. 68 | */ 69 | void died_unexpectedly() 70 | { 71 | m_pool->worker_died_unexpectedly(this->shared_from_this()); 72 | } 73 | 74 | 75 | public: 76 | /*! Executes pool's tasks sequentially. 77 | */ 78 | void run() 79 | { 80 | scope_guard notify_exception(bind(&worker_thread::died_unexpectedly, this)); 81 | 82 | while(m_pool->execute_task()) {} 83 | 84 | notify_exception.disable(); 85 | m_pool->worker_destructed(this->shared_from_this()); 86 | } 87 | 88 | 89 | /*! Joins the worker's thread. 90 | */ 91 | void join() 92 | { 93 | m_thread->join(); 94 | } 95 | 96 | 97 | /*! Constructs a new worker thread and attaches it to the pool. 98 | * \param pool Pointer to the pool. 99 | */ 100 | static void create_and_attach(shared_ptr const & pool) 101 | { 102 | shared_ptr worker(new worker_thread(pool)); 103 | if(worker) 104 | { 105 | worker->m_thread.reset(new boost::thread(bind(&worker_thread::run, worker))); 106 | } 107 | } 108 | 109 | }; 110 | 111 | 112 | } } } // namespace boost::threadpool::detail 113 | 114 | #endif // THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED 115 | 116 | --------------------------------------------------------------------------------