Ejemplo n.º 1
0
 public static int BOX_ON_PLANE_SIDE(double[] emins, double[] emaxs, model.mplane_t p)
 {
     return
     ((p.type < 3) ?
     (
         (p.dist <= emins[p.type]) ?
             1
         :
         (
             (p.dist >= emaxs[p.type]) ?
                 2
             :
                 3
         )
     )
     :
         BoxOnPlaneSide(emins, emaxs, p));
 }
Ejemplo n.º 2
0
        /*
        ================
        R_RecursiveWorldNode
        ================
        */
        static void R_RecursiveWorldNode(model.node_or_leaf_t node, int clipflags)
        {
            int			        i, c, side, pindex;
            double[]            acceptpt = new double[3] {0, 0, 0}, rejectpt = new double[3] {0, 0, 0};
            model.mplane_t	    plane;
            model.msurface_t	surf, mark;
            model.mleaf_t		pleaf;
            double		        d, dot;
            int                 surfofs;

            if (node.contents == bspfile.CONTENTS_SOLID)
                return;		// solid

            if (node.visframe != r_visframecount)
                return;

            // cull the clipping planes if not trivial accept
            // FIXME: the compiler is doing a lousy job of optimizing here; it could be
            //  twice as fast in ASM
            if (clipflags != 0)
            {
                for (i=0 ; i<4 ; i++)
                {
                    if ((clipflags & (1<<i)) == 0)
                        continue;	// don't need to clip against it

                // generate accept and reject points
                // FIXME: do with fast look-ups or integer tests based on the sign bit
                // of the floating point values

                    pindex = pfrustum_indexes[i];

                    rejectpt[0] = (double)node.minmaxs[r_frustum_indexes[pindex + 0]];
                    rejectpt[1] = (double)node.minmaxs[r_frustum_indexes[pindex + 1]];
                    rejectpt[2] = (double)node.minmaxs[r_frustum_indexes[pindex + 2]];

                    d = mathlib.DotProduct (rejectpt, view_clipplanes[i].normal);
                    d -= view_clipplanes[i].dist;

                    if (d <= 0)
                        return;

                    acceptpt[0] = (double)node.minmaxs[r_frustum_indexes[pindex + 3 + 0]];
                    acceptpt[1] = (double)node.minmaxs[r_frustum_indexes[pindex + 3 + 1]];
                    acceptpt[2] = (double)node.minmaxs[r_frustum_indexes[pindex + 3 + 2]];

                    d = mathlib.DotProduct(acceptpt, view_clipplanes[i].normal);
                    d -= view_clipplanes[i].dist;

                    if (d >= 0)
                        clipflags &= ~(1<<i);	// node is entirely on screen
                }
            }

            // if a leaf node, draw stuff
            if (node.contents < 0)
            {
                pleaf = (model.mleaf_t)node;

                helper.ObjectBuffer _mark = pleaf.firstmarksurface;
                int ofs = _mark.ofs;
                mark = (model.msurface_t)_mark.buffer[ofs];
                c = pleaf.nummarksurfaces;

                if (c != 0)
                {
                    do
                    {
                        mark.visframe = r_framecount;
                        mark = (model.msurface_t)_mark.buffer[++ofs];
                    } while (--c != 0);
                }

            // deal with model fragments in this leaf
                if (pleaf.efrags != null)
                {
                    R_StoreEfrags (pleaf.efrags);
                }

                pleaf.key = r_currentkey;
                r_currentkey++;		// all bmodels in a leaf share the same key
            }
            else
            {
                model.mnode_t _node = (model.mnode_t)node;
            // node is just a decision point, so go down the apropriate sides

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

                switch (plane.type)
                {
                case bspfile.PLANE_X:
                    dot = modelorg[0] - plane.dist;
                    break;
                case bspfile.PLANE_Y:
                    dot = modelorg[1] - plane.dist;
                    break;
                case bspfile.PLANE_Z:
                    dot = modelorg[2] - plane.dist;
                    break;
                default:
                    dot = mathlib.DotProduct (modelorg, plane.normal) - plane.dist;
                    break;
                }

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

            // recurse down the children, front side first
                R_RecursiveWorldNode (_node.children[side], clipflags);

            // draw stuff
                c = _node.numsurfaces;

                if (c != 0)
                {
                    surf = client.cl.worldmodel.surfaces[_node.firstsurface];
                    surfofs = _node.firstsurface;

                    if (dot < -BACKFACE_EPSILON)
                    {
                        do
                        {
                            if ((surf.flags & model.SURF_PLANEBACK) != 0 &&
                                (surf.visframe == r_framecount))
                            {
                                if (r_drawpolys)
                                {
                                    if (r_worldpolysbacktofront)
                                    {
                                        if (numbtofpolys < MAX_BTOFPOLYS)
                                        {
                                            pbtofpolys[numbtofpolys].clipflags =
                                                    clipflags;
                                            pbtofpolys[numbtofpolys].psurf = surf;
                                            numbtofpolys++;
                                        }
                                    }
                                    else
                                    {
                                        R_RenderPoly (surf, clipflags);
                                    }
                                }
                                else
                                {
                                    R_RenderFace (surf, clipflags);
                                }
                            }

                            surf = client.cl.worldmodel.surfaces[++surfofs];
                        } while (--c != 0);
                    }
                    else if (dot > BACKFACE_EPSILON)
                    {
                        do
                        {
                            if ((surf.flags & model.SURF_PLANEBACK) == 0 &&
                                (surf.visframe == r_framecount))
                            {
                                if (r_drawpolys)
                                {
                                    if (r_worldpolysbacktofront)
                                    {
                                        if (numbtofpolys < MAX_BTOFPOLYS)
                                        {
                                            pbtofpolys[numbtofpolys].clipflags =
                                                    clipflags;
                                            pbtofpolys[numbtofpolys].psurf = surf;
                                            numbtofpolys++;
                                        }
                                    }
                                    else
                                    {
                                        R_RenderPoly (surf, clipflags);
                                    }
                                }
                                else
                                {
                                    R_RenderFace (surf, clipflags);
                                }
                            }

                            surf = client.cl.worldmodel.surfaces[++surfofs];
                        } while (--c != 0);
                    }

                // all surfaces on the same node share the same sequence number
                    r_currentkey++;
                }

            // recurse down the back side
                R_RecursiveWorldNode (_node.children[side == 0 ? 1 : 0], clipflags);
            }
        }
