Пример #1
0
        private void MainPanel_Paint(object sender, PaintEventArgs e)
        {
            if (obj == null)
            {
                return;
            }

            e.Graphics.Clear(Color.Black);

            image = new Bitmap(e.ClipRectangle.Width, e.ClipRectangle.Height);

            provider = new BitmapProvider(image);
            graphics = new MyGraphics(provider);
            //graphics.Fill(Color.Black);

            int Width  = e.ClipRectangle.Width;
            int Height = e.ClipRectangle.Height;

            Vec3f zero = new Vec3f(0, 0, 0);

            Vec3f ligth = new Vec3f(
                ((float)e.ClipRectangle.Width / 2 - x) / (Width / 2),
                (y - (float)e.ClipRectangle.Height / 2) / (Height / 2),
                z);

            ligth = zero - ligth;

            ligth.Normalize();

            //graphics.DrawLine(new Vec2i(200, 200), new Vec2i(x, y), Color.White);
            graphics.DrawObject(obj, Color.White, ligth, c);
            graphics.DrawLight(ligth, Width / 2);
            e.Graphics.DrawImage(image, 0, 0);
        }
Пример #2
0
        public void InitQuads()
        {
            quadTilesRef?.Dispose();
            float height = 200;

            MeshData mesh = new MeshData(4, 6, false, true, true, false);
            float    x = 0, y = 0, z = 0;
            Random   rnd = new Random();

            for (int i = 0; i < 15; i++)
            {
                Vec3f dir = new Vec3f((float)rnd.NextDouble() * 20 - 10, (float)rnd.NextDouble() * 5 - 3, (float)rnd.NextDouble() * 20 - 10);
                dir.Normalize();
                x = (float)rnd.NextDouble() * 800 - 400;
                y = (float)rnd.NextDouble() * 80 - 40;
                z = (float)rnd.NextDouble() * 800 - 400;


                for (int j = 0; j < 100; j++)
                {
                    float lngx = (float)rnd.NextDouble() * 5 + 20;
                    float lngy = (float)rnd.NextDouble() * 4 + 4;
                    float lngz = (float)rnd.NextDouble() * 5 + 20;

                    x += dir.X * lngx;
                    y += dir.Y * lngy;
                    z += dir.Z * lngz;

                    //float width = 20 + (float)rnd.NextDouble() * 5;

                    //MeshData quad = QuadMeshUtil.GetCustomQuad(z, 20, x, x - prevx, height, 255, 255, 255, 255);
                    //mesh.AddMeshData(quad);

                    int lastelement = mesh.VerticesCount;

                    mesh.AddVertex(x, y + height, z, j % 2, 1);
                    mesh.AddVertex(x, y, z, j % 2, 0);

                    if (j > 0 && j < 19)
                    {
                        mesh.AddIndex(lastelement + 0);
                        mesh.AddIndex(lastelement + 1);
                        mesh.AddIndex(lastelement + 2);
                        mesh.AddIndex(lastelement + 1);
                        mesh.AddIndex(lastelement + 3);
                        mesh.AddIndex(lastelement + 2);
                    }
                }
            }

            quadTilesRef = capi.Render.UploadMesh(mesh);
        }
Пример #3
0
        //private Matrix DoubleArrayToMatrix(double[] m)
        //{
        //    return new Matrix(new double[,] {
        //        { m[00], m[04], m[08], m[12] },
        //        { m[01], m[05], m[09], m[13] },
        //        { m[02], m[06], m[10], m[14] },
        //        { m[03], m[07], m[11], m[15] }
        //    });
        //}

        //public Matrix GetGLModelMatrix()
        //{
        //    double[] m = new double[16];
        //    GL.GetDouble(GetPName.ModelviewMatrix, m);
        //    return DoubleArrayToMatrix(m);
        //}

        //public Matrix GetGLProjectionMatrix()
        //{
        //    double[] m = new double[16];
        //    GL.GetDouble(GetPName.ProjectionMatrix, m);
        //    return DoubleArrayToMatrix(m);
        //}
        #endregion

        public void Set(Vec3f tar, Quatf rot, float dist)
        {
            rot       = rot.Normalize();
            this.qrot = rot;
            this.dist = dist;
            Vec3f _forward = rot.Rotate(Vec3f.Y);
            Vec3f _up      = rot.Rotate(Vec3f.Z);

            Position = tar - _forward * dist;
            Scale    = 50.0f / dist;
            Forward  = Vec3f.Normalize(_forward);
            Target   = tar;
            Up       = _up;
        }
