private void ModifyVertex(CharacterData characterData, ref UIVertex uiVertex) { for (int i = 0; i < vertexModifiers.Length; i++) { VertexModifier vertexModifier = vertexModifiers[i]; vertexModifier.Apply(characterData, ref uiVertex); } }
public void ForEachVertex(VertexModifier modifier) { int count = Vertices.Count; for (int i = 0; i < count; ++i) { Vector3 vertex = Vertices[i]; Vector2 uv = UVs[i]; modifier(ref vertex, ref uv); Vertices[i] = vertex; UVs[i] = uv; } }
static void Build14(int gridSize, out VertexModifier vertexModifier, out Dictionary<string, MeshRebuilder> rebuilders) { List<Vector3B> vertices = new List<Vector3B>(); for (int y = 0; y < gridSize; ++y) for (int x = 0; x < gridSize; ++x) vertices.Add(new Vector3B(2 * x, 0, 2 * y)); List<int> triangles = new List<int>(); for (int y = 0; y < gridSize - 1; ++y) for (int x = 0; x < gridSize - 1; ++x) { triangles.Add(gridSize * (y) + (x)); triangles.Add(gridSize * (y) + (x + 1)); triangles.Add(gridSize * (y + 1) + (x + 1)); triangles.Add(gridSize * (y) + (x)); triangles.Add(gridSize * (y + 1) + (x + 1)); triangles.Add(gridSize * (y + 1) + (x)); } var physicsMesh = new BEPUphysics.BroadPhaseEntries.StaticMesh(vertices.ToArray(), triangles.ToArray(), BEPUutilities.AffineTransform.Identity); vertexModifier = (Random random) => { for (int vertexIndex = 0; vertexIndex < physicsMesh.Mesh.Data.Vertices.Length; ++vertexIndex) physicsMesh.Mesh.Data.Vertices[vertexIndex].Y = (float)random.NextDouble() * 2; }; rebuilders = new Dictionary<string, MeshRebuilder>(); rebuilders.Add("v1.4.0 Reconstruct", (i) => { physicsMesh.Mesh.Tree.Reconstruct(); physicsMesh.UpdateBoundingBox(); }); rebuilders.Add("v1.4.0 Refit", (i) => { physicsMesh.Mesh.Tree.Refit(); physicsMesh.UpdateBoundingBox(); }); }
/// <summary> /// Iterates over the vertices in the height map and modifies them according to the provided modifier. /// </summary> /// <param name="position"></param> /// <param name="radius"></param> /// <param name="magnitude"></param> /// <param name="modifyVertex"></param> private void ModifyVertices(Vector2 position, float radius, float magnitude, int numPasses, VertexModifier modifyVertex) { if (NewAction) { NewAction = false; BackupVertices(); mUndoStack.Push(mCurrentAction); mCurrentAction = null; mCurrentAction = new ModifyAction(); mRedoStack.Clear(); } float radiusSquared = radius * radius; // Normalize origin of modification to [0,mHeight), [0, mWidth). position.X = position.X / Utils.WorldScale.X + mWidth / 2; position.Y = position.Y / Utils.WorldScale.Z + mHeight / 2; int minZ = (int)Math.Max(0, position.Y - radius), maxZ = (int)Math.Min(mHeight - 1, position.Y + radius); int minX = (int)Math.Max(0, position.X - radius), maxX = (int)Math.Min(mWidth - 1, position.X + radius); for (int pass = 0; pass < numPasses; ++pass) { for (int zIndex = minZ; zIndex <= maxZ; ++zIndex) { for (int xIndex = minX; xIndex <= maxX; ++xIndex) { Vector2 displacement = new Vector2(xIndex, zIndex) - position; if (mIsBlock || displacement.LengthSquared() < radiusSquared) { float featherScale = mIsFeathered ? mIsBlock ? Math.Max(0.0f, (float)Math.Log(radius * 2.0f - displacement.Length())) / radius : Math.Max(0.0f, (float)Math.Log(radius - displacement.Length())) / radius : 1.0f; modifyVertex(xIndex, zIndex, magnitude * featherScale, pass); WriteDirtyBit(xIndex, zIndex); } } } } UpdateNormalVectors(minZ, maxZ, minX, maxX); UpdateVertexBuffers(); }
void Start() { _modifier = GetComponent <VertexModifier>(); StartCoroutine(Shrink()); }
static void Test(VertexModifier vertexModifier, MeshRebuilder rebuilder, CostMetricMeasurer costMeasurer, string testName, int iterations) { Random random = new Random(5); double sum = 0; double fastest = double.MaxValue; double slowest = 0; for (int iterationIndex = 0; iterationIndex < iterations; ++iterationIndex) { vertexModifier(random); var start = Stopwatch.GetTimestamp(); rebuilder(iterationIndex); var end = Stopwatch.GetTimestamp(); var time = (end - start) / (double)Stopwatch.Frequency; if (time < fastest) fastest = time; if (time > slowest) slowest = time; sum += time; } Console.WriteLine($"{testName}:"); Console.WriteLine($"Average: {sum / iterations}"); Console.WriteLine($"Fastest: {fastest}"); Console.WriteLine($"Slowest: {slowest}"); if (costMeasurer != null) Console.WriteLine($"Cost Metric: {costMeasurer()}"); }
static void Build2(int gridSize, out VertexModifier vertexModifier, out Dictionary<string, MeshRebuilder> rebuilders, out CostMetricMeasurer costMeasurer, out MeshDisposer disposer) { List<Vector3> vertices = new List<Vector3>(); for (int y = 0; y < gridSize; ++y) for (int x = 0; x < gridSize; ++x) vertices.Add(new Vector3(2 * x, 0, 2 * y)); List<int> triangles = new List<int>(); for (int y = 0; y < gridSize - 1; ++y) for (int x = 0; x < gridSize - 1; ++x) { triangles.Add(gridSize * (y) + (x)); triangles.Add(gridSize * (y) + (x + 1)); triangles.Add(gridSize * (y + 1) + (x + 1)); triangles.Add(gridSize * (y) + (x)); triangles.Add(gridSize * (y + 1) + (x + 1)); triangles.Add(gridSize * (y + 1) + (x)); } var physicsMesh = new Mesh(vertices.ToArray(), triangles.ToArray()); vertexModifier = (Random random) => { for (int vertexIndex = 0; vertexIndex < physicsMesh.Vertices.Length; ++vertexIndex) physicsMesh.Vertices[vertexIndex].Y = (float)random.NextDouble() * 2; }; rebuilders = new Dictionary<string, MeshRebuilder>(); //Note incremental first, sweep second. Starts the refine off with a better tree to begin with so it doesn't to do an unrealistic amount of optimization to begin with. rebuilders.Add("v2 Reconstruct Incremental", (i) => physicsMesh.RebuildIncremental()); rebuilders.Add("v2 Reconstruct Sweep", (i) => physicsMesh.RebuildSweep()); rebuilders.Add("v2 Refit And Refine", (i) => physicsMesh.RefitWithIncrementalRefine(i)); rebuilders.Add("v2 Refit", (i) => physicsMesh.Refit()); disposer = () => { physicsMesh.Tree.Dispose(); }; costMeasurer = () => { return physicsMesh.Tree.MeasureCostMetric(); }; }
private void IterateOverTerrainVertices(IEnumerable<Vector3> selectedBlocks, Vector3 center, float radius, VertexModifier modifier, float deltaHeight) { Vector2 centerVertexSpace = new Vector2(center.X / BLOCK_SIZE * HeightMapMesh.NUM_SIDE_VERTICES, center.Z / BLOCK_SIZE * HeightMapMesh.NUM_SIDE_VERTICES); float radiusVertexSpace = radius / BLOCK_SIZE * (float)Math.Sqrt(2 * HeightMapMesh.NUM_SIDE_VERTICES * HeightMapMesh.NUM_SIDE_VERTICES); float radiusSquared = radiusVertexSpace * radiusVertexSpace; int minX = (int)Math.Floor(centerVertexSpace.X - radiusVertexSpace), maxX = (int)Math.Ceiling(centerVertexSpace.X + radiusVertexSpace); int minZ = (int)Math.Floor(centerVertexSpace.Y - radiusVertexSpace), maxZ = (int)Math.Ceiling(centerVertexSpace.Y + radiusVertexSpace); for (int z = minZ; z <= maxZ; z++) { for (int x = minX; x <= maxX; x++) { Vector2 positionVertexSpace = new Vector2(x, z); if ((positionVertexSpace - centerVertexSpace).LengthSquared() <= radiusSquared) { modifier(selectedBlocks, positionVertexSpace, deltaHeight); } } } Vector3 radiusOffset = new Vector3(radius, 0, radius); Vector3 minCoordinate = CoordinateFromPosition(center - radiusOffset) + new Vector3(-1, 0, -1); Vector3 maxCoordinate = CoordinateFromPosition(center + radiusOffset) + new Vector3(1, 0, 1); List<Tuple<Vector3, List<Direction>>> blocksToConnectNormals = new List<Tuple<Vector3,List<Direction>>>(); for (int blockZ = (int)minCoordinate.Z; blockZ <= (int)maxCoordinate.Z; ++blockZ) { for (int blockX = (int)minCoordinate.X; blockX <= (int)maxCoordinate.X; ++blockX) { Vector3 coordinate = new Vector3(blockX, minCoordinate.Y, blockZ); if (!mBlocks.ContainsKey(coordinate)) { continue; } List<Direction> neighbors = new List<Direction>(); if (blockZ == (int)minCoordinate.Z) { neighbors.Add(Direction.NORTH); } neighbors.Add(Direction.SOUTH); if (blockX == (int)minCoordinate.X) { neighbors.Add(Direction.WEST); } neighbors.Add(Direction.EAST); UpdateMesh(coordinate, neighbors); blocksToConnectNormals.Add(new Tuple<Vector3,List<Direction>>(coordinate, neighbors)); mSpace.Remove(mBlocks[coordinate].HeightMap.StaticCollidable); mBlocks[coordinate].HeightMap.UpdateStaticCollidable(); mSpace.Add(mBlocks[coordinate].HeightMap.StaticCollidable); } } foreach (Tuple<Vector3, List<Direction>> neighbor in blocksToConnectNormals) { AttachNeighborNormals(neighbor.Item1, neighbor.Item2); } }