[896] | 1 | #pragma once
|
---|
| 2 | #include "light.hpp"
|
---|
| 3 |
|
---|
| 4 | class SquareLight :
|
---|
| 5 | public Light
|
---|
| 6 | {
|
---|
| 7 | Vector edge1; |
---|
| 8 | Vector edge2; |
---|
| 9 | public: |
---|
| 10 | Vector polyNodes[4]; |
---|
| 11 | unsigned int nPolyNodes; |
---|
| 12 | |
---|
| 13 | SquareLight(Vector* nodes, int nNodes, const Vector& radiance) |
---|
| 14 | { |
---|
| 15 | if(nNodes < 3) exit(-1); |
---|
| 16 | nPolyNodes = nNodes; |
---|
| 17 | for(int i=0; i<nPolyNodes; i++) |
---|
| 18 | polyNodes[i] = nodes[i]; |
---|
| 19 | Vector a; a.setDifference(nodes[0], nodes[1]); |
---|
| 20 | Vector b; b.setDifference(nodes[0], nodes[2]); |
---|
| 21 | edge1 = a; |
---|
| 22 | edge2.setDifference(nodes[0], nodes[nNodes-1]); |
---|
| 23 | this->direction.setCrossProduct(b, a); |
---|
| 24 | this->direction.normalize(); |
---|
| 25 | this->radiance = radiance; |
---|
| 26 | luminance = radiance.r + radiance.g + radiance.b; |
---|
| 27 | this->position.clear(); |
---|
| 28 | for(int c=0; c<nNodes; c++) |
---|
| 29 | this->position += nodes[c]; |
---|
| 30 | this->position *= 1.0f / (float)nNodes; |
---|
| 31 | |
---|
| 32 | area = sqrt(edge1.norm2() * edge2.norm2()); |
---|
| 33 | power = radiance; |
---|
| 34 | power *= area; |
---|
| 35 | } |
---|
| 36 | float getFormFactor(const Vector& lookpoint, const Vector& normal) const |
---|
| 37 | { |
---|
| 38 | Vector ffxcd, dif[4], cutRemains[5];
|
---|
| 39 | ffxcd.clear();
|
---|
| 40 | float acc = 0.0f;
|
---|
| 41 |
|
---|
| 42 | bool in[4];
|
---|
| 43 | for(int iCutter=0; iCutter<4; iCutter++)
|
---|
| 44 | {
|
---|
| 45 | dif[iCutter].setDifference(polyNodes[iCutter], lookpoint);
|
---|
| 46 | dif[iCutter].normalize();
|
---|
| 47 | in[iCutter] = (dif[iCutter] * normal > 0.0f);
|
---|
| 48 | }
|
---|
| 49 | int nRemain = 0;
|
---|
| 50 | for(int iGutter=0;iGutter<4;iGutter++)
|
---|
| 51 | {
|
---|
| 52 | int ta = iGutter & 3;
|
---|
| 53 | int tb = (iGutter + 1) & 3;
|
---|
| 54 | if(in[ta])
|
---|
| 55 | {
|
---|
| 56 | cutRemains[nRemain++] = dif[ta];
|
---|
| 57 | if(!in[tb])
|
---|
| 58 | {
|
---|
| 59 | Vector cutEdgePlaneNormal;
|
---|
| 60 | cutEdgePlaneNormal.setCrossProduct(dif[ta],dif[tb]);
|
---|
| 61 | cutEdgePlaneNormal.normalize();
|
---|
| 62 | cutRemains[nRemain].setCrossProduct(cutEdgePlaneNormal, normal);
|
---|
| 63 | cutRemains[nRemain++].normalize();
|
---|
| 64 | }
|
---|
| 65 | }
|
---|
| 66 | else
|
---|
| 67 | if(in[tb])
|
---|
| 68 | {
|
---|
| 69 | Vector cutEdgePlaneNormal;
|
---|
| 70 | cutEdgePlaneNormal.setCrossProduct(dif[ta],dif[tb]);
|
---|
| 71 | cutEdgePlaneNormal.normalize();
|
---|
| 72 | cutRemains[nRemain].setCrossProduct(normal, cutEdgePlaneNormal);
|
---|
| 73 | cutRemains[nRemain++].normalize();
|
---|
| 74 | }
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | if(nRemain == 0) return 0.0f;
|
---|
| 78 |
|
---|
| 79 | for(int pir = 0; pir < nRemain; pir++)
|
---|
| 80 | {
|
---|
| 81 | Vector rxr; rxr.setCrossProduct(cutRemains[pir], cutRemains[(pir + 1)%nRemain]);
|
---|
| 82 | float sinb = rxr.norm();
|
---|
| 83 | rxr *= 1.0f / sinb;
|
---|
| 84 | float alfa = asinf(sinb);
|
---|
| 85 | if(cutRemains[pir] * cutRemains[(pir + 1)%nRemain] < 0.0f)
|
---|
| 86 | alfa = 3.14f - alfa;
|
---|
| 87 | rxr *= alfa;
|
---|
| 88 | // ffxcd += rxr;
|
---|
| 89 | acc += rxr * normal;
|
---|
| 90 | }
|
---|
| 91 | return acc * 0.5f;
|
---|
| 92 | // return ffxcd * normal * 0.5f;
|
---|
| 93 | } |
---|
| 94 | Vector getSample() const |
---|
| 95 | { |
---|
| 96 | Vector ret = polyNodes[0]; |
---|
| 97 | ret.addScaled(-(float)rand() / RAND_MAX, edge1 ); |
---|
| 98 | ret.addScaled(-(float)rand() / RAND_MAX, edge2 ); |
---|
| 99 | return ret; |
---|
| 100 | }
|
---|
| 101 | bool isPossiblyVisible(const Vector& point) const
|
---|
| 102 | {
|
---|
| 103 | Vector diff; diff.setDifference(point, position);
|
---|
| 104 | return diff * direction > 0;
|
---|
| 105 | }
|
---|
| 106 | };
|
---|