Ejemplo n.º 1
0
        /*
         * ================
         * R_EmitEdge
         * ================
         */
        static void R_EmitEdge(model.mvertex_t pv0, model.mvertex_t pv1)
        {
            edge_t edge, pcheck;
            int    u_check;
            double u, u_step;

            double[] local = new double[3], transformed = new double[3];
            double[] world;
            int      v, v2, ceilv0;
            double   scale, lzi0, u0, v0;
            int      side;

            if (r_lastvertvalid)
            {
                u0     = r_u1;
                v0     = r_v1;
                lzi0   = r_lzi1;
                ceilv0 = r_ceilv1;
            }
            else
            {
                world = pv0.position;

                // transform and project
                mathlib.VectorSubtract(world, modelorg, ref local);
                TransformVector(local, ref transformed);

                if (transformed[2] < NEAR_CLIP)
                {
                    transformed[2] = NEAR_CLIP;
                }

                lzi0 = 1.0 / transformed[2];

                // FIXME: build x/yscale into transform?
                scale = xscale * lzi0;
                u0    = (xcenter + scale * transformed[0]);
                if (u0 < r_refdef.fvrectx_adj)
                {
                    u0 = r_refdef.fvrectx_adj;
                }
                if (u0 > r_refdef.fvrectright_adj)
                {
                    u0 = r_refdef.fvrectright_adj;
                }

                scale = yscale * lzi0;
                v0    = (ycenter - scale * transformed[1]);
                if (v0 < r_refdef.fvrecty_adj)
                {
                    v0 = r_refdef.fvrecty_adj;
                }
                if (v0 > r_refdef.fvrectbottom_adj)
                {
                    v0 = r_refdef.fvrectbottom_adj;
                }

                ceilv0 = (int)Math.Ceiling(v0);
            }

            world = pv1.position;

            // transform and project
            mathlib.VectorSubtract(world, modelorg, ref local);
            TransformVector(local, ref transformed);

            if (transformed[2] < NEAR_CLIP)
            {
                transformed[2] = NEAR_CLIP;
            }

            r_lzi1 = 1.0 / transformed[2];

            scale = xscale * r_lzi1;
            r_u1  = (xcenter + scale * transformed[0]);
            if (r_u1 < r_refdef.fvrectx_adj)
            {
                r_u1 = r_refdef.fvrectx_adj;
            }
            if (r_u1 > r_refdef.fvrectright_adj)
            {
                r_u1 = r_refdef.fvrectright_adj;
            }

            scale = yscale * r_lzi1;
            r_v1  = (ycenter - scale * transformed[1]);
            if (r_v1 < r_refdef.fvrecty_adj)
            {
                r_v1 = r_refdef.fvrecty_adj;
            }
            if (r_v1 > r_refdef.fvrectbottom_adj)
            {
                r_v1 = r_refdef.fvrectbottom_adj;
            }

            if (r_lzi1 > lzi0)
            {
                lzi0 = r_lzi1;
            }

            if (lzi0 > r_nearzi)        // for mipmap finding
            {
                r_nearzi = lzi0;
            }

            // for right edges, all we want is the effect on 1/z
            if (r_nearzionly)
            {
                return;
            }

            r_emitted = 1;

            r_ceilv1 = (int)Math.Ceiling(r_v1);


            // create the edge
            if (ceilv0 == r_ceilv1)
            {
                // we cache unclipped horizontal edges as fully clipped
                if (cacheoffset != 0x7FFFFFFF)
                {
                    cacheoffset = (uint)(FULLY_CLIPPED_CACHED |
                                         (r_framecount & FRAMECOUNT_MASK));
                }

                return;                 // horizontal edge
            }

            side = (ceilv0 > r_ceilv1) ? 1 : 0;

            edge = r_edges[edge_p++];

            edge.owner = r_pedge;

            edge.nearzi = lzi0;

            if (side == 0)
            {
                // trailing edge (go from p1 to p2)
                v  = ceilv0;
                v2 = r_ceilv1 - 1;

                edge.surfs[0] = (ushort)(surface_p + 1);
                edge.surfs[1] = 0;

                u_step = ((r_u1 - u0) / (r_v1 - v0));
                u      = u0 + ((double)v - v0) * u_step;
            }
            else
            {
                // leading edge (go from p2 to p1)
                v2 = ceilv0 - 1;
                v  = r_ceilv1;

                edge.surfs[0] = 0;
                edge.surfs[1] = (ushort)(surface_p + 1);

                u_step = ((u0 - r_u1) / (v0 - r_v1));
                u      = r_u1 + ((double)v - r_v1) * u_step;
            }

            edge.u_step = (int)(u_step * 0x100000);
            edge.u      = (int)(u * 0x100000 + 0xFFFFF);

            // we need to do this to avoid stepping off the edges if a very nearly
            // horizontal edge is less than epsilon above a scan, and numeric error causes
            // it to incorrectly extend to the scan, and the extension of the line goes off
            // the edge of the screen
            // FIXME: is this actually needed?
            if (edge.u < r_refdef.vrect_x_adj_shift20)
            {
                edge.u = r_refdef.vrect_x_adj_shift20;
            }
            if (edge.u > r_refdef.vrectright_adj_shift20)
            {
                edge.u = r_refdef.vrectright_adj_shift20;
            }

            //
            // sort the edge in normally
            //
            u_check = edge.u;
            if (edge.surfs[0] != 0)
            {
                u_check++;              // sort trailers after leaders
            }
            if (newedges[v] == null || newedges[v].u >= u_check)
            {
                edge.next   = newedges[v];
                newedges[v] = edge;
            }
            else
            {
                pcheck = newedges[v];
                while (pcheck.next != null && pcheck.next.u < u_check)
                {
                    pcheck = pcheck.next;
                }
                edge.next   = pcheck.next;
                pcheck.next = edge;
            }

            edge.nextremove = removeedges[v2];
            removeedges[v2] = edge;
        }
Ejemplo n.º 2
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");
                    }
                }
            }
        }
Ejemplo n.º 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);
        }
Ejemplo n.º 4
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);
                        }
                    }
                }
            }
        }