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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use nalgebra as na;
use na::{DMatrix, Dynamic, Vector3, RealField, geometry::{Point2, Point3}};
use ncollide3d::procedural::{TriMesh, IndexBuffer};
use ncollide3d::shape::HeightField;
pub use displacement::{midpoint_displacement, diamond_square};
mod displacement;
pub struct Heightmap<F> {
stride: usize,
data: Vec<F>,
}
impl<F> Heightmap<F> {
pub fn len0(&self) -> usize { self.stride }
pub fn len1(&self) -> usize { self.data.len() / self.stride }
pub fn set(&mut self, x: usize, y: usize, val: F) {
assert!(x < self.stride);
self.data[x + y * self.stride] = val;
}
}
impl<F: Clone> Heightmap<F> {
pub fn new(x: usize, y: usize, v: F) -> Self {
Heightmap {
stride: x,
data: vec![v; x * y],
}
}
pub fn get(&self, x: usize, y: usize) -> F {
assert!(x < self.stride);
self.data[x + y * self.stride].clone()
}
}
impl<F: RealField> Heightmap<F> {
pub fn to_heightfield(&self, width: F, height: F) -> HeightField<F> {
let rows = Dynamic::new(self.len1());
let cols = Dynamic::new(self.len0());
let heights = DMatrix::from_row_slice_generic(rows, cols, &self.data[..]);
let scale = Vector3::new(width, na::convert::<f64, F>(1.0), height);
HeightField::new(heights, scale)
}
pub fn to_trimesh(&self, width: F, height: F) -> TriMesh<F> {
let usubdivs = self.stride - 1;
let vsubdivs = self.data.len() / self.stride - 1;
let twstep = na::one::<F>() / na::convert(usubdivs as f64);
let thstep = na::one::<F>() / na::convert(vsubdivs as f64);
let wstep = twstep * width;
let hstep = thstep * height;
let cw = na::convert::<f64, F>(0.5) * width;
let ch = na::convert::<f64, F>(0.5) * height;
let mut vertices = Vec::new();
let mut triangles = Vec::new();
let mut tex_coords = Vec::new();
for i in 0usize..vsubdivs + 1 {
for j in 0usize..usubdivs + 1 {
let ni: F = na::convert(i as f64);
let nj: F = na::convert(j as f64);
let v = Point3::new(
nj * wstep - cw,
ni * hstep - ch,
self.get(i, j));
vertices.push(v);
let _1 = na::one::<F>();
tex_coords.push(Point2::new(_1 - nj * twstep, _1 - ni * thstep))
}
}
fn dl_triangle(i: u32, j: u32, ws: u32) -> Point3<u32> {
Point3::new((i + 1) * ws + j, i * ws + j, (i + 1) * ws + j + 1)
}
fn ur_triangle(i: u32, j: u32, ws: u32) -> Point3<u32> {
Point3::new(i * ws + j, i * ws + (j + 1), (i + 1) * ws + j + 1)
}
for i in 0usize..vsubdivs {
for j in 0usize..usubdivs {
triangles.push(dl_triangle(i as u32, j as u32, (usubdivs + 1) as u32));
triangles.push(ur_triangle(i as u32, j as u32, (usubdivs + 1) as u32));
}
}
let mut mesh = TriMesh::new(
vertices,
None,
Some(tex_coords),
Some(IndexBuffer::Unified(triangles)),
);
mesh.recompute_normals();
mesh
}
}