#pragma once #include "Intersectable.hpp" #include "SquareLight.hpp" class PlaneXAligned : public Intersectable { // const Material* material; float position; bool positiveFacing; public: float yMin, yMax, zMin, zMax; public: PlaneXAligned(std::istream& isc, Material** materialTable, int nMaterials) { material = &Material::DIFFUSEWHITE; position = 0.0f; yMin = zMin = -100.0f; yMax = zMax = 100.0f; positiveFacing = true; char key[200]; do { isc >> key; if(strcmp(key,"x") == 0) isc >> position; else if(strcmp(key,"facing") == 0) { isc >> key; if(strcmp(key,"positive") == 0) positiveFacing = true; else positiveFacing = false; } else if(strcmp(key,"y") == 0) { isc >> yMin; isc >> yMax; } else if(strcmp(key,"z") == 0) { isc >> zMin; isc >> zMax; } else if(strcmp(key,"material") == 0) { isc >> key; for(int i=0; i < nMaterials; i++) { material = materialTable[i]; if(strcmp(key, material->getName()) == 0) break; } } }while(strcmp(key,"end") != 0); bbox.minPoint.x = bbox.maxPoint.x = position; bbox.maxPoint.y = yMax; bbox.maxPoint.z = zMax; bbox.minPoint.y = yMin; bbox.minPoint.z = zMin; } PlaneXAligned(const float position, const bool positiveFacing, const Material* material) { this->material = material; this->position = position; this->positiveFacing = positiveFacing; bbox.minPoint.x = bbox.maxPoint.x = position; bbox.maxPoint.y = bbox.maxPoint.z = 100.0f; bbox.minPoint.y = bbox.minPoint.z = -100.0f; } bool intersectBackSide(const Ray& ray, float& depth, float rayMin, float rayMax ) { lastTestedRayResult.isIntersect = false; return false; return intersect(ray, depth, rayMin, rayMax); } bool intersect(const Ray& ray, float& depth, float rayMin, float rayMax ) { lastTestedRayId = ray.id; float distx = position - ray.origin.x; if(positiveFacing && distx < 0 && ray.dir.x < 0 || !positiveFacing && distx > 0 && ray.dir.x > 0) { depth = distx / ray.dir.x; lastTestedRayResult.isIntersect = true; lastTestedRayResult.depth = depth; lastTestedRayResult.material = this->material; lastTestedRayResult.normal = positiveFacing?Vector(1.0f, 0.0f, 0.0f):Vector(-1.0f, 0.0f, 0.0f); lastTestedRayResult.point = ray.origin + ray.dir * depth; if(lastTestedRayResult.point.y < yMin || lastTestedRayResult.point.y > yMax || lastTestedRayResult.point.z < zMin || lastTestedRayResult.point.z > zMax) { lastTestedRayResult.isIntersect = false; return false; } lastTestedRayResult.object = this; return true; } lastTestedRayResult.isIntersect = false; return false; } Vector getShadingNormal(const Vector& point) { return positiveFacing?Vector(1.0f, 0.0f, 0.0f):Vector(-1.0f, 0.0f, 0.0f); } Light* makeLight() const { Vector corners[4]; corners[0] = Vector(position, yMin, zMin); corners[positiveFacing?3:1] = Vector(position, yMax, zMin); corners[2] = Vector(position, yMax, zMax); corners[positiveFacing?1:3] = Vector(position, yMin, zMax); return new SquareLight(corners, 4, material->getSurfaceRadiance()); } }; class PlaneYAligned : public Intersectable { // const Material* material; float position; bool positiveFacing; public: float xMin, xMax, zMin, zMax; public: PlaneYAligned(std::istream& isc, Material** materialTable, int nMaterials) { material = &Material::DIFFUSEWHITE; position = 0.0f; xMin = zMin = -100.0f; xMax = zMax = 100.0f; positiveFacing = true; char key[200]; do { isc >> key; if(strcmp(key,"y") == 0) isc >> position; else if(strcmp(key,"facing") == 0) { isc >> key; if(strcmp(key,"positive") == 0) positiveFacing = true; else positiveFacing = false; } else if(strcmp(key,"x") == 0) { isc >> xMin; isc >> xMax; } else if(strcmp(key,"z") == 0) { isc >> zMin; isc >> zMax; } else if(strcmp(key,"material") == 0) { isc >> key; for(int i=0; i < nMaterials; i++) { material = materialTable[i]; if(strcmp(key, material->getName()) == 0) break; } } }while(strcmp(key,"end") != 0); bbox.minPoint.y = bbox.maxPoint.y = position; bbox.maxPoint.x = xMax; bbox.maxPoint.z = zMax; bbox.minPoint.x = xMin; bbox.minPoint.z = zMin; } PlaneYAligned(const float position, const bool positiveFacing, const Material* material) { this->material = material; this->position = position; this->positiveFacing = positiveFacing; bbox.minPoint.y = bbox.maxPoint.y = position; bbox.maxPoint.x = bbox.maxPoint.z = 100.0f; bbox.minPoint.x = bbox.minPoint.z = -100.0f; } bool intersectBackSide(const Ray& ray, float& depth, float rayMin, float rayMax ) { lastTestedRayResult.isIntersect = false; return false; return intersect(ray, depth, rayMin, rayMax); } bool intersect(const Ray& ray, float& depth, float rayMin, float rayMax) { lastTestedRayId = ray.id; float disty = position - ray.origin.y; if(positiveFacing && disty < 0 && ray.dir.y < 0 || !positiveFacing && disty > 0 && ray.dir.y > 0) { depth = disty / ray.dir.y; lastTestedRayResult.isIntersect = true; lastTestedRayResult.depth = depth; lastTestedRayResult.material = this->material; lastTestedRayResult.normal = positiveFacing?Vector(0.0f, 1.0f, 0.0f):Vector(0.0f, -1.0f, 0.0f); lastTestedRayResult.point = ray.origin + ray.dir * depth; if(lastTestedRayResult.point.x < xMin || lastTestedRayResult.point.x > xMax || lastTestedRayResult.point.z < zMin || lastTestedRayResult.point.z > zMax) { lastTestedRayResult.isIntersect = false; return false; } lastTestedRayResult.object = this; return true; } lastTestedRayResult.isIntersect = false; return false; } Vector getShadingNormal(const Vector& point) { return positiveFacing?Vector(0.0f, 1.0f, 0.0f):Vector(0.0f, -1.0f, 0.0f); } Light* makeLight() const { Vector corners[4]; corners[0] = Vector(xMin, position, zMin); corners[positiveFacing?1:3] = Vector(xMax, position, zMin); corners[2] = Vector(xMax, position, zMax); corners[positiveFacing?3:1] = Vector(xMin, position, zMax); return new SquareLight(corners, 4, material->getSurfaceRadiance()); } }; class PlaneZAligned : public Intersectable { // const Material* material; float position; bool positiveFacing; public: float xMin, xMax, yMin, yMax; public: PlaneZAligned(std::istream& isc, Material** materialTable, int nMaterials) { material = &Material::DIFFUSEWHITE; position = 0.0f; yMin = xMin = -100.0f; yMax = xMax = 100.0f; positiveFacing = true; char key[200]; do { isc >> key; if(strcmp(key,"z") == 0) isc >> position; else if(strcmp(key,"facing") == 0) { isc >> key; if(strcmp(key,"positive") == 0) positiveFacing = true; else positiveFacing = false; } else if(strcmp(key,"y") == 0) { isc >> yMin; isc >> yMax; } else if(strcmp(key,"x") == 0) { isc >> xMin; isc >> xMax; } else if(strcmp(key,"material") == 0) { isc >> key; for(int i=0; i < nMaterials; i++) { material = materialTable[i]; if(strcmp(key, material->getName()) == 0) break; } } }while(strcmp(key,"end") != 0); bbox.minPoint.z = bbox.maxPoint.z = position; bbox.maxPoint.y = yMax; bbox.maxPoint.x = xMax; bbox.minPoint.y = yMin; bbox.minPoint.x = xMin; } PlaneZAligned(const float position, const bool positiveFacing, const Material* material) { this->material = material; this->position = position; this->positiveFacing = positiveFacing; bbox.minPoint.z = bbox.maxPoint.z = position; bbox.maxPoint.y = bbox.maxPoint.x = 100.0f; bbox.minPoint.y = bbox.minPoint.x = -100.0f; } bool intersectBackSide(const Ray& ray, float& depth, float rayMin, float rayMax ) { lastTestedRayResult.isIntersect = false; return false; return intersect(ray, depth, rayMin, rayMax); } bool intersect(const Ray& ray, float& depth, float rayMin, float rayMax) { lastTestedRayId = ray.id; float distz = position - ray.origin.z; if(positiveFacing && distz < 0 && ray.dir.z < 0 || !positiveFacing && distz > 0 && ray.dir.z > 0) { depth = distz / ray.dir.z; lastTestedRayResult.isIntersect = true; lastTestedRayResult.depth = depth; lastTestedRayResult.material = this->material; lastTestedRayResult.normal = positiveFacing?Vector(0.0f, 0.0f, 1.0f):Vector(0.0f, 0.0f, -1.0f); lastTestedRayResult.point = ray.origin + ray.dir * depth; if(lastTestedRayResult.point.x < xMin || lastTestedRayResult.point.x > xMax || lastTestedRayResult.point.y < yMin || lastTestedRayResult.point.y > yMax) { lastTestedRayResult.isIntersect = false; return false; } lastTestedRayResult.object = this; return true; } lastTestedRayResult.isIntersect = false; return false; } Vector getShadingNormal(const Vector& point) { return positiveFacing?Vector(0.0f, 0.0f, 1.0f):Vector(0.0f, 0.0f, -1.0f); } Light* makeLight() const { Vector corners[4]; corners[0] = Vector(xMin, yMin, position); corners[positiveFacing?3:1] = Vector(xMax, yMin, position); corners[2] = Vector(xMax, yMax, position); corners[positiveFacing?1:3] = Vector(xMin, yMax, position); return new SquareLight(corners, 4, material->getSurfaceRadiance()); } };