public DigimonWorld2Model3D(ref BinaryReader reader) { ModelHeader = new TextureModelHeader(ref reader); reader.BaseStream.Position = ModelHeader.TimOffset; Texture = new DigimonWorld2Texture(ref reader, false); //new Thread(() => { Model3DWindow window = new Model3DWindow(); }).Start(); }
public static void CheckForTIMHeader(string filePath) { DigimonWorld2ToolForm.Main.AddLogToLogWindow($"Attempting to parse texture {filePath}"); if (!File.Exists(filePath)) { DigimonWorld2ToolForm.Main.AddErrorToLogWindow($"No file found at \"{filePath}\""); return; } BinaryReader reader = new BinaryReader(File.Open(filePath, FileMode.Open)); switch ((TextureType)DigimonWorld2ToolForm.Main.TextureTypeComboBox.SelectedIndex) { case TextureType.Generic: CurrentTexture = new DigimonWorld2Texture(ref reader); if (CurrentTexture.TimHeader == null) { DigimonWorld2ToolForm.Main.AddErrorToLogWindow("No TimHeader found for current texture!"); return; } break; case TextureType.Model: DigimonWorld2Model3D currentModel = new DigimonWorld2Model3D(ref reader); CurrentTexture = currentModel.Texture; if (CurrentTexture.TimHeader == null) { DigimonWorld2ToolForm.Main.AddErrorToLogWindow("No TimHeader found for current texture!"); return; } break; default: break; } palette = DigimonWorld2ToolForm.Main.TextureUseAltClutCheckbox.Checked ? CurrentTexture.TimHeader.AlternativeClutPalette : CurrentTexture.TimHeader.TimClutPalette; if (palette == null) { DigimonWorld2ToolForm.Main.AddErrorToLogWindow($"No Palette was found, terminating."); reader.Close(); reader.Dispose(); return; } DrawCLUTPalette(palette); DrawTextureBMP(ref reader, palette, CurrentTexture); reader.Close(); reader.Dispose(); if (CurrentTexture.TextureHeader != null && CurrentTexture.TextureHeader.TextureSectionsOffsets != null && CurrentTexture.TextureHeader.TextureSectionsOffsets.Length > 0) { DigimonWorld2ToolForm.Main.TextureSegmentSelectComboBox.Enabled = true; DigimonWorld2ToolForm.Main.TextureLayerSelectComboBox.Enabled = true; DigimonWorld2ToolForm.Main.TextureSegmentSelectComboBox.SelectedIndex = 0; } else { DigimonWorld2ToolForm.Main.TextureSegmentSelectComboBox.Enabled = false; DigimonWorld2ToolForm.Main.TextureLayerSelectComboBox.Enabled = false; } }
/// <summary> /// Draw a BMP image of the selected texture of the given texture /// </summary> /// <param name="reader">The stream to read the bytes from</param> /// <param name="palette">The colour palette to use</param> /// <param name="texture">The texture to draw</param> private static void DrawTextureBMP(ref BinaryReader reader, Color[] palette, DigimonWorld2Texture texture) { TextureScaleSize = DigimonWorld2ToolForm.Main.ScaleTextureToFitCheckbox.Checked ? 2 : 1; Bitmap imageBmp = null; int CLUTOffset = (int)DigimonWorld2ToolForm.Main.CLUTOffsetUpDown.Value; switch (texture.TimHeader.Bpp) { case TIMHeader.BitDepth.Four: { var width = texture.TimHeader.ImageWidth * 4; // in a 4BPP colour depth we only use a quarter of a byte per pixel, so to get the real width the multiply by 4 var height = texture.TimHeader.ImageHeight; imageBmp = new Bitmap(width * TextureScaleSize, height * TextureScaleSize); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x += 2) // We skip every 2nd pixel on the x axis, as we render 2 pixels per byte { byte colourValue = reader.ReadByte(); CurrentTexture.AddByteToTextureData(colourValue); for (int i = 0; i < TextureScaleSize; i++) { for (int j = 0; j < TextureScaleSize; j++) { if (DigimonWorld2ToolForm.Main.TextureUseAltClutCheckbox.Checked) { byte rightPixelValue = colourValue.GetRightNiblet(); imageBmp.SetPixel((x * TextureScaleSize) + i, (y * TextureScaleSize) + j, palette[CLUTOffset + rightPixelValue]); // The left pixel is the right half byte due to endianess byte leftPixelValue = colourValue.GetLeftNiblet(); imageBmp.SetPixel((x * TextureScaleSize) + TextureScaleSize + i, (y * TextureScaleSize) + j, palette[CLUTOffset + leftPixelValue]); //+ 1 to the x to render the right pixel } else { byte rightPixelValue = colourValue.GetRightNiblet(); imageBmp.SetPixel((x * TextureScaleSize) + i, (y * TextureScaleSize) + j, palette[rightPixelValue]); // The left pixel is the right half byte due to endianess byte leftPixelValue = colourValue.GetLeftNiblet(); imageBmp.SetPixel((x * TextureScaleSize) + TextureScaleSize + i, (y * TextureScaleSize) + j, palette[leftPixelValue]); //+ 1 to the x to render the right pixel } } } } } } break; case TIMHeader.BitDepth.Eight: { var width = texture.TimHeader.ImageWidth * 2; // in a 8BPP colour depth we only use a half of a byte per pixel, so to get the real width the multiply by 2 var height = texture.TimHeader.ImageHeight; imageBmp = new Bitmap(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { byte colourValue = reader.ReadByte(); imageBmp.SetPixel(x, y, palette[colourValue]); } } } break; } DigimonWorld2ToolForm.Main.SelectedTextureRenderLayer.Image = imageBmp; CurrentBitmap = imageBmp; }