Inheritance: Asset
Example #1
0
    public void Load(string LEVname)
    {
        _lev = Asset.LoadCached<LEV>(LEVname + ".LEV");
        _pal = Asset.LoadCached<PAL>(_lev.Palette.ToUpper());
        _cmp = Asset.LoadCached<CMP>(LEVname + ".CMP");

        _game.SolidCMP.SetTexture("_PAL", _pal.Texture);
        _game.SolidCMP.SetTexture("_CMP", _cmp.Texture);

        BM.CreateArgs bmCreateArgs = new BM.CreateArgs();
        bmCreateArgs.Pal = _pal;

        if (_game.EmulateCMPShading) {
            bmCreateArgs.TextureFormat = TextureFormat.Alpha8;
            bmCreateArgs.AnisoLevel = 0;
            bmCreateArgs.FilterMode = FilterMode.Point;
            bmCreateArgs.bMipmap = false;
        } else {
            bmCreateArgs.TextureFormat = TextureFormat.RGBA32;
            bmCreateArgs.AnisoLevel = 9;
            bmCreateArgs.FilterMode = FilterMode.Trilinear;
            bmCreateArgs.bMipmap = true;
        }

        foreach (var texName in _lev.Textures) {
            try {
                BM bm = Asset.LoadCached<BM>(texName.ToUpper(), bmCreateArgs);
                _textures.Add(bm);
                if (_defaultTexture == null) {
                    _defaultTexture = bm;
                }
            } catch (System.IO.FileNotFoundException) {
                _textures.Add(null);
            }
        }

        GenerateSectors();
    }
Example #2
0
    // Returns list of triangle indices
    public static List<int> TesselateSector(LEV.Sector sector, int sectorIndex, bool debugDraw = false)
    {
        LinkedList<Seg> segs = new LinkedList<Seg>();
        List<int> verts = new List<int>();
        List<int> counts = new List<int>();

        for (int i = 0; i < sector.Vertices.Count; ++i) {
            verts.Add(i);
            counts.Add(0);
        }

        for (int i = 0; i < sector.Walls.Count; ++i) {
            LEV.Wall wall = sector.Walls[i];

            // is there a reversed seg?
            LinkedListNode<Seg> revSeg = FindSeg(segs, wall.V1, wall.V0);

            if (revSeg != null) {
                // if this wall is an adjoin it overrides the solid wall
                if (wall.Adjoin != -1) {
                    segs.Remove(revSeg);
                } else {
                    continue; // this is a duplicate of either a solid or an existing adjoin.
                }
            }

            Incr(counts, wall.V0, 1);
            Incr(counts, wall.V1, 1);
            segs.AddLast(new Seg(sector, wall.V0, wall.V1, i));
        }

        List<int> tris = new List<int>();

        if (debugDraw) {
            _debugRenderOffset = sector.CeilAlt + 8f;
            _segSteps = new List<List<Seg>>();
            DebugDrawStep(sector, segs, null, null, tris);
            _segSteps.Add(CopySegList(sector, segs));
        }

        for (var node = segs.First; node != null;) {

            List<int> validVerts = new List<int>();
            for (int i = 0; i < counts.Count; ++i) {
                if (counts[i] > 0) {
                    DebugCheck.Assert(counts[i] > 1);
                    validVerts.Add(i);
                }
            }

            verts = validVerts;

            node = MakeSegTri(sector, node, verts, counts, tris, debugDraw);
        }

        if (segs.Count > 0) {
            Debug.LogWarning("Bad floor in sector " + sectorIndex);
        }

        _segSteps = null;

        return tris;
    }
Example #3
0
        public Seg(LEV.Sector sector, int a, int b, int wallIdx)
        {
            IdxA = a;
            IdxB = b;
            WallIdx = wallIdx;

            A = sector.Vertices[a];
            B = sector.Vertices[b];

            LN = B-A;
            LN.Normalize();

            DA = Vector2.Dot(A, LN);
            DB = Vector2.Dot(B, LN);

            DBmDA = DB - DA;

            N = -LN;

            float t = N.x;
            N.x = -N.y;
            N.y = t;

            D = Vector2.Dot(this.A, N);
        }
