Team Ai
Apppublic

OpenMotionLab/MotionGPT

sourceHugging Facemitupdated 1y agoView on Hugging Face
118likes
light.py386 linesDownload Raw Back to pyrender
1"""Punctual light sources as defined by the glTF 2.0 KHR extension at2https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual3 4Author: Matthew Matl5"""6import abc7import numpy as np8import six9 10from OpenGL.GL import *11 12from .utils import format_color_vector13from .texture import Texture14from .constants import SHADOW_TEX_SZ15from .camera import OrthographicCamera, PerspectiveCamera16 17 18 19@six.add_metaclass(abc.ABCMeta)20class Light(object):21    """Base class for all light objects.22 23    Parameters24    ----------25    color : (3,) float26        RGB value for the light's color in linear space.27    intensity : float28        Brightness of light. The units that this is defined in depend on the29        type of light. Point and spot lights use luminous intensity in candela30        (lm/sr), while directional lights use illuminance in lux (lm/m2).31    name : str, optional32        Name of the light.33    """34    def __init__(self,35                 color=None,36                 intensity=None,37                 name=None):38 39        if color is None:40            color = np.ones(3)41        if intensity is None:42            intensity = 1.043 44        self.name = name45        self.color = color46        self.intensity = intensity47        self._shadow_camera = None48        self._shadow_texture = None49 50    @property51    def name(self):52        """str : The user-defined name of this object.53        """54        return self._name55 56    @name.setter57    def name(self, value):58        if value is not None:59            value = str(value)60        self._name = value61 62    @property63    def color(self):64        """(3,) float : The light's color.65        """66        return self._color67 68    @color.setter69    def color(self, value):70        self._color = format_color_vector(value, 3)71 72    @property73    def intensity(self):74        """float : The light's intensity in candela or lux.75        """76        return self._intensity77 78    @intensity.setter79    def intensity(self, value):80        self._intensity = float(value)81 82    @property83    def shadow_texture(self):84        """:class:`.Texture` : A texture used to hold shadow maps for this light.85        """86        return self._shadow_texture87 88    @shadow_texture.setter89    def shadow_texture(self, value):90        if self._shadow_texture is not None:91            if self._shadow_texture._in_context():92                self._shadow_texture.delete()93        self._shadow_texture = value94 95    @abc.abstractmethod96    def _generate_shadow_texture(self, size=None):97        """Generate a shadow texture for this light.98 99        Parameters100        ----------101        size : int, optional102            Size of texture map. Must be a positive power of two.103        """104        pass105 106    @abc.abstractmethod107    def _get_shadow_camera(self, scene_scale):108        """Generate and return a shadow mapping camera for this light.109 110        Parameters111        ----------112        scene_scale : float113            Length of scene's bounding box diagonal.114 115        Returns116        -------117        camera : :class:`.Camera`118            The camera used to render shadowmaps for this light.119        """120        pass121 122 123class DirectionalLight(Light):124    """Directional lights are light sources that act as though they are125    infinitely far away and emit light in the direction of the local -z axis.126    This light type inherits the orientation of the node that it belongs to;127    position and scale are ignored except for their effect on the inherited128    node orientation. Because it is at an infinite distance, the light is129    not attenuated. Its intensity is defined in lumens per metre squared,130    or lux (lm/m2).131 132    Parameters133    ----------134    color : (3,) float, optional135        RGB value for the light's color in linear space. Defaults to white136        (i.e. [1.0, 1.0, 1.0]).137    intensity : float, optional138        Brightness of light, in lux (lm/m^2). Defaults to 1.0139    name : str, optional140        Name of the light.141    """142 143    def __init__(self,144                 color=None,145                 intensity=None,146                 name=None):147        super(DirectionalLight, self).__init__(148            color=color,149            intensity=intensity,150            name=name,151        )152 153    def _generate_shadow_texture(self, size=None):154        """Generate a shadow texture for this light.155 156        Parameters157        ----------158        size : int, optional159            Size of texture map. Must be a positive power of two.160        """161        if size is None:162            size = SHADOW_TEX_SZ163        self.shadow_texture = Texture(width=size, height=size,164                                      source_channels='D', data_format=GL_FLOAT)165 166    def _get_shadow_camera(self, scene_scale):167        """Generate and return a shadow mapping camera for this light.168 169        Parameters170        ----------171        scene_scale : float172            Length of scene's bounding box diagonal.173 174        Returns175        -------176        camera : :class:`.Camera`177            The camera used to render shadowmaps for this light.178        """179        return OrthographicCamera(180            znear=0.01 * scene_scale,181            zfar=10 * scene_scale,182            xmag=scene_scale,183            ymag=scene_scale184        )185 186 187class PointLight(Light):188    """Point lights emit light in all directions from their position in space;189    rotation and scale are ignored except for their effect on the inherited190    node position. The brightness of the light attenuates in a physically191    correct manner as distance increases from the light's position (i.e.192    brightness goes like the inverse square of the distance). Point light193    intensity is defined in candela, which is lumens per square radian (lm/sr).194 195    Parameters196    ----------197    color : (3,) float198        RGB value for the light's color in linear space.199    intensity : float200        Brightness of light in candela (lm/sr).201    range : float202        Cutoff distance at which light's intensity may be considered to203        have reached zero. If None, the range is assumed to be infinite.204    name : str, optional205        Name of the light.206    """207 208    def __init__(self,209                 color=None,210                 intensity=None,211                 range=None,212                 name=None):213        super(PointLight, self).__init__(214            color=color,215            intensity=intensity,216            name=name,217        )218        self.range = range219 220    @property221    def range(self):222        """float : The cutoff distance for the light.223        """224        return self._range225 226    @range.setter227    def range(self, value):228        if value is not None:229            value = float(value)230            if value <= 0:231                raise ValueError('Range must be > 0')232            self._range = value233        self._range = value234 235    def _generate_shadow_texture(self, size=None):236        """Generate a shadow texture for this light.237 238        Parameters239        ----------240        size : int, optional241            Size of texture map. Must be a positive power of two.242        """243        raise NotImplementedError('Shadows not implemented for point lights')244 245    def _get_shadow_camera(self, scene_scale):246        """Generate and return a shadow mapping camera for this light.247 248        Parameters249        ----------250        scene_scale : float251            Length of scene's bounding box diagonal.252 253        Returns254        -------255        camera : :class:`.Camera`256            The camera used to render shadowmaps for this light.257        """258        raise NotImplementedError('Shadows not implemented for point lights')259 260 261class SpotLight(Light):262    """Spot lights emit light in a cone in the direction of the local -z axis.263    The angle and falloff of the cone is defined using two numbers, the264    ``innerConeAngle`` and ``outerConeAngle``.265    As with point lights, the brightness266    also attenuates in a physically correct manner as distance increases from267    the light's position (i.e. brightness goes like the inverse square of the268    distance). Spot light intensity refers to the brightness inside the269    ``innerConeAngle`` (and at the location of the light) and is defined in270    candela, which is lumens per square radian (lm/sr). A spot light's position271    and orientation are inherited from its node transform. Inherited scale does272    not affect cone shape, and is ignored except for its effect on position273    and orientation.274 275    Parameters276    ----------277    color : (3,) float278        RGB value for the light's color in linear space.279    intensity : float280        Brightness of light in candela (lm/sr).281    range : float282        Cutoff distance at which light's intensity may be considered to283        have reached zero. If None, the range is assumed to be infinite.284    innerConeAngle : float285        Angle, in radians, from centre of spotlight where falloff begins.286        Must be greater than or equal to ``0`` and less287        than ``outerConeAngle``. Defaults to ``0``.288    outerConeAngle : float289        Angle, in radians, from centre of spotlight where falloff ends.290        Must be greater than ``innerConeAngle`` and less than or equal to291        ``PI / 2.0``. Defaults to ``PI / 4.0``.292    name : str, optional293        Name of the light.294    """295 296    def __init__(self,297                 color=None,298                 intensity=None,299                 range=None,300                 innerConeAngle=0.0,301                 outerConeAngle=(np.pi / 4.0),302                 name=None):303        super(SpotLight, self).__init__(304            name=name,305            color=color,306            intensity=intensity,307        )308        self.outerConeAngle = outerConeAngle309        self.innerConeAngle = innerConeAngle310        self.range = range311 312    @property313    def innerConeAngle(self):314        """float : The inner cone angle in radians.315        """316        return self._innerConeAngle317 318    @innerConeAngle.setter319    def innerConeAngle(self, value):320        if value < 0.0 or value > self.outerConeAngle:321            raise ValueError('Invalid value for inner cone angle')322        self._innerConeAngle = float(value)323 324    @property325    def outerConeAngle(self):326        """float : The outer cone angle in radians.327        """328        return self._outerConeAngle329 330    @outerConeAngle.setter331    def outerConeAngle(self, value):332        if value < 0.0 or value > np.pi / 2.0 + 1e-9:333            raise ValueError('Invalid value for outer cone angle')334        self._outerConeAngle = float(value)335 336    @property337    def range(self):338        """float : The cutoff distance for the light.339        """340        return self._range341 342    @range.setter343    def range(self, value):344        if value is not None:345            value = float(value)346            if value <= 0:347                raise ValueError('Range must be > 0')348            self._range = value349        self._range = value350 351    def _generate_shadow_texture(self, size=None):352        """Generate a shadow texture for this light.353 354        Parameters355        ----------356        size : int, optional357            Size of texture map. Must be a positive power of two.358        """359        if size is None:360            size = SHADOW_TEX_SZ361        self.shadow_texture = Texture(width=size, height=size,362                                      source_channels='D', data_format=GL_FLOAT)363 364    def _get_shadow_camera(self, scene_scale):365        """Generate and return a shadow mapping camera for this light.366 367        Parameters368        ----------369        scene_scale : float370            Length of scene's bounding box diagonal.371 372        Returns373        -------374        camera : :class:`.Camera`375            The camera used to render shadowmaps for this light.376        """377        return PerspectiveCamera(378            znear=0.01 * scene_scale,379            zfar=10 * scene_scale,380            yfov=np.clip(2 * self.outerConeAngle + np.pi / 16.0, 0.0, np.pi),381            aspectRatio=1.0382        )383 384 385__all__ = ['Light', 'DirectionalLight', 'SpotLight', 'PointLight']386