public void QueryVisibleRenderers(IDrawDevice device, RawList<ICmpRenderer> targetList) { // Empty the cached list of visible renderers targetList.Count = 0; targetList.Reserve(this.totalRendererCount); // Copy references to all renderers that are visible to the target device int visibleCount = 0; ICmpRenderer[] targetData = targetList.Data; foreach (var pair in this.renderersByType) { ICmpRenderer[] data = pair.Value.Data; for (int i = 0; i < data.Length; i++) { if (i >= pair.Value.Count) break; if ((data[i] as Component).Active && data[i].IsVisible(device)) { targetData[visibleCount] = data[i]; visibleCount++; } } } targetList.Count = visibleCount; }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public ConvexHullTestDemo(DemosGame game) : base(game) { var random = new Random(5); for (int i = 0; i < 500000; ++i) { List<Vector3> points = new List<Vector3>(); for (int k = 0; k < random.Next(8, 60); k++) { points.Add(new Vector3(-100 + 30 * (float)random.NextDouble(), 100 + 500 * (float)random.NextDouble(), 100 + 30 * (float)random.NextDouble())); } var convexHull = new ConvexHull(new Vector3(0, 7, 0), points, 10); Console.WriteLine(convexHull.CollisionInformation.Shape.Vertices.Count); } var vertices = new[] { new Vector3(0, -1.750886E-9f, -1.5f), new Vector3(1, 1, 0.5f), new Vector3(1, -1, 0.5f), new Vector3(-1, 1, 0.5f), new Vector3(-1, -1, 0.5f), }; var hullVertices = new RawList<Vector3>(); ConvexHullHelper.GetConvexHull(vertices, hullVertices); ConvexHull hull = new ConvexHull(vertices, 5); Space.Add(hull); Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
[Test] public void Move() { int[] testArray = Enumerable.Range(0, 10).ToArray(); RawList<int> intList = new RawList<int>(); intList.AddRange(testArray); intList.Move(0, 3, 1); CollectionAssert.AreEqual(new int[] { 0, 0, 1, 2, 4, 5, 6, 7, 8, 9 }, intList); intList.Clear(); intList.AddRange(testArray); intList.Move(0, 3, 3); CollectionAssert.AreEqual(new int[] { 0, 0, 0, 0, 1, 2, 6, 7, 8, 9 }, intList); intList.Clear(); intList.AddRange(testArray); intList.Move(0, 3, 5); CollectionAssert.AreEqual(new int[] { 0, 0, 0, 3, 4, 0, 1, 2, 8, 9 }, intList); intList.Clear(); intList.AddRange(testArray); intList.Move(7, 3, -1); CollectionAssert.AreEqual(new int[] { 0, 1, 2, 3, 4, 5, 7, 8, 9, 0 }, intList); intList.Clear(); intList.AddRange(testArray); intList.Move(7, 3, -3); CollectionAssert.AreEqual(new int[] { 0, 1, 2, 3, 7, 8, 9, 0, 0, 0 }, intList); intList.Clear(); intList.AddRange(testArray); intList.Move(7, 3, -5); CollectionAssert.AreEqual(new int[] { 0, 1, 7, 8, 9, 5, 6, 0, 0, 0 }, intList); intList.Clear(); }
/// <summary> /// Returns a resource to the pool. /// </summary> /// <param name="list">List to return.</param> public static void GiveBack(RawList<RayCastResult> list) { if (SubPoolRayCastResultList == null) SubPoolRayCastResultList = new UnsafeResourcePool<RawList<RayCastResult>>(); list.Clear(); SubPoolRayCastResultList.GiveBack(list); }
///<summary> /// Constructs a new convex-convex manifold. ///</summary> public GeneralConvexContactManifold() { contacts = new RawList<Contact>(4); unusedContacts = new UnsafeResourcePool<Contact>(4); contactIndicesToRemove = new RawList<int>(4); pairTester = new GeneralConvexPairTester(); }
/// <summary> /// Returns a resource to the pool. /// </summary> /// <param name="list">List to return.</param> public static void GiveBack(RawList<BroadPhaseEntry> list) { if (SubPoolBroadPhaseEntryList == null) SubPoolBroadPhaseEntryList = new UnsafeResourcePool<RawList<BroadPhaseEntry>>(); list.Clear(); SubPoolBroadPhaseEntryList.GiveBack(list); }
[Test] public void Basics() { RawList<int> intList = new RawList<int>(); intList.Add(10); intList.AddRange(new int[] { 17, 42, 94 }); Assert.AreEqual(4, intList.Count); Assert.IsTrue(intList.Contains(42)); Assert.AreEqual(2, intList.IndexOf(42)); CollectionAssert.AreEqual(new int[] { 10, 17, 42, 94 }, intList); CollectionAssert.AreEqual(new int[] { 10, 17, 42, 94 }, intList.Data.Take(4)); intList.ShrinkToFit(); Assert.AreEqual(intList.Count, intList.Capacity); intList.Remove(42); Assert.AreEqual(3, intList.Count); Assert.IsTrue(!intList.Contains(42)); Assert.AreEqual(-1, intList.IndexOf(42)); CollectionAssert.AreEqual(new int[] { 10, 17, 94 }, intList); CollectionAssert.AreEqual(new int[] { 10, 17, 94 }, intList.Data.Take(3)); intList.Insert(1, 100); CollectionAssert.AreEqual(new int[] { 10, 100, 17, 94 }, intList); CollectionAssert.AreEqual(new int[] { 10, 100, 17, 94 }, intList.Data.Take(4)); intList.InsertRange(2, new int[] { 150, 200, 250, 300 }); CollectionAssert.AreEqual(new int[] { 10, 100, 150, 200, 250, 300, 17, 94 }, intList); CollectionAssert.AreEqual(new int[] { 10, 100, 150, 200, 250, 300, 17, 94 }, intList.Data.Take(8)); intList.Clear(); Assert.AreEqual(0, intList.Count); Assert.IsTrue(!intList.Contains(94)); }
public static void GetShapeMeshData(EntityCollidable collidable, List<VertexPositionNormalTexture> vertices, List<ushort> indices) { var shape = collidable.Shape as ConvexShape; if (shape == null) throw new ArgumentException("Wrong shape type for this helper."); var vertexPositions = new BEPUutilities.Vector3[SampleDirections.Length]; for (int i = 0; i < SampleDirections.Length; ++i) { shape.GetLocalExtremePoint(SampleDirections[i], out vertexPositions[i]); } var hullIndices = new RawList<int>(); ConvexHullHelper.GetConvexHull(vertexPositions, hullIndices); var hullTriangleVertices = new RawList<BEPUutilities.Vector3>(); foreach (int i in hullIndices) { hullTriangleVertices.Add(vertexPositions[i]); } for (ushort i = 0; i < hullTriangleVertices.Count; i += 3) { Vector3 normal = MathConverter.Convert(BEPUutilities.Vector3.Normalize(BEPUutilities.Vector3.Cross(hullTriangleVertices[i + 2] - hullTriangleVertices[i], hullTriangleVertices[i + 1] - hullTriangleVertices[i]))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i]), normal, new Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i + 1]), normal, new Vector2(1, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i + 2]), normal, new Vector2(0, 1))); indices.Add(i); indices.Add((ushort)(i + 1)); indices.Add((ushort)(i + 2)); } }
/// <summary> /// Adds the specified vertex array to the Canvas' buffering mechanism. As long as buffers are available, the /// Canvas will prefer re-using one of them over creating a new vertex array. Every vertex array will only be used once. /// </summary> /// <param name="array"></param> public void AddVertexArray(RawList<VertexC1P3T2> array) { if (array == null) throw new ArgumentNullException("buffer"); if (this.dummy) return; if (this.vertexArraysFree.Contains(array)) return; if (this.vertexArraysUsed.Contains(array)) return; this.vertexArraysFree.Add(array); }
/// <summary> /// Adds entities associated with the solver item to the involved entities list. /// Ensure that sortInvolvedEntities() is called at the end of the function. /// This allows the non-batched multithreading system to lock properly. /// </summary> protected internal override void CollectInvolvedEntities(RawList<Entity> outputInvolvedEntities) { if (connectionA != null && connectionA != WorldEntity) outputInvolvedEntities.Add(connectionA); if (connectionB != null && connectionB != WorldEntity) outputInvolvedEntities.Add(connectionB); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public BroadPhaseRemovalTestDemo(DemosGame game) : base(game) { Entity toAdd; //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7)); BoundingBox box = new BoundingBox(new Vector3(-500, -500, -500), new Vector3(500, 500, 500)); DynamicHierarchy dh = new DynamicHierarchy(); Random rand = new Random(0); RawList<Entity> entities = new RawList<Entity>(); for (int k = 0; k < 1000; k++) { Vector3 position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X), (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y), (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z)); toAdd = new Box(MathConverter.Convert(position), 1, 1, 1, 1); entities.Add(toAdd); } testResults = new double[2]; int runCount = 10; for (int k = 0; k < runCount; k++) { for (int i = 0; i < entities.Count; i++) { dh.Add(entities[i].CollisionInformation); } long start = Stopwatch.GetTimestamp(); for (int i = 0; i < entities.Count; i++) { //dh.RemoveFast(entities[i].CollisionInformation); } long end = Stopwatch.GetTimestamp(); testResults[0] += (end - start) / (double)Stopwatch.Frequency; for (int i = 0; i < entities.Count; i++) { dh.Add(entities[i].CollisionInformation); } start = Stopwatch.GetTimestamp(); for (int i = 0; i < entities.Count; i++) { //dh.RemoveBrute(entities[i].CollisionInformation); } end = Stopwatch.GetTimestamp(); testResults[1] += (end - start) / (double)Stopwatch.Frequency; } testResults[0] /= runCount; testResults[1] /= runCount; }
protected internal override void CollectInvolvedEntities(RawList<Entity> outputInvolvedEntities) { //The default implementation for solver groups looks at every single subconstraint. //That's not necessary for these special constraints. if (entityA != null) outputInvolvedEntities.Add(entityA); if (entityB != null) outputInvolvedEntities.Add(entityB); }
///<summary> /// Averages together all the points in the point list. ///</summary> ///<param name="pointContributions">Point list to average.</param> ///<returns>Averaged point.</returns> public static Vector3 AveragePoints(RawList<Vector3> pointContributions) { var center = new Vector3(); for (int i = 0; i < pointContributions.Count; i++) { center += pointContributions[i]; //Every point has equal weight. } return center / pointContributions.Count; }
public EditTilesetTileInputAction(Tileset tileset, RawList<TileInput> tileInput, RawList<bool> tileInputMask) { if (tileset == null) throw new ArgumentNullException("tileset"); if (tileInput == null) throw new ArgumentNullException("tileInput"); if (tileInputMask == null) throw new ArgumentNullException("tileInputMask"); if (tileInputMask.Count != tileInput.Count) throw new ArgumentException("Input Mask needs to be the same size as input.", "tileInputMask"); this.tileset = tileset; this.tileInput = tileInput; this.tileInputMask = tileInputMask; }
public TilesetViewPaintTilesEventArgs( Graphics graphics, Rectangle clipRect, Tileset tileset, Bitmap sourceImage, RawList<TilesetViewPaintTileData> paintedTiles) : base(graphics, clipRect) { this.tileset = tileset; this.sourceImage = sourceImage; this.paintedTiles = paintedTiles; }
public void RemoveRenderer(ICmpRenderer renderer) { Type type = renderer.GetType(); RawList<ICmpRenderer> list; if (!this.renderersByType.TryGetValue(type, out list)) { list = new RawList<ICmpRenderer>(); this.renderersByType.Add(type, list); } list.Remove(renderer); this.totalRendererCount--; }
///<summary> /// Constructs a new convex hull shape. /// The point set will be recentered on the local origin. ///</summary> ///<param name="vertices">Point set to use to construct the convex hull.</param> /// <param name="center">Computed center of the convex hull shape prior to recentering.</param> /// <param name="outputHullTriangleIndices">Triangle indices computed on the surface of the point set.</param> /// <param name="outputUniqueSurfaceVertices">Unique vertices on the surface of the convex hull.</param> ///<exception cref="ArgumentException">Thrown when the point set is empty.</exception> public ConvexHullShape(IList<Vector3> vertices, out Vector3 center, IList<int> outputHullTriangleIndices, IList<Vector3> outputUniqueSurfaceVertices) { if (vertices.Count == 0) throw new ArgumentException("Vertices list used to create a ConvexHullShape cannot be empty."); //Ensure that the convex hull is centered on its local origin. center = ComputeCenter(vertices, outputHullTriangleIndices, outputUniqueSurfaceVertices); this.vertices = new RawList<Vector3>(outputUniqueSurfaceVertices); OnShapeChanged(); }
///<summary> /// Constructs a new convex hull shape. /// The point set will be recentered on the local origin. ///</summary> ///<param name="vertices">Point set to use to construct the convex hull.</param> /// <param name="center">Computed center of the convex hull shape prior to recentering.</param> ///<exception cref="ArgumentException">Thrown when the point set is empty.</exception> public ConvexHullShape(IList<Vector3> vertices, out Vector3 center) { if (vertices.Count == 0) throw new ArgumentException("Vertices list used to create a ConvexHullShape cannot be empty."); var surfaceVertices = Resources.GetVectorList(); center = ComputeCenter(vertices, surfaceVertices); this.vertices = new RawList<Vector3>(surfaceVertices); Resources.GiveBack(surfaceVertices); OnShapeChanged(); }
/// <summary> /// Refreshes the contact manifold, removing any out of date contacts /// and updating others. /// </summary> public static void ContactRefresh(RawList<Contact> contacts, RawValueList<ContactSupplementData> supplementData, ref RigidTransform transformA, ref RigidTransform transformB, RawList<int> toRemove) { //TODO: Could also refresh normals with some trickery. //Would also need to refresh depth using new normals, and would require some extra information. for (int k = 0; k < contacts.Count; k++) { contacts.Elements[k].Validate(); ContactSupplementData data = supplementData.Elements[k]; System.Numerics.Vector3 newPosA, newPosB; RigidTransform.Transform(ref data.LocalOffsetA, ref transformA, out newPosA); RigidTransform.Transform(ref data.LocalOffsetB, ref transformB, out newPosB); //ab - (ab*n)*n //Compute the horizontal offset. System.Numerics.Vector3 ab; Vector3Ex.Subtract(ref newPosB, ref newPosA, out ab); float dot; Vector3Ex.Dot(ref ab, ref contacts.Elements[k].Normal, out dot); System.Numerics.Vector3 temp; Vector3Ex.Multiply(ref contacts.Elements[k].Normal, dot, out temp); Vector3Ex.Subtract(ref ab, ref temp, out temp); dot = temp.LengthSquared(); if (dot > CollisionDetectionSettings.ContactInvalidationLengthSquared) { toRemove.Add(k); } else { //Depth refresh: //Find deviation ((Ra-Rb)*N) and add to base depth. Vector3Ex.Dot(ref ab, ref contacts.Elements[k].Normal, out dot); contacts.Elements[k].PenetrationDepth = data.BasePenetrationDepth - dot; if (contacts.Elements[k].PenetrationDepth < -CollisionDetectionSettings.maximumContactDistance) toRemove.Add(k); else { //Refresh position and ra/rb. System.Numerics.Vector3 newPos; Vector3Ex.Add(ref newPosB, ref newPosA, out newPos); Vector3Ex.Multiply(ref newPos, .5f, out newPos); contacts.Elements[k].Position = newPos; //This is an interesting idea, but has very little effect one way or the other. //data.BasePenetrationDepth = contacts.Elements[k].PenetrationDepth; //RigidTransform.TransformByInverse(ref newPos, ref transformA, out data.LocalOffsetA); //RigidTransform.TransformByInverse(ref newPos, ref transformB, out data.LocalOffsetB); } contacts.Elements[k].Validate(); } } }
/// <summary> /// Collects the entities which are affected by the solver group and updates the internal listing. /// </summary> protected internal override void CollectInvolvedEntities(RawList<Entity> outputInvolvedEntities) { foreach (EntitySolverUpdateable item in solverUpdateables) { for (int i = 0; i < item.involvedEntities.count; i++) { if (!outputInvolvedEntities.Contains(item.involvedEntities.Elements[i])) { outputInvolvedEntities.Add(item.involvedEntities.Elements[i]); } } } }
public EditTilesetTileInputAction(Tileset tileset, int tileIndex, TileInput tileInput) { if (tileset == null) throw new ArgumentNullException("tileset"); this.tileset = tileset; this.tileInput = new RawList<TileInput>(tileIndex + 1); this.tileInput.Count = tileIndex + 1; this.tileInput.Data[tileIndex] = tileInput; this.tileInputMask = new RawList<bool>(tileIndex + 1); this.tileInputMask.Count = tileIndex + 1; this.tileInputMask.Data[tileIndex] = true; }
public EditTilesetAutoTileItemAction(Tileset tileset, TilesetAutoTileInput autoTile, int tileIndex, TilesetAutoTileItem tileInput) { if (tileset == null) throw new ArgumentNullException("tileset"); if (autoTile == null) throw new ArgumentNullException("autoTile"); this.tileset = tileset; this.autoTile = autoTile; this.tileInput = new RawList<TilesetAutoTileItem>(tileIndex + 1); this.tileInput.Count = tileIndex + 1; this.tileInput.Data[tileIndex] = tileInput; this.tileInputMask = new RawList<bool>(tileIndex + 1); this.tileInputMask.Count = tileIndex + 1; this.tileInputMask.Data[tileIndex] = true; }
///<summary> /// Constructs a new convex contact manifold constraint. ///</summary> public ConvexContactManifoldConstraint() { //All of the constraints are always in the solver group. Some of them are just deactivated sometimes. //This reduces some bookkeeping complications. penetrationConstraints = new RawList<ContactPenetrationConstraint>(4); //Order matters in this adding process. Sliding friction computes some information used by the twist friction, and both use penetration impulses. for (int i = 0; i < 4; i++) { var penetrationConstraint = new ContactPenetrationConstraint(); Add(penetrationConstraint); penetrationConstraintPool.Push(penetrationConstraint); } slidingFriction = new SlidingFrictionTwoAxis(); Add(slidingFriction); twistFriction = new TwistFrictionConstraint(); Add(twistFriction); }
///<summary> /// Constructs a new nonconvex manifold constraint. ///</summary> public NonConvexContactManifoldConstraint() { //All of the constraints are always in the solver group. Some of them are just deactivated sometimes. //This reduces some bookkeeping complications. penetrationConstraints = new RawList<ContactPenetrationConstraint>(4); frictionConstraints = new RawList<ContactFrictionConstraint>(4); for (int i = 0; i < 4; i++) { var penetrationConstraint = new ContactPenetrationConstraint(); penetrationConstraintPool.Push(penetrationConstraint); Add(penetrationConstraint); var frictionConstraint = new ContactFrictionConstraint(); frictionConstraintPool.Push(frictionConstraint); Add(frictionConstraint); } }
public void CopyTo() { RawList<int> list = new RawList<int>(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 100, 100 }, 10); RawList<int> listCopy = new RawList<int>(list); Assert.AreNotSame(list.Data, listCopy.Data); Assert.AreEqual(list.Count, listCopy.Count); CollectionAssert.AreEqual(list.Data.Take(list.Count), listCopy.Data.Take(list.Count)); CollectionAssert.AreEqual(list, listCopy); RawList<int> listCopy2 = new RawList<int>(); Assert.Throws<ArgumentNullException>(() => list.CopyTo(null, 0, 1)); Assert.Throws<ArgumentException>(() => list.CopyTo(listCopy2, 0, 17)); Assert.Throws<ArgumentException>(() => list.CopyTo(listCopy2, -1, 1)); CollectionAssert.AreEqual(new int[] { }, listCopy2); list.CopyTo(listCopy2, 1, 2); CollectionAssert.AreEqual(new int[] { 0, 0, 1 }, listCopy2); list.CopyTo(listCopy2, 0, 10); CollectionAssert.AreEqual(list, listCopy2); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public ConvexHullTestDemo(DemosGame game) : base(game) { var vertices = new[] { new Vector3(0, -1.750886E-9f, -1.5f), new Vector3(1, 1, 0.5f), new Vector3(1, -1, 0.5f), new Vector3(-1, 1, 0.5f), new Vector3(-1, -1, 0.5f), }; RawList<Vector3> hullVertices = new RawList<Vector3>(); ConvexHullHelper.GetConvexHull(vertices, hullVertices); ConvexHull hull = new ConvexHull(vertices, 5); ShapeDistributionInformation shapeInfo; hull.CollisionInformation.Shape.ComputeDistributionInformation(out shapeInfo); Space.Add(hull); Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
public FCOContactManifold() { contacts = new RawList<Contact>(4); unusedContacts = new UnsafeResourcePool<Contact>(4); contactIndicesToRemove = new RawList<int>(4); }
///<summary> /// Constructs a new compound shape from cached data. ///</summary> ///<param name="shapes">Shape entries used to create the compound. Assumed to be centered properly.</param> /// <param name="volumeDescription">Description of the volume and its distribution in the shape. Assumed to be correct; no processing or validation is performed.</param> public CompoundShape(IList <CompoundShapeEntry> shapes, EntityShapeVolumeDescription volumeDescription) { this.shapes = new RawList <CompoundShapeEntry>(shapes); UpdateEntityShapeVolume(volumeDescription); }
public EditTilesetTileInputAction(Tileset tileset, RawList <TileInput> tileInput, RawList <bool> tileInputMask) { if (tileset == null) { throw new ArgumentNullException("tileset"); } if (tileInput == null) { throw new ArgumentNullException("tileInput"); } if (tileInputMask == null) { throw new ArgumentNullException("tileInputMask"); } if (tileInputMask.Count != tileInput.Count) { throw new ArgumentException("Input Mask needs to be the same size as input.", "tileInputMask"); } this.tileset = tileset; this.tileInput = tileInput; this.tileInputMask = tileInputMask; }
public override void Draw(IDrawDevice device) { // Determine basic working data Tilemap tilemap = this.ActiveTilemap; Tileset tileset = tilemap != null ? tilemap.Tileset.Res : null; Point2 tileCount = tilemap != null ? tilemap.Size : new Point2(1, 1); Vector2 tileSize = tileset != null ? tileset.TileSize : Tileset.DefaultTileSize; // Early-out, if insufficient if (tilemap == null) { return; } if (tileset == null) { return; } // Determine the total size and origin of the rendered Tilemap Vector2 renderTotalSize = tileCount * tileSize; Vector2 renderOrigin = Vector2.Zero; this.origin.ApplyTo(ref renderOrigin, ref renderTotalSize); MathF.TransformCoord(ref renderOrigin.X, ref renderOrigin.Y, this.GameObj.Transform.Angle, this.GameObj.Transform.Scale); // Determine Tile visibility TilemapCulling.TileInput cullingIn = new TilemapCulling.TileInput { // Remember: All these transform values are in world space TilemapPos = this.GameObj.Transform.Pos + new Vector3(renderOrigin), TilemapScale = this.GameObj.Transform.Scale, TilemapAngle = this.GameObj.Transform.Angle, TileCount = tileCount, TileSize = tileSize }; TilemapCulling.TileOutput cullingOut = TilemapCulling.GetVisibleTileRect(device, cullingIn); int renderedTileCount = cullingOut.VisibleTileCount.X * cullingOut.VisibleTileCount.Y; // Determine rendering parameters Material material = (tileset != null ? tileset.RenderMaterial : null) ?? Material.Checkerboard.Res; ColorRgba mainColor = this.colorTint; // Determine and adjust data for Z offset generation float depthPerTile = -cullingIn.TileSize.Y * cullingIn.TilemapScale * this.tileDepthScale; if (this.tileDepthMode == TileDepthOffsetMode.Flat) { depthPerTile = 0.0f; } float originDepthOffset = Rect.Align(this.origin, 0, 0, 0, tileCount.Y * depthPerTile).Y; if (this.tileDepthMode == TileDepthOffsetMode.World) { originDepthOffset += (this.GameObj.Transform.Pos.Y / (float)tileSize.Y) * depthPerTile; } float renderBaseOffset = this.offset + this.tileDepthOffset * depthPerTile + originDepthOffset; // Prepare vertex generation data Vector2 tileXStep = cullingOut.XAxisWorld * cullingIn.TileSize.X; Vector2 tileYStep = cullingOut.YAxisWorld * cullingIn.TileSize.Y; Vector3 renderPos = cullingOut.RenderOriginWorld; float renderOffset = renderBaseOffset; Point2 tileGridPos = cullingOut.VisibleTileStart; // Reserve the required space for vertex data in our locally cached buffer const int MaxVerticesPerBatch = 65532; if (this.vertices == null) { this.vertices = new RawList <VertexC1P3T2>(); } this.vertices.Count = Math.Min(renderedTileCount * 4, MaxVerticesPerBatch); VertexC1P3T2[] vertexData = this.vertices.Data; // Prepare vertex data array for batch-submitting IReadOnlyGrid <Tile> tiles = tilemap.Tiles; TileInfo[] tileData = tileset.TileData.Data; int submittedTileCount = 0; int submittedBatchCount = 0; int vertexBaseIndex = 0; for (int tileIndex = 0; tileIndex < renderedTileCount; tileIndex++) { Tile tile = tiles[tileGridPos.X, tileGridPos.Y]; if (tile.Index < tileData.Length) { Rect uvRect = tileData[tile.Index].TexCoord0; bool visualEmpty = tileData[tile.Index].IsVisuallyEmpty; int tileBaseOffset = tileData[tile.Index].DepthOffset; float localDepthOffset = (tile.DepthOffset + tileBaseOffset) * depthPerTile; if (!visualEmpty) { vertexData[vertexBaseIndex + 0].Pos.X = renderPos.X; vertexData[vertexBaseIndex + 0].Pos.Y = renderPos.Y; vertexData[vertexBaseIndex + 0].Pos.Z = renderPos.Z; vertexData[vertexBaseIndex + 0].DepthOffset = renderOffset + localDepthOffset; vertexData[vertexBaseIndex + 0].TexCoord.X = uvRect.X; vertexData[vertexBaseIndex + 0].TexCoord.Y = uvRect.Y; vertexData[vertexBaseIndex + 0].Color = mainColor; vertexData[vertexBaseIndex + 1].Pos.X = renderPos.X + tileYStep.X; vertexData[vertexBaseIndex + 1].Pos.Y = renderPos.Y + tileYStep.Y; vertexData[vertexBaseIndex + 1].Pos.Z = renderPos.Z; vertexData[vertexBaseIndex + 1].DepthOffset = renderOffset + localDepthOffset + depthPerTile; vertexData[vertexBaseIndex + 1].TexCoord.X = uvRect.X; vertexData[vertexBaseIndex + 1].TexCoord.Y = uvRect.Y + uvRect.H; vertexData[vertexBaseIndex + 1].Color = mainColor; vertexData[vertexBaseIndex + 2].Pos.X = renderPos.X + tileXStep.X + tileYStep.X; vertexData[vertexBaseIndex + 2].Pos.Y = renderPos.Y + tileXStep.Y + tileYStep.Y; vertexData[vertexBaseIndex + 2].Pos.Z = renderPos.Z; vertexData[vertexBaseIndex + 2].DepthOffset = renderOffset + localDepthOffset + depthPerTile; vertexData[vertexBaseIndex + 2].TexCoord.X = uvRect.X + uvRect.W; vertexData[vertexBaseIndex + 2].TexCoord.Y = uvRect.Y + uvRect.H; vertexData[vertexBaseIndex + 2].Color = mainColor; vertexData[vertexBaseIndex + 3].Pos.X = renderPos.X + tileXStep.X; vertexData[vertexBaseIndex + 3].Pos.Y = renderPos.Y + tileXStep.Y; vertexData[vertexBaseIndex + 3].Pos.Z = renderPos.Z; vertexData[vertexBaseIndex + 3].DepthOffset = renderOffset + localDepthOffset; vertexData[vertexBaseIndex + 3].TexCoord.X = uvRect.X + uvRect.W; vertexData[vertexBaseIndex + 3].TexCoord.Y = uvRect.Y; vertexData[vertexBaseIndex + 3].Color = mainColor; bool vertical = tileData[tile.Index].IsVertical; if (vertical) { vertexData[vertexBaseIndex + 0].DepthOffset += depthPerTile; vertexData[vertexBaseIndex + 3].DepthOffset += depthPerTile; } submittedTileCount++; vertexBaseIndex += 4; } } tileGridPos.X++; renderPos.X += tileXStep.X; renderPos.Y += tileXStep.Y; if ((tileGridPos.X - cullingOut.VisibleTileStart.X) >= cullingOut.VisibleTileCount.X) { tileGridPos.X = cullingOut.VisibleTileStart.X; tileGridPos.Y++; renderPos = cullingOut.RenderOriginWorld; renderPos.X += tileYStep.X * (tileGridPos.Y - cullingOut.VisibleTileStart.Y); renderPos.Y += tileYStep.Y * (tileGridPos.Y - cullingOut.VisibleTileStart.Y); renderOffset = renderBaseOffset + tileGridPos.Y * depthPerTile; } // If we reached the maximum number of vertices per batch, submit early and restart if (vertexBaseIndex >= MaxVerticesPerBatch) { device.AddVertices( material, VertexMode.Quads, vertexData, vertexBaseIndex); vertexBaseIndex = 0; submittedBatchCount++; } } // Submit the final batch will all remaining vertices if (vertexBaseIndex > 0) { device.AddVertices( material, VertexMode.Quads, vertexData, vertexBaseIndex); submittedBatchCount++; } Profile.AddToStat(@"Duality\Stats\Render\Tilemaps\NumTiles", renderedTileCount); Profile.AddToStat(@"Duality\Stats\Render\Tilemaps\NumVertices", submittedTileCount * 4); Profile.AddToStat(@"Duality\Stats\Render\Tilemaps\NumBatches", submittedBatchCount); }
public FontTexture(int width, int height, int linescount, RawList <WebLinkRect> links) : base(width, height) { LinesCount = linescount; Links = links; }
///<summary> /// Constructs a new manifold. ///</summary> public BoxContactManifold() { contacts = new RawList <Contact>(4); unusedContacts = new UnsafeResourcePool <Contact>(4); contactIndicesToRemove = new RawList <int>(4); }
protected override void CollectInvolvedEntities(RawList<Entity> outputInvolvedEntities) { var entityCollidable = supportData.SupportObject as EntityCollidable; if (entityCollidable != null) outputInvolvedEntities.Add(entityCollidable.Entity); outputInvolvedEntities.Add(character.Body); }
/// <summary> /// Returns a resource to the pool. /// </summary> /// <param name="list">List to return.</param> public static void GiveBack(RawList <RayHit> list) { list.Clear(); SubPoolRayHitList.GiveBack(list); }
/// <summary> /// Returns a resource to the pool. /// </summary> /// <param name="list">List to return.</param> public static void GiveBack(RawList <int> list) { list.Clear(); SubPoolIntList.GiveBack(list); }
///<summary> /// Constructs a new manifold. ///</summary> public SphereContactManifold() { contacts = new RawList <Contact>(1); }
private void CollectDrawcalls() { // If no visibility groups are met, don't bother looking for renderers. // This is important to allow efficient drawcall injection with additional // "dummy" renderpasses. CamViewStates render their overlays by temporarily // adding 3 - 4 of these passes. Iterating over all objects again would be // devastating for performance and at the same time pointless. if ((this.drawDevice.VisibilityMask & VisibilityFlag.AllGroups) == VisibilityFlag.None) { return; } // Query renderers IRendererVisibilityStrategy visibilityStrategy = Scene.Current.VisibilityStrategy; RawList <ICmpRenderer> visibleRenderers; { if (visibilityStrategy == null) { return; } Profile.TimeQueryVisibleRenderers.BeginMeasure(); visibleRenderers = new RawList <ICmpRenderer>(); visibilityStrategy.QueryVisibleRenderers(this.drawDevice, visibleRenderers); if (this.editorRenderFilter.Count > 0) { visibleRenderers.RemoveAll(r => { for (int i = 0; i < this.editorRenderFilter.Count; i++) { if (!this.editorRenderFilter[i](r)) { return(true); } } return(false); }); } Profile.TimeQueryVisibleRenderers.EndMeasure(); } // Collect drawcalls if (this.drawDevice.IsPicking) { this.pickingMap.AddRange(visibleRenderers); foreach (ICmpRenderer r in visibleRenderers) { r.Draw(this.drawDevice); this.drawDevice.PickingIndex++; } } else { bool profilePerType = visibilityStrategy.IsRendererQuerySorted; Profile.TimeCollectDrawcalls.BeginMeasure(); Type lastRendererType = null; Type rendererType = null; TimeCounter activeProfiler = null; ICmpRenderer[] data = visibleRenderers.Data; for (int i = 0; i < data.Length; i++) { if (i >= visibleRenderers.Count) { break; } // Manage profilers per Component type if (profilePerType) { rendererType = data[i].GetType(); if (rendererType != lastRendererType) { if (activeProfiler != null) { activeProfiler.EndMeasure(); } activeProfiler = Profile.RequestCounter <TimeCounter>(Profile.TimeCollectDrawcalls.FullName + @"\" + rendererType.Name); activeProfiler.BeginMeasure(); lastRendererType = rendererType; } } // Collect Drawcalls from this Component data[i].Draw(this.drawDevice); } if (activeProfiler != null) { activeProfiler.EndMeasure(); } Profile.TimeCollectDrawcalls.EndMeasure(); } }
protected internal override void CollectInvolvedEntities(RawList<Entity> outputInvolvedEntities) { //This should never really have to be called. if (entityA != null) outputInvolvedEntities.Add(entityA); if (entityB != null) outputInvolvedEntities.Add(entityB); }
internal bool IsPointContained(ref Vector3 point, RawList<int> triangles) { Vector3 rayDirection; //Point from the approximate center of the mesh outwards. //This is a cheap way to reduce the number of unnecessary checks when objects are external to the mesh. Vector3.Add(ref boundingBox.Max, ref boundingBox.Min, out rayDirection); Vector3.Multiply(ref rayDirection, .5f, out rayDirection); Vector3.Subtract(ref point, ref rayDirection, out rayDirection); //If the point is right in the middle, we'll need a backup. if (rayDirection.LengthSquared() < .01f) rayDirection = Vector3.Up; var ray = new Ray(point, rayDirection); triangleMesh.Tree.GetOverlaps(ray, triangles); float minimumT = float.MaxValue; bool minimumIsClockwise = false; for (int i = 0; i < triangles.Count; i++) { Vector3 a, b, c; triangleMesh.Data.GetTriangle(triangles.Elements[i], out a, out b, out c); RayHit hit; bool hitClockwise; if (Toolbox.FindRayTriangleIntersection(ref ray, float.MaxValue, ref a, ref b, ref c, out hitClockwise, out hit)) { if (hit.T < minimumT) { minimumT = hit.T; minimumIsClockwise = hitClockwise; } } } triangles.Clear(); //If the first hit is on the inner surface, then the ray started inside the mesh. return minimumT < float.MaxValue && minimumIsClockwise == innerFacingIsClockwise; }
/// <summary> /// Returns a resource to the pool. /// </summary> /// <param name="list">List to return.</param> public static void GiveBack(RawList <Vector3> list) { list.Clear(); SubPoolVectorList.GiveBack(list); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public BroadPhasesTestDemo(DemosGame game) : base(game) { Space.Solver.IterationLimit = 0; Entity toAdd; //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7)); BoundingBox box = new BoundingBox(new Vector3(-50, -50, -50), new Vector3(50, 50, 50)); //DynamicHierarchyOld dhOld = new DynamicHierarchyOld(Space.ThreadManager); DynamicHierarchy dh = new DynamicHierarchy(Space.ParallelLooper); SortAndSweep1D sas1d = new SortAndSweep1D(Space.ParallelLooper); Grid2DSortAndSweep grid2DSAS = new Grid2DSortAndSweep(Space.ParallelLooper); //DynamicHierarchy dh = new DynamicHierarchy(); //DynamicHierarchy4 dh4 = new DynamicHierarchy4(); //SortAndSweep1D sas1d = new SortAndSweep1D(); //Grid2DSortAndSweep grid2DSAS = new Grid2DSortAndSweep(); //DynamicHierarchy2 dh2 = new DynamicHierarchy2(); //DynamicHierarchy3 dh3 = new DynamicHierarchy3(); //SortAndSweep3D sap3d = new SortAndSweep3D(); RawList <Entity> entities = new RawList <Entity>(); for (int k = 0; k < 100; k++) { Vector3 position = new Vector3((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X, (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y, (Fix64)rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z); toAdd = new Box(position, 1, 1, 1, 1); toAdd.CollisionInformation.CollisionRules.Personal = CollisionRule.NoNarrowPhasePair; toAdd.CollisionInformation.UpdateBoundingBox(0); //Space.Add(toAdd); //dhOld.Add(toAdd.CollisionInformation); dh.Add(toAdd.CollisionInformation); sas1d.Add(toAdd.CollisionInformation); grid2DSAS.Add(toAdd.CollisionInformation); entities.Add(toAdd); } Space.ForceUpdater.Gravity = new Vector3(); int numRuns = 10000; //Prime the system. grid2DSAS.Update(); sas1d.Update(); //dhOld.Update(); dh.Update(); var testType = Test.Update; double startTime, endTime; switch (testType) { #region Update Timing case Test.Update: for (int i = 0; i < numRuns; i++) { ////DH //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //dhOld.Update(); //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //DHOldTime += endTime - startTime; //DH4 startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; dh.Update(); endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; DHtime += endTime - startTime; //SAP1D startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; sas1d.Update(); endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; SAS1Dtime += endTime - startTime; //Grid2D SOS startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; grid2DSAS.Update(); endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; grid2DSAStime += endTime - startTime; //if (sap1d.Overlaps.Count != dh.Overlaps.Count) // Debug.WriteLine("SAP1D Failure"); //if (grid2DSOS.Overlaps.Count != dh.Overlaps.Count) // Debug.WriteLine("grid2DSOS Failure"); //for (int j = 0; j < dh2.Overlaps.Count; j++) //{ // if (!grid2DSOS.Overlaps.Contains(dh2.Overlaps[j])) // Debug.WriteLine("Break."); //} //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++) //{ // if (!dh2.Overlaps.Contains(grid2DSOS.Overlaps[j])) // break; //} //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++) //{ // if (!dh4.Overlaps.Contains(grid2DSOS.Overlaps[j])) // break; //} //for (int j = 0; j < dh.Overlaps.Count; j++) //{ // if (!dh.Overlaps[j].EntryA.BoundingBox.Intersects(dh.Overlaps[j].EntryB.BoundingBox)) // Debug.WriteLine("Break."); //} //for (int j = 0; j < sap1d.Overlaps.Count; j++) //{ // if (!sap1d.Overlaps[j].EntryA.BoundingBox.Intersects(sap1d.Overlaps[j].EntryB.BoundingBox)) // Debug.WriteLine("Break."); //} //for (int j = 0; j < grid2DSOS.Overlaps.Count; j++) //{ // if (!grid2DSOS.Overlaps[j].EntryA.BoundingBox.Intersects(grid2DSOS.Overlaps[j].EntryB.BoundingBox)) // Debug.WriteLine("Break."); //} //MoveEntities(entities); } break; #endregion #region Ray cast timing case Test.RayCast: Fix64 rayLength = 100; RawList <Ray> rays = new RawList <Ray>(); for (int i = 0; i < numRuns; i++) { rays.Add(new Ray() { Position = new Vector3((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X, (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y, (Fix64)rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z), Direction = Vector3.Normalize(new Vector3((Fix64)(rand.NextDouble() - .5), (Fix64)(rand.NextDouble() - .5), (Fix64)(rand.NextDouble() - .5))) }); } RawList <BroadPhaseEntry> outputIntersections = new RawList <BroadPhaseEntry>(); ////DH //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //for (int i = 0; i < numRuns; i++) //{ // dhOld.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections); // outputIntersections.Clear(); //} //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //DHOldTime = endTime - startTime; //DH4 startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int i = 0; i < numRuns; i++) { dh.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections); outputIntersections.Clear(); } endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; DHtime = endTime - startTime; //Grid2DSAS startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int i = 0; i < numRuns; i++) { grid2DSAS.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections); outputIntersections.Clear(); } endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; grid2DSAStime = endTime - startTime; break; #endregion #region Bounding box query timing case Test.BoundingBoxQuery: Fix64 boundingBoxSize = 10; var boundingBoxes = new RawList <BoundingBox>(); Vector3 offset = new Vector3(boundingBoxSize / 2, boundingBoxSize / 2, boundingBoxSize / 2); for (int i = 0; i < numRuns; i++) { Vector3 center = new Vector3((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X, (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y, (Fix64)rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z); boundingBoxes.Add(new BoundingBox() { Min = center - offset, Max = center + offset }); } outputIntersections = new RawList <BroadPhaseEntry>(); ////DH //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //for (int i = 0; i < numRuns; i++) //{ // dhOld.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections); // outputIntersections.Clear(); //} //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //DHOldTime = endTime - startTime; //DH4 startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int i = 0; i < numRuns; i++) { dh.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections); outputIntersections.Clear(); } endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; DHtime = endTime - startTime; //Grid2DSAS startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int i = 0; i < numRuns; i++) { grid2DSAS.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections); outputIntersections.Clear(); } endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; grid2DSAStime = endTime - startTime; break; #endregion } DHOldTime /= numRuns; DH2time /= numRuns; DH3time /= numRuns; DHtime /= numRuns; SAS1Dtime /= numRuns; grid2DSAStime /= numRuns; }
/// <summary> /// Returns a resource to the pool. /// </summary> /// <param name="list">List to return.</param> public static void GiveBack(RawList <float> list) { list.Clear(); SubPoolFloatList.GiveBack(list); }