load jupiter from a texture rather than scene
This commit is contained in:
parent
1f046fe8c3
commit
ccd993a4fe
Binary file not shown.
Before Width: | Height: | Size: 495 KiB After Width: | Height: | Size: 403 KiB |
|
@ -11,10 +11,12 @@ actor 0 0 0 suit
|
||||||
engine monopropellant
|
engine monopropellant
|
||||||
|
|
||||||
actor 300000 0 500000 jupiter
|
actor 300000 0 500000 jupiter
|
||||||
scale 200000
|
scale 400000
|
||||||
|
sphere yes
|
||||||
physics off
|
physics off
|
||||||
rotationy -1.40
|
rotationx -0.50
|
||||||
angularmomentum 0 0.0001 0
|
rotationz -0.28
|
||||||
|
angularmomentum 30 30 30
|
||||||
|
|
||||||
actor 3000 0 0 moonlet
|
actor 3000 0 0 moonlet
|
||||||
scale 500
|
scale 500
|
||||||
|
|
239
src/world.rs
239
src/world.rs
|
@ -22,7 +22,6 @@ const ASSET_ASTEROID2: &str = "models/asteroid2.glb#Scene0";
|
||||||
fn asset_name_to_path(name: &str) -> &'static str {
|
fn asset_name_to_path(name: &str) -> &'static str {
|
||||||
match name {
|
match name {
|
||||||
"suit" => "models/suit.glb#Scene0",
|
"suit" => "models/suit.glb#Scene0",
|
||||||
"jupiter" => "models/jupiter.glb#Scene0",
|
|
||||||
"asteroid1" => ASSET_ASTEROID1,
|
"asteroid1" => ASSET_ASTEROID1,
|
||||||
"asteroid2" => ASSET_ASTEROID2,
|
"asteroid2" => ASSET_ASTEROID2,
|
||||||
"moonlet" => "models/moonlet.glb#Scene0",
|
"moonlet" => "models/moonlet.glb#Scene0",
|
||||||
|
@ -38,15 +37,19 @@ pub struct WorldPlugin;
|
||||||
impl Plugin for WorldPlugin {
|
impl Plugin for WorldPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(Startup, (setup, load_defs));
|
app.add_systems(Startup, (setup, load_defs));
|
||||||
|
app.add_systems(Update, spawn_entities);
|
||||||
//app.add_systems(Update, asset_loaded.after(load_cubemap_asset));
|
//app.add_systems(Update, asset_loaded.after(load_cubemap_asset));
|
||||||
//app.add_systems(Update, swap_world_on_ar_toggle);
|
//app.add_systems(Update, swap_world_on_ar_toggle);
|
||||||
app.add_plugins(PhysicsPlugins::default());
|
app.add_plugins(PhysicsPlugins::default());
|
||||||
//app.add_plugins(PhysicsDebugPlugin::default());
|
//app.add_plugins(PhysicsDebugPlugin::default());
|
||||||
app.insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)));
|
app.insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)));
|
||||||
app.insert_resource(Gravity(Vec3::splat(0.0)));
|
app.insert_resource(Gravity(Vec3::splat(0.0)));
|
||||||
|
app.add_event::<SpawnEvent>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Event)] pub struct SpawnEvent(ParserState);
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct Star;
|
pub struct Star;
|
||||||
|
|
||||||
|
@ -183,12 +186,14 @@ pub fn setup(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone)]
|
||||||
enum DefClass {
|
enum DefClass {
|
||||||
Actor,
|
Actor,
|
||||||
Chat,
|
Chat,
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct ParserState {
|
struct ParserState {
|
||||||
class: DefClass,
|
class: DefClass,
|
||||||
|
|
||||||
|
@ -204,6 +209,7 @@ struct ParserState {
|
||||||
rotation: Quat,
|
rotation: Quat,
|
||||||
angular_momentum: Vec3,
|
angular_momentum: Vec3,
|
||||||
pronoun: String,
|
pronoun: String,
|
||||||
|
is_sphere: bool,
|
||||||
is_player: bool,
|
is_player: bool,
|
||||||
is_lifeform: bool,
|
is_lifeform: bool,
|
||||||
is_alive: bool,
|
is_alive: bool,
|
||||||
|
@ -250,6 +256,7 @@ impl Default for ParserState {
|
||||||
rotation: Quat::IDENTITY,
|
rotation: Quat::IDENTITY,
|
||||||
angular_momentum: Vec3::new(0.03, 0.3, 0.09),
|
angular_momentum: Vec3::new(0.03, 0.3, 0.09),
|
||||||
pronoun: "they/them".to_string(),
|
pronoun: "they/them".to_string(),
|
||||||
|
is_sphere: false,
|
||||||
is_player: false,
|
is_player: false,
|
||||||
is_lifeform: false,
|
is_lifeform: false,
|
||||||
is_alive: false,
|
is_alive: false,
|
||||||
|
@ -291,14 +298,6 @@ impl ParserState {
|
||||||
self.text = default.text;
|
self.text = default.text;
|
||||||
self.is_choice = default.is_choice;
|
self.is_choice = default.is_choice;
|
||||||
}
|
}
|
||||||
fn reset_chat(&mut self) {
|
|
||||||
let default = ParserState::default();
|
|
||||||
self.reset_message();
|
|
||||||
self.stores_item = default.stores_item;
|
|
||||||
}
|
|
||||||
fn reset(&mut self) {
|
|
||||||
*self = Self::default();
|
|
||||||
}
|
|
||||||
fn as_chatbranch(&self) -> actor::ChatBranch {
|
fn as_chatbranch(&self) -> actor::ChatBranch {
|
||||||
return actor::ChatBranch {
|
return actor::ChatBranch {
|
||||||
id: self.chat.clone(),
|
id: self.chat.clone(),
|
||||||
|
@ -315,91 +314,10 @@ impl ParserState {
|
||||||
script_parameter2: self.script_parameter2.clone(),
|
script_parameter2: self.script_parameter2.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn spawn_chat(&mut self, commands: &mut Commands) {
|
|
||||||
if self.stores_item {
|
|
||||||
debug!("{:#?}", self.as_chatbranch());
|
|
||||||
commands.spawn(self.as_chatbranch());
|
|
||||||
}
|
|
||||||
self.reset_message();
|
|
||||||
}
|
|
||||||
fn spawn_actor(&mut self, commands: &mut Commands, asset_server: &Res<AssetServer>) {
|
|
||||||
let mut actor = commands.spawn_empty();
|
|
||||||
actor.insert(actor::Actor {
|
|
||||||
id: self.id.clone(),
|
|
||||||
camdistance: self.camdistance,
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
actor.insert(SceneBundle {
|
|
||||||
transform: Transform {
|
|
||||||
translation: self.pos,
|
|
||||||
scale: Vec3::splat(self.model_scale),
|
|
||||||
rotation: self.rotation,
|
|
||||||
},
|
|
||||||
scene: asset_server.load(asset_name_to_path(self.model.as_str())),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
|
|
||||||
// Physics Parameters
|
|
||||||
if self.has_physics {
|
|
||||||
let fix_scale = 1.0 / self.model_scale.powf(3.0);
|
|
||||||
actor.insert(RigidBody::Dynamic);
|
|
||||||
actor.insert(AngularVelocity(self.angular_momentum));
|
|
||||||
actor.insert(self.collider.clone());
|
|
||||||
actor.insert(ColliderDensity(self.mass * fix_scale));
|
|
||||||
}
|
|
||||||
// TODO: angular velocity for objects without collisions, static objects
|
|
||||||
|
|
||||||
// Optional Components
|
|
||||||
if self.is_player {
|
|
||||||
actor.insert(actor::Player);
|
|
||||||
actor.insert(actor::PlayerCamera);
|
|
||||||
}
|
|
||||||
if self.is_lifeform {
|
|
||||||
actor.insert(actor::LifeForm::default());
|
|
||||||
actor.insert(actor::Suit {
|
|
||||||
oxygen: self.oxygen,
|
|
||||||
oxygen_max: nature::OXY_D,
|
|
||||||
integrity: self.suit_integrity,
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if !self.chat.is_empty() {
|
|
||||||
actor.insert(actor::Talker {
|
|
||||||
conv_id: self.chat.clone(),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if self.is_vehicle {
|
|
||||||
actor.insert(actor::Vehicle::default());
|
|
||||||
}
|
|
||||||
if self.is_vehicle || self.is_suited {
|
|
||||||
actor.insert(actor::Engine {
|
|
||||||
thrust_forward: self.thrust_forward,
|
|
||||||
thrust_back: self.thrust_back,
|
|
||||||
thrust_sideways: self.thrust_sideways,
|
|
||||||
reaction_wheels: self.reaction_wheels,
|
|
||||||
warmup_seconds: self.warmup_seconds,
|
|
||||||
engine_type: self.engine_type,
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//info!("Spawning actor {} with model {} at {}/{}/{}",
|
|
||||||
// self.name, self.model, self.pos.x, self.pos.y, self.pos.z);
|
|
||||||
self.reset();
|
|
||||||
}
|
|
||||||
fn spawn_entities(&mut self, commands: &mut Commands, asset_server: &Res<AssetServer>) {
|
|
||||||
match self.class {
|
|
||||||
DefClass::Actor => { self.spawn_actor(commands, asset_server); }
|
|
||||||
DefClass::Chat => { self.spawn_chat(commands); }
|
|
||||||
DefClass::None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_defs(
|
pub fn load_defs(
|
||||||
mut commands: Commands,
|
mut ew_spawn: EventWriter<SpawnEvent>,
|
||||||
asset_server: Res<AssetServer>,
|
|
||||||
) {
|
) {
|
||||||
let re1 = Regex::new(r"^\s*([a-z_-]+)\s+(.*)$").unwrap();
|
let re1 = Regex::new(r"^\s*([a-z_-]+)\s+(.*)$").unwrap();
|
||||||
let re2 = Regex::new("\"([^\"]*)\"|(-?[0-9]+(?:\\.[0-9]+)?)|([a-zA-Z_-][a-zA-Z0-9_-]*)").unwrap();
|
let re2 = Regex::new("\"([^\"]*)\"|(-?[0-9]+(?:\\.[0-9]+)?)|([a-zA-Z_-][a-zA-Z0-9_-]*)").unwrap();
|
||||||
|
@ -445,8 +363,8 @@ pub fn load_defs(
|
||||||
match parts.as_slice() {
|
match parts.as_slice() {
|
||||||
// Parsing actors
|
// Parsing actors
|
||||||
["actor", x, y, z, model] => {
|
["actor", x, y, z, model] => {
|
||||||
state.spawn_entities(&mut commands, &asset_server);
|
ew_spawn.send(SpawnEvent(state));
|
||||||
state.reset();
|
state = ParserState::default();
|
||||||
state.class = DefClass::Actor;
|
state.class = DefClass::Actor;
|
||||||
state.model = model.to_string();
|
state.model = model.to_string();
|
||||||
if let (Ok(x_float), Ok(y_float), Ok(z_float)) =
|
if let (Ok(x_float), Ok(y_float), Ok(z_float)) =
|
||||||
|
@ -455,10 +373,13 @@ pub fn load_defs(
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
error!("Can't parse coordinates as floats in def: {line}");
|
error!("Can't parse coordinates as floats in def: {line}");
|
||||||
state.reset();
|
state = ParserState::default();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
["sphere", "yes"] => {
|
||||||
|
state.is_sphere = true;
|
||||||
|
}
|
||||||
["id", id] => {
|
["id", id] => {
|
||||||
state.id = id.to_string();
|
state.id = id.to_string();
|
||||||
}
|
}
|
||||||
|
@ -498,7 +419,7 @@ pub fn load_defs(
|
||||||
}
|
}
|
||||||
["rotationx", rotation_x] => {
|
["rotationx", rotation_x] => {
|
||||||
if let Ok(rotation_x_float) = rotation_x.parse::<f32>() {
|
if let Ok(rotation_x_float) = rotation_x.parse::<f32>() {
|
||||||
state.rotation = Quat::from_rotation_x(PI * rotation_x_float);
|
state.rotation *= Quat::from_rotation_x(PI * rotation_x_float);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
error!("Can't parse float: {line}");
|
error!("Can't parse float: {line}");
|
||||||
|
@ -507,7 +428,16 @@ pub fn load_defs(
|
||||||
}
|
}
|
||||||
["rotationy", rotation_y] => {
|
["rotationy", rotation_y] => {
|
||||||
if let Ok(rotation_y_float) = rotation_y.parse::<f32>() {
|
if let Ok(rotation_y_float) = rotation_y.parse::<f32>() {
|
||||||
state.rotation = Quat::from_rotation_y(PI * rotation_y_float);
|
state.rotation *= Quat::from_rotation_y(PI * rotation_y_float);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
error!("Can't parse float: {line}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
["rotationz", rotation_z] => {
|
||||||
|
if let Ok(rotation_z_float) = rotation_z.parse::<f32>() {
|
||||||
|
state.rotation *= Quat::from_rotation_z(PI * rotation_z_float);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
error!("Can't parse float: {line}");
|
error!("Can't parse float: {line}");
|
||||||
|
@ -598,8 +528,8 @@ pub fn load_defs(
|
||||||
// Parsing chats
|
// Parsing chats
|
||||||
["chat", chat_name] => {
|
["chat", chat_name] => {
|
||||||
debug!("Registering chat: {}", chat_name);
|
debug!("Registering chat: {}", chat_name);
|
||||||
state.spawn_entities(&mut commands, &asset_server);
|
ew_spawn.send(SpawnEvent(state));
|
||||||
state.reset_chat();
|
state = ParserState::default();
|
||||||
state.class = DefClass::Chat;
|
state.class = DefClass::Chat;
|
||||||
state.chat = chat_name.to_string();
|
state.chat = chat_name.to_string();
|
||||||
}
|
}
|
||||||
|
@ -609,7 +539,7 @@ pub fn load_defs(
|
||||||
}
|
}
|
||||||
["msg", sleep, text] => {
|
["msg", sleep, text] => {
|
||||||
debug!("Registering message (sleep={}): {}", sleep, text);
|
debug!("Registering message (sleep={}): {}", sleep, text);
|
||||||
state.spawn_entities(&mut commands, &asset_server);
|
ew_spawn.send(SpawnEvent(state.clone()));
|
||||||
if let Ok(sleep_float) = sleep.parse::<f64>() {
|
if let Ok(sleep_float) = sleep.parse::<f64>() {
|
||||||
state.delay = sleep_float;
|
state.delay = sleep_float;
|
||||||
state.text = text.to_string();
|
state.text = text.to_string();
|
||||||
|
@ -622,7 +552,8 @@ pub fn load_defs(
|
||||||
}
|
}
|
||||||
["msg", sleep, label, goto, text] => {
|
["msg", sleep, label, goto, text] => {
|
||||||
debug!("Registering message (sleep={}): {}", sleep, text);
|
debug!("Registering message (sleep={}): {}", sleep, text);
|
||||||
state.spawn_entities(&mut commands, &asset_server);
|
ew_spawn.send(SpawnEvent(state.clone()));
|
||||||
|
state.reset_message();
|
||||||
if let Ok(sleep_float) = sleep.parse::<f64>() {
|
if let Ok(sleep_float) = sleep.parse::<f64>() {
|
||||||
state.delay = sleep_float;
|
state.delay = sleep_float;
|
||||||
state.text = text.to_string();
|
state.text = text.to_string();
|
||||||
|
@ -637,7 +568,8 @@ pub fn load_defs(
|
||||||
}
|
}
|
||||||
["choice", sleep, text] => {
|
["choice", sleep, text] => {
|
||||||
debug!("Registering choice (sleep={}): {}", sleep, text);
|
debug!("Registering choice (sleep={}): {}", sleep, text);
|
||||||
state.spawn_entities(&mut commands, &asset_server);
|
ew_spawn.send(SpawnEvent(state.clone()));
|
||||||
|
state.reset_message();
|
||||||
if let Ok(sleep_float) = sleep.parse::<f64>() {
|
if let Ok(sleep_float) = sleep.parse::<f64>() {
|
||||||
state.delay = sleep_float;
|
state.delay = sleep_float;
|
||||||
state.text = text.to_string();
|
state.text = text.to_string();
|
||||||
|
@ -650,7 +582,8 @@ pub fn load_defs(
|
||||||
}
|
}
|
||||||
["choice", sleep, label, goto, text] => {
|
["choice", sleep, label, goto, text] => {
|
||||||
debug!("Registering choice (sleep={}): {}", sleep, text);
|
debug!("Registering choice (sleep={}): {}", sleep, text);
|
||||||
state.spawn_entities(&mut commands, &asset_server);
|
ew_spawn.send(SpawnEvent(state.clone()));
|
||||||
|
state.reset_message();
|
||||||
if let Ok(sleep_float) = sleep.parse::<f64>() {
|
if let Ok(sleep_float) = sleep.parse::<f64>() {
|
||||||
state.delay = sleep_float;
|
state.delay = sleep_float;
|
||||||
state.text = text.to_string();
|
state.text = text.to_string();
|
||||||
|
@ -690,7 +623,107 @@ pub fn load_defs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.spawn_entities(&mut commands, &asset_server);
|
ew_spawn.send(SpawnEvent(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_entities(
|
||||||
|
mut er_spawn: EventReader<SpawnEvent>,
|
||||||
|
mut commands: Commands,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
for state_wrapper in er_spawn.read() {
|
||||||
|
let state = &state_wrapper.0;
|
||||||
|
if state.class == DefClass::Chat {
|
||||||
|
if state.stores_item {
|
||||||
|
commands.spawn(state.as_chatbranch());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if state.class == DefClass::Actor {
|
||||||
|
let mut actor = commands.spawn_empty();
|
||||||
|
actor.insert(actor::Actor {
|
||||||
|
id: state.id.clone(),
|
||||||
|
camdistance: state.camdistance,
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
if state.is_sphere {
|
||||||
|
let sphere_texture_handle: Handle<Image> = asset_server.load(format!("textures/{}.jpg", state.model));
|
||||||
|
let sphere_handle = meshes.add(Sphere::default().mesh().uv(128, 128));
|
||||||
|
let sphere_material_handle = materials.add(StandardMaterial {
|
||||||
|
base_color_texture: Some(sphere_texture_handle.clone()),
|
||||||
|
perceptual_roughness: 1.0,
|
||||||
|
metallic: 0.0,
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
actor.insert(PbrBundle {
|
||||||
|
mesh: sphere_handle,
|
||||||
|
material: sphere_material_handle,
|
||||||
|
transform: Transform {
|
||||||
|
translation: state.pos,
|
||||||
|
scale: Vec3::splat(state.model_scale),
|
||||||
|
rotation: state.rotation,
|
||||||
|
},
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
actor.insert(SceneBundle {
|
||||||
|
transform: Transform {
|
||||||
|
translation: state.pos,
|
||||||
|
scale: Vec3::splat(state.model_scale),
|
||||||
|
rotation: state.rotation,
|
||||||
|
},
|
||||||
|
scene: asset_server.load(asset_name_to_path(state.model.as_str())),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Physics Parameters
|
||||||
|
if state.has_physics {
|
||||||
|
let fix_scale = 1.0 / state.model_scale.powf(3.0);
|
||||||
|
actor.insert(RigidBody::Dynamic);
|
||||||
|
actor.insert(AngularVelocity(state.angular_momentum));
|
||||||
|
actor.insert(state.collider.clone());
|
||||||
|
actor.insert(ColliderDensity(state.mass * fix_scale));
|
||||||
|
}
|
||||||
|
// TODO: angular velocity for objects without collisions, static objects
|
||||||
|
|
||||||
|
// Optional Components
|
||||||
|
if state.is_player {
|
||||||
|
actor.insert(actor::Player);
|
||||||
|
actor.insert(actor::PlayerCamera);
|
||||||
|
}
|
||||||
|
if state.is_lifeform {
|
||||||
|
actor.insert(actor::LifeForm::default());
|
||||||
|
actor.insert(actor::Suit {
|
||||||
|
oxygen: state.oxygen,
|
||||||
|
oxygen_max: nature::OXY_D,
|
||||||
|
integrity: state.suit_integrity,
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if !state.chat.is_empty() {
|
||||||
|
actor.insert(actor::Talker {
|
||||||
|
conv_id: state.chat.clone(),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if state.is_vehicle {
|
||||||
|
actor.insert(actor::Vehicle::default());
|
||||||
|
}
|
||||||
|
if state.is_vehicle || state.is_suited {
|
||||||
|
actor.insert(actor::Engine {
|
||||||
|
thrust_forward: state.thrust_forward,
|
||||||
|
thrust_back: state.thrust_back,
|
||||||
|
thrust_sideways: state.thrust_sideways,
|
||||||
|
reaction_wheels: state.reaction_wheels,
|
||||||
|
warmup_seconds: state.warmup_seconds,
|
||||||
|
engine_type: state.engine_type,
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//pub fn swap_world_on_ar_toggle(
|
//pub fn swap_world_on_ar_toggle(
|
||||||
|
|
Loading…
Reference in a new issue