public void LoadRawData(ref BinaryReader br, byte[] buffer)
        {
            int triangle_count = ((((IndexCount / 3) + 1) * 6) / 2) / 3;

            m_Mesh = new EnhancedMesh(IndexCount);

            //load verts
            m_Mesh.AllocateVertexBuffer(MeshFormat.Model, (int)VertexCount);
            for (int v = 0; v < VertexCount; v++)
            {
                m_Mesh.LoadH1ModelVertexData(v, ref br, buffer, UScale, VScale, MapfileVersion.XHALO1);
            }
            m_Mesh.UpdateDxBuffer();

            //load indices
            m_Mesh.AllocateAndLoadH1XboxIndexBuffer(PrimitiveType.TriangleStrip, IndexCount, ref br, true);
            //m_Mesh.AllocateAndLoadIndexBuffer(PrimitiveType.TriangleStrip, IndexCount+1, ref br, true);
        }
        public void LoadRawData(ref BinaryReader br, byte[] buffer)
        {
            m_Mesh = new EnhancedMesh(TriangleCount);

            //Trace.WriteLine(string.Format("vertex_position = {0:X}", br.BaseStream.Position + 0x40));

            //load verts
            m_Mesh.AllocateVertexBuffer(MeshFormat.Model, (int)VertexCount);
            for (int v = 0; v < VertexCount; v++)
            {
                //version arg only cares if it is xbox, other versions use default (uncompressed) behavior
                m_Mesh.LoadH1ModelVertexData(v, ref br, buffer, UScale, VScale, MapfileVersion.HALOPC);
            }
            m_Mesh.UpdateDxBuffer();

            //Trace.WriteLine(string.Format("index_position = {0:X}", br.BaseStream.Position + 0x40));

            //load indices
            int index_count = (TriangleCount / 3 + 1) * 6;

            m_Mesh.AllocateAndLoadIndexBuffer(PrimitiveType.TriangleStrip, TriangleCount + 1, ref br, true);
        }
        public static UVConversionMap CacheUVConversionData(EnhancedMesh[] meshes, int width, int height)
        {
            if (meshes == null)
            {
                throw new InvalidOperationException("Cannot cache UV conversion data when there are no meshes loaded.");
            }
            if ((width <= 0) || (height <= 0))
            {
                throw new ArgumentOutOfRangeException("The size of the UV conversion cache was below zero.");
            }

            Vector2 pixelSize = new Vector2(1f / (float)width, 1f / (float)height);
            float   widthF = (float)width, heightF = (float)height;

            UVConversionMap map = new UVConversionMap(width, height);

            // iterate through the meshes
            for (int materialIndex = 0; materialIndex < meshes.Length; materialIndex++)
            {
                EnhancedMesh mesh = meshes[materialIndex];

                // iterate through the faces
                int faceCount = mesh.Indices.Length / 3;
                for (int f = 0; f < faceCount; f++)
                {
                    RadiosityHelper.UVConversionCacheItem it = new RadiosityHelper.UVConversionCacheItem(materialIndex, f);
                    Vertex[] verts = { mesh.Vertices[mesh.Indices[f * 3]], mesh.Vertices[mesh.Indices[f * 3 + 1]], mesh.Vertices[mesh.Indices[f * 3 + 2]] };
                    Vector2  a = new Vector2(verts[0].u2, verts[0].v2), b = new Vector2(verts[1].u2, verts[1].v2), c = new Vector2(verts[2].u2, verts[2].v2);

                    #region Step 1: Create pixel bounding box.
                    // Step 1: Get a basic idea of nearby pixels to test against the face by
                    // creating a rectangle
                    int left = int.MaxValue, right = int.MinValue, top = int.MaxValue, bottom = int.MinValue;
                    for (int x = 0; x < verts.Length; x++)
                    {
                        float tempF = verts[x].u2 * widthF;
                        int   temp  = (int)Math.Floor(tempF);
                        if (temp < left)
                        {
                            left = temp;
                        }
                        temp = (int)Math.Ceiling(tempF);
                        if (temp > right)
                        {
                            right = temp;
                        }
                        tempF = verts[x].v2 * heightF;
                        temp  = (int)Math.Floor(tempF);
                        if (temp < top)
                        {
                            top = temp;
                        }
                        temp = (int)Math.Ceiling(tempF);
                        if (temp > bottom)
                        {
                            bottom = temp;
                        }
                    }
                    #endregion

                    #region Step 2: Test all pixels against the current face.
                    for (int x = left; x <= right; x++)
                    {
                        for (int y = top; y <= bottom; y++)
                        {
                            if (map[x, y].Items.Contains(it))
                            {
                                continue; // these x,y coordinates are already on the table-- no need to recheck.
                            }
                            if ((left == right) && (left == x))
                            {
                                if ((bottom == top) && (top == y))
                                {
                                    map[x, y].Items.Add(it);
                                }
                            }

                            Vector2 pointUV = new Vector2((float)x / widthF, (float)y / heightF);
                            if (PointInTriangle(pointUV, a, b, c) == Vector2.Empty) // if this point is not inside the triangle
                            {
                                #region  Test to see if this face's vertices are the closest ones to the point
                                float dist = float.MaxValue;
                                dist = (pointUV - a).LengthSq();
                                map[x, y].TryAdd(it, dist);

                                dist = (pointUV - b).LengthSq();
                                map[x, y].TryAdd(it, dist);

                                dist = (pointUV - c).LengthSq();
                                map[x, y].TryAdd(it, dist);

                                #endregion
                                continue;
                                #region Unused
                                // This point's 100% UV is not on this triangle. Check for partial collision by
                                //  1) creating a bounding box for the current pixel
                                //  2) colliding every line in the box with the three lines of the triangle.
                                Vector2 pointUV10 = new Vector2(pointUV.X + pixelSize.X, pointUV.Y); // top right
                                Vector2 pointUV01 = new Vector2(pointUV.X, pointUV.Y + pixelSize.Y); // bottom left
                                Vector2 pointUV11 = new Vector2(pointUV10.X, pointUV01.Y);           // bottom right

                                float     ua, ub; int A, B;
                                Vector2[] linesA = new Vector2[] {
                                    pointUV, pointUV10,   // top
                                    pointUV10, pointUV11, // right
                                    pointUV11, pointUV01, // bottom
                                    pointUV01, pointUV
                                };
                                Vector2[] linesB = new Vector2[] {
                                    a, b,
                                    b, c,
                                    c, a
                                };
                                bool collided = LineIntersection(linesA, /* left */ linesB, out ua, out ub, out A, out B);

                                if (collided)
                                {
                                    float collX = linesA[A * 2].X + (ua * (linesA[A * 2 + 1].X - linesA[A * 2].X));
                                    float collY = linesA[A * 2].Y + (ua * (linesA[A * 2 + 1].Y - linesA[A * 2].Y));
                                    RadiosityHelper.UVConversionCacheItem newIT = new RadiosityHelper.UVConversionCacheItem(materialIndex, f, false, new Vector2(collX, collY));

                                    // Anything inside the bounding box will affect the current pixel, the pixel to the right, and the pixel below.
                                    map[x, y].Items.Add(newIT);
                                    if (x + 1 < width)
                                    {
                                        map[x + 1, y].Items.Add(newIT);
                                    }
                                    if (y + 1 < height)
                                    {
                                        map[x, y + 1].Items.Add(newIT);
                                    }
                                    if ((x + 1 < width) && (y + 1 < height))
                                    {
                                        map[x + 1, y + 1].Items.Add(newIT);
                                    }
                                }

                                continue;
                                #endregion
                            }
                            else
                            {
                                map[x, y].Items.Add(it); // The point is on this face, so add this face to the map
                            }
                        }
                    }
                    #endregion
                }
            }
            return(map);
        }
