예제 #1
0
        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);
        }
예제 #2
0
 public WadMeshBoneNode(WadMeshBoneNode parent, WadMesh wadMesh, WadBone bone)
 {
     Name            = bone.Name;
     WadMesh         = wadMesh;
     Bone            = bone;
     GlobalTransform = Matrix4x4.Identity;
     Parent          = parent;
 }
예제 #3
0
        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]);
                    }
                }
            }
        }
예제 #4
0
        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();
        }
예제 #5
0
        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);
                }
            }
        }
예제 #6
0
        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();
        }
예제 #7
0
        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();
                }
            }
        }
예제 #8
0
        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();
        }
예제 #9
0
        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);
                }
            }
        }
예제 #10
0
 public MeshTreeNode(IWadObjectId obj, WadMesh wadMesh)
 {
     ObjectId = obj;
     WadMesh  = wadMesh;
 }
예제 #11
0
        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);
        }
예제 #12
0
        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);
        }
예제 #13
0
        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;
        }
예제 #14
0
        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);
        }
예제 #15
0
        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);
        }
예제 #16
0
        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);
        }