public Hit hit = new Hit(); // Result of ray casting. Contains last ray state if not. // Casts a ray, returns true if a collision occurred. // Options of the raycaster are used. // Important : you must normalize the ray direction, // otherwise the crossed distance will not be accurate. public Hit Cast(Vector2f origin, Vector2f direction, HitPredicate hitFunc, float maxDistance) { float infinite = 9999999; // Equation : p + v*t // p : ray start position (ray.pos) // v : ray orientation vector (ray.dir) // t : parametric variable = a distance if v is normalized // This raycasting technique is described here : // http://www.cse.yorku.ca/~amana/research/grid.pdf // Note : the grid is assumed to have 1-unit square cells. // // Initialisation // hit.isHit = false; // Cell position hit.pos.X = (int)Mathf.Floor(origin.X); hit.pos.Y = (int)Mathf.Floor(origin.Y); hit.prevPos = hit.pos; // Voxel step (will not change) int xi_step = direction.X > 0 ? 1 : direction.X < 0 ? -1 : 0; int yi_step = direction.Y > 0 ? 1 : direction.Y < 0 ? -1 : 0; // Parametric voxel step (will not change) float tdelta_x = xi_step != 0 ? 1f / Mathf.Abs(direction.X) : infinite; float tdelta_y = yi_step != 0 ? 1f / Mathf.Abs(direction.Y) : infinite; // Parametric grid-cross float tcross_x; // At which value of T we will cross a vertical line? float tcross_y; // At which value of T we will cross a horizontal line? // X initialization if (xi_step != 0) { if (xi_step == 1) { tcross_x = (Mathf.Ceil(origin.X) - origin.X) * tdelta_x; } else { tcross_x = (origin.X - Mathf.Floor(origin.X)) * tdelta_x; } } else { tcross_x = infinite; // Will never cross on X } // Y initialization if (yi_step != 0) { if (yi_step == 1) { tcross_y = (Mathf.Ceil(origin.Y) - origin.Y) * tdelta_y; } else { tcross_y = (origin.Y - Mathf.Floor(origin.Y)) * tdelta_y; } } else { tcross_y = infinite; // Will never cross on X } // // Iteration // do { hit.prevPos = hit.pos; if (tcross_x < tcross_y) { // X collision //hit.prevPos.x = hit.pos.x; hit.pos.X += xi_step; if (tcross_x > maxDistance) { return(hit); } tcross_x += tdelta_x; } else { // Y collision //hit.prevPos.y = hit.pos.y; hit.pos.Y += yi_step; if (tcross_y > maxDistance) { return(hit); } tcross_y += tdelta_y; } } while (!hitFunc(hit.pos.X, hit.pos.Y)); return(hit); }
public void Draw(Vector2f position, IntRect subRect) { Draw(position, subRect, Color.White); }
public void DrawCentered(Vector2f position, IntRect subRect, Color color, Vector2f scale, float rotation) { Draw(position, subRect, color, scale, new Vector2f((float)subRect.Width / 2f, (float)subRect.Height / 2f), rotation); }
public void Draw(Vector2f position, IntRect subRect, Color color, Vector2f scale, Vector2f origin, float rotation) { if (_primitiveCount * 4 >= _vertices.Length) { Array.Resize <Vertex>(ref _vertices, _vertices.Length * 2); } float sin = __sin.GetRepeat(rotation); float cos = __cos.GetRepeat(rotation); origin.X *= scale.X; origin.Y *= scale.Y; scale.X *= subRect.Width; scale.Y *= subRect.Height; Vertex v = new Vertex(); v.Color = color; float pX, pY; uint vi = _primitiveCount * 4; pX = -origin.X; pY = -origin.Y; v.Position.X = pX * cos - pY * sin + position.X; v.Position.Y = pX * sin + pY * cos + position.Y; v.TexCoords.X = subRect.Left + E; v.TexCoords.Y = subRect.Top + E; _vertices[vi] = v; pX += scale.X; v.Position.X = pX * cos - pY * sin + position.X; v.Position.Y = pX * sin + pY * cos + position.Y; v.TexCoords.X += subRect.Width - 2f * E; _vertices[vi + 1] = v; pY += scale.Y; v.Position.X = pX * cos - pY * sin + position.X; v.Position.Y = pX * sin + pY * cos + position.Y; v.TexCoords.Y += subRect.Height - 2f * E; _vertices[vi + 2] = v; pX -= scale.X; v.Position.X = pX * cos - pY * sin + position.X; v.Position.Y = pX * sin + pY * cos + position.Y; v.TexCoords.X -= subRect.Width - 2f * E; _vertices[vi + 3] = v; ++_primitiveCount; }