Example #1
0
        public static void FindFacesAndGroups(Map map, out List <LMFace> faces, out List <LightmapGroup> lmGroups)
        {
            faces    = new List <LMFace>();
            lmGroups = new List <LightmapGroup>();
            foreach (Solid solid in map.WorldSpawn.Find(x => x is Solid).OfType <Solid>())
            {
                foreach (Face tface in solid.Faces)
                {
                    tface.Vertices.ForEach(v => { v.LMU = -500.0f; v.LMV = -500.0f; });
                    tface.UpdateBoundingBox();
                    if (tface.Texture?.Texture == null)
                    {
                        continue;
                    }
                    if (tface.Texture.Name.ToLowerInvariant() == "tooltextures/invisible_collision")
                    {
                        continue;
                    }
                    if (tface.Texture.Name.ToLowerInvariant() == "tooltextures/remove_face")
                    {
                        continue;
                    }
                    if (tface.Texture.Name.ToLowerInvariant() == "tooltextures/block_light")
                    {
                        continue;
                    }
                    if (tface.Texture.Texture.HasTransparency())
                    {
                        continue;
                    }
                    LMFace        face    = new LMFace(tface, solid);
                    LightmapGroup group   = LightmapGroup.FindCoplanar(lmGroups, face);
                    BoxF          faceBox = new BoxF(face.BoundingBox.Start - new CoordinateF(3.0f, 3.0f, 3.0f), face.BoundingBox.End + new CoordinateF(3.0f, 3.0f, 3.0f));
                    if (group == null)
                    {
                        group             = new LightmapGroup();
                        group.BoundingBox = faceBox;
                        group.Faces       = new List <LMFace>();
                        group.Plane       = new PlaneF(face.Plane.Normal, face.Vertices[0].Location);
                        lmGroups.Add(group);
                    }
#if DEBUG
                    if (face.Texture.ToLowerInvariant() == "tooltextures/debug_breakpoint")
                    {
                        group.DebugBreakpoint = true;
                    }
#endif
                    group.Faces.Add(face);
                    group.Plane       = new PlaneF(group.Plane.Normal, (face.Vertices[0].Location + group.Plane.PointOnPlane) / 2);
                    group.BoundingBox = new BoxF(new BoxF[] { group.BoundingBox, faceBox });
                }
            }
        }
Example #2
0
 public static void FindFacesAndGroups(Map map, out List <LMFace> faces, out List <LightmapGroup> lmGroups)
 {
     faces    = new List <LMFace>();
     lmGroups = new List <LightmapGroup>();
     foreach (Solid solid in map.WorldSpawn.Find(x => x is Solid).OfType <Solid>())
     {
         foreach (Face tface in solid.Faces)
         {
             tface.Vertices.ForEach(v => { v.LMU = -500.0f; v.LMV = -500.0f; });
             tface.UpdateBoundingBox();
             if (tface.Texture?.Texture == null)
             {
                 continue;
             }
             if (tface.Texture.IsToolTexture)
             {
                 continue;
             }
             if (tface.Texture.Texture.HasTransparency())
             {
                 continue;
             }
             LMFace        face    = new LMFace(tface, solid);
             LightmapGroup group   = LightmapGroup.FindCoplanar(lmGroups, face);
             BoxF          faceBox = new BoxF(face.BoundingBox.Start - new CoordinateF(3.0f, 3.0f, 3.0f), face.BoundingBox.End + new CoordinateF(3.0f, 3.0f, 3.0f));
             if (group == null)
             {
                 group             = new LightmapGroup();
                 group.BoundingBox = faceBox;
                 group.Faces       = new List <LMFace>();
                 group.Plane       = new PlaneF(face.Plane.Normal, face.Vertices[0].Location);
                 lmGroups.Add(group);
             }
             group.Faces.Add(face);
             group.Plane       = new PlaneF(group.Plane.Normal, (face.Vertices[0].Location + group.Plane.PointOnPlane) / 2);
             group.BoundingBox = new BoxF(new BoxF[] { group.BoundingBox, faceBox });
         }
     }
 }
