Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Panic when using "parallel" feature #289

Closed
mikex86 opened this issue Feb 18, 2022 · 0 comments · Fixed by #304
Closed

Panic when using "parallel" feature #289

mikex86 opened this issue Feb 18, 2022 · 0 comments · Fixed by #304

Comments

@mikex86
Copy link

mikex86 commented Feb 18, 2022

The following error occurs when the "parallel" feature is used

thread '<unnamed>' panicked at 'index out of bounds: the len is 128 but the index is 128', C:\Users\Mike\.cargo\registry\src\git.luolix.top-1ecc6299db9ec823\rapier3d-0.11.1\src\dynamics\solver\interaction_groups.rs:116:21
stack backtrace:
   0:     0x7ff7c33c71b0 - std::backtrace_rs::backtrace::dbghelp::trace
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\..\..\backtrace\src\backtrace\dbghelp.rs:98
   1:     0x7ff7c33c71b0 - std::backtrace_rs::backtrace::trace_unsynchronized
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\..\..\backtrace\src\backtrace\mod.rs:66
   2:     0x7ff7c33c71b0 - std::sys_common::backtrace::_print_fmt
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\sys_common\backtrace.rs:66
   3:     0x7ff7c33c71b0 - std::sys_common::backtrace::_print::impl$0::fmt
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\sys_common\backtrace.rs:45
   4:     0x7ff7c33deefa - core::fmt::write
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\core\src\fmt\mod.rs:1190
   5:     0x7ff7c33c24d9 - std::io::Write::write_fmt<std::sys::windows::stdio::Stderr>
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\io\mod.rs:1657
   6:     0x7ff7c33c9a22 - std::sys_common::backtrace::_print
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\sys_common\backtrace.rs:48
   7:     0x7ff7c33c9a22 - std::sys_common::backtrace::print
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\sys_common\backtrace.rs:35
   8:     0x7ff7c33c9a22 - std::panicking::default_hook::closure$1
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\panicking.rs:295
   9:     0x7ff7c33c95e3 - std::panicking::default_hook
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\panicking.rs:314
  10:     0x7ff7c33ca079 - std::panicking::rust_panic_with_hook
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\panicking.rs:698
  11:     0x7ff7c33c9f2d - std::panicking::begin_panic_handler::closure$0
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\panicking.rs:588
  12:     0x7ff7c33c7ae7 - std::sys_common::backtrace::__rust_end_short_backtrace<std::panicking::begin_panic_handler::closure_env$0,never$>
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\sys_common\backtrace.rs:138
  13:     0x7ff7c33c9ba9 - std::panicking::begin_panic_handler
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\panicking.rs:584
  14:     0x7ff7c33f50f5 - core::panicking::panic_fmt
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\core\src\panicking.rs:143
  15:     0x7ff7c33f5017 - core::panicking::panic_bounds_check
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\core\src\panicking.rs:85
  16:     0x7ff7c319605e - getrandom::getrandom::ha8f6e5f9ea41018c
  17:     0x7ff7c318e004 - getrandom::getrandom::ha8f6e5f9ea41018c
  18:     0x7ff7c33f170b - rayon_core::registry::WorkerThread::wait_until_cold::ha989360900ccdf89
  19:     0x7ff7c338eda4 - rayon_core::registry::ThreadBuilder::run::h55c61aae20fe7e3f
  20:     0x7ff7c3392d53 - <rayon_core::ThreadPoolBuildError as core::fmt::Debug>::fmt::h005935bc4b76bb63
  21:     0x7ff7c338cec6 - <jpeg_decoder::marker::Marker as core::fmt::Debug>::fmt::hed11917a0d7ec491
  22:     0x7ff7c33cd9fc - alloc::boxed::impl$44::call_once
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\library\alloc\src\boxed.rs:1854
  23:     0x7ff7c33cd9fc - alloc::boxed::impl$44::call_once
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\library\alloc\src\boxed.rs:1854
  24:     0x7ff7c33cd9fc - std::sys::windows::thread::impl$0::new::thread_start
                               at /rustc/30b3f35c420694a4f24e5a4df00f06073f4f3a37\/library\std\src\sys\windows\thread.rs:58
  25:     0x7ff91d4754e0 - BaseThreadInitThunk
  26:     0x7ff91f32485b - RtlUserThreadStart

How to reproduce:

Load a sufficiently complex 3D model as trimesh and produce a collision with a cube at sufficient speed (not necessarily high).
The "monkey.obj" object is the default Blender "monkey" with scale 1.0 with no further subdivisions exported as OBJ with triangulated faces.
The crate used to extract the vertices and indices is the obj-rs crate.