Ejemplo n.º 3
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);
                        }
                    }
                }
            }
        }
Ejemplo n.º 4
0
        /*
        ================
        R_DrawSubmodelPolygons
        ================
        */
        static void R_DrawSubmodelPolygons(model.model_t pmodel, int clipflags)
        {
            int                 i;
            double              dot;
            model.msurface_t    psurf;
            int                 numsurfaces;
            model.mplane_t      pplane;

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

            numsurfaces = pmodel.nummodelsurfaces;

            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)))
                {
                    r_currentkey = ((model.mleaf_t)currententity.topnode).key;

                    // FIXME: use bounding-box-based frustum clipping info?
                    R_RenderFace(psurf, clipflags);
                }
            }
        }
Ejemplo n.º 5
0
        /*
        ================
        R_RenderBmodelFace
        ================
        */
        static void R_RenderBmodelFace(bedge_t pedges, model.msurface_t psurf)
        {
            int			    i;
            uint	        mask;
            model.mplane_t	pplane;
            double		    distinv;
            double[]        p_normal = new double[3] {0, 0, 0};
            model.medge_t	tedge = new model.medge_t();
            clipplane_t	    pclip;

            // skip out if no more surfs
            if (surface_p >= surf_max)
            {
                r_outofsurfaces++;
                return;
            }

            // ditto if not enough edges left, or switch to auxedges if possible
            if ((edge_p + psurf.numedges + 4) >= edge_max)
            {
                r_outofedges += psurf.numedges;
                return;
            }

            c_faceclip++;

            // this is a dummy to give the caching mechanism someplace to write to
            r_pedge = tedge;

            // set up clip planes
            pclip = null;

            for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
            {
                if ((r_clipflags & mask) != 0)
                {
                    view_clipplanes[i].next = pclip;
                    pclip = view_clipplanes[i];
                }
            }

            // push the edges through
            r_emitted = 0;
            r_nearzi = 0;
            r_nearzionly = false;
            makeleftedge = makerightedge = false;
            // FIXME: keep clipped bmodel edges in clockwise order so last vertex caching
            // can be used?
            r_lastvertvalid = false;

            for ( ; pedges != null ; pedges = pedges.pnext)
            {
                r_leftclipped = r_rightclipped = false;
                R_ClipEdge (pedges.v[0], pedges.v[1], pclip);

                if (r_leftclipped)
                    makeleftedge = true;
                if (r_rightclipped)
                    makerightedge = true;
            }

            // if there was a clip off the left edge, add that edge too
            // FIXME: faster to do in screen space?
            // FIXME: share clipped edges?
            if (makeleftedge)
            {
                r_pedge = tedge;
                R_ClipEdge (r_leftexit, r_leftenter, pclip.next);
            }

            // if there was a clip off the right edge, get the right r_nearzi
            if (makerightedge)
            {
                r_pedge = tedge;
                r_nearzionly = true;
                R_ClipEdge (r_rightexit, r_rightenter, view_clipplanes[1].next);
            }

            // if no edges made it out, return without posting the surface
            if (r_emitted == 0)
                return;

            r_polycount++;

            surfaces[surface_p].data = psurf;
            surfaces[surface_p].nearzi = r_nearzi;
            surfaces[surface_p].flags = psurf.flags;
            surfaces[surface_p].insubmodel = true;
            surfaces[surface_p].spanstate = 0;
            surfaces[surface_p].entity = currententity;
            surfaces[surface_p].key = r_currentbkey;
            surfaces[surface_p].spans = null;

            pplane = psurf.plane;
            // FIXME: cache this?
            TransformVector (pplane.normal, p_normal);
            // FIXME: cache this?
            distinv = 1.0 / (pplane.dist - mathlib.DotProduct (modelorg, pplane.normal));

            surfaces[surface_p].d_zistepu = p_normal[0] * xscaleinv * distinv;
            surfaces[surface_p].d_zistepv = -p_normal[1] * yscaleinv * distinv;
            surfaces[surface_p].d_ziorigin = p_normal[2] * distinv -
                    xcenter * surfaces[surface_p].d_zistepu -
                    ycenter * surfaces[surface_p].d_zistepv;

            //JDC	VectorCopy (r_worldmodelorg, surface_p.modelorg);
            surface_p++;
        }