Example #3
0
        private static void CalculateUV(List <LightmapGroup> lmGroups, Rectangle area, out int usedWidth, out int usedHeight)
        {
            usedWidth  = 0;
            usedHeight = 0;
            if (lmGroups.Count <= 0)
            {
                return;
            }

            for (int i = 0; i < lmGroups.Count; i++)
            {
                LightmapGroup lmGroup = lmGroups[i];

                if ((area.Width <= area.Height) != (lmGroup.Width <= lmGroup.Height))
                {
                    lmGroup.SwapUV();
                }

                for (int j = 0; j < 2; j++)
                {
                    int downscaledWidth  = (int)Math.Ceiling(lmGroup.Width / LightmapConfig.DownscaleFactor);
                    int downscaledHeight = (int)Math.Ceiling(lmGroup.Height / LightmapConfig.DownscaleFactor);

                    if (downscaledWidth <= area.Width && downscaledHeight <= area.Height)
                    {
                        usedWidth  += downscaledWidth;
                        usedHeight += downscaledHeight;
                        lmGroups.RemoveAt(i);
                        lmGroup.writeX = area.Left;
                        lmGroup.writeY = area.Top;

                        int subWidth = -1; int subHeight = -1;
                        if (downscaledWidth < area.Width)
                        {
                            int subUsedWidth = 0;
                            while (subWidth != 0)
                            {
                                CalculateUV(lmGroups, new Rectangle(area.Left + subUsedWidth + downscaledWidth + LightmapConfig.PlaneMargin,
                                                                    area.Top,
                                                                    area.Width - subUsedWidth - downscaledWidth - LightmapConfig.PlaneMargin,
                                                                    downscaledHeight),
                                            out subWidth, out subHeight);
                                subUsedWidth += subWidth + LightmapConfig.PlaneMargin;
                            }

                            usedWidth += subUsedWidth;
                            subWidth   = -1; subHeight = -1;
                        }

                        if (downscaledHeight < area.Height)
                        {
                            int subUsedHeight = 0;
                            while (subHeight != 0)
                            {
                                CalculateUV(lmGroups, new Rectangle(area.Left,
                                                                    area.Top + subUsedHeight + downscaledHeight + LightmapConfig.PlaneMargin,
                                                                    downscaledWidth,
                                                                    area.Height - subUsedHeight - downscaledHeight - LightmapConfig.PlaneMargin),
                                            out subWidth, out subHeight);
                                subUsedHeight += subHeight + LightmapConfig.PlaneMargin;
                            }

                            usedHeight += subUsedHeight;
                        }

                        if (downscaledWidth < area.Width && downscaledHeight < area.Height)
                        {
                            Rectangle remainder = new Rectangle(area.Left + downscaledWidth + LightmapConfig.PlaneMargin,
                                                                area.Top + downscaledHeight + LightmapConfig.PlaneMargin,
                                                                area.Width - downscaledWidth - LightmapConfig.PlaneMargin,
                                                                area.Height - downscaledHeight - LightmapConfig.PlaneMargin);

                            CalculateUV(lmGroups, remainder,
                                        out subWidth, out subHeight);

                            usedWidth  += subWidth;
                            usedHeight += subHeight;
                        }

                        return;
                    }

                    lmGroup.SwapUV();
                }
            }
        }
