/**
  * @brief Increases box's local scale by 1% while collision with a ball remains active.
  **/
 public void OnSyncedCollisionStay(FPCollision other)
 {
     if (other.gameObject.name == "Box(Clone)")
     {
         Debug.Log("OnSyncedCollisionStay:other:" + other.transform.name);
         other.gameObject.transform.localScale *= 1.01f;
     }
 }
 /**
  * @brief Tints box's material with gray color when it collides with the ball.
  **/
 public void OnSyncedCollisionEnter(FPCollision other)
 {
     if (other.gameObject.name == "Box(Clone)")
     {
         Debug.Log("OnSyncedCollisionEnter:other:" + other.transform.name);
         other.gameObject.GetComponent <Renderer>().material.color = Color.gray;
     }
 }
 /**
  * @brief Resets changes in box's properties when there is no more collision with the ball.
  **/
 public void OnSyncedCollisionExit(FPCollision other)
 {
     if (other.gameObject.name == "Box(Clone)")
     {
         Debug.Log("OnSyncedCollisionExit:other:" + other.transform.name);
         other.gameObject.transform.localScale = Vector3.one;
         other.gameObject.GetComponent <Renderer>().material.color = Color.blue;
     }
 }
Beispiel #4
0
 public void OnSyncedTriggerEnter(FPCollision other)
 {
     if (other.gameObject.tag == "Player")
     {
         PlayerBehaviour hitPlayer = other.gameObject.GetComponent <PlayerBehaviour>();
         //if (hitPlayer.owner.id != owner.id)
         {
             //FPS_Manager.SyncedDestroy(this.gameObject);
             //hitPlayer.Respawn();
         }
     }
 }
