How to animate 3d asset (.obj) file loaded with Model I/O framework on metal





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















The obj file loaded with Model I/O. I receive vertex buffer and index buffer from mesh and submesh. I draw it with index buffer. In GPU buffer unpacked and load all triangles.
When I load asset I am creating vertex descriptor, to say what should be loaded from 3D asset. When I pass it to shader I am using [[ stage_in ]] vertex parameter.



But somehow I need to change the structure of vertex that is created by loading model asset in parameter of vertex-shader function to pass more data with animation offset for each vertex. For example I need to pass data that in an 3D asset, to apply offset to all vertices.



vertex VertexOut vertex_main(VertexIn vertexIn [[ stage_in ]], constant Uniforms &uniforms [[ buffer(1) ]], uint vertexID [[ vertex_id ]]) {
float4 worldPosition = uniforms.modelMatrix *float4(vertexIn.position, 1);
VertexOut vertexOut;
vertexOut.position = uniforms.viewProjectionMatrix * worldPosition;
vertexOut.worldPosition = worldPosition.xyz;
vertexOut.worldNormal = uniforms.normalMatrix * vertexIn.normal;
vertexOut.texCoords = vertexIn.texCoords;
return vertexOut;
}


That how looks VertexIn



struct VertexIn {
float3 position [[attribute(0)]];
float3 normal [[attribute(1)]];
float2 texCoords [[attribute(2)]];
};


Drawing of 3D asset



for mesh in meshes {
for i in 0..<mesh.vertexBuffers.count {
let vertexBuffer = mesh.vertexBuffers[i]
commandEncoder.setVertexBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: i)
}

for submesh in mesh.submeshes {
let indexBuffer = submesh.indexBuffer
commandEncoder.drawIndexedPrimitives(type: submesh.primitiveType,
indexCount: submesh.indexCount,
indexType: submesh.indexType,
indexBuffer: indexBuffer.buffer,
indexBufferOffset: indexBuffer.offset)
}
}


Vertex descriptor for loading 3D Model asset



    let vertexDescriptor = MDLVertexDescriptor()
vertexDescriptor.attributes[0] = MDLVertexAttribute(name: MDLVertexAttributePosition, format: .float3, offset: 0, bufferIndex: 0)
vertexDescriptor.attributes[1] = MDLVertexAttribute(name: MDLVertexAttributeNormal, format: .float3, offset: MemoryLayout<Float>.size * 3, bufferIndex: 0)
vertexDescriptor.attributes[2] = MDLVertexAttribute(name: MDLVertexAttributeTextureCoordinate, format: .float2, offset: MemoryLayout<Float>.size * 6, bufferIndex: 0)

vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: MemoryLayout<Float>.size * 8)


Thank you for help.
P.S.
I was trying to change after loading of 3d asset, but it fails, because I can't change the vertex buffer created with Model I/O.










share|improve this question























  • It seems to me that you could load the vertex offsets into your own MTLBuffer and pass that as an argument to your vertex function. You'd probably want to use triple buffering to keep three "frames" of animation data in flight at once.

    – warrenm
    Nov 16 '18 at 17:10











  • @warrenm I've made it with buffer, just with one, without triple buffering, and it came out that the order of my buffer that consist of animation offset for each vertices is wrong. And that strange. Because I thought that is unpacked in same order as it goes in my .obj file with defined faces example(f 1/1/1'). But it appeared that no. Could I be wrong ?

    – Ivan Tkachenko
    Nov 19 '18 at 14:16











  • You absolutely can't rely on the order of vertices in the file to correspond 1:1 with the vertices in your buffer after loading. OBJ allows separate indexing of position, normal, and texcoord data, so the data in the resulting buffers is almost always in a completely different order than the input. Admittedly, that makes vertex animation based on offsets a challenge.

    – warrenm
    Nov 19 '18 at 18:00











  • If your animation data is dense (i.e., every frame has an offset for every vertex), you might be better off using a series of OBJ files that have absolute positions instead. Or use a format like glTF that has a notion of animation built into the format.

    – warrenm
    Nov 19 '18 at 18:02






  • 1





    You can leave room in the vertex buffers by configuring the offsets of the attributes and the strides of the layouts. Then you can write the offsets into the "blank" space between vertices. But it seems you'd still need a way to determine the mapping from the vertices in the original model and the loaded vertices.

    – warrenm
    Nov 22 '18 at 16:58


















