private void WriteIndices(BitmapData destData)
        {
            ARGBPixel *sPtr = _srcPixels;
            ushort     id;
            byte *     dPtr = (byte *)destData.Scan0;
            int        step, val;

            if (destData.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                step = destData.Stride - _width;
                for (int y = 0; y < _height; y++, dPtr += step)
                {
                    for (int x = 0; x < _width; x++)
                    {
                        _idFunc(*sPtr++, &id);
                        *dPtr++ = (byte)_groupTable[id]->_box->_index;
                    }
                }
            }
            else
            {
                step = destData.Stride - ((_width + 1) / 2);
                for (int y = 0; y < _height; y++, dPtr += step)
                {
                    for (int x = _width; x > 0; x -= 2)
                    {
                        _idFunc(*sPtr++, &id);
                        val = _groupTable[id]->_box->_index << 4;

                        if (x > 1)
                        {
                            _idFunc(*sPtr++, &id);
                            val |= _groupTable[id]->_box->_index & 0xF;
                        }

                        *dPtr++ = (byte)val;
                    }
                }
            }
        }
예제 #2
0
        public virtual Bitmap DecodeTexture(VoidPtr addr, int w, int h, int mipLevel)
        {
            addr += GetMipOffset(ref w, ref h, mipLevel);

            int aw = w.Align(BlockWidth), ah = h.Align(BlockHeight);

            using (DIB dib = new DIB(w, h, BlockWidth, BlockHeight, PixelFormat.Format32bppArgb))
            {
                int sStep   = BlockWidth * BlockHeight * BitsPerPixel / 8;
                int bStride = aw * BitsPerPixel / 8;
                for (int y = 0; y < ah; y += BlockHeight)
                {
                    ARGBPixel *dPtr = (ARGBPixel *)dib.Scan0 + (y * aw);
                    VoidPtr    sPtr = addr + (y * bStride);
                    for (int x = 0; x < aw; x += BlockWidth, dPtr += BlockWidth, sPtr += sStep)
                    {
                        DecodeBlock(sPtr, dPtr, aw);
                    }
                }
                return(dib.ToBitmap());
            }
        }