Beispiel #5
0
        static Boolean TriangleContains(NavMeshTriangle[] ts, NavMeshVertex[] vs, FPVector2 point)
        {
            for (Int32 i = 0; i < ts.Length; ++i)
            {
                var t = ts[i];

                if (FPCollision.TriangleContainsPoint(point, vs[t.Vertex0].Point, vs[t.Vertex1].Point, vs[t.Vertex2].Point))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #6
0
        public static NavMesh BakeNavMesh(MapData data, MapNavMeshDefinition navmeshDefinition)
        {
            try {
                FPMathUtils.LoadLookupTables();

                var vs_array     = navmeshDefinition.Vertices.ToArray();
                var nav_vertices = vs_array.Map(x => new NavMeshVertex {
                    Point = x.Position.ToFPVector2(), Neighbors = new Int32[0], Triangles = new Int32[0], Borders = new Int32[0]
                });
                var nav_triangles = new NavMeshTriangle[0];

                // TRIANGLES
                for (Int32 i = 0; i < navmeshDefinition.Triangles.Length; ++i)
                {
                    Progress("Baking NavMesh '" + navmeshDefinition.name + "': Calculating Triangles", i, navmeshDefinition.Triangles.Length);

                    var t = navmeshDefinition.Triangles[i];

                    var v0 = Array.FindIndex(vs_array, x => x.Id == t.VertexIds[0]);
                    var v1 = Array.FindIndex(vs_array, x => x.Id == t.VertexIds[1]);
                    var v2 = Array.FindIndex(vs_array, x => x.Id == t.VertexIds[2]);

                    ArrayUtils.Add(ref nav_triangles, new NavMeshTriangle {
                        Vertex0 = v0,
                        Vertex1 = v1,
                        Vertex2 = v2,
                        Center  = (nav_vertices[v0].Point + nav_vertices[v1].Point + nav_vertices[v2].Point) / FP._3
                    });
                }


                // TRIANGLE GRID
                var nav_triangles_grid = new NavMeshTriangleNode[data.Asset.Settings.GridSize * data.Asset.Settings.GridSize];

                //for (Int32 i = 0; i < nav_triangles_grid.Length; ++i) {
                //  nav_triangles_grid[i] = i + 1;
                //}

                for (Int32 i = 0; i < nav_triangles.Length; ++i)
                {
                    Progress("Baking NavMesh '" + navmeshDefinition.name + "': Calculating Triangle Grid", i, nav_triangles.Length);

                    var v0 = nav_vertices[nav_triangles[i].Vertex0].Point;
                    var v1 = nav_vertices[nav_triangles[i].Vertex1].Point;
                    var v2 = nav_vertices[nav_triangles[i].Vertex2].Point;

                    for (Int32 z = 0; z < data.Asset.Settings.GridSize; ++z)
                    {
                        for (Int32 x = 0; x < data.Asset.Settings.GridSize; ++x)
                        {
                            var bl = data.Asset.Settings.WorldOffset + new FPVector2(x * data.Asset.Settings.GridNodeSize, z * data.Asset.Settings.GridNodeSize);
                            var br = bl + new FPVector2(data.Asset.Settings.GridNodeSize, 0);
                            var ur = bl + new FPVector2(data.Asset.Settings.GridNodeSize, data.Asset.Settings.GridNodeSize);
                            var ul = bl + new FPVector2(0, data.Asset.Settings.GridNodeSize);

                            if (
                                // if any of the corners are inside the triangle
                                FPCollision.TriangleContainsPoint(bl, v0, v1, v2) ||
                                FPCollision.TriangleContainsPoint(br, v0, v1, v2) ||
                                FPCollision.TriangleContainsPoint(ur, v0, v1, v2) ||
                                FPCollision.TriangleContainsPoint(ul, v0, v1, v2) ||

                                // BL => BR
                                FPCollision.TriangleContainsPoint(v0, v1, bl, br) ||
                                FPCollision.TriangleContainsPoint(v1, v2, bl, br) ||
                                FPCollision.TriangleContainsPoint(v2, v0, bl, br) ||

                                // BR => UR
                                FPCollision.TriangleContainsPoint(v0, v1, br, ur) ||
                                FPCollision.TriangleContainsPoint(v1, v2, br, ur) ||
                                FPCollision.TriangleContainsPoint(v2, v0, br, ur) ||

                                // UR => UL
                                FPCollision.TriangleContainsPoint(v0, v1, ur, ul) ||
                                FPCollision.TriangleContainsPoint(v1, v2, ur, ul) ||
                                FPCollision.TriangleContainsPoint(v2, v0, ur, ul) ||

                                // UL => BL
                                FPCollision.TriangleContainsPoint(v0, v1, ul, bl) ||
                                FPCollision.TriangleContainsPoint(v1, v2, ul, bl) ||
                                FPCollision.TriangleContainsPoint(v2, v0, ul, bl)
                                )
                            {
                                var idx = (z * data.Asset.Settings.GridSize) + x;

                                if (nav_triangles_grid[idx].Triangles == null)
                                {
                                    nav_triangles_grid[idx].Triangles = new Int32[0];
                                }

                                // add triangle to this grid node
                                ArrayUtils.Add(ref nav_triangles_grid[idx].Triangles, i);
                            }
                        }
                    }
                }

                // VERTEX NEIGHBORS

                for (Int32 v = 0; v < nav_vertices.Length; ++v)
                {
                    Progress("Baking NavMesh '" + navmeshDefinition.name + "': Calculating Vertex Neighbors", v, nav_vertices.Length);

                    var triangles = new HashSet <Int32>();
                    var neighbors = new HashSet <Int32>();

                    for (Int32 t = 0; t < nav_triangles.Length; ++t)
                    {
                        var tr = nav_triangles[t];
                        if (tr.Vertex0 == v || tr.Vertex1 == v || tr.Vertex2 == v)
                        {
                            triangles.Add(t);

                            neighbors.Add(tr.Vertex0);
                            neighbors.Add(tr.Vertex1);
                            neighbors.Add(tr.Vertex2);
                        }
                    }

                    // remove itself from neighbors set
                    neighbors.Remove(v);

                    //
                    nav_vertices[v].Triangles = triangles.OrderBy(x => x).ToArray();
                    nav_vertices[v].Neighbors = neighbors.ToArray();
                }

                // BORDER EDGES

                for (Int32 t = 0; t < nav_triangles.Length; ++t)
                {
                    Progress("Baking NavMesh '" + navmeshDefinition.name + "': Calculating Border Edges", t, nav_triangles.Length);

                    var tr = nav_triangles[t];
                    if (IsBorderEdge(nav_triangles, t, tr.Vertex0, tr.Vertex1))
                    {
                        ArrayUtils.Add(ref nav_vertices[tr.Vertex0].Borders, tr.Vertex1);
                        ArrayUtils.Add(ref nav_vertices[tr.Vertex1].Borders, tr.Vertex0);
                    }

                    if (IsBorderEdge(nav_triangles, t, tr.Vertex1, tr.Vertex2))
                    {
                        ArrayUtils.Add(ref nav_vertices[tr.Vertex1].Borders, tr.Vertex2);
                        ArrayUtils.Add(ref nav_vertices[tr.Vertex2].Borders, tr.Vertex1);
                    }

                    if (IsBorderEdge(nav_triangles, t, tr.Vertex2, tr.Vertex0))
                    {
                        ArrayUtils.Add(ref nav_vertices[tr.Vertex2].Borders, tr.Vertex0);
                        ArrayUtils.Add(ref nav_vertices[tr.Vertex0].Borders, tr.Vertex2);
                    }
                }

                // NORMALS

                var pt2 = FP._0_10 * FP._2;
                var pt3 = FP._0_10 * FP._3;

                for (Int32 i = 0; i < nav_vertices.Length; ++i)
                {
                    Progress("Baking NavMesh '" + navmeshDefinition.name + "': Calculating Normals", i, nav_vertices.Length);

                    var v  = nav_vertices[i];
                    var tn = new FPVector2[3];

                    if (v.Borders != null)
                    {
                        // 0. preferred middle of borders
                        var borders = v.Borders.Map(x => FPVector2.Normalize(nav_vertices[x].Point - v.Point));
                        if (borders.Length == 2)
                        {
                            tn[0] = FPVector2.Normalize(FPVector2.Lerp(borders[0], borders[1], FP._0_50));
                        }

                        // 1. second preferred neighbor edge that is furthest away from borders
                        if (v.Neighbors != null)
                        {
                            var neighbors = v.Neighbors.Where(x => !v.Borders.Contains(x)).Select(x =>
                                                                                                  new Neighbor {
                                Direction = FPVector2.Normalize(nav_vertices[x].Point - v.Point),
                                Vertex    = x
                            }
                                                                                                  ).ToArray();

                            var max_dot      = FP.MinValue;
                            var max_neighbor = default(Neighbor);
                            max_neighbor.Vertex = -1;

                            for (Int32 n = 0; n < neighbors.Length; ++n)
                            {
                                var dot = FP._0;

                                for (Int32 b = 0; b < borders.Length; ++b)
                                {
                                    dot += FPVector2.Dot(borders[b], neighbors[n].Direction);
                                }

                                dot = FPMath.Abs(dot);

                                if (dot > max_dot)
                                {
                                    max_dot      = dot;
                                    max_neighbor = neighbors[n];
                                }
                            }

                            if (max_neighbor.Vertex >= 0)
                            {
                                tn[1] = max_neighbor.Direction * pt2;
                            }
                        }
                    }

                    // 2. least preferred, avarage of triangle normals
                    foreach (var tc in v.Triangles.Select(x => FPVector2.Normalize(TriangleCenter(nav_triangles[x], nav_vertices) - v.Point)))
                    {
                        tn[2] += tc;
                    }

                    tn[2] = FPVector2.Normalize(tn[2]);

                    // find normal
                    var failed = true;

                    for (Int32 k = 0; failed && k < tn.Length; ++k)
                    {
                        if (tn[k] != FPVector2.Zero)
                        {
                            if (failed && TriangleContains(nav_triangles, nav_vertices, (v.Point + (tn[k] * pt3))))
                            {
                                nav_vertices[i].Normal = FPVector2.Normalize(tn[k] * pt2);

                                // we're done
                                failed = false;
                            }

                            if (failed && TriangleContains(nav_triangles, nav_vertices, (v.Point + (-tn[k] * pt3))))
                            {
                                nav_vertices[i].Normal = FPVector2.Normalize(-tn[k] * pt2);

                                // we're done
                                failed = false;
                            }
                        }
                    }
                }

                // BORDER SET

                HashSet <Border> border_set = new HashSet <Border>();

                for (Int32 v = 0; v < nav_vertices.Length; ++v)
                {
                    Progress(navmeshDefinition.name + " Baking: Border Set", v, nav_vertices.Length);

                    if (nav_vertices[v].Borders != null)
                    {
                        for (Int32 n = 0; n < nav_vertices[v].Borders.Length; ++n)
                        {
                            border_set.Add(new Border(v, nav_vertices[v].Borders[n], border_set.Count + 1));
                        }
                    }
                }

                // BORDER GRID

                var nav_border_grid = new NavMeshBorderNode[data.Asset.Settings.GridSize * data.Asset.Settings.GridSize];

                for (Int32 z = 0; z < data.Asset.Settings.GridSize; ++z)
                {
                    for (Int32 x = 0; x < data.Asset.Settings.GridSize; ++x)
                    {
                        var idx = (z * data.Asset.Settings.GridSize) + x;

                        Progress("Baking NavMesh '" + navmeshDefinition.name + "': Border Grid", idx, data.Asset.Settings.GridSize * data.Asset.Settings.GridSize);

                        // set index key
                        // nav_border_grid[idx].key = idx + 1;

                        //
                        var zn = (FP)z * data.Asset.Settings.GridNodeSize;
                        var xn = (FP)x * data.Asset.Settings.GridNodeSize;

                        FPVector2 bl = data.Asset.Settings.WorldOffset + new FPVector2(xn, zn);
                        FPVector2 br = data.Asset.Settings.WorldOffset + new FPVector2(xn + data.Asset.Settings.GridNodeSize, zn);
                        FPVector2 ur = data.Asset.Settings.WorldOffset + new FPVector2(xn + data.Asset.Settings.GridNodeSize, zn + data.Asset.Settings.GridNodeSize);
                        FPVector2 ul = data.Asset.Settings.WorldOffset + new FPVector2(xn, zn + data.Asset.Settings.GridNodeSize);

                        foreach (var b in border_set)
                        {
                            var p0 = nav_vertices[b.V0].Point;
                            var p1 = nav_vertices[b.V1].Point;

                            if (
                                FPCollision.LineIntersectsLine(p0, p1, bl, br) ||
                                FPCollision.LineIntersectsLine(p0, p1, br, ur) ||
                                FPCollision.LineIntersectsLine(p0, p1, ur, ul) ||
                                FPCollision.LineIntersectsLine(p0, p1, ul, bl)
                                )
                            {
                                if (nav_border_grid[idx].Borders == null)
                                {
                                    nav_border_grid[idx].Borders = new NavMeshBorder[0];
                                }

                                ArrayUtils.Add(ref nav_border_grid[idx].Borders, new NavMeshBorder {
                                    Key = b.Key,
                                    V0  = p0,
                                    V1  = p1,
                                });
                            }
                        }
                    }
                }

                // TRIANGLE CENTER GRID

                var nav_triangles_center_grid = new Int32[data.Asset.Settings.GridSize * data.Asset.Settings.GridSize];

                for (Int32 z = 0; z < data.Asset.Settings.GridSize; ++z)
                {
                    for (Int32 x = 0; x < data.Asset.Settings.GridSize; ++x)
                    {
                        var idx = (z * data.Asset.Settings.GridSize) + x;

                        Progress("Baking NavMesh '" + navmeshDefinition.name + "': Triangle Center Grid", idx, data.Asset.Settings.GridSize * data.Asset.Settings.GridSize);

                        var zn = (FP)(z * data.Asset.Settings.GridNodeSize);
                        var xn = (FP)(x * data.Asset.Settings.GridNodeSize);
                        var g  = data.Asset.Settings.WorldOffset + new FPVector2(xn, zn) + new FPVector2(FP.FromFloat_UNSAFE(data.Asset.Settings.GridNodeSize * 0.5f), FP.FromFloat_UNSAFE(data.Asset.Settings.GridNodeSize * 0.5f));

                        var d = FP.MaxValue;
                        var t = -1;

                        for (Int32 i = 0; i < nav_triangles.Length; ++i)
                        {
                            var c = nav_triangles[i].Center;

                            if (FPVector2.DistanceSquared(g, c) < d)
                            {
                                d = FPVector2.DistanceSquared(g, c);
                                t = i;
                            }
                        }

                        Assert.Check(t >= 0);

                        nav_triangles_center_grid[idx] = t;
                    }
                }

                NavMesh navmesh;

                navmesh              = new NavMesh();
                navmesh.GridSize     = data.Asset.Settings.GridSize;
                navmesh.GridNodeSize = data.Asset.Settings.GridNodeSize;
                navmesh.WorldOffset  = data.Asset.Settings.WorldOffset;

                navmesh.Name                = navmeshDefinition.name;
                navmesh.Vertices            = nav_vertices;
                navmesh.BorderGrid          = nav_border_grid;
                navmesh.Triangles           = nav_triangles;
                navmesh.TrianglesGrid       = nav_triangles_grid;
                navmesh.TrianglesCenterGrid = nav_triangles_center_grid;

                return(navmesh);
            }
            finally {
#if UNITY_EDITOR
                EditorUtility.ClearProgressBar();
#endif
            }
        }