Error in 14.3

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Fax3D
Posts: 22
Joined: Mon Sep 29, 2008 7:42 am

Error in 14.3

Post by Fax3D »

Hi Norbo,

i've just update to last 14.3 version and i started getting this error when i try to extract vertex data from an xna model:

Code: Select all

System.FormatException was unhandled
  Message=Unsupported vertex type in mesh.
  Source=BEPUphysics
  StackTrace:
       at BEPUphysics.DataStructures.TriangleMesh.AddMesh(ModelMesh collisionModelMesh, Matrix transform, List`1 vertices, List`1 indices)
       at BEPUphysics.DataStructures.TriangleMesh.GetVerticesAndIndicesFromModel(Model collisionModel, Vector3[]& vertices, Int32[]& indices)
       at BEPUphysics.StaticTriangleGroup.GetVerticesAndIndicesFromModel(Model collisionModel, StaticTriangleGroupVertex[]& vertices, Int32[]& indices)
This is my function:

Code: Select all

        private List<Vector3> GetVerticesFromModel(float p_Scale)
        {
            int[] _staticTriangleIndices;
            StaticTriangleGroup.StaticTriangleGroupVertex[] _staticTriangleVertices;

            StaticTriangleGroup.GetVerticesAndIndicesFromModel(m_XnaModel, out _staticTriangleVertices, out _staticTriangleIndices);
            List<Vector3> _points = new List<Vector3>();
            foreach (StaticTriangleGroup.StaticTriangleGroupVertex triangle in _staticTriangleVertices)
            {
                Vector3 _pos = Vector3.Transform(triangle.Position, Matrix.CreateScale(p_Scale));
                _points.Add(_pos);
            }

            return _points;
        }
What's wrong? With previous version i've never had any problem...


Thanks in advance!

Fax3D
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Error in 14.3

Post by Norbo »

The vertex extractor in v0.14.2 and before does not work properly on the WP7 hardware due to an issue with the VertexBuffer.GetData method it used. In the XNA 4.0 RTM release notes it says:
2. On Windows Phone devices, VertexBuffer.GetData will not return correct results for the overload of this method which allows developers to set the vertexStride parameter. Accessing data with this overload will return the correct data for the Windows Phone Emulator, Windows, and Xbox 360 games. As a work around for Windows Phone games, games must read the entire vertex buffer instead of using the vertex stride to locate elements.
I could have had a separate path for WP7 versus Windows/Xbox360, but given the relative unimportance of this convenience method and the desire to maintain a consistent behavior across all platforms, I opted for the replacement which works for some built-in vertex types.

If the new system causes problems, I would recommend using a content processor to extract the vertices. This is the typically recommended method of extracting vertices anyway.
Fax3D
Posts: 22
Joined: Mon Sep 29, 2008 7:42 am

Re: Error in 14.3

Post by Fax3D »

Thanks very much, i solved my issue writing my own custom importer with a custom vertex!

Fax3D
Danthekilla
Posts: 136
Joined: Sun Jan 17, 2010 11:35 am

Re: Error in 14.3

Post by Danthekilla »

Any chance we could have a look at your processor? Ours we made is not quite working...
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Error in 14.3

Post by Norbo »

There should be one in the Triangle Picking sample on the XNA website if you still need it.
Fax3D
Posts: 22
Joined: Mon Sep 29, 2008 7:42 am

Re: Error in 14.3

Post by Fax3D »

This is the code to extract vertices:

Code: Select all

private List<Vector3> GetVerticesModel(float p_Scale)
        {
            List<Vector3> _points = new List<Vector3>();

            foreach (ModelMesh modelMesh in m_XnaModel.Meshes)
            {
                foreach (ModelMeshPart part in modelMesh.MeshParts)
                {
                    VertexPositionNormalTextureBinormalTangent[] _vertices = new VertexPositionNormalTextureBinormalTangent[part.VertexBuffer.VertexCount];
                    part.VertexBuffer.GetData<VertexPositionNormalTextureBinormalTangent>(_vertices);

                    foreach (VertexPositionNormalTextureBinormalTangent vertices in _vertices)
                    {
                        _points.Add(Vector3.Transform(vertices.Position, Matrix.CreateScale(p_Scale)));
                    }
                }
            }

            return _points;
        }
