diff --git a/src/RWGltf/RWGltf_GltfJsonParser.cxx b/src/RWGltf/RWGltf_GltfJsonParser.cxx index 89feb12a9f..6c3b78c180 100644 --- a/src/RWGltf/RWGltf_GltfJsonParser.cxx +++ b/src/RWGltf/RWGltf_GltfJsonParser.cxx @@ -1522,7 +1522,7 @@ bool RWGltf_GltfJsonParser::gltfParseAccessor (const Handle(RWGltf_GltfLatePrimi const RWGltf_JsonValue* aTypeStr = findObjectMember (theAccessor, "type"); const RWGltf_JsonValue* aBufferViewName = findObjectMember (theAccessor, "bufferView"); const RWGltf_JsonValue* aByteOffset = findObjectMember (theAccessor, "byteOffset"); - const RWGltf_JsonValue* aByteStride = findObjectMember (theAccessor, "byteStride"); + const RWGltf_JsonValue* aByteStride = findObjectMember (theAccessor, "byteStride"); // byteStride was part of bufferView in glTF 1.0 const RWGltf_JsonValue* aCompType = findObjectMember (theAccessor, "componentType"); const RWGltf_JsonValue* aCount = findObjectMember (theAccessor, "count"); if (aTypeStr == NULL @@ -1664,6 +1664,7 @@ bool RWGltf_GltfJsonParser::gltfParseBufferView (const Handle(RWGltf_GltfLatePri const RWGltf_JsonValue* aBufferName = findObjectMember (theBufferView, "buffer"); const RWGltf_JsonValue* aByteLength = findObjectMember (theBufferView, "byteLength"); const RWGltf_JsonValue* aByteOffset = findObjectMember (theBufferView, "byteOffset"); + const RWGltf_JsonValue* aByteStride = findObjectMember (theBufferView, "byteStride"); // byteStride is part of bufferView since glTF 2.0 const RWGltf_JsonValue* aTarget = findObjectMember (theBufferView, "target"); if (aBufferName == NULL) { @@ -1677,6 +1678,9 @@ bool RWGltf_GltfJsonParser::gltfParseBufferView (const Handle(RWGltf_GltfLatePri aBuffView.ByteLength = aByteLength != NULL && aByteLength->IsNumber() ? (int64_t )aByteLength->GetDouble() : 0; + aBuffView.ByteStride = aByteStride != NULL && aByteStride->IsInt() + ? aByteStride->GetInt() + : 0; if (aTarget != NULL && aTarget->IsInt()) { aBuffView.Target = (RWGltf_GltfBufferViewTarget )aTarget->GetInt(); @@ -1698,6 +1702,12 @@ bool RWGltf_GltfJsonParser::gltfParseBufferView (const Handle(RWGltf_GltfLatePri reportGltfError ("BufferView '" + theName + "' defines invalid byteOffset."); return false; } + else if (aBuffView.ByteStride < 0 + || aBuffView.ByteStride > 255) + { + reportGltfError ("BufferView '" + theName + "' defines invalid byteStride."); + return false; + } const RWGltf_JsonValue* aBuffer = myGltfRoots[RWGltf_GltfRootElement_Buffers].FindChild (*aBufferName); if (aBuffer == NULL @@ -1726,6 +1736,7 @@ bool RWGltf_GltfJsonParser::gltfParseBuffer (const Handle(RWGltf_GltfLatePrimiti const RWGltf_JsonValue* anUriVal = findObjectMember (theBuffer, "uri"); int64_t anOffset = theView.ByteOffset + theAccessor.ByteOffset; + const int32_t aByteStride = theAccessor.ByteStride != 0 ? theView.ByteStride : theView.ByteStride; bool isBinary = false; if (myIsBinary) { @@ -1738,6 +1749,7 @@ bool RWGltf_GltfJsonParser::gltfParseBuffer (const Handle(RWGltf_GltfLatePrimiti RWGltf_GltfPrimArrayData& aData = theMeshData->AddPrimArrayData (theType); aData.Accessor = theAccessor; + aData.Accessor.ByteStride = aByteStride; aData.StreamOffset = anOffset; aData.StreamUri = myFilePath; return true; @@ -1755,6 +1767,7 @@ bool RWGltf_GltfJsonParser::gltfParseBuffer (const Handle(RWGltf_GltfLatePrimiti { RWGltf_GltfPrimArrayData& aData = theMeshData->AddPrimArrayData (theType); aData.Accessor = theAccessor; + aData.Accessor.ByteStride = aByteStride; aData.StreamOffset = anOffset; if (!myDecodedBuffers.Find (theName, aData.StreamData)) { @@ -1788,6 +1801,7 @@ bool RWGltf_GltfJsonParser::gltfParseBuffer (const Handle(RWGltf_GltfLatePrimiti RWGltf_GltfPrimArrayData& aData = theMeshData->AddPrimArrayData (theType); aData.Accessor = theAccessor; + aData.Accessor.ByteStride = aByteStride; aData.StreamOffset = anOffset; aData.StreamUri = myFolder + anUri; if (myExternalFiles != NULL) diff --git a/tests/de_mesh/gltf_read/boxinterleaved b/tests/de_mesh/gltf_read/boxinterleaved new file mode 100644 index 0000000000..d309473ba4 --- /dev/null +++ b/tests/de_mesh/gltf_read/boxinterleaved @@ -0,0 +1,35 @@ +puts "========" +puts "0031332: Data Exchange - RWGltf_CafReader ignores bufferView.byteStride within glTF 2.0" +puts "========" + +# glTF file content +set cubeGltf { +{ +"asset": {"generator": "","version": "2.0"}, +"scene": 0, +"scenes": [{"nodes": [0]}], +"nodes": [{"children": [1],"matrix": [1.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0]},{"mesh": 0}], +"meshes": [{"primitives": [{"attributes": {"NORMAL": 1,"POSITION": 2},"indices": 0,"mode": 4,"material": 0}],"name": "Mesh"}], +"accessors": [ +{"bufferView": 0,"byteOffset": 0, "componentType": 5123,"count": 36,"max": [23],"min": [0],"type": "SCALAR"}, +{"bufferView": 1,"byteOffset": 0, "componentType": 5126,"count": 24,"max": [1.0,1.0,1.0],"min": [-1.0,-1.0,-1.0],"type": "VEC3"}, +{"bufferView": 1,"byteOffset": 12,"componentType": 5126,"count": 24,"max": [0.5,0.5,0.5],"min": [-0.5,-0.5,-0.5],"type": "VEC3"} +], +"materials": [{"pbrMetallicRoughness": {"baseColorFactor": [0.800000011920929,0.0,0.0,1.0]}}], +"bufferViews": [ +{"buffer": 0,"byteOffset": 576,"byteLength": 72,"target": 34963}, +{"buffer": 0,"byteOffset": 0, "byteLength": 576,"byteStride": 24,"target": 34962} +], +"buffers": [{"byteLength": 648,"uri": "data:application/octet-stream;base64,AAAAAAAAAAAAAIA/AAAAvwAAAL8AAAA/AAAAAAAAAAAAAIA/AAAAPwAAAL8AAAA/AAAAAAAAAAAAAIA/AAAAvwAAAD8AAAA/AAAAAAAAAAAAAIA/AAAAPwAAAD8AAAA/AAAAAAAAgL8AAAAAAAAAPwAAAL8AAAA/AAAAAAAAgL8AAAAAAAAAvwAAAL8AAAA/AAAAAAAAgL8AAAAAAAAAPwAAAL8AAAC/AAAAAAAAgL8AAAAAAAAAvwAAAL8AAAC/AACAPwAAAAAAAAAAAAAAPwAAAD8AAAA/AACAPwAAAAAAAAAAAAAAPwAAAL8AAAA/AACAPwAAAAAAAAAAAAAAPwAAAD8AAAC/AACAPwAAAAAAAAAAAAAAPwAAAL8AAAC/AAAAAAAAgD8AAAAAAAAAvwAAAD8AAAA/AAAAAAAAgD8AAAAAAAAAPwAAAD8AAAA/AAAAAAAAgD8AAAAAAAAAvwAAAD8AAAC/AAAAAAAAgD8AAAAAAAAAPwAAAD8AAAC/AACAvwAAAAAAAAAAAAAAvwAAAL8AAAA/AACAvwAAAAAAAAAAAAAAvwAAAD8AAAA/AACAvwAAAAAAAAAAAAAAvwAAAL8AAAC/AACAvwAAAAAAAAAAAAAAvwAAAD8AAAC/AAAAAAAAAAAAAIC/AAAAvwAAAL8AAAC/AAAAAAAAAAAAAIC/AAAAvwAAAD8AAAC/AAAAAAAAAAAAAIC/AAAAPwAAAL8AAAC/AAAAAAAAAAAAAIC/AAAAPwAAAD8AAAC/AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUA"}] +} +} + +set fd [open ${imagedir}/${casename}.gltf w] +fconfigure $fd -translation lf +puts $fd $cubeGltf +close $fd + +ReadGltf D ${imagedir}/${casename}.gltf +XGetOneShape s D +checknbshapes s -face 1 -compound 0 +checktrinfo s -tri 12 -nod 24