Exemple #4
0
        public float SurfaceArea(scenario_structure_bsp bsp, scenario_structure_bsp.StructureBspMaterialBlock material, int f, EnhancedMesh mesh)
        {
            float area = 0f;
            int   end  = f + material.SurfaceCount;

            for (int x = f; x < end; x++)
            {
                Vector3 v1 = mesh.Vertices[bsp.ScenarioStructureBspValues.Surfaces[x].Tria].position;
                Vector3 v2 = mesh.Vertices[bsp.ScenarioStructureBspValues.Surfaces[x].Trib].position;
                Vector3 v3 = mesh.Vertices[bsp.ScenarioStructureBspValues.Surfaces[x].Tric].position;

                area += ComputeTriangleArea((v2 - v1).Length(), (v3 - v2).Length(), (v1 - v3).Length());
            }
            return(area);
        }
Exemple #5
0
        public float SurfaceArea(scenario_structure_bsp.StructureBspSurfaceBlock surface, EnhancedMesh mesh)
        {
            Vector3 v1 = mesh.Vertices[surface.Tria].position;
            Vector3 v2 = mesh.Vertices[surface.Trib].position;
            Vector3 v3 = mesh.Vertices[surface.Tric].position;

            return(ComputeTriangleArea((v2 - v1).Length(), (v3 - v2).Length(), (v1 - v3).Length()));
        }
