Exemple #1
0
        public override CompiledSpriteFont Process(SpriteFontContent input, string filename, ContentProcessorContext context)
        {
            string fontFile;

            if (!FontConfig.Instance.GetFontFile(input.FontName, input.Size, input.Style, out fontFile))
            {
                context.RaiseBuildMessage(filename, $"'{input.FontName}' was not found, using fallback font", BuildMessageEventArgs.BuildMessageType.Warning);
            }

            if (fontFile == null)
            {
                context.RaiseBuildMessage(filename, $"'{input.FontName}' was not found, no fallback font provided", BuildMessageEventArgs.BuildMessageType.Error);
                return(null);
            }

            //Initialization
            SharpFont.Library lib = new SharpFont.Library();
            var    face           = lib.NewFace(fontFile, 0);
            Bitmap dummyBitmap    = new Bitmap(1, 1);

            System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(dummyBitmap);
            face.SetCharSize(new Fixed26Dot6(0), new Fixed26Dot6(input.Size), (uint)g.DpiX, (uint)g.DpiY);

            CompiledSpriteFont compiled = new CompiledSpriteFont();

            compiled.Spacing          = input.Spacing;
            compiled.DefaultCharacter = input.DefaultCharacter;


            var glyphs = new Dictionary <uint, GlyphSlot>();

            var characters = input.CharacterRegions.SelectMany(
                r => r.GetChararcters().Select(c => Tuple.Create(c, face.GetCharIndex(c)))).Where(x => x.Item2 != 0).ToList();

            var bitmaps = new List <Tuple <char, FTBitmap, int, GlyphMetrics> >();

            compiled.LineSpacing = face.Size.Metrics.Height.Value >> 6;
            compiled.BaseLine    = face.Size.Metrics.Ascender.Value >> 6;
            //Loading Glyphs, Calculate Kernings and Create Bitmaps
            int totalWidth = 0, maxWidth = 0, maxHeight = 0;

            foreach (var l in characters)
            {
                var character  = l.Item1;
                var glyphIndex = l.Item2;

                //Load Glyphs
                face.LoadGlyph(glyphIndex, LoadFlags.Color, LoadTarget.Normal);
                var glyph = face.Glyph;
                glyph.Tag = character;
                glyphs.Add(character, glyph);

                //Calculate Kernings
                if (input.UseKerning)
                {
                    foreach (var r in characters)
                    {
                        var kerning = face.GetKerning(l.Item2, r.Item2, KerningMode.Default);
                        if (kerning == default(FTVector26Dot6))
                        {
                            continue;
                        }
                        compiled.kernings[(int)l.Item1 << 16 | (int)r.Item1] = kerning.X.Value >> 6;
                    }
                }

                //Create bitmaps
                glyph.OwnBitmap();
                var glyphActual = glyph.GetGlyph();
                glyphActual.ToBitmap(RenderMode.Normal, default(FTVector26Dot6), false);

                var bmg = glyphActual.ToBitmapGlyph();
                if (bmg.Bitmap.Width == 0 || bmg.Bitmap.Rows == 0)
                {
                    totalWidth += 2 + 1;
                    maxWidth    = Math.Max(maxWidth, 1 + 2);
                    maxHeight   = Math.Max(maxHeight, 1 + 2);
                    bitmaps.Add(Tuple.Create(character, (FTBitmap)null, glyph.Advance.X.Value >> 6, glyph.Metrics));
                }
                else
                {
                    var bmp = bmg.Bitmap;
                    totalWidth += 2 + bmp.Width;
                    maxWidth    = Math.Max(maxWidth, bmp.Width + 2);//TODO: divide by 3?
                    maxHeight   = Math.Max(maxHeight, bmp.Rows + 2);
                    bitmaps.Add(Tuple.Create(character, bmp, glyph.Advance.X.Value >> 6, glyph.Metrics));
                }
            }
            g.Dispose();
            dummyBitmap.Dispose();
            int cellCount = (int)Math.Ceiling(Math.Sqrt(bitmaps.Count));

            var target = new Bitmap(cellCount * maxWidth, cellCount * maxHeight);
            var targetRectangle = new Rectangle(0, 0, target.Width, target.Height);
            var targetData = target.LockBits(new System.Drawing.Rectangle(0, 0, target.Width, target.Height), ImageLockMode.WriteOnly, target.PixelFormat);
            int offsetX = 0, offsetY = 0;

            //Create Glyph Atlas
            foreach (var bmpKvp in bitmaps)
            {
                var bmp       = bmpKvp.Item2;
                var character = bmpKvp.Item1;

                if (bmp == null)
                {
                    compiled.characterMap.Add(character, new FontCharacter(character, targetRectangle, new Rectangle(offsetX, offsetY, 1, 1), new Vector2(bmpKvp.Item4.HorizontalBearingX.Value >> 6, compiled.BaseLine - (bmpKvp.Item4.HorizontalBearingY.Value >> 6)), bmpKvp.Item3));
                    if (offsetX++ > target.Width)
                    {
                        offsetY += maxHeight;
                        offsetX  = 0;
                    }
                    continue;
                }
                int width  = bmp.Width;
                int height = bmp.Rows;
                if (offsetX + width > target.Width)
                {
                    offsetY += maxHeight;
                    offsetX  = 0;
                }
                //TODO divide width by 3?
                compiled.characterMap.Add(character, new FontCharacter(character, targetRectangle, new Rectangle(offsetX, offsetY, width, height), new Vector2(bmpKvp.Item4.HorizontalBearingX.Value >> 6, compiled.BaseLine - (bmpKvp.Item4.HorizontalBearingY.Value >> 6)), bmpKvp.Item3));

                unsafe {
                    switch (bmp.PixelMode)
                    {
                    case PixelMode.Mono:
                        CopyFTBitmapToAtlas_Mono((uint *)targetData.Scan0 + offsetX + offsetY * target.Width, offsetX, offsetY, target.Width, bmp, width, height);//TODO: divide width by 3?
                        break;

                    case PixelMode.Gray:
                        CopyFTBitmapToAtlas_Gray((uint *)targetData.Scan0 + offsetX + offsetY * target.Width, offsetX, offsetY, target.Width, bmp, width, height);//TODO: divide width by 3?
                        break;

                    case PixelMode.Lcd:
                        CopyFTBitmapToAtlas_LcdBGR((uint *)targetData.Scan0 + offsetX + offsetY * target.Width, offsetX, offsetY, target.Width, bmp, width, height);//TODO: divide width by 3?
                        break;

                    case PixelMode.Bgra:
                        CopyFTBitmapToAtlas_BGRA((uint *)targetData.Scan0 + offsetX + offsetY * target.Width, offsetX, offsetY, target.Width, bmp, width, height);//TODO: divide width by 3?
                        break;

                    default:
                        throw new NotImplementedException("Pixel Mode not supported");
                    }
                }
                offsetX += width;//TODO divide by 3?
                bmp.Dispose();
            }
            compiled.texture          = new TextureContent(context.GraphicsDevice, false, 1, targetData.Scan0, target.Width, target.Height, TextureContentFormat.Png, TextureContentFormat.Png);
            compiled.Spacing          = input.Spacing;
            compiled.DefaultCharacter = input.DefaultCharacter;

            target.UnlockBits(targetData);

            //Saving files
            //target.Save("test.png",ImageFormat.Png);
            target.Dispose();
            //System.Diagnostics.Process.Start("test.png"); //TODO: Remove later

            return(compiled);
        }
