예제 #1
0
        //======================================================================================

        // Creates all needed model references in portal areas, chaining them to both the area and the entityDef. Bumps tr.viewCount.
        public static void R_CreateEntityRefs(IRenderEntity def)
        {
            int i; Vector3 v;
            var transformed = stackalloc Vector3[8];

            if (def.parms.hModel == null)
            {
                def.parms.hModel = renderModelManager.DefaultModel();
            }

            // if the entity hasn't been fully specified due to expensive animation calcs for md5 and particles, use the provided conservative bounds.
            def.referenceBounds = def.parms.callback != null ? def.parms.bounds : def.parms.hModel.Bounds(def.parms);

            // some models, like empty particles, may not need to be added at all
            if (def.referenceBounds.IsCleared)
            {
                return;
            }

            if (r_showUpdates.Bool && (
                    def.referenceBounds[1].x - def.referenceBounds[0].x > 1024 ||
                    def.referenceBounds[1].y - def.referenceBounds[0].y > 1024))
            {
                common.Printf($"big entityRef: {def.referenceBounds[1].x - def.referenceBounds[0].x},{def.referenceBounds[1].y - def.referenceBounds[0].y}\n");
            }

            for (i = 0; i < 8; i++)
            {
                v.x = def.referenceBounds[i & 1][0];
                v.y = def.referenceBounds[(i >> 1) & 1][1];
                v.z = def.referenceBounds[(i >> 2) & 1][2];
                R_LocalPointToGlobal(def.modelMatrix, v, out transformed[i]);
            }

            // bump the view count so we can tell if an area already has a reference
            tr.viewCount++;

            // push these points down the BSP tree into areas
            def.world.PushVolumeIntoTree(def, null, 8, transformed);
        }
예제 #2
0
        // are dangling edges that are outside the light frustum still making planes?
        public static SrfTriangles R_CreateVertexProgramTurboShadowVolume(IRenderEntity ent, SrfTriangles tri, IRenderLight light, ref SrfCullInfo cullInfo)
        {
            int i, j; SrfTriangles newTri; GlIndex[] indexes; byte *facing;
            var tri_indexes = tri.indexes; var tri_silEdges = tri.silEdges;

            R_CalcInteractionFacing(ent, tri, light, ref cullInfo);

            if (r_useShadowProjectedCull.Bool)
            {
                R_CalcInteractionCullBits(ent, tri, light, ref cullInfo);
            }

            var numFaces          = tri.numIndexes / 3;
            var numShadowingFaces = 0;

            facing = cullInfo.facing;

            // if all the triangles are inside the light frustum
            if (cullInfo.cullBits == Interaction.LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.Bool)
            {
                // count the number of shadowing faces
                for (i = 0; i < numFaces; i++)
                {
                    numShadowingFaces += facing[i];
                }
                numShadowingFaces = numFaces - numShadowingFaces;
            }
            else
            {
                // make all triangles that are outside the light frustum "facing", so they won't cast shadows
                indexes = tri_indexes;
                var modifyFacing = cullInfo.facing;
                var cullBits     = cullInfo.cullBits;

                for (j = i = 0; i < tri.numIndexes; i += 3, j++)
                {
                    if (modifyFacing[j] == 0)
                    {
                        var i1 = indexes[i + 0];
                        var i2 = indexes[i + 1];
                        var i3 = indexes[i + 2];

                        if ((cullBits[i1] & cullBits[i2] & cullBits[i3]) != 0)
                        {
                            modifyFacing[j] = 1;
                        }
                        else
                        {
                            numShadowingFaces++;
                        }
                    }
                }
            }

            // no faces are inside the light frustum and still facing the right way
            if (numShadowingFaces == 0)
            {
                return(null);
            }

            // shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface
            newTri = R_AllocStaticTriSurf();

            newTri.numVerts = tri.numVerts * 2;

            // alloc the max possible size
#if USE_TRI_DATA_ALLOCATOR
            R_AllocStaticTriSurfIndexes(newTri, (numShadowingFaces + tri.numSilEdges) * 6);
            GlIndex tempIndexes   = newTri.indexes;
            GlIndex shadowIndexes = newTri.indexes;
#else
            GlIndex *tempIndexes   = stackalloc GlIndex[tri.numSilEdges * 6 + intX.ALLOC16]; tempIndexes = (GlIndex *)_alloca16(tempIndexes);
            GlIndex *shadowIndexes = tempIndexes;
#endif

            // create new triangles along sil planes
            SilEdge sil;
            for (sil = tri_silEdges, i = tri.numSilEdges; i > 0; i--, sil++)
            {
                int f1 = facing[sil.p1], f2 = facing[sil.p2];

                if ((f1 ^ f2) == 0)
                {
                    continue;
                }

                int v1 = sil.v1 << 1, v2 = sil.v2 << 1;

                // set the two triangle winding orders based on facing without using a poorly-predictable branch

                shadowIndexes[0] = v1;
                shadowIndexes[1] = v2 ^ f1;
                shadowIndexes[2] = v2 ^ f2;
                shadowIndexes[3] = v1 ^ f2;
                shadowIndexes[4] = v1 ^ f1;
                shadowIndexes[5] = v2 ^ 1;

                shadowIndexes += 6;
            }

            int numShadowIndexes = shadowIndexes - tempIndexes;

            // we aren't bothering to separate front and back caps on these
            newTri.numIndexes             = newTri.numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
            newTri.numShadowIndexesNoCaps = numShadowIndexes;
            newTri.shadowCapPlaneBits     = SHADOW_CAP_INFINITE;

#if USE_TRI_DATA_ALLOCATOR
            // decrease the size of the memory block to only store the used indexes
            R_ResizeStaticTriSurfIndexes(newTri, newTri.numIndexes);
#else
            // allocate memory for the indexes
            R_AllocStaticTriSurfIndexes(newTri, newTri.numIndexes);
            // copy the indexes we created for the sil planes
            Simd.Memcpy(newTri.indexes, tempIndexes, numShadowIndexes * sizeof(GlIndex));
#endif

            // these have no effect, because they extend to infinity
            newTri.bounds.Clear();

            // put some faces on the model and some on the distant projection
            indexes       = tri_indexes;
            shadowIndexes = newTri.indexes + numShadowIndexes;

            for (i = 0, j = 0; i < tri.numIndexes; i += 3, j++)
            {
                if (facing[j] != 0)
                {
                    continue;
                }

                var i0 = indexes[i + 0] << 1; shadowIndexes[2] = i0; shadowIndexes[3] = i0 ^ 1;
                var i1 = indexes[i + 1] << 1; shadowIndexes[1] = i1; shadowIndexes[4] = i1 ^ 1;
                var i2 = indexes[i + 2] << 1; shadowIndexes[0] = i2; shadowIndexes[5] = i2 ^ 1;
                shadowIndexes += 6;
            }

            return(newTri);
        }