0















The obj file loaded with Model I/O. I receive vertex buffer and index buffer from mesh and submesh. I draw it with index buffer. In GPU buffer unpacked and load all triangles.
When I load asset I am creating vertex descriptor, to say what should be loaded from 3D asset. When I pass it to shader I am using [[ stage_in ]] vertex parameter.



But somehow I need to change the structure of vertex that is created by loading model asset in parameter of vertex-shader function to pass more data with animation offset for each vertex. For example I need to pass data that in an 3D asset, to apply offset to all vertices.



vertex VertexOut vertex_main(VertexIn vertexIn [[ stage_in ]], constant Uniforms &uniforms [[ buffer(1) ]], uint vertexID [[ vertex_id ]]) {
float4 worldPosition = uniforms.modelMatrix *float4(vertexIn.position, 1);
VertexOut vertexOut;
vertexOut.position = uniforms.viewProjectionMatrix * worldPosition;
vertexOut.worldPosition = worldPosition.xyz;
vertexOut.worldNormal = uniforms.normalMatrix * vertexIn.normal;
vertexOut.texCoords = vertexIn.texCoords;
return vertexOut;
}


That how looks VertexIn



struct VertexIn {
float3 position [[attribute(0)]];
float3 normal [[attribute(1)]];
float2 texCoords [[attribute(2)]];
};


Drawing of 3D asset



for mesh in meshes {
for i in 0..<mesh.vertexBuffers.count {
let vertexBuffer = mesh.vertexBuffers[i]
commandEncoder.setVertexBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: i)
}

for submesh in mesh.submeshes {
let indexBuffer = submesh.indexBuffer
commandEncoder.drawIndexedPrimitives(type: submesh.primitiveType,
indexCount: submesh.indexCount,
indexType: submesh.indexType,
indexBuffer: indexBuffer.buffer,
indexBufferOffset: indexBuffer.offset)
}
}


Vertex descriptor for loading 3D Model asset



    let vertexDescriptor = MDLVertexDescriptor()
vertexDescriptor.attributes[0] = MDLVertexAttribute(name: MDLVertexAttributePosition, format: .float3, offset: 0, bufferIndex: 0)
vertexDescriptor.attributes[1] = MDLVertexAttribute(name: MDLVertexAttributeNormal, format: .float3, offset: MemoryLayout<Float>.size * 3, bufferIndex: 0)
vertexDescriptor.attributes[2] = MDLVertexAttribute(name: MDLVertexAttributeTextureCoordinate, format: .float2, offset: MemoryLayout<Float>.size * 6, bufferIndex: 0)

vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: MemoryLayout<Float>.size * 8)


Thank you for help.
P.S.
I was trying to change after loading of 3d asset, but it fails, because I can't change the vertex buffer created with Model I/O.










share|improve this question























  • It seems to me that you could load the vertex offsets into your own MTLBuffer and pass that as an argument to your vertex function. You'd probably want to use triple buffering to keep three "frames" of animation data in flight at once.

    – warrenm
    Nov 16 '18 at 17:10











  • @warrenm I've made it with buffer, just with one, without triple buffering, and it came out that the order of my buffer that consist of animation offset for each vertices is wrong. And that strange. Because I thought that is unpacked in same order as it goes in my .obj file with defined faces example(f 1/1/1'). But it appeared that no. Could I be wrong ?

    – Ivan Tkachenko
    Nov 19 '18 at 14:16











  • You absolutely can't rely on the order of vertices in the file to correspond 1:1 with the vertices in your buffer after loading. OBJ allows separate indexing of position, normal, and texcoord data, so the data in the resulting buffers is almost always in a completely different order than the input. Admittedly, that makes vertex animation based on offsets a challenge.

    – warrenm
    Nov 19 '18 at 18:00











  • If your animation data is dense (i.e., every frame has an offset for every vertex), you might be better off using a series of OBJ files that have absolute positions instead. Or use a format like glTF that has a notion of animation built into the format.

    – warrenm
    Nov 19 '18 at 18:02






  • 1





    You can leave room in the vertex buffers by configuring the offsets of the attributes and the strides of the layouts. Then you can write the offsets into the "blank" space between vertices. But it seems you'd still need a way to determine the mapping from the vertices in the original model and the loaded vertices.

    – warrenm
    Nov 22 '18 at 16:58














