1 #include <core_api/surface.h>
2 #include <core_api/ray.h>
3 #include <utilities/interpolation.h>
4 
5 __BEGIN_YAFRAY
6 
spDifferentials_t(const surfacePoint_t & spoint,const diffRay_t & ray)7 spDifferentials_t::spDifferentials_t(const surfacePoint_t &spoint, const diffRay_t &ray): sp(spoint)
8 {
9 	if (ray.hasDifferentials)
10 	{
11 		// Estimate screen-space change in \pt and $(u,v)$
12 		// Compute auxiliary intersection points with plane
13 		float d = -(sp.N * vector3d_t(sp.P));
14 		vector3d_t rxv(ray.xfrom);
15 		float tx = -((sp.N * rxv) + d) / (sp.N * ray.xdir);
16 		point3d_t px = ray.xfrom + tx * ray.xdir;
17 		vector3d_t ryv(ray.yfrom);
18 		float ty = -((sp.N * ryv) + d) / (sp.N * ray.ydir);
19 		point3d_t py = ray.yfrom + ty * ray.ydir;
20 		dPdx = px - sp.P;
21 		dPdy = py - sp.P;
22 	}
23 	else
24 	{
25 		//dudx = dvdx = 0.;
26 		//dudy = dvdy = 0.;
27 		dPdx = dPdy = vector3d_t(0,0,0);
28 	}
29 }
30 
reflectedRay(const diffRay_t & in,diffRay_t & out) const31 void spDifferentials_t::reflectedRay(const diffRay_t &in, diffRay_t &out) const
32 {
33 	if(!in.hasDifferentials)
34 	{
35 		out.hasDifferentials = false;
36 		return;
37 	}
38 	// Compute ray differential _rd_ for specular reflection
39 	out.hasDifferentials = true;
40 	out.xfrom = sp.P + dPdx;
41 	out.yfrom = sp.P + dPdy;
42 	// Compute differential reflected directions
43 //	Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx +
44 //				  bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
45 //	Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy +
46 //				  bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
47 	vector3d_t dwodx = in.dir - in.xdir, dwody = in.dir - in.ydir;
48 	float dDNdx = (dwodx * sp.N); // + (out.dir * dndx);
49 	float dDNdy = (dwody * sp.N); // + (out.dir * dndy);
50 	out.xdir = out.dir - dwodx + 2 * (/* (out.dir * sp.N) * dndx + */ dDNdx * sp.N);
51 	out.ydir = out.dir - dwody + 2 * (/* (out.dir * sp.N) * dndy + */ dDNdy * sp.N);
52 }
53 
refractedRay(const diffRay_t & in,diffRay_t & out,float IOR) const54 void spDifferentials_t::refractedRay(const diffRay_t &in, diffRay_t &out, float IOR) const
55 {
56 	if(!in.hasDifferentials)
57 	{
58 		out.hasDifferentials = false;
59 		return;
60 	}
61 	//RayDifferential rd(p, wi);
62 	out.hasDifferentials = true;
63 	out.xfrom = sp.P + dPdx;
64 	out.yfrom = sp.P + dPdy;
65 	//if (Dot(wo, n) < 0) eta = 1.f / eta;
66 
67 	//Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx + bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
68 	//Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy + bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
69 
70 	vector3d_t dwodx = in.dir - in.xdir, dwody = in.dir - in.ydir;
71 	float dDNdx = (dwodx * sp.N); // + Dot(wo, dndx);
72 	float dDNdy = (dwody * sp.N); // + Dot(wo, dndy);
73 
74 //	float mu = IOR * (in.dir * sp.N) - (out.dir * sp.N);
75 	float dmudx = (IOR - (IOR*IOR*(in.dir * sp.N))/(out.dir * sp.N)) * dDNdx;
76 	float dmudy = (IOR - (IOR*IOR*(in.dir * sp.N))/(out.dir * sp.N)) * dDNdy;
77 
78 	out.xdir = out.dir + IOR * dwodx - (/* mu * dndx + */ dmudx * sp.N);
79 	out.ydir = out.dir + IOR * dwody - (/* mu * dndy + */ dmudy * sp.N);
80 }
81 
projectedPixelArea()82 float spDifferentials_t::projectedPixelArea()
83 {
84 	return (dPdx ^ dPdy).length();
85 }
86 
dU_dV_from_dP_dPdU_dPdV(float & dU,float & dV,const point3d_t & dP,const vector3d_t & dPdU,const vector3d_t & dPdV) const87 void spDifferentials_t::dU_dV_from_dP_dPdU_dPdV(float &dU, float &dV, const point3d_t &dP, const vector3d_t &dPdU, const vector3d_t &dPdV) const
88 {
89 	float detXY = (dPdU.x*dPdV.y)-(dPdV.x*dPdU.y);
90 	float detXZ = (dPdU.x*dPdV.z)-(dPdV.x*dPdU.z);
91 	float detYZ = (dPdU.y*dPdV.z)-(dPdV.y*dPdU.z);
92 
93 	if(fabsf(detXY) > 0.f && fabsf(detXY) > fabsf(detXZ) && fabsf(detXY) > fabsf(detYZ))
94 	{
95 		dU = ((dP.x*dPdV.y)-(dPdV.x*dP.y)) / detXY;
96 		dV = ((dPdU.x*dP.y)-(dP.x*dPdU.y)) / detXY;
97 	}
98 
99 	else if(fabsf(detXZ) > 0.f && fabsf(detXZ) > fabsf(detXY) && fabsf(detXZ) > fabsf(detYZ))
100 	{
101 		dU = ((dP.x*dPdV.z)-(dPdV.x*dP.z)) / detXZ;
102 		dV = ((dPdU.x*dP.z)-(dP.x*dPdU.z)) / detXZ;
103 	}
104 
105 	else if(fabsf(detYZ) > 0.f && fabsf(detYZ) > fabsf(detXY) && fabsf(detYZ) > fabsf(detXZ))
106 	{
107 		dU = ((dP.y*dPdV.z)-(dPdV.y*dP.z)) / detYZ;
108 		dV = ((dPdU.y*dP.z)-(dP.y*dPdU.z)) / detYZ;
109 	}
110 }
111 
getUVdifferentials(float & dUdx,float & dVdx,float & dUdy,float & dVdy) const112 void spDifferentials_t::getUVdifferentials(float &dUdx, float &dVdx, float &dUdy, float &dVdy) const
113 {
114 	dU_dV_from_dP_dPdU_dPdV(dUdx, dVdx, dPdx, sp.dPdU_abs, sp.dPdV_abs);
115 	dU_dV_from_dP_dPdU_dPdV(dUdy, dVdy, dPdy, sp.dPdU_abs, sp.dPdV_abs);
116 }
117 
118 
blend_surface_points(surfacePoint_t const & sp_0,surfacePoint_t const & sp_1,float const alpha)119 surfacePoint_t blend_surface_points(surfacePoint_t const& sp_0, surfacePoint_t const& sp_1, float const alpha)
120 {
121     surfacePoint_t sp_result(sp_0);
122 
123     sp_result.N = lerp(sp_0.N, sp_1.N, alpha);
124 
125     sp_result.NU = lerp(sp_0.NU, sp_1.NU, alpha);
126     sp_result.NV = lerp(sp_0.NV, sp_1.NV, alpha);
127     sp_result.dPdU = lerp(sp_0.dPdU, sp_1.dPdU, alpha);
128     sp_result.dPdV = lerp(sp_0.dPdV, sp_1.dPdV, alpha);
129     sp_result.dSdU = lerp(sp_0.dSdU, sp_1.dSdU, alpha);
130     sp_result.dSdV = lerp(sp_0.dSdV, sp_1.dSdV, alpha);
131 
132     return sp_result;
133 }
134 
135 __END_YAFRAY
136