Exemple #6
0
        public override void DoPostProcess()
        {
            base.DoPostProcess();

            shaders = new shader[gbxmodelValues.Shaders.Count];
            for (int i = 0; i < shaders.Length; i++)
            {
                shaders[i] = OpenShader(gbxmodelValues.Shaders[i].Shader.Value, gbxmodelValues.Shaders[i].Shader.TagGroup);
            }

            meshes = new EnhancedMesh[gbxmodelValues.Geometries.Count][];
            for (int i = 0; i < meshes.Length; i++)
            {
                meshes[i] = new EnhancedMesh[gbxmodelValues.Geometries[i].Parts.Count];
                for (int j = 0; j < meshes[i].Length; j++)
                {
                    ushort[] strip    = new ushort[gbxmodelValues.Geometries[i].Parts[j].Triangles.Count * 3];
                    Vertex[] vertices = new Vertex[gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices.Count];

                    for (int k = 0; k < vertices.Length; k++)
                    {
                        vertices[k].position.X = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Position.X;
                        vertices[k].position.Y = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Position.Y;
                        vertices[k].position.Z = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Position.Z;
                        vertices[k].normal.X   = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Normal.I;
                        vertices[k].normal.Y   = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Normal.J;
                        vertices[k].normal.Z   = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Normal.K;
                        vertices[k].u1         = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].TextureCoords.X * ((gbxmodelValues.BaseMap.Value == 0.0f) ? 1.0f : gbxmodelValues.BaseMap.Value);
                        vertices[k].v1         = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].TextureCoords.Y * ((gbxmodelValues.BaseMap2.Value == 0.0f) ? 1.0f : gbxmodelValues.BaseMap2.Value);
                        vertices[k].u2         = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Node0Weight.Value;
                        vertices[k].v2         = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Node1Weight.Value;
                        vertices[k].nodeIndex1 = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Node0Index.Value;
                        vertices[k].nodeIndex2 = gbxmodelValues.Geometries[i].Parts[j].UncompressedVertices[k].Node1Index.Value;
                        bounds.Update(vertices[k].position.X, vertices[k].position.Y, vertices[k].position.Z);
                    }
                    for (int k = 0; k < gbxmodelValues.Geometries[i].Parts[j].Triangles.Count; k++)
                    {
                        strip[k * 3]     = (ushort)gbxmodelValues.Geometries[i].Parts[j].Triangles[k].Vertex0Index.Value;
                        strip[k * 3 + 1] = (ushort)gbxmodelValues.Geometries[i].Parts[j].Triangles[k].Vertex1Index.Value;
                        strip[k * 3 + 2] = (ushort)gbxmodelValues.Geometries[i].Parts[j].Triangles[k].Vertex2Index.Value;
                    }

                    try
                    {
                        SubMesh[] sub = new SubMesh[1];
                        sub[0]       = new SubMesh(0, (ushort)(strip.Length - 2), 0);
                        meshes[i][j] = new EnhancedMesh(vertices, strip, sub, true, false, true);
                        meshes[i][j].DefaultShader = shaders[gbxmodelValues.Geometries[i].Parts[j].ShaderIndex.Value];
                    }
                    catch (Exception ex)
                    {
                        LogError("Model tag {0}.{1} failed to create Mesh: {2}", Name, "gbxmodel", ex.Message);
                    }

                    //instances.Add(new ObjectInstance(meshes[i][j], new Vector3(gbxmodelValues.Geometries[i].Parts[j].Centroid.X, gbxmodelValues.Geometries[i].Parts[j].Centroid.Y, gbxmodelValues.Geometries[i].Parts[j].Centroid.Z)));
                    //instances.Add(new PartInstance(meshes[i][j], new Vector3(gbxmodelValues.Geometries[i].Parts[j].Centroid.X, gbxmodelValues.Geometries[i].Parts[j].Centroid.Y, gbxmodelValues.Geometries[i].Parts[j].Centroid.Z)));
                }
            }

            int[] regionPermutationCounts = new int[gbxmodelValues.Regions.Count];
            for (int i = 0; i < gbxmodelValues.Regions.Count; i++)
            {
                regionPermutationCounts[i] = gbxmodelValues.Regions[i].Permutations.Count;
            }

            superLow  = new InstanceCollection[regionPermutationCounts.Length][];
            low       = new InstanceCollection[regionPermutationCounts.Length][];
            medium    = new InstanceCollection[regionPermutationCounts.Length][];
            high      = new InstanceCollection[regionPermutationCounts.Length][];
            superHigh = new InstanceCollection[regionPermutationCounts.Length][];

            for (int i = 0; i < regionPermutationCounts.Length; i++)
            {
                superLow[i]  = new InstanceCollection[regionPermutationCounts[i]];
                low[i]       = new InstanceCollection[regionPermutationCounts[i]];
                medium[i]    = new InstanceCollection[regionPermutationCounts[i]];
                high[i]      = new InstanceCollection[regionPermutationCounts[i]];
                superHigh[i] = new InstanceCollection[regionPermutationCounts[i]];
            }

            int geometry;

            for (int i = 0; i < regionPermutationCounts.Length; i++)
            {
                for (int j = 0; j < regionPermutationCounts[i]; j++)
                {
                    geometry       = gbxmodelValues.Regions[i].Permutations[j].SuperLow.Value;
                    superLow[i][j] = new InstanceCollection();
                    for (int k = 0; k < meshes[geometry].Length; k++)
                    {
                        superLow[i][j].Add(new PartInstance(meshes[geometry][k],
                                                            meshes[geometry][k].DefaultShader,
                                                            new Vector3(gbxmodelValues.Geometries[geometry].Parts[k].Centroid.X,
                                                                        gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Y,
                                                                        gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Z),
                                                            meshes[geometry][k].BoundingBox));
                    }

                    geometry  = gbxmodelValues.Regions[i].Permutations[j].Low.Value;
                    low[i][j] = new InstanceCollection();
                    for (int k = 0; k < meshes[geometry].Length; k++)
                    {
                        low[i][j].Add(new PartInstance(meshes[geometry][k],
                                                       meshes[geometry][k].DefaultShader,
                                                       new Vector3(gbxmodelValues.Geometries[geometry].Parts[k].Centroid.X,
                                                                   gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Y,
                                                                   gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Z),
                                                       meshes[geometry][k].BoundingBox));
                    }

                    geometry     = gbxmodelValues.Regions[i].Permutations[j].Medium.Value;
                    medium[i][j] = new InstanceCollection();
                    for (int k = 0; k < meshes[geometry].Length; k++)
                    {
                        medium[i][j].Add(new PartInstance(meshes[geometry][k],
                                                          meshes[geometry][k].DefaultShader,
                                                          new Vector3(gbxmodelValues.Geometries[geometry].Parts[k].Centroid.X,
                                                                      gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Y,
                                                                      gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Z),
                                                          meshes[geometry][k].BoundingBox));
                    }

                    geometry   = gbxmodelValues.Regions[i].Permutations[j].High.Value;
                    high[i][j] = new InstanceCollection();
                    for (int k = 0; k < meshes[geometry].Length; k++)
                    {
                        high[i][j].Add(new PartInstance(meshes[geometry][k],
                                                        meshes[geometry][k].DefaultShader,
                                                        new Vector3(gbxmodelValues.Geometries[geometry].Parts[k].Centroid.X,
                                                                    gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Y,
                                                                    gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Z),
                                                        meshes[geometry][k].BoundingBox));
                    }

                    geometry        = gbxmodelValues.Regions[i].Permutations[j].SuperHigh.Value;
                    superHigh[i][j] = new InstanceCollection();
                    for (int k = 0; k < meshes[geometry].Length; k++)
                    {
                        superHigh[i][j].Add(new PartInstance(meshes[geometry][k],
                                                             meshes[geometry][k].DefaultShader,
                                                             new Vector3(gbxmodelValues.Geometries[geometry].Parts[k].Centroid.X,
                                                                         gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Y,
                                                                         gbxmodelValues.Geometries[geometry].Parts[k].Centroid.Z),
                                                             meshes[geometry][k].BoundingBox));
                    }
                }
            }
        }