Пример #4
0
        public void DrawObject(Object3D obj, Color color, Vec3f lightDirection, float c = 5)
        {
            var Width           = graphicsProvider.Width;
            var Height          = graphicsProvider.Height;
            var vertexesFromMem = new Vec3f[3];
            var vertexes        = new Vec3i[3];

            for (int i = 0; i < graphicsProvider.Width; i++)
            {
                for (int j = 0; j < graphicsProvider.Height; j++)
                {
                    zbuffer[i, j] = Int32.MinValue;
                }
            }


            foreach (var face in obj.Faces)
            {
                //Работает медленно
                vertexesFromMem[0] = (obj.Vertexes.ElementAt(face.v1.v - 1));
                vertexesFromMem[1] = (obj.Vertexes.ElementAt(face.v2.v - 1));
                vertexesFromMem[2] = (obj.Vertexes.ElementAt(face.v3.v - 1));
                for (int i = 0; i < vertexes.Length; i++)
                {
                    Vec3f v = vertexesFromMem[i];
                    v          *= c;
                    vertexes[i] = new Vec3i(new Vec3f(Width / 2, Height / 2, 0) - new Vec3f(-v.X, v.Y, -v.Z));
                }

                //color = Color.FromArgb(random.Next(255), random.Next(255), random.Next(255));

                Vec3f normal = Vec3f.VecMul(vertexesFromMem[2] - vertexesFromMem[0], vertexesFromMem[1] - vertexesFromMem[0]);
                normal.Normalize();
                float intensity = normal * lightDirection;
                if (intensity > 1.0f)
                {
                    //Костыль
                    intensity = 1.0f;
                }
                if (intensity > 0)
                {
                    DrawTriangle(vertexes[0], vertexes[1], vertexes[2], Color.FromArgb(
                                     (int)(color.R * intensity),
                                     (int)(color.G * intensity),
                                     (int)(color.B * intensity)
                                     ));
                }
            }
        }
Пример #5
0
        public override bool OnHeldInteractStep(float secondsUsed, IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            if (blockSel == null)
            {
                return(false);
            }

            if (byEntity.World is IClientWorldAccessor)
            {
                ModelTransform tf = new ModelTransform();
                tf.EnsureDefaultValues();

                float offset = GameMath.Clamp(secondsUsed * 3, 0, 2f);

                tf.Translation.Set(-offset, offset / 4f, 0);

                byEntity.Controls.UsingHeldItemTransformBefore = tf;
            }

            SimpleParticleProperties bees = BlockEntityBeehive.Bees;
            BlockPos pos  = blockSel.Position;
            Random   rand = byEntity.World.Rand;

            Vec3d startPos = new Vec3d(pos.X + rand.NextDouble(), pos.Y + rand.NextDouble() * 0.25f, pos.Z + rand.NextDouble());
            Vec3d endPos   = new Vec3d(byEntity.LocalPos.X, byEntity.LocalPos.Y + byEntity.EyeHeight - 0.2f, byEntity.LocalPos.Z);

            Vec3f minVelo = new Vec3f((float)(endPos.X - startPos.X), (float)(endPos.Y - startPos.Y), (float)(endPos.Z - startPos.Z));

            minVelo.Normalize();
            minVelo *= 2;

            bees.minPos               = startPos;
            bees.minVelocity          = minVelo;
            bees.WithTerrainCollision = true;

            IPlayer byPlayer = null;

            if (byEntity is IEntityPlayer)
            {
                byPlayer = byEntity.World.PlayerByUid(((IEntityPlayer)byEntity).PlayerUID);
            }

            byEntity.World.SpawnParticles(bees, byPlayer);

            return(secondsUsed < 4);
        }
Пример #6
0
        public ContactData(Vec3f worldPointA, Vec3f localPointA, Vec3f worldPointB, Vec3f localPointB, Vec3f normal, float depth)
        {
            this.localPointA = localPointA;
            this.localPointB = localPointB;
            this.worldPointA = worldPointA;
            this.worldPointB = worldPointB;
            this.depth       = depth;
            this.normal      = normal;

            if (normal.x >= 0.57735f)
            {
                tang1 = new Vec3f(normal.y, -normal.x, 0);
            }
            else
            {
                tang1 = new Vec3f(0.0f, normal.z, -normal.y);
            }

            tang1.Normalize();
            tang2 = Vec3f.Cross(normal, tang1);
        }