Example #4
0
    static bool TrySegToVertex(LEV.Sector sector, LinkedList<Seg> segs, Seg seg, int index, List<int> counts, List<int> outTris, bool debugDraw)
    {
        // bad sector: inward facing wall
        if ((FindSeg(segs, seg.IdxA, index) != null) ||
            (FindSeg(segs, index, seg.IdxB) != null)) {
            return false;
        }

        // does this vertex cross any segs?
        Seg addSeg0 = new Seg(sector, seg.IdxA, index, -1);

        foreach (var testSeg in segs) {
            if (seg != testSeg) {
                if (addSeg0.Intersects(testSeg)) {
                    return false;
                }
            }
        }

        Seg addSeg1 = new Seg(sector, index, seg.IdxB, -1);

        foreach (var testSeg in segs) {
            if (seg != testSeg) {
                if (addSeg1.Intersects(testSeg)) {
                    return false;
                }
            }
        }

        if (ContainsAnyVertices(sector, seg, addSeg0, addSeg1)) {
            return false;
        }

        // seg + seg + vertex creates valid triangle
        outTris.Add(seg.IdxA);
        outTris.Add(seg.IdxB);
        outTris.Add(index);

        segs.AddFirst(addSeg0);
        segs.AddFirst(addSeg1);
        segs.Remove(seg);

        Incr(counts, index, 2);

        if (debugDraw) {
            DebugDrawStep(sector, segs, addSeg0, addSeg1, outTris);
            _segSteps.Add(CopySegList(sector, segs));
        }

        return true;
    }
Example #5
0
    static bool TrySegToSeg(LEV.Sector sector, LinkedList<Seg> segs, Seg seg0, Seg seg1, List<int> counts, List<int> outTris, bool debugDraw)
    {
        if (!seg0.InFront(seg1.B)) {
            // concave angle
            return false;
        }

        // does this vertex cross any segs?
        LinkedListNode<Seg> existingSeg = FindSeg(segs, seg1.IdxB, seg0.IdxA);
        Seg addSeg0;

        if (existingSeg == null) {
            if (FindSeg(segs, seg0.IdxA, seg1.IdxB) != null) {
                 // bad-sector: inward facing wall.
                return false;
            }
            addSeg0 = new Seg(sector, seg0.IdxA, seg1.IdxB, -1);
        } else {
            addSeg0 = existingSeg.Value;
        }

        if (existingSeg == null) {
            foreach (var testSeg in segs) {
                if ((seg0 != testSeg) && (seg1 != testSeg)) {
                    if (addSeg0.Intersects(testSeg)) {
                        return false;
                    }
                }
            }
        }

        if (ContainsAnyVertices(sector, seg0, seg1, addSeg0)) {
            return false;
        }

        // seg + seg create valid triangle
        outTris.Add(seg1.IdxA);
        outTris.Add(seg1.IdxB);
        outTris.Add(seg0.IdxA);

        segs.Remove(seg0);
        segs.Remove(seg1);

        if (existingSeg != null) {
            Incr(counts, seg0.IdxA, -2);
            Incr(counts, seg0.IdxB, -2);
            Incr(counts, seg1.IdxB, -2);
            segs.Remove(existingSeg);
            if (debugDraw) {
                DebugDrawStep(sector, segs, null, null, outTris);
                _segSteps.Add(CopySegList(sector, segs));
            }
        } else {
            segs.AddFirst(addSeg0);
            Incr(counts, seg0.IdxB, -2);
            if (debugDraw) {
                DebugDrawStep(sector, segs, addSeg0, null, outTris);
                _segSteps.Add(CopySegList(sector, segs));
            }
        }

        return true;
    }
