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] ); } } } }
void SWGameScene::draw() { static tarray<tuint> proxyIDs; for ( SWObject::Array::iterator itor = m_renderers.begin() ; itor != m_renderers.end() ; ++itor) { taabb3d aabb; SWRenderer* renderer = (SWRenderer*)((*itor)()); renderer->computeAABB(aabb); m_rendererTree.updateProxy(renderer->getProxyID(), aabb); } /* */ m_cameras.sort( CameraSorter() ); SWObject::List::iterator itor = m_cameras.begin(); for ( ; itor != m_cameras.end() ; ++itor ) { SWCamera* camera = swrtti_cast<SWCamera>( (*itor)() ); tflag32 cullingMask = camera->getCullingMask(); //! get clear mask int clearMask = GL_NONE; int clearFlags = camera->getClearFlags(); if ( clearFlags & SW_Clear_Color ) clearMask |= GL_COLOR_BUFFER_BIT; if ( clearFlags & SW_Clear_Depth ) clearMask |= GL_DEPTH_BUFFER_BIT; //! clear buffer if ( clearMask != GL_NONE ) { tcolor color = camera->getClearColor(); glClearColor( color.r, color.g, color.b, color.a ); glClearDepth( camera->getClearDepth() ); glClear( clearMask ); } taabb3d frustrumAABB; camera->computeFrustrumAABB(frustrumAABB); m_rendererTree.query(proxyIDs, frustrumAABB); for (int i = 0 ; i <proxyIDs.size() ; ++i) { tuint proxyID = proxyIDs[i]; SWRenderer* renderer = (SWRenderer*)m_rendererTree.getUserData(proxyID); tuint layerMask = renderer->gameObject()->getLayer(); if (cullingMask.get(layerMask)) renderer->render(camera); } } onPostDraw(); }
void addDynamicOccluder(ZTransform* aTransform) { int i; FOccluderBox obox; tvector3 extend(1,1,1); const tmatrix& boxmat = aTransform->GetWorldMatrix(); for (i=0; i<8; i++) { tvector3 bvt(BoxCorners[i].x, BoxCorners[i].y, BoxCorners[i].z),bvt2; bvt2.TransformPoint((bvt*extend), boxmat); obox.mVertex[i] = vector4(bvt2.x, bvt2.y, bvt2.z, 0); } for (i=0; i<6; i++) { tvector3 cross = obox.mVertex[FaceVertexIndex[i][1]]; cross -= obox.mVertex[FaceVertexIndex[i][0]]; tvector3 cr2 = obox.mVertex[FaceVertexIndex[i][2]]; cr2 -= obox.mVertex[FaceVertexIndex[i][0]]; cross.Cross(cr2); obox.mPlanes[i] = vector4(cross.x, cross.y, cross.z, 0); obox.mPlanes[i].Normalize(); obox.mPlanes[i].w = -DotProduct(obox.mPlanes[i], obox.mVertex[FaceVertexIndex[i][0]]); obox.mVertex[i].w = fabs(obox.mPlanes[i].Dot( cross)); // save area in vertex w component } obox.mCenter = vector4(boxmat.m16[12], boxmat.m16[13], boxmat.m16[14], 0); obox.mCenter.w = Distance(obox.mCenter, obox.mVertex[0]); gOccluderBoxes.push_back(obox); }
void SWPolygonShape2D::set( const tarray<tvec2>& vertices ) { if ( vertices.size() <= 2 ) return; tuint count = vertices.size(); m_normals.resize( count ); m_vertices.resize( count ); for ( tuint i = 0 ; i < vertices.size() ; ++i ) { tuint i1 = i; tuint i2 = ((i+1)%count); const tvec2& v1 = vertices.at( i1 ); const tvec2& v2 = vertices.at( i2 ); tvec2 edge = v2 - v1; m_vertices[i] = v1; m_normals[i] = edge.cross( 1 ).normal(); } computeLocalOBB( m_localOBB ); }
inline T RayTesselatedTimeSampledTrianglePrimitive::_InterpolateFaceAttrib(float time, const tarray<T>& f) { return f.interpolate(idx, time); }
inline void RayTesselatedTimeSampledTrianglePrimitive::_InterpolateVertexAttrib(T& v0, T& v1, T& v2, float time, const tarray<T>& v) { v0 = v.interpolate(triangles->triangles[idx][0], time); v1 = v.interpolate(triangles->triangles[idx][1], time); v2 = v.interpolate(triangles->triangles[idx][2], time); }
inline void RayTesselatedTimeSampledTrianglePrimitive::_ResolveVertexAttrib(T& v0, T& v1, T& v2, int timeIdx, const tarray<T>& v) { v0 = v.at(triangles->triangles[idx][0], timeIdx); v1 = v.at(triangles->triangles[idx][1], timeIdx); v2 = v.at(triangles->triangles[idx][2], timeIdx); }
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; }