Пример #7
0
        /*public void OrbitTargetUpDownNatural( double theta_degrees )
         *      {
         *              float fn = Forward.Val % NaturalUp.Val;
         *              if( ( theta_degrees < 0.0 && fn >= 0.95f ) || ( theta_degrees > 0.0 && fn <= -0.95f ) ) return;
         *
         *              double theta = theta_degrees * Math.PI / 180.0;
         *              Vec3f posreltar = Position.Val - Target.Val;
         *              Vec3f right = Forward.Val ^ NaturalUp.Val;
         *              float dist = (Target.Val - Position.Val).Length;
         *
         *              Properties.DeferPropertyChanged = true;
         *              bIgnoreChanges = true;
         *              Position.Set( Target.Val + Vec3f.Normalize( VecExtensions.RotateVectorAroundAxis( posreltar, right, (float) theta ) ) * dist );
         *              Up.Set( VecExtensions.RotateVectorAroundAxis( Up.Val, right, (float) theta ) );
         *              bIgnoreChanges = false;
         *              Target.Set( Target.Val );
         *              Properties.DeferPropertyChanged = false;
         *      }*/

        public void OrbitTargetUpDown(double theta_degrees, bool clampflips)
        {
            double theta  = theta_degrees * Math.PI / 180.0;
            Quatf  newrot = qrot * Quatf.AxisAngleToQuatf(GetRight(), (float)theta);

            if (clampflips)
            {
                // prevent camera from flipping over!
                Vec3f newup = Vec3f.Normalize(newrot.Rotate(Vec3f.Y));
                float dot   = FMath.PI / 2.0f - Vec3f.AngleBetween(newup, NaturalUp.Val);
                if (dot < 0)
                {
                    Vec3f newforward = Vec3f.Normalize(newrot.Rotate(-Vec3f.Z));
                    Vec3f newright   = newforward ^ newup;
                    float sign       = -Math.Sign(newforward % NaturalUp.Val);
                    newrot = newrot * Quatf.RotAxisAngleToQuatf(newright, dot * sign);
                }
            }

            Set(Target.Val, newrot, dist);
        }
Пример #8
0
        public void Set(Vec3f tar, Quatf rot, float dist)
        {
            rot = rot.Normalize();

            /*if( AlwaysUp )
             *          {
             *                  // prevent camera from rolling
             *                  Vec3f newright = Vec3f.Normalize( rot.Rotate( Vec3f.X ) );
             *                  Vec3f newup = Vec3f.Normalize( rot.Rotate( Vec3f.Y ) );
             *                  Vec3f newforward = Vec3f.Normalize( rot.Rotate( -Vec3f.Z ) );
             *
             *                  if( Math.Abs( newforward % NaturalUp ) < 0.95f ) {
             *                          Vec3f goodright = Vec3f.Normalize( newforward ^ Vec3f.Z );
             *                          float dot = Vec3f.AngleBetween( goodright, newright );
             *                          System.Console.WriteLine( newup.ToStringFormatted() + "  " + newright.ToStringFormatted() + "  " + goodright.ToStringFormatted() );
             *                          float sign = -Math.Sign( newright % NaturalUp );
             *                          //rot = rot * Quatf.RotAxisAngleToQuatf( newforward, dot * sign );
             *                  }
             *          }*/

            this.qrot = rot;
            this.dist = dist;

            Properties.DeferPropertyChanged = true;
            bIgnoreChanges = true;

            Vec3f fwd = rot.Rotate(-Vec3f.Z);
            Vec3f up  = rot.Rotate(Vec3f.Y);

            Position.Set(tar - fwd * dist);
            Scale.Set(50.0f / dist);
            Target.Set(tar);
            Forward.Set(Vec3f.Normalize(fwd));
            Up.Set(up);

            bIgnoreChanges = false;
            Properties.DeferPropertyChanged = false;
        }
