00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00040 #include "omicron/internal.h"
00041 #include "omicron/list.h"
00042 #include "omicron/octree.h"
00043 #include "omicron/input.h"
00044 #include "omicron/array.h"
00045 #include "omicron/render.h"
00046
00047 #define BIGPOLY 100000
00048
00049 template <class T>
00050 octree_c<T>::octree_c()
00051 {
00052 for (ulong i=0; i<8; i++)
00053 root.subnodes[i] = NULL;
00054
00055 root.data = NULL;
00056 }
00057
00058 template <class T>
00059 octree_c<T>::~octree_c()
00060 {
00061 AssertThis;
00062
00063 for (ulong i=0; i<8; i++)
00064 removenode(root.subnodes[i]);
00065 }
00066
00067 template <class T>
00068 octree_c<T>::node_t<T> *octree_c<T>::create_node(octree_c::node_t<T> *node, ulong num)
00069 {
00070 AssertThisV;
00071
00072 ulong i;
00073 if (!node->subnodes[num])
00074 {
00075 node->subnodes[num] = new octree_c::node_t<T>;
00076
00077 vec3_t size;
00078
00079 vector_subtract(node->max, node->min, size);
00080 vector_scale(size, 0.5, size);
00081
00082 vector_copy(node->min, node->subnodes[num]->min);
00083
00084 for (i=0; i<3; i++)
00085 if (num && (1<<i))
00086 node->subnodes[num]->min[i]+=size[i];
00087
00088 for (i=0; i<8; i++)
00089 node->subnodes[num]->subnodes[i] = NULL;
00090
00091 node->subnodes[num]->data = NULL;
00092
00093 vector_add(node->subnodes[num]->min, size, node->subnodes[num]->max);
00094
00095 for (i=0; i<8; i++)
00096 {
00097 node->subnodes[num]->pts[i][0] =
00098 (i&1)?node->subnodes[num]->max[0]:node->subnodes[num]->min[0];
00099
00100 node->subnodes[num]->pts[i][1] =
00101 (i&2)?node->subnodes[num]->max[1]:node->subnodes[num]->min[1];
00102
00103 node->subnodes[num]->pts[i][2] =
00104 (i&4)?node->subnodes[num]->max[2]:node->subnodes[num]->min[2];
00105 }
00106 }
00107
00108 return node->subnodes[num];
00109 }
00110
00111 template <class T>
00112 slong octree_c<T>::get_subnode_num_vec(octree_c::node_t<T> *node, vec3_t p)
00113 {
00114 AssertThisV;
00115
00116 ulong num = 0;
00117 vec3_t center;
00118
00119 vector_add(node->max, node->min, center);
00120 vector_scale(center, 0.5, center);
00121
00122 for (ulong i=0; i<3; i++)
00123 {
00124 if (p[i]>=center[i])
00125 num |= 1<<i;
00126 }
00127
00128 return num;
00129 }
00130
00131 template <class T>
00132 slong octree_c<T>::get_subnode_num(octree_c::node_t<T> *node, vec3_t mn, vec3_t mx)
00133 {
00134 AssertThisV;
00135
00136 ulong num, lnum, i;
00137 vec3_t pts[8];
00138
00139 for (i=0; i<8; i++)
00140 {
00141 pts[i][0] = (i&1)?mx[0]:mn[0];
00142 pts[i][1] = (i&2)?mx[1]:mn[1];
00143 pts[i][2] = (i&4)?mx[2]:mn[2];
00144 }
00145
00146 lnum = num = getsubnodenumvec(node, pts[0]);
00147
00148 for (i=1; i<8; i++)
00149 {
00150 num = getsubnodenumvec(node, pts[i]);
00151 if (lnum != num)
00152 return -1;
00153 }
00154
00155 return num;
00156 }
00157
00158 template <class T>
00159 void octree_c<T>::add_to_subnode(octree_c::node_t<T> *node, T *d, vec3_t mn, vec3_t mx)
00160 {
00161 AssertThis;
00162
00163 ulong num;
00164
00165 num = getsubnodenum(node, mn, mx);
00166
00167 if (num == -1)
00168 {
00169 if (!node->data)
00170 node->data = new list_c<T>;
00171
00172 node->data->add_first(d);
00173 }
00174 else
00175 {
00176 createnode(node, num);
00177 addtosubnode(node->subnodes[num], d, mn, mx);
00178 }
00179 }
00180
00181 template <class T>
00182 void octree_c<T>::add(T *d, vec3_t mn, vec3_t mx)
00183 {
00184 AssertThis;
00185
00186 add_to_subnode(&root, d, mn, mx);
00187 }
00188
00189 template <class T>
00190 void octree_c<T>::update_view()
00191 {
00192 AssertThis;
00193
00194
00195
00196
00197 vec3_t pts[5];
00198 vec3_t f,r,u;
00199 ulong i;
00200 float rpf;
00201
00202 for (i=0; i<5; i++)
00203 vector_copy(gv.renderer->get_viewpos(), pts[i]);
00204
00205 rpf = ftan(gv.renderer->get_fov()/2)*2500;
00206
00207 vector_scale(gv.renderer->get_viewdir(), 5000, f);
00208 vector_scale(gv.renderer->get_viewright(), rpf, r);
00209 vector_scale(gv.renderer->get_viewup2(), rpf, u);
00210
00211 for (i=1; i<5; i++)
00212 vector_add(pts[i], f, pts[i]);
00213
00214 vector_ma(pts[1], -1, r, pts[1]);
00215 vector_ma(pts[1], -1, u, pts[1]);
00216
00217 vector_ma(pts[2], 1, r, pts[2]);
00218 vector_ma(pts[2], -1, u, pts[2]);
00219
00220 vector_ma(pts[3], 1, r, pts[3]);
00221 vector_ma(pts[3], 1, u, pts[3]);
00222
00223 vector_ma(pts[4], -1, r, pts[4]);
00224 vector_ma(pts[4], 1, u, pts[4]);
00225
00226 vector_set(viewmin, BIGPOLY, BIGPOLY, BIGPOLY);
00227 vector_set(viewmax, -BIGPOLY, -BIGPOLY, -BIGPOLY);
00228
00229 for (i=0; i<5; i++)
00230 for (ulong j=0; j<3; j++)
00231 {
00232 if (pts[i][j]>viewmax[j])
00233 viewmax[j] = pts[i][j];
00234 if (pts[i][j]<viewmin[j])
00235 viewmin[j] = pts[i][j];
00236 }
00237 }
00238
00239
00240
00241
00242 template <class T>
00243 slong octree_c<T>::get_visibility(octree_c::node_t<T> *node)
00244 {
00245 AssertThisV;
00246
00247 ulong visible;
00248 ulong i, j, inside;
00249
00250 if (node == &root)
00251 return 1;
00252
00253 if ((gv.renderer->get_viewpos()[0]>node->min[0] &&
00254 gv.renderer->get_viewpos()[0]<node->max[0]) &&
00255 (gv.renderer->get_viewpos()[1]>node->min[1] &&
00256 gv.renderer->get_viewpos()[1]<node->max[1]) &&
00257 (gv.renderer->get_viewpos()[2]>node->min[2] &&
00258 gv.renderer->get_viewpos()[2]<node->max[2]))
00259 {
00260 return 1;
00261 }
00262
00263 visible = 0;
00264
00265 inside = 1;
00266 for (i=0; i<3; i++)
00267 {
00268 if (node->pts[0][i]>viewmax[i] && node->pts[0][i]<viewmin[i])
00269 inside = 0;
00270 }
00271
00272 for (j=0; j<8; j++)
00273 for (i=0; i<3; i++)
00274 {
00275 if (node->pts[j][i]>viewmax[i] && node->pts[j][i]<viewmin[i])
00276 {
00277 if (inside)
00278 return 1;
00279 }
00280 else
00281 {
00282 if (!inside)
00283 return 1;
00284 }
00285 }
00286
00287 if (inside)
00288 return 2;
00289
00290 return 0;
00291 }
00292
00293 template <class T>
00294 void octree_c<T>::add_complete_node_to_array(octree_c::node_t<T> *node, array_c<T> &list)
00295 {
00296 AssertThis;
00297
00298 ulong i;
00299
00300 if (!node)
00301 return;
00302
00303 if (node->data)
00304 {
00305 ulong c = node->data->getcount();
00306 T *data = node->data->getfirst();
00307
00308 while (data)
00309 {
00310 list.add(data);
00311 data = node->data->getnext();
00312 }
00313 }
00314
00315 for (i=0; i<8; i++)
00316 addcompletenodetolist(node->subnodes[i], list);
00317 }
00318
00319 template <class T>
00320 void octree_c<T>::add_node_to_array(octree_c::node_t<T> *node, array_c<T> &list)
00321 {
00322 AssertThis;
00323
00324 if (!node)
00325 return;
00326
00327 ulong vis = getvisibility(node);
00328
00329 if (!vis)
00330 return;
00331
00332 if (vis==1)
00333 {
00334 if (node->data)
00335 {
00336 T *data = node->data->getfirst();
00337
00338 while (data)
00339 {
00340 list.add(data);
00341 data = node->data->getnext();
00342 }
00343 }
00344
00345 for (ulong i=0; i<8; i++)
00346 addnodetolist(node->subnodes[i], list);
00347
00348 return;
00349 }
00350 addcompletenodetolist(node, list);
00351 }
00352
00353 template <class T>
00354 void octree_c<T>::get_visible(array_c<T> &list)
00355 {
00356 AssertThis;
00357
00358 list.clear();
00359 addnodetolist(&root, list);
00360 }
00361
00362 template <class T>
00363 void octree_c<T>::remove_node(octree_c::node_t<T> *node)
00364 {
00365 AssertThis;
00366
00367 if (!node)
00368 return;
00369
00370 for (ulong i=0; i<8; i++)
00371 removenode(node->subnodes[i]);
00372
00373 SafeDelete(node->data);
00374 SafeDelete(node);
00375 }
00376