예제 #3
0
        private MedianCut(Bitmap bmp, WiiPixelFormat texFormat, WiiPaletteFormat palFormat)
        {
            //Set output format
            if (texFormat == WiiPixelFormat.CI4)
                _outFormat = PixelFormat.Format4bppIndexed;
            else if (texFormat == WiiPixelFormat.CI8)
                _outFormat = PixelFormat.Format8bppIndexed;
            else
                throw new ArgumentException("Invalid pixel format.");

            //Set conversion functions
            if (palFormat == WiiPaletteFormat.IA8)
            {
                _idFunc = IA8Handler;
                _idConv = IA8Converter;
            }
            else if (palFormat == WiiPaletteFormat.RGB565)
            {
                _idFunc = RGB565Handler;
                _idConv = RGB565Converter;
            }
            else
            {
                _idFunc = RGB5A3Handler;
                _idConv = RGB5A3Converter;
            }

            //Lock/set source data
            _srcBmp = bmp;
            _width = bmp.Width;
            _height = bmp.Height;
            _size = _width * _height;
            _srcData = bmp.LockBits(new Rectangle(0, 0, _width, _height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            _srcPixels = (ARGBPixel*)_srcData.Scan0;

            //Create buffers
            _boxes = (ColorBox*)Marshal.AllocHGlobal(256 * sizeof(ColorBox));
            _groupTable = (ColorEntry**)Marshal.AllocHGlobal(65536 * 4);
        }
예제 #4
0
        private static CMPRBlock compressDXT1(ARGBPixel *pBlock)
        {
            float *  pointData = stackalloc float[48];
            Vector3 *points    = (Vector3 *)pointData;

            extractColorBlockRGB(pBlock, points);

            // find min and max colors
            Vector3 maxColor, minColor;

            findMinMaxColorsBox(points, 16, &maxColor, &minColor);

            selectDiagonal(points, 16, &maxColor, &minColor);

            insetBBox(&maxColor, &minColor);

            ushort color0 = roundAndExpand(&maxColor);
            ushort color1 = roundAndExpand(&minColor);

            if (color0 < color1)
            {
                Vector3 t = maxColor;
                maxColor = minColor;
                minColor = t;
                VoidPtr.Swap(&color0, &color1);
            }

            CMPRBlock block = new CMPRBlock();

            block._root0._data = color0;
            block._root1._data = color1;
            block._lookup      = computeIndices4(points, &maxColor, &minColor);


            optimizeEndPoints4(points, &block);

            return(block);
        }
예제 #5
0
        protected override void DecodeBlock(VoidPtr blockAddr, ARGBPixel *dPtr, int width)
        {
            byte *s1 = (byte *)blockAddr;
            byte *s2 = s1 + 32;
            byte *d2 = (byte *)dPtr;

            for (int y = 0; y < 4; y++, d2 += (width - 4) << 2)
            {
                for (int x = 0; x < 4; x++, d2 += 4)
                {
                    d2[3] = *s1++;
                    d2[2] = *s1++;
                    d2[1] = *s2++;
                    d2[0] = *s2++;
                }
            }

            //RGBA8Pixel* sPtr = (RGBA8Pixel*)blockAddr;
            ////ARGBPixel* dPtr = (ARGBPixel*)destAddr;
            //for (int y = 0; y < 4; y++, dPtr += width)
            //    for (int x = 0; x < 4; sPtr = (RGBA8Pixel*)((int)sPtr + 2) )
            //        dPtr[x++] = (ARGBPixel)(*sPtr);
        }
예제 #6
0
        public void Dispose()
        {
            if (_boxes != null)
            {
                Marshal.FreeHGlobal((IntPtr)_boxes);
                _boxes = null;
            }

            if (_groupTable != null)
            {
                Marshal.FreeHGlobal((IntPtr)_groupTable);
                _groupTable = null;
            }

            if (_srcBmp != null)
            {
                _srcBmp.UnlockBits(_srcData);
                _srcBmp    = null;
                _srcData   = null;
                _srcPixels = null;
            }

            GC.SuppressFinalize(this);
        }
예제 #7
0
 protected abstract void EncodeBlock(ARGBPixel *sPtr, VoidPtr blockAddr, int width);
예제 #8
0
        public static unsafe Bitmap IndexColors(this Bitmap src, ColorPalette palette, PixelFormat format)
        {
            int w = src.Width, h = src.Height;

            int entries = palette.Entries.Length;

            switch (format)
            {
            case PixelFormat.Format4bppIndexed: { entries = Math.Min(entries, 16); break; }

            case PixelFormat.Format8bppIndexed: { entries = Math.Min(entries, 256); break; }

            default: { throw new ArgumentException("Pixel format is not an indexed format."); }
            }

            Bitmap dst = new Bitmap(w, h, format);

            dst.Palette = palette;

            BitmapData sData = src.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BitmapData dData = dst.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, format);

            ARGBPixel *sPtr = (ARGBPixel *)sData.Scan0;

            for (int y = 0; y < h; y++)
            {
                byte *dPtr = (byte *)dData.Scan0 + (y * dData.Stride);
                for (int x = 0; x < w; x++)
                {
                    ARGBPixel p = *sPtr++;

                    int bestDist = Int32.MaxValue, bestIndex = 0;
                    for (int z = 0; z < entries; z++)
                    {
                        int dist = p.DistanceTo(palette.Entries[z]);
                        if (dist < bestDist)
                        {
                            bestDist  = dist;
                            bestIndex = z;
                        }
                    }

                    if (format == PixelFormat.Format4bppIndexed)
                    {
                        byte val = *dPtr;
                        if ((x % 2) == 0)
                        {
                            *dPtr = (byte)((bestIndex << 4) | (val & 0x0F));
                        }
                        else
                        {
                            *dPtr++ = (byte)((val & 0xF0) | (bestIndex & 0x0F));
                        }
                    }
                    else
                    {
                        *dPtr++ = (byte)bestIndex;
                    }
                }
            }

            dst.UnlockBits(dData);
            src.UnlockBits(sData);

            return(dst);
        }
예제 #9
0
        public static unsafe void Clamp(this Bitmap bmp, WiiPixelFormat format)
        {
            int        w = bmp.Width, h = bmp.Height;
            BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite,
                                           PixelFormat.Format32bppArgb);

            PixelClamper clmp;

            switch (format)
            {
            case WiiPixelFormat.I4:
            {
                clmp = p => { *p = ((I4Pixel)(*p))[0]; };
                break;
            }

            case WiiPixelFormat.I8:
            {
                clmp = p => { *p = (ARGBPixel)(I8Pixel)(*p); };
                break;
            }

            case WiiPixelFormat.IA4:
            {
                clmp = p => { *p = (IA4Pixel)(*p); };
                break;
            }

            case WiiPixelFormat.IA8:
            {
                clmp = p => { *p = (IA8Pixel)(*p); };
                break;
            }

            case WiiPixelFormat.RGB565:
            {
                clmp = p => { *p = (ARGBPixel)(wRGB565Pixel)(*p); };
                break;
            }

            case WiiPixelFormat.RGB5A3:
            {
                clmp = p => { *p = (ARGBPixel)(wRGB5A3Pixel)(*p); };
                break;
            }

            case WiiPixelFormat.RGBA8:
            default:
            {
                clmp = p => { };
                break;
            }
            }

            for (ARGBPixel *ptr = (ARGBPixel *)data.Scan0, ceil = ptr + w * h; ptr < ceil;)
            {
                clmp(ptr++);
            }

            bmp.UnlockBits(data);
        }