Ejemplo n.º 6
0
        /*
        ================
        R_GetSpriteframe
        ================
        */
        static model.mspriteframe_t R_GetSpriteframe(model.msprite_t psprite)
        {
            model.mspritegroup_t    pspritegroup;
            model.mspriteframe_t    pspriteframe;
            int                     i, numframes, frame;
            //double* pintervals, fullinterval, targettime, time;

            frame = currententity.frame;

            if ((frame >= psprite.numframes) || (frame < 0))
            {
                console.Con_Printf("R_DrawSprite: no such frame " + frame + "\n");
                frame = 0;
            }

            if (psprite.frames[frame].type == model.spriteframetype_t.SPR_SINGLE)
            {
                pspriteframe = (model.mspriteframe_t)psprite.frames[frame].frameptr;
            }
            else
            {
                pspriteframe = null;
            }

            return pspriteframe;
        }
Ejemplo n.º 7
0
        /*
        ===============
        R_TextureAnimation

        Returns the proper texture for a given time and base texture
        ===============
        */
        public static model.texture_t R_TextureAnimation(model.texture_t @base)
        {
            int		reletive;
            int		count;

            if (currententity.frame != 0)
            {
                if (@base.alternate_anims != null)
                    @base = @base.alternate_anims;
            }

            if (@base.anim_total == 0)
                return @base;

            reletive = (int)(client.cl.time*10) % @base.anim_total;

            count = 0;
            while (@base.anim_min > reletive || @base.anim_max <= reletive)
            {
                @base = @base.anim_next;
                if (@base == null)
                    sys_linux.Sys_Error ("R_TextureAnimation: broken cycle");
                if (++count > 100)
                    sys_linux.Sys_Error("R_TextureAnimation: infinite cycle");
            }

            return @base;
        }
Ejemplo n.º 8
0
        /*
        =============
        R_BmodelCheckBBox
        =============
        */
        static int R_BmodelCheckBBox(model.model_t clmodel, double[] minmaxs)
        {
            int			i, pindex, clipflags;
            double[]    acceptpt = new double[3] {0, 0, 0}, rejectpt = new double[3] {0, 0, 0};
            double		d;

            clipflags = 0;

            if (currententity.angles[0] != 0 || currententity.angles[1] != 0
                || currententity.angles[2] != 0)
            {
                for (i=0 ; i<4 ; i++)
                {
                    d = mathlib.DotProduct (currententity.origin, view_clipplanes[i].normal);
                    d -= view_clipplanes[i].dist;

                    if (d <= -clmodel.radius)
                        return BMODEL_FULLY_CLIPPED;

                    if (d <= clmodel.radius)
                        clipflags |= (1<<i);
                }
            }
            else
            {
                for (i=0 ; i<4 ; i++)
                {
                // generate accept and reject points
                // FIXME: do with fast look-ups or integer tests based on the sign bit
                // of the floating point values

                    pindex = pfrustum_indexes[i];

                    rejectpt[0] = minmaxs[r_frustum_indexes[pindex + 0]];
                    rejectpt[1] = minmaxs[r_frustum_indexes[pindex + 1]];
                    rejectpt[2] = minmaxs[r_frustum_indexes[pindex + 2]];

                    d = mathlib.DotProduct (rejectpt, view_clipplanes[i].normal);
                    d -= view_clipplanes[i].dist;

                    if (d <= 0)
                        return BMODEL_FULLY_CLIPPED;

                    acceptpt[0] = minmaxs[r_frustum_indexes[pindex + 3 + 0]];
                    acceptpt[1] = minmaxs[r_frustum_indexes[pindex + 3 + 1]];
                    acceptpt[2] = minmaxs[r_frustum_indexes[pindex + 3 + 2]];

                    d = mathlib.DotProduct (acceptpt, view_clipplanes[i].normal);
                    d -= view_clipplanes[i].dist;

                    if (d <= 0)
                        clipflags |= (1<<i);
                }
            }

            return clipflags;
        }
Ejemplo n.º 9
0
 /*
 ================
 R_ZDrawSubmodelPolys
 ================
 */
 static void R_ZDrawSubmodelPolys(model.model_t pmodel)
 {
 }
