/* * photonkdtree.C : implementation of specific kdtree for photonmaps */ #include "photonkdtree.H" class Cnormalquery { public: CIrrPhoton *photon; float* point; VECTOR normal; float threshold; float maxdist; }; static Cnormalquery qdat_s; // Distance calculation COPY FROM kdtree.C ! inline static float SqrDistance3D(float *a, float *b) { float result,tmp; tmp = *(a++) - *(b++); result = tmp*tmp; // result = *ptmp++ tmp = *(a++) - *(b++); result += tmp*tmp; tmp = *a - *b; result += tmp*tmp; return result; } void CPhotonkdtree::NormalBQuery_rec(const int index) { const Cbkdnode &node=m_broot[index]; int discr = node.Discriminator(); float dist; int nearIndex, farIndex; // Recursive call to the child nodes // Test discr (reuse dist) if(index < m_firstLeaf) { dist = ((float *)node.m_data)[discr] - (qdat_s.point)[discr]; if( dist >= 0.0 ) // qdat_s.point[discr] <= ((float *)node->m_data)[discr] { nearIndex = (index << 1) + 1; //node->loson; farIndex = nearIndex+1; //node->hison; } else { farIndex = (index << 1) + 1;//node->loson; nearIndex = farIndex+1;//node->hison; } // Always call near node recursively if(nearIndex < m_numBalanced) { NormalBQuery_rec(nearIndex); } dist *= dist; // Square distance to the separator plane if((farIndex < m_numBalanced) && (dist < qdat_s.maxdist)) { // Discriminator line closer than maxdist : nearer points can lie // on the far side. Or there are still not enough nodes found NormalBQuery_rec(farIndex); } } // if(!(node->m_flags & qdat_s.excludeFlags)) { dist = SqrDistance3D((float *)node.m_data, qdat_s.point); if(dist < qdat_s.maxdist) { // Normal constraint if((((CIrrPhoton *)node.m_data)->Normal() & qdat_s.normal) > qdat_s.threshold) { // Replace point if distance < maxdist AND normal is similar qdat_s.maxdist = dist; qdat_s.photon = (CIrrPhoton *)node.m_data; } } } } CIrrPhoton* CPhotonkdtree::NormalPhotonQuery(VECTOR *pos, VECTOR *normal, float threshold, float maxR2) { // Fill qdat_s qdat_s.photon = NULL; qdat_s.normal = *normal; qdat_s.point = (float *)pos; qdat_s.threshold = threshold; qdat_s.maxdist = maxR2; if(m_broot && (m_numNodes > 0) && (m_numUnbalanced == 0)) { // Find the best photon NormalBQuery_rec(0); } return qdat_s.photon; }