void OctTreeNode::remove(OctTreeObject *object, const AxisAlignedBoundingBox &aabb, int iteration) { if (iteration == max_iterations) { objects.erase(std::find(objects.begin(), objects.end(), object)); object->release(); } else { for (int i = 0; i < 8; i++) { AxisAlignedBoundingBox child_box = child_aabb(i, aabb); if (IntersectionTest::aabb(object->box, child_box) == IntersectionTest::overlap) { children[i]->remove(object, child_box, iteration + 1); bool empty = children[i]->objects.empty(); for (int j = 0; j < 8; j++) empty = empty && children[i]->children[j] == 0; if (empty) { delete children[i]; children[i] = 0; } } } } }
void OctTreeNode::cull(int frame, const Vec3f &point, const AxisAlignedBoundingBox &aabb, std::vector<SceneItem *> &pvs) { bool inside = point.x >= aabb.aabb_min.x && point.x <= aabb.aabb_max.x && point.y >= aabb.aabb_min.y && point.y <= aabb.aabb_max.y && point.z >= aabb.aabb_min.z && point.z <= aabb.aabb_max.z; if (inside) { for (size_t i = 0; i < objects.size(); i++) { bool obj_inside = point.x >= objects[i]->box.aabb_min.x && point.x <= objects[i]->box.aabb_max.x && point.y >= objects[i]->box.aabb_min.y && point.y <= objects[i]->box.aabb_max.y && point.z >= objects[i]->box.aabb_min.z && point.z <= objects[i]->box.aabb_max.z; if (obj_inside) objects[i]->add(frame, pvs); } for (int i = 0; i < 8; i++) { if (children[i]) children[i]->cull(frame, point, child_aabb(i, aabb), pvs); } } }
void sprite_aabb(struct sprite *s, struct srt *srt, int aabb[4]) { int i; if (s->visible) { aabb[0] = INT_MAX; aabb[1] = INT_MAX; aabb[2] = INT_MIN; aabb[3] = INT_MIN; child_aabb(s,srt,NULL,aabb); for (i=0;i<4;i++) aabb[i] /= SCREEN_SCALE; } else { for (i=0;i<4;i++) aabb[i] = 0; } }
static int child_aabb(struct sprite *s, struct srt *srt, struct matrix * mat, int aabb[4]) { struct matrix temp; struct matrix *t = mat_mul(s->t.mat, mat, &temp); switch (s->type) { case TYPE_PICTURE: quad_aabb(s->s.pic, srt, t, aabb); return 0; case TYPE_POLYGON: polygon_aabb(s->s.poly, srt, t, aabb); return 0; case TYPE_LABEL: label_aabb(s->s.label, srt, t, aabb); return 0; case TYPE_ANIMATION: break; case TYPE_PANNEL: panel_aabb(s->s.pannel, srt, t, aabb); return s->data.scissor; default: // todo : invalid type return 0; } // draw animation struct pack_animation *ani = s->s.ani; int frame = real_frame(s) + s->start_frame; struct pack_frame * pf = &ani->frame[frame]; int i; for (i=0;i<pf->n;i++) { struct pack_part *pp = &pf->part[i]; int index = pp->component_id; struct sprite * child = s->data.children[index]; if (child == NULL || child->visible == false) { continue; } struct matrix temp2; struct matrix *ct = mat_mul(pp->t.mat, t, &temp2); if (child_aabb(child, srt, ct, aabb)) break; } return 0; }
void OctTreeNode::insert(OctTreeObject *object, const AxisAlignedBoundingBox &aabb, int iteration) { if (iteration == max_iterations) { objects.push_back(object); object->add_ref(); } else { for (int i = 0; i < 8; i++) { AxisAlignedBoundingBox child_box = child_aabb(i, aabb); if (IntersectionTest::aabb(object->box, child_box) == IntersectionTest::overlap) { if (children[i] == 0) children[i] = new OctTreeNode(); children[i]->insert(object, child_box, iteration + 1); } } } }
void sprite_aabb(struct sprite *s, struct srt *srt, bool world_aabb, int aabb[4]) { int i; if (s->visible) { struct matrix tmp; if (world_aabb) { sprite_matrix(s, &tmp); } else { matrix_identity(&tmp); } aabb[0] = INT_MAX; aabb[1] = INT_MAX; aabb[2] = INT_MIN; aabb[3] = INT_MIN; child_aabb(s,srt,&tmp,aabb); for (i=0;i<4;i++) aabb[i] /= SCREEN_SCALE; } else { for (i=0;i<4;i++) aabb[i] = 0; } }
void OctTreeNode::cull(int frame, const FrustumPlanes &frustum, const AxisAlignedBoundingBox &aabb, std::vector<SceneItem *> &pvs) { IntersectionTest::Result result = IntersectionTest::frustum_aabb(frustum, aabb); if (result == IntersectionTest::inside) { show(frame, pvs); } else if (result == IntersectionTest::intersecting) { for (size_t i = 0; i < objects.size(); i++) { if (IntersectionTest::aabb(objects[i]->box, aabb) == IntersectionTest::overlap) objects[i]->add(frame, pvs); } for (int i = 0; i < 8; i++) { if (children[i]) children[i]->cull(frame, frustum, child_aabb(i, aabb), pvs); } } }