示例#1
0
        public static void SV_FatPVS(Single[] org)
        {
            Int32[] leafs = new Int32[64];
            Int32   i, j, count;
            Int32   longs;

            Byte[]   src;
            Single[] mins = new Single[] { 0, 0, 0 }, maxs = new Single[] { 0, 0, 0 };
            for (i = 0; i < 3; i++)
            {
                mins[i] = org[i] - 8;
                maxs[i] = org[i] + 8;
            }

            count = CM.CM_BoxLeafnums(mins, maxs, leafs, 64, null);
            if (count < 1)
            {
                Com.Error(Defines.ERR_FATAL, "SV_FatPVS: count < 1");
            }
            longs = (CM.CM_NumClusters() + 31) >> 5;
            for (i = 0; i < count; i++)
            {
                leafs[i] = CM.CM_LeafCluster(leafs[i]);
            }
            System.Array.Copy(CM.CM_ClusterPVS(leafs[0]), 0, SV_ENTS.fatpvs, 0, longs << 2);
            for (i = 1; i < count; i++)
            {
                for (j = 0; j < i; j++)
                {
                    if (leafs[i] == leafs[j])
                    {
                        break;
                    }
                }
                if (j != i)
                {
                    continue;
                }
                src = CM.CM_ClusterPVS(leafs[i]);
                var k = 0;
                for (j = 0; j < longs; j++)
                {
                    SV_ENTS.fatpvs[k] |= src[k++];
                    SV_ENTS.fatpvs[k] |= src[k++];
                    SV_ENTS.fatpvs[k] |= src[k++];
                    SV_ENTS.fatpvs[k] |= src[k++];
                }
            }
        }
示例#2
0
        public static void SV_LinkEdict(edict_t ent)
        {
            areanode_t node;
            int        num_leafs;
            int        j, k;
            int        area;
            int        topnode = 0;

            if (ent.area.prev != null)
            {
                SV_UnlinkEdict(ent);
            }
            if (ent == GameBase.g_edicts[0])
            {
                return;
            }
            if (!ent.inuse)
            {
                return;
            }
            Math3D.VectorSubtract(ent.maxs, ent.mins, ent.size);
            if (ent.solid == Defines.SOLID_BBOX && 0 == (ent.svflags & Defines.SVF_DEADMONSTER))
            {
                int i = (int)(ent.maxs[0] / 8);
                if (i < 1)
                {
                    i = 1;
                }
                if (i > 31)
                {
                    i = 31;
                }
                j = (int)((-ent.mins[2]) / 8);
                if (j < 1)
                {
                    j = 1;
                }
                if (j > 31)
                {
                    j = 31;
                }
                k = (int)((ent.maxs[2] + 32) / 8);
                if (k < 1)
                {
                    k = 1;
                }
                if (k > 63)
                {
                    k = 63;
                }
                ent.s.solid = (k << 10) | (j << 5) | i;
            }
            else if (ent.solid == Defines.SOLID_BSP)
            {
                ent.s.solid = 31;
            }
            else
            {
                ent.s.solid = 0;
            }
            if (ent.solid == Defines.SOLID_BSP && (ent.s.angles[0] != 0 || ent.s.angles[1] != 0 || ent.s.angles[2] != 0))
            {
                float max, v;
                max = 0;
                for (int i = 0; i < 3; i++)
                {
                    v = Math.Abs(ent.mins[i]);
                    if (v > max)
                    {
                        max = v;
                    }
                    v = Math.Abs(ent.maxs[i]);
                    if (v > max)
                    {
                        max = v;
                    }
                }

                for (int i = 0; i < 3; i++)
                {
                    ent.absmin[i] = ent.s.origin[i] - max;
                    ent.absmax[i] = ent.s.origin[i] + max;
                }
            }
            else
            {
                Math3D.VectorAdd(ent.s.origin, ent.mins, ent.absmin);
                Math3D.VectorAdd(ent.s.origin, ent.maxs, ent.absmax);
            }

            ent.absmin[0]--;
            ent.absmin[1]--;
            ent.absmin[2]--;
            ent.absmax[0]++;
            ent.absmax[1]++;
            ent.absmax[2]++;
            ent.num_clusters = 0;
            ent.areanum      = 0;
            ent.areanum2     = 0;
            int[] iw = new[] { topnode };
            num_leafs = CM.CM_BoxLeafnums(ent.absmin, ent.absmax, SV_WORLD.leafs, SV_WORLD.MAX_TOTAL_ENT_LEAFS, iw);
            topnode   = iw[0];
            for (int i = 0; i < num_leafs; i++)
            {
                SV_WORLD.clusters[i] = CM.CM_LeafCluster(SV_WORLD.leafs[i]);
                area = CM.CM_LeafArea(SV_WORLD.leafs[i]);
                if (area != 0)
                {
                    if (ent.areanum != 0 && ent.areanum != area)
                    {
                        if (ent.areanum2 != 0 && ent.areanum2 != area && SV_INIT.sv.state == Defines.ss_loading)
                        {
                            Com.DPrintf("Object touching 3 areas at " + ent.absmin[0] + " " + ent.absmin[1] + " " + ent.absmin[2] + "\\n");
                        }
                        ent.areanum2 = area;
                    }
                    else
                    {
                        ent.areanum = area;
                    }
                }
            }

            if (num_leafs >= SV_WORLD.MAX_TOTAL_ENT_LEAFS)
            {
                ent.num_clusters = -1;
                ent.headnode     = topnode;
            }
            else
            {
                ent.num_clusters = 0;
                for (int i = 0; i < num_leafs; i++)
                {
                    if (SV_WORLD.clusters[i] == -1)
                    {
                        continue;
                    }
                    for (j = 0; j < i; j++)
                    {
                        if (SV_WORLD.clusters[j] == SV_WORLD.clusters[i])
                        {
                            break;
                        }
                    }
                    if (j == i)
                    {
                        if (ent.num_clusters == Defines.MAX_ENT_CLUSTERS)
                        {
                            ent.num_clusters = -1;
                            ent.headnode     = topnode;
                            break;
                        }

                        ent.clusternums[ent.num_clusters++] = SV_WORLD.clusters[i];
                    }
                }
            }

            if (0 == ent.linkcount)
            {
                Math3D.VectorCopy(ent.s.origin, ent.s.old_origin);
            }

            ent.linkcount++;
            if (ent.solid == Defines.SOLID_NOT)
            {
                return;
            }
            node = SV_WORLD.sv_areanodes[0];
            while (true)
            {
                if (node.axis == -1)
                {
                    break;
                }
                if (ent.absmin[node.axis] > node.dist)
                {
                    node = node.children[0];
                }
                else if (ent.absmax[node.axis] < node.dist)
                {
                    node = node.children[1];
                }
                else
                {
                    break;
                }
            }

            if (ent.solid == Defines.SOLID_TRIGGER)
            {
                InsertLinkBefore(ent.area, node.trigger_edicts);
            }
            else
            {
                InsertLinkBefore(ent.area, node.solid_edicts);
            }
        }