Ejemplo n.º 10
0
        static void SV_AddToFatPVS(double[] org, model.node_or_leaf_t node)
        {
            int		i;
            Uint8Array pvs;
            model.mplane_t	plane;
            double	d;

            while (true)
            {
            // if this is a leaf, accumulate the pvs bits
                if (node.contents < 0)
                {
                    if (node.contents != bspfile.CONTENTS_SOLID)
                    {
                        pvs = model.Mod_LeafPVS((model.node_or_leaf_t)node, sv.worldmodel);
                        for (i=0 ; i<fatbytes ; i++)
                            fatpvs[i] |= pvs[i];
                    }
                    return;
                }

                plane = node.plane;
                d = mathlib.DotProduct (org, plane.normal) - plane.dist;
                if (d > 8)
                    node = ((model.node_or_leaf_t)node).children[0];
                else if (d < -8)
                    node = (model.node_or_leaf_t)node.children[1];
                else
                {	// go down both
                    SV_AddToFatPVS(org, (model.node_or_leaf_t)node.children[0]);
                    node = (model.node_or_leaf_t)node.children[1];
                }
            }
        }
Ejemplo n.º 11
0
 /*
 ================
 R_RenderPoly
 ================
 */
 static void R_RenderPoly(model.msurface_t fa, int clipflags)
 {
 }
Ejemplo n.º 12
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.º 13
0
        /*
        ================
        R_RenderFace
        ================
        */
        static void R_RenderFace(model.msurface_t fa, int clipflags)
        {
            int			    i, lindex;
            uint	        mask;
            model.mplane_t	pplane;
            double		    distinv;
            double[]		p_normal = new double[3] {0, 0, 0};
            model.medge_t[]	pedges;
            model.medge_t   tedge = new model.medge_t();
            clipplane_t	    pclip;

            // skip out if no more surfs
            if ((surface_p) >= surf_max)
            {
                r_outofsurfaces++;
                return;
            }

            // ditto if not enough edges left, or switch to auxedges if possible
            if ((edge_p + fa.numedges + 4) >= edge_max)
            {
                r_outofedges += fa.numedges;
                return;
            }

            c_faceclip++;

            // set up clip planes
            pclip = null;

            for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
            {
                if ((clipflags & mask) != 0)
                {
                    view_clipplanes[i].next = pclip;
                    pclip = view_clipplanes[i];
                }
            }

            // push the edges through
            r_emitted = 0;
            r_nearzi = 0;
            r_nearzionly = false;
            makeleftedge = makerightedge = false;
            pedges = currententity.model.edges;
            r_lastvertvalid = false;

            for (i=0 ; i<fa.numedges ; i++)
            {
                lindex = currententity.model.surfedges[fa.firstedge + i];

                if (lindex > 0)
                {
                    r_pedge = pedges[lindex];

                // if the edge is cached, we can just reuse the edge
                    if (!insubmodel)
                    {
                        if ((r_pedge.cachededgeoffset & FULLY_CLIPPED_CACHED) != 0)
                        {
                            if ((r_pedge.cachededgeoffset & FRAMECOUNT_MASK) ==
                                r_framecount)
                            {
                                r_lastvertvalid = false;
                                continue;
                            }
                        }
                        else
                        {
                            if ((edge_p > r_pedge.cachededgeoffset) &&
                                (r_edges[r_pedge.cachededgeoffset].owner == r_pedge))
                            {
                                R_EmitCachedEdge ();
                                r_lastvertvalid = false;
                                continue;
                            }
                        }
                    }

                // assume it's cacheable
                    cacheoffset = (uint)edge_p;
                    r_leftclipped = r_rightclipped = false;
                    R_ClipEdge (r_pcurrentvertbase[r_pedge.v[0]],
                                r_pcurrentvertbase[r_pedge.v[1]],
                                pclip);
                    r_pedge.cachededgeoffset = cacheoffset;

                    if (r_leftclipped)
                        makeleftedge = true;
                    if (r_rightclipped)
                        makerightedge = true;
                    r_lastvertvalid = true;
                }
                else
                {
                    lindex = -lindex;
                    r_pedge = pedges[lindex];
                // if the edge is cached, we can just reuse the edge
                    if (!insubmodel)
                    {
                        if ((r_pedge.cachededgeoffset & FULLY_CLIPPED_CACHED) != 0)
                        {
                            if ((r_pedge.cachededgeoffset & FRAMECOUNT_MASK) ==
                                r_framecount)
                            {
                                r_lastvertvalid = false;
                                continue;
                            }
                        }
                        else
                        {
                        // it's cached if the cached edge is valid and is owned
                        // by this medge_t
                            if ((edge_p > r_pedge.cachededgeoffset) &&
                                (r_edges[r_pedge.cachededgeoffset].owner == r_pedge))
                            {
                                R_EmitCachedEdge ();
                                r_lastvertvalid = false;
                                continue;
                            }
                        }
                    }

                // assume it's cacheable
                    cacheoffset = (uint)edge_p;
                    r_leftclipped = r_rightclipped = false;
                    R_ClipEdge (r_pcurrentvertbase[r_pedge.v[1]],
                                r_pcurrentvertbase[r_pedge.v[0]],
                                pclip);
                    r_pedge.cachededgeoffset = cacheoffset;

                    if (r_leftclipped)
                        makeleftedge = true;
                    if (r_rightclipped)
                        makerightedge = true;
                    r_lastvertvalid = true;
                }
            }

            // if there was a clip off the left edge, add that edge too
            // FIXME: faster to do in screen space?
            // FIXME: share clipped edges?
            if (makeleftedge)
            {
                r_pedge = tedge;
                r_lastvertvalid = false;
                R_ClipEdge (r_leftexit, r_leftenter, pclip.next);
            }

            // if there was a clip off the right edge, get the right r_nearzi
            if (makerightedge)
            {
                r_pedge = tedge;
                r_lastvertvalid = false;
                r_nearzionly = true;
                R_ClipEdge (r_rightexit, r_rightenter, view_clipplanes[1].next);
            }

            // if no edges made it out, return without posting the surface
            if (r_emitted == 0)
                return;

            r_polycount++;

            surfaces[surface_p].data = fa;
            surfaces[surface_p].nearzi = r_nearzi;
            surfaces[surface_p].flags = fa.flags;
            surfaces[surface_p].insubmodel = insubmodel;
            surfaces[surface_p].spanstate = 0;
            surfaces[surface_p].entity = currententity;
            surfaces[surface_p].key = r_currentkey++;
            surfaces[surface_p].spans = null;

            pplane = fa.plane;
            // FIXME: cache this?
            TransformVector(pplane.normal, p_normal);
            // FIXME: cache this?
            distinv = 1.0 / (pplane.dist - mathlib.DotProduct(modelorg, pplane.normal));

            surfaces[surface_p].d_zistepu = p_normal[0] * xscaleinv * distinv;
            surfaces[surface_p].d_zistepv = -p_normal[1] * yscaleinv * distinv;
            surfaces[surface_p].d_ziorigin = p_normal[2] * distinv -
                    xcenter * surfaces[surface_p].d_zistepu -
                    ycenter * surfaces[surface_p].d_zistepv;

            //JDC	VectorCopy (r_worldmodelorg, surface_p->modelorg);
            surface_p++;
        }
