use nalgebra_glm::{Quat, Vec3, Vec4};
use nightshade::ecs::bounding_volume::components::BoundingVolume;
use nightshade::ecs::text::components::{TextAlignment, TextProperties, VerticalAlignment};
use nightshade::prelude::*;
fn hue_to_rgb(hue: f32) -> Vec3 {
let h = hue / 60.0;
let c = 1.0;
let x = c * (1.0 - ((h % 2.0) - 1.0).abs());
let (r, g, b) = match h as i32 {
0 => (c, x, 0.0),
1 => (x, c, 0.0),
2 => (0.0, c, x),
3 => (0.0, x, c),
4 => (x, 0.0, c),
_ => (c, 0.0, x),
};
Vec3::new(r, g, b)
}
pub fn spawn_lines(world: &mut World) {
const LINE_COUNT: usize = 2_000;
let entity = world.spawn_entities(
LINES | NAME | LOCAL_TRANSFORM | GLOBAL_TRANSFORM | LOCAL_TRANSFORM_DIRTY | VISIBILITY,
1,
)[0];
if let Some(name) = world.core.get_name_mut(entity) {
*name = Name(format!("{} Lines", LINE_COUNT));
}
if let Some(transform) = world.core.get_local_transform_mut(entity) {
*transform = LocalTransform::default();
}
if let Some(lines) = world.core.get_lines_mut(entity) {
let mut test_lines = Vec::new();
(0..LINE_COUNT).for_each(|index| {
let angle = (index as f32 / LINE_COUNT as f32) * std::f32::consts::PI * 20.0;
let radius = 5.0 + (index as f32 / LINE_COUNT as f32) * 50.0;
let height = (index as f32 / 100.0).sin() * 20.0;
let start = Vec3::new(radius * angle.cos(), height, radius * angle.sin());
let end = Vec3::new(
radius * (angle + 0.05).cos(),
height + 2.0,
radius * (angle + 0.05).sin(),
);
let hue = (index as f32 / LINE_COUNT as f32) * 360.0;
let color = hue_to_rgb(hue);
test_lines.push(Line {
start,
end,
color: Vec4::new(color.x, color.y, color.z, 1.0),
});
});
lines.lines = test_lines;
}
}
pub fn spawn_meshes(world: &mut World) {
const MESH_COUNT: usize = 10_000;
const GRID_SIZE: usize = 22;
const SPACING: f32 = 2.0;
let parent_entity = world.spawn_entities(
NAME | LOCAL_TRANSFORM | LOCAL_TRANSFORM_DIRTY | GLOBAL_TRANSFORM,
1,
)[0];
world
.core
.set_name(parent_entity, Name("10,000 Meshes Group".to_string()));
world.core.set_local_transform(
parent_entity,
LocalTransform {
translation: Vec3::new(0.0, 0.0, 0.0),
rotation: Quat::identity(),
scale: Vec3::new(1.0, 1.0, 1.0),
},
);
world
.core
.set_local_transform_dirty(parent_entity, LocalTransformDirty);
world
.core
.set_global_transform(parent_entity, GlobalTransform::default());
let mut mesh_count = 0;
let mesh_types = ["Cube", "Sphere", "Cylinder", "Cone", "Torus", "Plane"];
let offset = -(GRID_SIZE as f32 * SPACING) / 2.0;
let y_offset = 1.0;
'outer: for x in 0..GRID_SIZE {
for y in 0..GRID_SIZE {
for z in 0..GRID_SIZE {
if mesh_count >= MESH_COUNT {
break 'outer;
}
let entity = world.spawn_entities(
NAME | LOCAL_TRANSFORM
| LOCAL_TRANSFORM_DIRTY
| GLOBAL_TRANSFORM
| RENDER_MESH
| MATERIAL_REF
| VISIBILITY
| CASTS_SHADOW
| PARENT
| BOUNDING_VOLUME,
1,
)[0];
world.update_parent(entity, Some(Parent(Some(parent_entity))));
world
.core
.set_name(entity, Name(format!("Mesh {}", mesh_count + 1)));
world.core.set_local_transform(
entity,
LocalTransform {
translation: Vec3::new(
offset + x as f32 * SPACING,
offset + y as f32 * SPACING + y_offset,
offset + z as f32 * SPACING,
),
rotation: Quat::identity(),
scale: Vec3::new(0.5, 0.5, 0.5),
},
);
world
.core
.set_local_transform_dirty(entity, LocalTransformDirty);
world
.core
.set_global_transform(entity, GlobalTransform::default());
let mesh_type = mesh_types[mesh_count % mesh_types.len()];
world
.core
.set_render_mesh(entity, RenderMesh::new(mesh_type));
world.resources.mesh_render_state.mark_entity_added(entity);
world
.core
.set_bounding_volume(entity, BoundingVolume::from_mesh_type(mesh_type));
let material_name = match mesh_count % 6 {
0 => "Red",
1 => "Green",
2 => "Blue",
3 => "Yellow",
4 => "Magenta",
_ => "Cyan",
};
if let Some(&index) = world
.resources
.material_registry
.registry
.name_to_index
.get(material_name)
{
world
.resources
.material_registry
.registry
.add_reference(index);
}
world
.core
.set_material_ref(entity, MaterialRef::new(material_name.to_string()));
world
.core
.set_visibility(entity, Visibility { visible: true });
world.core.set_casts_shadow(entity, CastsShadow);
mesh_count += 1;
}
}
}
}
pub fn spawn_3d_text(world: &mut World) {
let text_index = world.resources.text_cache.add_text("3D Text Object");
let entity = world.spawn_entities(
NAME | LOCAL_TRANSFORM | LOCAL_TRANSFORM_DIRTY | GLOBAL_TRANSFORM | TEXT | VISIBILITY,
1,
)[0];
world.core.set_name(entity, Name("3D Text".to_string()));
world.core.set_local_transform(
entity,
LocalTransform {
translation: Vec3::new(
rand::random::<f32>() * 10.0 - 5.0,
3.0,
rand::random::<f32>() * 10.0 - 5.0,
),
rotation: Quat::identity(),
scale: Vec3::new(1.0, 1.0, 1.0),
},
);
world
.core
.set_local_transform_dirty(entity, LocalTransformDirty);
world
.core
.set_global_transform(entity, GlobalTransform::default());
if let Some(text) = world.core.get_text_mut(entity) {
text.text_index = text_index;
text.properties = TextProperties {
font_size: 32.0,
color: Vec4::new(
rand::random::<f32>(),
rand::random::<f32>(),
rand::random::<f32>(),
1.0,
),
alignment: TextAlignment::Center,
vertical_alignment: VerticalAlignment::Middle,
..Default::default()
};
text.dirty = true;
}
}
pub fn spawn_text_lattice(world: &mut World) {
const TEXT_COUNT: usize = 5_000;
const GRID_X: usize = 25;
const GRID_Y: usize = 20;
const GRID_Z: usize = 10;
const SPACING: f32 = 3.0;
let parent_entity = world.spawn_entities(
NAME | LOCAL_TRANSFORM | LOCAL_TRANSFORM_DIRTY | GLOBAL_TRANSFORM,
1,
)[0];
world.core.set_name(
parent_entity,
Name("Text Lattice (Stress Test)".to_string()),
);
world.core.set_local_transform(
parent_entity,
LocalTransform {
translation: Vec3::new(0.0, 5.0, 0.0),
rotation: Quat::identity(),
scale: Vec3::new(1.0, 1.0, 1.0),
},
);
world
.core
.set_local_transform_dirty(parent_entity, LocalTransformDirty);
world
.core
.set_global_transform(parent_entity, GlobalTransform::default());
let text_variations = [
"Text", "Hello", "World", "Test", "Lorem", "Ipsum", "3D", "Engine", "Render", "Buffer",
"Dynamic", "Scale", "Vertex", "Index", "GPU", "SDF",
];
let offset_x = -(GRID_X as f32 * SPACING) / 2.0;
let offset_y = -(GRID_Y as f32 * SPACING) / 2.0;
let offset_z = -(GRID_Z as f32 * SPACING) / 2.0;
let mut text_count = 0;
'outer: for x in 0..GRID_X {
for y in 0..GRID_Y {
for z in 0..GRID_Z {
if text_count >= TEXT_COUNT {
break 'outer;
}
let text_content = format!(
"{} #{}",
text_variations[text_count % text_variations.len()],
text_count + 1
);
let text_index = world.resources.text_cache.add_text(&text_content);
let entity = world.spawn_entities(
NAME | LOCAL_TRANSFORM
| LOCAL_TRANSFORM_DIRTY
| GLOBAL_TRANSFORM
| TEXT
| VISIBILITY
| PARENT,
1,
)[0];
world.core.set_parent(entity, Parent(Some(parent_entity)));
world
.core
.set_name(entity, Name(format!("Text {}", text_count + 1)));
world.core.set_local_transform(
entity,
LocalTransform {
translation: Vec3::new(
offset_x + x as f32 * SPACING,
offset_y + y as f32 * SPACING,
offset_z + z as f32 * SPACING,
),
rotation: Quat::identity(),
scale: Vec3::new(1.0, 1.0, 1.0),
},
);
world
.core
.set_local_transform_dirty(entity, LocalTransformDirty);
world
.core
.set_global_transform(entity, GlobalTransform::default());
if let Some(text) = world.core.get_text_mut(entity) {
text.text_index = text_index;
text.properties = TextProperties {
font_size: 16.0,
color: Vec4::new(
rand::random::<f32>(),
rand::random::<f32>(),
rand::random::<f32>(),
1.0,
),
alignment: TextAlignment::Center,
vertical_alignment: VerticalAlignment::Middle,
..Default::default()
};
text.dirty = true;
}
text_count += 1;
}
}
}
}