SerahToolkit_SharpGL.BattleStage.GetUVpoints C# (CSharp) Method

GetUVpoints() public method

public GetUVpoints ( int offset, string stagePath, int lastKnownTim ) : Tuple,List,int>
offset int
stagePath string
lastKnownTim int
return Tuple,List,int>
        public Tuple<List<double>,List<double>,int> GetUVpoints(int offset, string stagePath, int lastKnownTim)
        {
            List<double> uv1 = new List<double>();
            List<double> uv2 = new List<double>();

            int clut = 0;
            _stage = File.ReadAllBytes(stagePath);
            int tim = lastKnownTim;
            int tiMoffsetCluTetc = tim + 18;
            ushort cluTsize = BitConverter.ToUInt16(_stage, tiMoffsetCluTetc);
            tiMoffsetCluTetc += 2 + (cluTsize * 512) + 8;
            _textureDataInt = tiMoffsetCluTetc + 4;
            ushort szerU = BitConverter.ToUInt16(_stage, tiMoffsetCluTetc);
            ushort wysoU = BitConverter.ToUInt16(_stage, tiMoffsetCluTetc + 2);
            _width = szerU * 2;
            _height = wysoU;
            _verts = BitConverter.ToUInt16(_stage, offset + 4);
            _absolutePolygon = offset + 6 + (_verts * 6);
            _triangles = BitConverter.ToUInt16(_stage, _absolutePolygon + 4 + (_absolutePolygon % 4));
            _quads = BitConverter.ToUInt16(_stage, _absolutePolygon + 6 + (_absolutePolygon % 4));
            if (_triangles != 0)
            {
                    _triangleOffset = _absolutePolygon + 12 + (_absolutePolygon % 4);
                    _currRun = _triangleOffset + 6;
                    _trisStop = _currRun + (_triangles * 20);
                while (true)
                {
                    _u1 = _stage[_currRun];
                    _v1 = _stage[_currRun + 1];
                    _u2 = _stage[_currRun + 2];
                    _v2 = _stage[_currRun + 3];

                    byte[] clutBuff = new byte[2];
                    Buffer.BlockCopy(_stage, _currRun + 4, clutBuff, 0, 2);
                    clut = ResolveClut(clutBuff);
                    _u3 = _stage[_currRun + 6];
                    _v3 = _stage[_currRun + 7];
                    string strByte = _stage[_currRun + 8].ToString("X2");
                    strByte = "0" + strByte.Substring(1);
                    byte page = byte.Parse(strByte);
                    int pageInt = page * 128;
                    double uu1 = _u1 / (float)_width + ((float)pageInt / _width);
                    double vv1 = 1.0f - (_v1 / 256.0f);
                    double uu2 = _u2 / (float)_width + ((float)pageInt / _width);
                    double vv2 = 1.0f - (_v2 / 256.0f);
                    double uu3 = _u3 / (float)_width + ((float)pageInt / _width);
                    double vv3 = 1.0f - (_v3 / 256.0f);
                    uv1.Add(uu1);
                    uv2.Add(vv1);
                    uv1.Add(uu2);
                    uv2.Add(vv2);
                    uv1.Add(uu3);
                    uv2.Add(vv3);
                        _changeStop = _trisStop - 20;
                        _changeAdd = 20;
                    if (_currRun == _changeStop)
                        break;
                    _currRun += _changeAdd;
                }
            }
            _currRun = 0;
            if (_quads != 0)
            {
                if (_triangles != 0)
                {
                    _quadOffset = _absolutePolygon + 12 + (_absolutePolygon % 4) + _triangles * 20;
                }
                else
                {
                    _quadOffset = _absolutePolygon + 12 + (_absolutePolygon % 4);
                }
                _currRun = _quadOffset + 8;
                _quadStop = (_currRun + (_quads * 24));
                _trisStop = (_currRun + (_triangles * 20));
                while (true)
                {
                    _u1 = _stage[_currRun];
                    _v1 = _stage[_currRun + 1];
                    byte[] clutBuff = new byte[2];
                    Buffer.BlockCopy(_stage, _currRun + 2, clutBuff, 0, 2);
                    clut = ResolveClut(clutBuff);
                    _u2 = _stage[_currRun + 4];
                    _v2 = _stage[_currRun + 5];
                    _u3 = _stage[_currRun + 8];
                    _v3 = _stage[_currRun + 9];
                    _u4 = _stage[_currRun + 10];
                    _v4 = _stage[_currRun + 11];
                    string strByte = _stage[_currRun + 6].ToString("X2");
                    strByte = "0" + strByte.Substring(1);
                    byte page = byte.Parse(strByte);
                    int pageInt = page * 128;

                    double uu1 = _u1 / (float)_width + ((float)pageInt / _width);
                    double vv1 = 1.0f - (_v1 / 256.0f);
                    double uu2 = _u2 / (float)_width + ((float)pageInt / _width);
                    double vv2 = 1.0f - (_v2 / 256.0f);
                    double uu3 = _u3 / (float)_width + ((float)pageInt / _width);
                    double vv3 = 1.0f - (_v3 / 256.0f);
                    double uu4 = _u4 / (float)_width + ((float)pageInt / _width);
                    double vv4 = 1.0f - (_v4 / 256.0f);
                    uv1.Add(uu1);
                    uv2.Add(vv1);
                    uv1.Add(uu2);
                    uv2.Add(vv2);
                    uv1.Add(uu3);
                    uv2.Add(vv3);
                    uv1.Add(uu4);
                    uv2.Add(vv4);
                    _changeStop = _quadStop - 24;
                    _changeAdd = 24;
                    if (_currRun == _changeStop)
                        break;
                    _currRun += _changeAdd;
                }
            }
            return new Tuple<List<double>, List<double>, int>(uv1, uv2, clut);
        }

