diff --git a/Skeleton.cpp b/Skeleton.cpp index 87f0e2365af932a580ca8a923e8f41aba209e3ca..4f66788d249f0599e0d3539ac9eb2b8bb48aaaef 100644 --- a/Skeleton.cpp +++ b/Skeleton.cpp @@ -110,12 +110,17 @@ struct ReflectiveMaterial: Material { struct PortalMaterial: Material { void trace(const Scene& scene, const Hit& hit, const Ray& ray, const std::vector<Light*>& lights, int depth, vec3& outRadiance) override; + inline static vec3 rodrigues(const vec3& v, const vec3& normal, const float& theta){ + return v * cos(theta) + cross(normal, v)*sin(theta)+normal*dot(normal, v)*(1-cos(theta)); + } }; struct Hit { float t = -1; vec3 position, normal; Material* material = nullptr; + + vec3 origo; }; struct Ray { @@ -260,6 +265,7 @@ struct Pentagon : public Intersectable { hit.normal = n; hit.material = material; hit.position = p; + hit.origo = (r1 + r2 + r3 + r4 + r5) / 5.0; if ( distance(r1, r2, p) > 0.1 && @@ -345,7 +351,6 @@ public: vec3 kappa(3.1, 2.7, 1.9); Material* gold = new ReflectiveMaterial(n, kappa); objects.push_back(new Chips(gold)); - //objects.push_back(new Pentagon(vec3(0.03, -.01, 0), vec3(0, .37, 0), vec3(-.47, .49, 0), vec3(-.73, .08, 0), vec3(-.414, -0.288, 0), dodekaMat)); vec3 kd(0.3f, 0.3f, .3f), ks(2, 2, 2); Material* dodekaMat = new RoughMaterial(kd, ks, 50); @@ -440,7 +445,16 @@ void PortalMaterial::trace(const Scene& scene, const Hit& hit, const Ray& ray, c vec3 reflectedDir = ray.dir - hit.normal * dot(hit.normal, ray.dir) * 2.0f; auto theta = (2.0 * M_PI) * (72.0 / 360.0); - outRadiance = outRadiance + scene.trace(Ray(hit.position + hit.normal * epsilon, reflectedDir), depth + 1); + reflectedDir = PortalMaterial::rodrigues(reflectedDir, hit.normal, theta); + + const vec3& mid = hit.origo; + + vec3 pos = hit.position - mid; + pos = PortalMaterial::rodrigues(pos, hit.normal, theta); + pos = pos + mid; + + + outRadiance = outRadiance + scene.trace(Ray(pos + hit.normal * epsilon, reflectedDir), depth + 1); } GPUProgram gpuProgram; // vertex and fragment shaders