Beispiel #1
0
        // The ambientCache is on the stack, so we don't want to leave a reference to it that would try to be freed later.  Create the ambientCache immediately.
        static void R_FinishDeform(DrawSurf drawSurf, SrfTriangles newTri, DrawVert *ac)
        {
            if (newTri == null)
            {
                return;
            }

            // generate current normals, tangents, and bitangents We might want to support the possibility of deform functions generating
            // explicit normals, and we might also want to allow the cached deformInfo optimization for these.
            // FIXME: this doesn't work, because the deformed surface is just the ambient one, and there isn't an opportunity to generate light interactions
            if (drawSurf.material.ReceivesLighting)
            {
                newTri.verts = ac; R_DeriveTangents(newTri, false); newTri.verts = null;
            }
            newTri.ambientCache = vertexCache.AllocFrameTemp(ac, newTri.numVerts * DrawVert.SizeOf, false);

            fixed(void *newTri_indexes_ = newTri.indexes) newTri.indexCache = vertexCache.AllocFrameTemp(newTri_indexes_, newTri.numIndexes * sizeof(GlIndex), true);

            drawSurf.geoFrontEnd  = newTri;
            drawSurf.ambientCache = newTri.ambientCache;
            drawSurf.indexCache   = newTri.indexCache;
            drawSurf.numIndexes   = newTri.numIndexes;
            drawSurf.numShadowIndexesNoFrontCaps = newTri.numShadowIndexesNoFrontCaps;
            drawSurf.numShadowIndexesNoCaps      = newTri.numShadowIndexesNoCaps;
            drawSurf.shadowCapPlaneBits          = newTri.shadowCapPlaneBits;
        }
Beispiel #2
0
 public RenderModelDecal()
 {
     tri         = new();
     tri.verts   = verts;
     tri.indexes = indexes;
     material    = null;
     nextDecal   = null;
 }
Beispiel #3
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);
        }
Beispiel #4
0
 // If we know that we are "off to the side" of an infinite shadow volume, we can draw it without caps in zpass mode
 static bool R_PotentiallyInsideInfiniteShadow(SrfTriangles occluder, in Vector3 localView, in Vector3 localLight)