Ejemplo n.º 14
0
        /*
        ================
        R_AliasTransformAndProjectFinalVerts
        ================
        */
        static void R_AliasTransformAndProjectFinalVerts(draw.finalvert_t[] pfv, model.stvert_t[] pstverts)
        {
            int			        i, temp;
            double		        lightcos;
            double[]            plightnormal;
            double              zi;
            model.trivertx_t	pverts;

            for (i=0 ; i<r_anumverts ; i++)
            {
                draw.finalvert_t    fv = pfv[i];
                model.stvert_t stverts = pstverts[i];
                pverts = r_apverts[i];

                // transform and project
                zi = 1.0 / (mathlib.DotProduct(pverts.v, aliastransform[2]) +
                        aliastransform[2][3]);

            // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
            // scaled up by 1/2**31, and the scaling cancels out for x and y in the
            // projection
                fv.v[5] = (int)zi;

                fv.v[0] = (int)(((mathlib.DotProduct(pverts.v, aliastransform[0]) +
                        aliastransform[0][3]) * zi) + aliasxcenter);
                fv.v[1] = (int)(((mathlib.DotProduct(pverts.v, aliastransform[1]) +
                        aliastransform[1][3]) * zi) + aliasycenter);

                fv.v[2] = stverts.s;
                fv.v[3] = stverts.t;
                fv.flags = stverts.onseam;

            // lighting
                plightnormal = r_avertexnormals[pverts.lightnormalindex];
                lightcos = mathlib.DotProduct(plightnormal, r_plightvec);
                temp = r_ambientlight;

                if (lightcos < 0)
                {
                    temp += (int)(r_shadelight * lightcos);

                // clamp; because we limited the minimum ambient and shading light, we
                // don't have to clamp low light, just bright
                    if (temp < 0)
                        temp = 0;
                }

                fv.v[4] = temp;
            }
        }
