Example #1
0
        public Game.RadiosityMaps GenerateMemoryTextures(Game.LightmapSpecs specs)
        {
            if (IntPtr.Size != 4)
            {
                throw new InvalidOperationException("Cannot generate memory textures unless running in 32-bit mode");
            }
            if (specs.Surfaces.Count != _surfaces.Length)
            {
                throw new ArgumentException("The number of surfaces in the lightmap spec doesn't match the number of surfaces in the BSP", "specs");
            }

            const int minSize = 4;

            Game.RadiosityMaps maps = new Game.RadiosityMaps(specs);

            foreach (BspSurface surface in _surfaces)
            {
                Game.LightmapSpecs.SurfaceLightmap lm = specs.Surfaces[(int)surface.index];

                maps.Maps[surface.index].MemoryTexture = Game.Radiosity.GenerateMemoryTexture(lm.Width, lm.Height, 0, 0, 0);
            }

            return(maps);
        }
Example #2
0
        public void CalcRadiosityPass(Graphics.LightmapResource original, Game.RadiosityMaps radiosity)
        {
            const int batchSize = 256;

            Game.Radiosity.LightmapTexel[] texels = new Game.Radiosity.LightmapTexel[batchSize];

            System.Runtime.InteropServices.GCHandle[] h = new System.Runtime.InteropServices.GCHandle[_surfaces.Length];

            int count = 0;


            int currentBatchIndex = 0;

            foreach (BspSurface surface in _surfaces)
            {
                if (surface.index == 90)
                {
                    count++;
                }

                count++;
                //if (count >950)break;

                h[surface.index] = System.Runtime.InteropServices.GCHandle.Alloc(radiosity.Maps[surface.index].Map, System.Runtime.InteropServices.GCHandleType.Pinned);

                //TextureResource memTex = surface.textureResource;
                TextureResource memTex       = radiosity.Maps[surface.index].MemoryTexture;
                Rect            lightmapRect = original.PackedLightmaps.GetPackedTextureRect((int)surface.index);

                // iterate over each triangle
                for (int tri = 0; tri < surface.VertexCount / 3; tri++)
                {
                    Math.Vector2 a, b, c;

                    a.X = _lightmapcoords[(surface.VertexIndex + tri * 3 + 0) * 2 + 0];
                    a.Y = _lightmapcoords[(surface.VertexIndex + tri * 3 + 0) * 2 + 1];

                    b.X = _lightmapcoords[(surface.VertexIndex + tri * 3 + 1) * 2 + 0];
                    b.Y = _lightmapcoords[(surface.VertexIndex + tri * 3 + 1) * 2 + 1];

                    c.X = _lightmapcoords[(surface.VertexIndex + tri * 3 + 2) * 2 + 0];
                    c.Y = _lightmapcoords[(surface.VertexIndex + tri * 3 + 2) * 2 + 1];

                    Math.Vector3 pa, pb, pc;
                    pa.X = _bspVertices[surface.VertexIndex + tri * 3 + 0].X;
                    pa.Y = _bspVertices[surface.VertexIndex + tri * 3 + 0].Y;
                    pa.Z = _bspVertices[surface.VertexIndex + tri * 3 + 0].Z;

                    pb.X = _bspVertices[surface.VertexIndex + tri * 3 + 1].X;
                    pb.Y = _bspVertices[surface.VertexIndex + tri * 3 + 1].Y;
                    pb.Z = _bspVertices[surface.VertexIndex + tri * 3 + 1].Z;

                    pc.X = _bspVertices[surface.VertexIndex + tri * 3 + 2].X;
                    pc.Y = _bspVertices[surface.VertexIndex + tri * 3 + 2].Y;
                    pc.Z = _bspVertices[surface.VertexIndex + tri * 3 + 2].Z;

                    Math.Vector3 up = (pa - pb).Normalize();
                    Math.Vector3 n  = up.Cross((pa - pc).Normalize()).Normalize();

                    Math.Vector2 minUV, maxUV;
                    minUV.X = System.Math.Min(System.Math.Min(a.X, b.X), c.X);
                    minUV.Y = System.Math.Min(System.Math.Min(a.Y, b.Y), c.Y);
                    maxUV.X = System.Math.Max(System.Math.Max(a.X, b.X), c.X);
                    maxUV.Y = System.Math.Max(System.Math.Max(a.Y, b.Y), c.Y);

                    // map the triangle to the texture
                    int minTX = System.Math.Max((int)(memTex.Width * minUV.X) - 1, 0);
                    int minTY = System.Math.Max((int)(memTex.Height * minUV.Y) - 1, 0);
                    int maxTX = System.Math.Min((int)(System.Math.Ceiling(memTex.Width * maxUV.X + 1)), memTex.Width);
                    int maxTY = System.Math.Min((int)(System.Math.Ceiling(memTex.Height * maxUV.Y + 1)), memTex.Height);

                    float halfPixelU = 1.0f / memTex.Width * 0.5f;
                    float halfPixelV = 1.0f / memTex.Height * 0.5f;

                    // go through each texel and do the radiosity stuff
                    for (int y = minTY; y < maxTY; y++)
                    {
                        for (int x = minTX; x < maxTX; x++)
                        {
                            /* if (x < 0 || y < 0 ||
                             *      x >= radiosity.Maps[surface.index].Width ||
                             *      y >= radiosity.Maps[surface.index].Height)
                             *   continue;*/

                            Math.Vector2 texelUV;

                            texelUV.X = (float)x / memTex.Width + halfPixelU;
                            texelUV.Y = (float)y / memTex.Height + halfPixelV;

                            /*if (memTex.Width > 1)
                             *  texelUV.X = (float)x / memTex.Width + halfPixelU;
                             * else
                             *  texelUV.X = (float)x / memTex.Width;
                             *
                             * if (memTex.Height > 1)
                             *  texelUV.Y = (float)y / memTex.Height + halfPixelV;
                             * else
                             *  texelUV.Y = (float)y / memTex.Height;
                             */

                            // radiosity.Maps[surface.index].Map[(y * radiosity.Maps[surface.index].Width + x) * 3 + 0] = 1000.0f;
                            //radiosity.Maps[surface.index].Map[(y * radiosity.Maps[surface.index].Width + x) * 3 + 1] = 0;
                            // radiosity.Maps[surface.index].Map[(y * radiosity.Maps[surface.index].Width + x) * 3 + 2] = 0;
                            //radiosity.Maps[surface.index].SetColor(x, y, 1000.0f, 0, 0);

                            // are we on the triangle?
                            Math.Vector2 projectedUV;
                            Math.Vector2 texelMin, texelMax;
                            texelMin.X = (float)x / memTex.Width;
                            texelMin.Y = (float)y / memTex.Height;
                            texelMax.X = (float)(x + 1) / memTex.Width;
                            texelMax.Y = (float)(y + 1) / memTex.Height;
                            // if (Gk3Main.Utils.TestTriangleBox(a, b, c, texelMin, texelMax))
                            if (Gk3Main.Utils.TestTriangleBoxAndGetCenterOfMassUV(a, b, c, texelMin, texelMax, out projectedUV))
                            {
                                // Gk3Main.Utils.IsPointInTriangle(texelUV, a, b, c, out projectedUV);

                                // calc the world coordinates
                                Math.Vector3 p3 = pa + (pb - pa) * projectedUV.Y + (pc - pa) * projectedUV.X;
                                //Math.Vector3 p3(p.X, p.Y, p.Z);

                                //Math.Vector4 p4 = worldView * p3;



                                texels[currentBatchIndex].Tag = Gk3Main.Utils.IncrementIntPtr(h[surface.index].AddrOfPinnedObject(), (y * radiosity.Maps[surface.index].Width + x) * 3 * 4);

                                //texels[currentBatchIndex].Tag = (IntPtr)(h[surface.index].AddrOfPinnedObject() + (IntPtr)((y * radiosity.Maps[surface.index].Width + x) * 3 * 4);
                                texels[currentBatchIndex].PosX    = p3.X;
                                texels[currentBatchIndex].PosY    = p3.Y;
                                texels[currentBatchIndex].PosZ    = p3.Z;
                                texels[currentBatchIndex].NormalX = n.X;
                                texels[currentBatchIndex].NormalY = n.Y;
                                texels[currentBatchIndex].NormalZ = n.Z;
                                texels[currentBatchIndex].UpX     = up.X;
                                texels[currentBatchIndex].UpY     = up.Y;
                                texels[currentBatchIndex].UpZ     = up.Z;
                                texels[currentBatchIndex].Red     = 0;
                                texels[currentBatchIndex].Green   = 0;
                                texels[currentBatchIndex].Blue    = 0;

                                //rad_CalcPass(p4.getX(), p4.getY(), p4.getZ(),
                                //    n.X, n.Y, n.Z,
                                //    &results[(y * texture->GetWidth() + x) * 3 + 0],
                                //    &results[(y * texture->GetWidth() + x) * 3 + 1],
                                //    &results[(y * texture->GetWidth() + x) * 3 + 2]);

                                //results[(y * texture->GetWidth() + x) * 3 + 0] *= 0.1f;
                                //results[(y * texture->GetWidth() + x) * 3 + 1] *= 0.1f;
                                //results[(y * texture->GetWidth() + x) * 3 + 2] *= 0.1f;

                                currentBatchIndex++;

                                if (currentBatchIndex >= batchSize)
                                {
                                    Game.Radiosity.CalcPass(texels, currentBatchIndex);

                                    for (int i = 0; i < currentBatchIndex; i++)
                                    {
                                        //int index = texels[i].Tag.ToInt32() * 3;

                                        unsafe
                                        {
                                            float *f = (float *)texels[i].Tag.ToPointer();

                                            /*radiosity.Maps[surface.index].Map[index + 0] = texels[i].Red;
                                             * radiosity.Maps[surface.index].Map[index + 1] = texels[i].Green;
                                             * radiosity.Maps[surface.index].Map[index + 2] = texels[i].Blue;*/


                                            f[0] = System.Math.Max(texels[i].Red, f[0]);
                                            f[1] = System.Math.Max(texels[i].Green, f[1]);
                                            f[2] = System.Math.Max(texels[i].Blue, f[2]);
                                        }

                                        //texels[i].r
                                    }

                                    currentBatchIndex = 0;
                                }
                            }
                            else
                            {
                                currentBatchIndex = currentBatchIndex;
                            }
                        }
                    }
                }
            }

            if (currentBatchIndex > 0)
            {
                Game.Radiosity.CalcPass(texels, currentBatchIndex);

                for (int i = 0; i < currentBatchIndex; i++)
                {
                    unsafe
                    {
                        float *f = (float *)texels[i].Tag.ToPointer();

                        /*radiosity.Maps[surface.index].Map[index + 0] = texels[i].Red;
                         * radiosity.Maps[surface.index].Map[index + 1] = texels[i].Green;
                         * radiosity.Maps[surface.index].Map[index + 2] = texels[i].Blue;*/

                        f[0] = System.Math.Max(texels[i].Red, f[0]);
                        f[1] = System.Math.Max(texels[i].Green, f[1]);
                        f[2] = System.Math.Max(texels[i].Blue, f[2]);
                    }

                    /*int index = texels[i].Tag.ToInt32() * 3;
                     * radiosity.Maps[surface.index].Map[index + 0] = texels[i].Red;
                     * radiosity.Maps[surface.index].Map[index + 1] = texels[i].Green;
                     * radiosity.Maps[surface.index].Map[index + 2] = texels[i].Blue;
                     *
                     */
                    //texels[i].r
                }
            }
        }