Beispiel #5
0
 // Calculates two axis for the surface sutch that a point dotted against the axis will give a 0.0 to 1.0 range in S and T when inside the gui surface
 public static void R_SurfaceToTextureAxis(SrfTriangles tri, ref Vector3 origin, Vector3 *axis)
 {
     float *d0 = stackalloc float[5], d1 = stackalloc float[5];
     var    bounds = stackalloc (float x, float y)[2];
Beispiel #6
0
 public void DrawTrail(int index, RenderEntity ent, SrfTriangles tri, float globalAlpha);
Beispiel #7
0
        // If we resort the vertexes so all silverts come first, we can save some work here.
        public unsafe static LocalTrace R_LocalTrace(Vector3 start, Vector3 end, float radius, SrfTriangles tri)
        {
            int        i, j;
            Plane *    planes = stackalloc Plane[4];
            LocalTrace hit = new();
            int        c_testEdges, c_testPlanes, c_intersect;
            Vector3    startDir;
            byte       totalOr;
            float      radiusSqr;
            var        tri_verts = tri.verts.Value; var tri_indexes = tri.indexes.Value; var tri_facePlanes = tri.facePlanes.Value;

#if TEST_TRACE
            Stopwatch trace_timer = new();
            trace_timer.Start();
#endif

            hit.fraction = 1f;

            // create two planes orthogonal to each other that intersect along the trace
            startDir = end - start;
            startDir.Normalize();
            startDir.NormalVectors(out planes[0].Normal, out planes[1].Normal);
            planes[0].d = -start * planes[0].Normal;
            planes[1].d = -start * planes[1].Normal;

            // create front and end planes so the trace is on the positive sides of both
            planes[2] = startDir; planes[2].d = -start * planes[2].Normal;
            planes[3] = -startDir; planes[3].d = -end * planes[3].Normal;

            // catagorize each point against the four planes
            var cullBits = stackalloc byte[tri.numVerts];

            fixed(DrawVert *vertsD = tri_verts) Simd.TracePointCull(cullBits, out totalOr, radius, planes, vertsD, tri.numVerts);

            // if we don't have points on both sides of both the ray planes, no intersection
            if (((totalOr ^ (totalOr >> 4)) & 3) != 0) /*common.Printf("nothing crossed the trace planes\n");*/ return {
                (hit);
            }

            // if we don't have any points between front and end, no intersection
            if (((totalOr ^ (totalOr >> 1)) & 4) != 0) /*common.Printf("trace didn't reach any triangles\n");*/ return {
                (hit);
            }

            // scan for triangles that cross both planes
            c_testPlanes = c_testEdges = c_intersect = 0;

            radiusSqr = MathX.Square(radius);
            startDir  = end - start;

            if (tri.facePlanes == null || !tri.facePlanesCalculated)
            {
                R_DeriveFacePlanes(tri);
            }

            for (i = 0, j = 0; i < tri.numIndexes; i += 3, j++)
            {
                float   d1, d2, f, d, edgeLengthSqr; byte triOr;
                Vector3 cross, edge; Vector3[] dir = new Vector3[3];

                // get sidedness info for the triangle
                triOr  = cullBits[tri_indexes[i + 0]];
                triOr |= cullBits[tri_indexes[i + 1]];
                triOr |= cullBits[tri_indexes[i + 2]];

                // if we don't have points on both sides of both the ray planes, no intersection
                if (((triOr ^ (triOr >> 4)) & 3) != 0)
                {
                    continue;
                }

                // if we don't have any points between front and end, no intersection
                if (((triOr ^ (triOr >> 1)) & 4) != 0)
                {
                    continue;
                }

                c_testPlanes++;

                ref Plane plane = ref tri_facePlanes[j];
                d1 = plane.Distance(start);
                d2 = plane.Distance(end);

                if (d1 <= d2)
                {
                    continue;                 // comning at it from behind or parallel
                }
                if (d1 < 0f)
                {
                    continue;                // starts past it
                }
                if (d2 > 0f)
                {
                    continue;                // finishes in front of it
                }
                f = d1 / (d1 - d2);
                if (f < 0f)
                {
                    continue;               // shouldn't happen
                }
                if (f >= hit.fraction)
                {
                    continue;                          // have already hit something closer
                }
                c_testEdges++;

                // find the exact point of impact with the plane
                var point = start + f * startDir;

                // see if the point is within the three edges if radius > 0 the triangle is expanded with a circle in the triangle plane

                dir[0] = tri_verts[tri_indexes[i + 0]].xyz - point;
                dir[1] = tri_verts[tri_indexes[i + 1]].xyz - point;

                cross = dir[0].Cross(dir[1]);
                d     = plane.Normal * cross;
                if (d > 0f)
                {
                    if (radiusSqr <= 0f)
                    {
                        continue;
                    }
                    edge          = tri_verts[tri_indexes[i + 0]].xyz - tri_verts[tri_indexes[i + 1]].xyz;
                    edgeLengthSqr = edge.LengthSqr;
                    if (cross.LengthSqr > edgeLengthSqr * radiusSqr)
                    {
                        continue;
                    }
                    d = edge * dir[0];
                    if (d < 0f)
                    {
                        edge = tri_verts[tri_indexes[i + 0]].xyz - tri_verts[tri_indexes[i + 2]].xyz;
                        d    = edge * dir[0];
                        if (d < 0f && dir[0].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                    else if (d > edgeLengthSqr)
                    {
                        edge = tri_verts[tri_indexes[i + 1]].xyz - tri_verts[tri_indexes[i + 2]].xyz;
                        d    = edge * dir[1];
                        if (d < 0f && dir[1].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                }

                dir[2] = tri_verts[tri_indexes[i + 2]].xyz - point;

                cross = dir[1].Cross(dir[2]);
                d     = plane.Normal * cross;
                if (d > 0f)
                {
                    if (radiusSqr <= 0f)
                    {
                        continue;
                    }
                    edge          = tri_verts[tri_indexes[i + 1]].xyz - tri_verts[tri_indexes[i + 2]].xyz;
                    edgeLengthSqr = edge.LengthSqr;
                    if (cross.LengthSqr > edgeLengthSqr * radiusSqr)
                    {
                        continue;
                    }
                    d = edge * dir[1];
                    if (d < 0f)
                    {
                        edge = tri_verts[tri_indexes[i + 1]].xyz - tri_verts[tri_indexes[i + 0]].xyz;
                        d    = edge * dir[1];
                        if (d < 0f && dir[1].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                    else if (d > edgeLengthSqr)
                    {
                        edge = tri_verts[tri_indexes[i + 2]].xyz - tri_verts[tri_indexes[i + 0]].xyz;
                        d    = edge * dir[2];
                        if (d < 0f && dir[2].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                }

                cross = dir[2].Cross(dir[0]);
                d     = plane.Normal * cross;
                if (d > 0f)
                {
                    if (radiusSqr <= 0f)
                    {
                        continue;
                    }
                    edge          = tri_verts[tri_indexes[i + 2]].xyz - tri_verts[tri_indexes[i + 0]].xyz;
                    edgeLengthSqr = edge.LengthSqr;
                    if (cross.LengthSqr > edgeLengthSqr * radiusSqr)
                    {
                        continue;
                    }
                    d = edge * dir[2];
                    if (d < 0f)
                    {
                        edge = tri_verts[tri_indexes[i + 2]].xyz - tri_verts[tri_indexes[i + 1]].xyz;
                        d    = edge * dir[2];
                        if (d < 0f && dir[2].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                    else if (d > edgeLengthSqr)
                    {
                        edge = tri_verts[tri_indexes[i + 0]].xyz - tri_verts[tri_indexes[i + 1]].xyz;
                        d    = edge * dir[0];
                        if (d < 0f && dir[0].LengthSqr > radiusSqr)
                        {
                            continue;
                        }
                    }
                }

                // we hit it
                c_intersect++;

                hit.fraction   = f;
                hit.normal     = plane.Normal;
                hit.point      = point;
                hit.indexes[0] = tri_indexes[i];
                hit.indexes[1] = tri_indexes[i + 1];
                hit.indexes[2] = tri_indexes[i + 2];
            }