Skip to main content

box2d_rust/types/
shape.rs

1// Shape and chain creation types and defaults from types.h / types.c.
2// SPDX-FileCopyrightText: 2023 Erin Catto
3// SPDX-License-Identifier: MIT
4
5use super::{DEFAULT_CATEGORY_BITS, DEFAULT_MASK_BITS};
6use crate::core::SECRET_COOKIE;
7use crate::math_functions::Vec2;
8
9/// Collision filtering data for shapes. (b2Filter)
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct Filter {
12    /// The collision category bits. Normally you would just set one bit.
13    pub category_bits: u64,
14    /// The collision mask bits: the categories this shape accepts for collision.
15    pub mask_bits: u64,
16    /// Collision groups: never collide (negative) or always collide (positive).
17    /// A group index of zero has no effect. Non-zero group filtering always
18    /// wins against the mask bits.
19    pub group_index: i32,
20}
21
22/// Initialize a filter with the default values. (b2DefaultFilter)
23pub fn default_filter() -> Filter {
24    Filter {
25        category_bits: DEFAULT_CATEGORY_BITS,
26        mask_bits: DEFAULT_MASK_BITS,
27        group_index: 0,
28    }
29}
30
31impl Default for Filter {
32    fn default() -> Self {
33        default_filter()
34    }
35}
36
37/// The query filter is used to filter collisions between queries and shapes.
38/// (b2QueryFilter)
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub struct QueryFilter {
41    /// The collision category bits of this query.
42    pub category_bits: u64,
43    /// The shape categories this query accepts for collision.
44    pub mask_bits: u64,
45}
46
47/// Initialize a query filter with the default values. (b2DefaultQueryFilter)
48pub fn default_query_filter() -> QueryFilter {
49    QueryFilter {
50        category_bits: DEFAULT_CATEGORY_BITS,
51        mask_bits: DEFAULT_MASK_BITS,
52    }
53}
54
55impl Default for QueryFilter {
56    fn default() -> Self {
57        default_query_filter()
58    }
59}
60
61/// Surface materials allow chain shapes to have per segment surface properties.
62/// (b2SurfaceMaterial)
63#[derive(Debug, Clone, Copy, PartialEq)]
64pub struct SurfaceMaterial {
65    /// The Coulomb (dry) friction coefficient, usually in the range [0,1].
66    pub friction: f32,
67    /// The coefficient of restitution (bounce), usually in the range [0,1].
68    pub restitution: f32,
69    /// The rolling resistance, usually in the range [0,1].
70    pub rolling_resistance: f32,
71    /// The tangent speed for conveyor belts.
72    pub tangent_speed: f32,
73    /// User material identifier, passed to friction/restitution callbacks and
74    /// query results. Not used internally.
75    pub user_material_id: u64,
76    /// Custom debug draw color.
77    pub custom_color: u32,
78}
79
80/// Initialize a surface material with the default values.
81/// (b2DefaultSurfaceMaterial)
82pub fn default_surface_material() -> SurfaceMaterial {
83    SurfaceMaterial {
84        friction: 0.6,
85        restitution: 0.0,
86        rolling_resistance: 0.0,
87        tangent_speed: 0.0,
88        user_material_id: 0,
89        custom_color: 0,
90    }
91}
92
93impl Default for SurfaceMaterial {
94    fn default() -> Self {
95        default_surface_material()
96    }
97}
98
99/// Used to create a shape. Must be initialized using [`default_shape_def`].
100/// (b2ShapeDef)
101#[derive(Debug, Clone, Copy, PartialEq)]
102pub struct ShapeDef {
103    /// Application specific shape data.
104    pub user_data: u64,
105    /// The surface material for this shape.
106    pub material: SurfaceMaterial,
107    /// The density, usually in kg/m^2.
108    pub density: f32,
109    /// Collision filtering data.
110    pub filter: Filter,
111    /// Enable custom filtering. Only one of the two shapes needs to enable it.
112    pub enable_custom_filtering: bool,
113    /// A sensor shape generates overlap events but no collision response.
114    pub is_sensor: bool,
115    /// Enable sensor events for this shape. False by default, even for sensors.
116    pub enable_sensor_events: bool,
117    /// Enable contact events for this shape. False by default.
118    pub enable_contact_events: bool,
119    /// Enable hit events for this shape. False by default.
120    pub enable_hit_events: bool,
121    /// Enable pre-solve contact events for this shape.
122    pub enable_pre_solve_events: bool,
123    /// When shapes are created they scan the environment for collision next
124    /// step. Ignored for dynamic and kinematic shapes.
125    pub invoke_contact_creation: bool,
126    /// Should the body update the mass properties when this shape is created.
127    pub update_body_mass: bool,
128    /// Used internally to detect a valid definition. DO NOT SET.
129    pub internal_value: i32,
130}
131
132/// Initialize a shape definition with the default values. (b2DefaultShapeDef)
133pub fn default_shape_def() -> ShapeDef {
134    ShapeDef {
135        user_data: 0,
136        // C zero-inits the material then sets friction = 0.6, which is exactly
137        // the default surface material.
138        material: default_surface_material(),
139        density: 1.0,
140        filter: default_filter(),
141        enable_custom_filtering: false,
142        is_sensor: false,
143        enable_sensor_events: false,
144        enable_contact_events: false,
145        enable_hit_events: false,
146        enable_pre_solve_events: false,
147        invoke_contact_creation: true,
148        update_body_mass: true,
149        internal_value: SECRET_COOKIE,
150    }
151}
152
153impl Default for ShapeDef {
154    fn default() -> Self {
155        default_shape_def()
156    }
157}
158
159/// Used to create a chain of line segments. Must be initialized using
160/// [`default_chain_def`]. (b2ChainDef)
161///
162/// The C struct uses `points`/`count` and `materials`/`materialCount` pointer +
163/// length pairs; the Rust port carries owned `Vec`s whose lengths encode the
164/// counts (the C notes these are cloned).
165#[derive(Debug, Clone, PartialEq, Default)]
166pub struct ChainDef {
167    /// Application specific shape data.
168    pub user_data: u64,
169    /// An array of at least 4 points.
170    pub points: Vec<Vec2>,
171    /// Surface materials. Must have length 1 (one material for all segments) or
172    /// `points.len()` (a unique material per segment).
173    pub materials: Vec<SurfaceMaterial>,
174    /// Contact filtering data.
175    pub filter: Filter,
176    /// Indicates a closed chain formed by connecting the first and last points.
177    pub is_loop: bool,
178    /// Enable sensors to detect this chain. False by default.
179    pub enable_sensor_events: bool,
180    /// Used internally to detect a valid definition. DO NOT SET.
181    pub internal_value: i32,
182}
183
184/// Initialize a chain definition with the default values. (b2DefaultChainDef)
185pub fn default_chain_def() -> ChainDef {
186    ChainDef {
187        user_data: 0,
188        points: Vec::new(),
189        materials: vec![default_surface_material()],
190        filter: default_filter(),
191        is_loop: false,
192        enable_sensor_events: false,
193        internal_value: SECRET_COOKIE,
194    }
195}