let input = BufReader::new(File::open("monkey.obj").unwrap());
let obj_mesh: Obj = obj::load_obj(input).unwrap();
let vertices: Vec<Point<Real>> = obj_mesh.vertices
    .iter()
     .map(|v| Point3::from(v.position))
    .collect();

let indices: Vec<[u32; 3]> = obj_mesh.indices.chunks(3)
    .map(|chunk| [chunk[0] as u32, chunk[1] as u32, chunk[2] as u32])
    .collect();

let collider = ColliderBuilder::trimesh(vertices.clone(), indices.clone())
    .restitution(0.7)
    .mass_properties(MassProperties::from_convex_polyhedron(1.0, vertices.as_slice(), indices.as_slice()))
    .build();

Full code

The kiss-3d crate is used for rendering.

extern crate kiss3d;

use std::fs::File;
use std::io::BufReader;
use std::path::Path;
use std::time::{Instant};
use glam::Vec3A;
use kiss3d::camera::{ArcBall};
use kiss3d::light::Light;
use kiss3d::nalgebra::{Translation3};
use kiss3d::scene::SceneNode;
use kiss3d::window::{CanvasSetup, NumSamples, State, Window};
use obj::Obj;
use rapier3d::na::Point3;
use rapier3d::prelude::*;
use crate::nalgebra::Vector3;

trait Node {
    fn update(&mut self, rigid_body_set: &RigidBodySet, window: &mut Window);
}

struct Cube {
    cube_node: SceneNode,
    cube_handle: RigidBodyHandle,
}

impl Cube {
    fn new(rigid_body_set: &mut RigidBodySet, collider_set: &mut ColliderSet, window: &mut Window, position: Vec3A, dimension: Vec3A, is_static: bool) -> Cube {
        let rigid_body = RigidBodyBuilder::new(if is_static { RigidBodyType::Static } else { RigidBodyType::Dynamic })
            .translation(vector![position.x, position.y, position.z])
            .ccd_enabled(true)
            .build();
        let collider = ColliderBuilder::cuboid(dimension.x / 2.0, dimension.y / 2.0, dimension.z / 2.0).restitution(0.7).build();
        let ball_body_handle = rigid_body_set.insert(rigid_body);
        collider_set.insert_with_parent(collider, ball_body_handle, rigid_body_set);

        let mut node = window.add_cube(dimension.x, dimension.y, dimension.z);
        node.set_visible(false);

        return Cube {
            cube_node: node,
            cube_handle: ball_body_handle,
        };
    }
}

impl Node for Cube {
    fn update(&mut self, rigid_body_set: &RigidBodySet, _: &mut Window) {
        let position = rigid_body_set[self.cube_handle].position().translation;

        self.cube_node.set_local_translation(Translation3::new(position.x, position.y, position.z));
        self.cube_node.set_visible(true);
    }
}

struct Mesh {
    mesh_node: SceneNode,
    mesh_handle: RigidBodyHandle,
}

impl Mesh {
    fn new(rigid_body_set: &mut RigidBodySet, collider_set: &mut ColliderSet, window: &mut Window, model_file: &Path, collider_model_file: &Path, position: Vec3A, is_static: bool) -> Mesh {
        let rigid_body = RigidBodyBuilder::new(if is_static { RigidBodyType::Static } else { RigidBodyType::Dynamic })
            .translation(vector![position.x, position.y, position.z])
            .ccd_enabled(false)
            .build();

        let input = BufReader::new(File::open(collider_model_file).unwrap());
        let obj_mesh: Obj = obj::load_obj(input).unwrap();

        let vertices: Vec<Point<Real>> = obj_mesh.vertices
            .iter()
            .map(|v| Point3::from(v.position))
            .collect();

        let indices: Vec<[u32; 3]> = obj_mesh.indices.chunks(3)
            .map(|chunk| [chunk[0] as u32, chunk[1] as u32, chunk[2] as u32])
            .collect();

        let collider = ColliderBuilder::trimesh(vertices.clone(), indices.clone())
            .restitution(0.7)
            .mass_properties(MassProperties::from_convex_polyhedron(1.0, vertices.as_slice(), indices.as_slice()))
            .build();

        let body_handle = rigid_body_set.insert(rigid_body);
        collider_set.insert_with_parent(collider, body_handle, rigid_body_set);

        let mut node = window.add_obj(Path::new(model_file), model_file.parent().unwrap(), Vector3::new(1.0, 1.0, 1.0));
        node.set_visible(false);

        return Mesh {
            mesh_node: node,
            mesh_handle: body_handle,
        };
    }
}

