private tr_mesh CreateDummyWadMesh(WadMesh oldMesh, bool isStatic, int objectId, bool isWaterfall = false, bool isOptics = false, WadMeshLightingType lightType = WadMeshLightingType.PrecalculatedGrayShades) { int currentMeshSize = 0; var newMesh = new tr_mesh { Center = new tr_vertex { X = (short)oldMesh.BoundingSphere.Center.X, Y = (short)-oldMesh.BoundingSphere.Center.Y, Z = (short)oldMesh.BoundingSphere.Center.Z }, Radius = (short)oldMesh.BoundingSphere.Radius }; int numShades = 0; currentMeshSize += 10; newMesh.NumVertices = 0; currentMeshSize += 2; int numNormals = 0; newMesh.Vertices = new tr_vertex[0]; newMesh.NumNormals = 0; currentMeshSize += 2; short numQuads = 0; short numTriangles = 0; newMesh.NumTexturedQuads = numQuads; currentMeshSize += 2; newMesh.NumTexturedTriangles = numTriangles; currentMeshSize += 2; int lastQuad = 0; int lastTriangle = 0; newMesh.TexturedQuads = new tr_face4[numQuads]; newMesh.TexturedTriangles = new tr_face3[numTriangles]; if (_level.Settings.GameVersion <= TRVersion.Game.TR3) { currentMeshSize += 4; // Num colored quads and triangles } if (currentMeshSize % 4 != 0) { currentMeshSize += 2; } newMesh.MeshSize = currentMeshSize; newMesh.MeshPointer = _totalMeshSize; _meshPointers.Add((uint)_totalMeshSize); _totalMeshSize += currentMeshSize; _meshes.Add(newMesh); return(newMesh); }
public WadMeshBoneNode(WadMeshBoneNode parent, WadMesh wadMesh, WadBone bone) { Name = bone.Name; WadMesh = wadMesh; Bone = bone; GlobalTransform = Matrix4x4.Identity; Parent = parent; }
private void ReplaceAllBonesFromFile() { var boneCount = _bones.Count; using (FileDialog dialog = new OpenFileDialog()) { dialog.InitialDirectory = PathC.GetDirectoryNameTry(_tool.DestinationWad.FileName); dialog.FileName = PathC.GetFileNameTry(_tool.DestinationWad.FileName); dialog.Filter = BaseGeometryImporter.FileExtensions.GetFilter(); dialog.Title = "Select a 3D file that you want to see imported."; if (dialog.ShowDialog(this) != DialogResult.OK) { return; } using (var form = new GeometryIOSettingsDialog(new IOGeometrySettings())) { form.AddPreset(IOSettingsPresets.GeometryImportSettingsPresets); if (form.ShowDialog(this) != DialogResult.OK) { return; } var meshes = WadMesh.ImportFromExternalModel(dialog.FileName, form.Settings, false); if (meshes == null || meshes.Count == 0) { ImportFailed(); return; } int meshCount; if (meshes.Count > _bones.Count) { meshCount = _bones.Count; popup.ShowError(panelRendering, "Mesh count is higher in imported model. Only first " + _bones.Count + " will be imported."); } else if (meshes.Count < _bones.Count) { meshCount = meshes.Count; popup.ShowError(panelRendering, "Mesh count is lower in imported model. Only meshes up to " + meshes.Count + " will be replaced."); } else { meshCount = _bones.Count; } for (int i = 0; i < meshCount; i++) { ReplaceExistingBone(meshes[i], _bones[i]); } } } }
private void ReplaceExistingBone(WadMesh mesh, WadMeshBoneNode node) { node.Bone.Mesh = mesh; node.WadMesh = mesh; // Reload skeleton _lastBone = node; treeSkeleton.Nodes.AddRange(LoadSkeleton()); ExpandSkeleton(); panelRendering.Skeleton = _bones; panelRendering.Invalidate(); }
public static void ImportModelAsStaticMesh(WadToolClass tool, IWin32Window owner) { if (tool.DestinationWad == null) { tool.SendMessage("You must have a wad opened", PopupType.Error); return; } using (FileDialog dialog = new OpenFileDialog()) { try { dialog.InitialDirectory = Path.GetDirectoryName(tool.DestinationWad.FileName); dialog.FileName = Path.GetFileName(tool.DestinationWad.FileName); } catch { // ignored } dialog.Filter = BaseGeometryImporter.FileExtensions.GetFilter(); dialog.Title = "Select a 3D file that you want to see imported."; if (dialog.ShowDialog(owner) != DialogResult.OK) { return; } using (var form = new GeometryIOSettingsDialog(new IOGeometrySettings())) { form.AddPreset(IOSettingsPresets.GeometryImportSettingsPresets); if (form.ShowDialog(owner) != DialogResult.OK) { return; } var @static = new WadStatic(tool.DestinationWad.GetFirstFreeStaticMesh()); var mesh = WadMesh.ImportFromExternalModel(dialog.FileName, form.Settings); if (mesh == null) { tool.SendMessage("Error while loading the 3D model. Please check that the file " + "is one of the supported formats and that the meshes are textured", PopupType.Error); return; } @static.Mesh = mesh; @static.VisibilityBox = @static.Mesh.BoundingBox; @static.CollisionBox = @static.Mesh.BoundingBox; tool.DestinationWad.Statics.Add(@static.Id, @static); tool.WadChanged(WadArea.Destination); } } }
private void btOk_Click(object sender, EventArgs e) { // Update big image view if (lstMeshes.SelectedNodes.Count <= 0 || lstMeshes.SelectedNodes[0].Tag == null) { return; } SelectedMesh = ((MeshTreeNode)lstMeshes.SelectedNodes[0].Tag).WadMesh; _tool.ToggleUnsavedChanges(); DialogResult = DialogResult.OK; Close(); }
private void butImportMeshFromFile_Click(object sender, EventArgs e) { using (FileDialog dialog = new OpenFileDialog()) { dialog.InitialDirectory = PathC.GetDirectoryNameTry(_tool.DestinationWad.FileName); dialog.FileName = PathC.GetFileNameTry(_tool.DestinationWad.FileName); dialog.Filter = BaseGeometryImporter.FileExtensions.GetFilter(); dialog.Title = "Select a 3D file that you want to see imported."; if (dialog.ShowDialog(this) != DialogResult.OK) { return; } using (var form = new GeometryIOSettingsDialog(new IOGeometrySettings())) { form.AddPreset(IOSettingsPresets.GeometryImportSettingsPresets); if (form.ShowDialog(this) != DialogResult.OK) { return; } var mesh = WadMesh.ImportFromExternalModel(dialog.FileName, form.Settings); if (mesh == null) { DarkMessageBox.Show(this, "Error while loading 3D model. Check that the file format \n" + "is supported, meshes are textured and texture file is present.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } _workingStatic.Mesh = mesh; _workingStatic.VisibilityBox = _workingStatic.Mesh.CalculateBoundingBox(panelRendering.GizmoTransform); _workingStatic.CollisionBox = _workingStatic.Mesh.CalculateBoundingBox(panelRendering.GizmoTransform); _workingStatic.Version = DataVersion.GetNext(); _workingStatic.Mesh.CalculateNormals(); panelRendering.Invalidate(); UpdatePositionUI(); UpdateCollisionBoxUI(); UpdateVisibilityBoxUI(); UpdateLightUI(); } } }
private void InsertNewBone(WadMesh mesh, WadMeshBoneNode parentNode) { // Create the new bone var bone = new WadBone(); bone.Mesh = mesh; bone.Name = "Bone_" + mesh.Name; bone.OpCode = WadLinkOpcode.NotUseStack; // Create the new node var node = new WadMeshBoneNode(parentNode, mesh, bone); // Insert the bone int index = _bones.IndexOf(parentNode); _bones.Insert(index + 1, node); // Special case: we're inserting root node if (_bones.Count == 1 && index == -1) { index = 0; } // Add angles to animations foreach (var animation in _moveable.Animations) { foreach (var kf in animation.KeyFrames) { kf.Angles.Insert(index, new WadKeyFrameRotation()); } } // Reload skeleton _lastBone = node; treeSkeleton.Nodes.AddRange(LoadSkeleton()); ExpandSkeleton(); panelRendering.Skeleton = _bones; panelRendering.Invalidate(); }
private void AddChildBoneFromFile() { if (treeSkeleton.SelectedNodes.Count == 0) { return; } var theNode = (WadMeshBoneNode)treeSkeleton.SelectedNodes[0].Tag; using (FileDialog dialog = new OpenFileDialog()) { dialog.InitialDirectory = PathC.GetDirectoryNameTry(_tool.DestinationWad.FileName); dialog.FileName = PathC.GetFileNameTry(_tool.DestinationWad.FileName); dialog.Filter = BaseGeometryImporter.FileExtensions.GetFilter(); dialog.Title = "Select a 3D file that you want to see imported."; if (dialog.ShowDialog(this) != DialogResult.OK) { return; } using (var form = new GeometryIOSettingsDialog(new IOGeometrySettings())) { form.AddPreset(IOSettingsPresets.GeometryImportSettingsPresets); if (form.ShowDialog(this) != DialogResult.OK) { return; } var mesh = WadMesh.ImportFromExternalModel(dialog.FileName, form.Settings); if (mesh == null) { ImportFailed(); return; } InsertNewBone(mesh, theNode); } } }
public MeshTreeNode(IWadObjectId obj, WadMesh wadMesh) { ObjectId = obj; WadMesh = wadMesh; }
public static ObjectMesh FromWad2(GraphicsDevice device, WadMesh msh, Func <WadTexture, VectorInt2> allocateTexture) { Console.WriteLine(msh.Name); // Initialize the mesh var mesh = new ObjectMesh(device, msh.Name); // Prepare materials var materialOpaque = new Material(Material.Material_Opaque + "_0_0_0_0", null, false, false, 0); var materialOpaqueDoubleSided = new Material(Material.Material_OpaqueDoubleSided + "_0_0_1_0", null, false, true, 0); var materialAdditiveBlending = new Material(Material.Material_AdditiveBlending + "_0_1_0_0", null, true, false, 0); var materialAdditiveBlendingDoubleSided = new Material(Material.Material_AdditiveBlendingDoubleSided + "_0_1_1_0", null, true, true, 0); mesh.Materials = new List <Material>(); mesh.Materials.Add(materialOpaque); mesh.Materials.Add(materialOpaqueDoubleSided); mesh.Materials.Add(materialAdditiveBlending); mesh.Materials.Add(materialAdditiveBlendingDoubleSided); mesh.Submeshes.Add(materialOpaque, new Submesh(materialOpaque)); mesh.Submeshes.Add(materialOpaqueDoubleSided, new Submesh(materialOpaqueDoubleSided)); mesh.Submeshes.Add(materialAdditiveBlending, new Submesh(materialAdditiveBlending)); mesh.Submeshes.Add(materialAdditiveBlendingDoubleSided, new Submesh(materialAdditiveBlendingDoubleSided)); mesh.BoundingBox = msh.BoundingBox; mesh.BoundingSphere = msh.BoundingSphere; // For some reason, wad meshes sometimes may have position count desynced from color count, so we check that too. var hasShades = msh.VerticesShades.Count != 0 && msh.VerticesPositions.Count == msh.VerticesShades.Count; for (int j = 0; j < msh.Polys.Count; j++) { WadPolygon poly = msh.Polys[j]; Vector2 positionInPackedTexture = allocateTexture((WadTexture)poly.Texture.Texture); // Get the right submesh var submesh = mesh.Submeshes[materialOpaque]; if (poly.Texture.BlendMode == BlendMode.Additive) { if (poly.Texture.DoubleSided) { submesh = mesh.Submeshes[materialAdditiveBlendingDoubleSided]; } else { submesh = mesh.Submeshes[materialAdditiveBlending]; } } else { if (poly.Texture.DoubleSided) { submesh = mesh.Submeshes[materialOpaqueDoubleSided]; } } // Do half-pixel correction on texture to prevent bleeding var coords = poly.Texture.TexCoords; var shape = (int)TextureExtensions.GetTextureShapeType(poly.Texture.TexCoords, poly.Shape == WadPolygonShape.Triangle); for (int i = 0; i < (poly.Shape == WadPolygonShape.Triangle /*poly.Texture.TextureIsTriangle*/ ? 3 : 4); i++) { if (poly.Shape == WadPolygonShape.Triangle /*poly.Texture.TextureIsTriangle*/) { coords[i] += TextureExtensions.CompensationTris[shape, i]; } else { coords[i] += TextureExtensions.CompensationQuads[shape, i]; } } if (poly.Shape == WadPolygonShape.Triangle) { int v1 = poly.Index0; int v2 = poly.Index1; int v3 = poly.Index2; PutObjectVertexAndIndex(msh.VerticesPositions[v1], msh.VerticesNormals[v1], mesh, submesh, coords[0], 0, (short)(hasShades ? msh.VerticesShades[v1] : 0), positionInPackedTexture); PutObjectVertexAndIndex(msh.VerticesPositions[v2], msh.VerticesNormals[v2], mesh, submesh, coords[1], 0, (short)(hasShades ? msh.VerticesShades[v2] : 0), positionInPackedTexture); PutObjectVertexAndIndex(msh.VerticesPositions[v3], msh.VerticesNormals[v3], mesh, submesh, coords[2], 0, (short)(hasShades ? msh.VerticesShades[v3] : 0), positionInPackedTexture); } else { int v1 = poly.Index0; int v2 = poly.Index1; int v3 = poly.Index2; int v4 = poly.Index3; PutObjectVertexAndIndex(msh.VerticesPositions[v1], msh.VerticesNormals[v1], mesh, submesh, coords[0], 0, (short)(hasShades ? msh.VerticesShades[v1] : 0), positionInPackedTexture); PutObjectVertexAndIndex(msh.VerticesPositions[v2], msh.VerticesNormals[v2], mesh, submesh, coords[1], 0, (short)(hasShades ? msh.VerticesShades[v2] : 0), positionInPackedTexture); PutObjectVertexAndIndex(msh.VerticesPositions[v4], msh.VerticesNormals[v4], mesh, submesh, coords[3], 0, (short)(hasShades ? msh.VerticesShades[v4] : 0), positionInPackedTexture); PutObjectVertexAndIndex(msh.VerticesPositions[v4], msh.VerticesNormals[v4], mesh, submesh, coords[3], 0, (short)(hasShades ? msh.VerticesShades[v4] : 0), positionInPackedTexture); PutObjectVertexAndIndex(msh.VerticesPositions[v2], msh.VerticesNormals[v2], mesh, submesh, coords[1], 0, (short)(hasShades ? msh.VerticesShades[v2] : 0), positionInPackedTexture); PutObjectVertexAndIndex(msh.VerticesPositions[v3], msh.VerticesNormals[v3], mesh, submesh, coords[2], 0, (short)(hasShades ? msh.VerticesShades[v3] : 0), positionInPackedTexture); } } mesh.UpdateBuffers(); return(mesh); }
public static WadMesh CreateFakeMesh(string name) { var mesh = new WadMesh(); mesh.Name = name; mesh.VerticesPositions.Add(new Vector3(-1, 1, 1)); // 0 mesh.VerticesPositions.Add(new Vector3(1, 1, 1)); // 1 mesh.VerticesPositions.Add(new Vector3(1, 1, -1)); // 2 mesh.VerticesPositions.Add(new Vector3(-1, 1, -1)); // 3 mesh.VerticesPositions.Add(new Vector3(-1, -1, 1)); // 4 mesh.VerticesPositions.Add(new Vector3(1, -1, 1)); // 5 mesh.VerticesPositions.Add(new Vector3(1, -1, -1)); // 6 mesh.VerticesPositions.Add(new Vector3(-1, -1, -1)); // 7 for (int i = 0; i < 8; i++) { mesh.VerticesNormals.Add(Vector3.Zero); } var texture = new TextureArea(); var image = ImageC.Magenta; texture.Texture = new WadTexture(image); texture.TexCoord0 = new Vector2(0, 0); texture.TexCoord1 = new Vector2(1, 0); texture.TexCoord2 = new Vector2(1, 1); texture.TexCoord3 = new Vector2(0, 1); mesh.Polys.Add(new WadPolygon { Index0 = 0, Index1 = 1, Index2 = 2, Index3 = 3, Shape = WadPolygonShape.Quad, Texture = texture }); mesh.Polys.Add(new WadPolygon { Index0 = 2, Index1 = 1, Index2 = 5, Index3 = 6, Shape = WadPolygonShape.Quad, Texture = texture }); mesh.Polys.Add(new WadPolygon { Index0 = 1, Index1 = 0, Index2 = 4, Index3 = 5, Shape = WadPolygonShape.Quad, Texture = texture }); mesh.Polys.Add(new WadPolygon { Index0 = 0, Index1 = 3, Index2 = 7, Index3 = 4, Shape = WadPolygonShape.Quad, Texture = texture }); mesh.Polys.Add(new WadPolygon { Index0 = 3, Index1 = 2, Index2 = 6, Index3 = 7, Shape = WadPolygonShape.Quad, Texture = texture }); mesh.Polys.Add(new WadPolygon { Index0 = 7, Index1 = 6, Index2 = 5, Index3 = 4, Shape = WadPolygonShape.Quad, Texture = texture }); return(mesh); }
public static void ExportMesh(WadToolClass tool, IWin32Window owner, WadMesh m) { // Step 1: collect all textures /*var texturePieces = new Dictionary<Hash, WadTexture>(); * for (int i = 0; i < m.Polys.Count; i++) * { * var poly = m.Polys[i]; * * // Create the new tile and compute hash * var textureQuad = poly.Texture.GetRect(poly.Shape == WadPolygonShape.Triangle); * var image = ImageC.CreateNew((int)textureQuad.Width, (int)textureQuad.Height); * image.CopyFrom(0, 0, poly.Texture.Texture.Image, (int)textureQuad.X0, (int)textureQuad.Y0, * (int)(textureQuad.X0 + textureQuad.X1), (int)(textureQuad.Y0 + textureQuad.Y1)); * WadTexture text = new WadTexture(image); * * // Store the hash for the next steps * poly.TextureHash = text.Hash; * * //Add uniquely the texture to the dictionary * if (!texturePieces.ContainsKey(text.Hash)) * texturePieces.Add(text.Hash, text); * } * * // Step 2: collect textures in 256x256 pages * int processedTextures = 0; * var lastTexture = ImageC.CreateNew(256, 256); * var packer = new RectPackerSimpleStack(new VectorInt2(256, 256)); * while (processedTextures < texturePieces.Count) * { * var texture = texturePieces.ElementAt(processedTextures).Value; * var result = packer.TryAdd(new VectorInt2(texture.Image.Width, texture.Image.Height)); * if (!result.HasValue) * { * * } * processedTextures++; * } * * var matOpaque = new IOMaterial(Material.Material_Opaque + "_" + j + "_" + i, * texture, * fileName, * i, * false, * false, * 0); * * var matOpaqueDoubleSided = new IOMaterial(Material.Material_OpaqueDoubleSided + "_" + j + "_" + i, * texture, * fileName, * i, * false, * true, * 0); * * var matAdditiveBlending = new IOMaterial(Material.Material_AdditiveBlending + "_" + j + "_" + i, * texture, * fileName, * i, * true, * false, * 0); * * var matAdditiveBlendingDoubleSided = new IOMaterial(Material.Material_AdditiveBlendingDoubleSided + "_" + j + "_" + i, * texture, * fileName, * i, * true, * true, * 0); * * var mesh = new IOMesh(m.Name); * * foreach (var poly in m.Polys) * { * * } * * m.Polys[0].Texture.*/ return; }
private tr_mesh ConvertWadMesh(WadMesh oldMesh, bool isStatic, int objectId, int meshIndex, bool isWaterfall = false, bool isOptics = false, WadMeshLightingType lightType = WadMeshLightingType.PrecalculatedGrayShades) { int currentMeshSize = 0; var newMesh = new tr_mesh { Center = new tr_vertex { X = (short)oldMesh.BoundingSphere.Center.X, Y = (short)-oldMesh.BoundingSphere.Center.Y, Z = (short)oldMesh.BoundingSphere.Center.Z }, Radius = (short)oldMesh.BoundingSphere.Radius }; currentMeshSize += 10; newMesh.NumVertices = (short)oldMesh.VerticesPositions.Count; currentMeshSize += 2; newMesh.Vertices = new tr_vertex[oldMesh.VerticesPositions.Count]; for (int j = 0; j < oldMesh.VerticesPositions.Count; j++) { var vertex = oldMesh.VerticesPositions[j]; newMesh.Vertices[j] = new tr_vertex((short)vertex.X, (short)-vertex.Y, (short)vertex.Z); currentMeshSize += 6; } // FIX: the following code will check for valid normals and shades combinations. // As last chance, I recalculate the normals on the fly. bool useShades = false; if (isStatic) { if (lightType == WadMeshLightingType.Normals) { if (oldMesh.VerticesNormals.Count == 0) { _progressReporter.ReportWarn(string.Format("Static {0} is a mesh with invalid lighting data. Normals will be recalculated on the fly.", objectId)); oldMesh.CalculateNormals(); } useShades = false; } else { if (oldMesh.VerticesShades.Count == 0) { if (oldMesh.VerticesNormals.Count == 0) { _progressReporter.ReportWarn(string.Format("Static {0} is a mesh with invalid lighting data. Normals will be recalculated on the fly.", objectId)); oldMesh.CalculateNormals(); } useShades = false; } else { useShades = true; } } } else { if (oldMesh.VerticesNormals.Count == 0) { _progressReporter.ReportWarn(string.Format("Mesh {0} of Moveable {1} contains invalid lighting data. Normals will be recalculated on the fly.", meshIndex, objectId)); oldMesh.CalculateNormals(); } useShades = false; } newMesh.NumNormals = (short)(useShades ? -oldMesh.VerticesShades.Count : oldMesh.VerticesNormals.Count); currentMeshSize += 2; if (!useShades) { newMesh.Normals = new tr_vertex[oldMesh.VerticesNormals.Count]; for (int j = 0; j < oldMesh.VerticesNormals.Count; j++) { Vector3 normal = oldMesh.VerticesNormals[j]; normal = Vector3.Normalize(normal); normal *= 16300.0f; newMesh.Normals[j] = new tr_vertex((short)normal.X, (short)-normal.Y, (short)normal.Z); currentMeshSize += 6; } } else { newMesh.Lights = new short[oldMesh.VerticesShades.Count]; for (int j = 0; j < oldMesh.VerticesShades.Count; j++) { newMesh.Lights[j] = oldMesh.VerticesShades[j]; currentMeshSize += 2; } } short numQuads = 0; short numTriangles = 0; foreach (var poly in oldMesh.Polys) { if (poly.Shape == WadPolygonShape.Quad) { numQuads++; } else { numTriangles++; } } newMesh.NumTexturedQuads = numQuads; currentMeshSize += 2; newMesh.NumTexturedTriangles = numTriangles; currentMeshSize += 2; int lastQuad = 0; int lastTriangle = 0; newMesh.TexturedQuads = new tr_face4[numQuads]; newMesh.TexturedTriangles = new tr_face3[numTriangles]; for (int j = 0; j < oldMesh.Polys.Count; j++) { var poly = oldMesh.Polys[j]; ushort lightingEffect = poly.Texture.BlendMode == BlendMode.Additive ? (ushort)1 : (ushort)0; if (poly.ShineStrength > 0) { if (useShades && isStatic) { _progressReporter.ReportWarn("Stray shiny effect found on static " + objectId + ", face " + oldMesh.Polys.IndexOf(poly) + ". Ignoring data."); } else { lightingEffect |= 0x02; lightingEffect |= (ushort)(Math.Min((byte)63, poly.ShineStrength) << 2); } } // Very quirky way to identify 1st face of a waterfall in TR4-TR5 wads. bool topmostAndUnpadded = (j == 0) ? isWaterfall : false; // Check if we should merge object and room textures in same texture tiles. bool agressivePacking = _level.Settings.AgressiveTexturePacking; if (poly.Shape == WadPolygonShape.Quad) { FixWadTextureCoordinates(ref poly.Texture); var result = _textureInfoManager.AddTexture(poly.Texture, agressivePacking, false, topmostAndUnpadded); if (isOptics) { result.Rotation = 0; // Very ugly hack for TR4-5 binocular/target optics! } newMesh.TexturedQuads[lastQuad++] = result.CreateFace4(new ushort[] { (ushort)poly.Index0, (ushort)poly.Index1, (ushort)poly.Index2, (ushort)poly.Index3 }, poly.Texture.DoubleSided, lightingEffect); currentMeshSize += _level.Settings.GameVersion <= TRVersion.Game.TR3 ? 10 : 12; } else { FixWadTextureCoordinates(ref poly.Texture); var result = _textureInfoManager.AddTexture(poly.Texture, agressivePacking, true, topmostAndUnpadded); if (isOptics) { result.Rotation = 0; // Very ugly hack for TR4-5 binocular/target optics! } newMesh.TexturedTriangles[lastTriangle++] = result.CreateFace3(new ushort[] { (ushort)poly.Index0, (ushort)poly.Index1, (ushort)poly.Index2 }, poly.Texture.DoubleSided, lightingEffect); currentMeshSize += _level.Settings.GameVersion <= TRVersion.Game.TR3 ? 8 : 10; } } if (_level.Settings.GameVersion <= TRVersion.Game.TR3) { currentMeshSize += 4; // Num colored quads and triangles } if (currentMeshSize % 4 != 0) { currentMeshSize += 2; } newMesh.MeshSize = currentMeshSize; newMesh.MeshPointer = _totalMeshSize; _meshPointers.Add((uint)_totalMeshSize); _totalMeshSize += currentMeshSize; _meshes.Add(newMesh); return(newMesh); }
private static WadMesh ConvertTr4MeshToWadMesh(Wad2 wad, Tr4Wad oldWad, Dictionary <int, WadTexture> textures, wad_mesh oldMesh, int objectID) { WadMesh mesh = new WadMesh(); var meshIndex = oldWad.Meshes.IndexOf(oldMesh); mesh.Name = "Mesh-" + objectID + "-" + meshIndex; // Create the bounding sphere mesh.BoundingSphere = new BoundingSphere(new Vector3(oldMesh.SphereX, -oldMesh.SphereY, oldMesh.SphereZ), oldMesh.Radius); // Add positions foreach (var oldVertex in oldMesh.Vertices) { mesh.VerticesPositions.Add(new Vector3(oldVertex.X, -oldVertex.Y, oldVertex.Z)); } // Add normals foreach (var oldNormal in oldMesh.Normals) { mesh.VerticesNormals.Add(new Vector3(oldNormal.X, -oldNormal.Y, oldNormal.Z)); } // Add shades foreach (var oldShade in oldMesh.Shades) { mesh.VerticesShades.Add(oldShade); } // Add polygons foreach (var oldPoly in oldMesh.Polygons) { WadPolygon poly = new WadPolygon(); poly.Shape = oldPoly.Shape == 8 ? WadPolygonShape.Triangle : WadPolygonShape.Quad; // Polygon indices poly.Index0 = oldPoly.V1; poly.Index1 = oldPoly.V2; poly.Index2 = oldPoly.V3; if (poly.Shape == WadPolygonShape.Quad) { poly.Index3 = oldPoly.V4; } // Polygon special effects poly.ShineStrength = (byte)((oldPoly.Attributes & 0x7c) >> 2); // Add the texture poly.Texture = CalculateTr4UVCoordinates(wad, oldWad, oldPoly, textures); mesh.Polys.Add(poly); } mesh.BoundingBox = new BoundingBox(oldMesh.Minimum, oldMesh.Maximum); // Usually only for static meshes if (mesh.VerticesNormals.Count == 0) { mesh.CalculateNormals(); } return(mesh); }
private static WadMesh ConvertTrLevelMeshToWadMesh(Wad2 wad, TrLevel oldLevel, tr_mesh oldMesh, TextureArea[] objectTextures) { WadMesh mesh = new WadMesh(); mesh.Name = "Mesh_" + oldLevel.Meshes.IndexOf(oldMesh); // Add positions foreach (var oldVertex in oldMesh.Vertices) { mesh.VerticesPositions.Add(new Vector3(oldVertex.X, -oldVertex.Y, oldVertex.Z)); } // Create the bounding areas mesh.BoundingSphere = new BoundingSphere(new Vector3(oldMesh.Center.X, oldMesh.Center.Y, oldMesh.Center.Z), oldMesh.Radius); mesh.BoundingBox = mesh.CalculateBoundingBox(); // Add normals foreach (var oldNormal in oldMesh.Normals) { mesh.VerticesNormals.Add(new Vector3(oldNormal.X, -oldNormal.Y, oldNormal.Z)); } // Add shades foreach (var oldShade in oldMesh.Lights) { mesh.VerticesShades.Add(oldShade); } // Add polygons foreach (var oldPoly in oldMesh.TexturedQuads) { TextureArea textureArea = objectTextures[oldPoly.Texture & 0x7fff]; textureArea.DoubleSided = (oldPoly.Texture & 0x8000) != 0; WadPolygon poly; poly.Shape = WadPolygonShape.Quad; poly.Index0 = oldPoly.Index0; poly.Index1 = oldPoly.Index1; poly.Index2 = oldPoly.Index2; poly.Index3 = oldPoly.Index3; poly.ShineStrength = (byte)((oldPoly.LightingEffect & 0x7c) >> 2); poly.Texture = textureArea; mesh.Polys.Add(poly); } foreach (var oldPoly in oldMesh.TexturedTriangles) { TextureArea textureArea = objectTextures[oldPoly.Texture & 0x7fff]; textureArea.DoubleSided = (oldPoly.Texture & 0x8000) != 0; WadPolygon poly = new WadPolygon(); poly.Shape = WadPolygonShape.Triangle; poly.Index0 = oldPoly.Index0; poly.Index1 = oldPoly.Index1; poly.Index2 = oldPoly.Index2; poly.Index3 = 0; poly.ShineStrength = (byte)((oldPoly.LightingEffect & 0x7c) >> 2); poly.Texture = textureArea; mesh.Polys.Add(poly); } foreach (var oldPoly in oldMesh.ColoredRectangles) { WadPolygon poly = new WadPolygon(); poly.Shape = WadPolygonShape.Quad; poly.Index0 = oldPoly.Index0; poly.Index1 = oldPoly.Index1; poly.Index2 = oldPoly.Index2; poly.Index3 = oldPoly.Index3; poly.Texture = ConvertColoredFaceToTexture(wad, oldLevel, oldPoly.Texture, false); poly.ShineStrength = 0; mesh.Polys.Add(poly); } foreach (var oldPoly in oldMesh.ColoredTriangles) { WadPolygon poly; poly.Shape = WadPolygonShape.Triangle; poly.Index0 = oldPoly.Index0; poly.Index1 = oldPoly.Index1; poly.Index2 = oldPoly.Index2; poly.Index3 = 0; poly.Texture = ConvertColoredFaceToTexture(wad, oldLevel, oldPoly.Texture, true); poly.ShineStrength = 0; mesh.Polys.Add(poly); } // Usually only for static meshes if (mesh.VerticesNormals.Count == 0) { mesh.CalculateNormals(); } return(mesh); }