Ejemplo n.º 15
0
       /*
       ===============
       SV_FindTouchedLeafs

       ===============
       */
       static void SV_FindTouchedLeafs(prog.edict_t ent, model.node_or_leaf_t node)
       {
           model.mplane_t splitplane;
           model.node_or_leaf_t leaf;
           int sides;
           int leafnum;

           if (node.contents == bspfile.CONTENTS_SOLID)
               return;

           // add an efrag if the node is a leaf

           if (node.contents < 0)
           {
               if (ent.num_leafs == prog.MAX_ENT_LEAFS)
                   return;

               leaf = (model.node_or_leaf_t)node;
               int i;
               for ( i = 0; i < server.sv.worldmodel.leafs.Length; i++)
               {
                   var mleafT = server.sv.worldmodel.leafs[i];
                   if (mleafT == leaf)
                   {
                       break;
                   }
               }
               leafnum = i - 1;
               ent.leafnums[ent.num_leafs] = (short)leafnum;
               ent.num_leafs++;
               //Debug.WriteLine("num_leafs " + ent.num_leafs);
               //Debug.WriteLine("leafnum_ " + leafnum);
               return;
           }

           // NODE_MIXED

           splitplane = ((model.mnode_t)node).plane;
           sides = mathlib.BOX_ON_PLANE_SIDE(ent.v.absmin, ent.v.absmax, splitplane);

           // recurse down the contacted sides
           if ((sides & 1) != 0)
               SV_FindTouchedLeafs(ent, ((model.mnode_t)node).children[0]);

           if ((sides & 2) !=0)
               SV_FindTouchedLeafs(ent, ((model.mnode_t)node).children[1]);
       }
Ejemplo n.º 16
0
        /*
        ================
        R_AliasTransformFinalVert
        ================
        */
        static void R_AliasTransformFinalVert(draw.finalvert_t fv, auxvert_t av,
            model.trivertx_t pverts, model.stvert_t pstverts)
        {
            int		    temp;
            double      lightcos;
            double[]    plightnormal;

            av.fv[0] = mathlib.DotProduct(pverts.v, aliastransform[0]) +
                    aliastransform[0][3];
            av.fv[1] = mathlib.DotProduct(pverts.v, aliastransform[1]) +
                    aliastransform[1][3];
            av.fv[2] = mathlib.DotProduct(pverts.v, aliastransform[2]) +
                    aliastransform[2][3];

            fv.v[2] = pstverts.s;
            fv.v[3] = pstverts.t;

            fv.flags = pstverts.onseam;

            // lighting
            plightnormal = r_avertexnormals[pverts.lightnormalindex];
            lightcos = mathlib.DotProduct(plightnormal, r_plightvec);
            temp = r_ambientlight;

            if (lightcos < 0)
            {
                temp += (int)(r_shadelight * lightcos);

            // clamp; because we limited the minimum ambient and shading light, we
            // don't have to clamp low light, just bright
                if (temp < 0)
                    temp = 0;
            }

            fv.v[4] = temp;
        }
Ejemplo n.º 17
0
        /*
        ===============================================================================

        POINT TESTING IN HULLS

        ===============================================================================
        */


        /*
        ==================
        SV_HullPointContents

        ==================
        */
        public static int SV_HullPointContents(model.hull_t hull, int num, double[] p)
        {
            double d;
            bspfile.dclipnode_t node;
            model.mplane_t plane;

            while (num >= 0)
            {
                if (num < hull.firstclipnode || num > hull.lastclipnode)
                    sys_linux.Sys_Error("SV_HullPointContents: bad node number");

                node = hull.clipnodes[num];
                plane = hull.planes[node.planenum];

                if (plane.type < 3)
                    d = p[plane.type] - plane.dist;
                else
                    d = mathlib.DotProduct(plane.normal, p) - plane.dist;
                if (d < 0)
                    num = node.children[1];
                else
                    num = node.children[0];
            }

            //Debug.WriteLine("SV_HullPointContents " + num);
            return num;
        }
Ejemplo n.º 18
0
        /*
        ==================
        BoxOnPlaneSide

        Returns 1, 2, or 1 + 2
        ==================
        */
        static int BoxOnPlaneSide(double[] emins, double[] emaxs, model.mplane_t p)
        {
            double	dist1, dist2;
            int		sides;

            /*	// this is done by the BOX_ON_PLANE_SIDE macro before calling this
                // function
            // fast axial cases
            if (p.type < 3)
            {
                if (p.dist <= emins[p.type])
                    return 1;
                if (p.dist >= emaxs[p.type])
                    return 2;
                return 3;
            }
            */

            // general case
            switch (p.signbits)
            {
            case 0:
            dist1 = p.normal[0]*emaxs[0] + p.normal[1]*emaxs[1] + p.normal[2]*emaxs[2];
            dist2 = p.normal[0]*emins[0] + p.normal[1]*emins[1] + p.normal[2]*emins[2];
                break;
            case 1:
            dist1 = p.normal[0]*emins[0] + p.normal[1]*emaxs[1] + p.normal[2]*emaxs[2];
            dist2 = p.normal[0]*emaxs[0] + p.normal[1]*emins[1] + p.normal[2]*emins[2];
                break;
            case 2:
            dist1 = p.normal[0]*emaxs[0] + p.normal[1]*emins[1] + p.normal[2]*emaxs[2];
            dist2 = p.normal[0]*emins[0] + p.normal[1]*emaxs[1] + p.normal[2]*emins[2];
                break;
            case 3:
            dist1 = p.normal[0]*emins[0] + p.normal[1]*emins[1] + p.normal[2]*emaxs[2];
            dist2 = p.normal[0]*emaxs[0] + p.normal[1]*emaxs[1] + p.normal[2]*emins[2];
                break;
            case 4:
            dist1 = p.normal[0]*emaxs[0] + p.normal[1]*emaxs[1] + p.normal[2]*emins[2];
            dist2 = p.normal[0]*emins[0] + p.normal[1]*emins[1] + p.normal[2]*emaxs[2];
                break;
            case 5:
            dist1 = p.normal[0]*emins[0] + p.normal[1]*emaxs[1] + p.normal[2]*emins[2];
            dist2 = p.normal[0]*emaxs[0] + p.normal[1]*emins[1] + p.normal[2]*emaxs[2];
                break;
            case 6:
            dist1 = p.normal[0]*emaxs[0] + p.normal[1]*emins[1] + p.normal[2]*emins[2];
            dist2 = p.normal[0]*emins[0] + p.normal[1]*emaxs[1] + p.normal[2]*emaxs[2];
                break;
            case 7:
            dist1 = p.normal[0]*emins[0] + p.normal[1]*emins[1] + p.normal[2]*emins[2];
            dist2 = p.normal[0]*emaxs[0] + p.normal[1]*emaxs[1] + p.normal[2]*emaxs[2];
                break;
            default:
                dist1 = dist2 = 0;		// shut up compiler
                BOPS_Error ();
                break;
            }

            sides = 0;
            if (dist1 >= p.dist)
                sides = 1;
            if (dist2 < p.dist)
                sides |= 2;

            return sides;
        }
