Example #1
0
 public static GradVertex SolidVert(Vector2 position, Color color, EllipseDesc ellipse)
 {
     return(new GradVertex()
     {
         Color1 = color,
         Coord = position,
         Params = new Vector4(0, 0, ellipse.pos.X, ellipse.pos.Y),
         EllipseDat = ellipse.dimensions
     });
 }
Example #2
0
        public static Tuple <GradVertex[], int[]> GenerateShadows(IEnumerable <Vector2[]> volumes, LightData light, List <Vector3> ctrWidths, List <Rectangle> rectGeom)
        {
            DistanceMult = 5000f;
            var pointLight = light.LightPos;
            var mat_cw     = Matrix.CreateRotationZ(WallPenumbra);
            var mat_ccw    = Matrix.CreateRotationZ(-WallPenumbra);
            var vertices   = new List <GradVertex>();
            var indices    = new List <int>();
            var j          = 0;
            var basicDesc  = new EllipseDesc();
            var hc         = Color.White * 0.5f;
            var p          = WallPenumbra * 2;

            foreach (var pts in volumes)
            {
                //find sides closest to point
                float distM;
                if (light.LightType == LightType.OUTDOORS && ctrWidths == null)
                {
                    distM = 32f * light.FalloffMultiplier;
                }
                else
                {
                    distM = DistanceMult;
                }
                var baseIdx = vertices.Count;
                //var pts = ClockwiseLine(wall, pointLight);
                //var pts = ClosestPtsClockwise(wall, pointLight);

                //through project the points on each side with angle offsets.

                var mid = (pts[0] + pts[2]) / 2;

                Vector2 leftNorm, midNorm, rightNorm, leftFac, midFac, rightFac;
                if (light.LightType == LightType.OUTDOORS)
                {
                    leftNorm = midNorm = rightNorm = light.LightDir;
                }
                else
                {
                    leftNorm  = pts[0] - pointLight; leftNorm.Normalize();
                    midNorm   = mid - pointLight; midNorm.Normalize();
                    rightNorm = pts[2] - pointLight; rightNorm.Normalize();
                }

                leftFac = leftNorm * distM; rightFac = rightNorm * distM; midFac = midNorm * distM;

                EllipseDesc ellipse;
                if (ctrWidths != null)
                {
                    //distance * obj2height / (lightheight - obj2height)
                    var   ctW  = ctrWidths[j++];
                    var   mid2 = new Vector2(ctW.X, ctW.Y);
                    float height;
                    if (light.LightType == LightType.OUTDOORS)
                    {
                        height = 16 * light.FalloffMultiplier;
                    }
                    else
                    {
                        height = (mid2 - pointLight).Length() * 16 / ((16 * 3) - 16);
                    }
                    var midNorm2 = mid2 - pointLight; midNorm2.Normalize();
                    var largeDim = (ctW.Z + height) * midNorm2;
                    var smallDim = new Vector2(largeDim.Y, -largeDim.X);
                    smallDim.Normalize();
                    smallDim *= ctW.Z;
                    ellipse   = new EllipseDesc {
                        pos = mid2, dimensions = new Vector4(smallDim, largeDim.X, largeDim.Y)
                    };
                }
                else if (light.LightType == LightType.OUTDOORS)
                {
                    //wall linear falloff
                    var perp = (pts[2] - pts[0]);
                    var px   = perp.Y;
                    perp.Y = -perp.X;
                    perp.X = px;
                    perp.Normalize();

                    var midN2 = light.LightDir;

                    var dot = Vector2.Dot(perp, midN2);
//if (Math.Abs(dot) < 0.35) continue;
                    var length = distM * (dot);
                    var spos   = pts[0];// - ((dot>0)?perp:(-perp))*2;
                    perp   *= length;
                    ellipse = new EllipseDesc {
                        pos = spos, dimensions = new Vector4(length * length, 0, perp.X, perp.Y)
                    };
                }
                else
                {
                    ellipse = basicDesc;
                }

                //rotate the left and right norms to make the new penumbras
                var leftpen1 = pts[0] + Vector2.Transform(leftFac, mat_ccw);
                var leftpen2 = pts[0] + Vector2.Transform(leftFac, mat_cw);

                var rightpen1 = pts[2] + Vector2.Transform(rightFac, mat_ccw);
                var rightpen2 = pts[2] + Vector2.Transform(rightFac, mat_cw);


                //------ filled points ------

                //three cases. left and right penubras intersect at some point, in which case we make 2 triangles.
                //if they diverge, make 4 triangles.
                //penumbras contain each other. use one and center at half the target color.

                //y = mx + c

                var dist1 = (pts[0] - pointLight).LengthSquared();
                var dist2 = (pts[2] - pointLight).LengthSquared();
                if (dist1 > dist2)
                {
                    //is penumbra 1 inside 2?
                    if (Vector2.Dot(Vector2.Normalize(pts[0] - pts[2]), rightNorm) > PenCos)
                    {
                        //yes
                        //continue;
                        var conectr = pts[2] + rightNorm;
                        vertices.Add(GradVertex.ConeVert(pts[2], pts[2], conectr, Color.TransparentBlack, hc, p / 2, ellipse));
                        vertices.Add(GradVertex.ConeVert(rightpen1, pts[2], conectr, Color.TransparentBlack, hc, p / 2, ellipse));
                        vertices.Add(GradVertex.ConeVert(rightpen2, pts[2], conectr, Color.TransparentBlack, hc, p / 2, ellipse));
                        for (int i = 0; i < 3; i++)
                        {
                            indices.Add(baseIdx + i);
                        }
                        continue;
                    }
                }
                else
                {
                    //is penumbra 2 inside 1?
                    if (Vector2.Dot(Vector2.Normalize(pts[2] - pts[0]), leftNorm) > PenCos)
                    {
                        //yes
                        //continue;
                        var conectr = pts[0] + leftNorm;
                        vertices.Add(GradVertex.ConeVert(pts[0], pts[0], conectr, Color.TransparentBlack, hc, p, ellipse));
                        vertices.Add(GradVertex.ConeVert(leftpen1, pts[0], conectr, Color.TransparentBlack, hc, p, ellipse));
                        vertices.Add(GradVertex.ConeVert(leftpen2, pts[0], conectr, Color.TransparentBlack, hc, p, ellipse));
                        for (int i = 0; i < 3; i++)
                        {
                            indices.Add(baseIdx + i);
                        }
                        continue;
                    }
                }

                var midBack = pts[1] + midFac;
                //continue;
                var a    = leftpen2 - pts[0];
                var b    = (rightpen1 - pts[2]);
                var negX = -b.X;
                b.X = b.Y;
                b.Y = negX;
                var c = pts[2] - pts[0];
                var t = Vector2.Dot(c, b) / Vector2.Dot(a, b);

                if (t < 0)
                {
                    vertices.Add(GradVertex.SolidVert(pts[0], Color.White, ellipse));
                    vertices.Add(GradVertex.SolidVert(pts[1], Color.White, ellipse));
                    vertices.Add(GradVertex.SolidVert(pts[2], Color.White, ellipse));

                    vertices.Add(GradVertex.SolidVert(leftpen2, Color.White, ellipse));
                    vertices.Add(GradVertex.SolidVert(midBack, Color.White, ellipse));
                    vertices.Add(GradVertex.SolidVert(rightpen1, Color.White, ellipse));

                    indices.Add(baseIdx); indices.Add(baseIdx + 2); indices.Add(baseIdx + 1);     //half of rectangle
                    indices.Add(baseIdx); indices.Add(baseIdx + 3); indices.Add(baseIdx + 2);     //extension 1
                    indices.Add(baseIdx + 3); indices.Add(baseIdx + 4); indices.Add(baseIdx + 2); //extension 2
                    indices.Add(baseIdx + 4); indices.Add(baseIdx + 5); indices.Add(baseIdx + 2); //extension 3
                    baseIdx += 6;

                    //penumbras

                    vertices.Add(GradVertex.ConeVert(pts[0], pts[0], leftpen2, Color.TransparentBlack, Color.White, p, ellipse));
                    vertices.Add(GradVertex.ConeVert(leftpen1, pts[0], leftpen2, Color.TransparentBlack, Color.White, p, ellipse));
                    vertices.Add(GradVertex.ConeVert(leftpen2, pts[0], leftpen2, Color.TransparentBlack, Color.White, p, ellipse));

                    vertices.Add(GradVertex.ConeVert(pts[2], pts[2], rightpen1, Color.TransparentBlack, Color.White, p, ellipse));
                    vertices.Add(GradVertex.ConeVert(rightpen1, pts[2], rightpen1, Color.TransparentBlack, Color.White, p, ellipse));
                    vertices.Add(GradVertex.ConeVert(rightpen2, pts[2], rightpen1, Color.TransparentBlack, Color.White, p, ellipse));

                    for (int i = 0; i < 6; i++)
                    {
                        indices.Add(baseIdx + i);
                    }
                }
                else
                {
                    var inter   = pts[0] + a * t;
                    var distant = mid + Vector2.Normalize(inter - pointLight) * distM;
                    vertices.Add(GradVertex.SolidVert(pts[0], Color.White, ellipse));
                    vertices.Add(GradVertex.SolidVert(pts[0] + a * t, Color.White, ellipse));
                    vertices.Add(GradVertex.SolidVert(pts[2], Color.White, ellipse));
                    vertices.Add(GradVertex.SolidVert(pts[1], Color.White, ellipse));

                    indices.Add(baseIdx); indices.Add(baseIdx + 1); indices.Add(baseIdx + 2);
                    indices.Add(baseIdx); indices.Add(baseIdx + 2); indices.Add(baseIdx + 3); //half of rectangle

                    baseIdx += 4;

                    //penumbras: each penumbra becomes two tris as they intersect

                    vertices.Add(GradVertex.ConeVert(pts[0], pts[0], leftpen2, Color.TransparentBlack, Color.White, p, ellipse));
                    vertices.Add(GradVertex.ConeVert(leftpen1, pts[0], leftpen2, Color.TransparentBlack, Color.White, p, ellipse));
                    vertices.Add(GradVertex.ConeVert(inter, pts[0], leftpen2, Color.TransparentBlack, Color.White, p, ellipse));
                    vertices.Add(GradVertex.ConeVert(distant, pts[0], leftpen2, Color.TransparentBlack, Color.White, p, ellipse));

                    vertices.Add(GradVertex.ConeVert(pts[2], pts[2], rightpen1, Color.TransparentBlack, Color.White, p, ellipse));
                    vertices.Add(GradVertex.ConeVert(rightpen2, pts[2], rightpen1, Color.TransparentBlack, Color.White, p, ellipse));
                    vertices.Add(GradVertex.ConeVert(inter, pts[2], rightpen1, Color.TransparentBlack, Color.White, p, ellipse));
                    vertices.Add(GradVertex.ConeVert(distant, pts[2], rightpen1, Color.TransparentBlack, Color.White, p, ellipse));

                    indices.Add(baseIdx); indices.Add(baseIdx + 1); indices.Add(baseIdx + 2);
                    indices.Add(baseIdx + 1); indices.Add(baseIdx + 3); indices.Add(baseIdx + 2);

                    baseIdx += 4;
                    indices.Add(baseIdx); indices.Add(baseIdx + 1); indices.Add(baseIdx + 2);
                    indices.Add(baseIdx + 1); indices.Add(baseIdx + 3); indices.Add(baseIdx + 2);
                }
            }

            return(new Tuple <GradVertex[], int[]>(vertices.ToArray(), indices.ToArray()));
        }
Example #3
0
 public static GradVertex ConeVert(Vector2 position, Vector2 coneCtr, Vector2 coneOuter, Color color1, Color color2, float penumbra, EllipseDesc ellipse)
 {
     return(new GradVertex()
     {
         Color1 = color1,
         Color2 = color2,
         Coord = position,
         StartPosition = coneCtr,
         EndPosition = coneOuter,
         Params = new Vector4(2, penumbra, ellipse.pos.X, ellipse.pos.Y),
         EllipseDat = ellipse.dimensions
     });
 }