mesh.rs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use crate::gfx::{
  19. DebugTag, DrawMesh, ManagedBufferPtr, ManagedTexturePtr, Point, Rectangle, RenderApi, Vertex,
  20. };
  21. pub type Color = [f32; 4];
  22. // rgba!(0xRRGGBBAA) expands to a [f32; 4] with each channel normalized to 0. .. 1.
  23. #[macro_export]
  24. macro_rules! rgba {
  25. ($c:expr) => {{
  26. let c: u32 = $c;
  27. [
  28. ((c >> 24) & 0xFF) as f32 / 255.,
  29. ((c >> 16) & 0xFF) as f32 / 255.,
  30. ((c >> 8) & 0xFF) as f32 / 255.,
  31. (c & 0xFF) as f32 / 255.,
  32. ]
  33. }};
  34. }
  35. pub use crate::rgba;
  36. #[allow(dead_code)]
  37. pub const COLOR_RED: Color = [1., 0., 0., 1.];
  38. #[allow(dead_code)]
  39. pub const COLOR_DARKGREY: Color = [0.2, 0.2, 0.2, 1.];
  40. #[allow(dead_code)]
  41. pub const COLOR_LIGHTGREY: Color = [0.7, 0.7, 0.7, 1.];
  42. #[allow(dead_code)]
  43. pub const COLOR_GREEN: Color = [0., 1., 0., 1.];
  44. #[allow(dead_code)]
  45. pub const COLOR_BLUE: Color = [0., 0., 1., 1.];
  46. #[allow(dead_code)]
  47. pub const COLOR_PINK: Color = [0.8, 0.3, 0.8, 1.];
  48. #[allow(dead_code)]
  49. pub const COLOR_CYAN: Color = [0., 1., 1., 1.];
  50. #[allow(dead_code)]
  51. pub const COLOR_TEAL: Color = [0.0784, 0.6824, 0.7216, 1.];
  52. #[allow(dead_code)]
  53. pub const COLOR_MINT: Color = [0.467, 1.0, 0.745, 1.0];
  54. #[allow(dead_code)]
  55. pub const COLOR_MINT_OP: Color = [0.573, 0.847, 0.714, 1.0];
  56. #[allow(dead_code)]
  57. pub const COLOR_INACTIVE: Color = [0.596, 0.765, 0.682, 1.0];
  58. #[allow(dead_code)]
  59. pub const COLOR_PURPLE: Color = [1., 0., 1., 1.];
  60. #[allow(dead_code)]
  61. pub const COLOR_WHITE: Color = [1., 1., 1., 1.];
  62. #[allow(dead_code)]
  63. pub const COLOR_BLACK: Color = [1., 1., 1., 1.];
  64. #[allow(dead_code)]
  65. pub const COLOR_GREY: Color = [0.5, 0.5, 0.5, 1.];
  66. #[allow(dead_code)]
  67. pub const DONE_MENU_BTN_GRADIENT: [[f32; 4]; 4] =
  68. [[0., 0.1, 0.15, 1.], [0., 0.1, 0.15, 1.], [0., 0., 0., 1.], [0., 0., 0., 1.]];
  69. #[allow(dead_code)]
  70. pub const CANCEL_MENU_BTN_GRADIENT: [[f32; 4]; 4] =
  71. [[0., 0., 0., 1.], [0., 0., 0., 1.], [0.1, 0., 0., 1.], [0.1, 0., 0., 1.]];
  72. #[allow(dead_code)]
  73. pub const MINT_BTN_GRADIENT: [[f32; 4]; 4] =
  74. [[0., 0.1, 0.15, 1.], [0., 0.1, 0.15, 1.], [0., 0., 0., 1.], [0., 0., 0., 1.]];
  75. #[derive(Clone)]
  76. pub struct MeshInfo {
  77. pub vertex_buffer: ManagedBufferPtr,
  78. pub index_buffer: ManagedBufferPtr,
  79. pub num_elements: i32,
  80. }
  81. impl MeshInfo {
  82. /// Convenience method for textured mesh
  83. pub fn draw_with_textures(self, textures: Vec<ManagedTexturePtr>) -> DrawMesh {
  84. DrawMesh {
  85. vertex_buffer: self.vertex_buffer,
  86. index_buffer: self.index_buffer,
  87. textures: Some(textures),
  88. num_elements: self.num_elements,
  89. }
  90. }
  91. /// Convenience method
  92. pub fn draw_untextured(self) -> DrawMesh {
  93. DrawMesh {
  94. vertex_buffer: self.vertex_buffer,
  95. index_buffer: self.index_buffer,
  96. textures: None,
  97. num_elements: self.num_elements,
  98. }
  99. }
  100. }
  101. pub struct MeshBuilder {
  102. pub verts: Vec<Vertex>,
  103. pub indices: Vec<u16>,
  104. tag: DebugTag,
  105. }
  106. impl MeshBuilder {
  107. pub fn new(tag: DebugTag) -> Self {
  108. Self { verts: vec![], indices: vec![], tag }
  109. }
  110. pub fn append(&mut self, mut verts: Vec<Vertex>, indices: Vec<u16>) {
  111. let mut indices = indices.into_iter().map(|i| i + self.verts.len() as u16).collect();
  112. self.verts.append(&mut verts);
  113. self.indices.append(&mut indices);
  114. }
  115. pub fn draw_box(&mut self, obj: &Rectangle, color: Color, uv: &Rectangle) {
  116. let (x1, y1) = obj.pos().unpack();
  117. let (x2, y2) = obj.corner().unpack();
  118. let (u1, v1) = uv.pos().unpack();
  119. let (u2, v2) = uv.corner().unpack();
  120. let verts = vec![
  121. // top left
  122. Vertex { pos: [x1, y1], color, uv: [u1, v1] },
  123. // top right
  124. Vertex { pos: [x2, y1], color, uv: [u2, v1] },
  125. // bottom left
  126. Vertex { pos: [x1, y2], color, uv: [u1, v2] },
  127. // bottom right
  128. Vertex { pos: [x2, y2], color, uv: [u2, v2] },
  129. ];
  130. let indices = vec![0, 2, 1, 1, 2, 3];
  131. self.append(verts, indices);
  132. }
  133. pub fn draw_filled_box(&mut self, obj: &Rectangle, color: Color) {
  134. let uv = Rectangle::zero();
  135. self.draw_box(obj, color, &uv);
  136. }
  137. pub fn draw_box_shadow(&mut self, obj: &Rectangle, color: Color, spread: f32) {
  138. let (x1, y1) = obj.pos().unpack();
  139. let (x2, y2) = obj.corner().unpack();
  140. let uv = Rectangle::zero();
  141. let (u1, v1) = uv.pos().unpack();
  142. let (u2, v2) = uv.corner().unpack();
  143. let color2 = [color[0], color[1], color[2], 0.];
  144. // left
  145. self.append(
  146. vec![
  147. Vertex { pos: [x1, y1], color, uv: [u1, v1] },
  148. Vertex { pos: [x1 - spread, y1 - spread], color: color2, uv: [u2, v1] },
  149. Vertex { pos: [x1, y2], color, uv: [u1, v2] },
  150. Vertex { pos: [x1 - spread, y2 + spread], color: color2, uv: [u2, v2] },
  151. ],
  152. vec![0, 2, 1, 1, 2, 3],
  153. );
  154. // top
  155. self.append(
  156. vec![
  157. Vertex { pos: [x1, y1], color, uv: [u1, v1] },
  158. Vertex { pos: [x1 - spread, y1 - spread], color: color2, uv: [u2, v1] },
  159. Vertex { pos: [x2, y1], color, uv: [u1, v2] },
  160. Vertex { pos: [x2 + spread, y1 - spread], color: color2, uv: [u2, v2] },
  161. ],
  162. vec![0, 2, 1, 1, 2, 3],
  163. );
  164. // right
  165. self.append(
  166. vec![
  167. Vertex { pos: [x2, y1], color, uv: [u1, v1] },
  168. Vertex { pos: [x2 + spread, y1 - spread], color: color2, uv: [u2, v1] },
  169. Vertex { pos: [x2, y2], color, uv: [u1, v2] },
  170. Vertex { pos: [x2 + spread, y2 + spread], color: color2, uv: [u2, v2] },
  171. ],
  172. vec![0, 2, 1, 1, 2, 3],
  173. );
  174. // bottom
  175. self.append(
  176. vec![
  177. Vertex { pos: [x1, y2], color, uv: [u1, v1] },
  178. Vertex { pos: [x1 - spread, y2 + spread], color: color2, uv: [u2, v1] },
  179. Vertex { pos: [x2, y2], color, uv: [u1, v2] },
  180. Vertex { pos: [x2 + spread, y2 + spread], color: color2, uv: [u2, v2] },
  181. ],
  182. vec![0, 2, 1, 1, 2, 3],
  183. );
  184. }
  185. pub fn draw_outline(&mut self, obj: &Rectangle, color: Color, thickness: f32) {
  186. let (x1, y1) = obj.pos().unpack();
  187. let (dist_x, dist_y) = (obj.w, obj.h);
  188. let (x2, y2) = obj.corner().unpack();
  189. // top
  190. self.draw_filled_box(&Rectangle::new(x1, y1, dist_x, thickness), color);
  191. // left
  192. self.draw_filled_box(&Rectangle::new(x1, y1, thickness, dist_y), color);
  193. // right
  194. self.draw_filled_box(&Rectangle::new(x2 - thickness, y1, thickness, dist_y), color);
  195. // bottom
  196. self.draw_filled_box(&Rectangle::new(x1, y2 - thickness, dist_x, thickness), color);
  197. }
  198. pub fn draw_line(&mut self, start: Point, end: Point, color: Color, thickness: f32) {
  199. let mut dir = end - start;
  200. dir.normalize();
  201. let left = dir.perp_left() * (thickness / 2.);
  202. let right = dir.perp_right() * (thickness / 2.);
  203. let p1 = start + left;
  204. let p2 = end + left;
  205. let p3 = start + right;
  206. let p4 = end + right;
  207. let uv = [0., 0.];
  208. let verts = vec![
  209. // top left
  210. Vertex { pos: [p1.x, p1.y], color, uv },
  211. // top right
  212. Vertex { pos: [p2.x, p2.y], color, uv },
  213. // bottom left
  214. Vertex { pos: [p3.x, p3.y], color, uv },
  215. // bottom right
  216. Vertex { pos: [p4.x, p4.y], color, uv },
  217. ];
  218. let indices = vec![0, 2, 1, 1, 2, 3];
  219. self.append(verts, indices);
  220. }
  221. pub fn alloc<R: RenderApi>(self, renderer: &R) -> MeshInfo {
  222. //debug!(target: "mesh", "allocating {} verts:", self.verts.len());
  223. //for vert in &self.verts {
  224. // debug!(target: "mesh", " {:?}", vert);
  225. //}
  226. let num_elements = self.indices.len() as i32;
  227. let vertex_buffer = renderer.new_vertex_buffer(self.verts, self.tag);
  228. let index_buffer = renderer.new_index_buffer(self.indices, self.tag);
  229. MeshInfo { vertex_buffer, index_buffer, num_elements }
  230. }
  231. }