1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//! additional physical rules applied

use std::time::Instant;

use bevy::prelude::*;
use bevy_rapier2d::prelude::*;

use crate::consts::*;

pub fn setup_gravity(mut rapier_config: ResMut<RapierConfiguration>) {
    if TRAINING_MODE == "swim" {
        rapier_config.gravity = Vec2::ZERO;
    }
}

/// Create drag force for under-water simulation
/// Cost about 5% of total running time in Physical Simulation
pub fn viscosity(mut block_q: Query<(&Collider, &Transform, &Velocity, &mut ExternalForce)>) {
    let start_time = Instant::now();
    // // parallel implementation, save about 3% of running time (in physical simulation)
    // block_q
    //     .par_iter_mut()
    //     .for_each_mut(|(collider, transform, v, mut force)| {
    //         // skip objects not moving
    //         if v.linvel.length().abs() < EPSILON {
    //             return;
    //         }
    //         let cube_shape: Vec2 = collider.as_cuboid().unwrap().half_extents();
    //         let rotation: f32 = transform.rotation.to_axis_angle().1;

    //         let velocity_direction = v.linvel.normalize();
    //         let face_direction = Vec2::new(rotation.cos(), rotation.sin());
    //         let angle = velocity_direction.angle_between(face_direction).abs();
    //         let projected_area =
    //             (cube_shape.x * angle.sin().abs()) + cube_shape.y * angle.cos().abs();

    //         // considering changing drag_coeff
    //         force.force = DRAG_COEFF * (-v.linvel * projected_area);
    //     });

    // sequencial implementation

    for (collider,transform,v,mut force) in block_q.iter_mut(){
        // skip objects not moving
        if v.linvel.length().abs() < EPSILON{
            continue;
        }
        let cube_shape: Vec2 = collider.as_cuboid().unwrap().half_extents();
        let rotation: f32 = transform.rotation.to_axis_angle().1;

        let velocity_direction = v.linvel.normalize();
        let face_direction = Vec2::new(rotation.cos(), rotation.sin());
        let angle = velocity_direction.angle_between(face_direction).abs();
        let projected_area = (cube_shape.x * angle.sin().abs())
            + cube_shape.y * angle.cos().abs();

        // considering changing drag_coeff
        force.force = DRAG_COEFF * (-v.linvel * projected_area);
    }

    let duration = Instant::now() - start_time;
    if PRINT_FUNCTION_TIME && duration >= MIN_PRINT_DURATION{
        println!("viscosity: {:?}", duration);
    }
}