/// <summary> /// Fired when the entity ticks. /// </summary> public void Tick() { Game game = Engine3D.Source as Game; Matrix4 m = Engine3D.MainView.PrimaryMatrix.Inverted(); m.Transpose(); float x = 2.0f * Engine3D.Client.MouseX / Engine3D.Window.Width - 1.0f; float y = 1.0f - 2.0f * Engine3D.Client.MouseY / Engine3D.Window.Height; Vector4 vIn = new Vector4(x, y, 1, 1); Vector4 vOut = Vector4.Transform(m, vIn); float mul = 1.0f / vOut.W; BEPUutilities.Vector3 dir = new BEPUutilities.Vector3(vOut.X * mul, vOut.Y * mul, vOut.Z * mul); if (game.Terrain.Body.RayCast(new BEPUutilities.Ray(Engine3D.MainCamera.Position.ToBVector(), dir), 100.0, out BEPUutilities.RayHit hit)) { BEPUutilities.Vector3 loc = hit.Location; Target = GridVertex.FromXY(loc.X, loc.Y); Vector2 pos = Target.ToCartesianCoords2D(); Entity.SetPosition(new Location(pos.X, pos.Y, game.Terrain.HeightMap[Target.U, Target.V] + 0.5)); BasicUnitAction action = game.UnitController.SelectedAction; if (action != null) { action.Update(); Rend.Color = action.AffectedVertices.Contains(Target) ? Color4F.Red : Color4F.Blue; } Rend.IsVisible = true; } else { Rend.IsVisible = false; } }
public Tuple <float, float> get2DCordinate(GridVertex gv) { float x = gv.col * CellSz + (gv.col * WallSz) + WallSz, y = gv.row * CellSz + (gv.row * WallSz) + WallSz; return(new Tuple <float, float>(1f, 1f)); }
public override HashSet <GridVertex> Area(GridVertex source, GridVertex direction) { HashSet <GridVertex> verts = new HashSet <GridVertex>(); GridVertex left = direction.Rotate(-2); GridVertex right = direction.Rotate(2); for (int i = Offset; i < Range + Offset; i++) { int U = source.U + i * direction.U; int V = source.V + i * direction.V; for (int j = 0; j < Width; j++) { int a = left.U * j; int b = left.V * j; int c = right.U * j; int d = right.V * j; verts.UnionWith(new GridVertex[] { new GridVertex(U + a, V + b), new GridVertex(U + c, V + d) }); } } return(verts); }
/// <summary> /// Calculates the next affected grid vertices. /// </summary> /// <param name="source">The current flooded grid vertex.</param> public void Flood(GridVertex source, int currentSteps) { if (Range - currentSteps <= 0) { return; } Game game = Unit.Engine3D.Source as Game; foreach (GridVertex target in source.Adjacent()) { if (target.IsInsideBoundaries(game.Terrain.Size)) { double h = Math.Abs(game.Terrain.HeightMap[target.U, target.V] - game.Terrain.HeightMap[source.U, source.V]); if (h <= Unit.Stability) { if (!AffectedPaths.ContainsKey(target)) { AffectedPaths.Add(target, source); Flood(target, currentSteps + 1); } else if (currentSteps < TraceSteps(target)) { AffectedPaths.Remove(target); AffectedPaths.Add(target, source); Flood(target, currentSteps + 1); } } } } }
/// <summary> /// Traces a grid vertex step back to the source. /// </summary> /// <param name="vert">The final vertex.</param> /// <returns>The number of steps taken to reach the start.</returns> public int TraceSteps(GridVertex vert) { int steps = 0; while (!vert.Equals(Unit.Coords)) { steps++; AffectedPaths.TryGetValue(vert, out vert); } return(steps); }
/// <summary> /// Updates the action's affected zone. This usually happens when the action is selected and the cursor is moved. /// </summary> public override void Update() { Game game = Unit.Engine3D.Source as Game; Vector2 distance = game.CursorController.Target.ToCartesianCoords2D() - Unit.Coords.ToCartesianCoords2D(); float degrees = (float)(Math.Atan2(distance.Y, distance.X) * 180 / Math.PI); int Angle = (int)(((degrees + 390) % 360) / 60); Direction = GridVertex.Directions[Angle]; game.UnitController.Entity.RemoveProperty <BasicMeshRenderableProperty>(); Generate(); }
/// <summary> /// Executes and then deselects the action. This usually happens when right clicking after an action has been selected. /// </summary> public override void Execute() { SubtractEnergy(); Game game = Unit.Engine3D.Source as Game; GridVertex target = game.CursorController.Target; if (AffectedVertices.Contains(target)) { game.Terrain.AdjustVertexHeight(target, -Amount * 0.25f); game.UnitController.Entity.RemoveProperty <BasicMeshRenderableProperty>(); game.UnitController.SelectedAction = null; } }
/// <summary> /// Spawns a new unit entity at the specified location if it's empty. /// </summary> /// <param name="unit">The unit property for this entity.</param> /// <param name="pos">The position in grid vertex coordinates.</param> /// <returns></returns> public ClientEntity SpawnUnit(BasicUnitProperty unit, GridVertex pos) { foreach (GridFace face in UnitController.OccupiedFaces(unit.Size, pos)) { if (UnitFaces[face.U, face.V] != null) { SysConsole.OutputCustom("Error", "Grid position already occupied by another unit!"); return(null); } } unit.Coords = pos; return(Client.Engine3D.SpawnEntity(unit)); }
private static void TrisToVertCPUAlt(ref ComputeBuffer bufIn, ref ComputeBuffer bufOut, int count) { Triangle[] data = new Triangle[count / 3]; GridVertex[] vertices = new GridVertex[count]; bufIn.GetData(data); int n = 0; for (int i = 0; i < count / 3; i++) { vertices[n] = data[i].v1; vertices[n + 1] = data[i].v2; vertices[n + 2] = data[i].v3; n += 3; } bufOut.SetData(vertices); }
/// <summary> /// The grid faces occupied by this unit. /// </summary> /// <returns></returns> public HashSet <GridFace> OccupiedFaces(int size, GridVertex pos) { switch (size) { case 1: return(pos.Touches()); case 2: HashSet <GridFace> faces = new HashSet <GridFace>(); foreach (GridVertex vert in pos.Adjacent()) { faces.UnionWith(vert.Touches()); } return(faces); default: return(null); } }
public static void PrintGraph <T>(Graph.Core.Grid.GridGraph <T> g) where T : IComparable { for (int row = 0; row < g.Mapping.RowSz; row++) { Console.Write(" _"); } Console.WriteLine(); for (int row = 0; row < g.Mapping.RowSz; row++) { Console.Write("|"); for (int col = 0; col < g.Mapping.ColSz; col++) { GridVertex v = g.GetVertex(col, row); var b = v.ConnectsToVertex(v.DOWN) ? " " : "_"; var r = v.ConnectsToVertex(v.RIGHT) ? " " : "|"; Console.Write(b + r); } Console.WriteLine(); } }
/// <summary> /// Executes and then deselects the action. This usually happens when right clicking after an action has been selected. /// </summary> public override void Execute() { SubtractEnergy(); Game game = Unit.Engine3D.Source as Game; GridVertex target = game.CursorController.Target; if (AffectedVertices.Contains(target)) { List <GridVertex> steps = new List <GridVertex>(); while (!target.Equals(Unit.Coords)) { steps.Add(target); AffectedPaths.TryGetValue(target, out target); } Unit.MoveSteps = steps.Reverse <GridVertex>().ToList().GetEnumerator(); Unit.MoveSteps.MoveNext(); Unit.IsMoving = true; game.UnitController.Entity.RemoveProperty <BasicMeshRenderableProperty>(); game.UnitController.SelectedAction = null; } }
public void JoiningEdge_NeighborNodes_Edge() { Vec2 position = new Vec2(3, 3); GridNode node = _grid[position]; IPathfindingEdge joiningEdge = node.JoiningEdge(_grid[position + Direction.N]); IPathfindingEdge edge = new GridEdge(position, Direction.N); Assert.AreEqual(edge, joiningEdge); joiningEdge = node.JoiningEdge(_grid[position + Direction.W]); edge = new GridEdge(position, Direction.W); Assert.AreEqual(edge, joiningEdge); joiningEdge = node.JoiningEdge(_grid[position + Direction.E]); edge = new GridEdge(new Vec2(position.x + 1, position.y), Direction.W); Assert.AreEqual(edge, joiningEdge); joiningEdge = node.JoiningEdge(_grid[position + Direction.S]); edge = new GridEdge(new Vec2(position.x, position.y + 1), Direction.N); Assert.AreEqual(edge, joiningEdge); joiningEdge = node.JoiningEdge(_grid[position + Direction.NW]); edge = new GridVertex(position); Assert.AreEqual(edge, joiningEdge); joiningEdge = node.JoiningEdge(_grid[position + Direction.NE]); edge = new GridVertex(new Vec2(position.x + 1, position.y)); Assert.AreEqual(edge, joiningEdge); joiningEdge = node.JoiningEdge(_grid[position + Direction.SW]); edge = new GridVertex(new Vec2(position.x, position.y + 1)); Assert.AreEqual(edge, joiningEdge); joiningEdge = node.JoiningEdge(_grid[position + Direction.SE]); edge = new GridVertex(new Vec2(position.x + 1, position.y + 1)); Assert.AreEqual(edge, joiningEdge); }
/// <summary> /// Fired every tick while the entity is spawned. /// </summary> public void Tick() { Game game = Engine3D.Source as Game; if (IsMoving) { Vector3 v = MoveSteps.Current.ToCartesianCoords3D(game.Terrain.HeightMap); Location target = new Location(v.X, v.Y, v.Z + Size); double move = Engine.Delta * 4; if (Entity.LastKnownPosition.DistanceSquared(target) <= move * move) { Entity.SetPosition(target); Coords = MoveSteps.Current; if (!MoveSteps.MoveNext()) { IsMoving = false; } } else { Entity.MoveRelative((target - Entity.LastKnownPosition).Normalize() * move); } } }
public List <GridVertex> FindPath(Vector3 start, Vector3 end, float moves) { List <GridVertex> path = new List <GridVertex>(); start.z = 0; end.z = 0; for (int i = 0; i < verts.Count; i++) { float newH = Mathf.Sqrt(Mathf.Pow(end.x - verts[i].vertPos.x, 2) + Mathf.Pow(end.y - verts[i].vertPos.y, 2)); verts[i].heuristic = newH; } //setting starting and ending vertices foreach (GridVertex vert in verts) { vert.visited = false; if (vert.vertPos == start) { startVert = vert; path.Add(startVert); } else if (vert.vertPos == end) { endVert = vert; } } int iteration = 0; while (path.Count > 0) { GridVertex curVert = path[path.Count - 1]; bool add = false; iteration++; //checking if path is complete if (curVert == endVert) { //Debug.Log(iteration + "st Round"); break; } //checking nearby vertices if (curVert.adjVertices.Count > 0) { GridVertex best = curVert.adjVertices[0]; foreach (GridVertex adj in curVert.adjVertices) { if (!adj.visited && adj.heuristic <= best.heuristic) { best = adj; } } if (!best.visited) { best.visited = true; path.Add(best); add = true; } } if (!add) { path.RemoveAt(path.Count - 1); } } return(path); }
/// <summary> /// Build grid index for road network /// </summary> private void buildRNIndex() { //this.edgeIndex = new GridEdge(edges.Values, mbr, edgeCellSize); this.vertexIndex = new GridVertex(vertices.Values, mbr, vertexCellSize); }
//init grid mesh private void Start() { #region GenGridMesh GridVertex[] vertices = new GridVertex[vertCount]; int offset = 0; for (int i = -gridSize; i <= gridSize; i++) { Vector3 color = Vector3.One * 0.03f; if (i % 10 == 0) { color = Vector3.One * 0.3f; } if (i == 0) { color = new Vector3(0f, 0f, 1f); } vertices[offset + 0] = new GridVertex(new Vector3(i, 0f, -gridSize), color); vertices[offset + 1] = new GridVertex(new Vector3(i, 0f, gridSize), color); offset += 2; } for (int i = -gridSize; i <= gridSize; i++) { Vector3 color = Vector3.One * 0.03f; if (i % 10 == 0) { color = Vector3.One * 0.3f; } if (i == 0) { color = new Vector3(1f, 0f, 0f); } vertices[offset + 0] = new GridVertex(new Vector3(-gridSize, 0f, i), color); vertices[offset + 1] = new GridVertex(new Vector3(gridSize, 0f, i), color); offset += 2; } #endregion VAO = GL.GenVertexArray(); GL.BindVertexArray(VAO); VBO = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, VBO); GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * Unsafe.SizeOf <GridVertex>(), vertices, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Unsafe.SizeOf <GridVertex>(), 0); GL.EnableVertexAttribArray(0); GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, Unsafe.SizeOf <GridVertex>(), Vector3.SizeInBytes); GL.EnableVertexAttribArray(1); GL.BindVertexArray(0); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); }
void generateNormalField(ref GridVertex[] chunkVertices) { int cbase=ox+oy+oz; //Compute normals on volume verts... for (int rx=0; rx<=chunkDim; rx++){ int cplane=cbase; for (int ry=0; ry<=chunkDim; ry++){ int cidx=cplane; for (int rz=0; rz<=chunkDim; rz++) { float nmlx=chunkVertices[cidx+normalNeighbors[0]].density-chunkVertices[cidx+normalNeighbors[1]].density; float nmly=chunkVertices[cidx+normalNeighbors[2]].density-chunkVertices[cidx+normalNeighbors[3]].density; float nmlz=chunkVertices[cidx+normalNeighbors[4]].density-chunkVertices[cidx+normalNeighbors[5]].density; chunkVertices[cidx].normal=new Vector3(nmlx,nmly,nmlz); chunkVertices[cidx].normal.Normalize(); cidx+=oz; } cplane+=oy; } cbase+=ox; } }
void generateMesh(Region chunk,GameObject archetype,ref GridVertex[] chunkData) { generateNormalField(ref chunkData); Mesh mesh = new Mesh(); generateMeshGeometry(ref chunkData,ref mesh); chunk.obj.GetComponent<MeshFilter> ().mesh=mesh; chunk.obj.GetComponent<MeshCollider> ().sharedMesh = mesh; //chunk.AddComponent(chunk.GetComponent<"Material">().); //Material mat = new Material (Shader.Find ("Diffuse")); chunk.obj.GetComponent<MeshRenderer> ().sharedMaterial = archetype.GetComponent<MeshRenderer> ().sharedMaterial; }
void generateMeshGeometry(ref GridVertex[] chunkVertices,ref Mesh mesh) { curVert = 0; curIndex = 0; int cbase=ox+oy+oz; //Loop through the density volume and call marching cubes on each cube... for (int rx=0; rx<chunkDim; rx++){ int cplane=cbase; for (int ry=0; ry<chunkDim; ry++){ int cidx=cplane; for (int rz=0; rz<chunkDim; rz++) { for(int ax=0;ax<8;ax++){ GridVertex gv=chunkVertices[cidx+cacheNeighbors[ax]]; cell.p[ax]=gv.position; cell.n[ax]=gv.normal; cell.val[ax]=gv.density; } MCubes.Polygonise (cell, 0.5, ref vertices, ref normals, ref uvs, ref indices, ref curVert, ref curIndex); cidx+=oz; } cplane+=oy; } cbase+=ox; } //Make a mesh to hold this chunk and assign the verts/tris mesh.Clear(true); mesh.vertices = v3subarray(ref vertices,curVert); mesh.uv = v2subarray(ref uvs,curVert); mesh.normals = v3subarray(ref normals,curVert); mesh.triangles = vIntsubarray(ref indices,curIndex); //mesh.RecalculateNormals (); }
void initializeField(int x, int y, int z,ref GridVertex[] chunkVertices) { int vtop=0; //Build the procedural field for this chunk... for (int rx=-1; rx<=chunkDim+1; rx++) for (int ry=-1; ry<=chunkDim+1; ry++) for (int rz=-1; rz<=chunkDim+1; rz++) { chunkVertices[vtop].position.Set(rx, ry, rz); float nx = (x + rx) * noiseRes; float ny = (y + ry) * noiseRes; float nz = (z + rz) * noiseRes; float d= chunkVertices[vtop].density = evaluateField(ref nx,ref ny,ref nz); float n2sz=matNoiseRes; chunkVertices[vtop].material.Set (//0.7f, (snoise (nx*n2sz, ny*n2sz, 0.0f)*0.7f)+ (snoise (ny*3.0f, nx*3.0f, 0.0f)*0.3f) //(snoise (nx*n2sz, ny*n2sz, 0.0f)*0.7f)+ //(snoise (ny*(n2sz*2), nx*(n2sz*2), 0.0f)*0.3f) , snoise (ny*n2sz, nx*n2sz, 0.0f)); vtop++; } }
void initializeField(int x, int y, int z,ref GridVertex[] chunkVertices) { int vtop=0; //Build the procedural field for this chunk... for (int rx=-1; rx<=chunkDim+1; rx++) for (int ry=-1; ry<=chunkDim+1; ry++) for (int rz=-1; rz<=chunkDim+1; rz++) { chunkVertices[vtop].position = new Vector3 (rx, ry, rz); float nx = (x + rx) * noiseRes; float ny = (y + ry) * noiseRes; float nz = (z + rz) * noiseRes; chunkVertices[vtop].density = evaluateField(ref nx,ref ny,ref nz); vtop++; } }
/// <summary> /// Returns this hitbox' borders. /// </summary> /// <param name="source">The source vertex of the hitbox.</param> /// <param name="direction">The direction of the hitbox.</param> /// <returns>This hitbox' borders.</returns> public abstract HashSet <GridVertex> Area(GridVertex source, GridVertex direction);