Esempio n. 1
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;
        }
Esempio n. 2
0
 /*
  * ================
  * R_RenderPoly
  * ================
  */
 static void R_RenderPoly(model.msurface_t fa, int clipflags)
 {
 }
Esempio n. 3
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];
            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, ref 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++;
        }
Esempio n. 4
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];
            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, ref 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++;
        }
Esempio n. 5
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);
                        }
                    }
                }
            }
        }
Esempio n. 6
0
        //=============================================================================

        /*
         * ================
         * D_CacheSurface
         * ================
         */
        static surfcache_t D_CacheSurface(model.msurface_t surface, int miplevel)
        {
            surfcache_t cache;

            //
            // if the surface is animating or flashing, flush the cache
            //
            render.r_drawsurf.texture     = render.R_TextureAnimation(surface.texinfo.texture);
            render.r_drawsurf.lightadj[0] = render.d_lightstylevalue[surface.styles[0]];
            render.r_drawsurf.lightadj[1] = render.d_lightstylevalue[surface.styles[1]];
            render.r_drawsurf.lightadj[2] = render.d_lightstylevalue[surface.styles[2]];
            render.r_drawsurf.lightadj[3] = render.d_lightstylevalue[surface.styles[3]];

            //
            // see if the cache holds apropriate data
            //
            cache = surface.cachespots[miplevel];

            if (cache != null && cache.dlight == 0 && surface.dlightframe != render.r_framecount &&
                cache.texture == render.r_drawsurf.texture &&
                cache.lightadj[0] == render.r_drawsurf.lightadj[0] &&
                cache.lightadj[1] == render.r_drawsurf.lightadj[1] &&
                cache.lightadj[2] == render.r_drawsurf.lightadj[2] &&
                cache.lightadj[3] == render.r_drawsurf.lightadj[3])
            {
                return(cache);
            }

            //
            // determine shape of surface
            //
            surfscale = 1.0 / (1 << miplevel);
            render.r_drawsurf.surfmip    = miplevel;
            render.r_drawsurf.surfwidth  = surface.extents[0] >> miplevel;
            render.r_drawsurf.rowbytes   = render.r_drawsurf.surfwidth;
            render.r_drawsurf.surfheight = surface.extents[1] >> miplevel;

            //
            // allocate memory if needed
            //
            if (cache == null)         // if a texture just animated, don't reallocate it
            {
                cache = D_SCAlloc(render.r_drawsurf.surfwidth,
                                  render.r_drawsurf.surfwidth * render.r_drawsurf.surfheight);
                surface.cachespots[miplevel] = cache;
                cache.owner    = surface.cachespots[miplevel];
                cache.mipscale = surfscale;
            }

            if (surface.dlightframe == render.r_framecount)
            {
                cache.dlight = 1;
            }
            else
            {
                cache.dlight = 0;
            }

            render.r_drawsurf.surfdat = cache.data;

            cache.texture     = render.r_drawsurf.texture;
            cache.lightadj[0] = render.r_drawsurf.lightadj[0];
            cache.lightadj[1] = render.r_drawsurf.lightadj[1];
            cache.lightadj[2] = render.r_drawsurf.lightadj[2];
            cache.lightadj[3] = render.r_drawsurf.lightadj[3];

            //
            // draw and light the surface texture
            //
            render.r_drawsurf.surf = surface;

            render.c_surf++;
            render.R_DrawSurface();

            return(surface.cachespots[miplevel]);
        }