texturing a polygon

Topics: Developer Forum, User Forum
Aug 25, 2011 at 9:23 PM

I've been banging my head on this for 3 days. I'm trying to tile a texture from a polygon I generated from an image.  It appears when the polygon is drawn it stretches and rotates the texture instead of tiling it.  I know pharseer is only a physics engine and doesnt do the drawing but can someone please check out this code and see where I'm going wrong?  I think the problem is with the uv mapping.

 

    public class PolyBatch2 : IDisposable
    {
        private ContentManager _content;
        private const int DefaultBufferSize = 500;
        private Vector2[] _tempVertices = new Vector2[Settings.MaxPolygonVertices];
        private VertexPositionNormalTexture[] _triangleVertices;
        private int _triangleVertsCount;
        // a basic effect, which contains the shaders that we will use to draw our
        // primitives.
        private BasicEffect _basicEffect;
        Texture2D texture;

        // the device that we will issue draw calls to.
        private GraphicsDevice _device;

        // hasBegun is flipped to true once Begin is called, and is used to make
       //s cled.
        private bool _hasBegun;


        private bool _isDisposed;
        private VertexPositionColor[] _lineVertices;
        private int _lineVertsCount;

        //public PolyBatch(GraphicsDevice graphicsDevice)
        //    : this(graphicsDevice, DefaultBufferSize)
        //{
        //}

        public PolyBatch2(GraphicsDevice graphicsDevice, int bufferSize, Texture2D tiletexture)
        {
            if (graphicsDevice == null)
            {
                throw new ArgumentNullException("graphicsDevice");
            }
            
            _device = graphicsDevice;

            texture = tiletexture;

            _triangleVertices = new VertexPositionNormalTexture[bufferSize - bufferSize % 3];
            _basicEffect = new BasicEffect(graphicsDevice);

        }

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            
            GC.SuppressFinalize(this);
        }

        #endregion

        protected virtual void Dispose(bool disposing)
        {
            if (disposing && !_isDisposed)
            {
                if (_basicEffect != null)
                    _basicEffect.Dispose();

                _isDisposed = true;
            }
        }

        public void Begin(Matrix projection, Matrix view)
        {
            if (_hasBegun)
            {
                throw new InvalidOperationException("End must be called before Begin can be called again.");
            }
_basicEffect.Texture = texture;
            _basicEffect.TextureEnabled = true;
            _basicEffect.Projection = projection;
            _basicEffect.View = view;
            _basicEffect.CurrentTechnique.Passes[0].Apply();

            _hasBegun = true;
        }

       
        public void DrawPolyShape(Shape shape, Color color, Transform xf)
        {

            

            
            if (shape.ShapeType == ShapeType.Polygon)
            {
                PolygonShape poly = (PolygonShape)shape;
                Min = new Vector2(float.MaxValue, float.MaxValue); Max = new Vector2(float.MinValue, float.MinValue);
               

                foreach (var point in poly.Vertices)
                {
                    if (point.X < Min.X)
                        Min.X = point.X;
                    if (point.Y < Min.Y)
                        Min.Y = point.Y;

                    if (point.X > Max.X)
                        Max.X = point.X;
                    if (point.Y > Max.Y)
                        Max.Y = point.Y;
                }
                 int vertexCount = poly.Vertices.Count;
                

                for (int i = 0; i < vertexCount; ++i)
                {
                    _tempVertices[i] = MathUtils.Multiply(ref xf, poly.Vertices[i]);
                }
                Map(Min, Max);
                DrawTexturedPolygon(_tempVertices, vertexCount, color,false);
            }
        }
        public void DrawTexturedPolygon(Vector2[] vertices, int count, Color color, bool outline)
        {
 
            for (int i = 1; i < count - 1; i++)
            {
                   AddVertex(vertices[0],  PrimitiveType.TriangleList, UVs[0]);
                   AddVertex(vertices[i],  PrimitiveType.TriangleList, UVs[i]);
                   AddVertex(vertices[i + 1],  PrimitiveType.TriangleList, UVs[i+1]);

            }
        }
        public Texture2D Texture;
        public Vector2 Min, Max;
        

       
       List UVs = new List();
        public void Map(Vector2 topLeft, Vector2 bottomRight)
        {
            UVs.Clear();
            for (int i = 0; i < _tempVertices.Length-1; i++)
            {
                UVs.Add(new Vector2(Math.Abs((_tempVertices[i].X + topLeft.X) / (bottomRight.X - topLeft.X)), Math.Abs((_tempVertices[i].Y + topLeft.Y) / (bottomRight.Y - topLeft.Y))));
            }
        }

        public void End()
        {
            if (!_hasBegun)
            {
                throw new InvalidOperationException("Begin must be called before End can be called.");
            }

            FlushTriangles();
            Flush();

            _hasBegun = false;
        }

        private void Flush()
        {
            if (!_hasBegun)
            {
                throw new InvalidOperationException("Begin must be called before Flush can be called.");
            }
            if (_lineVertsCount >= 2)
            {
                int primitiveCount = _lineVertsCount / 2;
                _device.DrawUserPrimitives(PrimitiveType.LineList, _lineVertices, 0, primitiveCount);
                _lineVertsCount -= primitiveCount * 2;
            }
        }
        public void AddVertex(Vector2 vertex, PrimitiveType primitiveType, Vector2 textpos)
        {
            

            if (primitiveType == PrimitiveType.TriangleList)
            {
                if (_triangleVertsCount >= _triangleVertices.Length)
                {
                    FlushTriangles();
                }
                
                _triangleVertices[_triangleVertsCount].Position = new Vector3(vertex, -0.1f);

                _triangleVertices[_triangleVertsCount].TextureCoordinate = textpos;
                _triangleVertsCount++;
            }
           
        }
        private void FlushTriangles()
        {
            if (!_hasBegun)
            {
                throw new InvalidOperationException("Begin must be called before Flush can be called.");
            }
            if (_triangleVertsCount >= 3)
            {
                int primitiveCount = _triangleVertsCount / 3;
                
                _device.RasterizerState = RasterizerState.CullNone;
                _device.SamplerStates[0] = SamplerState.LinearWrap;
               _device.DrawUserPrimitives(PrimitiveType.TriangleList, _triangleVertices, 0, primitiveCount);
                _triangleVertsCount -= primitiveCount * 3;
            }
        }
    }
}
Aug 27, 2011 at 12:52 AM

I'm starting to think this isnt possible.

Aug 27, 2011 at 4:34 PM

take a look at texture cuting here: http://farseerphysics.codeplex.com/discussions/261926

Aug 28, 2011 at 12:14 AM

I was working with that one but the I think I'm having is that the texture is smaller then the triangle.  So i'm trying to get it to "tile" the texture but I havent been able too get it.

Aug 28, 2011 at 7:42 AM

I'm not much of a graphics person, and I don't have the time to truly dig into your code, but it sounds like you're not setting the UV coordinates correctly.  If you want the texture to wrap, your UV coordinate needs to be greater than 1.

Say you have a box:

A              B
+--------------+
|              |
|              |
|              |
|              |
+--------------+
C              D

For regular texturing, A should be 0,0, B should be 1,0, C should be 0,1, and D should be 1,1.  The coordinates are interpolated based on that, so halfway along the top edge is 0.5, 0, etc.  If you want it to tile, then, you have to set B to 2,0, C to 0,2, and D to 2,2.  Thus, the centerpoint of the polygon would be "1,1", representing the bottom corner of the texture, and since there's "more polygon to fill", it will wrap and start back over at 0,0.