ChunkPos

Struct ChunkPos 

Source
pub struct ChunkPos(pub IVec3);
Expand description

The position of a chunk in chunk-space coordinates.

When added to an entity, automatically updates the entity’s Transform to match the chunk’s world position.

§Example

use bevy::prelude::*;
use chunky_bevy::prelude::*;

fn spawn_chunk(mut commands: Commands) {
    // Spawns a chunk at chunk position (5, 0, 3)
    // With default 10x10x10 chunks, this will be at world position (50, 0, 30)
    commands.spawn((
        Chunk,
        ChunkPos(IVec3::new(5, 0, 3)),
    ));
}

Tuple Fields§

§0: IVec3

Methods from Deref<Target = IVec3>§

Source

pub const ZERO: IVec3

Source

pub const ONE: IVec3

Source

pub const NEG_ONE: IVec3

Source

pub const MIN: IVec3

Source

pub const MAX: IVec3

Source

pub const X: IVec3

Source

pub const Y: IVec3

Source

pub const Z: IVec3

Source

pub const NEG_X: IVec3

Source

pub const NEG_Y: IVec3

Source

pub const NEG_Z: IVec3

Source

pub const AXES: [IVec3; 3]

Source

pub fn to_array(&self) -> [i32; 3]

Converts self to [x, y, z]

Source

pub fn as_vec3(&self) -> Vec3

Casts all elements of self to f32.

Examples found in repository?
examples/sculpt.rs (line 276)
234fn sculpt_terrain(
235    time: Res<Time>,
236    keyboard: Res<ButtonInput<KeyCode>>,
237    mouse_buttons: Res<ButtonInput<MouseButton>>,
238    window_q: Query<&Window, With<PrimaryWindow>>,
239    camera_q: Query<(&Camera, &GlobalTransform), With<FlyCam>>,
240    mut chunks: Query<(&ChunkPos, &mut DensityField)>,
241    mesh_size: Res<DensityFieldMeshSize>,
242    brush: Res<SculptBrush>,
243    mut commands: Commands,
244    chunk_entities: Query<Entity, With<ChunkPos>>,
245) {
246    let adding = mouse_buttons.pressed(MouseButton::Right);
247    let removing = mouse_buttons.pressed(MouseButton::Left);
248
249    if !adding && !removing {
250        return;
251    }
252
253    let Ok(window) = window_q.single() else {
254        return;
255    };
256    let Some(cursor_pos) = window.cursor_position() else {
257        return;
258    };
259    let Ok((camera, cam_transform)) = camera_q.single() else {
260        return;
261    };
262    let Ok(ray) = camera.viewport_to_world(cam_transform, cursor_pos) else {
263        return;
264    };
265
266    let Some(hit_point) = raycast_terrain(&chunks, &mesh_size, ray) else {
267        return;
268    };
269
270    let world_brush_radius = brush.radius;
271    let chunk_world_size = mesh_size.0;
272    let use_hard_brush =
273        keyboard.pressed(KeyCode::ControlLeft) || keyboard.pressed(KeyCode::ControlRight);
274
275    for (chunk_pos, mut field) in chunks.iter_mut() {
276        let chunk_world_origin = chunk_pos.0.as_vec3() * chunk_world_size;
277        let local_hit = hit_point - chunk_world_origin;
278
279        let scale = Vec3::new(32.0, 32.0, 32.0) / chunk_world_size;
280        let grid_center = local_hit * scale;
281        let grid_radius = world_brush_radius * scale.x;
282
283        // AABB check
284        let chunk_min = Vec3::ZERO;
285        let chunk_max = Vec3::splat(32.0);
286        let brush_min = grid_center - Vec3::splat(grid_radius);
287        let brush_max = grid_center + Vec3::splat(grid_radius);
288
289        if brush_max.x < chunk_min.x
290            || brush_min.x > chunk_max.x
291            || brush_max.y < chunk_min.y
292            || brush_min.y > chunk_max.y
293            || brush_max.z < chunk_min.z
294            || brush_min.z > chunk_max.z
295        {
296            continue;
297        }
298
299        if use_hard_brush {
300            // Hard CSG brush (instant)
301            bevy_sculpter::helpers::brush_sphere(&mut field, grid_center, grid_radius, adding);
302        } else {
303            match brush.mode {
304                BrushMode::Smooth => {
305                    // Smooth brush: rate is strength per second
306                    // Negative rate = add material (decrease SDF)
307                    // Positive rate = remove material (increase SDF)
308                    let rate = if adding {
309                        -brush.strength
310                    } else {
311                        brush.strength
312                    };
313                    bevy_sculpter::helpers::brush_smooth_timed(
314                        &mut field,
315                        grid_center,
316                        grid_radius,
317                        rate,
318                        time.delta_secs(),
319                        brush.falloff,
320                    );
321                }
322                BrushMode::Blur => {
323                    // Blur/smooth brush
324                    bevy_sculpter::helpers::brush_blur(
325                        &mut field,
326                        grid_center,
327                        grid_radius,
328                        brush.strength * 0.1 * time.delta_secs(),
329                        brush.falloff,
330                    );
331                }
332                BrushMode::_Hard => {
333                    bevy_sculpter::helpers::brush_sphere(
334                        &mut field,
335                        grid_center,
336                        grid_radius,
337                        adding,
338                    );
339                }
340            }
341        }
342    }
343
344    for entity in chunk_entities.iter() {
345        commands.entity(entity).insert(DensityFieldDirty);
346    }
347}
348
349fn raycast_terrain(
350    chunks: &Query<(&ChunkPos, &mut DensityField)>,
351    mesh_size: &DensityFieldMeshSize,
352    ray: Ray3d,
353) -> Option<Vec3> {
354    let chunk_world_size = mesh_size.0;
355    let max_dist = 200.0;
356    let step = 0.1;
357    let mut t = 0.0;
358
359    while t < max_dist {
360        let point = ray.origin + ray.direction * t;
361        let chunk_coord = (point / chunk_world_size).floor().as_ivec3();
362
363        for (chunk_pos, field) in chunks.iter() {
364            if chunk_pos.0 != chunk_coord {
365                continue;
366            }
367
368            let chunk_origin = chunk_pos.0.as_vec3() * chunk_world_size;
369            let local_pos = point - chunk_origin;
370            let scale = Vec3::new(32.0, 32.0, 32.0) / chunk_world_size;
371            let grid_pos = local_pos * scale;
372
373            if grid_pos.x >= 0.0
374                && grid_pos.x < 32.0
375                && grid_pos.y >= 0.0
376                && grid_pos.y < 32.0
377                && grid_pos.z >= 0.0
378                && grid_pos.z < 32.0
379            {
380                let density = field.get(grid_pos.x as u32, grid_pos.y as u32, grid_pos.z as u32);
381                if density < 0.0 {
382                    return Some(point);
383                }
384            }
385        }
386        t += step;
387    }
388    None
389}
Source

