1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use crate::{Mesh3D, ToMesh3D};
use rfw_backend::Mesh3dFlags;
use rfw_math::*;

pub struct Quad3D {
    pub normal: Vec3,
    pub position: Vec3,
    pub width: f32,
    pub height: f32,
    pub material_id: u32,

    vertices: [Vec3; 6],
    normals: [Vec3; 6],
    uvs: [Vec2; 6],
    material_ids: [u32; 2],
}

#[allow(dead_code)]
impl Quad3D {
    pub fn new<T: Into<[f32; 3]>>(
        normal: T,
        position: T,
        width: f32,
        height: f32,
        material_id: u32,
    ) -> Quad3D {
        let material_id = material_id.max(0);
        // TODO: uvs
        let uvs = [vec2(0.0, 0.0); 6];
        let material_ids = [material_id as u32; 2];

        let normal = Vec3::from(normal.into());
        let position = Vec3::from(position.into());

        let (vertices, normals) = Quad3D::generate_render_data(position, normal, width, height);

        Quad3D {
            normal,
            position,
            width,
            height,
            material_id,

            vertices,
            normals,
            uvs,
            material_ids,
        }
    }

    fn generate_render_data(pos: Vec3, n: Vec3, width: f32, height: f32) -> ([Vec3; 6], [Vec3; 6]) {
        let normal = n.normalize();
        let tmp = if normal.x > 0.9 {
            Vec3::new(0.0, 1.0, 0.0)
        } else {
            Vec3::new(1.0, 0.0, 0.0)
        };

        let tangent: Vec3 = 0.5 * width * normal.cross(tmp).normalize();
        let bi_tangent: Vec3 = 0.5 * height * tangent.normalize().cross(normal);

        let vertices: [Vec3; 6] = [
            pos - bi_tangent - tangent,
            pos + bi_tangent - tangent,
            pos - bi_tangent + tangent,
            pos + bi_tangent - tangent,
            pos + bi_tangent + tangent,
            pos - bi_tangent + tangent,
        ];

        let normals = [normal.clone(); 6];

        (vertices, normals)
    }
}

impl ToMesh3D for Quad3D {
    fn into_mesh_3d(self) -> Mesh3D {
        Mesh3D::new(
            self.vertices.to_vec(),
            self.normals.to_vec(),
            Vec::new(),
            Vec::new(),
            self.uvs.to_vec(),
            self.material_ids.to_vec(),
            Mesh3dFlags::default(),
            Some("quad"),
        )
    }
}