/// <summary>
 /// Converts the passed <see cref="MAPTerrainMoHAA"/> into a <see cref="MAPTerrainEF2"/>
 /// with the same heightmap.
 /// </summary>
 /// <param name="mohTerrain">The <see cref="MAPTerrainMoHAA"/> to convert.</param>
 /// <returns><see cref="MAPTerrainEF2"/> with the same shader and heightmap as <paramref name="mohTerrain"/>.</returns>
 private MAPTerrainEF2 ConvertToEF2Terrain(MAPTerrainMoHAA mohTerrain)
 {
     if (mohTerrain.size == new Vector2(9, 9))
     {
         MAPTerrainMoHAA.Partition partition  = mohTerrain.partitions[0];
         MAPTerrainEF2             ef2Terrain = new MAPTerrainEF2()
         {
             side          = 9,
             texture       = partition.shader,
             textureShiftS = partition.textureShift[0],
             textureShiftT = partition.textureShift[1],
             texRot        = (float)partition.rotation,
             texScaleX     = partition.textureScale[0],
             texScaleY     = partition.textureScale[1],
             flags         = 1024,             // maybe don't hardcode this?
             sideLength    = 512,
             start         = new Vector3(mohTerrain.origin.X, mohTerrain.origin.Y, 0),
             IF            = Vector4.Zero,
             LF            = Vector4.Zero,
             heightMap     = new float[9, 9],
             alphaMap      = new float[9, 9]
         };
         for (int y = 0; y < ef2Terrain.heightMap.GetLength(0); ++y)
         {
             for (int x = 0; x < ef2Terrain.heightMap.GetLength(1); ++x)
             {
                 ef2Terrain.heightMap[y, x] = mohTerrain.vertices[(y * (int)mohTerrain.size.Y) + x].height + (float)mohTerrain.origin.Z;
             }
         }
         return(ef2Terrain);
     }
     return(null);
 }
Beispiel #2
0
        /// <summary>
        /// Processes a <see cref="LODTerrain"/> in a <see cref="MAPTerrainMoHAA"/>.
        /// For MoHAA forks only.
        /// </summary>
        /// <param name="lodTerrain">The <see cref="LODTerrain"/> object to process.</param>
        /// <returns>A <see cref="MAPTerrainMoHAA"/> object to be added to a <see cref="MAPBrush"/> object.</returns>
        private MAPTerrainMoHAA ProcessTerrainMoHAA(LODTerrain lodTerrain)
        {
            string shader = _bsp.textures[lodTerrain.texture].name;

            MAPTerrainMoHAA.Partition partition = new MAPTerrainMoHAA.Partition()
            {
                shader       = shader,
                textureScale = new double[] { 1, 1 },
            };
            MAPTerrainMoHAA terrain = new MAPTerrainMoHAA()
            {
                size   = new Vector2d(9, 9),
                flags  = ((lodTerrain.flags & (1 << 6)) > 0) ? 1 : 0,
                origin = new Vector3d(lodTerrain.x * 64, lodTerrain.y * 64, lodTerrain.baseZ),
            };

            terrain.partitions.Add(partition);
            terrain.partitions.Add(partition);
            terrain.partitions.Add(partition);
            terrain.partitions.Add(partition);
            for (int i = 0; i < 9; ++i)
            {
                for (int j = 0; j < 9; ++j)
                {
                    MAPTerrainMoHAA.Vertex vertex = new MAPTerrainMoHAA.Vertex()
                    {
                        height = lodTerrain.heightmap[i, j] * 2,
                    };
                    terrain.vertices.Add(vertex);
                }
            }
            return(terrain);
        }