Пример #9
0
        public SnapshotModel(string sFilename)
        {
            int nverts   = 0;
            int nfaces   = 0;
            int nvertsel = 0;
            //int nedgesel = 0;
            //int nfacesel = 0;
            int nmods = 0;

            Vec3f[] coords;

            int[]      selected;
            Modifier[] modifiers;

            using (Stream s = new FileStream(sFilename, FileMode.Open))
            {
                string plyline = FileIOFunctions.ReadTextString(s);
                if (plyline != "ply")
                {
                    throw new ArgumentException("TVModel.LoadObjectFromPLY: Specified file is not .ply file");
                }

                bool header = true;
                while (header)
                {
                    string cmd = FileIOFunctions.ReadTextString(s);
                    switch (cmd)
                    {
                    case "format":
                    case "comment":
                    case "property":
                        while (s.ReadByte() != 10)
                        {
                            ;                            // ignore the rest of the line
                        }
                        break;

                    case "element":
                        string variable = FileIOFunctions.ReadTextString(s);
                        int    val      = FileIOFunctions.ReadTextInteger(s);
                        switch (variable)
                        {
                        case "vertex": nverts = val; break;

                        case "face": nfaces = val; break;

                        case "selected":
                            nvertsel = val;
                            FileIOFunctions.ReadTextInteger(s);         // nedgesel =
                            FileIOFunctions.ReadTextInteger(s);         // nfacesel =
                            break;

                        case "modifiers": nmods = val; break;

                        default: throw new Exception("TVModel.LoadObjectFromPLY: Unhandled element type " + variable);
                        }
                        break;

                    case "end_header": header = false; break;

                    default: throw new Exception("TVModel.LoadObjectFromPLY: Unhandled command type " + cmd);
                    }
                }

                coords    = new Vec3f[nverts];
                selected  = new int[nvertsel];
                modifiers = new Modifier[nmods];
                groups    = new List <GroupInfo>[] {
                    new List <GroupInfo>(nverts), new List <GroupInfo>(nfaces), new List <GroupInfo>(nfaces), new List <GroupInfo>(nfaces)
                };
                groupselected = new List <bool>[] {
                    new List <bool>(nverts), new List <bool>(nverts), new List <bool>(nverts), new List <bool>(nverts)
                };
                facenormals = new List <Vec3f>[] { new List <Vec3f>(), new List <Vec3f>() };

                // read vert locations and visibility
                for (int i = 0; i < nverts; i++)
                {
                    coords[i] = new Vec3f(FileIOFunctions.ReadTextFloat(s), FileIOFunctions.ReadTextFloat(s), FileIOFunctions.ReadTextFloat(s));
                    bool v = (FileIOFunctions.ReadTextInteger(s) == 1);
                    groups[0].Add(new GroupInfo(new int[] { i }, v));
                }

                // read inds of edges and faces
                for (int i = 0; i < nfaces; i++)
                {
                    int   count = FileIOFunctions.ReadTextInteger(s);
                    int[] inds  = new int[count];
                    for (int j = 0; j < count; j++)
                    {
                        inds[j] = FileIOFunctions.ReadTextInteger(s);
                    }
                    bool v    = (FileIOFunctions.ReadTextInteger(s) == 1);
                    bool gsel = (FileIOFunctions.ReadTextInteger(s) == 1);
                    groups[count - 1].Add(new GroupInfo(inds, v));
                    groupselected[count - 1].Add(gsel);

                    if (count == 3 || count == 4)
                    {
                        Vec3f v0 = Vec3f.Normalize(coords[inds[0]] - coords[inds[1]]);
                        Vec3f v1 = Vec3f.Normalize(coords[inds[2]] - coords[inds[1]]);
                        Vec3f vn = v1 ^ v0;
                        if (vn.LengthSqr > 0.00001f)
                        {
                            facenormals[count - 3].Add(Vec3f.Normalize(vn));
                        }
                        else
                        {
                            facenormals[count - 3].Add(new Vec3f());
                        }
                    }
                }

                groups[1].TrimExcess();
                groups[2].TrimExcess();
                groups[3].TrimExcess();
                groupselected[1].TrimExcess();
                groupselected[2].TrimExcess();
                groupselected[3].TrimExcess();

                // read inds of selected verts
                for (int i = 0; i < nvertsel; i++)
                {
                    selected[i] = FileIOFunctions.ReadTextInteger(s);
                }

                // read modifiers
                for (int i = 0; i < nmods; i++)
                {
                    string modifier = FileIOFunctions.ReadTextString(s);
                    switch (modifier)
                    {
                    case "mirror":
                        modifiers[i] = new ModifierMirror()
                        {
                            name           = FileIOFunctions.ReadTextQuotedString(s),
                            usex           = (FileIOFunctions.ReadTextInteger(s) == 1),
                            usey           = (FileIOFunctions.ReadTextInteger(s) == 1),
                            usez           = (FileIOFunctions.ReadTextInteger(s) == 1),
                            mergethreshold = FileIOFunctions.ReadTextFloat(s)
                        };
                        break;

                    /*case "subdiv":
                     *  modifiers[i] = new ModifierSubDiv() {
                     *      name = FileIOFunctions.ReadTextQuotedString(s),
                     *      levels = FileIOFunctions.ReadTextInteger(s)
                     *  };
                     *  break;
                     * case "boolop":
                     *  modifiers[i] = new ModifierBoolOp
                     *      (
                     *       FileIOFunctions.ReadTextQuotedString(s),
                     *       ModifierBoolOp.StringToBoolOp( FileIOFunctions.ReadTextString(s) ),
                     *       FileIOFunctions.ReadTextString(s)
                     *       );
                     *  break;
                     * case "solidify":
                     *  modifiers[i] = new ModifierSolidify
                     *      (
                     *       FileIOFunctions.ReadTextString(s),
                     *       FileIOFunctions.ReadTextFloat(s),
                     *       FileIOFunctions.ReadTextFloat(s),
                     *       FileIOFunctions.ReadTextFloat(s),
                     *       FileIOFunctions.ReadTextFloat(s),
                     *       FileIOFunctions.ReadTextFloat(s),
                     *       ( FileIOFunctions.ReadTextInteger(s) == 1 ),
                     *       ( FileIOFunctions.ReadTextInteger(s) == 1 ),
                     *       ( FileIOFunctions.ReadTextInteger(s) == 1 )
                     *       );
                     *  break;*/
                    default: throw new Exception("TVModel.LoadObjectFromPLY: Unknown modifier " + modifier);
                    }
                }
            }

            this.verts     = coords;
            this.selinds   = selected;
            this.modifiers = modifiers;

            this.nverts = nverts;
            FillIsVertSelected();
            CalcVertexNormals();
        }