Exemple #2
0
        public override ModelContent Process(Assimp.Scene scene, string filename, ContentProcessorContext context)
        {
            try
            {
                Assimp.AssimpContext c = new Assimp.AssimpContext();

                Assimp.ExportFormatDescription des = c.GetSupportedExportFormats()[0];
                //c.ExportFile(scene,Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),"test.dae"),des.FormatId);
                ModelContent content = new ModelContent();
                content.Meshes = new MeshContent[scene.MeshCount];
                for (int meshIndex = 0; meshIndex < scene.MeshCount; meshIndex++)
                {
                    var sceneMesh   = scene.Meshes[meshIndex];
                    var meshContent = new MeshContent();
                    meshContent.PrimitiveCount = sceneMesh.FaceCount;

                    meshContent.Vertices = new VertexPositionNormalTexture[meshContent.PrimitiveCount * 3];
                    int vertex = 0;
                    //TODO: indexing
                    foreach (var f in sceneMesh.Faces)
                    {
                        foreach (var i in f.Indices)
                        {
                            var             pos  = sceneMesh.Vertices[i];
                            var             norm = sceneMesh.Normals[i];
                            Assimp.Vector3D tex  = new Assimp.Vector3D();
                            if (sceneMesh.TextureCoordinateChannels.Length > 0 && sceneMesh.TextureCoordinateChannels[0].Count > i)
                            {
                                tex = sceneMesh.TextureCoordinateChannels[0][i];
                            }
                            var translated = new Vector3(pos.X, pos.Y, pos.Z) + settings.Translate;
                            meshContent.Vertices[vertex++] = new VertexPositionNormalTexture(
                                new Vector3(translated.X * settings.Scale.X, translated.Y * settings.Scale.Y, translated.Z * settings.Scale.Z),
                                new Vector3(norm.X, norm.Y, norm.Z),
                                new Vector2(tex.X, -tex.Y));
                        }
                    }

                    /*for (int i = 0; i < sceneMesh.VertexCount; i++)
                     * {
                     *
                     * }*/

                    content.Meshes[meshIndex] = meshContent;
                }
                content.Nodes    = new List <NodeContent>();
                content.RootNode = ParseNode(content, scene.RootNode);
                foreach (var animation in scene.Animations)
                {
                    var anim = new AnimationContent();
                    anim.Channels = new List <AnimationNodeContent>();
                    foreach (var channel in animation.NodeAnimationChannels)
                    {
                        AnimationNodeContent node = new AnimationNodeContent();
                        var curNode = content.Nodes.First(n => n.Name == channel.NodeName);
                        node.Node   = curNode;
                        node.Frames = new List <AnimationFrame>();
                        int   frameCount = Math.Max(Math.Max(channel.PositionKeyCount, channel.RotationKeyCount), channel.ScalingKeyCount);
                        float diff = 0.0f, maxTime = 0;;
                        for (int i = 0; i < frameCount; i++)
                        {
                            AnimationFrame frame = new AnimationFrame();

                            if (i < channel.PositionKeyCount)
                            {
                                frame.Frame = (float)channel.PositionKeys[i].Time;
                            }
                            else if (i < channel.RotationKeyCount)
                            {
                                frame.Frame = (float)channel.RotationKeys[i].Time;
                            }
                            else if (i < channel.ScalingKeyCount)
                            {
                                frame.Frame = (float)channel.ScalingKeys[i].Time;
                            }
                            if (i == 0)
                            {
                                diff = frame.Frame;
                            }
                            frame.Frame -= diff;
                            frame.Frame  = (float)(frame.Frame / animation.TicksPerSecond);
                            maxTime      = Math.Max(frame.Frame, maxTime);
                            //TODO: interpolation
                            var rot = channel.RotationKeyCount == 0 ? new Assimp.Quaternion(1, 0, 0, 0) : i >= channel.RotationKeyCount ? channel.RotationKeys.Last().Value : channel.RotationKeys[i].Value;
                            var loc = channel.PositionKeyCount == 0 ? new Assimp.Vector3D() : i >= channel.PositionKeyCount ? channel.PositionKeys.Last().Value : channel.PositionKeys[i].Value;
                            var sca = channel.ScalingKeyCount == 0 ? new Assimp.Vector3D(1, 1, 1) : i >= channel.ScalingKeyCount ? channel.ScalingKeys.Last().Value : channel.ScalingKeys[i].Value;
                            rot.Normalize();

                            frame.Transform = new AnimationTransform(node.Node.Name, new Vector3((loc.X + settings.Translate.X), (loc.Y + settings.Translate.Y), (loc.Z + settings.Translate.Z)),
                                                                     new Vector3(sca.X * settings.Scale.X, sca.Y * settings.Scale.Y, sca.Z * settings.Scale.Z), new Quaternion(rot.X, rot.Y, rot.Z, rot.W));
                            node.Frames.Add(frame);
                        }
                        anim.MaxTime = maxTime;
                        anim.Channels.Add(node);
                    }
                    content.Animations.Add(anim);
                }
                PostProcess(content, content.RootNode);



                return(content);
            }
            catch (Exception ex)
            {
                context.RaiseBuildMessage(filename, ex.Message, BuildMessageEventArgs.BuildMessageType.Error);
            }
            return(null);
        }