Пример #1
0
 public bool Equals(WadMesh other) => Hash == other.Hash;
Пример #2
0
        private static WadMesh LoadMesh(ChunkReader chunkIO, long chunkSize, Dictionary <long, WadTexture> textures)
        {
            var  mesh          = new WadMesh();
            long obsoleteIndex = 0;

            chunkIO.ReadChunks((id2, chunkSize2) =>
            {
                if (id2 == Wad2Chunks.MeshIndex)
                {
                    obsoleteIndex = chunkIO.ReadChunkLong(chunkSize2);
                }
                else if (id2 == Wad2Chunks.MeshName)
                {
                    mesh.Name = chunkIO.ReadChunkString(chunkSize2);
                }
                else if (id2 == Wad2Chunks.MeshSphere)
                {
                    // Read bounding sphere
                    float radius   = 0;
                    Vector3 center = Vector3.Zero;
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshSphereCenter)
                        {
                            center = chunkIO.ReadChunkVector3(chunkSize3);
                        }
                        else if (id3 == Wad2Chunks.MeshSphereRadius)
                        {
                            radius = chunkIO.ReadChunkFloat(chunkSize3);
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                    mesh.BoundingSphere = new BoundingSphere(center, radius);
                }
                else if (id2 == Wad2Chunks.MeshBoundingBox)
                {
                    // Read bounding box
                    Vector3 min = Vector3.Zero;
                    Vector3 max = Vector3.Zero;
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshBoundingBoxMin)
                        {
                            min = chunkIO.ReadChunkVector3(chunkSize3);
                        }
                        else if (id3 == Wad2Chunks.MeshBoundingBoxMax)
                        {
                            max = chunkIO.ReadChunkVector3(chunkSize3);
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                    mesh.BoundingBox = new BoundingBox(min, max);
                }
                else if (id2 == Wad2Chunks.MeshVertexPositions)
                {
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshVertexPosition)
                        {
                            mesh.VerticesPositions.Add(chunkIO.ReadChunkVector3(chunkSize3));
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                }
                else if (id2 == Wad2Chunks.MeshVertexNormals)
                {
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshVertexNormal)
                        {
                            mesh.VerticesNormals.Add(chunkIO.ReadChunkVector3(chunkSize3));
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                }
                else if (id2 == Wad2Chunks.MeshVertexShades)
                {
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshVertexShade)
                        {
                            mesh.VerticesShades.Add(chunkIO.ReadChunkShort(chunkSize3));
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                }
                else if (id2 == Wad2Chunks.MeshPolygons)
                {
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshQuad ||
                            id3 == Wad2Chunks.MeshTriangle)
                        {
                            var polygon    = new WadPolygon();
                            polygon.Shape  = id3 == Wad2Chunks.MeshQuad ? WadPolygonShape.Quad : WadPolygonShape.Triangle;
                            polygon.Index0 = LEB128.ReadInt(chunkIO.Raw);
                            polygon.Index1 = LEB128.ReadInt(chunkIO.Raw);
                            polygon.Index2 = LEB128.ReadInt(chunkIO.Raw);
                            if (id3 == Wad2Chunks.MeshQuad)
                            {
                                polygon.Index3 = LEB128.ReadInt(chunkIO.Raw);
                            }
                            polygon.ShineStrength = LEB128.ReadByte(chunkIO.Raw);

                            TextureArea textureArea = new TextureArea();
                            textureArea.Texture     = textures[LEB128.ReadInt(chunkIO.Raw)];
                            textureArea.TexCoord0   = chunkIO.Raw.ReadVector2();
                            textureArea.TexCoord1   = chunkIO.Raw.ReadVector2();
                            textureArea.TexCoord2   = chunkIO.Raw.ReadVector2();
                            if (id3 == Wad2Chunks.MeshQuad)
                            {
                                textureArea.TexCoord3 = chunkIO.Raw.ReadVector2();
                            }
                            else
                            {
                                textureArea.TexCoord3 = textureArea.TexCoord2;
                            }
                            textureArea.BlendMode   = (BlendMode)LEB128.ReadLong(chunkIO.Raw);
                            textureArea.DoubleSided = chunkIO.Raw.ReadBoolean();
                            polygon.Texture         = textureArea;

                            chunkIO.ReadChunks((id4, chunkSize4) =>
                            {
                                return(false);
                            });

                            mesh.Polys.Add(polygon);
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                }
                else
                {
                    return(false);
                }

                return(true);
            });

            return(mesh);
        }
