void AddSectors() { sectorParent = new GameObject("sectorParent").transform; sectorParent.parent = mapParent; for (int i = 0; i < openedMap.sectors.Count(); i++) //start with a loop for each sector { //if(i != 31) { continue; } SECTORS sector = openedMap.sectors[i]; CreateMapObject(sector, "Sector_" + i, Triangulator.GeneratingGo.Sector); if (sector.isMovingCeiling) { CreateMapObject(sector, sector.isDoor ? ("Sector_" + i + "_Door") : ("Sector_" + i + "_MovingCeiling"), Triangulator.GeneratingGo.Ceiling); } if (sector.isMovingFloor) { CreateMapObject(sector, "Sector_" + i + "_MovingFloor", Triangulator.GeneratingGo.Floor); } } hasOpenedAllDoors = false; }
public static List <SubMesh> CreateWalls(SECTORS sector, WAD wad, GeneratingGo generating) { List <SubMesh> sMeshs = new List <SubMesh>(); foreach (LINEDEFS line in sector.lines) { SECTORS fSector = line.getFrontSector(); SECTORS bSector = line.getBackSector(); // check to see if this line is totally broken if (fSector == null && bSector == null) { continue; } // figure out which sector this wall actually belongs to bool hasBothSectors = (fSector != null && bSector != null); bool genMidWalls = (generating == GeneratingGo.Sector); bool genLowerWalls = hasBothSectors; bool genUpperWalls = hasBothSectors; if (hasBothSectors) { if (sector.isMovingCeiling) { genLowerWalls = genLowerWalls ? (generating != GeneratingGo.Ceiling) : false; genUpperWalls = genUpperWalls ? (generating == GeneratingGo.Ceiling) : false; } if (sector.isMovingFloor) { genLowerWalls = genLowerWalls ? (generating == GeneratingGo.Floor) : false; genUpperWalls = genUpperWalls ? (generating != GeneratingGo.Floor) : false; } } // create all walls if (genMidWalls) { sMeshs.AddRange(CreateMidWalls(sector, line, wad)); } if (genLowerWalls) { sMeshs.AddRange(CreateLowerWalls(sector, line, wad)); } if (genUpperWalls) { sMeshs.AddRange(CreateUpperWalls(sector, line, wad)); } } return(sMeshs); }
public override int[] GetCeilingMovementBound(WAD wad, SECTORS sector) { int[] bound = new int[2]; bound[0] = sector.floorHeight + 8; bound[1] = sector.ceilingHeight; if (bound[1] < bound[0]) { bound[0] = bound[1]; bound[1] = sector.floorHeight + 8; } return(bound); }
void UpdateSectorBounds(SECTORS sector, LINEDEFS line) { if (sector == null) { return; } int[] floorBounds = LineDefTypes.types[line.types].GetFloorMovementBound(reader.newWad, sector); sector.floorBounds[0] = Math.Min(sector.floorBounds[0], floorBounds[0]); sector.floorBounds[1] = Math.Max(sector.floorBounds[1], floorBounds[1]); int[] ceilingBounds = LineDefTypes.types[line.types].GetCeilingMovementBound(reader.newWad, sector); sector.ceilingBounds[0] = Math.Min(sector.ceilingBounds[0], ceilingBounds[0]); sector.ceilingBounds[1] = Math.Max(sector.ceilingBounds[1], ceilingBounds[1]); }
public override int[] GetCeilingMovementBound(WAD wad, SECTORS sector) { int lowestNeighborCeiling = int.MaxValue; sector.neighbors.ForEach(n => lowestNeighborCeiling = Math.Min(lowestNeighborCeiling, n.ceilingHeight)); if (lowestNeighborCeiling == int.MaxValue || (lowestNeighborCeiling - 4) < sector.floorHeight) { return new int[2] { sector.floorHeight, sector.ceilingHeight } } ; else { return new int[2] { sector.floorHeight, lowestNeighborCeiling - 4 } }; } }
public static List <SubMesh> CreateUpperWalls(SECTORS sector, LINEDEFS line, WAD wad) // uppertex { List <SubMesh> walls = new List <SubMesh>(); SECTORS otherSector = (sector == line.getFrontSector()) ? line.getBackSector() : line.getFrontSector(); // figure out how much extra height we have to add to a moving ceiling float[] addMovementHeight = new float[2]; addMovementHeight[0] = Math.Min(Math.Min(sector.ceilingHeight, otherSector.ceilingHeight), sector.ceilingBounds[0]); addMovementHeight[1] = Math.Max(Math.Max(sector.ceilingHeight, otherSector.ceilingHeight), sector.ceilingBounds[1]); // figure out start and end heights float startHeight = sector.ceilingHeight; float endHeight = Math.Max(otherSector.ceilingHeight, sector.ceilingHeight + (addMovementHeight[1] - addMovementHeight[0])); // this is an ugly hack in order to get DOOM2 MAP31 to have correct doors: bool backSectorDoor = line.getBackSector() != null && line.getBackSector().isMovingCeiling; // generate a wall for each textured side if (line.getBackSector() == sector && line.side1 != null && wad.textures.ContainsKey(line.side1.upTex)) { walls.Add(CreateWall(line.getFrontSector(), line, wad.textures[line.side1.upTex], startHeight, endHeight, false, WallType.Upper)); } if (line.getFrontSector() == sector && line.side2 != null && wad.textures.ContainsKey(line.side2.upTex) && !backSectorDoor) { walls.Add(CreateWall(line.getBackSector(), line, wad.textures[line.side2.upTex], startHeight, endHeight, true, WallType.Upper)); } // generate skybox hole textures if (line.getFrontSector() == sector && line.side1 != null && !wad.textures.ContainsKey(line.side1.upTex)) { if (line.getFrontSector().ceilingFlat.StartsWith("F_SKY") && line.getBackSector().ceilingFlat.StartsWith("F_SKY")) { Material texture = wad.flats[sector.ceilingFlat]; walls.Add(CreateWall(line.getFrontSector(), line, texture, startHeight, endHeight, false, WallType.Upper)); } } return(walls); }
public static List <SubMesh> CreateLowerWalls(SECTORS sector, LINEDEFS line, WAD wad) // lowtex { List <SubMesh> walls = new List <SubMesh>(); // figure out start and end heights SECTORS otherSector = (sector == line.getFrontSector()) ? line.getBackSector() : line.getFrontSector(); float startHeight = Math.Min(sector.floorHeight + sector.floorBounds[0] - sector.floorBounds[1], otherSector.floorHeight + otherSector.floorBounds[0] - otherSector.floorBounds[1]); float endHeight = sector.floorHeight; // generate a wall for each textured side if (line.getBackSector() == sector && line.side1 != null && wad.textures.ContainsKey(line.side1.lowTex)) { walls.Add(CreateWall(line.getFrontSector(), line, wad.textures[line.side1.lowTex], startHeight, endHeight, false, WallType.Lower)); } if (line.getFrontSector() == sector && line.side2 != null && wad.textures.ContainsKey(line.side2.lowTex)) { walls.Add(CreateWall(line.getBackSector(), line, wad.textures[line.side2.lowTex], startHeight, endHeight, true, WallType.Lower)); } return(walls); }
public static SubMesh CreateWall(SECTORS sector, LINEDEFS line, Material texture, float startHeight, float endHeight, bool flipped, WallType wallType) { List <Vector3> tmpVerts = new List <Vector3>(); List <Vector2> tmpUv = new List <Vector2>(); SubMesh sMesh = new SubMesh(); sMesh.mesh = new Mesh(); sMesh.mesh.vertices = new Vector3[4]; sMesh.mesh.uv = new Vector2[4]; // create the vertices tmpVerts.Add(new Vector3(line.firstVert.x, startHeight, line.firstVert.z)); tmpVerts.Add(new Vector3(line.firstVert.x, endHeight, line.firstVert.z)); tmpVerts.Add(new Vector3(line.lastVert.x, endHeight, line.lastVert.z)); tmpVerts.Add(new Vector3(line.lastVert.x, startHeight, line.lastVert.z)); // remember things for uv generation SIDEDEFS side = flipped ? line.side2 : line.side1; float xOffset = side.xOfs; float yOffset = side.yOfs; float textureWidth = texture.mainTexture.width; float textureHeight = texture.mainTexture.height; float wallHeight = endHeight - startHeight; float wallWidth = line.getLength(); // check upper and lower unpegged flags bool lowerUnpegged = (wallType == WallType.Upper) ? ((line.flags & 0x0008) == 0) : ((line.flags & 0x0010) != 0); // generate UVs if (lowerUnpegged) { if (wallType == WallType.Lower) { float sectorHeight = sector.ceilingHeight - sector.floorHeight; tmpUv.Add(new Vector2(xOffset / textureWidth, (sectorHeight + yOffset) / textureHeight)); tmpUv.Add(new Vector2(xOffset / textureWidth, (sectorHeight - wallHeight + yOffset) / textureHeight)); tmpUv.Add(new Vector2((wallWidth + xOffset) / textureWidth, (sectorHeight - wallHeight + yOffset) / textureHeight)); tmpUv.Add(new Vector2((wallWidth + xOffset) / textureWidth, (sectorHeight + yOffset) / textureHeight)); } else { tmpUv.Add(new Vector2(xOffset / textureWidth, (textureHeight + yOffset) / textureHeight)); tmpUv.Add(new Vector2(xOffset / textureWidth, (textureHeight - wallHeight + yOffset) / textureHeight)); tmpUv.Add(new Vector2((wallWidth + xOffset) / textureWidth, (textureHeight - wallHeight + yOffset) / textureHeight)); tmpUv.Add(new Vector2((wallWidth + xOffset) / textureWidth, (textureHeight + yOffset) / textureHeight)); } } else { tmpUv.Add(new Vector2(xOffset / textureWidth, (wallHeight + yOffset) / textureHeight)); tmpUv.Add(new Vector2(xOffset / textureWidth, yOffset / textureHeight)); tmpUv.Add(new Vector2((wallWidth + xOffset) / textureWidth, yOffset / textureHeight)); tmpUv.Add(new Vector2((wallWidth + xOffset) / textureWidth, (wallHeight + yOffset) / textureHeight)); } // set mesh data sMesh.mesh.uv = tmpUv.ToArray(); sMesh.mesh.vertices = tmpVerts.ToArray(); sMesh.material = texture; if (flipped) { sMesh.mesh.triangles = new int[6] { 2, 1, 0, 0, 3, 2 }; sMesh.mesh.normals = new Vector3[4] { -line.frontVector(), -line.frontVector(), -line.frontVector(), -line.frontVector() }; } else { sMesh.mesh.triangles = new int[6] { 0, 1, 2, 2, 3, 0 }; sMesh.mesh.normals = new Vector3[4] { line.frontVector(), line.frontVector(), line.frontVector(), line.frontVector() }; } return(sMesh); }
public static List <SubMesh> CreateMidWalls(SECTORS sector, LINEDEFS line, WAD wad) // midtex { float startHeight = 0; float endHeight = 0; // figure out start and end heights if (line.getFrontSector() != null && line.getBackSector() != null) { startHeight = Math.Max(line.getFrontSector().floorHeight, line.getBackSector().floorHeight); endHeight = Math.Min(line.getFrontSector().ceilingHeight, line.getBackSector().ceilingHeight); } else if (line.getFrontSector() != null && line.getBackSector() == null) { SECTORS fSector = line.getFrontSector(); startHeight = fSector.floorHeight; endHeight = fSector.ceilingHeight; if (fSector.isMovingCeiling) { endHeight = fSector.ceilingBounds[1]; } if (fSector.isMovingFloor) { startHeight = Math.Min(startHeight, fSector.floorBounds[0]); endHeight = Math.Max(endHeight, fSector.floorBounds[1]); } } else if (line.getFrontSector() == null && line.getBackSector() != null) { startHeight = line.getBackSector().floorHeight; endHeight = line.getBackSector().ceilingHeight; } // generate a wall for each textured side List <SubMesh> walls = new List <SubMesh>(); if (line.getFrontSector() == sector && line.side1 != null && wad.textures.ContainsKey(line.side1.midTex)) { Material texture = wad.textures[line.side1.midTex]; if (line.getFrontSector() != null && line.getBackSector() != null) { endHeight = Math.Min(startHeight + texture.mainTexture.height, endHeight); //dont tile middle textures with 2 sides } walls.Add(CreateWall(line.getFrontSector(), line, texture, startHeight, endHeight, false, WallType.Middle)); } if (line.getBackSector() == sector && line.side2 != null && wad.textures.ContainsKey(line.side2.midTex)) { Material texture = wad.textures[line.side2.midTex]; if (line.getFrontSector() != null && line.getBackSector() != null) { endHeight = Math.Min(startHeight + texture.mainTexture.height, endHeight); //dont tile middle textures with 2 sides } walls.Add(CreateWall(line.getBackSector(), line, texture, startHeight, endHeight, true, WallType.Middle)); } // generate skybox hole textures if (line.getFrontSector() == sector && line.side1 != null && !wad.textures.ContainsKey(line.side1.midTex) && sector.ceilingFlat.StartsWith("F_SKY")) { SECTORS bSector = line.getBackSector(); if (bSector == null || (bSector.floorHeight == bSector.ceilingHeight && !bSector.isMovingCeiling && !bSector.isMovingFloor)) { Material texture = wad.flats[sector.ceilingFlat]; startHeight = line.getFrontSector().floorHeight; endHeight = line.getFrontSector().ceilingHeight; walls.Add(CreateWall(line.getFrontSector(), line, texture, startHeight, endHeight, false, WallType.Middle)); } } return(walls); }
public static SubMesh CreateCeiling(SubMesh floor, SECTORS sector, Material mat, GeneratingGo generating) { if (sector.isMovingFloor && generating == GeneratingGo.Floor) { return(null); } if (sector.isMovingFloor && generating != GeneratingGo.Floor) { floor = CreateFloor(sector, mat, GeneratingGo.Floor); } if (sector.isMovingCeiling && generating != GeneratingGo.Ceiling) { return(null); } if (sector.isMovingCeiling && generating == GeneratingGo.Ceiling) { floor = CreateFloor(sector, mat, sector.isMovingFloor ? GeneratingGo.Floor : GeneratingGo.Sector); } //reverse Mesh ceiling = new Mesh(); List <Vector3> tmpVerts = new List <Vector3>(floor.mesh.vertices); List <Vector2> tmpUvs = new List <Vector2>(floor.mesh.uv); List <int> tmpTris = new List <int>(floor.mesh.triangles); List <Vector3> tmpNrm = new List <Vector3>(floor.mesh.normals); for (int a = 0; a < tmpVerts.Count; a++) { tmpVerts[a] = new Vector3(tmpVerts[a].x, sector.ceilingHeight, tmpVerts[a].z); //change height for ceiling tmpNrm[a] = Vector3.down; } for (int i = 0; i < tmpTris.Count; i += 3) { int tri = tmpTris[i]; tmpTris[i] = tmpTris[i + 2]; tmpTris[i + 2] = tri; } ceiling.vertices = tmpVerts.ToArray(); ceiling.uv = tmpUvs.ToArray(); ceiling.triangles = tmpTris.ToArray(); ceiling.normals = tmpNrm.ToArray(); SubMesh newSubMesh = new SubMesh(); newSubMesh.mesh = ceiling; newSubMesh.material = mat; return(newSubMesh); }
void fillInfo(DoomMap map) { // find and remember each sector's tag and index map.sectorsByTag.Clear(); for (int i = 0; i < map.sectors.Count; i++) { SECTORS sector = map.sectors[i]; sector.lines.Clear(); sector.otherLines.Clear(); sector.sectorIndex = i; if (sector.sectorTag == 0) { continue; } if (!map.sectorsByTag.ContainsKey(sector.sectorTag)) { map.sectorsByTag.Add(sector.sectorTag, new List <SECTORS> { sector }); } else { map.sectorsByTag[sector.sectorTag].Add(sector); } } // set sector's default movement bounds foreach (SECTORS sector in map.sectors) { sector.floorBounds = new int[2] { sector.floorHeight, sector.floorHeight }; sector.ceilingBounds = new int[2] { sector.ceilingHeight, sector.ceilingHeight }; } foreach (LINEDEFS line in map.linedefs) { line.map = map; line.getVerts(); //store the vertex information inside the linedef line.getSidedefs(); //store the sidedefs in the linedef for easier access SECTORS front = line.getFrontSector(); SECTORS back = line.getBackSector(); // tag dynamic sectors if (LineDefTypes.types.ContainsKey(line.types)) { switch (LineDefTypes.types[line.types].category) { case LineDefTypes.Category.Door: LineDefTypes.LineDefDoorType doorType = (LineDefTypes.types[line.types] as LineDefTypes.LineDefDoorType); // tag door sectors if (doorType.isLocal() && back != null) { back.isMovingCeiling = true; back.isDoor = true; } else if (!doorType.isLocal() && map.sectorsByTag.ContainsKey(line.tag)) { map.sectorsByTag[line.tag].ForEach(x => x.isMovingCeiling = true); map.sectorsByTag[line.tag].ForEach(x => x.isDoor = true); } break; case LineDefTypes.Category.Floor: // tag floor sectors if (map.sectorsByTag.ContainsKey(line.tag)) { map.sectorsByTag[line.tag].ForEach(x => x.isMovingFloor = true); } break; case LineDefTypes.Category.Lift: // tag lift sectors if (map.sectorsByTag.ContainsKey(line.tag)) { map.sectorsByTag[line.tag].ForEach(x => x.isMovingFloor = true); } break; case LineDefTypes.Category.Ceiling: // tag ceiling sectors if (map.sectorsByTag.ContainsKey(line.tag)) { map.sectorsByTag[line.tag].ForEach(x => x.isMovingCeiling = true); } break; case LineDefTypes.Category.Crusher: // tag crusher sectors if (map.sectorsByTag.ContainsKey(line.tag)) { map.sectorsByTag[line.tag].ForEach(x => x.isMovingCeiling = true); } break; } } if (front == null && back == null) //if this line is BROKEN { continue; //we ignore it } else if (front == back) //if the front and the back are the same, it is inside a single sector { //if the line is internal to the sector, theres a special place in the sector class for them front.otherLines.Add(line); } else if (front != null) //if the front is defined, add the front { front.lines.Add(line); if (back != null) { back.lines.Add(line);//add the line to the sector on its back as well..if it exists } } else { back.lines.Add(line); //if all else fails, the line must be backwards } } // find and remember each sector's neighboring sectors foreach (SECTORS sector in map.sectors) { foreach (LINEDEFS line in sector.lines) { if (line.getFrontSector() != sector && line.getFrontSector() != null && !sector.neighbors.Contains(line.getFrontSector())) { sector.neighbors.Add(line.getFrontSector()); } if (line.getBackSector() != sector && line.getBackSector() != null && !sector.neighbors.Contains(line.getBackSector())) { sector.neighbors.Add(line.getBackSector()); } } } //set sector's movement bounds foreach (LINEDEFS line in map.linedefs) { if (!LineDefTypes.types.ContainsKey(line.types)) { continue; } if (LineDefTypes.types[line.types].category == LineDefTypes.Category.Door) { LineDefTypes.LineDefDoorType doorType = LineDefTypes.types[line.types] as LineDefTypes.LineDefDoorType; if (doorType.isLocal()) { UpdateSectorBounds(line.getBackSector(), line); continue; } } if (line.tag != 0 && map.sectorsByTag.ContainsKey(line.tag)) { foreach (SECTORS sector in map.sectorsByTag[line.tag]) { UpdateSectorBounds(sector, line); } } } }
static void RepairSector(SECTORS sector, List <Line> lines) { if (lines.Count < 2) { // sector with a single line, don't repair return; } // generate a list of all vertices List <Vertex> vertices = new List <Vertex>(); foreach (Line line in lines) { if (!vertices.Contains(line.vertices[0])) { vertices.Add(line.vertices[0]); } if (!vertices.Contains(line.vertices[1])) { vertices.Add(line.vertices[1]); } } // find all vertices that only have one line List <Vertex> loneVertices = new List <Vertex>(); foreach (Vertex vertex in vertices) { int count = 0; foreach (Line line in lines) { if (line.vertices.Contains(vertex)) { count++; } } if (count < 2) { loneVertices.Add(vertex); } } if (loneVertices.Count == 0) { // nothing wrong here return; } Debug.Log("BAD SECTOR: " + sector.sectorIndex); // find lines that intersect foreach (Line line1 in lines) { foreach (Line line2 in lines) { if (line1 == line2) { continue; } Vertex intersect = line1.Intersection(line2); if (intersect == null) { continue; } Debug.Log("REPAIRING: intersection, SECTOR: " + sector.sectorIndex); // find closest vertex to intersection point Vertex closestVertex = line1.vertices[0]; foreach (Vertex vertex in line1.vertices) { if (vertex.DistanceTo(intersect) < closestVertex.DistanceTo(intersect)) { closestVertex = vertex; } } foreach (Vertex vertex in line2.vertices) { if (vertex.DistanceTo(intersect) < closestVertex.DistanceTo(intersect)) { closestVertex = vertex; } } // move closest to intersection point closestVertex.x = intersect.x; closestVertex.y = intersect.y; // replace closest line1 vertex with closest vertex if (line1.vertices[0].DistanceTo(intersect) < line1.vertices[1].DistanceTo(intersect)) { line1.vertices[0] = closestVertex; loneVertices.Remove(line1.vertices[0]); } else { line1.vertices[1] = closestVertex; loneVertices.Remove(line1.vertices[1]); } // replace closest line2 vertex with closest vertex if (line2.vertices[0].DistanceTo(intersect) < line2.vertices[1].DistanceTo(intersect)) { line2.vertices[0] = closestVertex; loneVertices.Remove(line2.vertices[0]); } else { line2.vertices[1] = closestVertex; loneVertices.Remove(line2.vertices[1]); } } } if (loneVertices.Count == 0) { // sector was repaired return; } // generate every combination of vertices in pairs SortedList <double, VertexPair> pairs = new SortedList <double, VertexPair>(); foreach (Vertex v1 in loneVertices) { foreach (Vertex v2 in loneVertices) { if (v1 == v2) { continue; } // make sure pair is unique foreach (VertexPair pair in pairs.Values) { if (pair.vertices.Contains(v1) && pair.vertices.Contains(v2)) { goto nextPair; } } VertexPair vertexPair = new VertexPair(v1, v2); double dist = vertexPair.Distance(); while (pairs.ContainsKey(dist)) { dist += 0.001; } pairs.Add(dist, vertexPair); nextPair :; } } // generate a line for every pair, sorted by distance while (pairs.Count > 0) { // grab a pair with the least distance between them VertexPair pair = pairs.Values.First(); pairs.RemoveAt(0); // generate the line between the two vertices Line line = new Line(pair.vertices[0], pair.vertices[1], false, false); // check for collision foreach (Line line2 in lines) { if (line.Intersects(line2)) { goto nextPair; } } // add the line to the list lines.Add(line); Debug.Log("REPAIRING: missing line, SECTOR: " + sector.sectorIndex); Debug.DrawLine(new Vector3((float)pair.vertices[0].x, 0, (float)pair.vertices[0].y), new Vector3((float)pair.vertices[1].x, 0, (float)pair.vertices[1].y), Color.red, 10000); // remove any pairs that contain a shared vertex to this one for (int i = 0; i < pairs.Count; i++) { if (pairs.Values[i].vertices.Contains(pair.vertices[0]) || pairs.Values[i].vertices.Contains(pair.vertices[1])) { pairs.RemoveAt(i); i--; continue; } } nextPair :; } }
// This class is the actual triangulator, you feed it a list of linedefs and it spits out triangles public static SubMesh CreateFloor(SECTORS sector, Material mat, GeneratingGo generating) { if (sector.isMovingCeiling && generating == GeneratingGo.Ceiling) { return(null); } if (sector.isMovingFloor && generating != GeneratingGo.Floor) { return(null); } Mesh mesh = new Mesh(); VertexPool vertexPool = new VertexPool(); List <Triangle2D> triangles = new List <Triangle2D>(); List <Line> lines = new List <Line>(); // convert linedefs to lines foreach (LINEDEFS linedef in sector.lines) { Vertex v1 = vertexPool.Get(linedef.firstVert.x, linedef.firstVert.z); Vertex v2 = vertexPool.Get(linedef.lastVert.x, linedef.lastVert.z); if (linedef.getFrontSector() == sector) { lines.Add(new Line(v1, v2, true, false)); } else { lines.Add(new Line(v1, v2, true, true)); } } // walk lines to make sure the sector isn't broken RepairSector(sector, lines); // go through every line and attach it to every other vertex. // reject the triangle if it isn't valid List <Line> unmarked = new List <Line>(lines); // ignore all initial lines that do not come from a linedef for (int i = 0; i < unmarked.Count; i++) { Line line = unmarked[i]; if (!line.fromLinedef) { unmarked.RemoveAt(i); i--; } } while (unmarked.Count > 0) { Line line = unmarked.Last(); unmarked.Remove(line); CreateTriangle(line, lines, unmarked, triangles, vertexPool.vertices); } List <Vector3> vertices = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <Vector3> normals = new List <Vector3>(); foreach (Vertex vertex in vertexPool.vertices) { vertices.Add(new Vector3((float)vertex.x, sector.floorHeight, (float)vertex.y)); uvs.Add(new Vector2((float)vertex.x / 64f, (float)vertex.y / 64f)); normals.Add(Vector3.up); } List <int> triangleIndices = new List <int>(); foreach (Triangle2D triangle in triangles) { double mx = (triangle.vertices[0].x + triangle.vertices[1].x + triangle.vertices[2].x) / 3f; double my = (triangle.vertices[0].y + triangle.vertices[1].y + triangle.vertices[2].y) / 3f; SortedList <double, Vertex> sorted = new SortedList <double, Vertex>(); foreach (Vertex vertex in triangle.vertices) { double theta = Math.Atan2(my - vertex.y, mx - vertex.x); //while (sorted.ContainsKey(theta)) { theta += 0.1; } // maybe needed? sorted.Add(theta, vertex); } triangleIndices.Add(vertexPool.vertices.IndexOf(sorted.Values[2])); triangleIndices.Add(vertexPool.vertices.IndexOf(sorted.Values[1])); triangleIndices.Add(vertexPool.vertices.IndexOf(sorted.Values[0])); } mesh.Clear(); mesh.vertices = vertices.ToArray(); mesh.uv = uvs.ToArray(); mesh.triangles = triangleIndices.ToArray(); mesh.normals = normals.ToArray(); SubMesh newSubMesh = new SubMesh(); newSubMesh.mesh = mesh; newSubMesh.material = mat; return(newSubMesh); }
private GameObject CreateMapObject(SECTORS sector, string name, Triangulator.GeneratingGo generating) { //create lists for combining floor and ceiling meshes List <SubMesh> sectorMeshes = new List <SubMesh>(); Material[] sectorMaterials = new Material[2]; //theres a material for the floor and the ceiling //create floor SubMesh floor = Triangulator.CreateFloor(sector, reader.newWad.flats[sector.floorFlat], generating); sectorMeshes.Add(floor); //create ceiling sectorMeshes.Add(Triangulator.CreateCeiling(floor, sector, reader.newWad.flats[sector.ceilingFlat], generating)); //set the skybox's texture //DOOM2 SPECIFIC!!!! if (mapSelected <= 11) { Texture2D newSky = (Texture2D)reader.newWad.textures["SKY1"].mainTexture; sky = newSky; skybox.GetComponent <MeshRenderer>().material.SetColor("_LowerFogColor", AverageColorTop(newSky)); skybox.GetComponent <MeshRenderer>().material.SetColor("_UpperFogColor", AverageColorBottom(newSky)); } else if (mapSelected > 11 && mapSelected <= 20) { Texture2D newSky = (Texture2D)reader.newWad.textures["SKY2"].mainTexture; sky = newSky; skybox.GetComponent <MeshRenderer>().material.SetColor("_LowerFogColor", AverageColorTop(newSky)); skybox.GetComponent <MeshRenderer>().material.SetColor("_UpperFogColor", AverageColorBottom(newSky)); } else if (mapSelected > 20 && mapSelected <= 32) { Texture2D newSky = (Texture2D)reader.newWad.textures["SKY3"].mainTexture; sky = newSky; skybox.GetComponent <MeshRenderer>().material.SetColor("_LowerFogColor", AverageColorTop(newSky)); skybox.GetComponent <MeshRenderer>().material.SetColor("_UpperFogColor", AverageColorBottom(newSky)); } //create walls sectorMeshes.AddRange(Triangulator.CreateWalls(sector, reader.newWad, generating)); //remove null submeshes sectorMeshes.RemoveAll(x => x == null); //combine the meshes Mesh mesh = new Mesh(); Triangulator.CombineAsMesh(ref mesh, sectorMeshes, ref sectorMaterials); Renderer rend; MaterialPropertyBlock propBlock = new MaterialPropertyBlock(); //Setup GameObject GameObject go = new GameObject(); go.AddComponent <MeshFilter>(); go.AddComponent <MeshRenderer>(); go.name = name; go.transform.parent = sectorParent; //Set up some variables rend = go.GetComponent <Renderer>(); //Set the color for the material independently (for setting light level) propBlock.SetColor("_Color", new Color(sector.lightLevel / 255f, sector.lightLevel / 255f, sector.lightLevel / 255f, 1)); rend.SetPropertyBlock(propBlock); //fill in the materials and mesh for the gameobject go.GetComponent <MeshRenderer>().materials = sectorMaterials; go.GetComponent <MeshFilter>().mesh = mesh; go.AddComponent <MeshCollider>(); foreach (Material mat in go.GetComponent <MeshRenderer>().materials) { foreach (string str in AnimatedTextures.Keys) { if (AnimatedTextures[str].Contains(mat.mainTexture.name) && go.GetComponent <TextureAnimator>() == null) { TextureAnimator texAnim = go.AddComponent <TextureAnimator>(); texAnim.wad = reader.newWad; break; } } } go.tag = "Map"; return(go); }
void ReadMAPEntries() { for (int i = 0; i < newWad.directory.Count - 1; i++) { if (newWad.directory[i + 1].name.Contains("THINGS") && newWad.directory[i].size == 0) { DoomMap newMap = new DoomMap(); DrctEntry dirEntry = newWad.directory[i]; newMap.name = dirEntry.name; //THINGS lump if (newWad.directory[i + 1].name.Contains("THINGS")) { byte[] thingBytes = new byte[newWad.directory[i + 1].size]; wadOpener.Position = newWad.directory[i + 1].filepos; wadOpener.Read(thingBytes, 0, thingBytes.Length); for (int j = 0; j < newWad.directory[i + 1].size; j += 10) { THINGS newThing = new THINGS(); newThing.xPos = BitConverter.ToInt16(thingBytes, j + 0); newThing.yPos = BitConverter.ToInt16(thingBytes, j + 2); newThing.angle = BitConverter.ToInt16(thingBytes, j + 4); newThing.thingType = BitConverter.ToInt16(thingBytes, j + 6); newThing.thingOptions = BitConverter.ToInt16(thingBytes, j + 8); newMap.things.Add(newThing); } } //LINEDEEFS lump if (newWad.directory[i + 2].name.Contains("LINEDEFS")) { byte[] lineDefBytes = new byte[newWad.directory[i + 2].size]; wadOpener.Position = newWad.directory[i + 2].filepos; wadOpener.Read(lineDefBytes, 0, lineDefBytes.Length); for (int j = 0; j < newWad.directory[i + 2].size; j += 14) { LINEDEFS newLineDef = new LINEDEFS(); newLineDef.firstVertIndex = BitConverter.ToInt16(lineDefBytes, j + 0); newLineDef.lastVertIndex = BitConverter.ToInt16(lineDefBytes, j + 2); newLineDef.flags = BitConverter.ToInt16(lineDefBytes, j + 4); newLineDef.types = BitConverter.ToInt16(lineDefBytes, j + 6); newLineDef.tag = BitConverter.ToInt16(lineDefBytes, j + 8); newLineDef.side1Index = BitConverter.ToInt16(lineDefBytes, j + 10); newLineDef.side2Index = BitConverter.ToInt16(lineDefBytes, j + 12); newMap.linedefs.Add(newLineDef); } } //SIDEDEFS lump if (newWad.directory[i + 3].name.Contains("SIDEDEFS")) { byte[] sideDefBytes = new byte[newWad.directory[i + 3].size]; wadOpener.Position = newWad.directory[i + 3].filepos; wadOpener.Read(sideDefBytes, 0, sideDefBytes.Length); for (int j = 0; j < newWad.directory[i + 3].size; j += 30) { SIDEDEFS newSideDef = new SIDEDEFS(); newSideDef.xOfs = BitConverter.ToInt16(sideDefBytes, j + 0); newSideDef.yOfs = BitConverter.ToInt16(sideDefBytes, j + 2); newSideDef.upTex = new String(System.Text.Encoding.ASCII.GetChars(sideDefBytes, j + 4, 8)).ToUpper(); newSideDef.lowTex = new String(System.Text.Encoding.ASCII.GetChars(sideDefBytes, j + 12, 8)).ToUpper(); newSideDef.midTex = new String(System.Text.Encoding.ASCII.GetChars(sideDefBytes, j + 20, 8)).ToUpper(); newSideDef.secNum = BitConverter.ToInt16(sideDefBytes, j + 28); newSideDef.upTex = newSideDef.upTex.Replace("\0", ""); newSideDef.lowTex = newSideDef.lowTex.Replace("\0", ""); newSideDef.midTex = newSideDef.midTex.Replace("\0", ""); newMap.sidedefs.Add(newSideDef); } } //VERTEXES lump if (newWad.directory[i + 4].name.Contains("VERTEXES")) { byte[] vertexBytes = new byte[newWad.directory[i + 4].size]; wadOpener.Position = newWad.directory[i + 4].filepos; wadOpener.Read(vertexBytes, 0, vertexBytes.Length); for (int j = 0; j < newWad.directory[i + 4].size; j += 4) { Vector3 newVertex = new Vector3(0, 0, 0); newVertex.x = BitConverter.ToInt16(vertexBytes, j + 0); newVertex.z = BitConverter.ToInt16(vertexBytes, j + 2); newMap.vertexes.Add(newVertex); } } //SECTORS lump if (newWad.directory[i + 8].name.Contains("SECTORS")) { byte[] secBytes = new byte[newWad.directory[i + 8].size]; wadOpener.Position = newWad.directory[i + 8].filepos; wadOpener.Read(secBytes, 0, secBytes.Length); for (int j = 0; j < newWad.directory[i + 8].size; j += 26) { SECTORS newSec = new SECTORS(); newSec.floorHeight = BitConverter.ToInt16(secBytes, j + 0); newSec.ceilingHeight = BitConverter.ToInt16(secBytes, j + 2); newSec.floorFlat = new String(System.Text.Encoding.ASCII.GetChars(secBytes, j + 4, 8)); newSec.ceilingFlat = new String(System.Text.Encoding.ASCII.GetChars(secBytes, j + 12, 8)); newSec.lightLevel = BitConverter.ToInt16(secBytes, j + 20); newSec.specialSec = BitConverter.ToInt16(secBytes, j + 22); newSec.sectorTag = BitConverter.ToInt16(secBytes, j + 24); newSec.floorFlat = newSec.floorFlat.Replace("\0", ""); newSec.ceilingFlat = newSec.ceilingFlat.Replace("\0", ""); newMap.sectors.Add(newSec); } } //BLOCKMAPS lump if (newWad.directory[i + 10].name.Contains("BLOCKMAP")) { byte[] blockBytes = new byte[newWad.directory[i + 10].size]; wadOpener.Position = newWad.directory[i + 10].filepos; wadOpener.Read(blockBytes, 0, blockBytes.Length); BLOCKMAP newBlockmap = new BLOCKMAP(); newBlockmap.xcoord = BitConverter.ToInt16(blockBytes, 0); newBlockmap.ycoord = BitConverter.ToInt16(blockBytes, 2); newBlockmap.numColumns = BitConverter.ToInt16(blockBytes, 4); newBlockmap.numRows = BitConverter.ToInt16(blockBytes, 6); int N = newBlockmap.numColumns * newBlockmap.numRows; //Offsets for (int j = 8; j < (8 + (2 * (N - 1))); j += 2) // (8 + (2 * (N - 1))) IS DEFINITELY RIGHT { newBlockmap.Offsets.Add(BitConverter.ToUInt16(blockBytes, j) * 2); //multiply this times 2 so its right } foreach (int offset in newBlockmap.Offsets) { int line = 0; int blockOffset = offset; // List<int> newBlock = new List<int>(); Block blk = new Block(); do { line = BitConverter.ToUInt16(blockBytes, blockOffset + 2); //newBlock.Add(line); if (line == 0xFFFF) { continue; } blk.lines.Add(newMap.linedefs[line]); blockOffset += 2; } while (line != 0xFFFF); newBlockmap.blocks.Add(blk); } newMap.blockmap = newBlockmap; } newWad.maps.Add(newMap); //Store the map in newWad } } }
public override int[] GetFloorMovementBound(WAD wad, SECTORS sector) { int[] bound = new int[2]; switch (target) { case FloorTarget.LowestNeighborFloor: if (direction == Direction.Up) { throw new Exception("Unexpected LineDefFloorType direction!"); } bound[0] = sector.floorHeight; sector.neighbors.ForEach(n => bound[0] = Math.Min(bound[0], n.floorHeight)); bound[1] = sector.floorHeight; break; case FloorTarget.NextNeighborFloor: if (direction == Direction.Up) { bound[0] = sector.floorHeight; bound[1] = sector.floorHeight; if (repeatable == Repeatable.Multiple) { sector.neighbors.ForEach(n => bound[1] = Math.Max(bound[1], n.floorHeight)); } else { int height = int.MaxValue; sector.neighbors.ForEach(n => height = (n.floorHeight > sector.floorHeight) ? Math.Min(height, n.floorHeight) : height); if (height < int.MaxValue) { bound[1] = height; } } } else if (direction == Direction.Down) { bound[0] = sector.floorHeight; bound[1] = sector.floorHeight; if (repeatable == Repeatable.Multiple) { sector.neighbors.ForEach(n => bound[0] = Math.Min(bound[0], n.floorHeight)); } else { int height = int.MaxValue; sector.neighbors.ForEach(n => height = (n.floorHeight < sector.floorHeight) ? Math.Max(height, n.floorHeight) : height); if (height < int.MaxValue) { bound[0] = height; } } } break; case FloorTarget.LowestNeighborCeiling: if (direction == Direction.Down) { throw new Exception("Unexpected LineDefFloorType direction!"); } bound[0] = sector.floorHeight; bound[1] = sector.ceilingHeight; sector.neighbors.ForEach(n => bound[1] = Math.Min(bound[1], n.ceilingHeight)); break; case FloorTarget.LowestNeighborCeilingMinus8: if (direction == Direction.Down) { throw new Exception("Unexpected LineDefFloorType direction!"); } bound[0] = sector.floorHeight; bound[1] = sector.ceilingHeight - 8; sector.neighbors.ForEach(n => bound[1] = Math.Min(bound[1], n.ceilingHeight - 8)); break; case FloorTarget.HighestNeighborFloor: if (direction == Direction.Up) { throw new Exception("Unexpected LineDefFloorType direction!"); } bound[0] = -32000; sector.neighbors.ForEach(n => bound[0] = Math.Max(bound[0], n.floorHeight)); bound[1] = sector.floorHeight; break; case FloorTarget.HighestNeighborFloorPlus8: if (direction == Direction.Up) { throw new Exception("Unexpected LineDefFloorType direction!"); } bound[0] = -32000 + 8; sector.neighbors.ForEach(n => bound[0] = Math.Max(bound[0], n.floorHeight + 8)); bound[1] = sector.floorHeight; break; case FloorTarget.Ceiling: if (direction == Direction.Down) { throw new Exception("Unexpected LineDefFloorType direction!"); } bound[0] = sector.floorHeight; bound[1] = sector.ceilingHeight; break; case FloorTarget.Absolute24: if (direction == Direction.Down) { throw new Exception("Unexpected LineDefFloorType direction!"); } bound[0] = sector.floorHeight; bound[1] = (repeatable == Repeatable.Multiple) ? sector.ceilingHeight : sector.floorHeight + 24; break; case FloorTarget.Absolute32: if (direction == Direction.Down) { throw new Exception("Unexpected LineDefFloorType direction!"); } bound[0] = sector.floorHeight; bound[1] = (repeatable == Repeatable.Multiple) ? sector.ceilingHeight : sector.floorHeight + 32; break; case FloorTarget.Absolute512: if (direction == Direction.Down) { throw new Exception("Unexpected LineDefFloorType direction!"); } bound[0] = sector.floorHeight; bound[1] = (repeatable == Repeatable.Multiple) ? sector.ceilingHeight : sector.floorHeight + 512; break; case FloorTarget.AbsShortestLowerTexture: if (direction == Direction.Down) { throw new Exception("Unexpected LineDefFloorType direction!"); } bound[0] = sector.floorHeight; bound[1] = sector.floorHeight; int texHeight = int.MaxValue; foreach (LINEDEFS line in sector.lines) { if (line.side1 != null && wad.textures.ContainsKey(line.side1.lowTex)) { texHeight = Math.Min(texHeight, wad.textures[line.side1.lowTex].mainTexture.height); } if (line.side2 != null && wad.textures.ContainsKey(line.side2.lowTex)) { texHeight = Math.Min(texHeight, wad.textures[line.side2.lowTex].mainTexture.height); } } if (texHeight < int.MaxValue) { bound[1] = (repeatable == Repeatable.Multiple) ? sector.ceilingHeight : sector.floorHeight + texHeight; } break; case FloorTarget.None: bound[0] = sector.floorHeight; bound[1] = sector.ceilingHeight; break; default: throw new Exception("Unexpected LineDefFloorType target!"); } return(bound); }
public override int[] GetCeilingMovementBound(WAD wad, SECTORS sector) { int[] bound = new int[2]; switch (target) { case CeilingTarget.HighestNeighborCeiling: if (direction == Direction.Down) { throw new Exception("Unexpected LineDefCeilingType direction!"); } bound[0] = sector.ceilingHeight; bound[1] = -32000; sector.neighbors.ForEach(n => bound[1] = Math.Max(bound[1], n.ceilingHeight)); if (bound[1] < bound[0]) { bound[0] = bound[1]; bound[1] = sector.ceilingHeight; } break; case CeilingTarget.LowestNeighborCeiling: if (direction == Direction.Up) { throw new Exception("Unexpected LineDefCeilingType direction!"); } bound[0] = 32000; bound[1] = sector.ceilingHeight; sector.neighbors.ForEach(n => bound[0] = Math.Min(bound[0], n.ceilingHeight)); if (bound[1] < bound[0]) { bound[1] = bound[0]; bound[0] = sector.ceilingHeight; } break; case CeilingTarget.HighestNeighborFloor: if (direction == Direction.Up) { throw new Exception("Unexpected LineDefCeilingType direction!"); } bound[0] = Math.Max(sector.floorHeight, -32000); sector.neighbors.ForEach(n => bound[0] = Math.Max(bound[0], n.floorHeight)); bound[1] = sector.ceilingHeight; if (bound[1] < bound[0]) { bound[1] = bound[0]; bound[0] = sector.ceilingHeight; } break; case CeilingTarget.Floor: if (direction == Direction.Up) { throw new Exception("Unexpected LineDefCeilingType direction!"); } bound[0] = sector.floorHeight; bound[1] = sector.ceilingHeight; if (bound[1] < bound[0]) { bound[1] = bound[0]; bound[0] = sector.ceilingHeight; } break; case CeilingTarget.FloorPlus8: if (direction == Direction.Up) { throw new Exception("Unexpected LineDefCeilingType direction!"); } bound[0] = sector.floorHeight + 8; bound[1] = sector.ceilingHeight; if (bound[1] < bound[0]) { bound[1] = bound[0]; bound[0] = sector.ceilingHeight; } break; default: throw new Exception("Unexpected LineDefCeilingType target!"); } return(bound); }
public override int[] GetFloorMovementBound(WAD wad, SECTORS sector) { int[] bound = new int[2]; switch (target) { case LiftTarget.LowestNeighborFloor: bound[0] = sector.floorHeight; sector.neighbors.ForEach(n => bound[0] = Math.Min(bound[0], n.floorHeight)); bound[1] = sector.floorHeight; break; case LiftTarget.LowestAndHighestFloor: bound[0] = sector.floorHeight; sector.neighbors.ForEach(n => bound[0] = Math.Min(bound[0], n.floorHeight)); bound[1] = sector.floorHeight; sector.neighbors.ForEach(n => bound[1] = Math.Max(bound[1], n.floorHeight)); break; case LiftTarget.RaiseNextFloor: bound[0] = sector.floorHeight; bound[1] = sector.floorHeight; if (repeatable == Repeatable.Multiple) { sector.neighbors.ForEach(n => bound[1] = Math.Max(bound[1], n.floorHeight)); } else { int height = int.MaxValue; sector.neighbors.ForEach(n => height = (n.floorHeight > sector.floorHeight) ? Math.Min(height, n.floorHeight) : height); if (height < int.MaxValue) { bound[1] = height; } } break; case LiftTarget.Ceiling: bound[0] = sector.floorHeight; bound[1] = sector.ceilingHeight; break; case LiftTarget.Raise24: bound[0] = sector.floorHeight; bound[1] = (repeatable == Repeatable.Multiple) ? sector.ceilingHeight : sector.floorHeight + 24; break; case LiftTarget.Raise32: bound[0] = sector.floorHeight; bound[1] = (repeatable == Repeatable.Multiple) ? sector.ceilingHeight : sector.floorHeight + 32; break; case LiftTarget.Stop: bound[0] = sector.floorHeight; bound[1] = sector.floorHeight; break; default: throw new Exception("Unexpected LineDefFloorType target!"); } return(bound); }
public virtual int[] GetCeilingMovementBound(WAD wad, SECTORS sector) { return(new int[2] { sector.ceilingHeight, sector.ceilingHeight }); }
public virtual int[] GetFloorMovementBound(WAD wad, SECTORS sector) { return(new int[2] { sector.floorHeight, sector.floorHeight }); }