예제 #10
0
        public static CMPRBlock compressDXT1a(ARGBPixel *img, int imgX, int imgY, int imgW, int imgH)
        {
            uint *     pData  = stackalloc uint[16];
            ARGBPixel *pBlock = (ARGBPixel *)pData;

            bool hasAlpha = false;
            bool isSingle = true;

            ARGBPixel  p;
            ARGBPixel *sPtr  = img + (imgX + imgY * imgW);
            int        index = 0;

            for (int y = 0; y < 4; y++)
            {
                for (int x = 0; x < 4; x++)
                {
                    p = sPtr[x + y * imgW];
                    pBlock[index++] = p;
                    if (p != pBlock[0])
                    {
                        isSingle = false;
                    }

                    if (p.A < 128)
                    {
                        hasAlpha = true;
                    }
                }
            }

            if (isSingle)
            {
                return(optimalCompressDXT1a(sPtr[0]));
            }

            if (!hasAlpha)
            {
                return(compressDXT1(pBlock));
            }

            // @@ Handle single RGB, with varying alpha? We need tables for single color compressor in 3 color mode.
            //else if (rgba.isSingleColorNoAlpha()) { ... }

            float *  pointData = stackalloc float[48];
            Vector3 *points    = (Vector3 *)pointData;

            // read block
            //Vector3 block[16];
            int num = extractColorBlockRGBA(pBlock, points);

            // find min and max colors
            Vector3 maxColor, minColor;

            findMinMaxColorsBox(points, num, &maxColor, &minColor);

            selectDiagonal(points, num, &maxColor, &minColor);

            insetBBox(&maxColor, &minColor);

            ushort color0 = roundAndExpand(&maxColor);
            ushort color1 = roundAndExpand(&minColor);

            if (color0 < color1)
            {
                Vector3 t = maxColor;
                maxColor = minColor;
                minColor = t;
                VoidPtr.Swap(&color0, &color1);
            }

            CMPRBlock block = new CMPRBlock();

            block._root0._data = color1;
            block._root1._data = color0;
            block._lookup      = computeIndices3(pBlock, &maxColor, &minColor);

            //	optimizeEndPoints(block, dxtBlock);

            return(block);
        }
예제 #11
0
 public void Set(ARGBPixel *p)
 {
     A = p->A; R = p->R; G = p->G; B = p->B;
 }
