bool csPortalContainer::Draw (iRenderView* rview, iMovable* /*movable*/, csZBufMode /*zbufMode*/) { Prepare (); // We assume here that ObjectToWorld has already been called. iCamera* camera = rview->GetCamera (); const csReversibleTransform& camtrans = camera->GetTransform (); WorldToCamera (camera, camtrans); // Setup clip and far plane. csPlane3 portal_plane, *pportal_plane; bool do_portal_plane = ((CS::RenderManager::RenderView*)rview)->GetClipPlane (portal_plane); if (do_portal_plane) pportal_plane = &portal_plane; else pportal_plane = 0; csPlane3 *farplane = camera->GetFarPlane (); bool mirrored = camera->IsMirrored (); const csReversibleTransform movtrans = meshwrapper->GetCsMovable ().GetFullTransform (); csPoly2D poly; int viewWidth = rview->GetGraphics3D ()->GetWidth(); int viewHeight = rview->GetGraphics3D ()->GetHeight(); PerspectiveOutlet2D outlet (camera->GetProjectionMatrix(), poly, viewWidth, viewHeight); size_t i; if (clip_plane || clip_portal || clip_z_plane || do_portal_plane || farplane) { for (i = 0 ; i < portals.GetSize () ; i++) { csVector3 *verts; int num_verts; if (ClipToPlane ((int)i, pportal_plane, camtrans.GetOrigin (), verts, num_verts)) { // The far plane is defined negative. So if the portal is entirely // in front of the far plane it is not visible. Otherwise we will render // it. if (!farplane || csPoly3D::Classify (*farplane, verts, num_verts) != CS_POL_FRONT) { if (DoPerspective (outlet, verts, num_verts, mirrored, camera_planes[i]) && outlet.ClipAgainst (rview->GetClipper ())) { DrawOnePortal (portals[i], poly, movtrans, rview, camera_planes[i]); } } } } } else { for (i = 0 ; i < portals.GetSize () ; i++) { csPortal* prt = portals[i]; csDirtyAccessArray<int>& vt = prt->GetVertexIndices (); int num_vertices = (int)vt.GetSize (); int j; outlet.MakeEmpty (); for (j = 0 ; j < num_vertices ; j++) { outlet.Add (camera_vertices[vt[j]]); } DrawOnePortal (portals[i], poly, movtrans, rview, camera_planes[i]); } } return false; }
// Set up a clip plane with the specified normal. void SetWorldspaceClipPlane(point_t *normal, plane_t *plane){ // Rotate the plane normal into worldspace BackRotateVector(normal, &plane->normal); plane->distance = DotProduct(¤tpos, &plane->normal) + CLIP_PLANE_EPSILON;} // Set up the planes of the frustum, in worldspace coordinates. void SetUpFrustum(void){ double angle, s, c; point_t normal; angle = atan(2.0 / fieldofview * maxscale / xscreenscale); s = sin(angle); c = cos(angle); // Left clip plane normal.v[0] = s; normal.v[1] = 0; normal.v[2] = c; SetWorldspaceClipPlane(&normal, &frustumplanes[0]); // Right clip plane normal.v[0] = -s; SetWorldspaceClipPlane(&normal, &frustumplanes[1]); angle = atan(2.0 / fieldofview * maxscale / yscreenscale); s = sin(angle); c = cos(angle); // Bottom clip plane normal.v[0] = 0; normal.v[1] = s; normal.v[2] = c; SetWorldspaceClipPlane(&normal, &frustumplanes[2]); // Top clip plane normal.v[1] = -s; SetWorldspaceClipPlane(&normal, &frustumplanes[3]);} // Clip a polygon to the frustum. int ClipToFrustum(polygon_t *pin, polygon_t *pout){ int i, curpoly; polygon_t tpoly[2], *ppoly; curpoly = 0; ppoly = pin; for (i=0 ; i<(NUM_FRUSTUM_PLANES-1); i++) { if (!ClipToPlane(ppoly, &frustumplanes[i], &tpoly[curpoly])) return 0; ppoly = &tpoly[curpoly]; curpoly ^= 1; } return ClipToPlane(ppoly, &frustumplanes[NUM_FRUSTUM_PLANES-1], pout);}
void csPortalContainer::ComputeScreenPolygons (iRenderView* rview, csVector2* verts2D, csVector3* verts3D, size_t vertsSize, size_t* numVerts, int viewWidth, int viewHeight) { Prepare (); csSphere world_sphere, cam_sphere; GetBoundingSpheres (rview, 0, 0, world_sphere, cam_sphere); if (!CS::RenderViewClipper::CullBSphere (rview->GetRenderContext (), cam_sphere, world_sphere, clip_portal, clip_plane, clip_z_plane)) { memset (numVerts, 0, portals.GetSize () * sizeof (size_t)); return; } // We assume here that ObjectToWorld has already been called. iCamera* camera = rview->GetCamera (); const csReversibleTransform& camtrans = camera->GetTransform (); WorldToCamera (camera, camtrans); // Setup clip and far plane. csPlane3 portal_plane, *pportal_plane; bool do_portal_plane = ((CS::RenderManager::RenderView*)rview)->GetClipPlane (portal_plane); if (do_portal_plane) pportal_plane = &portal_plane; else pportal_plane = 0; csPlane3 *farplane = camera->GetFarPlane (); bool mirrored = camera->IsMirrored (); ScreenPolyOutputHelper outHelper (verts2D, verts3D, vertsSize, numVerts); size_t i; csPoly2D poly2D; csPoly3D poly3D; PerspectiveOutlet2D3D outlet (camera, poly2D, poly3D, viewWidth, viewHeight); if (clip_plane || clip_portal || clip_z_plane || do_portal_plane || farplane) { for (i = 0 ; i < portals.GetSize () ; i++) { csVector3 *verts; int num_verts; if (ClipToPlane ((int)i, pportal_plane, camtrans.GetOrigin (), verts, num_verts) // The far plane is defined negative. So if the portal is entirely // in front of the far plane it is not visible. Otherwise we will render // it. && (!farplane || csPoly3D::Classify (*farplane, verts, num_verts) != CS_POL_FRONT) && DoPerspective (outlet, verts, num_verts, mirrored, camera_planes[i]) && (poly2D.GetSignedArea() < 0) && outlet.ClipAgainst (rview->GetClipper ())) { outHelper.AddPoly (poly2D, poly3D); } else outHelper.AddEmpty (); } } else { for (i = 0 ; i < portals.GetSize () ; i++) { outlet.MakeEmpty(); csPortal* prt = portals[i]; csDirtyAccessArray<int>& vt = prt->GetVertexIndices (); int num_vertices = (int)vt.GetSize (); int j; for (j = 0 ; j < num_vertices ; j++) outlet.Add (camera_vertices[vt[j]]); if (poly2D.GetSignedArea() < 0) outHelper.AddPoly (poly2D, poly3D); else outHelper.AddEmpty (); } } }