Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: RenderTexture / Texture problems  (Read 4102 times)

0 Members and 1 Guest are viewing this topic.

nihohit

  • Newbie
  • *
  • Posts: 37
    • View Profile
RenderTexture / Texture problems
« on: May 15, 2012, 01:07:54 pm »
At some point after creating a RenderTexture, drawing to it, displaying & saving the texture in a sprite, some odd transformation happen - When I'll try to display the sprite, I'll get an error message - either a "tried to divide by zero" after the inner texture's parameters change (sometimes to 0,0, sometimes to impossibly large numbers), or a "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

This happens at a non-deterministic stage, and not at the first time the texture is displayed, and I failed to find a definite result to it. Could this be connected to garbage collection of the RenderTexture after it left operational scope, and something in it's destructor changing it's texture afterwards?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: RenderTexture / Texture problems
« Reply #1 on: May 15, 2012, 01:29:57 pm »
Without some code, it's hard to say anything.
Laurent Gomila - SFML developer

nihohit

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: RenderTexture / Texture problems
« Reply #2 on: May 15, 2012, 04:04:57 pm »
Sorry, couldn't parse it down to the bare minimum, so this came out a bit long.
Running this on debug mode in VS2010 opens a large window with smal green animation. After about two minutes it'll crash.

EDIT: Another run didn't crash, but began blinking white.  The one after threw a "divide by zero" exception after ten seconds. As I said, non-deterministic.

Code: [Select]
using System.Threading;
using System;
using SFML.Window;
using SFML.Graphics;
using System.Collections.Generic;

namespace Game
{
    internal enum Direction { LEFT, RIGHT, UP, DOWN, UPLEFT, UPRIGHT, DOWNLEFT, DOWNRIGHT }

    class main
    {
       

        static int Main(string[] args)
        {
            FileHandler.init();
            RenderWindow main = new RenderWindow(new VideoMode(800, 800), "main");
            List<Direction> list = new List<Direction>{Direction.UP,Direction.UP,Direction.UP,Direction.UP,Direction.UP,
                Direction.UPLEFT,Direction.UPLEFT,Direction.UPLEFT,Direction.UPLEFT,Direction.LEFT,Direction.LEFT,
                Direction.LEFT,Direction.LEFT,Direction.LEFT,Direction.LEFT,Direction.LEFT,Direction.LEFT,
                Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,
                Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,
                Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN,
                Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN};
            List<Sprite> sprites = generateNewComplexPath(list, new Vector2f(100, 100));

            while (true)
            {
                foreach (Sprite sprite in sprites)
                {
                    main.Clear();
                    main.Draw(sprite);
                    main.Display();
                }
            }
            Console.In.ReadLine();
            return 1;
        }

        public static List<Sprite> generateNewComplexPath(List<Direction> path, SFML.Window.Vector2f position)
        {
            Area area = getPathSize(path);
            List<Sprite> list = new List<Sprite>();
            List<Sprite> newSprite = generateNewPathSprite(path, area.Entry);

            list.Clear();
            Sprite temp;
            int count;
            RenderTexture texture;
            for (uint i = 0; i < 10; i++)
            {
                texture = new RenderTexture((uint)area.Size.X, (uint)area.Size.Y);
                for (uint j = 0; j < path.Count / 10; j++)
                {
                    count = (int)(j * 10 + i);
                    if (count < newSprite.Count)
                    {
                        texture.Draw(newSprite[count]);
                    }
                }
                texture.Display();
                temp = new Sprite(texture.Texture);
                temp.Origin = new SFML.Window.Vector2f(area.Entry.X, area.Entry.Y);
                temp.Position = position;
                list.Add(temp);
            }

            return list;
        }

        private static Area getPathSize(List<Direction> path)
        {
            //TODO - no to use magic numbers.
            int xSize = 9, xPos = 4, ySize = 9, yPos = 4, x = 4, y = 4;
            foreach (Direction dir in path)
            {
                switch (dir)
                {
                    case (Direction.DOWN):
                        y++;
                        break;
                    case (Direction.DOWNLEFT):
                        y++;
                        x--;
                        break;
                    case (Direction.DOWNRIGHT):
                        y++;
                        x++;
                        break;
                    case (Direction.LEFT):
                        x--;
                        break;
                    case (Direction.RIGHT):
                        x++;
                        break;
                    case (Direction.UP):
                        y--;
                        break;
                    case (Direction.UPLEFT):
                        y--;
                        x--;
                        break;
                    case (Direction.UPRIGHT):
                        x++;
                        y--;
                        break;
                }
                if (x < 4) { xPos++; xSize++; x = 4; }
                if (y < 4) { yPos++; ySize++; y = 4; }
                if (x >= xSize - 4) { xSize++; }
                if (y >= ySize - 4) { ySize++; }
            }

            return new Area(new Vector(xPos, yPos), new Vector(xSize, ySize));
        }

        private static List<Sprite> generateNewPathSprite(List<Direction> path, Vector initial)
        {
            List<Sprite> newList = new List<Sprite>();
            Texture text = new Texture("images/UI/path.png");
            Sprite temp;
            foreach (Direction dir in path)
            {
                temp = new Sprite(text);
                switch (dir)
                {
                    case (Direction.UP):
                        break;
                    case (Direction.DOWN):
                        temp.Rotation = 180F;
                        break;
                    case (Direction.LEFT):
                        temp.Rotation = 270;
                        break;
                    case (Direction.RIGHT):
                        temp.Rotation = 90F;
                        break;
                    case (Direction.UPRIGHT):
                        temp.Rotation = 45F;
                        break;
                    case (Direction.UPLEFT):
                        temp.Rotation = 315F;
                        break;
                    case (Direction.DOWNRIGHT):
                        temp.Rotation = 135F;
                        break;
                    case (Direction.DOWNLEFT):
                        temp.Rotation = 225F;
                        break;
                }
                initial = initial.addVector(Vector.directionToVector(dir));
                temp.Position = initial.toVector2f();
                newList.Add(temp);
            }

            return newList;
        }
    }

