1use super::{IndexBuffer, TriMesh};
2use crate::math::{Point, Vector};
3use na::{self, Point2, Point3, RealField};
45/// Adds a double-sided quad to the scene.
6///
7/// The quad is initially centered at (0, 0, 0). Its normal is the `z` axis. The quad itself is
8/// composed of a user-defined number of triangles regularly spaced on a grid. This is the main way
9/// to draw height maps.
10///
11/// # Arguments
12/// * `w` - the quad width.
13/// * `h` - the quad height.
14/// * `usubdivs` - number of horizontal subdivisions. This correspond to the number of squares
15/// which will be placed horizontally on each line. Must not be `0`.
16/// * `vsubdivs` - number of vertical subdivisions. This correspond to the number of squares
17/// which will be placed vertically on each line. Must not be `0`.
18pub fn quad<N: RealField + Copy>(
19 width: N,
20 height: N,
21 usubdivs: usize,
22 vsubdivs: usize,
23) -> TriMesh<N> {
24let mut quad = unit_quad(usubdivs, vsubdivs);
2526let mut s = Vector::zeros();
27 s[0] = width;
28 s[1] = height;
2930for i in 2..3 {
31 s[i] = na::one();
32 }
3334 quad.scale_by(&s);
3536 quad
37}
3839/// Adds a double-sided quad with the specified grid of vertices.
40///
41/// Normals are automatically computed.
42///
43/// # Arguments
44/// * `nhpoints` - number of columns on the grid.
45/// * `nvpoints` - number of lines on the grid.
46pub fn quad_with_vertices<N: RealField + Copy>(
47 vertices: &[Point<N>],
48 nhpoints: usize,
49 nvpoints: usize,
50) -> TriMesh<N> {
51assert!(
52 nhpoints > 1 && nvpoints > 1,
53"The number of points must be at least 2 in each dimension."
54);
5556let mut res = unit_quad(nhpoints - 1, nvpoints - 1);
5758for (dest, src) in res.coords.iter_mut().zip(vertices.iter()) {
59*dest = src.clone();
60 }
6162 res
63}
6465/// Adds a double-sided quad with unit size to the scene.
66///
67/// The quad is initially centered at (0, 0, 0). Its normal is the `z` axis. The quad itself is
68/// composed of a user-defined number of triangles regularly spaced on a grid. This is the main way
69/// to draw height maps.
70///
71/// # Arguments
72/// * `usubdivs` - number of horizontal subdivisions. This correspond to the number of squares
73/// which will be placed horizontally on each line. Must not be `0`.
74/// * `vsubdivs` - number of vertical subdivisions. This correspond to the number of squares
75/// which will be placed vertically on each line. Must not be `0`.
76pub fn unit_quad<N: RealField + Copy>(usubdivs: usize, vsubdivs: usize) -> TriMesh<N> {
77assert!(
78 usubdivs > 0 && vsubdivs > 0,
79"The number of subdivisions cannot be zero"
80);
81assert!(3 >= 2);
8283let wstep = na::one::<N>() / na::convert(usubdivs as f64);
84let hstep = na::one::<N>() / na::convert(vsubdivs as f64);
85let cw = na::convert(0.5);
86let ch = na::convert(0.5);
8788let mut vertices = Vec::new();
89let mut normals = Vec::new();
90let mut triangles = Vec::new();
91let mut tex_coords = Vec::new();
9293// create the vertices
94for i in 0usize..vsubdivs + 1 {
95for j in 0usize..usubdivs + 1 {
96let ni: N = na::convert(i as f64);
97let nj: N = na::convert(j as f64);
9899let mut v = Point::origin();
100 v[0] = nj * wstep - cw;
101 v[1] = ni * hstep - ch;
102 vertices.push(v);
103let _1 = na::one::<N>();
104 tex_coords.push(Point2::new(_1 - nj * wstep, _1 - ni * hstep))
105 }
106 }
107108// create the normals
109for _ in 0..(vsubdivs + 1) * (usubdivs + 1) {
110let mut n = Vector::zeros();
111 n[0] = na::one();
112 normals.push(n)
113 }
114115// create triangles
116fn dl_triangle(i: u32, j: u32, ws: u32) -> Point3<u32> {
117 Point3::new((i + 1) * ws + j, i * ws + j, (i + 1) * ws + j + 1)
118 }
119120fn ur_triangle(i: u32, j: u32, ws: u32) -> Point3<u32> {
121 Point3::new(i * ws + j, i * ws + (j + 1), (i + 1) * ws + j + 1)
122 }
123124for i in 0usize..vsubdivs {
125for j in 0usize..usubdivs {
126// build two triangles...
127triangles.push(dl_triangle(i as u32, j as u32, (usubdivs + 1) as u32));
128 triangles.push(ur_triangle(i as u32, j as u32, (usubdivs + 1) as u32));
129 }
130 }
131132 TriMesh::new(
133 vertices,
134Some(normals),
135Some(tex_coords),
136Some(IndexBuffer::Unified(triangles)),
137 )
138}