Пример #3
0
        public static List <WadMesh> ImportFromExternalModel(string fileName, IOGeometrySettings settings, bool mergeIntoOne)
        {
            IOModel tmpModel = null;
            var     meshList = new List <WadMesh>();

            bool calculateNormals = false;

            // Import the model
            try
            {
                var importer = BaseGeometryImporter.CreateForFile(fileName, settings, absoluteTexturePath =>
                {
                    return(new WadTexture(ImageC.FromFile(absoluteTexturePath)));
                });
                tmpModel = importer.ImportFromFile(fileName);

                calculateNormals = importer is MetasequoiaImporter;
            }
            catch (Exception ex)
            {
                logger.Error(ex, "Geometry import failed!");
                return(null);
            }

            // Create a new mesh (all meshes from model will be joined)
            WadMesh mesh           = null;
            var     lastBaseVertex = 0;

            for (int i = 0; i < tmpModel.Meshes.Count; i++)
            {
                var tmpMesh = tmpModel.Meshes[i];

                if (mesh == null || !mergeIntoOne)
                {
                    mesh      = new WadMesh();
                    mesh.Name = string.IsNullOrEmpty(tmpMesh.Name) ? "ImportedMesh" + i : tmpMesh.Name;

                    if (mergeIntoOne)
                    {
                        lastBaseVertex = 0;               // Reset if we're doing multi-mesh import
                    }
                }

                mesh.VerticesPositions.AddRange(tmpMesh.Positions);

                // Copy normals as well, if they are consistent
                if (tmpMesh.Normals.Count == tmpMesh.Positions.Count)
                {
                    mesh.VerticesNormals.AddRange(tmpMesh.Normals);
                }

                // FIXME: Why do we keep white intensity shades for wad2 meshes internally, and not vertex colors?
                if (tmpMesh.Colors.Count == tmpMesh.Positions.Count)
                {
                    mesh.VerticesShades.AddRange(tmpMesh.Colors.Select(v => (short)(8191.0f - (v.To3().GetLuma() * 8191.0f))));
                }

                foreach (var tmpSubmesh in tmpMesh.Submeshes)
                {
                    foreach (var tmpPoly in tmpSubmesh.Value.Polygons)
                    {
                        if (tmpPoly.Shape == IOPolygonShape.Quad)
                        {
                            var poly = new WadPolygon {
                                Shape = WadPolygonShape.Quad
                            };
                            poly.Index0 = tmpPoly.Indices[0] + lastBaseVertex;
                            poly.Index1 = tmpPoly.Indices[1] + lastBaseVertex;
                            poly.Index2 = tmpPoly.Indices[2] + lastBaseVertex;
                            poly.Index3 = tmpPoly.Indices[3] + lastBaseVertex;

                            var area = new TextureArea();
                            area.TexCoord0   = tmpMesh.UV[tmpPoly.Indices[0]];
                            area.TexCoord1   = tmpMesh.UV[tmpPoly.Indices[1]];
                            area.TexCoord2   = tmpMesh.UV[tmpPoly.Indices[2]];
                            area.TexCoord3   = tmpMesh.UV[tmpPoly.Indices[3]];
                            area.Texture     = tmpSubmesh.Value.Material.Texture;
                            area.DoubleSided = tmpSubmesh.Value.Material.DoubleSided;

                            poly.Texture       = area;
                            poly.ShineStrength = (byte)Math.Round(tmpSubmesh.Value.Material.Shininess / 16.0f, MidpointRounding.ToEven);

                            mesh.Polys.Add(poly);
                        }
                        else
                        {
                            var poly = new WadPolygon {
                                Shape = WadPolygonShape.Triangle
                            };
                            poly.Index0 = tmpPoly.Indices[0] + lastBaseVertex;
                            poly.Index1 = tmpPoly.Indices[1] + lastBaseVertex;
                            poly.Index2 = tmpPoly.Indices[2] + lastBaseVertex;

                            var area = new TextureArea();
                            area.TexCoord0   = tmpMesh.UV[tmpPoly.Indices[0]];
                            area.TexCoord1   = tmpMesh.UV[tmpPoly.Indices[1]];
                            area.TexCoord2   = tmpMesh.UV[tmpPoly.Indices[2]];
                            area.TexCoord3   = area.TexCoord2;
                            area.Texture     = tmpSubmesh.Value.Material.Texture;
                            area.DoubleSided = tmpSubmesh.Value.Material.DoubleSided;

                            poly.Texture       = area;
                            poly.ShineStrength = (byte)Math.Round(tmpSubmesh.Value.Material.Shininess / 16.0f, MidpointRounding.ToEven);

                            mesh.Polys.Add(poly);
                        }
                    }
                }

                if (!mergeIntoOne || i == tmpModel.Meshes.Count - 1)
                {
                    mesh.BoundingBox    = mesh.CalculateBoundingBox();
                    mesh.BoundingSphere = mesh.CalculateBoundingSphere();

                    if (mesh.VerticesNormals.Count == 0 || calculateNormals)
                    {
                        mesh.CalculateNormals(); // MQO files rarely have normals
                    }
                    if (mesh.VerticesPositions.Count != mesh.VerticesShades.Count)
                    {
                        mesh.VerticesShades.Clear(); // Reset vertex shades in case they got desynced from vertex count
                    }
                    lastBaseVertex = 0;
                    meshList.Add(mesh);
                }
                else
                {
                    lastBaseVertex = mesh.VerticesPositions.Count;
                }
            }

            return(meshList);
        }
