[ad_1]
I am making an attempt to do Skeleton Animation utilizing OpenGL and Rust, loading from a gltf file. And issues aren’t understanding very effectively. I do not know if the issue is within the file I am utilizing, if it is within the code or if it is in the way in which I load the knowledge.
That is the gltf file I am utilizing, it has a male basemesh mannequin with a “strolling” animation that I loaded from Mixamo:
ANDAR.gltf
I used the gl
library in rust to program.
To load the knowledge into the VBO, I used the next perform:
fn CarregarGltf(tudo : &mut Vec<f32>, modelo : &str){
let local_exe = std::env::current_dir().unwrap();
let native = local_exe.show();
let original_tamanho = tudo.len()/19;
let (gltf, buffers, _) = gltf::import(format!("extras/{}.gltf",modelo)).unwrap();
for m in gltf.meshes(){
for p in m.primitives(){
let r = p.reader(|buffer| Some(&buffers[buffer.index()]));
let mut indices = Vec::new();
if let Some(gltf::mesh::util::ReadIndices::U16(gltf::accessor::Iter::Customary(iter))) = r.read_indices(){
for v in iter{
indices.push(v);
}
}
let mut posicao = Vec::new();
if let Some(iter) = r.read_positions(){
for v in iter{
posicao.push(v);
}
}
let mut textura = Vec::new();
if let Some(gltf::mesh::util::ReadTexCoords::F32(gltf::accessor::Iter::Customary(iter))) = r.read_tex_coords(0){
for v in iter{
textura.push(v);
}
}
let mut normais = Vec::new();
if let Some(iter) = r.read_normals(){
for v in iter{
normais.push(v);
}
}
let mut ossosid = Vec::new();
if let Some(gltf::mesh::util::ReadJoints::U8(gltf::accessor::Iter::Customary(iter))) = r.read_joints(0){
for v in iter{
ossosid.push(v);
}
}
let mut pesos = Vec::new();
if let Some(gltf::mesh::util::ReadWeights::F32(gltf::accessor::Iter::Customary(iter))) = r.read_weights(0){
for v in iter{
pesos.push(v);
}
}
for q in indices{
// posição
tudo.push(posicao[q as usize][0] as f32);
tudo.push(posicao[q as usize][1] as f32);
tudo.push(posicao[q as usize][2] as f32);
// textura
tudo.push(textura[q as usize][0] as f32);
tudo.push(textura[q as usize][1] as f32);
// normais
tudo.push(normais[q as usize][0] as f32);
tudo.push(normais[q as usize][1] as f32);
tudo.push(normais[q as usize][2] as f32);
// ossosid
tudo.push(ossosid[q as usize][0] as f32);
tudo.push(ossosid[q as usize][1] as f32);
tudo.push(ossosid[q as usize][2] as f32);
tudo.push(ossosid[q as usize][3] as f32);
// pesos
tudo.push(pesos[q as usize][0]);
tudo.push(pesos[q as usize][1]);
tudo.push(pesos[q as usize][2]);
tudo.push(pesos[q as usize][3]);
// aoffset
tudo.push(0.0);
tudo.push(0.0);
tudo.push(0.0);
}
}
}
println!("VBO do "{}" : {}, {}", modelo, original_tamanho, tudo.len()/19-original_tamanho);
}
So as, it carries place, texture, regular, bones, affect weights and one final piece of data that’s not related in the mean time. The target was for the mannequin to be prepared in order that I may then apply the strolling animation transformations to it.
To load the animation, I used a separate perform that might hold the animation code separate within the code, right here is the perform:
fn CarregarAnimacao(modelo : &str) -> (Vec<Vec<f32>>,Vec<Vec<f32>>,Vec<Vec<f32>>){
let (knowledge, buffers, _) = gltf::import(format!("extras/{}.gltf",modelo)).unwrap();
let mut translate : Vec<Vec<f32>> = Vec::new();
let mut rotations : Vec<Vec<f32>> = Vec::new();
let mut scales : Vec<Vec<f32>> = Vec::new();
for a in knowledge.animations(){
for c in a.channels(){
let r = c.reader(|buffer| Some(&buffers[buffer.index()]));
let kt = if let Some(inputs) = r.read_inputs(){
match inputs{
gltf::accessor::Iter::Customary(occasions) =>{
let occasions : Vec<f32> = occasions.acquire();
},
gltf::accessor::Iter::Customary(_) => todo!(),
gltf::accessor::Iter::Sparse(_) => todo!()
}
};
let okay = if let Some(outputs) = r.read_outputs(){
match outputs{
gltf::animation::util::ReadOutputs::Translations(translation) => {
translation.for_each(|tr|{
let v : Vec<f32> = tr.into();
translate.push(v);
});
},
gltf::animation::util::ReadOutputs::Rotations(rotation) => {
for r in rotation.into_f32(){
rotations.push(r.into());
}
},
gltf::animation::util::ReadOutputs::Scales(scale) => {
scale.for_each(|tr|{
let v : Vec<f32> = tr.into();
scales.push(v);
});
},
different => ()
}
};
}
}
(rotations,translate,scales)
}
In flip, it masses the Rotation and Translation data from the identical file “ANDAR.gltf” and retains it in a variable within the code. Then I cross them to the code utilizing the next code snippet:
let andar = CarregarAnimacao("ANDAR"); // Rotação, Translate, Escala
unsafe{
for i in 0..65{
gl::Uniform3f(gl::GetUniformLocation(shader,std::ffi::CString::new(format!("ANIMACAO1[{}]",i)).unwrap().as_ptr()), andar.1[i*26+10][0], andar.1[i*26+10][1], andar.1[i*26+10][2]);
gl::Uniform3f(gl::GetUniformLocation(shader,std::ffi::CString::new(format!("ANIMACAO2[{}]",i)).unwrap().as_ptr()), andar.0[i*26+10][0], andar.0[i*26+10][1], andar.0[i*26+10][2]);
}
}
I am not very used to utilizing 4×4 matrices when programming vertex_shader, I attempted to create my model of the code from https://learnopengl.com/Visitor-Articles/2020/Skeletal-Animation when within the shader I used the next logic:
for(int i = 0; i < 4; i++){
if(ossosid[i] == -1){
proceed;
}
if(ossosid[i] >= 65){
break;
}
pos = pos+ANIMACAO1[int(ossosid[i])]*pesos[i];
// Rotate on the x axis
pos = vec3(pos.x,pos.y*cos(ANIMACAO2[int(ossosid[i])][0]*pi/180)-pos.z*sin(ANIMACAO2[int(ossosid[i])][0]*pi/180),pos.z*cos(ANIMACAO2[int(ossosid[i])][0]*pi/180)+pos.y*sin(ANIMACAO2[int(ossosid[i])][0]*pi/180));
// Different features to rotate the place.
// ...
}
Anyway, on this context, the outcome that got here out ultimately was a physique that, earlier than making use of the animation transformations, appeared intact and regular… However then it was so distorted that it was troublesome to interpret.
From then on, I attempted a collection of different variations within the code utilizing different websites as a base resembling https://lisyarus.github.io/weblog/graphics/2023/07/03/gltf-animation.html however I nonetheless could not obtain a constant outcome.
My query is… How do I make the animation work?
[ad_2]