void SWDynamicTree2D::query( tarray<tuint>& result, const taabb2d& aabb ) const { result.clear(); tlist<tuint> suspects; suspects.push_back( m_rootID ); while ( suspects.size() > 0 ) { tuint nodeID = suspects.front(); suspects.pop_front(); if ( nodeID == nullID ) continue; const TreeNode& node = m_nodes[ nodeID ]; if ( node.aabb.collide( aabb ) ) { if ( node.isLeaf() ) { result.push_back( nodeID ); } else { suspects.push_back( node.childID[0] ); suspects.push_back( node.childID[1] ); } } } }
int PreprocessOccluders(const tmatrix &invCameraMat) { if (!GetInstancesCount(ZOccluderBox)) return 0; PROFILER_START(PreprocessOccluders); tvector3 campos = invCameraMat.V4.position; tvector3 camdir = invCameraMat.V4.dir; FActiveOccluder* pActiveOccluder = &gActiveOccluders[0]; tvector4 viewPoint = vector4(campos.x, campos.y, campos.z, 0); tvector4 viewDir = vector4(camdir.x, camdir.y, camdir.z, 0); float sqrFar = 1000.0f * 1000.0f; float sqrDist; int i; gNbActiveOccluders = 0; gOccluderBoxes.clear(); ZOccluderBox *pocc = (ZOccluderBox*)FirstInstanceOf(ZOccluderBox); while (pocc) { addDynamicOccluder(pocc->GetTransform()); pocc = (ZOccluderBox*)NI(pocc); } for (unsigned int ju = 0;ju<gOccluderBoxes.size(); ju++) { // todo : frustum culling of the occluder (except far plane) // todo : compute solid angle to reorder occluder accordingly FOccluderBox *obox = &gOccluderBoxes[ju]; //= oboxiter.Get(); // check for far plane const tvector3 &oboxcenter = obox->mCenter;//pocc->GetTransform()->GetWorldMatrix().position; sqrDist= SquaredDistance(viewPoint, oboxcenter); if (sqrDist > sqrFar) { continue; } // check for near plane if (DotProduct(tvector3(viewDir), tvector3(oboxcenter - viewPoint)) < 0.0f) { continue; } // select planes of the occluder box that lies on the viewing direction // todo : reduce to 3 planes instead of 6 (due to box symetry) float invSqrDist = 1.0f/sqrDist;//Rcp(sqrDist); pActiveOccluder->mSolidAngle = 0.0f; BoxSilhouette silhouette; silhouette.vertices = &obox->mVertex[0]; for (i=0; i<6; i++) { tvector4 dir= obox->mVertex[FaceVertexIndex[i][0]]; dir -= viewPoint; float vdotp = silhouette.dots[i] = DotProduct(obox->mPlanes[i], dir); // compute the maximum solidAngle of the box : -area * v.p/d.d pActiveOccluder->mSolidAngle = Max(-obox->mVertex[i].w * vdotp * invSqrDist, pActiveOccluder->mSolidAngle); } // exit if the occluder is not relevant enough if (pActiveOccluder->mSolidAngle < gMinSolidAngle) continue; int nPlanes = 0; tvector4* pPlanes = &pActiveOccluder->mPlanes[0]; // find silhouette tvector4 vertices[12]; int nVertices = silhouette.findSilhouette(vertices); // create a plane with a edge of the occluder and the viewpoint for (i=0; i<nVertices; i+=2) { //tplane plan(campos, vertices[i], vertices[i+1]); tvector3 v1 = vertices[i]; v1 -= viewPoint; tvector3 v2 = vertices[i+1]; v2 -= viewPoint; v1.Normalize(); v2.Normalize(); *pPlanes = CrossProduct(v1, v2); pPlanes->Normalize(); pPlanes->w = - DotProduct(*pPlanes, vertices[i]); pPlanes++; nPlanes ++; } if (gAddNearPlane) { for (int i=0; i<6; i++) { if (silhouette.dots[i] < 0.0f) { pActiveOccluder->mPlanes[nPlanes] = obox->mPlanes[i]; nPlanes++; } } } pActiveOccluder->mNbPlanes = nPlanes; pActiveOccluder++; gNbActiveOccluders++; if (gNbActiveOccluders >= gMaxCandidateOccluders) break; } if (gNbActiveOccluders) { qsort(gActiveOccluders, gNbActiveOccluders, sizeof(FActiveOccluder), compareOccluder); if (gNbActiveOccluders > gMaxActiveOccluders) gNbActiveOccluders = gMaxActiveOccluders; } PROFILER_END(); return gNbActiveOccluders; }