Example #4
0
        private static void RenderLightOntoFace(Document doc, float[][] bitmaps, List <Light> lights, LightmapGroup group, LMFace targetFace, IEnumerable <LMFace> blockerFaces)
        {
            Random rand = new Random();

            int writeX = group.writeX;
            int writeY = group.writeY;

            int textureDims;

            lock (doc.TextureCollection.Lightmaps)
            {
                textureDims = doc.TextureCollection.Lightmaps[0].Width;
            }

            lights = lights.FindAll(x =>
            {
                float range   = x.Range;
                BoxF lightBox = new BoxF(x.Origin - new CoordinateF(range, range, range), x.Origin + new CoordinateF(range, range, range));
                return(lightBox.IntersectsWith(targetFace.BoundingBox));
            });

            float?minX = null; float?maxX = null;
            float?minY = null; float?maxY = null;

            foreach (CoordinateF coord in targetFace.Vertices.Select(x => x.Location))
            {
                float x = coord.Dot(group.uAxis);
                float y = coord.Dot(group.vAxis);

                if (minX == null || x < minX)
                {
                    minX = x;
                }
                if (minY == null || y < minY)
                {
                    minY = y;
                }
                if (maxX == null || x > maxX)
                {
                    maxX = x;
                }
                if (maxY == null || y > maxY)
                {
                    maxY = y;
                }
            }

            CoordinateF leewayPoint = group.Plane.PointOnPlane + (group.Plane.Normal * Math.Max(LightmapConfig.DownscaleFactor * 0.25f, 1.5f));

            minX -= LightmapConfig.DownscaleFactor; minY -= LightmapConfig.DownscaleFactor;
            maxX += LightmapConfig.DownscaleFactor; maxY += LightmapConfig.DownscaleFactor;

            minX /= LightmapConfig.DownscaleFactor; minX = (float)Math.Ceiling(minX.Value); minX *= LightmapConfig.DownscaleFactor;
            minY /= LightmapConfig.DownscaleFactor; minY = (float)Math.Ceiling(minY.Value); minY *= LightmapConfig.DownscaleFactor;
            maxX /= LightmapConfig.DownscaleFactor; maxX = (float)Math.Ceiling(maxX.Value); maxX *= LightmapConfig.DownscaleFactor;
            maxY /= LightmapConfig.DownscaleFactor; maxY = (float)Math.Ceiling(maxY.Value); maxY *= LightmapConfig.DownscaleFactor;

            foreach (LMFace.Vertex vert in targetFace.Vertices)
            {
                float x = vert.Location.Dot(group.uAxis);
                float y = vert.Location.Dot(group.vAxis);

                float u = (writeX + 0.5f + (x - group.minTotalX.Value) / LightmapConfig.DownscaleFactor);
                float v = (writeY + 0.5f + (y - group.minTotalY.Value) / LightmapConfig.DownscaleFactor);

                targetFace.LmIndex = (u >= LightmapConfig.TextureDims ? 1 : 0) + (v >= LightmapConfig.TextureDims ? 2 : 0);

                u /= (float)textureDims;
                v /= (float)textureDims;

                vert.LMU = u; vert.LMV = v;
                vert.OriginalVertex.LMU = u; vert.OriginalVertex.LMV = v;
            }

            float centerX           = (maxX.Value + minX.Value) / 2;
            float centerY           = (maxY.Value + minY.Value) / 2;

            int iterX = (int)Math.Ceiling((maxX.Value - minX.Value) / LightmapConfig.DownscaleFactor);
            int iterY = (int)Math.Ceiling((maxY.Value - minY.Value) / LightmapConfig.DownscaleFactor);

            float[][,] r = new float[4][, ];
            r[0]         = new float[iterX, iterY];
            r[1]         = new float[iterX, iterY];
            r[2]         = new float[iterX, iterY];
            r[3]         = new float[iterX, iterY];
            float[][,] g = new float[4][, ];
            g[0]         = new float[iterX, iterY];
            g[1]         = new float[iterX, iterY];
            g[2]         = new float[iterX, iterY];
            g[3]         = new float[iterX, iterY];
            float[][,] b = new float[4][, ];
            b[0]         = new float[iterX, iterY];
            b[1]         = new float[iterX, iterY];
            b[2]         = new float[iterX, iterY];
            b[3]         = new float[iterX, iterY];

            foreach (Light light in lights)
            {
                CoordinateF lightPos   = light.Origin;
                float       lightRange = light.Range;
                CoordinateF lightColor = light.Color * (1.0f / 255.0f) * light.Intensity;

                BoxF          lightBox = new BoxF(new BoxF[] { targetFace.BoundingBox, new BoxF(light.Origin - new CoordinateF(30.0f, 30.0f, 30.0f), light.Origin + new CoordinateF(30.0f, 30.0f, 30.0f)) });
                List <LMFace> applicableBlockerFaces = blockerFaces.Where(x =>
                {
                    if (x == targetFace)
                    {
                        return(false);
                    }
                    if (group.Faces.Contains(x))
                    {
                        return(false);
                    }
                    //return true;
                    if (lightBox.IntersectsWith(x.BoundingBox))
                    {
                        return(true);
                    }
                    return(false);
                }).ToList();

                bool[,] illuminated = new bool[iterX, iterY];

                for (int y = 0; y < iterY; y++)
                {
                    for (int x = 0; x < iterX; x++)
                    {
                        illuminated[x, y] = true;
                    }
                }

                for (int y = 0; y < iterY; y++)
                {
                    for (int x = 0; x < iterX; x++)
                    {
                        int tX = (int)(writeX + x + (int)(minX - group.minTotalX) / LightmapConfig.DownscaleFactor);
                        int tY = (int)(writeY + y + (int)(minY - group.minTotalY) / LightmapConfig.DownscaleFactor);

                        if (tX >= 0 && tY >= 0 && tX < textureDims && tY < textureDims)
                        {
                            int offset = (tX + tY * textureDims) * Bitmap.GetPixelFormatSize(System.Drawing.Imaging.PixelFormat.Format32bppArgb) / 8;
                            bitmaps[0][offset + 3] = 1.0f;
                            bitmaps[1][offset + 3] = 1.0f;
                            bitmaps[2][offset + 3] = 1.0f;
                            bitmaps[3][offset + 3] = 1.0f;
                        }
                    }
                }

                for (int y = 0; y < iterY; y++)
                {
                    for (int x = 0; x < iterX; x++)
                    {
                        float       ttX          = minX.Value + (x * LightmapConfig.DownscaleFactor);
                        float       ttY          = minY.Value + (y * LightmapConfig.DownscaleFactor);
                        CoordinateF pointOnPlane = (ttX - centerX) * group.uAxis + (ttY - centerY) * group.vAxis + targetFace.BoundingBox.Center;

                        /*Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                         * entity.Colour = Color.Pink;
                         * entity.Origin = new Coordinate(pointOnPlane);
                         * entity.UpdateBoundingBox();
                         * entity.SetParent(map.WorldSpawn);*/

                        int tX = (int)(writeX + x + (int)(minX - group.minTotalX) / LightmapConfig.DownscaleFactor);
                        int tY = (int)(writeY + y + (int)(minY - group.minTotalY) / LightmapConfig.DownscaleFactor);

                        CoordinateF luxelColor0    = new CoordinateF(r[0][x, y], g[0][x, y], b[0][x, y]);
                        CoordinateF luxelColor1    = new CoordinateF(r[1][x, y], g[1][x, y], b[1][x, y]);
                        CoordinateF luxelColor2    = new CoordinateF(r[2][x, y], g[2][x, y], b[2][x, y]);
                        CoordinateF luxelColorNorm = new CoordinateF(r[3][x, y], g[3][x, y], b[3][x, y]);

                        float dotToLight0    = Math.Max((lightPos - pointOnPlane).Normalise().Dot(targetFace.LightBasis0), 0.0f);
                        float dotToLight1    = Math.Max((lightPos - pointOnPlane).Normalise().Dot(targetFace.LightBasis1), 0.0f);
                        float dotToLight2    = Math.Max((lightPos - pointOnPlane).Normalise().Dot(targetFace.LightBasis2), 0.0f);
                        float dotToLightNorm = Math.Max((lightPos - pointOnPlane).Normalise().Dot(targetFace.Normal), 0.0f);

                        if (illuminated[x, y] && (pointOnPlane - lightPos).LengthSquared() < lightRange * lightRange)
                        {
#if TRUE
                            LineF lineTester = new LineF(lightPos, pointOnPlane);
                            for (int i = 0; i < applicableBlockerFaces.Count; i++)
                            {
                                LMFace      otherFace = applicableBlockerFaces[i];
                                CoordinateF hit       = otherFace.GetIntersectionPoint(lineTester);
                                if (hit != null && ((hit - leewayPoint).Dot(group.Plane.Normal) > 0.0f || (hit - pointOnPlane).LengthSquared() > LightmapConfig.DownscaleFactor * 2f))
                                {
                                    applicableBlockerFaces.RemoveAt(i);
                                    applicableBlockerFaces.Insert(0, otherFace);
                                    illuminated[x, y] = false;
                                    i++;
                                    break;
                                }
                            }
#endif
                        }
                        else
                        {
                            illuminated[x, y] = false;
                        }

                        if (illuminated[x, y])
                        {
                            float brightness = (lightRange - (pointOnPlane - lightPos).VectorMagnitude()) / lightRange;

                            if (light.Direction != null)
                            {
                                float directionDot = light.Direction.Dot((pointOnPlane - lightPos).Normalise());

                                if (directionDot < light.innerCos)
                                {
                                    if (directionDot < light.outerCos)
                                    {
                                        brightness = 0.0f;
                                    }
                                    else
                                    {
                                        brightness *= (directionDot - light.outerCos.Value) / (light.innerCos.Value - light.outerCos.Value);
                                    }
                                }
                            }

                            float brightness0    = dotToLight0 * brightness * brightness;
                            float brightness1    = dotToLight1 * brightness * brightness;
                            float brightness2    = dotToLight2 * brightness * brightness;
                            float brightnessNorm = dotToLightNorm * brightness * brightness;

                            brightness0    += ((float)rand.NextDouble() - 0.5f) * 0.005f;
                            brightness1    += ((float)rand.NextDouble() - 0.5f) * 0.005f;
                            brightness2    += ((float)rand.NextDouble() - 0.5f) * 0.005f;
                            brightnessNorm += ((float)rand.NextDouble() - 0.5f) * 0.005f;

                            r[0][x, y] += lightColor.Z * brightness0; if (r[0][x, y] > 1.0f)
                            {
                                r[0][x, y] = 1.0f;
                            }
                            if (r[0][x, y] < 0)
                            {
                                r[0][x, y] = 0;
                            }
                            g[0][x, y] += lightColor.Y * brightness0; if (g[0][x, y] > 1.0f)
                            {
                                g[0][x, y] = 1.0f;
                            }
                            if (g[0][x, y] < 0)
                            {
                                g[0][x, y] = 0;
                            }
                            b[0][x, y] += lightColor.X * brightness0; if (b[0][x, y] > 1.0f)
                            {
                                b[0][x, y] = 1.0f;
                            }
                            if (b[0][x, y] < 0)
                            {
                                b[0][x, y] = 0;
                            }

                            r[1][x, y] += lightColor.Z * brightness1; if (r[1][x, y] > 1.0f)
                            {
                                r[1][x, y] = 1.0f;
                            }
                            if (r[1][x, y] < 0)
                            {
                                r[1][x, y] = 0;
                            }
                            g[1][x, y] += lightColor.Y * brightness1; if (g[1][x, y] > 1.0f)
                            {
                                g[1][x, y] = 1.0f;
                            }
                            if (g[1][x, y] < 0)
                            {
                                g[1][x, y] = 0;
                            }
                            b[1][x, y] += lightColor.X * brightness1; if (b[1][x, y] > 1.0f)
                            {
                                b[1][x, y] = 1.0f;
                            }
                            if (b[1][x, y] < 0)
                            {
                                b[1][x, y] = 0;
                            }

                            r[2][x, y] += lightColor.Z * brightness2; if (r[2][x, y] > 1.0f)
                            {
                                r[2][x, y] = 1.0f;
                            }
                            if (r[2][x, y] < 0)
                            {
                                r[2][x, y] = 0;
                            }
                            g[2][x, y] += lightColor.Y * brightness2; if (g[2][x, y] > 1.0f)
                            {
                                g[2][x, y] = 1.0f;
                            }
                            if (g[2][x, y] < 0)
                            {
                                g[2][x, y] = 0;
                            }
                            b[2][x, y] += lightColor.X * brightness2; if (b[2][x, y] > 1.0f)
                            {
                                b[2][x, y] = 1.0f;
                            }
                            if (b[2][x, y] < 0)
                            {
                                b[2][x, y] = 0;
                            }

                            r[3][x, y] += lightColor.Z * brightnessNorm; if (r[3][x, y] > 1.0f)
                            {
                                r[3][x, y] = 1.0f;
                            }
                            if (r[3][x, y] < 0)
                            {
                                r[3][x, y] = 0;
                            }
                            g[3][x, y] += lightColor.Y * brightnessNorm; if (g[3][x, y] > 1.0f)
                            {
                                g[3][x, y] = 1.0f;
                            }
                            if (g[3][x, y] < 0)
                            {
                                g[3][x, y] = 0;
                            }
                            b[3][x, y] += lightColor.X * brightnessNorm; if (b[3][x, y] > 1.0f)
                            {
                                b[3][x, y] = 1.0f;
                            }
                            if (b[3][x, y] < 0)
                            {
                                b[3][x, y] = 0;
                            }

                            luxelColor0    = new CoordinateF(r[0][x, y], g[0][x, y], b[0][x, y]);
                            luxelColor1    = new CoordinateF(r[1][x, y], g[1][x, y], b[1][x, y]);
                            luxelColor2    = new CoordinateF(r[2][x, y], g[2][x, y], b[2][x, y]);
                            luxelColorNorm = new CoordinateF(r[3][x, y], g[3][x, y], b[3][x, y]);

                            if (tX >= 0 && tY >= 0 && tX < textureDims && tY < textureDims)
                            {
                                int offset = (tX + tY * textureDims) * Bitmap.GetPixelFormatSize(System.Drawing.Imaging.PixelFormat.Format32bppArgb) / 8;
                                if (luxelColor0.X + luxelColor0.Y + luxelColor0.Z > bitmaps[0][offset + 2] + bitmaps[0][offset + 1] + bitmaps[0][offset + 0])
                                {
                                    bitmaps[0][offset + 0] = luxelColor0.X;
                                    bitmaps[0][offset + 1] = luxelColor0.Y;
                                    bitmaps[0][offset + 2] = luxelColor0.Z;
                                }
                                if (luxelColor1.X + luxelColor1.Y + luxelColor1.Z > bitmaps[1][offset + 2] + bitmaps[1][offset + 1] + bitmaps[1][offset + 0])
                                {
                                    bitmaps[1][offset + 0] = luxelColor1.X;
                                    bitmaps[1][offset + 1] = luxelColor1.Y;
                                    bitmaps[1][offset + 2] = luxelColor1.Z;
                                }
                                if (luxelColor2.X + luxelColor2.Y + luxelColor2.Z > bitmaps[2][offset + 2] + bitmaps[2][offset + 1] + bitmaps[2][offset + 0])
                                {
                                    bitmaps[2][offset + 0] = luxelColor2.X;
                                    bitmaps[2][offset + 1] = luxelColor2.Y;
                                    bitmaps[2][offset + 2] = luxelColor2.Z;
                                }
                                if (luxelColorNorm.X + luxelColorNorm.Y + luxelColorNorm.Z > bitmaps[3][offset + 2] + bitmaps[3][offset + 1] + bitmaps[3][offset + 0])
                                {
                                    bitmaps[3][offset + 0] = luxelColorNorm.X;
                                    bitmaps[3][offset + 1] = luxelColorNorm.Y;
                                    bitmaps[3][offset + 2] = luxelColorNorm.Z;
                                }
                            }
                        }
                    }
                }
            }
        }
Example #5
0
 private static Thread CreateLightmapRenderThread(Document doc, float[][] bitmaps, List <Light> lights, LightmapGroup group, LMFace targetFace, IEnumerable <LMFace> blockerFaces)
 {
     return(new Thread(() => {
         try
         {
             RenderLightOntoFace(doc, bitmaps, lights, group, targetFace, blockerFaces);
         }
         catch (ThreadAbortException)
         {
             //do nothing
         }
         catch (Exception e)
         {
             threadExceptions.Add(new LMThreadException(e));
         }
     }));
 }