Ejemplo n.º 19
0
        public static bool SV_RecursiveHullCheck(
            model.hull_t hull, int num, double p1f, double p2f, double[] p1, double[] p2, trace_t trace)
        {

            bspfile.dclipnode_t node;
            model.mplane_t plane;
            double t1, t2;
            double frac;
            int i;
            double[] mid = new double[3] {0, 0, 0};
            int side;
            double midf;

            //Debug.WriteLine(string.Format("SV_RecursiveHullCheck hull.firstclipnode:{0} num:{1} {2:F6} {3:F6} p1[0] {4:F6} p1[1] {5:F6}  p1[2] {6:F6} -  p2[0] {7:F6} p2[1] {8:F6} p2[2] {9:F6} num_hullcheck: {10}", hull.firstclipnode, num, (float)p1f, (float)p2f, (float)p1[0], (float)p1[1], (float)p1[2], (float)p2[0], (float)p2[1], (float)p2[2], num_hullcheck));
            num_hullcheck++;
            // check for empty
            if (num < 0)
            {
                if (num != bspfile.CONTENTS_SOLID)
                {
                    trace.allsolid = false;
                    if (num == bspfile.CONTENTS_EMPTY) 
                        trace.inopen = true;
                    else 
                        trace.inwater = true;
                }
                else trace.startsolid = true;

                //Debug.WriteLine(string.Format("empty"));
                return true; // empty
            }

            if (num < hull.firstclipnode || num > hull.lastclipnode) 
                sys_linux.Sys_Error("SV_RecursiveHullCheck: bad node number");

            //
            // find the point distances
            //
            node = hull.clipnodes[num];
            plane = hull.planes[node.planenum];

            if (plane.type < 3)
            {
                t1 = p1[plane.type] - plane.dist;
                t2 = p2[plane.type] - plane.dist;
            }
            else
            {
                t1 = mathlib.DotProduct(plane.normal, p1) - plane.dist;
                t2 = mathlib.DotProduct(plane.normal, p2) - plane.dist;
            }
            //Debug.WriteLine(string.Format("t1: {0:F6} t2: {1:F6}", (float)t1, (float)t2));

            if (t1 >= 0 && t2 >= 0)
            {
                return SV_RecursiveHullCheck(hull, node.children[0], p1f, p2f, p1, p2, trace);
            }
            if (t1 < 0 && t2 < 0)
            {
                return SV_RecursiveHullCheck(hull, node.children[1], p1f, p2f, p1, p2, trace);
            }


            // put the crosspoint DIST_EPSILON pixels on the near side
            if (t1 < 0) frac = (t1 + DIST_EPSILON) / (t1 - t2);
            else frac = (t1 - DIST_EPSILON) / (t1 - t2);
            if (frac < 0) frac = 0;
            if (frac > 1) frac = 1;

            midf = p1f + (p2f - p1f) * frac;
            for (i = 0; i < 3; i++) mid[i] = p1[i] + frac * (p2[i] - p1[i]);

            side = (t1 < 0) ? 1 : 0;


            // move up to the node
            if (!SV_RecursiveHullCheck(hull, node.children[side], p1f, midf, p1, mid, trace))
            {
                return false;
            }

            if (SV_HullPointContents(hull, node.children[side ^ 1], mid) != bspfile.CONTENTS_SOLID) // go past the node
            {
                return SV_RecursiveHullCheck(hull, node.children[side ^ 1], midf, p2f, mid, p2, trace);
            }

            if (trace.allsolid) 
            {
                return false; // never got out of the solid area
            }

            //==================
            // the other side of the node is solid, this is the impact point
            //==================
            if (side == 0)
            {
                mathlib.VectorCopy(plane.normal, trace.plane.normal);
                trace.plane.dist = plane.dist;
            }
            else
            {
                mathlib.VectorSubtract(mathlib.vec3_origin, plane.normal, trace.plane.normal);
                trace.plane.dist = -plane.dist;
            }

            while (SV_HullPointContents(hull, hull.firstclipnode, mid) == bspfile.CONTENTS_SOLID)
            {
                // shouldn't really happen, but does occasionally
                frac -= 0.1;
                if (frac < 0)
                {
                    trace.fraction = midf;
                    mathlib.VectorCopy(mid, trace.endpos);
                    console.Con_DPrintf("backup past 0\n");
                    return false;
                }
                midf = p1f + (p2f - p1f) * frac;
                for (i = 0; i < 3; i++) 
                    mid[i] = p1[i] + frac * (p2[i] - p1[i]);
            }

            trace.fraction = midf;
            mathlib.VectorCopy(mid, trace.endpos);

            return false;
        }
