Пример #1
0
        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!");
            }
        }
Пример #2
0
        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);
        }
Пример #3
0
        // 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);
        }
Пример #4
0
        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();
            }
        }