Loading an huge, single textured world into Farseer

Jun 18, 2010 at 9:14 AM
Edited Jun 18, 2010 at 10:43 AM
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Factories;

namespace BaseDefend.Levels
{
    class Level
    {
        public static void CreateHugeWorld(Texture2D Texture, GraphicsDevice graphics,
            out List<Body> body, out List<Geom> geom, out List<Vector2> origin, PhysicsSimulator phy)
        {
            using (SpriteBatch spriteBatch = new SpriteBatch(graphics))
            {
                body = new List<Body>();
                geom = new List<Geom>();
                origin = new List<Vector2>();

                int Width = Texture.Width / 500;
                int Height = Texture.Height / 500 + 1;

                Texture2D[,] SubTextures = new Texture2D[Width, Height];
                PresentationParameters pp = graphics.PresentationParameters;
                RenderTarget2D target = new RenderTarget2D(graphics, 500, 500, 1, graphics.DisplayMode.Format,
                    pp.MultiSampleType, pp.MultiSampleQuality);

                for (int x = 0; x < Width; x++)
                {
                    for (int y = 0; y < Height; y++)
                    {
                        graphics.Clear(Color.Black);
                        graphics.SetRenderTarget(0, target);
                        graphics.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);
                        spriteBatch.Begin();
                        spriteBatch.Draw(Texture, Vector2.Zero, new Rectangle(x * 500, y * 500, 500, 500), Color.White);
                        spriteBatch.End();
                        graphics.SetRenderTarget(0, null);

                        Texture2D texture = target.GetTexture();

                        Color[] dataC = new Color[texture.Width * texture.Height];
                        texture.GetData(dataC);
                        for (int i = 0; i < dataC.Length; i++)
                            if (dataC[i] != Color.TransparentBlack)
                                dataC[i].A = 255;

                        Texture2D texture2 = new Texture2D(graphics, 500, 500);
                        texture2.SetData(dataC);

                        SubTextures[x, y] = texture2;
                        //SubTextures[x, y].Save(x + "," + y + ".png", ImageFileFormat.Png);
                    }
                }

                for (int x = 0; x < Width; x++)
                {
                    for (int y = 0; y < Height; y++)
                    {
                        Texture2D texture = SubTextures[x, y];

                        Color[] dataC = new Color[texture.Width * texture.Height];
                        uint[] dataU = new uint[texture.Width * texture.Height];
                        texture.GetData(dataC);

                        for (int i = 0; i < texture.Width * texture.Height; i++)
                            dataU[i] = dataC[i].PackedValue;

                        List<Vertices> vertices = Vertices.CreatePolygon(dataU, texture.Width, texture.Height, 0, 1, true, false);
                        foreach (Vertices vertice in vertices)
                        {
                            vertice.SubDivideEdges(7);

                            Body Body = BodyFactory.Instance.CreatePolygonBody(phy, vertice, 1);
                            Body.Position += new Vector2(x * 500, y * 500);
                            Body.IsStatic = true;
                            Geom Geom = GeomFactory.Instance.CreatePolygonGeom(phy, Body, vertice, 0);
                            Geom.FrictionCoefficient = 10;
                            Geom.RestitutionCoefficient = 0;
                            body.Add(Body);
                            geom.Add(Geom);
                            origin.Add(vertice.GetCentroid());
                        }
                    }
                }

                foreach (Texture2D subtexture in SubTextures)
                    subtexture.Dispose();
            }
        }
    }
}

Hi!

I did this code as I had to load a huge world into farseer, wich was single textured.

What this code does is that it breaks down the large texture into smaller textures, and then creates a body and geom from that each of those textures, at the real position, then all you have to do is to draw that huge texture, whitout lag! I think that the biggest texture I've loaded into it was about 5000 * 2500, it was updated and drawn without lag! (With objects on it!)

 

Developer
Jun 19, 2010 at 8:41 PM

I think I might port this to FP 3.0.

 

Aug 8, 2010 at 5:19 PM

Thanks!