Exemple #7
0
        private void CreateLightmap(float dist2, Vector3 badPoint, string path, int texIndex, float hemisphereSizeDivisor, TextureMap texMap, ref float maxIntensity)
        {
            int gatherCount = 100;

            int   width               = (int)(texMap.Width);  // * RadiosityHelper.LightmapScale);
            int   height              = (int)(texMap.Height); // * RadiosityHelper.LightmapScale);
            float heightF             = (float)texMap.Height; // *RadiosityHelper.LightmapScale;
            float widthF              = (float)texMap.Width;  // *RadiosityHelper.LightmapScale;
            float currentMaxIntensity = float.MinValue;
            float diffuse             = (float)RadiosityHelper.RadiosityDiffuseConstant;

            widthF  -= 1f;
            heightF -= 1f;

            SetOperation("Creating texture #" + (texIndex + 1));
            //List<CompressedPhoton> photons;

            Bitmap bitm = new Bitmap(width, height, PixelFormat.Format32bppRgb);

            RadiosityMaterial mat; Vector3 norm;

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < heightF; y++)
                {
                    bitm.SetPixel(x, y, m_bsp[0].ConvertUVTo3D(x, y, texIndex, 1, out mat, out norm) != Vector3.Empty ? new RealColor(1, 1, 1).ToARGB() : RealColor.Black.ToARGB());
                }
            }
            bitm.Save("k:\\convmap_" + texIndex + "_" + 1);

            //CreateLightmapWork(dist2, ref badPoint, texIndex, hemisphereSizeDivisor, texMap, width, height, heightF, widthF, ref currentMaxIntensity);

            // We are going to cycle through the materials of the bsp.
            EnhancedMesh[] meshes = m_bsp[0].GetMeshes(texIndex);
            for (int m = 0; m < meshes.Length; m++)
            {
                EnhancedMesh            material  = meshes[m];
                int                     faceCount = material.Indices.Length;
                RectangleBounds <float> bounds    = new RectangleBounds <float>(material.Vertices[0].u2, material.Vertices[0].v2);

                // First we're going to figure out a rectangle for this material.
                for (int v = 0; v < material.Vertices.Length; v++)
                {
                    bounds.Update(material.Vertices[v].u2, material.Vertices[v].v2);
                }
                int x      = (int)Math.Floor((widthF * bounds.left));
                int startX = x;
                int endX   = (int)Math.Ceiling(widthF * bounds.right);
                int y      = (int)Math.Floor(heightF * bounds.top);
                int endY   = (int)Math.Ceiling(heightF * bounds.bottom);

                //System.Diagnostics.Debugger.Break();

                for (; y <= endY; y++)
                {
                    x = startX;
                    for (; x <= endX; x++)
                    {
                        RadiosityMaterial illMaterial;
                        Vector3           faceNormal;

                        //if (y == 81)
                        // // if (x == 2)
                        //System.Diagnostics.Debugger.Break();
                        Vector3 worldPoint = m_bsp[0].ConvertUVTo3D(x, y, texIndex, m, out illMaterial, out faceNormal);
                        //AddDebugRay(worldPoint, faceNormal);

                        if (worldPoint != Vector3.Empty)
                        {
                            AddDebugPoint(worldPoint, RadiosityDebugPointListID.EstimateLocations);

                            var photons = photonMap.RetrieveNearestNeighbors((PhotonVector3)worldPoint, dist2, gatherCount, faceNormal);

                            RealColor estimate = RealColor.Black;

                            if (photons.Count > 0)
                            {
                                for (int p = 0; p < photons.Count; p++)
                                {
                                    if (photons.list[p].photonPtr == null)
                                    {
                                        continue;
                                    }
                                    float dotP = Vector3.Dot(photons.list[p].photonPtr.Direction, faceNormal);
                                    if (dotP < 0)
                                    {
                                        dotP *= -1;
                                        //AddDebugPoint(photons.list[p].photonPtr
                                        //AddDebugRay(photons.list[p].photonPtr.position.ToVector3(), photons.list[p].photonPtr.Direction);
                                    }

                                    estimate.Add(photons.list[p].photonPtr.Power.Copy().Multiply(dotP));
                                }

                                estimate.Multiply(diffuse);
                                estimate.Multiply(hemisphereSizeDivisor);
                                estimate.Multiply(illMaterial.AmbientLight);
                                //estimate.Multiply(1f / photons.Count);

                                if (RadiosityHelper.DoDistantLights)
                                {
                                    if (illMaterial.DistantLightCount > 1)
                                    {
                                        estimate.LambertianShade(faceNormal, illMaterial.DistantLight2Color, illMaterial.DistantLight2Direction, illMaterial.AmbientLight);
                                        estimate.LambertianShade(faceNormal, illMaterial.DistantLight1Color, illMaterial.DistantLight1Direction, illMaterial.AmbientLight);
                                    }
                                    else if (illMaterial.DistantLightCount > 0)
                                    {
                                        estimate.LambertianShade(faceNormal, illMaterial.DistantLight1Color, illMaterial.DistantLight1Direction, illMaterial.AmbientLight);
                                    }
                                }
                                texMap.SetPixel(x, y, estimate);
                            }
                            else
                            {
                                texMap.SetPixel(x, y, new RealColor(Color.Pink));
                            }
                        }
                        //else continue; // if there is no normal, the estimate is useless.
                    }
                }
            }

            if (currentMaxIntensity > maxIntensity)
            {
                maxIntensity = currentMaxIntensity;
            }

            texMap.SaveHDR(path + "lightmap_" + texIndex + ".hdr");
            bitm = texMap.Filter(new LinearToneMapper(), false);

            bitm.Save(path + "lightmap_" + texIndex + ".bmp");
        }