예제 #12
0
        private unsafe void Load(int index, int program, PLT0Node palette)
        {
            if (_context == null)
            {
                return;
            }

            Source = null;

            if (Texture != null)
            {
                Texture.Delete();
            }
            Texture = new GLTexture(_context, 0, 0);
            Texture.Bind(index, program);

            //ctx._states[String.Format("{0}_TexRef", Name)] = Texture;

            Bitmap   bmp   = null;
            TEX0Node tNode = null;

            if (_context._states.ContainsKey("_Node_Refs"))
            {
                List <ResourceNode> nodes    = _context._states["_Node_Refs"] as List <ResourceNode>;
                List <ResourceNode> searched = new List <ResourceNode>(nodes.Count);

                foreach (ResourceNode n in nodes)
                {
                    ResourceNode node = n.RootNode;
                    if (searched.Contains(node))
                    {
                        continue;
                    }
                    searched.Add(node);

                    //Search node itself first
                    if ((tNode = node.FindChild("Textures(NW4R)/" + Name, true) as TEX0Node) != null)
                    {
                        Source = tNode;
                        if (palette != null)
                        {
                            bmp = tNode.GetImage(0, palette);
                        }
                        else
                        {
                            bmp = tNode.GetImage(0);
                        }
                    }
                    else
                    {
                        //Then search node directory
                        string path = node._origPath;
                        if (path != null)
                        {
                            DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(path));
                            foreach (FileInfo file in dir.GetFiles(Name + ".*"))
                            {
                                if (file.Name.EndsWith(".tga"))
                                {
                                    Source = file.FullName;
                                    bmp    = TGA.FromFile(file.FullName);
                                    break;
                                }
                                else if (file.Name.EndsWith(".png") || file.Name.EndsWith(".tiff") || file.Name.EndsWith(".tif"))
                                {
                                    Source = file.FullName;
                                    bmp    = (Bitmap)Bitmap.FromFile(file.FullName);
                                    break;
                                }
                            }
                        }
                    }
                    if (bmp != null)
                    {
                        break;
                    }
                }
                searched.Clear();

                if (bmp != null)
                {
                    int w = bmp.Width, h = bmp.Height, size = w * h;

                    Texture._width  = w;
                    Texture._height = h;
                    //_context.glTexParameter(GLTextureTarget.Texture2D, GLTextureParameter.MagFilter, (int)GLTextureFilter.LINEAR);
                    //_context.glTexParameter(GLTextureTarget.Texture2D, GLTextureParameter.MinFilter, (int)GLTextureFilter.NEAREST_MIPMAP_LINEAR);
                    //_context.glTexParameter(GLTextureTarget.Texture2D, GLTextureParameter.BaseLevel, 0);

                    //if (tNode != null)
                    //    _context.glTexParameter(GLTextureTarget.Texture2D, GLTextureParameter.MaxLevel, tNode.LevelOfDetail);
                    //else
                    //    _context.glTexParameter(GLTextureTarget.Texture2D, GLTextureParameter.MaxLevel, 0);

                    BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                    try
                    {
                        using (UnsafeBuffer buffer = new UnsafeBuffer(size << 2))
                        {
                            ARGBPixel *sPtr = (ARGBPixel *)data.Scan0;
                            ABGRPixel *dPtr = (ABGRPixel *)buffer.Address;

                            for (int i = 0; i < size; i++)
                            {
                                *dPtr++ = (ABGRPixel)(*sPtr++);
                            }

                            int res = _context.gluBuild2DMipmaps(GLTextureTarget.Texture2D, GLInternalPixelFormat._4, w, h, GLPixelDataFormat.RGBA, GLPixelDataType.UNSIGNED_BYTE, buffer.Address);
                            if (res != 0)
                            {
                            }
                        }
                    }
                    finally
                    {
                        bmp.UnlockBits(data);
                        bmp.Dispose();
                    }
                }
            }
        }
