stride3d/stride · error · ArgumentException
meshData is not simple.
Error message
meshData is not simple.
What it means
GenerateTangentBinormal computes per-vertex tangents and binormals and only supports 'simple' meshes — a single vertex buffer containing all attributes. This ArgumentException is thrown when meshData.IsSimple() returns false (multiple vertex buffers or non-simple layout), because the tangent math indexes directly into VertexBuffers[0].
Solutions
- Re-interleave the mesh into one vertex buffer so IsSimple() is true, then compute tangents
- Compute tangents manually for multi-buffer meshes (parallel arrays) instead of using this extension
- Skip tangent generation and supply tangents from the asset/importer
Example fix
// before
mesh.GenerateTangentBinormal(); // multi-buffer mesh
// after
if (mesh.IsSimple())
mesh.GenerateTangentBinormal();
else
mesh = RebuildSingleBuffer(mesh); // then GenerateTangentBinormal Defensive patterns
Strategy: validation
Validate before calling
if (mesh.IsSimple()) mesh.GenerateTangentBinormal(); else mesh = RebuildSingleBuffer(mesh); // then generate tangents
Type guard
static bool CanGenerateTangents(MeshDraw mesh) => mesh.IsSimple();
Try / catch
try { mesh.GenerateTangentBinormal(); }
catch (ArgumentException ex) when (ex.Message.Contains("not simple")) {
mesh = RebuildSingleBuffer(mesh);
mesh.GenerateTangentBinormal();
} Prevention
- Ensure meshData.IsSimple() holds before any tangent/BINORMAL post-processing
- Rebuild multi-buffer meshes into a single interleaved buffer at import
- Automate tangent generation inside the asset pipeline where layout is guaranteed
When it happens
Trigger: Calling GenerateTangentBinormal on a MeshDraw with multiple vertex buffers, or one whose declaration is not a simple interleaved layout.
Common situations: Meshes with split position/attribute streams; multi-buffer meshes produced by merge tooling; forgetting to check IsSimple before generating tangents.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Non-matching vertex buffer declarations.
- Can only merge TriangleList.
- The mesh Data needs to have index buffer
- Sorting not implemented for multiple vertex buffers by…
- msaaResolverShaderName
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/9e0df2a4c6209b74.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Rendering/Extensions/TNBExtensions.cs:23
using Stride.Graphics.Data;
using Stride.Rendering;
namespace Stride.Extensions
{
public static class TNBExtensions
{
/// <summary>
/// Generates the tangents and binormals for this mesh data.
/// Tangents and bitangents will be encoded as float4:
/// float3 for tangent and an additional float for handedness (1 or -1),
/// so that bitangent can be reconstructed.
/// More info at http://www.terathon.com/code/tangent.html
/// </summary>
/// <param name="meshData">The mesh data.</param>
public static unsafe void GenerateTangentBinormal(this MeshDraw meshData)
{
if (!meshData.IsSimple())
throw new ArgumentException("meshData is not simple.");
if (meshData.PrimitiveType != PrimitiveType.TriangleList
&& meshData.PrimitiveType != PrimitiveType.TriangleListWithAdjacency)
throw new NotImplementedException();
var oldVertexBufferBinding = meshData.VertexBuffers[0];
var indexBufferBinding = meshData.IndexBuffer;
var indexData = indexBufferBinding?.Buffer.GetSerializationData().Content;
var oldVertexStride = oldVertexBufferBinding.Declaration.VertexStride;
var bufferData = oldVertexBufferBinding.Buffer.GetSerializationData().Content;
fixed (byte* indexBufferStart = indexData)
fixed (byte* oldBuffer = bufferData)
{
var result = VertexHelper.GenerateTangentBinormal(
vertexDeclaration: oldVertexBufferBinding.Declaration,
vertexBufferData: (nint)oldBuffer,View on GitHub (pinned to 96fad776d2)