0












0








0








The obj file loaded with Model I/O. I receive vertex buffer and index buffer from mesh and submesh. I draw it with index buffer. In GPU buffer unpacked and load all triangles.
When I load asset I am creating vertex descriptor, to say what should be loaded from 3D asset. When I pass it to shader I am using [[ stage_in ]] vertex parameter.



But somehow I need to change the structure of vertex that is created by loading model asset in parameter of vertex-shader function to pass more data with animation offset for each vertex. For example I need to pass data that in an 3D asset, to apply offset to all vertices.



vertex VertexOut vertex_main(VertexIn vertexIn [[ stage_in ]], constant Uniforms &uniforms [[ buffer(1) ]], uint vertexID [[ vertex_id ]]) {
float4 worldPosition = uniforms.modelMatrix *float4(vertexIn.position, 1);
VertexOut vertexOut;
vertexOut.position = uniforms.viewProjectionMatrix * worldPosition;
vertexOut.worldPosition = worldPosition.xyz;
vertexOut.worldNormal = uniforms.normalMatrix * vertexIn.normal;
vertexOut.texCoords = vertexIn.texCoords;
return vertexOut;
}


That how looks VertexIn



struct VertexIn {
float3 position [[attribute(0)]];
float3 normal [[attribute(1)]];
float2 texCoords [[attribute(2)]];
};


Drawing of 3D asset



for mesh in meshes {
for i in 0..<mesh.vertexBuffers.count {
let vertexBuffer = mesh.vertexBuffers[i]
commandEncoder.setVertexBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: i)
}

for submesh in mesh.submeshes {
let indexBuffer = submesh.indexBuffer
commandEncoder.drawIndexedPrimitives(type: submesh.primitiveType,
indexCount: submesh.indexCount,
indexType: submesh.indexType,
indexBuffer: indexBuffer.buffer,
indexBufferOffset: indexBuffer.offset)
}
}


Vertex descriptor for loading 3D Model asset



    let vertexDescriptor = MDLVertexDescriptor()
vertexDescriptor.attributes[0] = MDLVertexAttribute(name: MDLVertexAttributePosition, format: .float3, offset: 0, bufferIndex: 0)
vertexDescriptor.attributes[1] = MDLVertexAttribute(name: MDLVertexAttributeNormal, format: .float3, offset: MemoryLayout<Float>.size * 3, bufferIndex: 0)
vertexDescriptor.attributes[2] = MDLVertexAttribute(name: MDLVertexAttributeTextureCoordinate, format: .float2, offset: MemoryLayout<Float>.size * 6, bufferIndex: 0)

vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: MemoryLayout<Float>.size * 8)


Thank you for help.
P.S.
I was trying to change after loading of 3d asset, but it fails, because I can't change the vertex buffer created with Model I/O.










share|improve this question














The obj file loaded with Model I/O. I receive vertex buffer and index buffer from mesh and submesh. I draw it with index buffer. In GPU buffer unpacked and load all triangles.
When I load asset I am creating vertex descriptor, to say what should be loaded from 3D asset. When I pass it to shader I am using [[ stage_in ]] vertex parameter.



But somehow I need to change the structure of vertex that is created by loading model asset in parameter of vertex-shader function to pass more data with animation offset for each vertex. For example I need to pass data that in an 3D asset, to apply offset to all vertices.



vertex VertexOut vertex_main(VertexIn vertexIn [[ stage_in ]], constant Uniforms &uniforms [[ buffer(1) ]], uint vertexID [[ vertex_id ]]) {
float4 worldPosition = uniforms.modelMatrix *float4(vertexIn.position, 1);
VertexOut vertexOut;
vertexOut.position = uniforms.viewProjectionMatrix * worldPosition;
vertexOut.worldPosition = worldPosition.xyz;
vertexOut.worldNormal = uniforms.normalMatrix * vertexIn.normal;
vertexOut.texCoords = vertexIn.texCoords;
return vertexOut;
}