Пример #4
0
        public static void WriteMesh(ChunkWriter chunkIO, WadMesh mesh, List <WadTexture> textureTable)
        {
            chunkIO.WriteChunkWithChildren(Wad2Chunks.Mesh, () =>
            {
                chunkIO.WriteChunkInt(Wad2Chunks.MeshIndex, 0);
                chunkIO.WriteChunkString(Wad2Chunks.MeshName, mesh.Name);

                // Write bounding sphere
                chunkIO.WriteChunkWithChildren(Wad2Chunks.MeshSphere, () =>
                {
                    chunkIO.WriteChunkVector3(Wad2Chunks.MeshSphereCenter, mesh.BoundingSphere.Center);
                    chunkIO.WriteChunkFloat(Wad2Chunks.MeshSphereRadius, mesh.BoundingSphere.Radius);
                });

                // Write bounding box
                chunkIO.WriteChunkWithChildren(Wad2Chunks.MeshBoundingBox, () =>
                {
                    chunkIO.WriteChunkVector3(Wad2Chunks.MeshBoundingBoxMin, mesh.BoundingBox.Minimum);
                    chunkIO.WriteChunkVector3(Wad2Chunks.MeshBoundingBoxMax, mesh.BoundingBox.Maximum);
                });

                // Write positions
                chunkIO.WriteChunkWithChildren(Wad2Chunks.MeshVertexPositions, () =>
                {
                    foreach (var pos in mesh.VerticesPositions)
                    {
                        chunkIO.WriteChunkVector3(Wad2Chunks.MeshVertexPosition, pos);
                    }
                });

                // Write normals
                chunkIO.WriteChunkWithChildren(Wad2Chunks.MeshVertexNormals, () =>
                {
                    foreach (var normal in mesh.VerticesNormals)
                    {
                        chunkIO.WriteChunkVector3(Wad2Chunks.MeshVertexNormal, normal);
                    }
                });

                // Write shades
                chunkIO.WriteChunkWithChildren(Wad2Chunks.MeshVertexShades, () =>
                {
                    foreach (var shade in mesh.VerticesShades)
                    {
                        chunkIO.WriteChunkInt(Wad2Chunks.MeshVertexShade, shade);
                    }
                });

                // Write polygons
                chunkIO.WriteChunkWithChildren(Wad2Chunks.MeshPolygons, () =>
                {
                    foreach (var poly in mesh.Polys)
                    {
                        bool isQuad = poly.Shape == WadPolygonShape.Quad;

                        chunkIO.WriteChunkWithChildren(isQuad ? Wad2Chunks.MeshQuad : Wad2Chunks.MeshTriangle, () =>
                        {
                            LEB128.Write(chunkIO.Raw, poly.Index0);
                            LEB128.Write(chunkIO.Raw, poly.Index1);
                            LEB128.Write(chunkIO.Raw, poly.Index2);
                            if (isQuad)
                            {
                                LEB128.Write(chunkIO.Raw, poly.Index3);
                            }
                            LEB128.Write(chunkIO.Raw, poly.ShineStrength);

                            LEB128.Write(chunkIO.Raw, textureTable.IndexOf(poly.Texture.Texture as WadTexture));
                            chunkIO.Raw.Write(poly.Texture.TexCoord0);
                            chunkIO.Raw.Write(poly.Texture.TexCoord1);
                            chunkIO.Raw.Write(poly.Texture.TexCoord2);
                            if (isQuad)
                            {
                                chunkIO.Raw.Write(poly.Texture.TexCoord3);
                            }
                            LEB128.Write(chunkIO.Raw, (long)poly.Texture.BlendMode);
                            chunkIO.Raw.Write(poly.Texture.DoubleSided);
                        });
                    }
                });
            });
        }