public static void TR_GenMesh(World world, int mesh_index, BaseMesh mesh, Level tr) { var texMask = world.EngineVersion == Loader.Engine.TR4 ? TextureIndexMaskTr4 : TextureIndexMask; /* TR WAD FORMAT DOCUMENTATION! * tr4_face[3,4]_t: * flipped texture & 0x8000 (1 bit ) - horizontal flipping. * shape texture & 0x7000 (3 bits ) - texture sample shape. * index texture & $0FFF (12 bits) - texture sample index. * * if bit [15] is set, as in ( texture and $8000 ), it indicates that the texture * sample must be flipped horizontally prior to be used. * Bits [14..12] as in ( texture and $7000 ), are used to store the texture * shape, given by: ( texture and $7000 ) shr 12. * The valid values are: 0, 2, 4, 6, 7, as assigned to a square starting from * the top-left corner and going clockwise: 0, 2, 4, 6 represent the positions * of the square angle of the triangles, 7 represents a quad. */ var trMesh = tr.Meshes[mesh_index]; mesh.ID = (uint)mesh_index; mesh.Center.X = trMesh.Centre.X; mesh.Center.Y = trMesh.Centre.Z; mesh.Center.Z = trMesh.Centre.Y; mesh.Radius = trMesh.CollisionSize; mesh.TexturePageCount = world.TextureAtlas.NumAtlasPages + 1; mesh.Vertices.Resize(trMesh.Vertices.Length, () => new Vertex()); for (var i = 0; i < mesh.Vertices.Count; i++) { mesh.Vertices[i].Position = trMesh.Vertices[i].ToVector3(); mesh.Vertices[i].Normal = Vector3.Zero; // paranoid } mesh.FindBB(); mesh.Polygons.Clear(); // textured triangles foreach (var face3 in trMesh.TexturedTriangles) { var p = new Polygon(); var tex = tr.ObjectTextures[face3.Texture & texMask]; p.DoubleSide = face3.Texture >> 15 != 0; // CORRECT, BUT WRONG IN TR3-5 SetAnimTexture(p, (uint)face3.Texture & texMask, world); p.BlendMode = face3.Lighting.HasFlagUns(0x01) ? BlendingMode.Multiply : tex.TransparencyFlags; tr_accumulateNormals(trMesh, mesh, 3, face3.Vertices, p); tr_setupTexturedFace(trMesh, mesh, face3.Vertices, p); world.TextureAtlas.GetCoordinates((uint) face3.Texture & texMask, false, p); mesh.Polygons.Add(p); } // coloured triangles foreach (var face3 in trMesh.ColouredTriangles) { var p = new Polygon(); var col = face3.Texture & 0xff; p.TexIndex = (ushort)world.TextureAtlas.NumAtlasPages; p.BlendMode = BlendingMode.Opaque; p.AnimID = 0; tr_accumulateNormals(trMesh, mesh, 3, face3.Vertices, p); tr_setupColoredFace(trMesh, tr, mesh, face3.Vertices, col, p); mesh.Polygons.Add(p); } // textured rectangles foreach (var face4 in trMesh.TexturedRectangles) { var p = new Polygon(); var tex = tr.ObjectTextures[face4.Texture & texMask]; p.DoubleSide = face4.Texture >> 15 != 0; // CORRECT, BUT WRONG IN TR3-5 SetAnimTexture(p, (uint)face4.Texture & texMask, world); p.BlendMode = face4.Lighting.HasFlagUns(0x01) ? BlendingMode.Multiply : tex.TransparencyFlags; tr_accumulateNormals(trMesh, mesh, 4, face4.Vertices, p); tr_setupTexturedFace(trMesh, mesh, face4.Vertices, p); world.TextureAtlas.GetCoordinates((uint)face4.Texture & texMask, false, p); mesh.Polygons.Add(p); } // coloured rectangles foreach (var face4 in trMesh.ColouredRectangles) { var p = new Polygon(); var col = face4.Texture & 0xff; p.TexIndex = (ushort)world.TextureAtlas.NumAtlasPages; p.BlendMode = BlendingMode.Opaque; p.AnimID = 0; tr_accumulateNormals(trMesh, mesh, 4, face4.Vertices, p); tr_setupColoredFace(trMesh, tr, mesh, face4.Vertices, col, p); mesh.Polygons.Add(p); } // let us normalise normals %) foreach (var v in mesh.Vertices) { v.Normal = v.Normal.SafeNormalize(); } // triangles var j = 0; for (var i = 0; i < trMesh.TexturedTriangles.Length; i++, j++) { tr_copyNormals(mesh.Polygons[j], mesh, trMesh.TexturedTriangles[i].Vertices); } for (var i = 0; i < trMesh.ColouredTriangles.Length; i++, j++) { tr_copyNormals(mesh.Polygons[j], mesh, trMesh.ColouredTriangles[i].Vertices); } // triangles for (var i = 0; i < trMesh.TexturedRectangles.Length; i++, j++) { tr_copyNormals(mesh.Polygons[j], mesh, trMesh.TexturedRectangles[i].Vertices); } for (var i = 0; i < trMesh.ColouredRectangles.Length; i++, j++) { tr_copyNormals(mesh.Polygons[j], mesh, trMesh.ColouredRectangles[i].Vertices); } mesh.Vertices.Clear(); mesh.GenFaces(); mesh.PolySortInMesh(); }
public void GenMesh(World world, uint roomID, Level tr) { var texMask = world.EngineVersion == Loader.Engine.TR4 ? TextureIndexMaskTr4 : TextureIndexMask; var trRoom = tr.Rooms[roomID]; if(trRoom.Triangles.Length == 0 && trRoom.Rectangles.Length == 0) { Mesh = null; return; } Mesh = new BaseMesh { ID = roomID, TexturePageCount = world.TextureAtlas.NumAtlasPages + 1, UsesVertexColors = true // This is implicitly true on room meshes }; Mesh.Vertices.Resize(trRoom.Vertices.Length, () => new Vertex()); for (var i = 0; i < Mesh.Vertices.Count; i++) { Mesh.Vertices[i].Position = trRoom.Vertices[i].Vertex.ToVector3(); Mesh.Vertices[i].Normal = Vector3.Zero; // paranoid } Mesh.FindBB(); Mesh.Polygons.Resize(trRoom.Triangles.Length + trRoom.Rectangles.Length, () => new Polygon()); var p = 0; // triangles for (var i = 0; i < trRoom.Triangles.Length; i++, p++) { tr_setupRoomVertices(world, tr, trRoom, Mesh, 3, trRoom.Triangles[i].Vertices, (ushort)(trRoom.Triangles[i].Texture & texMask), Mesh.Polygons[p]); Mesh.Polygons[p].DoubleSide = (trRoom.Triangles[i].Texture & 0x8000) != 0; } // rectangles for (var i = 0; i < trRoom.Rectangles.Length; i++, p++) { tr_setupRoomVertices(world, tr, trRoom, Mesh, 4, trRoom.Rectangles[i].Vertices, (ushort)(trRoom.Rectangles[i].Texture & texMask), Mesh.Polygons[p]); Mesh.Polygons[p].DoubleSide = (trRoom.Rectangles[i].Texture & 0x8000) != 0; } // let us normalise normals %) foreach (var v in Mesh.Vertices) { v.Normal = v.Normal.SafeNormalize(); } p = 0; // triangles for (var i = 0; i < trRoom.Triangles.Length; i++, p++) { tr_copyNormals(Mesh.Polygons[p], Mesh, trRoom.Triangles[i].Vertices); } // rectangles for (var i = 0; i < trRoom.Rectangles.Length; i++, p++) { tr_copyNormals(Mesh.Polygons[p], Mesh, trRoom.Rectangles[i].Vertices); } Mesh.Vertices.Clear(); Mesh.GenFaces(); Mesh.PolySortInMesh(); }