00001
00028 #ifndef NODEWRAPPER_H_
00029 #define NODEWRAPPER_H_
00030 #include"LeafNode.h"
00031 #include"ClusterNode.h"
00032 #include"Box3d.h"
00033 #include"Point3.h"
00034 #include<math.h>
00035 class NodeWrapper :public Box3d{
00036 public:
00037 static const int CONE_RECURSE_SIZE;
00038 static const double GLOBAL_SCENE_DIAGONAL;
00039
00040 private:
00041
00042 AbstractNode & light;
00043 Box3d direction;
00044 double coneCosine;
00045 Point3 location;
00046 Point3 coneDirection;
00047 const int descendents;
00048 vector<ClusterNode *> coneClusters;
00049 const bool cleanLight;
00050 NodeWrapper * _l, *_r;
00051
00052 public:
00056 NodeWrapper(LeafNode & inNode):light(inNode),location(0),coneDirection(0),descendents(1),cleanLight(false){
00057 setBox(inNode.getPoint());
00058 direction.setBox(inNode.getDirection());
00059 coneCosine=1.0f;
00060 coneDirection.set(inNode.getDirection());
00061 location.set(getMin());
00062 location.add(getMax());
00063 location.scale(0.5f);
00064 _l=_r=NULL;
00065 }
00069 NodeWrapper(NodeWrapper & pLeft, NodeWrapper & pRight, vector<double> * coordArr, vector<ClusterNode*> & tempClusterArr)
00070 :light(*(new ClusterNode())),
00071 location(0),coneDirection(0), descendents(pLeft.descendents + pRight.descendents), cleanLight(true){
00072 NodeWrapper * l = &pLeft, *r = &pRight;
00073 if( (pLeft.location.getX() > pRight.location.getX()) ||
00074 ( (pLeft.location.getX()==pRight.location.getX()) && (pLeft.location.getY() > pRight.location.getY()) ) ||
00075 ( (pLeft.location.getX()==pRight.location.getX()) && (pLeft.location.getY() == pRight.location.getY()) && (pLeft.location.getZ() > pRight.location.getZ()) )
00076 ){
00077 l = &pRight;
00078 r = &pLeft;
00079
00080 }
00081 addBox(*r);
00082 addBox(*l);
00083 location.set(max);
00084 location.add(min);
00085 location.scale(0.5);
00086 ((ClusterNode&)light).setBox(min, max);
00087 ((ClusterNode&)light).setChildren(&l->light, &r->light, ((double) rand())/numeric_limits<double>::max());
00088 coneCosine = computeCone(*l,*r,((ClusterNode&)light));
00089 if(coneCosine>-0.9f){
00090 direction.addBox(l->direction);
00091 direction.addBox(r->direction);
00092 ((ClusterNode&)light).findConeDirsRecursive(coordArr,tempClusterArr);
00093 int numClus=0;
00094 for(; tempClusterArr[numClus]!=NULL;numClus++){
00095 }
00096 if(numClus>0){
00097 this->coneClusters.resize(numClus);
00098 for(int j=0;j<numClus;j++){
00099 coneClusters[j]=tempClusterArr[j];
00100 tempClusterArr[j]=NULL;
00101 }
00102 }
00103 }
00104 _l=l;
00105 _r=r;
00106
00107 }
00111 ~NodeWrapper(){
00112 if(cleanLight){
00113
00114 delete (ClusterNode*)(&light);
00115 }
00116 }
00117
00121 static double computeCone(const NodeWrapper & a, const NodeWrapper & b, ClusterNode & cluster){
00122 if(a.direction.isInitialized()==false || b.direction.isInitialized()==false)
00123 return -1.0f;
00124 Point3 min(a.direction.getMin());
00125 min.setIfMin(b.direction.getMin());
00126 Point3 max(a.direction.getMax());
00127 max.setIfMax(b.direction.getMax());
00128 Point3 temp(max);
00129 temp.sub(min);
00130 double radiusSq = temp.getLen();
00131 temp.set(max);
00132 temp.add(min);
00133 double centerSq = temp.getLen();
00134 if(centerSq <0.01){
00135 return -1.0f;
00136 }
00137 double invLen = 1.0f/sqrt(centerSq);
00138 double minCos = (centerSq+4.0f - radiusSq)*0.25f * invLen;
00139 if(minCos < -1.0f){
00140 minCos = -1.0f;
00141 }
00142 temp.scale(invLen);
00143 cluster.setDirectionCone(temp.getX(),temp.getY(),temp.getZ(),minCos);
00144 return minCos;
00145 }
00149 static double computeCone(const NodeWrapper & a, const NodeWrapper & b){
00150 if(a.direction.isInitialized()==false || b.direction.isInitialized()==false)
00151 return -1.0f;
00152 Point3 min(a.direction.getMin());
00153 min.setIfMin(b.direction.getMin());
00154 Point3 max(a.direction.getMax());
00155 max.setIfMax(b.direction.getMax());
00156 Point3 temp(max);
00157 temp.sub(min);
00158 double radiusSq = temp.getLen();
00159 temp.set(max);
00160 temp.add(min);
00161 double centerSq = temp.getLen();
00162 if(centerSq <0.01){
00163 return -1.0f;
00164 }
00165 double invLen = 1.0f/sqrt(centerSq);
00166 double minCos = (centerSq+4.0f - radiusSq)*0.25f * invLen;
00167 if(minCos < -1.0f){
00168 minCos = -1.0f;
00169 }
00170 temp.scale(invLen);
00171 return minCos;
00172 }
00176 AbstractNode & getLight()const {
00177 return light;
00178 }
00182 double getLocationX()const {
00183 return location.getX();
00184 }
00185 double getLocationY()const{
00186 return location.getY();
00187 }
00188
00189 double getLocationZ()const{
00190 return location.getZ();
00191 }
00192 double getConeCosine()const{
00193 return coneCosine;
00194 }
00195 double getHalfSizeX()const{
00196 return max.getX()-location.getX();
00197 }
00198 double getHalfSizeY()const{
00199 return max.getY()-location.getY();
00200 }
00201 double getHalfSizeZ()const{
00202 return max.getZ()-location.getZ();
00203 }
00207 const Point3 & getLocation()const {
00208 return location;
00209 }
00213 bool equals(const NodeWrapper & other){
00214 bool retVal=true;
00215 if(this->direction.equals(other.direction)==false)
00216 retVal &= false;
00217 if(this->coneCosine != other.coneCosine)
00218 retVal &= false;
00219 if(this->location.equals(other.location)==false)
00220 retVal &= false;
00221 if(this->coneDirection.equals(other.coneDirection)==false)
00222 retVal &= false;
00223 if(this->direction.equals(other.direction)==false)
00224 retVal &= false;
00225
00226 return retVal;
00227 }
00232 static double potentialClusterSize(const NodeWrapper &a, NodeWrapper &b) {
00233 Point3 max(a.max);
00234 max.setIfMax(b.max);
00235 Point3 min(a.min);
00236 min.setIfMin(b.min);
00237 Point3 diff(max);
00238 diff.sub(min);
00239 double minCos = computeCone(a, b);
00240 double maxIntensity = a.light.getScalarTotalIntensity() + b.light.getScalarTotalIntensity();
00241 return clusterSizeMetric(diff, minCos, maxIntensity);
00242 }
00243
00247 static double clusterSizeMetric(Point3 & size, double cosSemiAngle, double intensity) {
00248 double len2 = size.getLen();
00249 double angleFactor = (1 - cosSemiAngle) * GLOBAL_SCENE_DIAGONAL;
00250 double res = intensity * (len2 + angleFactor * angleFactor);
00251
00252 return res;
00253 }
00257 friend ostream& operator<<(ostream& s, const NodeWrapper & node);
00258
00259 };
00260 const int NodeWrapper::CONE_RECURSE_SIZE=4;
00261 const double NodeWrapper::GLOBAL_SCENE_DIAGONAL = 2.0;
00262
00266 ostream& operator<<(ostream& s, const NodeWrapper & node){
00267 s<<"NW::["<<node.location<<"] ConeClus :: ";
00268 for(unsigned int i=0;i<node.coneClusters.size();i++){
00269 if(node.coneClusters[i]!=NULL)
00270 s<<""<< (*node.coneClusters[i])<<",";
00271 }
00272 if(node._l!=NULL)
00273 s<<"{LEFT "<<*node._l<<"}";
00274 if(node._r!=NULL)
00275 s<<"{RIGHT "<<*node._r<<"}";
00276 s<<endl;
00277 return s;
00278 }
00279 #endif