Beispiel #1
0
        /// <summary>
        /// Creates dummy texture
        /// </summary>
        /// <param name="Material">Material to use for texture parameters</param>
        private void SetInvalidTexture(ObjFile.Material Material)
        {
            Format = GBI.G_IM_FMT_RGBA;
            Size   = GBI.G_IM_SIZ_16b;

            Data    = new byte[Material.Width * Material.Height * 2];
            Palette = null;
        }
Beispiel #2
0
        public void ConvertScene(bool ConsecutiveRoomInject, bool ForceRGBATextures)
        {
            /* Check if collision model is valid */
            if (ColModel == null)
            {
                throw new Exception("No collision model defined");
            }

            /* Process rooms... */
            for (int i = 0; i < _Rooms.Count; i++)
            {
                /* Get current room from list */
                ZRoom Room = _Rooms[i];

                /* Create new room file, DList offset list and texture list */
                Room.RoomData = new List <byte>();
                Room.DLists   = new List <NDisplayList>();
                Textures      = new List <NTexture>();

                /* Create room header */
                WriteRoomHeader(Room);

                /* Write objects */
                if (Room.ZObjects.Count != 0)
                {
                    ObjectOffset = Room.RoomData.Count;
                    foreach (ZUShort Obj in Room.ZObjects)
                    {
                        Helpers.Append16(ref Room.RoomData, Obj.Value);
                    }
                    AddPadding(ref Room.RoomData, 8);
                }

                /* Write actors */
                if (Room.ZActors.Count != 0)
                {
                    ActorOffset = Room.RoomData.Count;
                    foreach (ZActor Actor in Room.ZActors)
                    {
                        Helpers.Append16(ref Room.RoomData, Actor.Number);
                        Helpers.Append16(ref Room.RoomData, (ushort)Actor.XPos);
                        Helpers.Append16(ref Room.RoomData, (ushort)Actor.YPos);
                        Helpers.Append16(ref Room.RoomData, (ushort)Actor.ZPos);
                        Helpers.Append16(ref Room.RoomData, (ushort)Actor.XRot);
                        Helpers.Append16(ref Room.RoomData, (ushort)Actor.YRot);
                        Helpers.Append16(ref Room.RoomData, (ushort)Actor.ZRot);
                        Helpers.Append16(ref Room.RoomData, Actor.Variable);
                    }
                    AddPadding(ref Room.RoomData, 8);
                }

                /* Prepare dummy mesh header */
                MeshHeaderOffset = Room.MeshHeaderOffset = Room.RoomData.Count;
                Helpers.Append32(ref Room.RoomData, 0);  /* Mesh type X, Y meshes */
                Helpers.Append32(ref Room.RoomData, 0);  /* Start address */
                Helpers.Append32(ref Room.RoomData, 0);  /* End address */
                for (int j = 0; j < Room.ObjModel.Groups.Count; j++)
                {
                    Helpers.Append64(ref Room.RoomData, 0);
                    Helpers.Append32(ref Room.RoomData, 0);  /* Display List offset 1 */
                    Helpers.Append32(ref Room.RoomData, 0);  /* Display List offset 2 */
                }
                AddPadding(ref Room.RoomData, 8);

                /* Create textures */
                for (int M = 0; M < Room.ObjModel.Materials.Count; M++)
                {
                    /* Get material & force RGBA default */
                    ObjFile.Material Mat = Room.ObjModel.Materials[M];
                    Mat.ForceRGBA = ForceRGBATextures;

                    /* ---VERY kludgy RGBA forcing code--- */
                    for (int x = 0; x < Room.ObjModel.Groups.Count; x++)
                    {
                        /* If group has multitex material number... */
                        if (Room.ObjModel.Groups[x].MultiTexMaterial != -1)
                        {
                            /* Turn force RGBA ON for multitex material */
                            Room.ObjModel.Materials[Room.ObjModel.Groups[x].MultiTexMaterial].ForceRGBA = true;

                            /* Scan group's triangles for current material name... */
                            for (int y = 0; y < Room.ObjModel.Groups[x].Triangles.Count; y++)
                            {
                                if (Room.ObjModel.Groups[x].Triangles[y].MaterialName == Mat.Name)
                                {
                                    /* Turn force RGBA ON for current material */
                                    Mat.ForceRGBA = true;
                                    goto Cont;
                                }
                            }
                        }
                    }

                    /* Continue here... */
Cont:
                    if (Mat.TexImage == null)
                    {
                        continue;
                    }

                    /* Create new texture, convert current material */
                    NTexture Texture = new NTexture();
                    Texture.Convert(Mat);

                    /* Add current offset to texture offset list */
                    Texture.TexOffset = ((uint)Room.RoomData.Count);
                    /* Write converted data to room file */
                    Room.RoomData.AddRange(Texture.Data);

                    /* See if we've got a CI-format texture... */
                    int Format = ((Texture.Type & 0xE0) >> 5);
#if DEBUG
                    Console.WriteLine("Texture format N64: " + Format.ToString("X2"));
#endif
                    if (Format == GBI.G_IM_FMT_CI)
                    {
                        /* If it's CI, add current offset to palette offset list */
                        Texture.PalOffset = ((uint)Room.RoomData.Count);
                        /* Write palette data to room file */
                        Room.RoomData.AddRange(Texture.Palette);
                    }
                    else
                    {
                        /* Add dummy entry to palette offset list */
                        Texture.PalOffset = Dummy;
                    }

                    Textures.Add(Texture);
                }

                /* Create Display Lists */
                for (int j = 0; j < Room.ObjModel.Groups.Count; j++)
                {
                    NDisplayList DList = new NDisplayList(Scale, Room.ObjModel.Groups[j].TintAlpha, 1.0f, IsOutdoors, Room.ObjModel.Groups[j].BackfaceCulling);
                    DList.Convert(Room.ObjModel, j, Textures, (uint)Room.RoomData.Count);

                    if (DList.Data != null)
                    {
                        Room.RoomData.AddRange(DList.Data);
                    }

                    Room.DLists.Add(DList);
                }

                /* Fix room header and add missing data */
                FixRoomHeader(Room);

                /* Add some padding for good measure */
                AddPadding(ref Room.RoomData, 0x1000);

                /* Store room data length */
                Room.FullDataLength = Room.RoomData.ToArray().Length;

                /* Put modified room info back into list */
                _Rooms[i] = Room;
            }

            /* Create new scene file */
            SceneData = new List <byte>();

            /* Write scene header */
            Helpers.Append64(ref SceneData, (ulong)(0x1502000000000000 | Music));       /* Sound settings */
            CmdMapListOffset = SceneData.Count;
            Helpers.Append64(ref SceneData, 0x0400000000000000);                        /* Map list */
            CmdTransitionsOffset = SceneData.Count;
            Helpers.Append64(ref SceneData, 0x0E00000000000000);                        /* Transition list */
            Helpers.Append64(ref SceneData, 0x1900000000000003);                        /* Cutscenes */
            CmdCollisionOffset = SceneData.Count;
            Helpers.Append64(ref SceneData, 0x0300000000000000);                        /* Collision header */
            CmdEntranceListOffset = SceneData.Count;
            Helpers.Append64(ref SceneData, 0x0600000000000000);                        /* Entrance index */

            if (IsOutdoors == true)                                                     /* Special objects */
            {
                Helpers.Append64(ref SceneData, 0x0701000000000002);
            }
            else
            {
                Helpers.Append64(ref SceneData, 0x0702000000000003);
            }

            CmdSpawnPointOffset = SceneData.Count;
            Helpers.Append64(ref SceneData, 0x0000000000000000);                        /* Spawn point list */

            if (IsOutdoors == true)                                                     /* Skybox / lighting settings */
            {
                Helpers.Append64(ref SceneData, 0x1100000001000000);
            }
            else
            {
                Helpers.Append64(ref SceneData, 0x1100000000000100);
            }

            CmdExitListOffset = SceneData.Count;
            Helpers.Append64(ref SceneData, 0x1300000000000000);                        /* Exit list */
            CmdEnvironmentsOffset = SceneData.Count;
            Helpers.Append64(ref SceneData, 0x0F00000000000000);                        /* Environments */
            Helpers.Append64(ref SceneData, 0x1400000000000000);                        /* End marker */

            /* Fix scene header; map list ... */
            Helpers.Overwrite32(ref SceneData, CmdMapListOffset, (uint)(0x04000000 | (_Rooms.Count << 16)));
            Helpers.Overwrite32(ref SceneData, CmdMapListOffset + 4, (uint)(0x02000000 | SceneData.Count));
            if (ConsecutiveRoomInject == true)
            {
                int RoomInjectOffset = _Rooms[0].InjectOffset;
                foreach (ZRoom Room in _Rooms)
                {
                    Helpers.Append32(ref SceneData, (uint)RoomInjectOffset);
                    Helpers.Append32(ref SceneData, (uint)(RoomInjectOffset + Room.FullDataLength));
                    RoomInjectOffset += Room.FullDataLength;
                }
            }
            else
            {
                foreach (ZRoom Room in _Rooms)
                {
                    Helpers.Append32(ref SceneData, (uint)Room.InjectOffset);
                    Helpers.Append32(ref SceneData, (uint)(Room.InjectOffset + Room.FullDataLength));
                }
            }
            AddPadding(ref SceneData, 8);

            /* ... transition list ... */
            Helpers.Overwrite32(ref SceneData, CmdTransitionsOffset, (uint)(0x0E000000 | (Transitions.Count << 16)));
            Helpers.Overwrite32(ref SceneData, CmdTransitionsOffset + 4, (uint)(0x02000000 | SceneData.Count));
            foreach (ZActor Trans in Transitions)
            {
                SceneData.Add(Trans.FrontSwitchTo);
                SceneData.Add(Trans.FrontCamera);
                SceneData.Add(Trans.BackSwitchTo);
                SceneData.Add(Trans.BackCamera);
                Helpers.Append16(ref SceneData, Trans.Number);
                Helpers.Append16(ref SceneData, (ushort)Trans.XPos);
                Helpers.Append16(ref SceneData, (ushort)Trans.YPos);
                Helpers.Append16(ref SceneData, (ushort)Trans.ZPos);
                Helpers.Append16(ref SceneData, (ushort)Trans.YRot);
                Helpers.Append16(ref SceneData, Trans.Variable);
            }
            AddPadding(ref SceneData, 8);

            /* ... exit list ... */
            Helpers.Overwrite32(ref SceneData, CmdExitListOffset + 4, (uint)(0x02000000 | SceneData.Count));
            foreach (ZUShort Exit in ExitList)
            {
                Helpers.Append16(ref SceneData, Exit.Value);
            }
            AddPadding(ref SceneData, 8);

            /* ... spawn point list ... */
            Helpers.Overwrite32(ref SceneData, CmdSpawnPointOffset, (uint)(0x00000000 | (SpawnPoints.Count << 16)));
            Helpers.Overwrite32(ref SceneData, CmdSpawnPointOffset + 4, (uint)(0x02000000 | SceneData.Count));
            foreach (ZActor Spawn in SpawnPoints)
            {
                Helpers.Append16(ref SceneData, Spawn.Number);
                Helpers.Append16(ref SceneData, (ushort)Spawn.XPos);
                Helpers.Append16(ref SceneData, (ushort)Spawn.YPos);
                Helpers.Append16(ref SceneData, (ushort)Spawn.ZPos);
                Helpers.Append16(ref SceneData, (ushort)Spawn.XRot);
                Helpers.Append16(ref SceneData, (ushort)Spawn.YRot);
                Helpers.Append16(ref SceneData, (ushort)Spawn.ZRot);
                Helpers.Append16(ref SceneData, Spawn.Variable);
            }
            AddPadding(ref SceneData, 8);

            /* ... environments ... */
            Helpers.Overwrite32(ref SceneData, CmdEnvironmentsOffset, (uint)(0x0F000000 | (Environments.Count << 16)));
            Helpers.Overwrite32(ref SceneData, CmdEnvironmentsOffset + 4, (uint)(0x02000000 | SceneData.Count));
            foreach (ZEnvironment Env in Environments)
            {
                Helpers.Append48(ref SceneData, (ulong)(Env.C1C.ToArgb() & 0xFFFFFF));
                Helpers.Append48(ref SceneData, (ulong)(Env.C2C.ToArgb() & 0xFFFFFF));
                Helpers.Append48(ref SceneData, (ulong)(Env.C3C.ToArgb() & 0xFFFFFF));
                Helpers.Append48(ref SceneData, (ulong)(Env.C4C.ToArgb() & 0xFFFFFF));
                Helpers.Append48(ref SceneData, (ulong)(Env.C5C.ToArgb() & 0xFFFFFF));
                Helpers.Append48(ref SceneData, (ulong)(Env.FogColorC.ToArgb() & 0xFFFFFF));
                Helpers.Append16(ref SceneData, Env.FogDistance);
                Helpers.Append16(ref SceneData, Env.DrawDistance);
            }
            AddPadding(ref SceneData, 8);

            /* ... entrance list ... */
            Helpers.Overwrite32(ref SceneData, CmdEntranceListOffset + 4, (uint)(0x02000000 | SceneData.Count));
            Helpers.Append16(ref SceneData, 0x0000);    /* Map 0, spawn point 0 */
            AddPadding(ref SceneData, 8);

            /* ... collision */
            WriteSceneCollision();
        }