Пример #10
0
        /// <summary>
        /// Loads the meta information for each block in the schematic.
        /// </summary>
        /// <param name="blockAccessor"></param>
        /// <param name="worldForResolve"></param>
        /// <param name="fileNameForLogging"></param>
        public void LoadMetaInformationAndValidate(IBlockAccessor blockAccessor, IWorldAccessor worldForResolve, string fileNameForLogging)
        {
            List <BlockPos>  undergroundPositions = new List <BlockPos>();
            Queue <BlockPos> pathwayPositions     = new Queue <BlockPos>();

            HashSet <AssetLocation> missingBlocks = new HashSet <AssetLocation>();

            for (int i = 0; i < Indices.Count; i++)
            {
                uint index         = Indices[i];
                int  storedBlockid = BlockIds[i];

                int dx = (int)(index & 0x1ff);
                int dy = (int)((index >> 20) & 0x1ff);
                int dz = (int)((index >> 10) & 0x1ff);

                AssetLocation blockCode = BlockCodes[storedBlockid];
                Block         newBlock  = blockAccessor.GetBlock(blockCode);

                if (newBlock == null)
                {
                    missingBlocks.Add(blockCode);
                }

                if (newBlock != pathwayBlock && newBlock != undergroundBlock)
                {
                    continue;
                }

                BlockPos pos = new BlockPos(dx, dy, dz);

                if (newBlock == pathwayBlock)
                {
                    pathwayPositions.Enqueue(pos);
                }
                else
                {
                    undergroundPositions.Add(pos);
                }
            }

            if (missingBlocks.Count > 0)
            {
                worldForResolve.Logger.Warning("Block schematic file {0} uses blocks that could no longer be found. These will turn into air blocks! (affected: {1})", fileNameForLogging, string.Join(",", missingBlocks));
            }

            HashSet <AssetLocation> missingItems = new HashSet <AssetLocation>();

            foreach (var val in ItemCodes)
            {
                if (worldForResolve.GetItem(val.Value) == null)
                {
                    missingItems.Add(val.Value);
                }
            }

            if (missingItems.Count > 0)
            {
                worldForResolve.Logger.Warning("Block schematic file {0} uses items that could no longer be found. These will turn into unknown items! (affected: {1})", fileNameForLogging, string.Join(",", missingItems));
            }


            UndergroundCheckPositions = undergroundPositions.ToArray();


            List <List <BlockPos> > pathwayslist = new List <List <BlockPos> >();

            if (pathwayPositions.Count == 0)
            {
                this.PathwayStarts  = new BlockPos[0];
                this.PathwayOffsets = new BlockPos[0][];
                this.PathwaySides   = new BlockFacing[0];
                return;
            }


            while (pathwayPositions.Count > 0)
            {
                List <BlockPos> pathway = new List <BlockPos>()
                {
                    pathwayPositions.Dequeue()
                };
                pathwayslist.Add(pathway);

                int i = pathwayPositions.Count;

                while (i-- > 0)
                {
                    BlockPos pos   = pathwayPositions.Dequeue();
                    bool     found = false;

                    for (int j = 0; j < pathway.Count; j++)
                    {
                        BlockPos ppos     = pathway[j];
                        int      distance = Math.Abs(pos.X - ppos.X) + Math.Abs(pos.Y - ppos.Y) + Math.Abs(pos.Z - ppos.Z);

                        if (distance == 1)
                        {
                            found = true;
                            pathway.Add(pos);
                            break;
                        }
                    }

                    if (!found)
                    {
                        pathwayPositions.Enqueue(pos);
                    }
                    else
                    {
                        i = pathwayPositions.Count;
                    }
                }
            }



            PathwayStarts  = new BlockPos[pathwayslist.Count];
            PathwayOffsets = new BlockPos[pathwayslist.Count][];
            PathwaySides   = new BlockFacing[pathwayslist.Count];


            for (int i = 0; i < PathwayStarts.Length; i++)
            {
                // Concept to determine on which side the door is:
                // 1. Iterate over every pathway block
                // 2. Calculate the vector between the schematic center point an the pathway block
                // 3. Get the average vector by summing up + divide by count
                // => this is now basically the centerpoint of the door!
                // 4. This final vector can now be used to determine the block facing

                Vec3f dirToMiddle = new Vec3f();

                List <BlockPos> pathway = pathwayslist[i];

                for (int j = 0; j < pathway.Count; j++)
                {
                    BlockPos pos = pathway[j];
                    dirToMiddle.X += pos.X - SizeX / 2f;
                    dirToMiddle.Y += pos.Y - SizeY / 2f;
                    dirToMiddle.Z += pos.Z - SizeZ / 2f;
                }

                dirToMiddle.Normalize();

                PathwaySides[i] = BlockFacing.FromNormal(dirToMiddle);
                BlockPos start = PathwayStarts[i] = pathwayslist[i][0].Copy();

                PathwayOffsets[i] = new BlockPos[pathwayslist[i].Count];

                for (int j = 0; j < pathwayslist[i].Count; j++)
                {
                    PathwayOffsets[i][j] = pathwayslist[i][j].Sub(start);
                }
            }
        }