Beispiel #3
0
        /// <summary>
        /// Processes a <see cref="LODTerrain"/> in a <see cref="MAPTerrainMoHAA"/>.
        /// For MoHAA forks only.
        /// </summary>
        /// <param name="lodTerrain">The <see cref="LODTerrain"/> object to process.</param>
        /// <returns>A <see cref="MAPTerrainMoHAA"/> object to be added to a <see cref="MAPBrush"/> object.</returns>
        private MAPTerrainMoHAA ProcessTerrainMoHAA(LODTerrain lodTerrain)
        {
            string shader = _bsp.textures[lodTerrain.TextureIndex].Name;

            MAPTerrainMoHAA.Partition partition = new MAPTerrainMoHAA.Partition()
            {
                shader       = shader,
                textureScale = new float[] { 1, 1 },
            };
            MAPTerrainMoHAA terrain = new MAPTerrainMoHAA()
            {
                size   = new Vector2(9, 9),
                flags  = ((lodTerrain.Flags & (1 << 6)) > 0) ? 1 : 0,
                origin = new Vector3(lodTerrain.X * 64, lodTerrain.Y * 64, lodTerrain.BaseZ),
            };

            terrain.partitions.Add(partition);
            terrain.partitions.Add(partition);
            terrain.partitions.Add(partition);
            terrain.partitions.Add(partition);
            for (int i = 0; i < 9; ++i)
            {
                for (int j = 0; j < 9; ++j)
                {
                    MAPTerrainMoHAA.Vertex vertex = new MAPTerrainMoHAA.Vertex()
                    {
                        height = lodTerrain.Heightmap[i, j] * 2,
                    };
                    terrain.vertices.Add(vertex);
                }
            }
            return(terrain);
        }
 /// <summary>
 /// Postprocesser to convert the texture referenced by <paramref name="terrain"/> into one used by MOHRadiant, if necessary.
 /// </summary>
 /// <param name="patch">The <see cref="MAPTerrainMoHAA"/> to have its texture parsed.</param>
 private void PostProcessQuake3Texture(MAPTerrainMoHAA terrain)
 {
     foreach (MAPTerrainMoHAA.Partition partition in terrain.partitions)
     {
         if (partition.shader.StartsWith("textures/", StringComparison.InvariantCultureIgnoreCase))
         {
             partition.shader = partition.shader.Substring(9);
         }
     }
 }
Beispiel #5
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");
            }
        }
 /// <summary>
 /// Process the data in a <see cref="MAPTerrainMoHAA"/> into the passed <c>StringBuilder</c>.
 /// </summary>
 /// <param name="terrain">The <see cref="MAPTerrainMoHAA"/> to process.</param>
 /// <param name="sb">A <c>StringBuilder</c> object to append processed data from <paramref name="terrain"/> to.</param>
 private void ParseTerrain(MAPTerrainMoHAA terrain, StringBuilder sb)
 {
     sb.Append(" {\r\n  terrainDef\r\n  {\r\n   ")
     .Append(terrain.size[0])
     .Append(" ")
     .Append(terrain.size[1])
     .Append(" ")
     .Append(terrain.flags)
     .Append("\r\n   ")
     .Append(terrain.origin.x.ToString("###0.000000"))
     .Append(" ")
     .Append(terrain.origin.y.ToString("###0.000000"))
     .Append(" ")
     .Append(terrain.origin.z.ToString("###0.000000"))
     .Append("\r\n\t\t{\r\n");
     foreach (MAPTerrainMoHAA.Partition partition in terrain.partitions)
     {
         sb.Append("\t\t\t")
         .Append(partition.unknown1)
         .Append(" ")
         .Append(partition.unknown2)
         .Append(" ( ")
         .Append(partition.shader)
         .Append(" ")
         .Append(partition.textureShift[0])
         .Append(" ")
         .Append(partition.textureShift[1])
         .Append(" ")
         .Append(partition.rotation.ToString("###0.00"))
         .Append(" ")
         .Append(partition.unknown3)
         .Append(" ")
         .Append(partition.textureScale[0])
         .Append(" ")
         .Append(partition.textureScale[1])
         .Append(" ")
         .Append(partition.unknown4)
         .Append(" ")
         .Append(partition.flags)
         .Append(" ")
         .Append(partition.unknown5);
         if (!string.IsNullOrEmpty(partition.properties))
         {
             sb.Append(" ")
             .Append(partition.properties);
         }
         sb.Append(" )\r\n");
     }
     sb.Append("\t\t}\r\n\t\t{\r\n");
     foreach (MAPTerrainMoHAA.Vertex vertex in terrain.vertices)
     {
         sb.Append("\t\t\t")
         .Append(vertex.height.ToString("###0.000000"))
         .Append(" ( ");
         if (!string.IsNullOrEmpty(vertex.unknown1))
         {
             sb.Append(vertex.unknown1)
             .Append(" ");
         }
         sb.Append(") ( ");
         if (!string.IsNullOrEmpty(vertex.unknown2))
         {
             sb.Append(vertex.unknown2)
             .Append(" ");
         }
         sb.Append(")\r\n");
     }
     sb.Append("\t\t}\r\n  }\r\n }\r\n");
 }