Example #1
0
        /*
        ================
        R_DrawSolidClippedSubmodelPolygons
        ================
        */
        static void R_DrawSolidClippedSubmodelPolygons(model.model_t pmodel)
        {
            int			        i, j, lindex;
            double		        dot;
            model.msurface_t	psurf;
            int			        numsurfaces;
            model.mplane_t	    pplane;
            model.mvertex_t[]	bverts = new model.mvertex_t[MAX_BMODEL_VERTS];
            bedge_t[]		    bedges = new bedge_t[MAX_BMODEL_EDGES];
            int                 pbedge;
            model.medge_t		pedge;
            model.medge_t[]     pedges;

            int kk;
            for (kk = 0; kk < MAX_BMODEL_VERTS; kk++) bverts[kk] = new model.mvertex_t();
            for (kk = 0; kk < MAX_BMODEL_EDGES; kk++) bedges[kk] = new bedge_t();

            // FIXME: use bounding-box-based frustum clipping info?

            numsurfaces = pmodel.nummodelsurfaces;
            pedges = pmodel.edges;

            for (i=0 ; i<numsurfaces ; i++)
            {
                psurf = pmodel.surfaces[pmodel.firstmodelsurface + i];

            // find which side of the node we are on
                pplane = psurf.plane;

                dot = mathlib.DotProduct (modelorg, pplane.normal) - pplane.dist;

            // draw the polygon
                if (((psurf.flags & model.SURF_PLANEBACK) != 0 && (dot < -BACKFACE_EPSILON)) ||
                    ((psurf.flags & model.SURF_PLANEBACK) == 0 && (dot > BACKFACE_EPSILON)))
                {
                // FIXME: use bounding-box-based frustum clipping info?

                // copy the edges to bedges, flipping if necessary so always
                // clockwise winding
                // FIXME: if edges and vertices get caches, these assignments must move
                // outside the loop, and overflow checking must be done here
                    pbverts = bverts;
                    pbedges = bedges;
                    numbverts = numbedges = 0;

                    if (psurf.numedges > 0)
                    {
                        pbedge = numbedges;
                        numbedges += psurf.numedges;

                        for (j=0 ; j<psurf.numedges ; j++)
                        {
                           lindex = pmodel.surfedges[psurf.firstedge+j];

                            if (lindex > 0)
                            {
                                pedge = pedges[lindex];
                                bedges[pbedge + j].v[0] = r_pcurrentvertbase[pedge.v[0]];
                                bedges[pbedge + j].v[1] = r_pcurrentvertbase[pedge.v[1]];
                            }
                            else
                            {
                                lindex = -lindex;
                                pedge = pedges[lindex];
                                bedges[pbedge + j].v[0] = r_pcurrentvertbase[pedge.v[1]];
                                bedges[pbedge + j].v[1] = r_pcurrentvertbase[pedge.v[0]];
                            }

                            bedges[pbedge + j].pnext = bedges[pbedge + j + 1];
                        }

                        bedges[pbedge + j - 1].pnext = null;	// mark end of edges

                        R_RecursiveClipBPoly (bedges[pbedge], (model.mnode_t)currententity.topnode, psurf);
                    }
                    else
                    {
                        sys_linux.Sys_Error ("no edges in bmodel");
                    }
                }
            }
        }
