Example #1
0
    public static void CreateMeshes()
    {
        Transform holder = new GameObject("MapMeshes").transform;

        holder.transform.SetParent(GameManager.Instance.transform);

        //walls
        {
            int index = 0;
            foreach (Linedef l in MapLoader.linedefs)
            {
                //if (l.lineType > 0 || l.lineTag > 0)
                //Debug.Log("Line " + index + " type: " + l.lineType + " tag: " + l.lineTag);

                //add linedef to the fast lookup cache
                AxMath.CartesianLineF(l.start.Position, l.end.Position).Perform((n) =>
                {
                    int gridX = n.Data.x - TheGrid.origoX;
                    int gridY = n.Data.y - TheGrid.origoY;

                    TheGrid.linedefs[gridX, gridY].Add(l);
                    TheGrid.existenceBox.data[gridX, gridY] = true;
                });

                if (l.Back != null)
                {
                    //top part (front)
                    if (l.Front.Sector.ceilingHeight > l.Back.Sector.ceilingHeight)
                    {
                        l.TopFrontObject = CreateLineQuad
                                           (
                            l.Front,
                            l.Back.Sector.ceilingHeight,
                            l.Front.Sector.ceilingHeight + (l.Back.Sector.ceilingHeight - l.Back.Sector.minimumCeilingHeight),
                            l.Front.tHigh,
                            l.Front.offsetX,
                            (l.flags & (1 << 3)) != 0 ? l.Front.offsetY : -l.Front.offsetY,
                            (l.flags & (1 << 3)) != 0 ? 0 : 1,
                            false,
                            l.Front.Sector.brightness,
                            true,
                            "Wall_" + index + "_top_front",
                            holder
                                           );
                    }
                    //lowering ceiling (front)
                    else if (l.Front.Sector.ceilingHeight > l.Back.Sector.minimumCeilingHeight)
                    {
                        l.TopFrontObject = CreateLineQuad
                                           (
                            l.Front,
                            l.Back.Sector.ceilingHeight,
                            l.Front.Sector.ceilingHeight + (l.Back.Sector.ceilingHeight - l.Back.Sector.minimumCeilingHeight),
                            l.Front.tHigh,
                            l.Front.offsetX,
                            (l.flags & (1 << 3)) != 0 ? l.Front.offsetY : -l.Front.offsetY,
                            (l.flags & (1 << 3)) != 0 ? 0 : 1,
                            false,
                            l.Front.Sector.brightness,
                            true,
                            "Wall_" + index + "_top_front",
                            holder
                                           );
                    }

                    //top part (back)
                    if (l.Front.Sector.ceilingHeight < l.Back.Sector.ceilingHeight)
                    {
                        l.TopBackObject = CreateLineQuad
                                          (
                            l.Back,
                            l.Front.Sector.ceilingHeight,
                            l.Back.Sector.ceilingHeight,
                            l.Back.tHigh,
                            l.Back.offsetX,
                            (l.flags & (1 << 3)) != 0 ? l.Back.offsetY : l.Back.offsetY,
                            (l.flags & (1 << 3)) != 0 ? 0 : 1,
                            true,
                            l.Back.Sector.brightness,
                            true,
                            "Wall_" + index + "_top_back",
                            holder
                                          );
                    }

                    //bottom part (front)
                    if (l.Front.Sector.minimumFloorHeight < l.Back.Sector.floorHeight)
                    {
                        l.BotFrontObject = CreateLineQuad
                                           (
                            l.Front,
                            l.Front.Sector.minimumFloorHeight,
                            l.Back.Sector.floorHeight,
                            l.Front.tLow,
                            l.Front.offsetX,
                            l.Front.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 2 : 0,
                            false,
                            l.Front.Sector.brightness,
                            true,
                            "Wall_" + index + "_bot_front",
                            holder
                                           );
                    }
                    //rising floor (front)
                    else if (l.Front.Sector.maximumFloorHeight > l.Back.Sector.floorHeight && l.Front.Sector.maximumFloorHeight > l.Front.Sector.floorHeight)
                    {
                        l.BotFrontObject = CreateLineQuad
                                           (
                            l.Front,
                            l.Front.Sector.floorHeight - (l.Front.Sector.maximumFloorHeight - l.Back.Sector.floorHeight),
                            l.Front.Sector.floorHeight,
                            l.Front.tLow,
                            l.Front.offsetX,
                            l.Front.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 2 : 0,
                            false,
                            l.Front.Sector.brightness,
                            true,
                            "Wall_" + index + "_bot_front",
                            holder
                                           );
                    }

                    //bottom part (back)
                    if (l.Front.Sector.floorHeight > l.Back.Sector.minimumFloorHeight)
                    {
                        l.BotBackObject = CreateLineQuad
                                          (
                            l.Back,
                            l.Back.Sector.minimumFloorHeight,
                            l.Front.Sector.floorHeight,
                            l.Back.tLow,
                            l.Back.offsetX,
                            l.Front.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 2 : 0,
                            true,
                            l.Back.Sector.brightness,
                            true,
                            "Wall_" + index + "_bot_back",
                            holder
                                          );
                    }
                    //rising floor (back)
                    else if (l.Back.Sector.maximumFloorHeight > l.Front.Sector.floorHeight && l.Back.Sector.maximumFloorHeight > l.Back.Sector.floorHeight)
                    {
                        l.BotBackObject = CreateLineQuad
                                          (
                            l.Front,
                            l.Back.Sector.floorHeight - (l.Back.Sector.maximumFloorHeight - l.Front.Sector.floorHeight),
                            l.Back.Sector.floorHeight,
                            l.Front.tLow,
                            l.Front.offsetX,
                            l.Front.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 2 : 0,
                            false,
                            l.Front.Sector.brightness,
                            true,
                            "Wall_" + index + "_bot_front",
                            holder
                                          );
                    }

                    //middle (front)
                    if (l.Front.tMid != "-")
                    {
                        l.MidFrontObject = CreateLineQuad
                                           (
                            l.Front,
                            Mathf.Max(l.Front.Sector.floorHeight, l.Back.Sector.floorHeight),
                            Mathf.Min(l.Front.Sector.ceilingHeight, l.Back.Sector.ceilingHeight),
                            l.Front.tMid,
                            l.Front.offsetX,
                            l.Front.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 1 : 0,
                            false,
                            l.Front.Sector.brightness,
                            false,
                            "Wall_" + index + "_mid_front",
                            holder
                                           );
                    }

                    //middle (back)
                    if (l.Back.tMid != "-")
                    {
                        l.MidBackObject = CreateLineQuad
                                          (
                            l.Back,
                            Mathf.Max(l.Front.Sector.floorHeight, l.Back.Sector.floorHeight),
                            Mathf.Min(l.Front.Sector.ceilingHeight, l.Back.Sector.ceilingHeight),
                            l.Back.tMid,
                            l.Back.offsetX,
                            l.Back.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 1 : 0,
                            true,
                            l.Back.Sector.brightness,
                            false,
                            "Wall_" + index + "_mid_back",
                            holder
                                          );
                    }

                    if ((l.flags & (1 << 0)) != 0)
                    {
                        CreateInvisibleBlocker
                        (
                            l,
                            Mathf.Max(l.Front.Sector.floorHeight, l.Back.Sector.floorHeight),
                            Mathf.Min(l.Front.Sector.ceilingHeight, l.Back.Sector.ceilingHeight),
                            "Wall_" + index + "_blocker",
                            holder
                        );
                    }
                }
                else //solid wall
                {
                    l.MidFrontObject = CreateLineQuad
                                       (
                        l.Front,
                        l.Front.Sector.minimumFloorHeight,
                        l.Front.Sector.maximumCeilingHeight,
                        l.Front.tMid,
                        l.Front.offsetX,
                        l.Front.offsetY,
                        ((l.flags & (1 << 4)) != 0) ? 1 : 0,
                        false,
                        l.Front.Sector.brightness,
                        true,
                        "Wall_" + index,
                        holder
                                       );
                }

                index++;
            }
        }

        //sectors
        {
            Triangulator triangulator = new Triangulator();

            int index = 0;
            foreach (Sector s in MapLoader.sectors)
            {
                //if (s.specialType > 0 || s.tag > 0)
                //Debug.Log("Sector " + index + " type: " + s.specialType + " tag: " + s.tag);

                triangulator.Triangulate(s);

                if (Triangulator.vertices.Count == 0)
                {
                    Debug.Log("Triangulation failed for sector " + index);
                }

                //floor
                {
                    GameObject sectorObject = new GameObject("Sector_" + index + "_floor");
                    s.floorObject = sectorObject.AddComponent <SectorController>();
                    sectorObject.transform.SetParent(holder);
                    MeshRenderer mr         = sectorObject.AddComponent <MeshRenderer>();
                    MeshFilter   meshFilter = sectorObject.AddComponent <MeshFilter>();
                    Mesh         mesh       = new Mesh();
                    meshFilter.mesh = mesh;

                    if (!MaterialManager.Instance.OverridesFlat(s.floorTexture, sectorObject, mr))
                    {
                        mr.material = MaterialManager.Instance.defaultMaterial;
                    }

                    if (mr.material.mainTexture == null)
                    {
                        MaterialPropertyBlock materialProperties = new MaterialPropertyBlock();
                        materialProperties.SetTexture("_MainTex", TextureLoader.Instance.GetFlatTexture(s.floorTexture));
                        mr.SetPropertyBlock(materialProperties);
                    }

                    mesh.name = "Sector_" + index + "_floor_mesh";

                    int vc = Triangulator.vertices.Count;

                    Vector3[] vertices = new Vector3[vc];
                    Vector3[] normals  = new Vector3[vc];
                    Vector2[] uvs      = new Vector2[vc];
                    Color[]   colors   = new Color[vc];
                    int[]     indices  = new int[vc];

                    int          v      = 0;
                    int          i      = 0;
                    int          g      = 0;
                    Triangle     t      = null;
                    BooleanBox[] bboxes = new BooleanBox[Triangulator.vertices.Count / 3];
                    foreach (Vector2 p in Triangulator.vertices)
                    {
                        vertices[v] = new Vector3(p.x, s.floorHeight, p.y);
                        indices[v]  = v;
                        normals[v]  = Vector3.up;
                        uvs[v]      = new Vector2(p.x / MapLoader.flatUVdividor, 1 - (p.y / MapLoader.flatUVdividor));
                        colors[v]   = Color.white * s.brightness;

                        v++;

                        //add the triangle to the fast lookup cache
                        if (i == 0)
                        {
                            t = new Triangle();
                        }

                        t.vertices[i] = p;

                        i++;
                        if (i == 3)
                        {
                            i        = 0;
                            t.sector = s;
                            s.triangles.Add(t);

                            BooleanBox bbox = t.SelectBox;
                            if (bbox != null)
                            {
                                for (int y = 0; y < bbox.size.y; y++)
                                {
                                    for (int x = 0; x < bbox.size.x; x++)
                                    {
                                        if (bbox.data[x, y])
                                        {
                                            int gridX = bbox.origo.x - TheGrid.origoX + x;
                                            int gridY = bbox.origo.y - TheGrid.origoY + y;
                                            TheGrid.triangles[gridX, gridY].Add(t);
                                            TheGrid.existenceBox.data[gridX, gridY] = true;
                                        }
                                    }
                                }
                            }

                            bboxes[g++] = bbox;
                        }
                    }

                    //combine all triangles and add the sector to the fast lookup cache
                    BooleanBox sectorBox = BooleanBox.Combine(bboxes);
                    for (int y = 0; y < sectorBox.size.y; y++)
                    {
                        for (int x = 0; x < sectorBox.size.x; x++)
                        {
                            if (sectorBox.data[x, y])
                            {
                                int gridX = sectorBox.origo.x - TheGrid.origoX + x;
                                int gridY = sectorBox.origo.y - TheGrid.origoY + y;
                                TheGrid.sectors[gridX, gridY].Add(s);
                                TheGrid.existenceBox.data[gridX, gridY] = true;
                            }
                        }
                    }

                    mesh.vertices  = vertices;
                    mesh.triangles = indices;
                    mesh.normals   = normals;
                    mesh.uv        = uvs;
                    mesh.colors    = colors;

                    mesh.RecalculateBounds();

                    MeshCollider mc = sectorObject.AddComponent <MeshCollider>();
                    mc.sharedMesh = mesh;
                }

                //ceiling
                Triangulator.vertices.Reverse();
                {
                    GameObject sectorObject = new GameObject("Sector_" + index + "_ceiling");
                    s.ceilingObject = sectorObject;
                    sectorObject.transform.SetParent(holder);
                    MeshRenderer mr         = sectorObject.AddComponent <MeshRenderer>();
                    MeshFilter   meshFilter = sectorObject.AddComponent <MeshFilter>();
                    Mesh         mesh       = new Mesh();
                    meshFilter.mesh = mesh;
                    mesh.name       = "Sector_" + index + "_ceiling_mesh";

                    if (!MaterialManager.Instance.OverridesFlat(s.ceilingTexture, sectorObject, mr))
                    {
                        mr.material = MaterialManager.Instance.defaultMaterial;
                    }

                    if (mr.material.mainTexture == null)
                    {
                        MaterialPropertyBlock materialProperties = new MaterialPropertyBlock();
                        materialProperties.SetTexture("_MainTex", TextureLoader.Instance.GetFlatTexture(s.ceilingTexture));
                        mr.SetPropertyBlock(materialProperties);
                    }

                    int vc = Triangulator.vertices.Count;

                    Vector3[] vertices = new Vector3[vc];
                    Vector3[] normals  = new Vector3[vc];
                    Vector2[] uvs      = new Vector2[vc];
                    Color[]   colors   = new Color[vc];
                    int[]     indices  = new int[vc];

                    int v = 0;
                    foreach (Vector2 p in Triangulator.vertices)
                    {
                        vertices[v] = new Vector3(p.x, s.ceilingHeight, p.y);
                        indices[v]  = v;
                        normals[v]  = -Vector3.up;
                        uvs[v]      = new Vector2(p.x / MapLoader.flatUVdividor, 1 - (p.y / MapLoader.flatUVdividor));
                        colors[v]   = Color.white * s.brightness;
                        v++;
                    }

                    mesh.vertices  = vertices;
                    mesh.triangles = indices;
                    mesh.normals   = normals;
                    mesh.uv        = uvs;
                    mesh.colors    = colors;

                    mesh.RecalculateBounds();

                    MeshCollider mc = sectorObject.AddComponent <MeshCollider>();
                    mc.sharedMesh = mesh;
                }

                s.floorObject.sector = s;
                s.floorObject.Init();

                index++;
            }
        }
    }