private static int IntepolateValue(int val1, int val2, float delta, string mode) { switch (mode) { case BridgeInterpolationMode.HIGHEST: case BridgeInterpolationMode.BRIGHTNESS_HIGHEST: return(Math.Max(val1, val2)); case BridgeInterpolationMode.LOWEST: case BridgeInterpolationMode.BRIGHTNESS_LOWEST: return(Math.Min(val1, val2)); case BridgeInterpolationMode.LINEAR: return((int)Math.Round(InterpolationTools.Linear(val1, val2, delta))); case BridgeInterpolationMode.IN_SINE: return((int)Math.Round(InterpolationTools.EaseInSine(val1, val2, delta))); case BridgeInterpolationMode.OUT_SINE: return((int)Math.Round(InterpolationTools.EaseOutSine(val1, val2, delta))); case BridgeInterpolationMode.IN_OUT_SINE: return((int)Math.Round(InterpolationTools.EaseInOutSine(val1, val2, delta))); default: throw new Exception("DrawBezierPathMode.IntepolateValue: \"" + mode + "\" mode is not supported!"); } }
private List <Vector2D[]> GetShapes(Vector2D s, Vector2D e) { // No shape if (s == e) { return(new List <Vector2D[]>()); } // Setup slices switch (gridlockmode) { case GridLockMode.NONE: slicesH = horizontalslices; slicesV = verticalslices; break; case GridLockMode.HORIZONTAL: slicesH = width / General.Map.Grid.GridSize; slicesV = verticalslices; break; case GridLockMode.VERTICAL: slicesH = horizontalslices; slicesV = Math.Abs(height / General.Map.Grid.GridSize); break; case GridLockMode.BOTH: slicesH = Math.Abs(width / General.Map.Grid.GridSize); slicesV = Math.Abs(height / General.Map.Grid.GridSize); break; } // Create a segmented line List <Vector2D[]> shapes; if (width == 0 || height == 0) { if (slicesH > 0 && width > 0) { shapes = new List <Vector2D[]>(); int step = width / slicesH; for (int w = 0; w < slicesH; w++) { shapes.Add(new[] { new Vector2D(s.x + step * w, s.y), new Vector2D(s.x + step * w + step, s.y) }); } return(shapes); } if (slicesV > 0 && height > 0) { shapes = new List <Vector2D[]>(); int step = height / slicesV; for (int h = 0; h < slicesV; h++) { shapes.Add(new[] { new Vector2D(s.x, s.y + step * h), new Vector2D(s.x, s.y + step * h + step) }); } return(shapes); } // Create a line return(new List <Vector2D[]> { new[] { s, e } }); } // Create grid shape List <Vector2D> rect = new List <Vector2D> { s, new Vector2D(s.x, e.y), e, new Vector2D(e.x, s.y), s }; if (slicesH == 1 && slicesV == 1) { if (triangulate) { rect.AddRange(new[] { s, e }); } return(new List <Vector2D[]> { rect.ToArray() }); } // Create blocks shapes = new List <Vector2D[]> { rect.ToArray() }; RectangleF[,] blocks = new RectangleF[slicesH, slicesV]; for (int w = 0; w < slicesH; w++) { for (int h = 0; h < slicesV; h++) { double left = (InterpolationTools.Interpolate(s.x, e.x, (double)w / slicesH, horizontalinterpolation)); double top = (InterpolationTools.Interpolate(s.y, e.y, (double)h / slicesV, verticalinterpolation)); double right = (InterpolationTools.Interpolate(s.x, e.x, (w + 1.0f) / slicesH, horizontalinterpolation)); double bottom = (InterpolationTools.Interpolate(s.y, e.y, (h + 1.0f) / slicesV, verticalinterpolation)); blocks[w, h] = RectangleF.FromLTRB((float)left, (float)top, (float)right, (float)bottom); } } // Add subdivisions if (slicesH > 1) { for (int w = 1; w < slicesH; w++) { float px = blocks[w, 0].X; shapes.Add(new[] { new Vector2D(px, s.y), new Vector2D(px, e.y) }); } } if (slicesV > 1) { for (int h = 1; h < slicesV; h++) { float py = blocks[0, h].Y; shapes.Add(new[] { new Vector2D(s.x, py), new Vector2D(e.x, py) }); } } // Triangulate? if (triangulate) { bool startflip = ((int)Math.Round(((s.x + e.y) / General.Map.Grid.GridSizeF) % 2) == 0); bool flip = startflip; for (int w = 0; w < slicesH; w++) { for (int h = slicesV - 1; h > -1; h--) { if (flip) { shapes.Add(new[] { new Vector2D(blocks[w, h].X, blocks[w, h].Y), new Vector2D(blocks[w, h].Right, blocks[w, h].Bottom) }); } else { shapes.Add(new[] { new Vector2D(blocks[w, h].Right, blocks[w, h].Y), new Vector2D(blocks[w, h].X, blocks[w, h].Bottom) }); } flip = !flip; } startflip = !startflip; flip = startflip; } } return(shapes); }
// This generates the vertices to split the line with, from start to end private List <Vector2D> GenerateCurve(Linedef line) { // Fetch settings from the panel bool fixedcurve = panel.FixedCurve; int vertices = Math.Min(panel.Vertices, (int)Math.Ceiling(line.Length / 4)); int distance = panel.Distance; int angle = (!fixedcurve && distance == 0 ? Math.Max(5, panel.Angle) : panel.Angle); float theta = Angle2D.DegToRad(angle); if (distance < 0) { theta = -theta; //mxd } // Make list List <Vector2D> points = new List <Vector2D>(vertices); float segDelta = 1.0f / (vertices + 1); //mxd Vector2D linecenter = line.GetCenterPoint(); //mxd //mxd. Special cases... if (angle == 0) { for (int v = 1; v <= vertices; v++) { float x = (line.Length * segDelta) * (vertices - v + 1) - line.Length * 0.5f; // Line segment coord // Rotate and transform to fit original line Vector2D vertex = new Vector2D(x, 0).GetRotated(line.Angle + Angle2D.PIHALF) + linecenter; points.Add(vertex); } } else { //Added by Anders Åstrand 2008-05-18 //The formulas used are taken from http://mathworld.wolfram.com/CircularSegment.html //c and theta are known (length of line and angle parameter). d, R and h are //calculated from those two //If the curve is not supposed to be a circular segment it's simply deformed to fit //the value set for distance. //The vertices are generated to be evenly distributed (by angle) along the curve //and lastly they are rotated and moved to fit with the original line //calculate some identities of a circle segment (refer to the graph in the url above) float c = line.Length; float d = (c / (float)Math.Tan(theta / 2)) / 2; float R = d / (float)Math.Cos(theta / 2); float h = R - d; float yDeform = (fixedcurve ? 1 : distance / h); float xDelta = Math.Min(1, yDeform); //mxd for (int v = 1; v <= vertices; v++) { //calculate the angle for this vertex //the curve starts at PI/2 - theta/2 and is segmented into vertices+1 segments //this assumes the line is horisontal and on y = 0, the point is rotated and moved later float a = (Angle2D.PI - theta) / 2 + v * (theta / (vertices + 1)); //calculate the coordinates of the point, and distort the y coordinate //using the deform factor calculated above float xr = (float)Math.Cos(a) * R; //mxd. Circle segment coord float xl = (line.Length * segDelta) * (vertices - v + 1) - line.Length * 0.5f; // mxd. Line segment coord float x = InterpolationTools.Linear(xl, xr, xDelta); //mxd float y = ((float)Math.Sin(a) * R - d) * yDeform; //rotate and transform to fit original line Vector2D vertex = new Vector2D(x, y).GetRotated(line.Angle + Angle2D.PIHALF) + linecenter; points.Add(vertex); } } // Done return(points); }
private void UpdateShading() { // Update sector shading foreach (KeyValuePair <Sector, Vector3D> group in sectors) { // Calculate light amount float anglediff = Vector3D.DotProduct(group.Value, sunvector); int targetlight; PixelColor targetcolor; // Calculate light and light color when surface normal is rotated towards the sun vector if (anglediff >= 0.5f) { float lightmul = (anglediff - 0.5f) * 2.0f; targetlight = (int)Math.Round(lightamount.Value * lightmul); targetcolor = InterpolationTools.InterpolateColor(shadecolor.Color, lightcolor.Color, anglediff); } // Otherwise calculate shade and shade color else { float lightmul = (0.5f - anglediff) * -2.0f; targetlight = (int)Math.Round(shadeamount.Value * lightmul); targetcolor = InterpolationTools.InterpolateColor(shadecolor.Color, lightcolor.Color, anglediff); } // Apply settings if (group.Key.Fields.GetValue("lightfloorabsolute", false)) { UniFields.SetInteger(group.Key.Fields, "lightfloor", General.Clamp(targetlight + sectorbrightness[group.Key], 0, 255), 0); } else { UniFields.SetInteger(group.Key.Fields, "lightfloor", General.Clamp(targetlight, -255, 255), 0); } // Apply sector color int c = (targetcolor.ToInt() & 0x00FFFFFF); // Restore initial color? if (c == PixelColor.INT_WHITE_NO_ALPHA) { c = sectorcolors[group.Key]; } // Apply color UniFields.SetInteger(group.Key.Fields, "lightcolor", c, PixelColor.INT_WHITE_NO_ALPHA); // Mark for update group.Key.UpdateNeeded = true; } // Update sidedef shading foreach (KeyValuePair <Sidedef, Vector3D> group in sides) { // Calculate light amount float anglediff = Vector3D.DotProduct(group.Value, sunvector); int targetlight; // Calculate light and light color when surface normal is rotated towards the sun vector if (anglediff >= 0.5f) { float lightmul = (anglediff - 0.5f) * 2.0f; targetlight = (int)Math.Round(lightamount.Value * lightmul); } // Otherwise calculate shade and shade color else { float lightmul = (0.5f - anglediff) * -2.0f; targetlight = (int)Math.Round(shadeamount.Value * lightmul); } // Apply settings if (group.Key.Fields.GetValue("lightabsolute", false)) { UniFields.SetInteger(group.Key.Fields, "light", General.Clamp(targetlight + sidebrightness[group.Key], 0, 255), 0); } else { UniFields.SetInteger(group.Key.Fields, "light", General.Clamp(targetlight, -255, 255), 0); } // Mark for update group.Key.Sector.UpdateNeeded = true; } // Update map General.Map.Map.Update(); General.Map.IsChanged = true; // Update view if (visualsectors != null) { foreach (var vs in visualsectors) { vs.UpdateSectorData(); } } else if (sectors.Count > 0) { General.Interface.RedrawDisplay(); } }