Example #6
0
    static LinkedListNode<Seg> MakeSegTri(LEV.Sector sector, LinkedListNode<Seg> node, List<int> verts, List<int> counts, List<int> outTris, bool debugDraw)
    {
        LinkedList<Seg> segs = node.List;

        // can we trivially make a triangle from our connected seg?
        List<LinkedListNode<Seg>> connectedSegs = FindConnectedSegs(segs, node.Value, node.Value.IdxB);
        if (connectedSegs == null) {
            // this is a bad seg
            segs.Remove(node);
            return segs.First;
        }

        foreach (var connectedSeg in connectedSegs) {
            if (TrySegToSeg(sector, segs, node.Value, connectedSeg.Value, counts, outTris, debugDraw)) {
                return segs.First;
            }
        }

        connectedSegs = FindConnectedSegs(segs, node.Value, node.Value.IdxA);
        if (connectedSegs == null) {
            // this is a bad seg
            segs.Remove(node);
            return segs.First;
        }
        foreach (var connectedSeg in connectedSegs) {
            if (TrySegToSeg(sector, segs, connectedSeg.Value, node.Value, counts, outTris, debugDraw)) {
                return segs.First;
            }
        }

        int i;
        while ((i=FindVertex(sector, node.Value, verts)) != -1) {
            if (TrySegToVertex(sector, segs, node.Value, i, counts, outTris, debugDraw)) {
                return segs.First;
            } else {
                verts.Remove(i);
            }
        }

        return null;
    }
Example #7
0
    static int FindVertex(LEV.Sector sector, Seg seg, List<int> verts)
    {
        // find closest vertex in front of line
        float bestDist = float.MaxValue;
        int bestIndex = -1;

        foreach (var i in verts) {
            Vector2 p = sector.Vertices[i];

            float d = seg.Distance(p);
            if (d > 0f) {

                float d0 = (p-seg.A).sqrMagnitude;
                float d1 = (p-seg.B).sqrMagnitude;

                d = Mathf.Min(d0, d1);

                if (d < bestDist) {
                    bestIndex = i;
                    bestDist = d;
                }
            }
        }

        return bestIndex;
    }
Example #8
0
    static void DebugDrawStep(LEV.Sector sector, IEnumerable<Seg> newSegs, Seg newSeg0, Seg newSeg1, List<int> outTris)
    {
        foreach (var list in _segSteps) {
            foreach (var seg in list) {
                DrawSeg(seg, Color.green);
            }
        }

        foreach (var seg in newSegs) {
            if ((seg != newSeg0) && (seg != newSeg1)) {
                DrawSeg(seg, Color.red);
            }
        }

        if (outTris.Count >= 3) {
            int idx = outTris.Count - 3;

            Vector2 x = sector.Vertices[outTris[idx]];
            Vector2 y = sector.Vertices[outTris[idx+1]];
            Vector2 z = sector.Vertices[outTris[idx+2]];

            Vector3 a = new Vector3(x.x, _debugRenderOffset, x.y);
            Vector3 b = new Vector3(y.x, _debugRenderOffset, y.y);
            Vector3 c = new Vector3(z.x, _debugRenderOffset, z.y);

            Debug.DrawLine(a, b, Color.yellow, float.MaxValue);
            Debug.DrawLine(b, c, Color.yellow, float.MaxValue);
            Debug.DrawLine(c, a, Color.yellow, float.MaxValue);
        }

        if (newSeg0 != null) {
            Vector3 a = new Vector3(newSeg0.A.x, _debugRenderOffset, newSeg0.A.y);
            Vector3 b = new Vector3(newSeg0.B.x, _debugRenderOffset, newSeg0.B.y);
            Debug.DrawLine(a, b, Color.magenta, float.MaxValue);
        }

        if (newSeg1 != null) {
            Vector3 a = new Vector3(newSeg1.A.x, _debugRenderOffset, newSeg1.A.y);
            Vector3 b = new Vector3(newSeg1.B.x, _debugRenderOffset, newSeg1.B.y);
            Debug.DrawLine(a, b, Color.magenta, float.MaxValue);
        }

        _debugRenderOffset += 16f;
    }
Example #9
0
    static List<Seg> CopySegList(LEV.Sector sector, IEnumerable<Seg> segs)
    {
        List<Seg> newSegs = new List<Seg>();

        foreach (var seg in segs) {
            newSegs.Add(new Seg(sector, seg.IdxA, seg.IdxB, seg.WallIdx));
        }

        return newSegs;
    }