pub fn as_vec3a(&self) -> Vec3A

Casts all elements of self to f32.

Source

pub fn as_dvec3(&self) -> DVec3

Casts all elements of self to f64.

Source

pub fn as_i8vec3(&self) -> I8Vec3

Casts all elements of self to i8.

Source

pub fn as_u8vec3(&self) -> U8Vec3

Casts all elements of self to u8.

Source

pub fn as_i16vec3(&self) -> I16Vec3

Casts all elements of self to i16.

Source

pub fn as_u16vec3(&self) -> U16Vec3

Casts all elements of self to u16.

Source

pub fn as_uvec3(&self) -> UVec3

Casts all elements of self to u32.

Source

pub fn as_i64vec3(&self) -> I64Vec3

Casts all elements of self to i64.

Source

pub fn as_u64vec3(&self) -> U64Vec3

Casts all elements of self to u64.

Source

pub fn as_usizevec3(&self) -> USizeVec3

Casts all elements of self to usize.

Trait Implementations§

Source§

impl Component for ChunkPos
where ChunkPos: Send + Sync + 'static,

Required Components: Transform.

A component’s Required Components are inserted whenever it is inserted. Note that this will also insert the required components of the required components, recursively, in depth-first order.

Source§

const STORAGE_TYPE: StorageType = ::bevy::ecs::component::StorageType::Table

A constant indicating the storage type used for this component.
Source§

type Mutability = Immutable

A marker type to assist Bevy with determining if this component is mutable, or immutable. Mutable components will have Component<Mutability = Mutable>, while immutable components will instead have Component<Mutability = Immutable>. Read more
Source§

fn register_required_components( _requiree: ComponentId, required_components: &mut RequiredComponentsRegistrator<'_, '_>, )

Registers required components. Read more
Source§

fn on_add() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>

Gets the on_add ComponentHook for this Component if one is defined.
Source§

fn clone_behavior() -> ComponentCloneBehavior

Called when registering this component, allowing to override clone function (or disable cloning altogether) for this component. Read more
Source§

fn on_insert() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>

Gets the on_insert ComponentHook for this Component if one is defined.
Source§

fn on_replace() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>

Gets the on_replace ComponentHook for this Component if one is defined.
Source§

fn on_remove() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>

Gets the on_remove ComponentHook for this Component if one is defined.
Source§

fn on_despawn() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>

Gets the on_despawn ComponentHook for this Component if one is defined.
Source§

fn map_entities<E>(_this: &mut Self, _mapper: &mut E)
where E: EntityMapper,

Maps the entities on this component using the given EntityMapper. This is used to remap entities in contexts like scenes and entity cloning. When deriving Component, this is populated by annotating fields containing entities with #[entities] Read more
Source§

impl Default for ChunkPos

Source§

fn default() -> ChunkPos

Returns the “default value” for a type. Read more
Source§

impl Deref for ChunkPos

Source§

type Target = IVec3

The resulting type after dereferencing.
Source§

fn deref(&self) -> &<ChunkPos as Deref>::Target

Dereferences the value.
Source§

impl DerefMut for ChunkPos

Source§

fn deref_mut(&mut self) -> &mut <ChunkPos as Deref>::Target

Mutably dereferences the value.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

Source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<C> Bundle for C
where C: Component,

Source§

fn component_ids( components: &mut ComponentsRegistrator<'_>, ids: &mut impl FnMut(ComponentId), )

Source§

fn get_component_ids( components: &Components, ids: &mut impl FnMut(Option<ComponentId>), )

Gets this Bundle’s component ids. This will be None if the component has not been registered.
Source§

impl<C> BundleFromComponents for C
where C: Component,

Source§

unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> C
where F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<C> DynamicBundle for C
where C: Component,

Source§

type Effect = ()

An operation on the entity that happens after inserting this bundle.
Source§

unsafe fn get_components( ptr: MovingPtr<'_, C>, func: &mut impl FnMut(StorageType, OwningPtr<'_>), ) -> <C as DynamicBundle>::Effect

Moves the components out of the bundle. Read more
Source§

unsafe fn apply_effect( _ptr: MovingPtr<'_, MaybeUninit<C>>, _entity: &mut EntityWorldMut<'_>, )

Applies the after-effects of spawning this bundle. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> FromWorld for T
where T: Default,

Source§

fn from_world(_world: &mut World) -> T

Creates Self using default().

Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoResult<T> for T

Source§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
Source§

impl<A> Is for A
where A: Any,

Source§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> Settings for T
where T: 'static + Send + Sync,

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,