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
use crate::Document;
use gltf_json::Extras;

/// A light in the scene.
pub struct Light<'a> {
    /// The parent `Document` struct.
    #[allow(dead_code)]
    document: &'a Document,

    /// The corresponding JSON index.
    index: usize,

    /// The corresponding JSON struct.
    json: &'a json::extensions::scene::khr_lights_punctual::Light,
}

impl<'a> Light<'a> {
    /// Constructs a `Light`.
    pub(crate) fn new(
        document: &'a Document,
        index: usize,
        json: &'a json::extensions::scene::khr_lights_punctual::Light,
    ) -> Self {
        Self {
            document,
            index,
            json,
        }
    }

    /// Color of the light source.
    pub fn color(&self) -> [f32; 3] {
        self.json.color
    }

    /// Returns the internal JSON index.
    pub fn index(&self) -> usize {
        self.index
    }

    /// Optional user-defined name for this object.
    #[cfg(feature = "names")]
    pub fn name(&self) -> Option<&'a str> {
        self.json.name.as_deref()
    }

    /// Optional application specific data.
    pub fn extras(&self) -> &'a Extras {
        &self.json.extras
    }

    /// Intensity of the light source. `point` and `spot` lights use luminous intensity
    /// in candela (lm/sr) while `directional` lights use illuminance in lux (lm/m^2).
    pub fn intensity(&self) -> f32 {
        self.json.intensity
    }

    /// A distance cutoff at which the light's intensity may be considered to have reached
    /// zero.
    pub fn range(&self) -> Option<f32> {
        self.json.range
    }

    /// Specifies the light subcategory.
    pub fn kind(&self) -> Kind {
        use json::extensions::scene::khr_lights_punctual::Type;
        match self.json.type_.unwrap() {
            Type::Directional => Kind::Directional,
            Type::Point => Kind::Point,
            Type::Spot => {
                let args = self.json.spot.as_ref().unwrap();
                Kind::Spot {
                    inner_cone_angle: args.inner_cone_angle,
                    outer_cone_angle: args.outer_cone_angle,
                }
            }
        }
    }
}

/// Light subcategory.
pub enum Kind {
    /// Directional lights are light sources that act as though they are infinitely far away
    /// and emit light in the direction of the local -z axis. This light type inherits the
    /// orientation of the node that it belongs to; position and scale are ignored except for
    /// their effect on the inherited node orientation. Because it is at an infinite distance,
    /// the light is not attenuated. Its intensity is defined in lumens per metre squared, or
    /// lux (lm/m2).
    Directional,

    /// Point lights emit light in all directions from their position in space; rotation and
    /// scale are ignored except for their effect on the inherited node position. The
    /// brightness of the light attenuates in a physically correct manner as distance
    /// increases from the light's position (i.e. brightness goes like the inverse square of
    /// the distance). Point light intensity is defined in candela, which is lumens per square
    /// radian (lm/sr).
    Point,

    /// Spot lights emit light in a cone in the direction of the local -z axis. The angle and
    /// falloff of the cone is defined using two numbers, the `inner_cone_angle` and
    /// `outer_cone_angle`. As with point lights, the brightness also attenuates in a
    /// physically correct manner as distance increases from the light's position (i.e.
    /// brightness goes like the inverse square of the distance). Spot light intensity refers
    /// to the brightness inside the `inner_cone_angle` (and at the location of the light) and
    /// is defined in candela, which is lumens per square radian (lm/sr). Engines that don't
    /// support two angles for spotlights should use `outer_cone_angle` as the spotlight angle
    /// (leaving `inner_cone_angle` to implicitly be 0).
    ///
    /// A spot light's position and orientation are inherited from its node transform.
    /// Inherited scale does not affect cone shape, and is ignored except for its effect on
    /// position and orientation.
    Spot {
        /// Angle in radians from centre of spotlight where falloff begins.
        inner_cone_angle: f32,

        /// Angle in radians from centre of spotlight where falloff ends.
        outer_cone_angle: f32,
    },
}