#pragma once #include "light.hpp" class SquareLight : public Light { Vector edge1; Vector edge2; public: Vector polyNodes[4]; unsigned int nPolyNodes; SquareLight(Vector* nodes, int nNodes, const Vector& radiance) { if(nNodes < 3) exit(-1); nPolyNodes = nNodes; for(int i=0; idirection.setCrossProduct(b, a); this->direction.normalize(); this->radiance = radiance; luminance = radiance.r + radiance.g + radiance.b; this->position.clear(); for(int c=0; cposition += nodes[c]; this->position *= 1.0f / (float)nNodes; area = sqrt(edge1.norm2() * edge2.norm2()); power = radiance; power *= area; } float getFormFactor(const Vector& lookpoint, const Vector& normal) const { Vector ffxcd, dif[4], cutRemains[5]; ffxcd.clear(); float acc = 0.0f; bool in[4]; for(int iCutter=0; iCutter<4; iCutter++) { dif[iCutter].setDifference(polyNodes[iCutter], lookpoint); dif[iCutter].normalize(); in[iCutter] = (dif[iCutter] * normal > 0.0f); } int nRemain = 0; for(int iGutter=0;iGutter<4;iGutter++) { int ta = iGutter & 3; int tb = (iGutter + 1) & 3; if(in[ta]) { cutRemains[nRemain++] = dif[ta]; if(!in[tb]) { Vector cutEdgePlaneNormal; cutEdgePlaneNormal.setCrossProduct(dif[ta],dif[tb]); cutEdgePlaneNormal.normalize(); cutRemains[nRemain].setCrossProduct(cutEdgePlaneNormal, normal); cutRemains[nRemain++].normalize(); } } else if(in[tb]) { Vector cutEdgePlaneNormal; cutEdgePlaneNormal.setCrossProduct(dif[ta],dif[tb]); cutEdgePlaneNormal.normalize(); cutRemains[nRemain].setCrossProduct(normal, cutEdgePlaneNormal); cutRemains[nRemain++].normalize(); } } if(nRemain == 0) return 0.0f; for(int pir = 0; pir < nRemain; pir++) { Vector rxr; rxr.setCrossProduct(cutRemains[pir], cutRemains[(pir + 1)%nRemain]); float sinb = rxr.norm(); rxr *= 1.0f / sinb; float alfa = asinf(sinb); if(cutRemains[pir] * cutRemains[(pir + 1)%nRemain] < 0.0f) alfa = 3.14f - alfa; rxr *= alfa; // ffxcd += rxr; acc += rxr * normal; } return acc * 0.5f; // return ffxcd * normal * 0.5f; } Vector getSample() const { Vector ret = polyNodes[0]; ret.addScaled(-(float)rand() / RAND_MAX, edge1 ); ret.addScaled(-(float)rand() / RAND_MAX, edge2 ); return ret; } bool isPossiblyVisible(const Vector& point) const { Vector diff; diff.setDifference(point, position); return diff * direction > 0; } };