src/scene.cc
branchpyrit
changeset 25 b8232edee786
parent 24 d0d76e8a5203
child 28 ffe83ca074f3
equal deleted inserted replaced
24:d0d76e8a5203 25:b8232edee786
    92 	a = tnear;
    92 	a = tnear;
    93 	b = tfar;
    93 	b = tfar;
    94 	return true;
    94 	return true;
    95 }
    95 }
    96 
    96 
    97 bool Sphere::intersect(const Ray &ray, Float &dist)
    97 bool Sphere::intersect(const Ray &ray, Float &dist) const
    98 {
    98 {
    99 	Vector3 V = ray.o - center;
    99 	Vector3 V = ray.o - center;
   100 	register Float d = -dot(V, ray.dir);
   100 	register Float d = -dot(V, ray.dir);
   101 	register Float Det = d * d - (dot(V,V) - sqr_radius);
   101 	register Float Det = d * d - (dot(V,V) - sqr_radius);
   102 	if (Det > 0) {
   102 	if (Det > 0) {
   108 		}
   108 		}
   109 	}
   109 	}
   110 	return false;
   110 	return false;
   111 }
   111 }
   112 
   112 
   113 bool Sphere::intersect_all(const Ray &ray, Float dist, vector<Float> &allts)
   113 bool Sphere::intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const
   114 {
   114 {
   115 	//allts = new vector<Float>();
   115 	//allts = new vector<Float>();
   116 
   116 
   117 	Vector3 V = ((Ray)ray).o - center;
   117 	Vector3 V = ((Ray)ray).o - center;
   118 	Float Vd = - dot(V, ray.dir);
   118 	Float Vd = - dot(V, ray.dir);
   142 		}
   142 		}
   143 	}
   143 	}
   144 	return false;
   144 	return false;
   145 }
   145 }
   146 
   146 
   147 BBox Sphere::get_bbox()
   147 BBox Sphere::get_bbox() const
   148 {
   148 {
   149 	BBox bbox = BBox();
   149 	BBox bbox = BBox();
   150 	bbox.L = center - radius;
   150 	bbox.L = center - radius;
   151 	bbox.H = center + radius;
   151 	bbox.H = center + radius;
   152 	return bbox;
   152 	return bbox;
   153 }
   153 }
   154 
   154 
   155 bool Box::intersect(const Ray &ray, Float &dist)
   155 bool Box::intersect(const Ray &ray, Float &dist) const
   156 {
   156 {
   157 	Float a,b;
   157 	Float a,b;
   158 	bool res = get_bbox().intersect(ray, a, b);
   158 	bool res = get_bbox().intersect(ray, a, b);
   159 	if (res && a < dist)
   159 	if (res && a < dist)
   160 	{
   160 	{
   163 	}
   163 	}
   164 	else
   164 	else
   165 		return false;
   165 		return false;
   166 }
   166 }
   167 
   167 
   168 Vector3 Box::normal(Vector3 &P)
   168 Vector3 Box::normal(Vector3 &P) const
   169 {
   169 {
   170 	Vector3 N;
   170 	Vector3 N;
   171 	for (int i = 0; i < 3; i++)
   171 	for (int i = 0; i < 3; i++)
   172 	{
   172 	{
   173 		if (P.cell[i] >= L.cell[i]-Eps && P.cell[i] <= L.cell[i]+Eps)
   173 		if (P.cell[i] >= L.cell[i]-Eps && P.cell[i] <= L.cell[i]+Eps)
   184 		}
   184 		}
   185 	}
   185 	}
   186 	return N;
   186 	return N;
   187 }
   187 }
   188 
   188 
   189 // this initialization and following intersection methods implements
   189 #ifdef TRI_PLUCKER
   190 // Fast Triangle Intersection algorithm from
   190 inline void Plucker(const Vector3 &p, const Vector3 &q, Float* pl)
   191 // http://www.mpi-inf.mpg.de/~wald/PhD/
   191 {
       
   192     pl[0] = p.x*q.y - q.x*p.y;
       
   193     pl[1] = p.x*q.z - q.x*p.z;
       
   194     pl[2] = p.x - q.x;
       
   195     pl[3] = p.y*q.z - q.y*p.z;
       
   196     pl[4] = p.z - q.z;
       
   197     pl[5] = q.y - p.y;
       
   198 }
       
   199 
       
   200 inline Float Side(const Float* pla, const Float* plb)
       
   201 {
       
   202     return pla[0]*plb[4] + pla[1]*plb[5] + pla[2]*plb[3] + pla[4]*plb[0] + pla[5]*plb[1] + pla[3]*plb[2];
       
   203 }
       
   204 #endif
       
   205 
   192 Triangle::Triangle(const Vector3 &aA, const Vector3 &aB, const Vector3 &aC, Material *amaterial)
   206 Triangle::Triangle(const Vector3 &aA, const Vector3 &aB, const Vector3 &aC, Material *amaterial)
   193 	: A(aA), B(aB), C(aC)
   207 	: A(aA), B(aB), C(aC)
   194 {
   208 {
   195 	material = amaterial;
   209 	material = amaterial;
   196 	Vector3 c = B - A;
   210 	material->reflection = 0;
   197 	Vector3 b = C - A;
   211 
   198 
   212 	const Vector3 c = B - A;
   199 	N = cross(c, b);
   213 	const Vector3 b = C - A;
   200 
   214 
       
   215 	N = -cross(c, b);
       
   216 	N.normalize();
       
   217 
       
   218 #ifdef TRI_PLUCKER
       
   219 	Plucker(B,C,pla);
       
   220 	Plucker(C,A,plb);
       
   221 	Plucker(A,B,plc);
       
   222 #endif
       
   223 
       
   224 #if defined(TRI_BARI) || defined(TRI_BARI_PRE)
   201 	if (fabsf(N.x) > fabsf(N.y))
   225 	if (fabsf(N.x) > fabsf(N.y))
   202 	{
   226 	{
   203 		if (fabsf(N.x) > fabsf(N.z))
   227 		if (fabsf(N.x) > fabsf(N.z))
   204 			k = 0;
   228 			k = 0;
   205 		else
   229 		else
   210 		if (fabsf(N.y) > fabsf(N.z))
   234 		if (fabsf(N.y) > fabsf(N.z))
   211 			k = 1;
   235 			k = 1;
   212 		else
   236 		else
   213 			k = 2;
   237 			k = 2;
   214 	}
   238 	}
   215 
   239 #endif
       
   240 #ifdef TRI_BARI_PRE
   216 	int u = (k + 1) % 3;
   241 	int u = (k + 1) % 3;
   217 	int v = (k + 2) % 3;
   242 	int v = (k + 2) % 3;
   218 
   243 
   219 	Float krec = 1.0f / N[k];
   244 	Float krec = 1.0 / N[k];
   220 	nu = N[u] * krec;
   245 	nu = N[u] * krec;
   221 	nv = N[v] * krec;
   246 	nv = N[v] * krec;
   222 	nd = dot(N, A) * krec;
   247 	nd = dot(N, A) * krec;
   223 
   248 
   224 	// first line equation
   249 	// first line equation
   225 	Float reci = 1.0f / (b[u] * c[v] - b[v] * c[u]);
   250 	Float reci = 1.0f / (b[u] * c[v] - b[v] * c[u]);
   226 	bnu = b[u] * reci;
   251 	bnu = b[u] * reci;
   227 	bnv = -b[v] * reci;
   252 	bnv = -b[v] * reci;
   228 
   253 
   229 	// second line equation
   254 	// second line equation
   230 	cnu = c[v] * reci;
   255 	cnu = -c[u] * reci;
   231 	cnv = -c[u] * reci;
   256 	cnv = c[v] * reci;
   232 
   257 #endif
   233 	// finalize normal
   258 }
   234 	N.normalize();
   259 
   235 }
   260 bool Triangle::intersect(const Ray &ray, Float &dist) const
   236 
   261 {
   237 // see comment for previous method
   262 #ifdef TRI_PLUCKER
   238 bool Triangle::intersect(const Ray &ray, Float &dist)
   263 	Float plr[6];
   239 {
   264 	Plucker(ray.o, ray.o+ray.dir, plr);
   240 	Vector3 O = ray.o;
   265 	const bool side0 = Side(plr, pla) >= 0.0;
   241 	Vector3 D = ray.dir;
   266 	const bool side1 = Side(plr, plb) >= 0.0;
   242 
   267 	if (side0 != side1)
   243 	const int modulo3[5] = {0,1,2,0,1};
   268 		return false;
   244 	const int ku = modulo3[k+1];
   269 	const bool side2 = Side(plr, plc) >= 0.0;
   245 	const int kv = modulo3[k+2];
   270 	if (side0 != side2)
   246 	const Float lnd = 1.0f / (D[k] + nu * D[ku] + nv * D[kv]);
   271 		return false;
   247 	const Float t = (nd - O[k] - nu * O[ku] - nv * O[kv]) * lnd;
   272 	const Float t = - dot( (ray.o-A), N) / dot(ray.dir,N);
   248 
   273 	if(t <= Eps || t >= dist)
   249 	if (t < 0 || t >= dist)
   274 		return false;
   250 		return false;
       
   251 
       
   252 	Float hu = O[ku] + t * D[ku] - A[ku];
       
   253 	Float hv = O[kv] + t * D[kv] - A[kv];
       
   254 	Float beta = hv * bnu + hu * bnv;
       
   255 
       
   256 	if (beta < 0)
       
   257 		return false;
       
   258 
       
   259 	Float gamma = hu * cnu + hv * cnv;
       
   260 	if (gamma < 0)
       
   261 		return false;
       
   262 
       
   263 	if ((beta + gamma) > 1)
       
   264 		return false;
       
   265 
       
   266 	dist = t;
   275 	dist = t;
   267 	return true;
   276 	return true;
   268 }
   277 #endif
   269 
   278 
   270 BBox Triangle::get_bbox()
   279 #if defined(TRI_BARI) || defined(TRI_BARI_PRE)
       
   280 	static const int modulo3[5] = {0,1,2,0,1};
       
   281 	const Vector3 &O = ray.o;
       
   282 	const Vector3 &D = ray.dir;
       
   283 	register const int u = modulo3[k+1];
       
   284 	register const int v = modulo3[k+2];
       
   285 #endif
       
   286 #ifdef TRI_BARI_PRE
       
   287 	const Float t = (nd - O[k] - nu * O[u] - nv * O[v]) / (D[k] + nu * D[u] + nv * D[v]);
       
   288 
       
   289 	if (t >= dist || t < Eps)
       
   290 		return false;
       
   291 
       
   292 	const Float hu = O[u] + t * D[u] - A[u];
       
   293 	const Float hv = O[v] + t * D[v] - A[v];
       
   294 	const Float beta = hv * bnu + hu * bnv;
       
   295 
       
   296 	if (beta < 0.)
       
   297 		return false;
       
   298 
       
   299 	const Float gamma = hu * cnv + hv * cnu;
       
   300 	if (gamma < 0. || beta + gamma > 1)
       
   301 		return false;
       
   302 
       
   303 	dist = t;
       
   304 	return true;
       
   305 #endif
       
   306 
       
   307 #ifdef TRI_BARI
       
   308 	// original barycentric coordinates based intesection
       
   309 	// not optimized, just for reference
       
   310 	const Vector3 c = B - A;
       
   311 	const Vector3 b = C - A;
       
   312 	// distance test
       
   313 	const Float t = - dot( (O-A), N) / dot(D,N);
       
   314 	if (t < Eps || t > dist)
       
   315 		return false;
       
   316 
       
   317 	// calc hitpoint
       
   318 	const Float Hu = O[u] + t * D[u] - A[u];
       
   319 	const Float Hv = O[v] + t * D[v] - A[v];
       
   320 	const Float beta = (b[u] * Hv - b[v] * Hu) / (b[u] * c[v] - b[v] * c[u]);
       
   321 	if (beta < 0)
       
   322 		return false;
       
   323 	const Float gamma = (c[v] * Hu - c[u] * Hv) / (b[u] * c[v] - b[v] * c[u]);
       
   324 	if (gamma < 0)
       
   325 		return false;
       
   326 	if (beta+gamma > 1)
       
   327 		return false;
       
   328 	dist = t;
       
   329 	return true;
       
   330 #endif
       
   331 }
       
   332 
       
   333 BBox Triangle::get_bbox() const
   271 {
   334 {
   272 	BBox bbox = BBox();
   335 	BBox bbox = BBox();
   273 	bbox.L = A;
   336 	bbox.L = A;
   274 	if (B.x < bbox.L.x)  bbox.L.x = B.x;
   337 	if (B.x < bbox.L.x)  bbox.L.x = B.x;
   275 	if (C.x < bbox.L.x)  bbox.L.x = C.x;
   338 	if (C.x < bbox.L.x)  bbox.L.x = C.x;