Usage Example

        private void BattleStage_listbox(bool bGenerateTextures)
        {
            if (listBox1.SelectedIndex == -1)
                listBox1.SelectedIndex = 0;
            Image nullImageRes = _bmp2;
            _bmp = new Bitmap(nullImageRes);
            Graphics g = Graphics.FromImage(_bmp);
            int selected = Convert.ToInt32(listBox1.SelectedItems[0]);
            BattleStage bs = new BattleStage("UV");
            Tuple<List<double>, List<double>,int> uv = bs.GetUVpoints(selected, _lastKnownPath, _lastKnownTim);
            List<Point> uvPoint = new List<Point>();
            Pen pen = new Pen(Color.White, 1.0f);
            int index = 0;
            Tuple<int, int> texResTuple = bs.GetTextureRes();
            int width = texResTuple.Item1;
            int height = texResTuple.Item2;
            checkBox1.Checked = !_polygons[listBox1.SelectedIndex].IsEnabled;
            if (bGenerateTextures)
            {
                Console.WriteLine($"BS: Mixing textures...");
                Console.WriteLine($"BS: Collecting UV data and preparing bounding boxes");
                for (int i = 0; i != listBox1.Items.Count; i++)
                {
                    uv = bs.GetUVpoints(int.Parse(listBox1.Items[i].ToString()), _lastKnownPath, _lastKnownTim);
                    int clute = uv.Item3;
                    string pathText = Path.GetDirectoryName(_lastKnownPath);

                    if(clute!=0)
                        pathText = pathText + @"\" + Path.GetFileNameWithoutExtension(_lastKnownPath) + @"_" + clute + ".png";
                    else
                        pathText = pathText + @"\" + Path.GetFileNameWithoutExtension(_lastKnownPath) + ".png";

                    double u1Min = uv.Item1.Min(); double u1Max = uv.Item1.Max();
                    double v1Min = uv.Item2.Min(); double v1Max = uv.Item2.Max();
                    double x1 = Math.Floor(((u1Min * 100) * width) / 100);
                    double y1 = Math.Floor(((v1Min * 100) * height) / 100) ;
                    double x2 = Math.Floor(((u1Max * 100) * width) / 100);
                    double y2 = Math.Floor(((v1Max * 100) * height) / 100) ;
                    x1 = x1 <= 0 ? 1 : x1; x2 = x2 <= 0 ? 1 : x2;
                    Point topLeft = new Point((int)(Math.Round(x1)-1), height - (int)(Math.Round(y2)));
                    Point topRight = new Point((int)(Math.Round(x2)-1), height - (int)(Math.Round(y2)));
                    Point bottomLeft = new Point((int)(Math.Round(x1)), height - (int)(Math.Round(y1)));
                    Point bottomRight = new Point((int)(Math.Round(x2)), height - (int)(Math.Round(y1)));

                    if (!File.Exists(pathText)) continue;
                    Console.WriteLine($"BS: Mixing {pathText}");
                    Bitmap loadBmp = new Bitmap(pathText);
                    PixelFormat pf = PixelFormat.Format24bppRgb;
                    int wid = (topRight.X - topLeft.X) + 4;
                    int hei = (bottomLeft.Y - topLeft.Y) + 4;
                    wid = topLeft.X + wid > width ? wid - 4 : wid;
                    hei = bottomRight.Y + hei > height ? hei - 4 : hei;
                    Size sz = new Size(wid,hei);
                    Rectangle rectangle = new Rectangle(topLeft, sz);
                    BitmapData targetBitmapData = _bmp.LockBits(rectangle, ImageLockMode.WriteOnly, pf);
                    BitmapData sourBitmapData = loadBmp.LockBits(rectangle, ImageLockMode.ReadOnly, pf);
                    IntPtr workingptr = targetBitmapData.Scan0;
                    IntPtr sourceptr = sourBitmapData.Scan0;
                    byte[] rawLoadBmp = new byte[sourBitmapData.Stride * sourBitmapData.Height];
                    byte[] rawBmp = new byte[targetBitmapData.Stride * targetBitmapData.Height];
                    Marshal.Copy(workingptr, rawBmp, 0, rawBmp.Length);
                    Marshal.Copy(sourceptr, rawLoadBmp, 0, rawLoadBmp.Length);
                    for (int pixel = 0; pixel != rawLoadBmp.Length; pixel++)
                        rawBmp[pixel] = rawLoadBmp[pixel];
                    Marshal.Copy(rawBmp, 0, workingptr, rawBmp.Length);
                    loadBmp.UnlockBits(sourBitmapData);
                    _bmp.UnlockBits(targetBitmapData);
                    Console.WriteLine($"BS: Mixing finished");
                }
                pictureBox1.Image = _bmp;
                _bmp2 = _bmp;
                string pathTexte = Path.GetDirectoryName(_lastKnownPath);
                Console.WriteLine($"BS: Saving final texture");
                pathTexte = pathTexte + @"\" + Path.GetFileNameWithoutExtension(_lastKnownPath) + "_col.png";
                if (File.Exists(pathTexte))
                    File.Delete(pathTexte);
                Console.WriteLine($"BS: Setting transparency on final texture");
                _bmp.MakeTransparent(Color.Black);
                _bmp.Save(pathTexte);
                pathTexte = Path.GetDirectoryName(_lastKnownPath);
                pathTexte = pathTexte + @"\" + Path.GetFileNameWithoutExtension(_lastKnownPath) + ".MTL";
                string[] newfile = File.ReadAllLines(pathTexte);
                newfile[newfile.Length-1] = "map_Kd " + Path.GetFileNameWithoutExtension(_lastKnownPath) + "_col.png";
                File.WriteAllLines(pathTexte, newfile);
                pictureBox1.BackgroundImage = _bmp;
                Console.WriteLine($"BS: Finished!");
                Console.WriteLine($"BS: Delivered to renderer.");
                Render3D();
            }
            if (bGenerateTextures) return;
            {
                Console.WriteLine($"BS: Drawing UV layout");
                while (true)
                {
                    double x1 = (((uv.Item1[index] * 100) * width) / 100);
                    double y1 = (((uv.Item2[index] * 100) * height) / 100);
                    double x2 = (((uv.Item1[index + 1] * 100) * width) / 100);
                    double y2 = (((uv.Item2[index + 1] * 100) * height) / 100);
                    Point xy1 = new Point((int)(Math.Round(x1)), 256 - (int)(Math.Round(y1)));
                    Point xy2 = new Point((int)(Math.Round(x2)), 256 - (int)(Math.Round(y2)));
                    uvPoint.Add(xy1);
                    uvPoint.Add(xy2);
                    g.DrawLine(pen, uvPoint[index], uvPoint[index + 1]);

                    if (index >= uv.Item1.Count - 3 && index >= uv.Item2.Count - 3)
                        break;
                    index += 2;
                }
                g.Dispose();
                pictureBox1.Image = _bmp;
            }
        }