예제 #13
0
        public static CMPRBlock Encode(ARGBPixel *block, int width, bool fast)
        {
            CMPRBlock p = new CMPRBlock();

            uint *     pData  = stackalloc uint[16];
            ARGBPixel *pColor = (ARGBPixel *)pData;

            bool isSingle = true, hasAlpha = false, allAlpha = true;

            for (int y = 0, i = 0; y < 4; y++, block += width)
            {
                for (int x = 0; x < 4; i++)
                {
                    pColor[i] = block[x++];
                    if (pData[i] != pData[0])
                    {
                        isSingle = false;
                    }
                    if (pColor[i].A < 0x80)
                    {
                        hasAlpha = true;
                    }
                    else
                    {
                        allAlpha = false;
                    }
                }
            }

            /*
             *  Foreach block:
             *      copy block to buffer
             *      mirror remaning colors?
             *
             *      If block is single color:
             *          run optiml compress?
             *      else
             *          Initialize color set
             *          Compress block using color set
             *
             *
             */

            //BlockDecoder decoder = new BlockDecoder(width, 4, 4, 4);
            //bool isSingle = true, hasAlpha = false, allAlpha = true;
            //for (int i = 0; i < 16; i++)
            //{
            //    int index = decoder[i];
            //    pColor[i] = block[index];
            //    if (pData[i] != pData[0]) isSingle = false;
            //    if (pColor[i].A < 0x80) hasAlpha = true;
            //    else allAlpha = false;
            //}

            //bool isSingle = true, hasAlpha = false, allAlpha = true;
            //ARGBPixel* ptr = block;
            //int index = 0;
            //for (int y = 0; y < 4; y++, ptr += width - 4)
            //{
            //    for (int x = 0; x < 4; x++, ptr++, index++)
            //    {
            //        pColor[index] = block[(y * width) + x];
            //        if (pData[0] != pData[index]) isSingle = false;
            //        if (pColor[index].A < 0x80) hasAlpha = true;
            //        else allAlpha = false;
            //    }
            //}

            //if (allAlpha)
            //{
            //    p._root0._data = 0;
            //    p._root1._data = 0xFFFF;
            //    p._lookup = 0xFFFFFFFF;
            //}
            //else if (isSingle)
            //{
            //    p._root0 = (RGB565Pixel)(*block);
            //    p._root1._data = 0;
            //    p._lookup = 0x00000000;
            //}
            //else
            //{
            uint *     palData = stackalloc uint[4];
            ARGBPixel *palCol  = (ARGBPixel *)palData;

            int bestDist = -1;

            for (int i = 0; i < 16; i++)
            {
                ARGBPixel p1 = pColor[i];
                for (int x = i + 1; x < 16; x++)
                {
                    ARGBPixel p2 = pColor[x];
                    int       d  = p1.DistanceTo(p2);
                    if (d > bestDist)
                    {
                        bestDist  = d;
                        palCol[2] = p1;
                        palCol[3] = p2;
                    }
                }
            }

            wRGB565Pixel smax = (wRGB565Pixel)palCol[2];
            wRGB565Pixel smin = (wRGB565Pixel)palCol[3];

            if (smax < smin)
            {
                smax = (wRGB565Pixel)palCol[3]; smin = (wRGB565Pixel)palCol[2];
            }

            if (hasAlpha)
            {
                p._root0  = smin;
                p._root1  = smax;
                palCol[0] = (ARGBPixel)smin;
                palCol[1] = (ARGBPixel)smax;
                palCol[2] = new ARGBPixel(255, (byte)((palCol[0].R + palCol[1].R) >> 1), (byte)((palCol[0].G + palCol[1].G) >> 1), (byte)((palCol[0].B + palCol[1].B) >> 1));
                palCol[3] = new ARGBPixel();
            }
            else
            {
                p._root0  = smax;
                p._root1  = smin;
                palCol[0] = (ARGBPixel)smax;
                palCol[1] = (ARGBPixel)smin;
                palCol[2] = new ARGBPixel(255, (byte)(((palCol[0].R << 1) + palCol[1].R) / 3), (byte)(((palCol[0].G << 1) + palCol[1].G) / 3), (byte)(((palCol[0].B << 1) + palCol[1].B) / 3));
                palCol[3] = new ARGBPixel(255, (byte)(((palCol[1].R << 1) + palCol[0].R) / 3), (byte)(((palCol[1].G << 1) + palCol[0].G) / 3), (byte)(((palCol[1].B << 1) + palCol[0].B) / 3));
            }

            uint indicies = 0;

            for (int i = 0, shift = 30; i < 16; i++, shift -= 2)
            {
                uint index = 3;
                if (pColor[i].A >= 0x80)
                {
                    int bd = int.MaxValue;
                    for (int x = 0; x < ((hasAlpha) ? 4 : 3); x++)
                    {
                        int dist = palCol[x].DistanceTo(pColor[i]);
                        if (dist < bd)
                        {
                            bd = dist; index = (uint)x;
                        }
                    }
                }
                indicies |= index << shift;
            }
            p._lookup = indicies;

            //p = DXT1Fast.Compress(pColor);
            //}


            return(p);
        }
예제 #14
0
 public void Decode(ARGBPixel *image, int imgX, int imgY, int imgW, int imgH)
 {
     Decode(image + (imgX + (imgY * imgW)), imgW);
 }
예제 #15
0
 public void Dispose()
 {
     if (_boxes != null)
     {
         Marshal.FreeHGlobal((IntPtr)_boxes);
         _boxes = null;
     }
     if (_groupTable != null)
     {
         Marshal.FreeHGlobal((IntPtr)_groupTable);
         _groupTable = null;
     }
     if (_srcBmp != null)
     {
         _srcBmp.UnlockBits(_srcData);
         _srcBmp = null;
         _srcData = null;
         _srcPixels = null;
     }
     GC.SuppressFinalize(this);
 }
예제 #16
0
 protected abstract void DecodeBlock(VoidPtr blockAddr, ARGBPixel *destAddr, int width);