That how looks VertexIn



struct VertexIn {
float3 position [[attribute(0)]];
float3 normal [[attribute(1)]];
float2 texCoords [[attribute(2)]];
};


Drawing of 3D asset



for mesh in meshes {
for i in 0..<mesh.vertexBuffers.count {
let vertexBuffer = mesh.vertexBuffers[i]
commandEncoder.setVertexBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: i)
}

for submesh in mesh.submeshes {
let indexBuffer = submesh.indexBuffer
commandEncoder.drawIndexedPrimitives(type: submesh.primitiveType,
indexCount: submesh.indexCount,
indexType: submesh.indexType,
indexBuffer: indexBuffer.buffer,
indexBufferOffset: indexBuffer.offset)
}
}


Vertex descriptor for loading 3D Model asset



    let vertexDescriptor = MDLVertexDescriptor()
vertexDescriptor.attributes[0] = MDLVertexAttribute(name: MDLVertexAttributePosition, format: .float3, offset: 0, bufferIndex: 0)
vertexDescriptor.attributes[1] = MDLVertexAttribute(name: MDLVertexAttributeNormal, format: .float3, offset: MemoryLayout<Float>.size * 3, bufferIndex: 0)
vertexDescriptor.attributes[2] = MDLVertexAttribute(name: MDLVertexAttributeTextureCoordinate, format: .float2, offset: MemoryLayout<Float>.size * 6, bufferIndex: 0)

vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: MemoryLayout<Float>.size * 8)


Thank you for help.
P.S.
I was trying to change after loading of 3d asset, but it fails, because I can't change the vertex buffer created with Model I/O.







swift 3d metal vertex-buffer metalkit






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 16 '18 at 16:01









Ivan TkachenkoIvan Tkachenko

11615




11615













  • It seems to me that you could load the vertex offsets into your own MTLBuffer and pass that as an argument to your vertex function. You'd probably want to use triple buffering to keep three "frames" of animation data in flight at once.

    – warrenm
    Nov 16 '18 at 17:10











  • @warrenm I've made it with buffer, just with one, without triple buffering, and it came out that the order of my buffer that consist of animation offset for each vertices is wrong. And that strange. Because I thought that is unpacked in same order as it goes in my .obj file with defined faces example(f 1/1/1'). But it appeared that no. Could I be wrong ?

    – Ivan Tkachenko
    Nov 19 '18 at 14:16











  • You absolutely can't rely on the order of vertices in the file to correspond 1:1 with the vertices in your buffer after loading. OBJ allows separate indexing of position, normal, and texcoord data, so the data in the resulting buffers is almost always in a completely different order than the input. Admittedly, that makes vertex animation based on offsets a challenge.

    – warrenm
    Nov 19 '18 at 18:00











  • If your animation data is dense (i.e., every frame has an offset for every vertex), you might be better off using a series of OBJ files that have absolute positions instead. Or use a format like glTF that has a notion of animation built into the format.

    – warrenm
    Nov 19 '18 at 18:02






  • 1





    You can leave room in the vertex buffers by configuring the offsets of the attributes and the strides of the layouts. Then you can write the offsets into the "blank" space between vertices. But it seems you'd still need a way to determine the mapping from the vertices in the original model and the loaded vertices.

    – warrenm
    Nov 22 '18 at 16:58



















  • It seems to me that you could load the vertex offsets into your own MTLBuffer and pass that as an argument to your vertex function. You'd probably want to use triple buffering to keep three "frames" of animation data in flight at once.

    – warrenm
    Nov 16 '18 at 17:10











  • @warrenm I've made it with buffer, just with one, without triple buffering, and it came out that the order of my buffer that consist of animation offset for each vertices is wrong. And that strange. Because I thought that is unpacked in same order as it goes in my .obj file with defined faces example(f 1/1/1'). But it appeared that no. Could I be wrong ?

    – Ivan Tkachenko
    Nov 19 '18 at 14:16











  • You absolutely can't rely on the order of vertices in the file to correspond 1:1 with the vertices in your buffer after loading. OBJ allows separate indexing of position, normal, and texcoord data, so the data in the resulting buffers is almost always in a completely different order than the input. Admittedly, that makes vertex animation based on offsets a challenge.

    – warrenm
    Nov 19 '18 at 18:00











  • If your animation data is dense (i.e., every frame has an offset for every vertex), you might be better off using a series of OBJ files that have absolute positions instead. Or use a format like glTF that has a notion of animation built into the format.

    – warrenm
    Nov 19 '18 at 18:02






  • 1





    You can leave room in the vertex buffers by configuring the offsets of the attributes and the strides of the layouts. Then you can write the offsets into the "blank" space between vertices. But it seems you'd still need a way to determine the mapping from the vertices in the original model and the loaded vertices.

    – warrenm
    Nov 22 '18 at 16:58

