impl Node for Mesh {
    fn update(&mut self, rigid_body_set: &RigidBodySet, _: &mut Window) {
        let isometry = rigid_body_set[self.mesh_handle].position();
        let position = isometry.translation;
        let rotation = isometry.rotation;

        self.mesh_node.set_local_translation(Translation3::new(position.x, position.y, position.z));
        self.mesh_node.set_local_rotation(rotation);
        self.mesh_node.set_visible(true);
    }
}

struct AppState {
    last_time: std::time::Instant,
    nodes: Vec<Box<dyn Node>>,

    rigid_body_set: RigidBodySet,
    collider_set: ColliderSet,
    joint_set: JointSet,
    gravity: Vector<Real>,
    physics_pipeline: PhysicsPipeline,
    island_manager: IslandManager,
    broad_phase: BroadPhase,
    narrow_phase: NarrowPhase,
    ccd_solver: CCDSolver,
}

impl State for AppState {
    fn step(&mut self, window: &mut Window) {
        let delta_time_duration = Instant::now() - self.last_time;
        self.last_time = Instant::now();
        let delta_time_seconds = delta_time_duration.as_secs_f32();

        let fps = 1.0 / delta_time_seconds;
        if fps < 55.0 {
            println!("{} fps", fps);
        }

        let dt = 1.0 / 60.0;

        // println!("{}", delta_time_seconds);
        let mut integration_parameters = IntegrationParameters::default();
        integration_parameters.dt = dt;

        // Drive simulation
        {
            self.physics_pipeline.step(
                &self.gravity,
                &integration_parameters,
                &mut self.island_manager,
                &mut self.broad_phase,
                &mut self.narrow_phase,
                &mut self.rigid_body_set,
                &mut self.collider_set,
                &mut self.joint_set,
                &mut self.ccd_solver,
                &(),
                &(),
            );
        }

        // Update nodes
        {
            for node in &mut self.nodes {
                node.update(&self.rigid_body_set, window);
            }
        }
    }
}

fn main() {
    let mut window = Window::new_with_setup("Testing", 900, 600, CanvasSetup { vsync: true, samples: NumSamples::Sixteen });
    window.set_light(Light::StickToCamera);

    let mut rigid_body_set = RigidBodySet::new();
    let mut collider_set = ColliderSet::new();
    let joint_set = JointSet::new();

    let physics_pipeline = PhysicsPipeline::new();
    let island_manager = IslandManager::new();
    let broad_phase = BroadPhase::new();
    let narrow_phase = NarrowPhase::new();
    let ccd_solver = CCDSolver::new();
    let mut camera = ArcBall::new(Point3::from([15.0, 2.0, -5.0]), Point3::from([0.0, 1.0, -5.0]));

    let sim_size = 20;

    let mut nodes: Vec<Box<dyn Node>> = vec![
        // Box::new(Mesh::new(&mut rigid_body_set, &mut collider_set, &mut window, &Path::new("monkey.obj"), &Path::new("monkey_lowpoly.obj"), Vec3A::new(0.0, 5.0, 0.0), false)),
        // Box::new(Cube::new(&mut rigid_body_set, &mut collider_set, &mut window, Vec3A::new(0.0, 8.0, 0.0), Vec3A::new(1.0, 1.0, 1.0), false)),
        // Box::new(Cube::new(&mut rigid_body_set, &mut collider_set, &mut window, Vec3A::new(0.0, 12.0, -5.0), Vec3A::new(1.0, 1.0, 1.0), false)),

        // ground plane
        Box::new(Cube::new(&mut rigid_body_set, &mut collider_set, &mut window, Vec3A::new(0.0, 1.0, 0.0), Vec3A::new(sim_size as f32 * 10.0, 0.5, sim_size as f32 * 10.0), true)),
    ];

    for i in 0..2 * sim_size {
        for j in 0..2 * sim_size {
            let random_height = 2.0 + rand::random::<f32>() * sim_size as f32;
            nodes.push(Box::new(Mesh::new(&mut rigid_body_set, &mut collider_set, &mut window, &Path::new("monkey.obj"), &Path::new("monkey_lowpoly.obj"), Vec3A::new((i - sim_size) as f32 * 10.0, random_height, (j - sim_size) as f32 * 10.0), false)));
        }
    }

    let mut state = AppState {
        last_time: Instant::now(),
        nodes,
        rigid_body_set,
        collider_set,
        joint_set,
        gravity: Vector::new(0.0, -9.81, 0.0),
        physics_pipeline,
        island_manager,
        broad_phase,
        narrow_phase,
        ccd_solver,
    };

    while !window.should_close() {
        state.step(&mut window);
        window.render_with_camera(&mut camera);
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant