コード例 #1
0
ファイル: FrustumCulling.cs プロジェクト: Archina/vsapi
        public bool SphereInFrustumAndRange(Sphere sphere, bool nowVisible, int lodLevel = 0)
        {
            double d;

            d = frustum00 * sphere.x + frustum01 * sphere.y + frustum02 * sphere.z + frustum03;
            if (d <= -sphere.radius)
            {
                return(false);
            }
            d = frustum10 * sphere.x + frustum11 * sphere.y + frustum12 * sphere.z + frustum13;
            if (d <= -sphere.radius)
            {
                return(false);
            }
            d = frustum20 * sphere.x + frustum21 * sphere.y + frustum22 * sphere.z + frustum23;
            if (d <= -sphere.radius)
            {
                return(false);
            }
            d = frustum30 * sphere.x + frustum31 * sphere.y + frustum32 * sphere.z + frustum33;
            if (d <= -sphere.radius)
            {
                return(false);
            }
            d = frustum40 * sphere.x + frustum41 * sphere.y + frustum42 * sphere.z + frustum43;
            if (d <= -sphere.radius)
            {
                return(false);
            }
            d = frustum50 * sphere.x + frustum51 * sphere.y + frustum52 * sphere.z + frustum53;
            if (d <= -sphere.radius)
            {
                return(false);
            }

            // Lod level 1: all stuff
            // Lod level 0: only high detail stuff


            double distance = playerPos.HorDistanceSqTo(sphere.x, sphere.z);


            return((distance < ViewDistanceSq && lodLevel == 1) || (lodBiasSq > 0 && distance < ViewDistanceSq * lodBiasSq + 32 * 32));
        }
コード例 #2
0
ファイル: FrustumCulling.cs プロジェクト: anegostudios/vsapi
        public bool SphereInFrustumAndRange(Sphere sphere, bool nowVisible, int lodLevel = 0)
        {
            double d;
            float  x      = sphere.x;
            float  y      = sphere.y;
            float  z      = sphere.z;
            float  radius = sphere.radius;

            d = frustum00 * x + frustum01 * y + frustum02 * z + frustum03;
            if (d <= -radius)
            {
                return(false);
            }
            d = frustum10 * x + frustum11 * y + frustum12 * z + frustum13;
            if (d <= -radius)
            {
                return(false);
            }
            d = frustum20 * x + frustum21 * y + frustum22 * z + frustum23;
            if (d <= -radius)
            {
                return(false);
            }
            d = frustum30 * x + frustum31 * y + frustum32 * z + frustum33;
            if (d <= -radius)
            {
                return(false);
            }
            d = frustum40 * x + frustum41 * y + frustum42 * z + frustum43;
            if (d <= -radius)
            {
                return(false);
            }
            d = frustum50 * x + frustum51 * y + frustum52 * z + frustum53;
            if (d <= -radius)
            {
                return(false);
            }

            // Lod level 3: implements Lod2: this is the mesh drawn at long distance  (may be empty)
            // Lod level 2: implements Lod2: this is the mesh drawn at short and medium view distance
            // Lod level 1: drawn at all view distance
            // Lod level 0: only high detail stuff


            double distance = playerPos.HorDistanceSqTo(x, z);

            switch (lodLevel)
            {
            case 0:
                return(lod0BiasSq > 0 && distance < ViewDistanceSq * lod0BiasSq + 32 * 32);

            case 1:
                return(distance < ViewDistanceSq);

            case 2:
                return(distance <= ViewDistanceSq * lod2BiasSq);

            case 3:
                return(distance > ViewDistanceSq * lod2BiasSq && distance < ViewDistanceSq);

            default:
                return(false);
            }
        }
コード例 #3
0
        public Stack <BlockPos> FindTree(IWorldAccessor world, BlockPos startPos, out string treeType)
        {
            Queue <Vec4i>      queue            = new Queue <Vec4i>();
            HashSet <BlockPos> checkedPositions = new HashSet <BlockPos>();
            Stack <BlockPos>   foundPositions   = new Stack <BlockPos>();

            treeType = "";


            Block block = world.BlockAccessor.GetBlock(startPos);

            if (block.Code == null)
            {
                return(foundPositions);
            }

            if (block.Code.Path.StartsWith("log-grown") || block.Code.Path.StartsWith("beehive-inlog-") || block.Code.Path.StartsWith("log-resin") || block.Code.Path.StartsWith("bamboo-grown-"))
            {
                treeType = block.FirstCodePart(2);

                queue.Enqueue(new Vec4i(startPos.X, startPos.Y, startPos.Z, 2));
                foundPositions.Push(startPos);
                checkedPositions.Add(startPos);
            }

            string logcode = block.Code.Path.StartsWith("bamboo") ? "bamboo-grown-" + treeType : "log-grown-" + treeType;

            if (block is BlockFernTree)
            {
                treeType = "fern";
                logcode  = "ferntree-normal";
                queue.Enqueue(new Vec4i(startPos.X, startPos.Y, startPos.Z, 2));
                foundPositions.Push(startPos);
                checkedPositions.Add(startPos);
            }

            string logcode2          = "log-resin-" + treeType;
            string logcode3          = "log-resinharvested-" + treeType;
            string leavescode        = block.Code.Path.StartsWith("bamboo") ? "bambooleaves-" + treeType + "-grown"  : "leaves-grown-" + treeType;
            string leavesbranchycode = "leavesbranchy-grown-" + treeType;



            while (queue.Count > 0)
            {
                if (foundPositions.Count > 2000)
                {
                    break;
                }

                Vec4i pos = queue.Dequeue();

                for (int i = 0; i < Vec3i.DirectAndIndirectNeighbours.Length; i++)
                {
                    Vec3i    facing  = Vec3i.DirectAndIndirectNeighbours[i];
                    BlockPos neibPos = new BlockPos(pos.X + facing.X, pos.Y + facing.Y, pos.Z + facing.Z);

                    float hordist  = GameMath.Sqrt(neibPos.HorDistanceSqTo(startPos.X, startPos.Z));
                    float vertdist = (neibPos.Y - startPos.Y);

                    // "only breaks blocks inside an upside down square base pyramid"
                    if (hordist - 1 >= 2 * vertdist)
                    {
                        continue;
                    }
                    if (checkedPositions.Contains(neibPos))
                    {
                        continue;
                    }

                    block = world.BlockAccessor.GetBlock(neibPos);
                    if (block.Code == null)
                    {
                        continue;
                    }

                    if (block.Code.Path.StartsWith(logcode) || block.Code.Path.StartsWith(logcode2) || block.Code.Path.StartsWith(logcode3))
                    {
                        if (pos.W < 2)
                        {
                            continue;
                        }

                        foundPositions.Push(neibPos.Copy());
                        queue.Enqueue(new Vec4i(neibPos.X, neibPos.Y, neibPos.Z, 2));
                    }
                    else if (block.Code.Path.StartsWith(leavesbranchycode))
                    {
                        if (pos.W < 1)
                        {
                            continue;
                        }

                        foundPositions.Push(neibPos.Copy());
                        queue.Enqueue(new Vec4i(neibPos.X, neibPos.Y, neibPos.Z, 1));
                    }
                    else if (block.Code.Path.StartsWith(leavescode))
                    {
                        foundPositions.Push(neibPos.Copy());
                        queue.Enqueue(new Vec4i(neibPos.X, neibPos.Y, neibPos.Z, 0));
                    }

                    checkedPositions.Add(neibPos);
                }
            }

            return(foundPositions);
        }
コード例 #4
0
        public void CmdMeasuringTape(int groupId, CmdArgs args)
        {
            WaypointUtilSystem wUtil = capi.ModLoader.GetModSystem <WaypointUtilSystem>();
            string             arg   = args.PopWord();

            switch (arg)
            {
            case "start":
                if (capi.World.Player.CurrentBlockSelection != null)
                {
                    start = capi.World.Player.CurrentBlockSelection.Position;
                    //capi.ShowChatMessage("Okay, start set to: " + start);
                    MakeHighlights();
                }
                else
                {
                    capi.ShowChatMessage("Please look at a block.");
                }
                break;

            case "end":
                if (capi.World.Player.CurrentBlockSelection != null)
                {
                    end = capi.World.Player.CurrentBlockSelection.Position;
                    //capi.ShowChatMessage("Okay, end set to: " + end);
                    MakeHighlights();
                }
                else
                {
                    capi.ShowChatMessage("Please look at a block.");
                }
                break;

            case "startwp":
                int?swpID = args.PopInt();
                if (swpID != null)
                {
                    start = wUtil.Waypoints[(int)swpID].Position.AsBlockPos;
                    MakeHighlights();
                }
                else
                {
                    capi.ShowChatMessage("Please enter a waypoint id.");
                }
                break;

            case "endwp":
                int?ewpID = args.PopInt();
                if (ewpID != null)
                {
                    end = wUtil.Waypoints[(int)ewpID].Position.AsBlockPos;
                    MakeHighlights();
                }
                else
                {
                    capi.ShowChatMessage("Please enter a waypoint id.");
                }
                break;

            case "calc":
                string type = args.PopWord();
                switch (type)
                {
                case "block":
                    capi.ShowChatMessage("Block Distance: " + Math.Round(start.DistanceTo(end) + 1));
                    break;

                case "euclidian":
                    capi.ShowChatMessage("Euclidian Distance: " + start.DistanceTo(end));
                    break;

                case "manhattan":
                    capi.ShowChatMessage("Manhattan Distance: " + start.ManhattenDistance(end));
                    break;

                case "horizontal":
                    capi.ShowChatMessage("Horizontal Distance: " + Math.Sqrt(start.HorDistanceSqTo(end.X, end.Z)));
                    break;

                case "horizontalmanhattan":
                    capi.ShowChatMessage("Horizontal Manhattan Distance: " + start.HorizontalManhattenDistance(end));
                    break;

                default:
                    capi.ShowChatMessage("Syntax: .measure calc [block|euclidian|manhattan|horizontal|horizontalmanhattan]");
                    break;
                }
                break;

            default:
                capi.ShowChatMessage("Syntax: .measure [start|end|calc]");
                break;
            }
        }
コード例 #5
0
        public Stack <BlockPos> FindTree(IWorldAccessor world, BlockPos startPos)
        {
            Queue <Vec4i>      queue            = new Queue <Vec4i>();
            HashSet <BlockPos> checkedPositions = new HashSet <BlockPos>();
            Stack <BlockPos>   foundPositions   = new Stack <BlockPos>();

            Block block = world.BlockAccessor.GetBlock(startPos);

            if (block.Code == null)
            {
                return(foundPositions);
            }

            string treeFellingGroupCode = block.Attributes?["treeFellingGroupCode"].AsString();
            int    spreadIndex          = block.Attributes?["treeFellingGroupSpreadIndex"].AsInt(0) ?? 0;

            if (block.Attributes?["treeFellingCanChop"].AsBool(true) == false)
            {
                return(foundPositions);
            }

            EnumTreeFellingBehavior bh = EnumTreeFellingBehavior.Chop;

            if (block is ICustomTreeFellingBehavior ctfbh)
            {
                bh = ctfbh.GetTreeFellingBehavior(startPos, null, spreadIndex);
                if (bh == EnumTreeFellingBehavior.NoChop)
                {
                    return(foundPositions);
                }
            }


            // Must start with a log
            if (spreadIndex < 2)
            {
                return(foundPositions);
            }
            if (treeFellingGroupCode == null)
            {
                return(foundPositions);
            }

            queue.Enqueue(new Vec4i(startPos.X, startPos.Y, startPos.Z, spreadIndex));
            foundPositions.Push(startPos);
            checkedPositions.Add(startPos);

            while (queue.Count > 0)
            {
                if (foundPositions.Count > 2500)
                {
                    break;
                }

                Vec4i pos = queue.Dequeue();

                block = world.BlockAccessor.GetBlock(pos.X, pos.Y, pos.Z);

                if (block is ICustomTreeFellingBehavior ctfbhh)
                {
                    bh = ctfbhh.GetTreeFellingBehavior(startPos, null, spreadIndex);
                }
                if (bh == EnumTreeFellingBehavior.NoChop)
                {
                    continue;
                }


                for (int i = 0; i < Vec3i.DirectAndIndirectNeighbours.Length; i++)
                {
                    Vec3i    facing  = Vec3i.DirectAndIndirectNeighbours[i];
                    BlockPos neibPos = new BlockPos(pos.X + facing.X, pos.Y + facing.Y, pos.Z + facing.Z);

                    float hordist  = GameMath.Sqrt(neibPos.HorDistanceSqTo(startPos.X, startPos.Z));
                    float vertdist = (neibPos.Y - startPos.Y);

                    // "only breaks blocks inside an upside down square base pyramid"
                    float f = bh == EnumTreeFellingBehavior.ChopSpreadVertical ? 0.5f : 2;
                    if (hordist - 1 >= f * vertdist)
                    {
                        continue;
                    }
                    if (checkedPositions.Contains(neibPos))
                    {
                        continue;
                    }

                    block = world.BlockAccessor.GetBlock(neibPos);
                    if (block.Code == null || block.Id == 0)
                    {
                        continue;
                    }

                    string ngcode = block.Attributes?["treeFellingGroupCode"].AsString();

                    // Only break the same type tree blocks
                    if (ngcode != treeFellingGroupCode)
                    {
                        continue;
                    }

                    // Only spread from "high to low". i.e. spread from log to leaves, but not from leaves to logs
                    int nspreadIndex = block.Attributes?["treeFellingGroupSpreadIndex"].AsInt(0) ?? 0;
                    if (pos.W < nspreadIndex)
                    {
                        continue;
                    }

                    checkedPositions.Add(neibPos);

                    if (bh == EnumTreeFellingBehavior.ChopSpreadVertical && !facing.Equals(0, 1, 0) && nspreadIndex > 0)
                    {
                        continue;
                    }

                    foundPositions.Push(neibPos.Copy());
                    queue.Enqueue(new Vec4i(neibPos.X, neibPos.Y, neibPos.Z, nspreadIndex));
                }
            }

            return(foundPositions);
        }