This is the definition of my custom vertex (VertexPositionNormalTextureBinormalTangent)

Code: Select all

public struct VertexPositionNormalTextureBinormalTangent : IVertexType
    {
        Vector3 vertexPosition;
        Vector3 vertexNormal;
        Vector2 vertexTextureCoordinate;
        Vector3 vertexBinormal;
        Vector3 vertexTangent;

        public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration
        (
            new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
            new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0),
            new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
            new VertexElement(32, VertexElementFormat.Vector3, VertexElementUsage.Binormal, 0),
            new VertexElement(44, VertexElementFormat.Vector3, VertexElementUsage.Tangent, 0)
        );

        public VertexPositionNormalTextureBinormalTangent(Vector3 pos, Vector3 normal, Vector2 textureCoordinate, Vector3 binormal, Vector3 tangent)
        {
            vertexPosition = pos;
            vertexNormal = normal;
            vertexTextureCoordinate = textureCoordinate;
            vertexBinormal = binormal;
            vertexTangent = tangent;
        }

        public Vector3 Position
        {
            get { return vertexPosition; }
            set { vertexPosition = value; }
        }

        VertexDeclaration IVertexType.VertexDeclaration
        {
            get { return VertexDeclaration; }
        }
    }
And finally, my custom model processor. As you will see i create for each model the same vertex channel in output to match my custom vertex. If the model hasn't the vertex channel i need, i create it without any data. This isn't a good thing, but it's just an example to make you understand, you'll modify the code for computing all data you need, like binormal or tangent.

Code: Select all

[ContentProcessor(DisplayName = "CustomImporter.ModelImporter")]
    public class ModelImporter : ModelProcessor
    {

        static IList<string> acceptableVertexChannelNames =
            new string[]
            {                
                VertexChannelNames.Normal(0),
                VertexChannelNames.TextureCoordinate(0),
                VertexChannelNames.Binormal(0),
                VertexChannelNames.Tangent(0)
            };

        protected override void ProcessVertexChannel(GeometryContent geometry, int vertexChannelIndex, ContentProcessorContext context)
        {
            String vertexChannelName = geometry.Vertices.Channels[vertexChannelIndex].Name;

            if (!geometry.Vertices.Channels.Contains(acceptableVertexChannelNames[0]))
            {
                Vector3[] _tc = new Vector3[geometry.Vertices.VertexCount];
                geometry.Vertices.Channels.Add(acceptableVertexChannelNames[0], typeof(Vector3), _tc);
            }

            if (!geometry.Vertices.Channels.Contains(acceptableVertexChannelNames[1]))
            {
                Vector2[] _nr = new Vector2[geometry.Vertices.VertexCount];
                geometry.Vertices.Channels.Add(acceptableVertexChannelNames[1], typeof(Vector2), _nr);
            }

            if (!geometry.Vertices.Channels.Contains(acceptableVertexChannelNames[2]))
            {
                Vector3[] _bn = new Vector3[geometry.Vertices.VertexCount];
                geometry.Vertices.Channels.Add(acceptableVertexChannelNames[2], typeof(Vector3), _bn);
            }

            if (!geometry.Vertices.Channels.Contains(acceptableVertexChannelNames[3]))
            {
                Vector3[] _tn = new Vector3[geometry.Vertices.VertexCount];
                geometry.Vertices.Channels.Add(acceptableVertexChannelNames[3], typeof(Vector3), _tn);
            }

            if (acceptableVertexChannelNames.Contains(vertexChannelName))
            {
                base.ProcessVertexChannel(geometry, vertexChannelIndex, context);
            }
            else
            {
                geometry.Vertices.Channels.Remove(vertexChannelName);
            }
        }
    }
Hope this helps!

Fax3D
Post Reply