        struct Vector
        {
            private int _x, _y;

            public Vector(int x, int y)
            {
                this._x = x;
                this._y = y;
            }

            public int X
            {
                get { return _x; }
            }

            public int Y
            {
                get { return _y; }
            }

            public Vector addVector(Vector add)
            {
                return new Vector(this._x + add.X, this._y + add.Y);
            }


            public SFML.Window.Vector2f toVector2f()
            {
                return new SFML.Window.Vector2f(Convert.ToSingle(this._x), Convert.ToSingle(this._y));
            }

            static public Vector directionToVector(Direction direction)
            {
                switch (direction)
                {
                    case (Direction.UP):
                        return new Vector(0, -1);

                    case (Direction.DOWN):
                        return new Vector(0, 1);

                    case (Direction.LEFT):
                        return new Vector(-1, 0);

                    case (Direction.RIGHT):
                        return new Vector(1, 0);

                    case (Direction.UPRIGHT):
                        return new Vector(1, -1);

                    case (Direction.DOWNRIGHT):
                        return new Vector(1, 1);

                    case (Direction.UPLEFT):
                        return new Vector(-1, -1);

                    case (Direction.DOWNLEFT):
                        return new Vector(-1, 1);

                    default:
                        throw new Exception("not valid direction found");
                }
            }
        }
       

        internal struct Area
        {
            private readonly Vector _entry; //the top left of the shape
            private Vector _size;


            internal Area(Vector entry, Vector size)
            {
                this._entry = entry;
                this._size = size;
            }

            internal Vector Size
            {
                get { return _size; }
            }

            public Vector Entry
            {
                get { return _entry; }
            }

        }
   
}
« Last Edit: May 15, 2012, 04:47:58 pm by nihohit »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: RenderTexture / Texture problems
« Reply #3 on: May 15, 2012, 04:59:13 pm »
Sorry but it's too long. Is there really nothing that you can remove?
Laurent Gomila - SFML developer

nihohit

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: RenderTexture / Texture problems
« Reply #4 on: May 15, 2012, 05:30:43 pm »
Sorry, didn't notice I can skip the computations, since the values are known.

Code: [Select]
using System.Threading;
using System;
using SFML.Window;
using SFML.Graphics;
using System.Collections.Generic;

namespace Game
{
    internal enum Direction { LEFT, RIGHT, UP, DOWN, UPLEFT, UPRIGHT, DOWNLEFT, DOWNRIGHT }

    class main
    {
       

        static int Main(string[] args)
        {
            List<Direction> list = new List<Direction>{Direction.UP,Direction.UP,Direction.UP,Direction.UP,Direction.UP,
                Direction.UPLEFT,Direction.UPLEFT,Direction.UPLEFT,Direction.UPLEFT,Direction.LEFT,Direction.LEFT,
                Direction.LEFT,Direction.LEFT,Direction.LEFT,Direction.LEFT,Direction.LEFT,Direction.LEFT,
                Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,
                Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,Direction.DOWNLEFT,
                Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN,
                Direction.DOWN,Direction.DOWN,Direction.DOWN,Direction.DOWN};

            RenderWindow main = new RenderWindow(new VideoMode(800, 800), "main");
            List<Sprite> sprites = generateNewComplexPath(list, new Vector2f(100, 100));

            while (true)
            {
                foreach (Sprite sprite in sprites)
                {
                    main.Clear();
                    main.Draw(sprite);
                    main.Display();
                }
            }
            Console.In.ReadLine();
            return 1;
        }

        public static List<Sprite> generateNewComplexPath(List<Direction> path, SFML.Window.Vector2f position)
        {
            Vector2i entry = new Vector2i(28, 13);
            List<Sprite> list = new List<Sprite>();
            List<Sprite> newSprite = generateNewPathSprite(path, entry);
            Sprite temp;
            int count;
            RenderTexture texture;
            for (uint i = 0; i < 10; i++)
            {
                texture = new RenderTexture(33, 33);
                for (uint j = 0; j < path.Count / 10; j++)
                {
                    count = (int)(j * 10 + i);
                    if (count < newSprite.Count)
                    {
                        texture.Draw(newSprite[count]);
                    }
                }
                texture.Display();
                temp = new Sprite(texture.Texture);
                temp.Origin = new SFML.Window.Vector2f(entry.X, entry.Y);
                temp.Position = position;
                list.Add(temp);
            }

            return list;
        }

        private static List<Sprite> generateNewPathSprite(List<Direction> path, Vector2i initial)
        {
            List<Sprite> newList = new List<Sprite>();
            Texture text = new Texture("images/UI/path.png");
            Sprite temp;
            foreach (Direction dir in path)
            {
                temp = new Sprite(text);
                initial = new Vector2i(initial.X-1, initial.Y+1);
                temp.Position = toVector2f(initial);
                newList.Add(temp);
            }
            return newList;
        }

        private static Vector2f toVector2f(Vector2i initial)
        {
            return new Vector2f(initial.X, initial.Y);
        }
    }
   
}


Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: RenderTexture / Texture problems
« Reply #5 on: May 15, 2012, 05:53:34 pm »
You can't use the texture of a destroyed RenderTexture. SFML (C++) will internally destroy it, so even if you have a reference to it in your C# code, it will be invalid. A solution would be to use a copy of the texture.
Laurent Gomila - SFML developer

nihohit

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: RenderTexture / Texture problems
« Reply #6 on: May 15, 2012, 06:09:27 pm »
That works. Thanks!