luke-titley / usd-rs

55 stars 8 forks source link

How to convert an array value into a vector #3

Closed kubo-von closed 3 years ago

kubo-von commented 3 years ago

Hey @luke-titley, I'm trying to get a point positions (point3f array) from a mesh. I followed the examples but I'm not sure how to actually get those values either as Vec<Vec> or flattened Vec. Thanks for any help!

use pxr::sdf;
use pxr::usd::Stage;
use usd::pxr;
use pxr::tf;
use pxr::usd::*;
use pxr::vt;

use usd::c_str;

fn main() {
    let path = c_str!("test.usd");
    let stage = pxr::usd::Stage::open(pxr::usd::stage::desc::Open {
        file_path: &path,
        load: None,
    });

    for prim in stage.traverse().iter() {
        if (prim.get_type_name().get_text() == c_str!("Mesh")) {
            let attr = prim.get_attribute(&tf::Token::from(c_str!("points")));
            use vt::VtArray as _;
            let mut array = vt::ArrayVec3f::new();
            let mut _value = vt::Value::from(&array);
            attr.get(&mut _value, TimeCode::default());

            let values_as_vector: Vec<Vec<f32> = _value.into(); //NOT SURE WHAT TO DO HERE

            println!("points: {:?} ", values_as_vector);
        }
    }
}
luke-titley commented 3 years ago

There's no into implementation for converting to vector. But you can access the ArrayVec3f type directly to get access to the points, this has the benefit that you don't incur the cost of a copy.

let points: &vt::ArrayVec3f = points_value.as_ref();

ArrayVec3f implements the Index trait so you can access each element by index.

let p : [f32;3] = points[0];

All the array types implement the VtArray trait so they have a 'size' method (instead of len).

let mut values_as_vector = Vec::new();
values_as_vector.reserve(points.size());
for i in 0..points.size() {
    values_as_vector.push(points[i]);
}

in the future I'll try to add an iterator trait implementation so that you don't incur the cost of the range check for each element access.

if you want to flatten them for gpu drawing.

let mut values_as_vector = Vec::new();
values_as_vector.reserve(points.size()*3);
for i in 0..points.size() {
    for j in 0..3 {
       values_as_vector.push(points[i][j]);
    }
}
kubo-von commented 3 years ago

Awesome, Thanks a lot!! I knew I could access ArrayVec3f directly but just wasn't able to do it once it was vt::Value type. Was missing the _let points: &vt::ArrayVec3f = _value.asref(); piece. An iterator sounds great! I'm trying to use it in my pathtracer so the flattening comes in handy too! Thanks again! closing this