Ejemplo n.º 20
0
        /*
        ==============
        D_CalcGradients
        ==============
        */
        static void D_CalcGradients(model.msurface_t pface)
        {
            model.mplane_t  pplane;
            double          mipscale;
            double[]        p_temp1 = new double[3];
            double[]        p_saxis = new double[3], p_taxis = new double[3];
            double          t;

            pplane = pface.plane;

            mipscale = 1.0 / (double)(1 << miplevel);

            render.TransformVector(pface.texinfo.vecs[0], ref p_saxis);
            render.TransformVector(pface.texinfo.vecs[1], ref p_taxis);

            t = render.xscaleinv * mipscale;
            d_sdivzstepu = p_saxis[0] * t;
            d_tdivzstepu = p_taxis[0] * t;

            t = render.yscaleinv * mipscale;
            d_sdivzstepv = -p_saxis[1] * t;
            d_tdivzstepv = -p_taxis[1] * t;

            d_sdivzorigin = p_saxis[2] * mipscale - render.xcenter * d_sdivzstepu -
                    render.ycenter * d_sdivzstepv;
            d_tdivzorigin = p_taxis[2] * mipscale - render.xcenter * d_tdivzstepu -
                    render.ycenter * d_tdivzstepv;

            mathlib.VectorScale(transformed_modelorg, mipscale, ref p_temp1);

            t = 0x10000 * mipscale;
            sadjust = ((int)(mathlib.DotProduct(p_temp1, p_saxis) * 0x10000 + 0.5)) -
                    ((pface.texturemins[0] << 16) >> miplevel)
                    + (int)(pface.texinfo.vecs[0][3] * t);
            tadjust = ((int)(mathlib.DotProduct(p_temp1, p_taxis) * 0x10000 + 0.5)) -
                    ((pface.texturemins[1] << 16) >> miplevel)
                    + (int)(pface.texinfo.vecs[1][3] * t);

            //
            // -1 (-epsilon) so we never wander off the edge of the texture
            //
            bbextents = ((pface.extents[0] << 16) >> miplevel) - 1;
            bbextentt = ((pface.extents[1] << 16) >> miplevel) - 1;
        }
Ejemplo n.º 21
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.º 22
0
        /*
        =================
        CL_ParseBeam
        =================
        */
        static void CL_ParseBeam(model.model_t m)
        {
            int		    ent;
            double[]    start = new double[3], end = new double[3];
            beam_t	    b;
            int		    i;

            ent = common.MSG_ReadShort ();

            start[0] = common.MSG_ReadCoord();
            start[1] = common.MSG_ReadCoord();
            start[2] = common.MSG_ReadCoord();

            end[0] = common.MSG_ReadCoord();
            end[1] = common.MSG_ReadCoord();
            end[2] = common.MSG_ReadCoord();

            // override any beam with the same entity
            for (i = 0, b = cl_beams[i]; i < MAX_BEAMS; i++)
                b = cl_beams[i];
                if (b.entity == ent)
                {
                    b.entity = ent;
                    b.model = m;
                    b.endtime = cl.time + 0.2;
                    mathlib.VectorCopy (start, ref b.start);
                    mathlib.VectorCopy(end, ref b.end);
                    return;
                }

            // find a free beam
            for (i=0, b=cl_beams[i] ; i< MAX_BEAMS ; i++)
            {
                b = cl_beams[i];
                if (b.model == null || b.endtime < cl.time)
                {
                    b.entity = ent;
                    b.model = m;
                    b.endtime = cl.time + 0.2;
                    mathlib.VectorCopy (start, ref b.start);
                    mathlib.VectorCopy(end, ref b.end);
                    return;
                }
            }
            console.Con_Printf ("beam list overflow!\n");
        }
Ejemplo n.º 23
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] {0, 0, 0}, transformed = new double[3] {0, 0, 0};
            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, local);
                TransformVector (local, 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, local);
            TransformVector (local, 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;
        }