Пример #11
0
        public void InitQuads()
        {
            quadTilesRef?.Dispose();
            float height = 200;

            MeshData mesh = new MeshData(4, 6, false, true, true, false);

            mesh.CustomFloats = new CustomMeshDataPartFloat(4);
            mesh.CustomFloats.InterleaveStride  = 4;
            mesh.CustomFloats.InterleaveOffsets = new int[] { 0 };
            mesh.CustomFloats.InterleaveSizes   = new int[] { 1 };

            float  x, y, z;
            Random rnd = new Random();

            float resolution = 1.5f;
            float spread     = 1.5f;

            float parts   = 20 * resolution;
            float advance = 1f / resolution;

            for (int i = 0; i < 15; i++)
            {
                Vec3f dir = new Vec3f((float)rnd.NextDouble() * 20 - 10, (float)rnd.NextDouble() * 5 - 3, (float)rnd.NextDouble() * 20 - 10);
                dir.Normalize();
                dir.Mul(advance);

                x = spread * ((float)rnd.NextDouble() * 800 - 400);
                y = spread * ((float)rnd.NextDouble() * 80 - 40);
                z = spread * ((float)rnd.NextDouble() * 800 - 400);


                for (int j = 0; j < parts + 2; j++)
                {
                    float lngx = (float)rnd.NextDouble() * 5 + 20;
                    float lngy = (float)rnd.NextDouble() * 4 + 4;
                    float lngz = (float)rnd.NextDouble() * 5 + 20;

                    x += dir.X * lngx;
                    y += dir.Y * lngy;
                    z += dir.Z * lngz;

                    int lastelement = mesh.VerticesCount;

                    mesh.AddVertex(x, y + height, z, j % 2, 1);
                    mesh.AddVertex(x, y, z, j % 2, 0);

                    float f = j / (parts - 1);
                    mesh.CustomFloats.Add(f, f);

                    if (j > 0 && j < (parts - 1))
                    {
                        mesh.AddIndex(lastelement + 1);
                        mesh.AddIndex(lastelement + 3);
                        mesh.AddIndex(lastelement + 2);
                        mesh.AddIndex(lastelement + 0);
                        mesh.AddIndex(lastelement + 1);
                        mesh.AddIndex(lastelement + 2);
                    }
                }
            }

            quadTilesRef = capi.Render.UploadMesh(mesh);
        }