示例#3
0
        public static void SV_LinkEdict(edict_t ent)
        {
            areanode_t node;
            int        num_leafs;
            int        j, k;
            int        area;
            var        topnode = 0;

            if (ent.area.prev != null)
            {
                SV_WORLD.SV_UnlinkEdict(ent);                 // unlink from old position
            }
            if (ent == GameBase.g_edicts[0])
            {
                return;                 // don't add the world
            }
            if (!ent.inuse)
            {
                return;
            }

            // set the size
            Math3D.VectorSubtract(ent.maxs, ent.mins, ent.size);

            // encode the size into the entity_state for client prediction
            if (ent.solid == Defines.SOLID_BBOX && 0 == (ent.svflags & Defines.SVF_DEADMONSTER))
            {
                // assume that x/y are equal and symetric
                var i = (int)(ent.maxs[0] / 8);

                if (i < 1)
                {
                    i = 1;
                }

                if (i > 31)
                {
                    i = 31;
                }

                // z is not symetric
                j = (int)(-ent.mins[2] / 8);

                if (j < 1)
                {
                    j = 1;
                }

                if (j > 31)
                {
                    j = 31;
                }

                // and z maxs can be negative...
                k = (int)((ent.maxs[2] + 32) / 8);

                if (k < 1)
                {
                    k = 1;
                }

                if (k > 63)
                {
                    k = 63;
                }

                ent.s.solid = (k << 10) | (j << 5) | i;
            }
            else if (ent.solid == Defines.SOLID_BSP)
            {
                ent.s.solid = 31;                 // a solid_bbox will never create this value
            }
            else
            {
                ent.s.solid = 0;
            }

            // set the abs box
            if (ent.solid == Defines.SOLID_BSP && (ent.s.angles[0] != 0 || ent.s.angles[1] != 0 || ent.s.angles[2] != 0))
            {
                // expand for rotation
                float max, v;
                max = 0;

                for (var i = 0; i < 3; i++)
                {
                    v = Math.Abs(ent.mins[i]);

                    if (v > max)
                    {
                        max = v;
                    }

                    v = Math.Abs(ent.maxs[i]);

                    if (v > max)
                    {
                        max = v;
                    }
                }

                for (var i = 0; i < 3; i++)
                {
                    ent.absmin[i] = ent.s.origin[i] - max;
                    ent.absmax[i] = ent.s.origin[i] + max;
                }
            }
            else
            {
                // normal
                Math3D.VectorAdd(ent.s.origin, ent.mins, ent.absmin);
                Math3D.VectorAdd(ent.s.origin, ent.maxs, ent.absmax);
            }

            // because movement is clipped an epsilon away from an actual edge,
            // we must fully check even when bounding boxes don't quite touch
            ent.absmin[0]--;
            ent.absmin[1]--;
            ent.absmin[2]--;
            ent.absmax[0]++;
            ent.absmax[1]++;
            ent.absmax[2]++;

            // link to PVS leafs
            ent.num_clusters = 0;
            ent.areanum      = 0;
            ent.areanum2     = 0;

            // get all leafs, including solids
            int[] iw = { topnode };
            num_leafs = CM.CM_BoxLeafnums(ent.absmin, ent.absmax, SV_WORLD.leafs, SV_WORLD.MAX_TOTAL_ENT_LEAFS, iw);
            topnode   = iw[0];

            // set areas
            for (var i = 0; i < num_leafs; i++)
            {
                SV_WORLD.clusters[i] = CM.CM_LeafCluster(SV_WORLD.leafs[i]);
                area = CM.CM_LeafArea(SV_WORLD.leafs[i]);

                if (area != 0)
                {
                    // doors may legally straggle two areas,
                    // but nothing should evern need more than that
                    if (ent.areanum != 0 && ent.areanum != area)
                    {
                        if (ent.areanum2 != 0 && ent.areanum2 != area && SV_INIT.sv.state == Defines.ss_loading)
                        {
                            Com.DPrintf("Object touching 3 areas at " + ent.absmin[0] + " " + ent.absmin[1] + " " + ent.absmin[2] + "\n");
                        }

                        ent.areanum2 = area;
                    }
                    else
                    {
                        ent.areanum = area;
                    }
                }
            }

            if (num_leafs >= SV_WORLD.MAX_TOTAL_ENT_LEAFS)
            {
                // assume we missed some leafs, and mark by headnode
                ent.num_clusters = -1;
                ent.headnode     = topnode;
            }
            else
            {
                ent.num_clusters = 0;

                for (var i = 0; i < num_leafs; i++)
                {
                    if (SV_WORLD.clusters[i] == -1)
                    {
                        continue;                         // not a visible leaf
                    }
                    for (j = 0; j < i; j++)
                    {
                        if (SV_WORLD.clusters[j] == SV_WORLD.clusters[i])
                        {
                            break;
                        }
                    }

                    if (j == i)
                    {
                        if (ent.num_clusters == Defines.MAX_ENT_CLUSTERS)
                        {
                            // assume we missed some leafs, and mark by headnode
                            ent.num_clusters = -1;
                            ent.headnode     = topnode;

                            break;
                        }

                        ent.clusternums[ent.num_clusters++] = SV_WORLD.clusters[i];
                    }
                }
            }

            // if first time, make sure old_origin is valid
            if (0 == ent.linkcount)
            {
                Math3D.VectorCopy(ent.s.origin, ent.s.old_origin);
            }

            ent.linkcount++;

            if (ent.solid == Defines.SOLID_NOT)
            {
                return;
            }

            // find the first node that the ent's box crosses
            node = SV_WORLD.sv_areanodes[0];

            while (true)
            {
                if (node.axis == -1)
                {
                    break;
                }

                if (ent.absmin[node.axis] > node.dist)
                {
                    node = node.children[0];
                }
                else if (ent.absmax[node.axis] < node.dist)
                {
                    node = node.children[1];
                }
                else
                {
                    break;                     // crosses the node
                }
            }

            // link it in
            if (ent.solid == Defines.SOLID_TRIGGER)
            {
                SV_WORLD.InsertLinkBefore(ent.area, node.trigger_edicts);
            }
            else
            {
                SV_WORLD.InsertLinkBefore(ent.area, node.solid_edicts);
            }
        }
