void csBSPTree::Build (csTriangle* triangles, csPlane3* planes, size_t num_triangles, const csVector3* vertices, const csArray<int>& triidx) { CS_ASSERT (triidx.GetSize () > 0); if (triidx.GetSize () == 1) { splitters.Push (triidx[0]); return; } size_t idx = FindBestSplitter (triangles, planes, num_triangles, vertices, triidx); CS_ASSERT (idx != (size_t)-1); splitters.Push (triidx[idx]); csArray<int> left; csArray<int> right; size_t i; split_plane = planes[triidx[idx]]; for (i = 0 ; i < triidx.GetSize () ; i++) if (i != idx) { int idxi = triidx[i]; csTriangle& trj = triangles[idxi]; int cla = ClassifyPlane (split_plane, vertices[trj.a]); int clb = ClassifyPlane (split_plane, vertices[trj.b]); int clc = ClassifyPlane (split_plane, vertices[trj.c]); if ((cla == -clb && cla != 0) || (cla == -clc && cla != 0) || (clb == -clc && clb != 0)) { // There is a split. left.Push (idxi); right.Push (idxi); } else { if (cla == -1 || clb == -1 || clc == -1) left.Push (idxi); else if (cla == 1 || clb == 1 || clc == 1) right.Push (idxi); else splitters.Push (idxi); } } if (left.GetSize () > 0) { child1 = TreeNodes()->Alloc (); child1->Build (triangles, planes, num_triangles, vertices, left); } if (right.GetSize () > 0) { child2 = TreeNodes()->Alloc (); child2->Build (triangles, planes, num_triangles, vertices, right); } }
void HQBSPTreeNode::CreateChilds() { this->CalBoundingBox(); if(!FindBestSplitter())//this is leaf node, polygons in list form a convex group { this->tree->numPoly += this->numPoly; return; } frontNode = HQ_NEW HQBSPTreeNode(); backNode = HQ_NEW HQBSPTreeNode(); frontNode->tree = backNode->tree = this->tree; frontNode->parentNode = backNode->parentNode = this; HQPolyListNode *pNode = headNode; //chia danh sách polygon làm 2 nhánh sau và trước mặt splitter while(pNode != NULL) { const HQPolygon3D* poly = pNode->GetPolygon(); HQPlane::Side side = splitter.CheckSide(*poly); switch(side) { case HQPlane::FRONT_PLANE: frontNode->AddPolygon(poly); break; case HQPlane::BACK_PLANE: backNode->AddPolygon(poly); break; case HQPlane::IN_PLANE://nằm trên mặt splitter { hq_float32 dot = splitter.N * poly->GetPlane().N; if(dot >= 0.0f)//pháp vector polygon cùng hướng với pháp vector của splitter frontNode->AddPolygon(poly); else backNode->AddPolygon(poly); } break; case HQPlane::BOTH_SIDE://cắt splitter { #ifdef HQ_EXPLICIT_ALIGN HQ_DECL_STACK_VAR_ARRAY(HQPolygon3D, polys, 2); HQPolygon3D &front = polys[0]; HQPolygon3D &back = polys[1]; #else HQPolygon3D front,back; #endif poly->Clip(splitter , &front, &back);//chia polygon làm 2 polygon phía sau và trước splitter backNode->AddPolygon(&back); frontNode->AddPolygon(&front); } break; } pNode = pNode->pNext; } this->ClearPolyList(); frontNode->CreateChilds(); backNode->CreateChilds(); }