Пример #12
0
 private static Vec3f NormalizeVector(Vec3f newvec, Vec3f oldvec)
 {
     return(Vec3f.Normalize(newvec));
 }
        public override void OnGameTick(float dt)
        {
            if (asyncSearchObject != null)
            {
                if (!asyncSearchObject.Finished)
                {
                    return;
                }

                AfterFoundPath();
            }

            if (!Active)
            {
                return;
            }

            bool nearHorizontally = false;
            int  offset           = 0;
            bool nearAllDirs      =
                IsNearTarget(offset++, ref nearHorizontally) ||
                IsNearTarget(offset++, ref nearHorizontally) ||
                IsNearTarget(offset++, ref nearHorizontally)
            ;

            if (nearAllDirs)
            {
                waypointToReachIndex  += offset;
                lastWaypointIncTotalMs = entity.World.ElapsedMilliseconds;
            }

            target = waypoints[Math.Min(waypoints.Count - 1, waypointToReachIndex)];

            bool onlastWaypoint = waypointToReachIndex == waypoints.Count - 1;

            if (waypointToReachIndex >= waypoints.Count)
            {
                Stop();
                OnGoalReached?.Invoke();
                return;
            }

            bool stuck =
                (entity.CollidedVertically && entity.Controls.IsClimbing) ||
                (entity.CollidedHorizontally && entity.ServerPos.Motion.Y <= 0) ||
                (nearHorizontally && !nearAllDirs && entity.Properties.Habitat == EnumHabitat.Land) ||
                (entity.CollidedHorizontally && waypoints.Count > 1 && waypointToReachIndex < waypoints.Count && entity.World.ElapsedMilliseconds - lastWaypointIncTotalMs > 2000)       // If it takes more than 2 seconds to reach next waypoint (waypoints are always 1 block apart)
                //|| (entity.Swimming && false)
            ;
            // This used to test motion, but that makes no sense, we want to test if the entity moved, not if it had motion


            double distsq = prevPrevPos.SquareDistanceTo(prevPos);

            stuck |= (distsq < 0.01 * 0.01) ? (entity.World.Rand.NextDouble() < GameMath.Clamp(1 - distsq * 1.2, 0.1, 0.9)) : false;


            // Test movement progress between two points in 150 millisecond intervalls
            prevPosAccum += dt;
            if (prevPosAccum > 0.2)
            {
                prevPosAccum = 0;
                prevPrevPos.Set(prevPos);
                prevPos.Set(entity.ServerPos.X, entity.ServerPos.Y, entity.ServerPos.Z);
            }

            // Long duration tests to make sure we're not just wobbling around in the same spot
            distCheckAccum += dt;
            if (distCheckAccum > 2)
            {
                distCheckAccum = 0;
                if (sqDistToTarget - lastDistToTarget < 0.1)
                {
                    stuck         = true;
                    stuckCounter += 30;
                }
                else if (!stuck)
                {
                    stuckCounter = 0;                 // Only reset the stuckCounter in same tick as doing this test; otherwise the stuckCounter gets set to 0 every 2 or 3 ticks even if the entity collided horizontally (because motion vecs get set to 0 after the collision, so won't collide in the successive tick)
                }
                lastDistToTarget = sqDistToTarget;
            }

            if (stuck)
            {
                stuckCounter++;
            }

            if (GlobalConstants.OverallSpeedMultiplier > 0 && stuckCounter > 40 / GlobalConstants.OverallSpeedMultiplier)
            {
                //entity.World.SpawnParticles(10, ColorUtil.WhiteArgb, prevPos, prevPos, new Vec3f(0, 0, 0), new Vec3f(0, -1, 0), 1, 1);
                Stop();
                OnStuck?.Invoke();
                return;
            }

            EntityControls controls = entity.MountedOn == null ? entity.Controls : entity.MountedOn.Controls;

            if (controls == null)
            {
                return;
            }

            targetVec.Set(
                (float)(target.X - entity.ServerPos.X),
                (float)(target.Y - entity.ServerPos.Y),
                (float)(target.Z - entity.ServerPos.Z)
                );
            targetVec.Normalize();

            float desiredYaw = 0;

            if (sqDistToTarget >= 0.01)
            {
                desiredYaw = (float)Math.Atan2(targetVec.X, targetVec.Z);
            }

            float nowMoveSpeed = movingSpeed;

            if (sqDistToTarget < 1)
            {
                nowMoveSpeed = Math.Max(0.005f, movingSpeed * Math.Max(sqDistToTarget, 0.2f));
            }

            float yawDist   = GameMath.AngleRadDistance(entity.ServerPos.Yaw, desiredYaw);
            float turnSpeed = curTurnRadPerSec * dt * GlobalConstants.OverallSpeedMultiplier * movingSpeed;

            entity.ServerPos.Yaw += GameMath.Clamp(yawDist, -turnSpeed, turnSpeed);
            entity.ServerPos.Yaw  = entity.ServerPos.Yaw % GameMath.TWOPI;



            double cosYaw = Math.Cos(entity.ServerPos.Yaw);
            double sinYaw = Math.Sin(entity.ServerPos.Yaw);

            controls.WalkVector.Set(sinYaw, GameMath.Clamp(targetVec.Y, -1, 1), cosYaw);
            controls.WalkVector.Mul(nowMoveSpeed * GlobalConstants.OverallSpeedMultiplier);

            // Make it walk along the wall, but not walk into the wall, which causes it to climb
            if (entity.Properties.RotateModelOnClimb && entity.Controls.IsClimbing && entity.ClimbingIntoFace != null && entity.Alive)
            {
                BlockFacing facing = entity.ClimbingIntoFace;
                if (Math.Sign(facing.Normali.X) == Math.Sign(controls.WalkVector.X))
                {
                    controls.WalkVector.X = 0;
                }

                if (Math.Sign(facing.Normali.Y) == Math.Sign(controls.WalkVector.Y))
                {
                    controls.WalkVector.Y = -controls.WalkVector.Y;
                }

                if (Math.Sign(facing.Normali.Z) == Math.Sign(controls.WalkVector.Z))
                {
                    controls.WalkVector.Z = 0;
                }
            }

            //   entity.World.SpawnParticles(0.3f, ColorUtil.WhiteAhsl, target, target, new Vec3f(), new Vec3f(), 0.1f, 0.1f, 3f, EnumParticleModel.Cube);

            if (entity.Properties.Habitat == EnumHabitat.Underwater)
            {
                controls.FlyVector.Set(controls.WalkVector);

                Vec3d pos                 = entity.Pos.XYZ;
                Block inblock             = entity.World.BlockAccessor.GetLiquidBlock((int)pos.X, (int)(pos.Y), (int)pos.Z);
                Block aboveblock          = entity.World.BlockAccessor.GetLiquidBlock((int)pos.X, (int)(pos.Y + 1), (int)pos.Z);
                float waterY              = (int)pos.Y + inblock.LiquidLevel / 8f + (aboveblock.IsLiquid() ? 9 / 8f : 0);
                float bottomSubmergedness = waterY - (float)pos.Y;

                // 0 = at swim line  1 = completely submerged
                float swimlineSubmergedness = GameMath.Clamp(bottomSubmergedness - ((float)entity.SwimmingOffsetY), 0, 1);
                swimlineSubmergedness = 1f - Math.Min(1f, swimlineSubmergedness + 0.5f);
                if (swimlineSubmergedness > 0f)
                {
                    //Push the fish back underwater if part is poking out ...  (may need future adaptation for sharks[?], probably by changing SwimmingOffsetY)
                    controls.FlyVector.Y = GameMath.Clamp(controls.FlyVector.Y, -0.04f, -0.02f) * (1f - swimlineSubmergedness);
                }
                else
                {
                    float factor = movingSpeed * GlobalConstants.OverallSpeedMultiplier / (float)Math.Sqrt(targetVec.X * targetVec.X + targetVec.Z * targetVec.Z);
                    controls.FlyVector.Y = targetVec.Y * factor;
                }

                if (entity.CollidedHorizontally)
                {
                    //TODO
                }
            }
            else if (entity.Swimming)
            {
                controls.FlyVector.Set(controls.WalkVector);

                Vec3d pos                 = entity.Pos.XYZ;
                Block inblock             = entity.World.BlockAccessor.GetLiquidBlock((int)pos.X, (int)(pos.Y), (int)pos.Z);
                Block aboveblock          = entity.World.BlockAccessor.GetLiquidBlock((int)pos.X, (int)(pos.Y + 1), (int)pos.Z);
                float waterY              = (int)pos.Y + inblock.LiquidLevel / 8f + (aboveblock.IsLiquid() ? 9 / 8f : 0);
                float bottomSubmergedness = waterY - (float)pos.Y;

                // 0 = at swim line
                // 1 = completely submerged
                float swimlineSubmergedness = GameMath.Clamp(bottomSubmergedness - ((float)entity.SwimmingOffsetY), 0, 1);
                swimlineSubmergedness = Math.Min(1, swimlineSubmergedness + 0.5f);
                controls.FlyVector.Y  = GameMath.Clamp(controls.FlyVector.Y, 0.02f, 0.04f) * swimlineSubmergedness;


                if (entity.CollidedHorizontally)
                {
                    controls.FlyVector.Y = 0.05f;
                }
            }
        }