예제 #1
0
        /// <summary>
        /// Builds all <see cref="Mesh"/> objects for the <see cref="Entity"/> in <paramref name="instance"/> instance,
        /// combines them if necessary using <see cref="settings"/>.meshCombineOptions and adds the meshes to the
        /// <see cref="GameObject"/> in <paramref name="instance"/>.
        /// </summary>
        /// <param name="instance">The <see cref="EntityInstance"/> to build <see cref="Mesh"/>es for.</param>
        protected void BuildMesh(EntityInstance instance)
        {
            int   modelNumber = instance.entity.modelNumber;
            Model model       = bsp.models[modelNumber];
            Dictionary <string, List <Mesh> > textureMeshMap = new Dictionary <string, List <Mesh> >();
            GameObject gameObject = instance.gameObject;

            List <Face> faces = bsp.GetFacesInModel(model);
            int         i     = 0;

            for (i = 0; i < faces.Count; ++i)
            {
                Face face = faces[i];
                if (face.numEdges <= 0 && face.numVertices <= 0)
                {
                    continue;
                }

                int    textureIndex = bsp.GetTextureIndex(face);
                string textureName  = "";
                if (textureIndex >= 0)
                {
                    LibBSP.Texture texture = bsp.textures[textureIndex];
                    textureName = texture.name;

                    if (!textureMeshMap.ContainsKey(textureName) || textureMeshMap[textureName] == null)
                    {
                        textureMeshMap[textureName] = new List <Mesh>();
                    }

                    textureMeshMap[textureName].Add(CreateFaceMesh(face, textureName));
                }
            }

            if (modelNumber == 0)
            {
                if (bsp.lodTerrains != null)
                {
                    foreach (LODTerrain lodTerrain in bsp.lodTerrains)
                    {
                        if (lodTerrain.texture >= 0)
                        {
                            LibBSP.Texture texture     = bsp.textures[lodTerrain.texture];
                            string         textureName = texture.name;

                            if (!textureMeshMap.ContainsKey(textureName) || textureMeshMap[textureName] == null)
                            {
                                textureMeshMap[textureName] = new List <Mesh>();
                            }

                            textureMeshMap[textureName].Add(CreateLoDTerrainMesh(lodTerrain, textureName));
                        }
                    }
                }
            }

            if (settings.meshCombineOptions != MeshCombineOptions.None)
            {
                Mesh[]     textureMeshes = new Mesh[textureMeshMap.Count];
                Material[] materials     = new Material[textureMeshes.Length];
                i = 0;
                foreach (KeyValuePair <string, List <Mesh> > pair in textureMeshMap)
                {
                    textureMeshes[i] = MeshUtils.CombineAllMeshes(pair.Value.ToArray(), true, false);
                    if (materialDirectory.ContainsKey(pair.Key))
                    {
                        materials[i] = materialDirectory[pair.Key];
                    }
                    if (settings.meshCombineOptions == MeshCombineOptions.PerMaterial)
                    {
                        GameObject textureGameObject = new GameObject(pair.Key);
                        textureGameObject.transform.parent        = gameObject.transform;
                        textureGameObject.transform.localPosition = Vector3.zero;
                        if (textureMeshes[i].normals.Length == 0 || textureMeshes[i].normals[0] == Vector3.zero)
                        {
                            textureMeshes[i].RecalculateNormals();
                        }
                        textureMeshes[i].AddMeshToGameObject(new Material[] { materials[i] }, textureGameObject);
#if UNITY_EDITOR
                        if (!IsRuntime && (settings.assetSavingOptions & AssetSavingOptions.Meshes) > 0)
                        {
                            string meshPath = Path.Combine(Path.Combine(Path.Combine("Assets", settings.meshPath), bsp.MapNameNoExtension), "mesh_" + textureMeshes[i].GetHashCode() + ".asset").Replace('\\', '/');
                            Directory.CreateDirectory(Path.GetDirectoryName(meshPath));
                            AssetDatabase.CreateAsset(textureMeshes[i], meshPath);
                        }
#endif
                    }
                    ++i;
                }

                if (settings.meshCombineOptions != MeshCombineOptions.PerMaterial)
                {
                    Mesh mesh = MeshUtils.CombineAllMeshes(textureMeshes, false, false);
                    mesh.TransformVertices(gameObject.transform.localToWorldMatrix);
                    if (mesh.normals.Length == 0 || mesh.normals[0] == Vector3.zero)
                    {
                        mesh.RecalculateNormals();
                    }
                    mesh.AddMeshToGameObject(materials, gameObject);
#if UNITY_EDITOR
                    if (!IsRuntime && (settings.assetSavingOptions & AssetSavingOptions.Meshes) > 0)
                    {
                        string meshPath = Path.Combine(Path.Combine(Path.Combine("Assets", settings.meshPath), bsp.MapNameNoExtension), "mesh_" + mesh.GetHashCode() + ".asset").Replace('\\', '/');
                        Directory.CreateDirectory(Path.GetDirectoryName(meshPath));
                        AssetDatabase.CreateAsset(mesh, meshPath);
                    }
#endif
                }
            }
            else
            {
                i = 0;
                foreach (KeyValuePair <string, List <Mesh> > pair in textureMeshMap)
                {
                    GameObject textureGameObject = new GameObject(pair.Key);
                    textureGameObject.transform.parent        = gameObject.transform;
                    textureGameObject.transform.localPosition = Vector3.zero;
                    Material material = materialDirectory[pair.Key];
                    foreach (Mesh mesh in pair.Value)
                    {
                        GameObject faceGameObject = new GameObject("Face");
                        faceGameObject.transform.parent        = textureGameObject.transform;
                        faceGameObject.transform.localPosition = Vector3.zero;
                        if (mesh.normals.Length == 0 || mesh.normals[0] == Vector3.zero)
                        {
                            mesh.RecalculateNormals();
                        }
                        mesh.AddMeshToGameObject(new Material[] { material }, faceGameObject);
#if UNITY_EDITOR
                        if (!IsRuntime && (settings.assetSavingOptions & AssetSavingOptions.Meshes) > 0)
                        {
                            string meshPath = Path.Combine(Path.Combine(Path.Combine("Assets", settings.meshPath), bsp.MapNameNoExtension), "mesh_" + mesh.GetHashCode() + ".asset").Replace('\\', '/');
                            Directory.CreateDirectory(Path.GetDirectoryName(meshPath));
                            AssetDatabase.CreateAsset(mesh, meshPath);
                        }
#endif
                    }
                    ++i;
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Processes an <see cref="Entity"/> into a state where it can be output into a file that map editors can read.
        /// </summary>
        /// <param name="entity">The <see cref="Entity"/> to process.</param>
        /// <remarks>This method does not return anything, since the <see cref="Entity"/> object is modified by reference.</remarks>
        private void ProcessEntity(Entity entity)
        {
            int modelNumber = entity.modelNumber;

            // If this Entity has no modelNumber, then this is a no-op. No processing is needed.
            // A modelnumber of 0 indicates the world entity.
            if (modelNumber >= 0)
            {
                Model model = _bsp.models[modelNumber];
                if (_bsp.brushes != null)
                {
                    List <Brush> brushes = _bsp.GetBrushesInModel(model);
                    if (brushes != null)
                    {
                        foreach (Brush brush in brushes)
                        {
                            MAPBrush result = ProcessBrush(brush, entity.origin);
                            result.isWater |= (entity.className == "func_water");
                            if (_master.settings.brushesToWorld)
                            {
                                _bsp.entities.GetWithAttribute("classname", "worldspawn").brushes.Add(result);
                            }
                            else
                            {
                                entity.brushes.Add(result);
                            }
                            ++_itemsProcessed;
                            ReportProgress();
                        }
                    }
                }
                if (model.numLeafPatches > 0 && _bsp.markSurfaces != null && _bsp.patches != null)
                {
                    HashSet <Patch> patches            = new HashSet <Patch>();
                    List <long>     leafPatchesInModel = _bsp.GetReferencedObjects <long>(model, "markSurfaces");
                    foreach (long leafPatch in leafPatchesInModel)
                    {
                        if (leafPatch >= 0)
                        {
                            patches.Add(_bsp.patches[(int)leafPatch]);
                        }
                    }
                    foreach (Patch patch in patches)
                    {
                        if (_bsp.version != MapType.CoD || patch.patchType == 0)
                        {
                            MAPPatch mappatch = ProcessPatch(patch);
                            MAPBrush newBrush = new MAPBrush();
                            newBrush.patch = mappatch;
                            entity.brushes.Add(newBrush);
                        }
                    }
                }
                if (_bsp.faces != null)
                {
                    List <Face> surfaces = _bsp.GetFacesInModel(model);
                    foreach (Face face in surfaces)
                    {
                        if (face.displacement >= 0)
                        {
                            if (modelNumber != 0)
                            {
                                _master.Print("WARNING: Displacement not part of world in " + _bsp.MapNameNoExtension);
                            }
                            MAPDisplacement displacement = ProcessDisplacement(_bsp.dispInfos[face.displacement]);
                            MAPBrush        newBrush     = face.CreateBrush(_bsp, 32);
                            newBrush.sides[0].displacement = displacement;
                            // If we are not decompiling to VMF, vis will need to skip this brush.
                            newBrush.isDetail = true;
                            entity.brushes.Add(newBrush);
                        }
                        else if (face.flags == 2)
                        {
                            MAPPatch patch    = ProcessPatch(face);
                            MAPBrush newBrush = new MAPBrush();
                            newBrush.patch = patch;
                            entity.brushes.Add(newBrush);
                        }
                        else if ((_bsp.version == MapType.STEF2 || _bsp.version == MapType.STEF2Demo) && face.flags == 5)
                        {
                            if (modelNumber != 0)
                            {
                                _master.Print("WARNING: Terrain not part of world in " + _bsp.MapNameNoExtension);
                            }
                            MAPTerrainEF2 terrain  = ProcessEF2Terrain(face);
                            MAPBrush      newBrush = new MAPBrush();
                            newBrush.ef2Terrain = terrain;
                            entity.brushes.Add(newBrush);
                        }
                    }
                }

                // If this is model 0 (worldspawn) there are other things that need to be taken into account.
                if (modelNumber == 0)
                {
                    if (_bsp.lodTerrains != null)
                    {
                        foreach (LODTerrain lodTerrain in _bsp.lodTerrains)
                        {
                            MAPTerrainMoHAA terrain  = ProcessTerrainMoHAA(lodTerrain);
                            MAPBrush        newBrush = new MAPBrush();
                            newBrush.mohTerrain = terrain;
                            entity.brushes.Add(newBrush);
                        }
                    }
                }
                entity.Remove("model");
            }
        }