예제 #17
0
        public static ARGBPixel[] ExtractColors(MDL0ColorData *colors)
        {
            int count = colors->_numEntries;

            ARGBPixel[] c = new ARGBPixel[count];

            fixed(ARGBPixel *p = c)
            {
                ARGBPixel *dPtr = p;

                switch (colors->Type)
                {
                case WiiColorComponentType.RGB565:
                {
                    wRGB565Pixel *sPtr = (wRGB565Pixel *)colors->Data;
                    for (int i = 0; i < count; i++)
                    {
                        *dPtr++ = (ARGBPixel)(*sPtr++);
                    }
                    break;
                }

                case WiiColorComponentType.RGB8:
                {
                    wRGBPixel *sPtr = (wRGBPixel *)colors->Data;
                    for (int i = 0; i < count; i++)
                    {
                        *dPtr++ = (ARGBPixel)(*sPtr++);
                    }
                    break;
                }

                case WiiColorComponentType.RGBX8:
                {
                    wRGBXPixel *sPtr = (wRGBXPixel *)colors->Data;
                    for (int i = 0; i < count; i++)
                    {
                        *dPtr++ = (ARGBPixel)(*sPtr++);
                    }
                    break;
                }

                case WiiColorComponentType.RGBA4:
                {
                    wRGBA4Pixel *sPtr = (wRGBA4Pixel *)colors->Data;
                    for (int i = 0; i < count; i++)
                    {
                        *dPtr++ = (ARGBPixel)(*sPtr++);
                    }
                    break;
                }

                case WiiColorComponentType.RGBA6:
                {
                    wRGBA6Pixel *sPtr = (wRGBA6Pixel *)colors->Data;
                    for (int i = 0; i < count; i++)
                    {
                        *dPtr++ = (ARGBPixel)(*sPtr++);
                    }
                    break;
                }

                case WiiColorComponentType.RGBA8:
                {
                    wRGBAPixel *sPtr = (wRGBAPixel *)colors->Data;
                    for (int i = 0; i < count; i++)
                    {
                        *dPtr++ = (ARGBPixel)(*sPtr++);
                    }
                    break;
                }
                }
            }

            return(c);
        }
예제 #18
0
        internal unsafe void Render(GLContext context, uint[] texIds)
        {
            if (!_enabled)
            {
                return;
            }

            //context.glEnable(GLEnableCap.Texture2D);

            if (_parent._uvData[0] == null)
            {
                return;
            }

            //Vector3* vPtr = (Vector3*)_parent._vertices.Address;
            //Vector3* nPtr = _parent._normals != null ? (Vector3*)_parent._normals.Address : null;
            ARGBPixel *c1Ptr = _parent._colors1 != null ? (ARGBPixel *)_parent._colors1.Address : null;
            ARGBPixel *c2Ptr = _parent._colors2 != null ? (ARGBPixel *)_parent._colors2.Address : null;
            //Vector2* uvPtr = _parent._uvData[0] != null ? (Vector2*)_parent._uvData[0].Address : null;

            int numUV = 0;

            Vector2 *[] uPtrs = new Vector2 *[8];
            while (_parent._uvData[numUV] != null)
            {
                uPtrs[numUV] = (Vector2 *)_parent._uvData[numUV].Address;
                numUV++;
            }

            Vector3 v, n;
            Vector2 u;
            uint    id;

            fixed(Vector3 *vPtr = _vertices)
            fixed(Vector3 * nPtr = _normals)
            {
                for (int t = 0; t < 1; t++)
                {
                    if ((id = texIds[t]) == 0)
                    {
                        continue;
                    }

                    context.glBindTexture(GLTextureTarget.Texture2D, id);
                    context.glBegin(_type);
                    for (int i = 0; i < _elements; i++)
                    {
                        if (c1Ptr != null)
                        {
                            context.glColor4((byte *)&c1Ptr[_colorIndices[0][i]]);
                        }
                        //if(c2Ptr != null)
                        //    context.glColor4((byte*)&c2Ptr[_colorIndices[1][i]]);

                        context.glNormal((float *)&nPtr[i]);

                        context.glTexCoord2((float *)&uPtrs[0][_uvIndices[0][i]]);
                        //u = uPtrs[t][_uvIndices[t][i]];
                        //context.glTexCoord2((float*)&u);

                        context.glVertex3v((float *)&vPtr[i]);
                    }
                    context.glEnd();
                }
            }
            context.CheckErrors();
        }