示例#4
0
        /**
         * The client will interpolate the view position, so we can't use a single
         * PVS point.
         */
        public static void SV_FatPVS(float[] org)
        {
            var leafs = new int[64];
            int i, j, count;
            int longs;

            byte[]  src;
            float[] mins = { 0, 0, 0 }, maxs = { 0, 0, 0 };

            for (i = 0; i < 3; i++)
            {
                mins[i] = org[i] - 8;
                maxs[i] = org[i] + 8;
            }

            count = CM.CM_BoxLeafnums(mins, maxs, leafs, 64, null);

            if (count < 1)
            {
                Com.Error(Defines.ERR_FATAL, "SV_FatPVS: count < 1");
            }

            longs = (CM.CM_NumClusters() + 31) >> 5;

            // convert leafs to clusters
            for (i = 0; i < count; i++)
            {
                leafs[i] = CM.CM_LeafCluster(leafs[i]);
            }

            Array.Copy(CM.CM_ClusterPVS(leafs[0]), 0, SV_ENTS.fatpvs, 0, longs << 2);

            // or in all the other leaf bits
            for (i = 1; i < count; i++)
            {
                for (j = 0; j < i; j++)
                {
                    if (leafs[i] == leafs[j])
                    {
                        break;
                    }
                }

                if (j != i)
                {
                    continue;                     // already have the cluster we want
                }
                src = CM.CM_ClusterPVS(leafs[i]);

                //for (j=0 ; j<longs ; j++)
                //	((long *)fatpvs)[j] |= ((long *)src)[j];
                var k = 0;

                for (j = 0; j < longs; j++)
                {
                    SV_ENTS.fatpvs[k] |= src[k++];
                    SV_ENTS.fatpvs[k] |= src[k++];
                    SV_ENTS.fatpvs[k] |= src[k++];
                    SV_ENTS.fatpvs[k] |= src[k++];
                }
            }
        }