Example #10
0
    static bool ContainsAnyVertices(LEV.Sector sector, Seg seg0, Seg seg1, Seg seg2)
    {
        Vector2 a = sector.Vertices[seg0.IdxA];
        Vector2 b = sector.Vertices[seg0.IdxB];
        Vector2 c;

        if ((seg1.IdxA != seg0.IdxA) && (seg1.IdxA != seg0.IdxB)) {
            c = sector.Vertices[seg1.IdxA];
        } else {
            c = sector.Vertices[seg1.IdxB];
        }

        for (int i = 0; i < sector.Vertices.Count; ++i) {
            if ((seg0.IdxA != i) && (seg0.IdxB != i) &&
                (seg1.IdxA != i) && (seg1.IdxB != i) &&
                (seg2.IdxA != i) && (seg2.IdxB != i)) {

                Vector2 p = sector.Vertices[i];
                if (PointInTriangle(p, a, b, c)) {
                    return true;
                }
            }
        }

        return false;
    }
Example #11
0
    private void UpdateFloorUVs(LEV.Sector sector, BM bm, float shiftX, float shiftY, int ofs, Vector2[] outUVs)
    {
        BM.Frame frame = bm.Frames[0];
        float w = frame.Texture.width;
        float h = frame.Texture.height;
        float rw = frame.WRecip;
        float rh = frame.HRecip;

        for (int i = 0; i < sector.Vertices.Count; ++i) {
            Vector2 v = sector.Vertices[i];
            float s = -(v.x-shiftX)*8f;
            float t = -(v.y-shiftY)*8f;

            outUVs[ofs + i] = new Vector2(s*rw, 1f-(t*rh));
        }
    }
Example #12
0
    private void GenerateSectorFloorsAndCeilings(LEV.Sector sector, int sectorIndex, bool hasFloor, bool hasCeil, ref List<int> outFloorTris, ref List<int> outCeilTris, Vector2[] outUVs, Material[] outMats, bool debugDraw)
    {
        List<int> tess = SectorTess.TesselateSector(sector, sectorIndex, debugDraw);

        int vertOfs = 0;
        int matOfs = 0;

        if (hasFloor) {
            outFloorTris = tess;
            BM bm = _textures[sector.FloorTex] ?? _defaultTexture;
            outMats[0] = new Material(_game.EmulateCMPShading ? _game.SolidCMP : _game.Solid);
            outMats[0].mainTexture = bm.Frames[0].Texture;
            if (_game.EmulateCMPShading) {
                outMats[0].SetFloat("_LightLevel", sector.Ambient);
            }
            UpdateFloorUVs(sector, bm, sector.FloorShiftX, sector.FloorShiftZ, vertOfs, outUVs);
            vertOfs += sector.Vertices.Count;
            ++matOfs;
        }

        if (hasCeil) {
            outCeilTris = new List<int>(tess.Count);
            for (int i = 0; i < tess.Count; i += 3) {
                outCeilTris.Add(tess[i+2] + vertOfs);
                outCeilTris.Add(tess[i+1] + vertOfs);
                outCeilTris.Add(tess[i] + vertOfs);
            }

            BM bm = _textures[sector.CeilTex] ?? _defaultTexture;
            outMats[matOfs] = new Material(_game.EmulateCMPShading ? _game.SolidCMP : _game.Solid);
            outMats[matOfs].mainTexture = bm.Frames[0].Texture;
            if (_game.EmulateCMPShading) {
                outMats[matOfs].SetFloat("_LightLevel", sector.Ambient);
            }
            UpdateFloorUVs(sector, bm, sector.CeilShiftX, sector.CeilShiftZ, vertOfs, outUVs);
        }
    }
Example #13
0
    private bool CheckSector(LEV.Sector sector)
    {
        // all vertices in sector should be shared by at least 2 walls.
        List<int> count = new List<int>(sector.Vertices.Count);
        for (int i = 0; i < sector.Vertices.Count; ++i) {
            count.Add(0);
        }

        foreach (var wall in sector.Walls) {
            count[wall.V0] = count[wall.V0] + 1;
            count[wall.V1] = count[wall.V1] + 1;
        }

        for (int i = 0; i < sector.Vertices.Count; ++i) {
            if (count[i] < 2) {
                return false;
            }
        }

        return true;
    }