Example #2
0
        /*
        ================
        R_RecursiveClipBPoly
        ================
        */
        static void R_RecursiveClipBPoly(bedge_t pedges, model.mnode_t pnode, model.msurface_t psurf)
        {
            bedge_t[]               psideedges = new bedge_t[2];
            bedge_t                 pnextedge, ptedge;
            int			            i, side, lastside;
            double		            dist, frac, lastdist;
            model.mplane_t	        splitplane, tplane = new model.mplane_t();
            model.mvertex_t	        pvert, plastvert, ptvert;
            model.node_or_leaf_t	pn;

            psideedges[0] = psideedges[1] = null;

            makeclippededge = false;

            // transform the BSP plane into model space
            // FIXME: cache these?
            splitplane = pnode.plane;
            tplane.dist = splitplane.dist -
                    mathlib.DotProduct(r_entorigin, splitplane.normal);
            tplane.normal[0] = mathlib.DotProduct(entity_rotation[0], splitplane.normal);
            tplane.normal[1] = mathlib.DotProduct(entity_rotation[1], splitplane.normal);
            tplane.normal[2] = mathlib.DotProduct(entity_rotation[2], splitplane.normal);

            // clip edges to BSP plane
            for ( ; pedges != null ; pedges = pnextedge)
            {
                pnextedge = pedges.pnext;

            // set the status for the last point as the previous point
            // FIXME: cache this stuff somehow?
                plastvert = pedges.v[0];
                lastdist = mathlib.DotProduct (plastvert.position, tplane.normal) -
                           tplane.dist;

                if (lastdist > 0)
                    lastside = 0;
                else
                    lastside = 1;

                pvert = pedges.v[1];

                dist = mathlib.DotProduct(pvert.position, tplane.normal) - tplane.dist;

                if (dist > 0)
                    side = 0;
                else
                    side = 1;

                if (side != lastside)
                {
                // clipped
                    if (numbverts >= MAX_BMODEL_VERTS)
                        return;

                // generate the clipped vertex
                    frac = lastdist / (lastdist - dist);
                    ptvert = pbverts[numbverts++];
                    ptvert.position[0] = plastvert.position[0] +
                            frac * (pvert.position[0] -
                            plastvert.position[0]);
                    ptvert.position[1] = plastvert.position[1] +
                            frac * (pvert.position[1] -
                            plastvert.position[1]);
                    ptvert.position[2] = plastvert.position[2] +
                            frac * (pvert.position[2] -
                            plastvert.position[2]);

                // split into two edges, one on each side, and remember entering
                // and exiting points
                // FIXME: share the clip edge by having a winding direction flag?
                    if (numbedges >= (MAX_BMODEL_EDGES - 1))
                    {
                        console.Con_Printf ("Out of edges for bmodel\n");
                        return;
                    }

                    ptedge = pbedges[numbedges];
                    ptedge.pnext = psideedges[lastside];
                    psideedges[lastside] = ptedge;
                    ptedge.v[0] = plastvert;
                    ptedge.v[1] = ptvert;

                    ptedge = pbedges[numbedges + 1];
                    ptedge.pnext = psideedges[side];
                    psideedges[side] = ptedge;
                    ptedge.v[0] = ptvert;
                    ptedge.v[1] = pvert;

                    numbedges += 2;

                    if (side == 0)
                    {
                    // entering for front, exiting for back
                        pfrontenter = ptvert;
                        makeclippededge = true;
                    }
                    else
                    {
                        pfrontexit = ptvert;
                        makeclippededge = true;
                    }
                }
                else
                {
                // add the edge to the appropriate side
                    pedges.pnext = psideedges[side];
                    psideedges[side] = pedges;
                }
            }

            // if anything was clipped, reconstitute and add the edges along the clip
            // plane to both sides (but in opposite directions)
            if (makeclippededge)
            {
                if (numbedges >= (MAX_BMODEL_EDGES - 2))
                {
                    console.Con_Printf ("Out of edges for bmodel\n");
                    return;
                }

                ptedge = pbedges[numbedges];
                ptedge.pnext = psideedges[0];
                psideedges[0] = ptedge;
                ptedge.v[0] = pfrontexit;
                ptedge.v[1] = pfrontenter;

                ptedge = pbedges[numbedges + 1];
                ptedge.pnext = psideedges[1];
                psideedges[1] = ptedge;
                ptedge.v[0] = pfrontenter;
                ptedge.v[1] = pfrontexit;

                numbedges += 2;
            }

            // draw or recurse further
            for (i=0 ; i<2 ; i++)
            {
                if (psideedges[i] != null)
                {
                // draw if we've reached a non-solid leaf, done if all that's left is a
                // solid leaf, and continue down the tree if it's not a leaf
                    pn = pnode.children[i];

                // we're done with this branch if the node or leaf isn't in the PVS
                    if (pn.visframe == r_visframecount)
                    {
                        if (pn.contents < 0)
                        {
                            if (pn.contents != bspfile.CONTENTS_SOLID)
                            {
                                r_currentbkey = ((model.mleaf_t)pn).key;
                                R_RenderBmodelFace (psideedges[i], psurf);
                            }
                        }
                        else
                        {
                            R_RecursiveClipBPoly (psideedges[i], (model.mnode_t)pnode.children[i],
                                              psurf);
                        }
                    }
                }
            }
        }
Example #3
0
        /*
        ================
        R_ClipEdge
        ================
        */
        static void R_ClipEdge(model.mvertex_t pv0, model.mvertex_t pv1, clipplane_t clip)
        {
            double          d0, d1, f;
            model.mvertex_t clipvert = new model.mvertex_t();

            if (clip != null)
            {
                do
                {
                    d0 = mathlib.DotProduct(pv0.position, clip.normal) - clip.dist;
                    d1 = mathlib.DotProduct(pv1.position, clip.normal) - clip.dist;

                    if (d0 >= 0)
                    {
                        // point 0 is unclipped
                        if (d1 >= 0)
                        {
                            // both points are unclipped
                            continue;
                        }

                        // only point 1 is clipped

                        // we don't cache clipped edges
                        cacheoffset = 0x7FFFFFFF;

                        f = d0 / (d0 - d1);
                        clipvert.position[0] = pv0.position[0] +
                                f * (pv1.position[0] - pv0.position[0]);
                        clipvert.position[1] = pv0.position[1] +
                                f * (pv1.position[1] - pv0.position[1]);
                        clipvert.position[2] = pv0.position[2] +
                                f * (pv1.position[2] - pv0.position[2]);

                        if (clip.leftedge)
                        {
                            r_leftclipped = true;
                            r_leftexit = clipvert;
                        }
                        else if (clip.rightedge)
                        {
                            r_rightclipped = true;
                            r_rightexit = clipvert;
                        }

                        R_ClipEdge(pv0, clipvert, clip.next);
                        return;
                    }
                    else
                    {
                        // point 0 is clipped
                        if (d1 < 0)
                        {
                            // both points are clipped
                            // we do cache fully clipped edges
                            if (!r_leftclipped)
                                cacheoffset = (uint)(FULLY_CLIPPED_CACHED |
                                        (r_framecount & FRAMECOUNT_MASK));
                            return;
                        }

                        // only point 0 is clipped
                        r_lastvertvalid = false;

                        // we don't cache partially clipped edges
                        cacheoffset = 0x7FFFFFFF;

                        f = d0 / (d0 - d1);
                        clipvert.position[0] = pv0.position[0] +
                                f * (pv1.position[0] - pv0.position[0]);
                        clipvert.position[1] = pv0.position[1] +
                                f * (pv1.position[1] - pv0.position[1]);
                        clipvert.position[2] = pv0.position[2] +
                                f * (pv1.position[2] - pv0.position[2]);

                        if (clip.leftedge)
                        {
                            r_leftclipped = true;
                            r_leftenter = clipvert;
                        }
                        else if (clip.rightedge)
                        {
                            r_rightclipped = true;
                            r_rightenter = clipvert;
                        }

                        R_ClipEdge(clipvert, pv1, clip.next);
                        return;
                    }
                } while ((clip = clip.next) != null);
            }

            // add the edge
            R_EmitEdge(pv0, pv1);
        }