private static void addSunToSurface(Math.Vector3 direction, Math.Vector3 color, float radius, Math.Vector3 faceNormal, Math.Vector3 faceUp, BitmapSurface faceSurface, bool memory) { Math.Vector3 faceRight = faceNormal.Cross(faceUp); float t = -0.5f / faceNormal.Dot(-direction); if (t > 0) { return; // the sun never hits this plane } Math.Vector3 sunP = -direction * t; for (int y = 0; y < faceSurface.Height; y++) { for (int x = 0; x < faceSurface.Width; x++) { // calc the distance from this pixel to the sun float u = (float)x / faceSurface.Width - 0.5f; float v = (float)y / faceSurface.Height - 0.5f; Math.Vector3 texelP = faceUp * v + faceRight * u + -faceNormal * 0.5f; float distance = Math.Vector3.Distance(texelP, sunP); if (distance < radius) { if (!memory) { faceSurface.Pixels[(y * faceSurface.Width + x) * 4 + 0] = 255; faceSurface.Pixels[(y * faceSurface.Width + x) * 4 + 1] = 0; faceSurface.Pixels[(y * faceSurface.Width + x) * 4 + 2] = 0; } else { Color c = faceSurface.ReadColorAt(x, y); uint ptr = (uint)c.R | ((uint)c.G << 8) | ((uint)c.B << 16) | ((uint)c.A << 24); UIntPtr ptr2 = (UIntPtr)ptr; unsafe { float *f = (float *)ptr2.ToPointer(); f[0] = color.X; f[1] = color.Y; f[2] = color.Z; } } } } } }
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 } } }