merge pixmap handling from sampler, material.h and ccdemos's image module to new Pixmap class
add check for PNG library, allow writing PNG file from a Pixmap
simplify demos using new methods from Sampler and Pixmap
/*
* shapes.h: shape classes
*
* This file is part of Pyrit Ray Tracer.
*
* Copyright 2006, 2007, 2008 Radek Brich
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef SHAPES_H
#define SHAPES_H
#include "common.h"
#include "scene.h"
#include "material.h"
/*
triangle intersection alghoritm
options are:
TRI_PLUCKER
TRI_BARI
TRI_BARI_PRE
*/
#if !defined(TRI_PLUCKER) && !defined(TRI_BARI) && !defined(TRI_BARI_PRE)
# define TRI_BARI_PRE
#endif
/**
* shape
*/
class Shape
{
public:
Material *material;
Shape() {};
virtual ~Shape() {};
// first intersection point
virtual bool intersect(const Ray &ray, Float &dist) const = 0;
virtual __m128 intersect_packet(const RayPacket &rays, __m128 &dists)
{
__m128 results;
((int*)&results)[0] = intersect(rays[0], ((float*)&dists)[0]) ? -1 : 0;
((int*)&results)[1] = intersect(rays[1], ((float*)&dists)[1]) ? -1 : 0;
((int*)&results)[2] = intersect(rays[2], ((float*)&dists)[2]) ? -1 : 0;
((int*)&results)[3] = intersect(rays[3], ((float*)&dists)[3]) ? -1 : 0;
return results;
};
// all intersections (only for CSG)
virtual bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const = 0;
// intersection with AABB
virtual bool intersect_bbox(const BBox &bbox) const = 0;
// normal at point P
virtual const Vector3 normal(const Vector3 &P) const = 0;
virtual BBox get_bbox() const = 0;
virtual ostream & dump(ostream &st) const = 0;
};
/**
* list of shapes
*/
typedef vector<Shape*> ShapeList;
/**
* sphere shape
*/
class Sphere: public Shape
{
Vector3 center;
Float radius;
Float sqr_radius;
Float inv_radius;
public:
Sphere(const Vector3 &acenter, const Float aradius, Material *amaterial):
center(acenter), radius(aradius),
sqr_radius(aradius*aradius), inv_radius(1.0f/aradius)
{ material = amaterial; }
bool intersect(const Ray &ray, Float &dist) const;
__m128 intersect_packet(const RayPacket &rays, __m128 &dists);
bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const;
bool intersect_bbox(const BBox &bbox) const;
const Vector3 normal(const Vector3 &P) const { return (P - center) * inv_radius; };
BBox get_bbox() const;
const Vector3 getCenter() const { return center; };
Float getRadius() const { return radius; };
ostream & dump(ostream &st) const;
};
/**
* box shape
*/
class Box: public Shape
{
Vector3 L;
Vector3 H;
public:
Box(const Vector3 &aL, const Vector3 &aH, Material *amaterial): L(aL), H(aH)
{
for (int i = 0; i < 3; i++)
if (L.cell[i] > H.cell[i])
swap(L.cell[i], H.cell[i]);
material = amaterial;
};
bool intersect(const Ray &ray, Float &dist) const;
__m128 intersect_packet(const RayPacket &rays, __m128 &dists);
bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const { return false; };
bool intersect_bbox(const BBox &bbox) const;
const Vector3 normal(const Vector3 &P) const;
BBox get_bbox() const { return BBox(L, H); };
const Vector3 getL() const { return L; };
const Vector3 getH() const { return H; };
ostream & dump(ostream &st) const;
};
/**
* triangle vertex
*/
class Vertex
{
public:
Vector3 P;
Vertex(const Vector3 &aP): P(aP) {};
virtual ~Vertex() {};
virtual ostream & dump(ostream &st) const;
};
/**
* triangle vertex with normal
*/
class NormalVertex: public Vertex
{
public:
Vector3 N;
NormalVertex(const NormalVertex *v): Vertex(v->P), N(v->N) {};
NormalVertex(const Vector3 &aP): Vertex(aP) {};
NormalVertex(const Vector3 &aP, const Vector3 &aN): Vertex(aP), N(aN) {};
const Vector3 &getNormal() { return N; };
void setNormal(const Vector3 &aN) { N = aN; };
ostream & dump(ostream &st) const;
};
/**
* triangle shape
*/
class Triangle: public Shape
{
#ifdef TRI_BARI_PRE
Float nu, nv, nd;
int k; // dominant axis
Float bnu, bnv;
Float cnu, cnv;
#endif
#ifdef TRI_BARI
int k; // dominant axis
#endif
#ifdef TRI_PLUCKER
Float pla[6], plb[6], plc[6];
#endif
Vector3 N;
const Vector3 smooth_normal(const Vector3 &P) const
{
#ifdef TRI_BARI_PRE
const Vector3 &NA = static_cast<NormalVertex*>(A)->N;
const Vector3 &NB = static_cast<NormalVertex*>(B)->N;
const Vector3 &NC = static_cast<NormalVertex*>(C)->N;
static const int modulo3[5] = {0,1,2,0,1};
register const int ku = modulo3[k+1];
register const int kv = modulo3[k+2];
const Float pu = P[ku] - A->P[ku];
const Float pv = P[kv] - A->P[kv];
const Float u = pv * bnu + pu * bnv;
const Float v = pu * cnv + pv * cnu;
Vector3 n = NA + u * (NB - NA) + v * (NC - NA);
n.normalize();
return n;
#else
return N; // not implemented for other algorithms
#endif
};
public:
Vertex *A, *B, *C;
Triangle() {};
Triangle(Vertex *aA, Vertex *aB, Vertex *aC, Material *amaterial);
bool intersect(const Ray &ray, Float &dist) const;
#ifdef TRI_BARI_PRE
__m128 intersect_packet(const RayPacket &rays, __m128 &dists);
#endif
bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const {return false;};
bool intersect_bbox(const BBox &bbox) const;
const Vector3 normal(const Vector3 &P) const { return (material->smooth ? smooth_normal(P) : N); };
const Vector3 getNormal() const { return N; };
BBox get_bbox() const;
ostream & dump(ostream &st) const;
};
template <class T> class Array
{
T *array;
public:
Array(int n) { array = new T[n]; };
~Array() { delete[] array; };
const T &operator[](int i) const { return array[i]; };
};
typedef Array<Vertex> VertexArray;
typedef Array<NormalVertex> NormalVertexArray;
typedef Array<Triangle> TriangleArray;
#endif