|
1 | | -// Copyright 2018 Tristam MacDonald |
| 1 | +// Copyright 2021 Tristam MacDonald |
2 | 2 | // |
3 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | 4 | // you may not use this file except in compliance with the License. |
|
13 | 13 | // limitations under the License. |
14 | 14 |
|
15 | 15 | //! Isosurface definitions for use in multiple examples |
| 16 | +use isosurface::{ |
| 17 | + distance::{Directed, Signed}, |
| 18 | + math::Vec3, |
| 19 | + source::{HermiteSource, ScalarSource, VectorSource}, |
| 20 | +}; |
16 | 21 |
|
17 | | -use isosurface::source::Source; |
| 22 | +pub trait AllSources: ScalarSource + VectorSource + HermiteSource {} |
18 | 23 |
|
19 | | -/// The distance-field equation for a torus |
20 | | -fn torus(x: f32, y: f32, z: f32) -> f32 { |
21 | | - const R1: f32 = 1.0 / 4.0; |
22 | | - const R2: f32 = 1.0 / 10.0; |
23 | | - let q_x = ((x * x + y * y).sqrt()).abs() - R1; |
24 | | - let len = (q_x * q_x + z * z).sqrt(); |
25 | | - len - R2 |
26 | | -} |
27 | | - |
28 | | -pub struct Torus {} |
29 | | - |
30 | | -impl Source for Torus { |
31 | | - fn sample(&self, x: f32, y: f32, z: f32) -> f32 { |
32 | | - torus(x - 0.5, y - 0.5, z - 0.5) |
33 | | - } |
34 | | -} |
| 24 | +impl<S: ScalarSource + VectorSource + HermiteSource> AllSources for S {} |
35 | 25 |
|
36 | | -fn abs(x: f32, y: f32, z: f32) -> (f32, f32, f32) { |
37 | | - ( |
38 | | - if x > 0.0 { x } else { -x }, |
39 | | - if y > 0.0 { y } else { -y }, |
40 | | - if z > 0.0 { z } else { -z }, |
41 | | - ) |
| 26 | +pub struct DemoSource<'a> { |
| 27 | + pub source: Box<dyn 'a + AllSources>, |
42 | 28 | } |
43 | 29 |
|
44 | | -fn max(px: f32, py: f32, pz: f32, qx: f32, qy: f32, qz: f32) -> (f32, f32, f32) { |
45 | | - ( |
46 | | - if px > qx { px } else { qx }, |
47 | | - if py > qy { py } else { qy }, |
48 | | - if pz > qz { pz } else { qz }, |
49 | | - ) |
50 | | -} |
51 | | - |
52 | | -/// The distance field equation for a cube |
53 | | -fn cube(px: f32, py: f32, pz: f32, bx: f32, by: f32, bz: f32) -> f32 { |
54 | | - let (ax, ay, az) = abs(px, py, pz); |
55 | | - let (dx, dy, dz) = (ax - bx, ay - by, az - bz); |
56 | | - let (mx, my, mz) = max(dx, dy, dz, 0.0, 0.0, 0.0); |
57 | | - let l = (mx * mx + my * my + mz * mz).sqrt(); |
58 | | - dx.max(dz.max(dy)).min(0.0) + l |
| 30 | +impl<'a> DemoSource<'a> { |
| 31 | + pub fn new<S: 'a + AllSources>(source: S) -> Self { |
| 32 | + Self { |
| 33 | + source: Box::new(source), |
| 34 | + } |
| 35 | + } |
59 | 36 | } |
60 | 37 |
|
61 | | -/// The distance field equation for a sphere |
62 | | -fn sphere(x: f32, y: f32, z: f32, r: f32) -> f32 { |
63 | | - (x * x + y * y + z * z).sqrt() - r |
| 38 | +impl<'a> ScalarSource for DemoSource<'a> { |
| 39 | + fn sample_scalar(&self, p: Vec3) -> Signed { |
| 40 | + let q = p - Vec3::from_scalar(0.5); |
| 41 | + self.source.sample_scalar(q) |
| 42 | + } |
64 | 43 | } |
65 | 44 |
|
66 | | -/// Subtract one distance field from another (i.e. CSG difference operation) |
67 | | -fn subtract(d1: f32, d2: f32) -> f32 { |
68 | | - d2.max(-d1) |
| 45 | +impl<'a> VectorSource for DemoSource<'a> { |
| 46 | + fn sample_vector(&self, p: Vec3) -> Directed { |
| 47 | + let q = p - Vec3::from_scalar(0.5); |
| 48 | + self.source.sample_vector(q) |
| 49 | + } |
69 | 50 | } |
70 | 51 |
|
71 | | -pub struct CubeSphere {} |
72 | | - |
73 | | -impl Source for CubeSphere { |
74 | | - fn sample(&self, x: f32, y: f32, z: f32) -> f32 { |
75 | | - subtract( |
76 | | - sphere(x - 0.5, y - 0.5, z - 0.5, 0.25), |
77 | | - cube(x - 0.5, y - 0.5, z - 0.5, 0.2, 0.2, 0.2), |
78 | | - ) |
| 52 | +impl<'a> HermiteSource for DemoSource<'a> { |
| 53 | + fn sample_normal(&self, p: Vec3) -> Vec3 { |
| 54 | + let q = p - Vec3::from_scalar(0.5); |
| 55 | + self.source.sample_normal(q) |
79 | 56 | } |
80 | 57 | } |
0 commit comments