It seems to me that you could load the vertex offsets into your own MTLBuffer and pass that as an argument to your vertex function. You'd probably want to use triple buffering to keep three "frames" of animation data in flight at once.

– warrenm
Nov 16 '18 at 17:10





It seems to me that you could load the vertex offsets into your own MTLBuffer and pass that as an argument to your vertex function. You'd probably want to use triple buffering to keep three "frames" of animation data in flight at once.

– warrenm
Nov 16 '18 at 17:10













@warrenm I've made it with buffer, just with one, without triple buffering, and it came out that the order of my buffer that consist of animation offset for each vertices is wrong. And that strange. Because I thought that is unpacked in same order as it goes in my .obj file with defined faces example(f 1/1/1'). But it appeared that no. Could I be wrong ?

– Ivan Tkachenko
Nov 19 '18 at 14:16





@warrenm I've made it with buffer, just with one, without triple buffering, and it came out that the order of my buffer that consist of animation offset for each vertices is wrong. And that strange. Because I thought that is unpacked in same order as it goes in my .obj file with defined faces example(f 1/1/1'). But it appeared that no. Could I be wrong ?

– Ivan Tkachenko
Nov 19 '18 at 14:16













You absolutely can't rely on the order of vertices in the file to correspond 1:1 with the vertices in your buffer after loading. OBJ allows separate indexing of position, normal, and texcoord data, so the data in the resulting buffers is almost always in a completely different order than the input. Admittedly, that makes vertex animation based on offsets a challenge.

– warrenm
Nov 19 '18 at 18:00





You absolutely can't rely on the order of vertices in the file to correspond 1:1 with the vertices in your buffer after loading. OBJ allows separate indexing of position, normal, and texcoord data, so the data in the resulting buffers is almost always in a completely different order than the input. Admittedly, that makes vertex animation based on offsets a challenge.

– warrenm
Nov 19 '18 at 18:00













If your animation data is dense (i.e., every frame has an offset for every vertex), you might be better off using a series of OBJ files that have absolute positions instead. Or use a format like glTF that has a notion of animation built into the format.

– warrenm
Nov 19 '18 at 18:02





If your animation data is dense (i.e., every frame has an offset for every vertex), you might be better off using a series of OBJ files that have absolute positions instead. Or use a format like glTF that has a notion of animation built into the format.

– warrenm
Nov 19 '18 at 18:02




1




1





You can leave room in the vertex buffers by configuring the offsets of the attributes and the strides of the layouts. Then you can write the offsets into the "blank" space between vertices. But it seems you'd still need a way to determine the mapping from the vertices in the original model and the loaded vertices.

– warrenm
Nov 22 '18 at 16:58





You can leave room in the vertex buffers by configuring the offsets of the attributes and the strides of the layouts. Then you can write the offsets into the "blank" space between vertices. But it seems you'd still need a way to determine the mapping from the vertices in the original model and the loaded vertices.

– warrenm
Nov 22 '18 at 16:58












0






active

oldest

votes












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53341430%2fhow-to-animate-3d-asset-obj-file-loaded-with-model-i-o-framework-on-metal%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53341430%2fhow-to-animate-3d-asset-obj-file-loaded-with-model-i-o-framework-on-metal%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Florida Star v. B. J. F.

Error while running script in elastic search , gateway timeout

Adding quotations to stringified JSON object values