00001 #include "vuNormalTable.h" 00002 00010 class BList 00011 { 00012 public: 00014 vuNormalBlock* m_data; 00016 BList* m_next; 00017 }; 00018 00019 vuNormalTable::vuNormalTable() 00020 { 00021 m_Table = new float[768]; 00022 m_Block = 0; 00023 m_Size = 0; 00024 } 00025 00026 vuNormalTable::vuNormalTable(const vuNormalTable& inst) 00027 { 00028 dword i; 00029 00030 m_Table = new float[768]; 00031 for(i=0;i<768;++i) 00032 m_Table[i] = inst.m_Table[i]; 00033 00034 m_Block = new vuNormalBlock; 00035 *m_Block = *inst.m_Block; 00036 00037 m_Size = inst.m_Size; 00038 } 00039 00040 vuNormalTable::~vuNormalTable() 00041 { 00042 if (m_Table) 00043 delete [] m_Table; 00044 if (m_Block) 00045 delete [] m_Block; 00046 } 00047 00048 void vuNormalTable::setCollection(const float* n, dword size) 00049 { 00050 dword i; 00051 00052 if (m_Block) 00053 delete [] m_Block; 00054 m_Block = new vuNormalBlock; 00055 m_Block->setSize(size); 00056 m_Size = 0; 00057 00058 for(i=0;i<size;++i) 00059 m_Block->addNormal(&n[i*3]); 00060 } 00061 00062 void vuNormalTable::initCollection(dword size) 00063 { 00064 if (m_Block) 00065 delete [] m_Block; 00066 m_Block = new vuNormalBlock; 00067 m_Block->setSize(size); 00068 m_Size = 0; 00069 } 00070 00071 void vuNormalTable::addToCollection(const float* n) 00072 { 00073 m_Block->addNormal(n); 00074 } 00075 00076 void vuNormalTable::computeTable(void) 00077 { 00078 vuNormalBlock* left; 00079 vuNormalBlock* right; 00080 BList* head; 00081 BList* iter; 00082 BList* split; 00083 bool cansplit; 00084 dword i; 00085 00086 m_Block->computeStats(); 00087 00088 head = new BList; 00089 head->m_data = m_Block; 00090 head->m_next = 0; 00091 m_Block = 0; 00092 00093 // 00094 // Split normals according to groups that are close 00095 // together (using range and standard deviation). 00096 // 00097 m_Size = 1; 00098 cansplit = true; 00099 while((m_Size<256) && cansplit) 00100 { 00101 split = head; 00102 iter = head->m_next; 00103 while(iter != 0) 00104 { 00105 if (iter->m_data->getRange() > split->m_data->getRange()) 00106 split = iter; 00107 else if (iter->m_data->getRange() == split->m_data->getRange()) 00108 { 00109 if (iter->m_data->getStdDev() > split->m_data->getStdDev()) 00110 split = iter; 00111 } 00112 iter = iter->m_next; 00113 } 00114 left = new vuNormalBlock; 00115 right = new vuNormalBlock; 00116 if (split->m_data->medianSplit(*left, *right)) 00117 { 00118 delete split->m_data; 00119 split->m_data = left; 00120 iter = split->m_next; 00121 split->m_next = new BList; 00122 split->m_next->m_data = right; 00123 split->m_next->m_next = iter; 00124 ++m_Size; 00125 } 00126 else 00127 { 00128 delete left; 00129 delete right; 00130 cansplit = false; 00131 } 00132 } 00133 00134 // 00135 // Compute the average normal in each group. 00136 // 00137 i = 0; 00138 iter = head->m_next; 00139 while(iter != 0) 00140 { 00141 iter->m_data->computeAverage(&m_Table[i]); 00142 iter = iter->m_next; 00143 i += 3; 00144 } 00145 00146 // 00147 // Destroy the list that we computed. 00148 // 00149 iter = head->m_next; 00150 while(iter != 0) 00151 { 00152 delete iter->m_data; 00153 split = iter; 00154 iter = iter->m_next; 00155 delete split; 00156 } 00157 } 00158 00159 void vuNormalTable::destroyTable(void) 00160 { 00161 if (m_Table) 00162 { 00163 delete [] m_Table; 00164 m_Table = 0; 00165 } 00166 } 00167 00168 dword vuNormalTable::findNearest(const float* n) 00169 { 00170 float d; 00171 float min; 00172 dword index=0; 00173 dword i; 00174 00175 min = 1000000.0f; 00176 for(i=0;i<m_Size*3;i+=3) 00177 { 00178 d = ((n[0]-m_Table[i])*(n[0]-m_Table[i])) + 00179 ((n[1]-m_Table[i+1])*(n[1]-m_Table[i+1])) + 00180 ((n[2]-m_Table[i+2])*(n[2]-m_Table[i+2])); 00181 if (d < min) 00182 { 00183 index = i/3; 00184 min = d; 00185 } 00186 } 00187 00188 return index; 00189 } 00190 00191 vuNormalTable& vuNormalTable::operator=(const vuNormalTable& rhs) 00192 { 00193 if (this != &rhs) 00194 { 00195 dword i; 00196 00197 for(i=0;i<768;++i) 00198 m_Table[i] = rhs.m_Table[i]; 00199 00200 if (m_Block) 00201 delete [] m_Block; 00202 m_Block = new vuNormalBlock; 00203 *m_Block = *rhs.m_Block; 00204 } 00205 return *this; 00206 } 00207 00208 const float* vuNormalTable::operator[](dword index) 00209 { 00210 return &m_Table[index*3]; 00211 }