gloss_renderer/
actor.rs

1use gloss_geometry::geom;
2use gloss_hecs::{CommandBuffer, Entity};
3use log::{error, warn};
4
5use crate::{
6    components::{Colors, Faces, ModelMatrix, Normals, UVs, Verts},
7    scene::Scene,
8};
9use gloss_utils::tensor::{DynamicMatrixOps, DynamicTensorFloat2D};
10
11/// Contains a reference to an entity in the world so that any mesh processing
12/// will directly affect the relevant entity in the world.
13#[derive(Clone, Copy)]
14pub struct Actor {
15    pub entity: Entity,
16}
17
18impl Actor {
19    pub fn new(name: &str, scene: &mut Scene) -> Self {
20        //check if there is an entity with the same name, if no then spawn one
21        let entity = scene.get_or_create_hidden_entity(name).entity();
22        Self { entity }
23    }
24
25    pub fn from_entity(entity: Entity) -> Self {
26        Self { entity }
27    }
28
29    pub fn apply_model_matrix(&mut self, scene: &mut Scene) {
30        let mut command_buffer = CommandBuffer::new();
31
32        {
33            let Some(model_matrix) = scene.get_comp::<&ModelMatrix>(&self.entity).ok() else {
34                warn!("No model matrix to apply");
35                return;
36            };
37
38            //verts
39            if let Ok(verts) = scene.get_comp::<&Verts>(&self.entity) {
40                let new_verts = geom::transform_verts(&verts.0.to_dmatrix(), &model_matrix.0);
41                let new_verts_tensor = DynamicTensorFloat2D::from_dmatrix(&new_verts);
42                command_buffer.insert_one(self.entity, Verts(new_verts_tensor));
43            }
44
45            //normals
46            if let Ok(normals) = scene.get_comp::<&Normals>(&self.entity) {
47                let new_normals = geom::transform_vectors(&normals.0.to_dmatrix(), &model_matrix.0);
48                let new_normals_tensor = DynamicTensorFloat2D::from_dmatrix(&new_normals);
49                command_buffer.insert_one(self.entity, Normals(new_normals_tensor));
50            }
51
52            //model matrix is now identity
53            command_buffer.insert_one(self.entity, ModelMatrix::default());
54        }
55
56        command_buffer.run_on(&mut scene.world);
57    }
58
59    //methods that are not static and act directly on the entity
60    pub fn save_obj(&self, scene: &Scene, path: &str) {
61        let Some(verts) = scene.get_comp::<&Verts>(&self.entity).ok() else {
62            error!("No vertices present on entity, cannot save as obj");
63            return;
64        };
65        let faces = scene.get_comp::<&Faces>(&self.entity).ok();
66        let normals = scene.get_comp::<&Normals>(&self.entity).ok();
67        let uvs = scene.get_comp::<&UVs>(&self.entity).ok();
68
69        //TODO modify data given the model matrix
70        geom::save_obj(
71            &verts.0.to_dmatrix(),
72            faces.as_ref().map(|v| v.0.to_dmatrix()).as_ref(),
73            uvs.as_ref().map(|v| v.0.to_dmatrix()).as_ref(),
74            normals.as_ref().map(|v| v.0.to_dmatrix()).as_ref(),
75            path,
76        );
77    }
78
79    pub fn save_ply(&self, scene: &Scene, path: &str) {
80        let Some(verts) = scene.get_comp::<&Verts>(&self.entity).ok() else {
81            error!("No vertices present on entity, cannot save as obj");
82            return;
83        };
84
85        let faces = scene.get_comp::<&Faces>(&self.entity).ok();
86        let normals = scene.get_comp::<&Normals>(&self.entity).ok();
87        let uvs = scene.get_comp::<&UVs>(&self.entity).ok();
88        let colors = scene.get_comp::<&Colors>(&self.entity).ok();
89
90        //TODO modify data given the model matrix
91
92        geom::save_ply(
93            &verts.0.to_dmatrix(),
94            faces.as_ref().map(|v| v.0.to_dmatrix()).as_ref(),
95            uvs.as_ref().map(|v| v.0.to_dmatrix()).as_ref(),
96            normals.as_ref().map(|v| v.0.to_dmatrix()).as_ref(),
97            colors.as_ref().map(|v| v.0.to_dmatrix()).as_ref(),
98            path,
99        );
100    }
101}