public void EdgeOrientPointOnFringe() { var e1 = new EdgeEx(new PointF(0, 0), new PointF(2, 0)); var e2 = new EdgeEx(new PointF(2, 0), new PointF(0, 2)); var e3 = new EdgeEx(new PointF(0, 2), new PointF(0, 0)); Assert.IsTrue(Math.Abs(e1.Orient(new PointF(1,0))) < float.Epsilon); Assert.IsTrue(Math.Abs(e3.Orient(new PointF(0,1))) < float.Epsilon); }
public void EdgeOrientPointOutside() { var e1 = new EdgeEx(new PointF(0, 0), new PointF(2, 0)); var e2 = new EdgeEx(new PointF(2, 0), new PointF(0, 2)); var e3 = new EdgeEx(new PointF(0, 2), new PointF(0, 0)); Assert.IsTrue(e1.Orient(new PointF(1,-1)) < 0); Assert.IsTrue(e2.Orient(new PointF(3,3)) < 0); Assert.IsTrue(e3.Orient(new PointF(-1,1)) < 0); }
public void EdgeOrientPointInside() { var e1 = new EdgeEx(new PointF(0, 0), new PointF(2, 0)); var e2 = new EdgeEx(new PointF(2, 0), new PointF(0, 2)); var e3 = new EdgeEx(new PointF(0, 2), new PointF(0, 0)); var p = new PointF(0.5f, 0.5f); Assert.IsTrue(e1.Orient(p) > 0); Assert.IsTrue(e2.Orient(p) > 0); Assert.IsTrue(e3.Orient(p) > 0); }
private void DrawShadows(Light _light, PointF _avatarPoint) { #if DEBUG using (new Profiler()) #endif { GL.Enable(EnableCap.Multisample); var lp = new PointF(_light.Point.X + 0.5f, _light.Point.Y + 0.5f); GL.Disable(EnableCap.Blend); GL.ClearColor(_light.LightSource.Color.R, _light.LightSource.Color.G, _light.LightSource.Color.B, 1f); GL.Clear(ClearBufferMask.ColorBufferBit); GL.Enable(EnableCap.Blend); #region Собираем все грани лицевые для источника освещения и попадающие в круг света var apnts = new HashSet <PointF>(); var edgesCount = 0; var edges = new EdgeEx[m_edgesCount]; for (var i = 0; i < m_edgesCount; i++) { if (_light.LiveMapCell != null && m_allEdges[i].LiveMapCell == _light.LiveMapCell) { continue; } if (EdgeEx.Distant(m_allEdges[i].P1, lp) >= _light.LightSource.Radius) { continue; } var orient = m_allEdges[i].Orient(lp); if (orient <= 0) { continue; } if (m_allEdges[i].Orient(_avatarPoint) > 0 && !apnts.Contains(m_allEdges[i].CellCenter)) { apnts.Add(m_allEdges[i].CellCenter); } edges[edgesCount] = m_allEdges[i]; edges[edgesCount].Distance = Edge.Distant(m_allEdges[i].CellCenter, lp); edges[edgesCount].Valid = true; edgesCount++; } Array.Sort(edges, 0, edgesCount, new DistanceComparer()); #endregion GL.BlendFunc(BlendingFactorSrc.DstColor, BlendingFactorDest.OneMinusSrcAlpha); var pnts = new HashSet <PointF>(); GL.Begin(BeginMode.Quads); { for (var i = 0; i < edgesCount; i++) { if (!edges[i].Valid) { continue; } if (!pnts.Contains(edges[i].CellCenter)) { pnts.Add(edges[i].CellCenter); } var color = edges[i].LiveMapCell.GetTransparentColor() * _light.LightSource.Color * (1f - edges[i].Opacity); GL.Color4(color.R, color.G, color.B, 1f); var pnt = new[] { edges[i].P2, edges[i].P1, GetFarPnt(lp, edges[i].P1), GetFarPnt(lp, edges[i].P2) }; GL.Vertex2(pnt[0].X, pnt[0].Y); GL.Vertex2(pnt[1].X, pnt[1].Y); GL.Vertex2(pnt[2].X, pnt[2].Y); GL.Vertex2(pnt[3].X, pnt[3].Y); #region Отбрасываем все грани вошедшие внутрь теневой трапеции if (edges[i].Opacity > 0.9f) { var e1 = new EdgeEx(pnt[0], pnt[3]); var e2 = new EdgeEx(pnt[2], pnt[1]); for (var j = i + 1; j < edgesCount; j++) { if (!edges[j].Valid) { continue; } if (!(e1.Orient(edges[j].P2) < -float.Epsilon) || !(e2.Orient(edges[j].P1) < -float.Epsilon)) { continue; } if (!(e1.Orient(edges[j].P1) < -float.Epsilon) || !(e2.Orient(edges[j].P2) < -float.Epsilon)) { continue; } edges[j].Valid = false; } } #endregion } } GL.End(); GL.Disable(EnableCap.Blend); GL.Disable(EnableCap.Multisample); if (_light.LightSource is AvatarSight) { GL.Color4(1f, 1f, 1f, 1f); foreach (var pnt in pnts) { if (apnts.Contains(pnt)) { GL.Vertex2(pnt.X, pnt.Y); } } } else { GL.Begin(BeginMode.Points); { foreach (var pnt in pnts) { if (apnts.Contains(pnt) && pnt != _avatarPoint) { GL.Color4(1f, 1f, 1f, 1f); } else { GL.Color4(0f, 0f, 0f, 1f); } GL.Vertex2(pnt.X, pnt.Y); } } GL.End(); } } }
private void СформироватьМассивГраней() { #if DEBUG using (new Profiler()) #endif { m_edgesCount = 0; var hs = new Dictionary <Int32, int>(); var doubles = 0; for (var i = 1; i < MAP_SIZE - 1; ++i) { for (var j = 1; j < MAP_SIZE - 1; ++j) { var lmc = m_shadowCasters[i, j].LiveMapCell; lmc.FinalLighted = FColor.Empty; if (lmc == null) { continue; } var opacity = m_shadowCasters[i, j].Opacity; if (opacity > 0) { if (m_shadowCasters[i, j - 1].Opacity != opacity || m_shadowCasters[i - 1, j - 1].Opacity != opacity || m_shadowCasters[i + 1, j - 1].Opacity != opacity || m_shadowCasters[i, j + 1].Opacity != opacity || m_shadowCasters[i - 1, j + 1].Opacity != opacity || m_shadowCasters[i + 1, j + 1].Opacity != opacity || m_shadowCasters[i, j].Opacity != opacity || m_shadowCasters[i - 1, j].Opacity != opacity || m_shadowCasters[i + 1, j].Opacity != opacity) { var rect = new RectangleF(i, j, 1, 1); Action <PointF, PointF> add = (_a, _b) => { var edge = new EdgeEx(_a, _b); int doubleIndex; if (hs.TryGetValue(edge.GetHashCode(), out doubleIndex) && m_allEdges[doubleIndex].Opacity == opacity) { hs.Remove(edge.GetHashCode()); m_edgesCount--; doubles++; hs[m_allEdges[m_edgesCount].GetHashCode()] = doubleIndex; m_allEdges[doubleIndex] = m_allEdges[m_edgesCount]; return; } hs[edge.GetHashCode()] = m_edgesCount; m_allEdges[m_edgesCount++] = new EdgeEx(_a, _b) { Opacity = opacity, LiveMapCell = lmc, CellCenter = new PointF(i, j) }; }; add(new PointF(rect.Left, rect.Top), new PointF(rect.Right, rect.Top)); add(new PointF(rect.Right, rect.Bottom), new PointF(rect.Left, rect.Bottom)); add(new PointF(rect.Right, rect.Top), new PointF(rect.Right, rect.Bottom)); add(new PointF(rect.Left, rect.Bottom), new PointF(rect.Left, rect.Top)); } } } } } }