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); }
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); }
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())); }
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)); } } } }
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"); }