Beispiel #3
0
        /// <summary>
        /// Converts given ObjFile.Material into N64 texture
        /// </summary>
        /// <param name="Material">Material to convert</param>
        public void Convert(ObjFile.Material Material)
        {
            try
            {
                BitmapData RawBmp = null;
                byte[]     Raw    = null;

                IsGrayscale = false;
                HasAlpha    = false;

                CheckImageProperties(Material.TexImage);

                if (IsSizeValid() == false)
                {
                    throw new Exception(string.Format("Invalid texture size {0}x{1}", Width, Height));
                }

                try
                {
                    RawBmp = Material.TexImage.LockBits(
                        new Rectangle(0, 0, (int)Material.Width, (int)Material.Height),
                        ImageLockMode.ReadOnly,
                        PixelFormat.Format32bppArgb
                        );

                    int TotalSize = RawBmp.Height * RawBmp.Stride;
                    Raw = new byte[TotalSize];

                    System.Runtime.InteropServices.Marshal.Copy(RawBmp.Scan0, Raw, 0, TotalSize);
                }
                finally
                {
                    if (RawBmp != null)
                    {
                        Material.TexImage.UnlockBits(RawBmp);
                    }
                }

                //throw new Exception("Too many grayshades in texture OR invalid size");
                List <Color> UniqueColors = GetUniqueColors(Material.TexImage);

                if (IsGrayscale == true && Material.ForceRGBA == false)
                {
                    if (HasAlpha == true)
                    {
                        /* Convert to IA */
                        if (UniqueColors.Count <= 16)
                        {
#if DEBUG
                            Console.WriteLine("IA 8-bit <- " + Material.Name + ", " + Material.Width.ToString() + "*" + Material.Height.ToString() + ", " + UniqueColors.Count.ToString() + " grayshades");
#endif
                            /* Set type, IA 8-bit */
                            Format = GBI.G_IM_FMT_IA;
                            Size   = GBI.G_IM_SIZ_8b;

                            /* Generate texture buffer */
                            Data    = new byte[Material.Width * Material.Height];
                            Palette = null;

                            /* Loop through pixels, convert to IA 8-bit, write to texture buffer */
                            for (int i = 0, j = 0; i < Raw.Length; i += 4, j++)
                            {
                                Data[j] = (byte)(((Raw[i] / 16) << 4) | ((Raw[i + 3] / 16) & 0xF));
                            }
                        }
                        else if (UniqueColors.Count <= 256 && Material.Width * Material.Height <= 2048)
                        {
#if DEBUG
                            Console.WriteLine("IA 16-bit <- " + Material.Name + ", " + Material.Width.ToString() + "*" + Material.Height.ToString() + ", " + UniqueColors.Count.ToString() + " grayshades");
#endif
                            /* Set type, IA 16-bit */
                            Format = GBI.G_IM_FMT_IA;
                            Size   = GBI.G_IM_SIZ_16b;

                            /* Generate texture buffer */
                            Data    = new byte[Material.Width * Material.Height * 2];
                            Palette = null;

                            /* Loop through pixels, convert to IA 16-bit, write to texture buffer */
                            for (int i = 0, j = 0; i < Raw.Length; i += 4, j += 2)
                            {
                                Data[j]     = Raw[i + 2];
                                Data[j + 1] = Raw[i + 3];
                            }
                        }
                        else
                        {
                            /* Uh-oh, too many grayshades OR invalid size! */
                            throw new Exception("Too many grayshades in texture OR invalid size");
                        }
                    }
                    else
                    {
                        /* Convert to I */
                        if (UniqueColors.Count <= 16)
                        {
#if DEBUG
                            Console.WriteLine("I 4-bit <- " + Material.Name + ", " + Material.Width.ToString() + "*" + Material.Height.ToString() + ", " + UniqueColors.Count.ToString() + " grayshades");
#endif
                            /* Set type, I 4-bit */
                            Format = GBI.G_IM_FMT_I;
                            Size   = GBI.G_IM_SIZ_4b;

                            /* Generate texture buffer */
                            Data    = new byte[(Material.Width * Material.Height) / 2];
                            Palette = null;

                            /* Loop through pixels, convert to I 4-bit, write to texture buffer */
                            for (int i = 0, j = 0; i < Raw.Length; i += 8, j++)
                            {
                                Data[j] = (byte)(((Raw[i] / 16) << 4) | ((Raw[i + 4] / 16) & 0xF));
                            }
                        }
                        else if (UniqueColors.Count <= 256 && Material.Width * Material.Height <= 4096)
                        {
#if DEBUG
                            Console.WriteLine("I 8-bit <- " + Material.Name + ", " + Material.Width.ToString() + "*" + Material.Height.ToString() + ", " + UniqueColors.Count.ToString() + " grayshades");
#endif
                            /* Set type, I 8-bit */
                            Format = GBI.G_IM_FMT_I;
                            Size   = GBI.G_IM_SIZ_8b;

                            /* Generate texture buffer */
                            Data    = new byte[Material.Width * Material.Height];
                            Palette = null;

                            /* Loop through pixels, convert to I 8-bit, write to texture buffer */
                            for (int i = 0, j = 0; i < Raw.Length; i += 4, j++)
                            {
                                Data[j] = Raw[i];
                            }
                        }
                        else
                        {
                            /* Uh-oh, too many grayshades OR invalid size! */
                            throw new Exception("Too many grayshades in texture OR invalid size");
                        }
                    }
                }
                else
                {
                    /* Convert to CI */
                    if (UniqueColors.Count <= 16 && Material.ForceRGBA == false)
                    {
#if DEBUG
                        Console.WriteLine("CI 4-bit <- " + Material.Name + ", " + Material.Width.ToString() + "*" + Material.Height.ToString() + ", " + UniqueColors.Count.ToString() + " unique colors");
#endif
                        /* Set type, CI 4-bit */
                        Format = GBI.G_IM_FMT_CI;
                        Size   = GBI.G_IM_SIZ_4b;

                        /* Generate texture buffer */
                        Data = new byte[(Material.Width * Material.Height) / 2];

                        /* Generate 16-color RGBA5551 palette */
                        Palette = GeneratePalette(UniqueColors, 16);

                        /* Loop through pixels, get palette indexes, write to texture buffer */
                        for (int i = 0, j = 0; i < Raw.Length; i += 8, j++)
                        {
                            ushort RGBA5551_1 = ToRGBA5551(Raw[i + 2], Raw[i + 1], Raw[i], Raw[i + 3]);
                            ushort RGBA5551_2 = ToRGBA5551(Raw[i + 6], Raw[i + 5], Raw[i + 4], Raw[i + 7]);
                            byte   Value      = (byte)(
                                ((GetPaletteIndex(Palette, RGBA5551_1)) << 4) |
                                ((GetPaletteIndex(Palette, RGBA5551_2) & 0xF)));
                            Data[j] = Value;
                        }
                    }
                    else if (UniqueColors.Count <= 256 && Material.Width * Material.Height <= 2048 && Material.ForceRGBA == false)
                    {
#if DEBUG
                        Console.WriteLine("CI 8-bit <- " + Material.Name + ", " + Material.Width.ToString() + "*" + Material.Height.ToString() + ", " + UniqueColors.Count.ToString() + " unique colors");
#endif
                        /* Set type, CI 8-bit */
                        Format = GBI.G_IM_FMT_CI;
                        Size   = GBI.G_IM_SIZ_8b;

                        /* Generate texture buffer */
                        Data = new byte[Material.Width * Material.Height];

                        /* Generate 256-color RGBA5551 palette */
                        Palette = GeneratePalette(UniqueColors, 256);

                        /* Loop through pixels, get palette indexes, write to texture buffer */
                        for (int i = 0, j = 0; i < Raw.Length; i += 4, j++)
                        {
                            ushort RGBA5551 = ToRGBA5551(Raw[i + 2], Raw[i + 1], Raw[i], Raw[i + 3]);
                            Data[j] = (byte)GetPaletteIndex(Palette, RGBA5551);
                        }
                    }
                    else
                    {
                        /* Convert to RGBA */
#if DEBUG
                        Console.WriteLine("RGBA 16-bit <- " + Material.Name + ", " + Material.Width.ToString() + "*" + Material.Height.ToString());
#endif
                        /* Set type, RGBA 16-bit */
                        Format = GBI.G_IM_FMT_RGBA;
                        Size   = GBI.G_IM_SIZ_16b;

                        /* Generate texture buffer */
                        Data    = new byte[Material.Width * Material.Height * 2];
                        Palette = null;

                        /* Loop through pixels, convert to RGBA5551, write to texture buffer */
                        for (int i = 0, j = 0; i < Raw.Length; i += 4, j += 2)
                        {
                            ushort RGBA5551 = ToRGBA5551(Raw[i + 2], Raw[i + 1], Raw[i], Raw[i + 3]);
                            Data[j]     = (byte)(RGBA5551 >> 8);
                            Data[j + 1] = (byte)(RGBA5551 & 0xFF);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show("Material '" + Material.DisplayName + "': " + ex.Message, "Exception", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
                SetInvalidTexture(Material);
            }

            /* Pack texture type */
            Type = (byte)((Format << 5) | (Size << 3));
        }