compas-threejs 1.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- compas_threejs/__init__.py +8 -0
- compas_threejs/lights/__init__.py +15 -0
- compas_threejs/lights/ambientlight.py +19 -0
- compas_threejs/lights/light.py +11 -0
- compas_threejs/lights/pointlight.py +76 -0
- compas_threejs/lights/rectlight.py +73 -0
- compas_threejs/lights/sky.py +57 -0
- compas_threejs/lights/spotlight.py +143 -0
- compas_threejs/lights/sunlight.py +72 -0
- compas_threejs/materials/__init__.py +6 -0
- compas_threejs/materials/generic_material.py +11 -0
- compas_threejs/materials/line_material.py +30 -0
- compas_threejs/materials/material.py +161 -0
- compas_threejs/materials/physical_material.py +377 -0
- compas_threejs/materials/point_material.py +34 -0
- compas_threejs/metadata/__init__.py +4 -0
- compas_threejs/metadata/metadata.py +22 -0
- compas_threejs/tag/__init__.py +3 -0
- compas_threejs/tag/tag.py +51 -0
- compas_threejs/text/__init__.py +3 -0
- compas_threejs/text/text_geometry.py +72 -0
- compas_threejs/ui/__init__.py +8 -0
- compas_threejs/ui/button.py +27 -0
- compas_threejs/ui/checkbox.py +36 -0
- compas_threejs/ui/load_json_button.py +27 -0
- compas_threejs/ui/number_field.py +56 -0
- compas_threejs/ui/select_menu.py +33 -0
- compas_threejs/ui/slider.py +37 -0
- compas_threejs/ui/ui_element.py +11 -0
- compas_threejs/viewer/__init__.py +5 -0
- compas_threejs/viewer/app.py +454 -0
- compas_threejs/viewer/frontend/assets/compas_icon_white.png +0 -0
- compas_threejs/viewer/frontend/assets/index.css +2 -0
- compas_threejs/viewer/frontend/assets/index.js +4170 -0
- compas_threejs/viewer/frontend/index.html +25 -0
- compas_threejs/viewer/inbox.py +153 -0
- compas_threejs/viewer/outbox.py +79 -0
- compas_threejs/viewer/remote.py +279 -0
- compas_threejs/viewer/server.py +158 -0
- compas_threejs/viewer/workspace.py +566 -0
- compas_threejs-1.0.1.dist-info/METADATA +89 -0
- compas_threejs-1.0.1.dist-info/RECORD +45 -0
- compas_threejs-1.0.1.dist-info/WHEEL +5 -0
- compas_threejs-1.0.1.dist-info/licenses/LICENSE +21 -0
- compas_threejs-1.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""COMPAS ThreeJS - A lightweight Three.js viewer for COMPAS using Protobuf."""
|
|
2
|
+
|
|
3
|
+
__version__ = "1.0.1"
|
|
4
|
+
__author__ = "Eric Gozzi, Nicolas Benjamin Boscoboinik"
|
|
5
|
+
__email__ = "eric.gozzi@arch.ethz.ch"
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
|
|
8
|
+
__all__ = ["__version__", "__author__", "__email__", "__license__"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .ambientlight import AmbientLight
|
|
2
|
+
from .pointlight import PointLight
|
|
3
|
+
from .rectlight import RectLight
|
|
4
|
+
from .sky import Sky
|
|
5
|
+
from .spotlight import SpotLight
|
|
6
|
+
from .sunlight import Sunlight
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"PointLight",
|
|
10
|
+
"SpotLight",
|
|
11
|
+
"RectLight",
|
|
12
|
+
"Sunlight",
|
|
13
|
+
"Sky",
|
|
14
|
+
"AmbientLight",
|
|
15
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from compas.colors import Color
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AmbientLight:
|
|
7
|
+
def __init__(self, color: Color = Color.white(), intensity: float = 500):
|
|
8
|
+
self.color = color
|
|
9
|
+
self.intensity = intensity
|
|
10
|
+
self.guid = str(uuid.uuid4())
|
|
11
|
+
|
|
12
|
+
def as_dict(self) -> dict:
|
|
13
|
+
return {
|
|
14
|
+
"dispatch": "light",
|
|
15
|
+
"type": "ambient_light",
|
|
16
|
+
"guid": self.guid,
|
|
17
|
+
"color": self.color.hex,
|
|
18
|
+
"intensity": self.intensity,
|
|
19
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from uuid import uuid4
|
|
2
|
+
|
|
3
|
+
from compas.colors import Color
|
|
4
|
+
from compas.geometry import Point
|
|
5
|
+
|
|
6
|
+
from .light import Light
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PointLight(Light):
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
Constructs a new PointLight instance.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
color : int | Color | str, optional
|
|
17
|
+
The color of the light. Can be specified as an integer, a Color object, or a string.
|
|
18
|
+
Default is 0xffffff (white).
|
|
19
|
+
|
|
20
|
+
intensity : float, optional
|
|
21
|
+
The intensity or strength of the light, measured in candela (cd).
|
|
22
|
+
Default is 1.
|
|
23
|
+
|
|
24
|
+
distance : float, optional
|
|
25
|
+
The maximum range of the light. A value of 0 indicates no limit.
|
|
26
|
+
Default is 0.
|
|
27
|
+
|
|
28
|
+
decay : float, optional
|
|
29
|
+
The rate at which the light diminishes over distance.
|
|
30
|
+
Default is 2.
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
point: Point = Point(0, 0, 0),
|
|
37
|
+
color: Color = Color.white(),
|
|
38
|
+
intensity: float = 100,
|
|
39
|
+
distance: float = 0,
|
|
40
|
+
decay: float = 2,
|
|
41
|
+
helper: bool = False,
|
|
42
|
+
**kwargs,
|
|
43
|
+
):
|
|
44
|
+
super().__init__(**kwargs)
|
|
45
|
+
self.point = point
|
|
46
|
+
self.color = color
|
|
47
|
+
self.intensity = intensity
|
|
48
|
+
self.distance = distance
|
|
49
|
+
self.decay = decay
|
|
50
|
+
self.helper = helper
|
|
51
|
+
self.guid = str(uuid4())
|
|
52
|
+
|
|
53
|
+
def as_dict(self) -> dict:
|
|
54
|
+
return {
|
|
55
|
+
"dispatch": "light",
|
|
56
|
+
"type": "point_light",
|
|
57
|
+
"x": self.point.x,
|
|
58
|
+
"y": self.point.y,
|
|
59
|
+
"z": self.point.z,
|
|
60
|
+
"color": self.color.hex,
|
|
61
|
+
"intensity": self.intensity,
|
|
62
|
+
"distance": self.distance,
|
|
63
|
+
"decay": self.decay,
|
|
64
|
+
"helper": self.helper,
|
|
65
|
+
"guid": self.guid,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def color(self) -> Color:
|
|
70
|
+
return self._color
|
|
71
|
+
|
|
72
|
+
@color.setter
|
|
73
|
+
def color(self, value: Color):
|
|
74
|
+
if not isinstance(value, Color):
|
|
75
|
+
raise TypeError("color must be an instance of Color")
|
|
76
|
+
self._color = value
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from compas.colors import Color
|
|
4
|
+
from compas.geometry import Point
|
|
5
|
+
|
|
6
|
+
from .light import Light
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class RectLight(Light):
|
|
10
|
+
"""
|
|
11
|
+
A rectangular light source.
|
|
12
|
+
|
|
13
|
+
The `RectLight` class represents a light source with a rectangular shape,
|
|
14
|
+
defined by its position, target direction, color, intensity, width, and height.
|
|
15
|
+
|
|
16
|
+
Attributes
|
|
17
|
+
----------
|
|
18
|
+
point : :class:`compas.geometry.Point`
|
|
19
|
+
The position of the light source in 3D space. Defaults to the origin (0, 0, 0).
|
|
20
|
+
target : :class:`compas.geometry.Point`
|
|
21
|
+
The target point that the light is directed towards. Defaults to (0, -1, 0).
|
|
22
|
+
color : :class:`compas.colors.Color`
|
|
23
|
+
The color of the light. Defaults to white.
|
|
24
|
+
intensity : float
|
|
25
|
+
The intensity of the light. Defaults to 1.
|
|
26
|
+
width : float
|
|
27
|
+
The width of the rectangular light source. Defaults to 10.
|
|
28
|
+
height : float
|
|
29
|
+
The height of the rectangular light source. Defaults to 10.
|
|
30
|
+
helper : bool
|
|
31
|
+
Whether to display a helper visualization for the light. Defaults to False.
|
|
32
|
+
guid : str
|
|
33
|
+
A unique identifier for the light instance, automatically generated.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
point: Point = Point(0, 0, 0),
|
|
39
|
+
target: Point = Point(0, -1, 0),
|
|
40
|
+
color: Color = Color.white(),
|
|
41
|
+
intensity: float = 1,
|
|
42
|
+
width: float = 10,
|
|
43
|
+
height: float = 10,
|
|
44
|
+
helper: bool = False,
|
|
45
|
+
**kwargs,
|
|
46
|
+
):
|
|
47
|
+
super().__init__(**kwargs)
|
|
48
|
+
self.point = point
|
|
49
|
+
self.target = target
|
|
50
|
+
self.color = color
|
|
51
|
+
self.intensity = intensity
|
|
52
|
+
self.width = width
|
|
53
|
+
self.height = height
|
|
54
|
+
self.helper = helper
|
|
55
|
+
self.guid = str(uuid.uuid4())
|
|
56
|
+
|
|
57
|
+
def as_dict(self) -> dict:
|
|
58
|
+
return {
|
|
59
|
+
"dispatch": "light",
|
|
60
|
+
"type": "rect_light",
|
|
61
|
+
"x": self.point.x,
|
|
62
|
+
"y": self.point.y,
|
|
63
|
+
"z": self.point.z,
|
|
64
|
+
"tx": self.target.x,
|
|
65
|
+
"ty": self.target.y,
|
|
66
|
+
"tz": self.target.z,
|
|
67
|
+
"color": self.color.hex,
|
|
68
|
+
"intensity": self.intensity,
|
|
69
|
+
"width": self.width,
|
|
70
|
+
"height": self.height,
|
|
71
|
+
"helper": self.helper,
|
|
72
|
+
"guid": self.guid,
|
|
73
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from .light import Light
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Sky(Light):
|
|
7
|
+
"""
|
|
8
|
+
The Sky class represents a type of light source that simulates the sky's appearance
|
|
9
|
+
based on various atmospheric parameters.
|
|
10
|
+
|
|
11
|
+
Attributes:
|
|
12
|
+
turbidity (float): The amount of particles in the atmosphere that scatter light.
|
|
13
|
+
Higher values result in a hazier sky. Default is 5.
|
|
14
|
+
rayleigh (float): The scattering coefficient for Rayleigh scattering, which affects
|
|
15
|
+
the sky's blue color intensity. Default is 0.15.
|
|
16
|
+
mie_coefficient (float): The scattering coefficient for Mie scattering, which affects
|
|
17
|
+
the appearance of haze and fog. Default is 0.002.
|
|
18
|
+
mie_directional_g (float): The anisotropy factor for Mie scattering, controlling the
|
|
19
|
+
directionality of scattered light. Default is 0.95.
|
|
20
|
+
azimuth (float): The horizontal angle of the sun in degrees, measured clockwise from
|
|
21
|
+
the north. Default is 45.
|
|
22
|
+
elevation (float): The vertical angle of the sun in degrees, measured from the horizon.
|
|
23
|
+
Default is 20.
|
|
24
|
+
guid (str): A unique identifier for the Sky instance, generated automatically.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
turbidity: float = 5,
|
|
30
|
+
rayleigh: float = 0.15,
|
|
31
|
+
mie_coefficient: float = 0.002,
|
|
32
|
+
mie_directional_g: float = 0.95,
|
|
33
|
+
azimuth: float = 45,
|
|
34
|
+
elevation: float = 20,
|
|
35
|
+
**kwargs,
|
|
36
|
+
):
|
|
37
|
+
super().__init__(**kwargs)
|
|
38
|
+
self.turbidity = turbidity
|
|
39
|
+
self.rayleigh = rayleigh
|
|
40
|
+
self.mie_coefficient = mie_coefficient
|
|
41
|
+
self.mie_directional_g = mie_directional_g
|
|
42
|
+
self.azimuth = azimuth
|
|
43
|
+
self.elevation = elevation
|
|
44
|
+
self.guid = str(uuid.uuid4())
|
|
45
|
+
|
|
46
|
+
def as_dict(self) -> dict:
|
|
47
|
+
return {
|
|
48
|
+
"dispatch": "light",
|
|
49
|
+
"type": "sky",
|
|
50
|
+
"turbidity": self.turbidity,
|
|
51
|
+
"rayleigh": self.rayleigh,
|
|
52
|
+
"mie_coefficient": self.mie_coefficient,
|
|
53
|
+
"mie_directional_g": self.mie_directional_g,
|
|
54
|
+
"azimuth": self.azimuth,
|
|
55
|
+
"elevation": self.elevation,
|
|
56
|
+
"guid": self.guid,
|
|
57
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import uuid
|
|
3
|
+
|
|
4
|
+
from compas.colors import Color
|
|
5
|
+
from compas.geometry import Point
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SpotLight:
|
|
9
|
+
"""
|
|
10
|
+
A class representing a spotlight in a 3D environment.
|
|
11
|
+
|
|
12
|
+
The SpotLight class defines a light source that emits light in a specific direction
|
|
13
|
+
with a conical shape. It includes properties for position, target, color, intensity,
|
|
14
|
+
distance, angle, penumbra, and decay, among others.
|
|
15
|
+
|
|
16
|
+
Attributes
|
|
17
|
+
----------
|
|
18
|
+
point: Point
|
|
19
|
+
The position of the spotlight in 3D space.
|
|
20
|
+
target: Point
|
|
21
|
+
The target point that the spotlight is directed towards.
|
|
22
|
+
color: Color
|
|
23
|
+
The color of the light emitted by the spotlight.
|
|
24
|
+
intensity: float
|
|
25
|
+
The brightness of the light. Must be non-negative.
|
|
26
|
+
distance: float
|
|
27
|
+
The maximum range of the light. Must be non-negative.
|
|
28
|
+
angle: float
|
|
29
|
+
The angle of the spotlight's cone in radians. Must be between 0 and π/2.
|
|
30
|
+
penumbra: float
|
|
31
|
+
The softness of the spotlight's edge. Must be between 0 and 1.
|
|
32
|
+
decay: float
|
|
33
|
+
The rate at which the light intensity decreases over distance. Must be non-negative.
|
|
34
|
+
helper: bool
|
|
35
|
+
Whether to display a helper visualization for the spotlight.
|
|
36
|
+
guid: str
|
|
37
|
+
A unique identifier for the spotlight instance.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
point: Point = Point(0, 0, 0),
|
|
43
|
+
target: Point = Point(0, 0, -1),
|
|
44
|
+
color: Color = Color.white(),
|
|
45
|
+
intensity: float = 100,
|
|
46
|
+
distance: float = 0,
|
|
47
|
+
angle: float = math.pi / 7,
|
|
48
|
+
penumbra: float = 0,
|
|
49
|
+
decay: float = 1,
|
|
50
|
+
helper: bool = False,
|
|
51
|
+
**kwargs,
|
|
52
|
+
):
|
|
53
|
+
super().__init__(**kwargs)
|
|
54
|
+
self.point = point
|
|
55
|
+
self.target = target
|
|
56
|
+
self.color = color
|
|
57
|
+
self.intensity = intensity
|
|
58
|
+
self.distance = distance
|
|
59
|
+
self.angle = angle
|
|
60
|
+
self.penumbra = penumbra
|
|
61
|
+
self.decay = decay
|
|
62
|
+
self.helper = helper
|
|
63
|
+
self.guid = str(uuid.uuid4())
|
|
64
|
+
|
|
65
|
+
def as_dict(self) -> dict:
|
|
66
|
+
return {
|
|
67
|
+
"dispatch": "light",
|
|
68
|
+
"type": "spot_light",
|
|
69
|
+
"x": self.point.x,
|
|
70
|
+
"y": self.point.y,
|
|
71
|
+
"z": self.point.z,
|
|
72
|
+
"tx": self.target.x,
|
|
73
|
+
"ty": self.target.y,
|
|
74
|
+
"tz": self.target.z,
|
|
75
|
+
"color": self.color.hex,
|
|
76
|
+
"intensity": self.intensity,
|
|
77
|
+
"distance": self.distance,
|
|
78
|
+
"angle": self.angle,
|
|
79
|
+
"penumbra": self.penumbra,
|
|
80
|
+
"decay": self.decay,
|
|
81
|
+
"helper": self.helper,
|
|
82
|
+
"guid": self.guid,
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def color(self) -> Color:
|
|
87
|
+
return self._color
|
|
88
|
+
|
|
89
|
+
@color.setter
|
|
90
|
+
def color(self, value: Color):
|
|
91
|
+
if not isinstance(value, Color):
|
|
92
|
+
raise TypeError("color must be an instance of Color")
|
|
93
|
+
self._color = value
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def intensity(self) -> float:
|
|
97
|
+
return self._intensity
|
|
98
|
+
|
|
99
|
+
@intensity.setter
|
|
100
|
+
def intensity(self, value: float):
|
|
101
|
+
if value < 0:
|
|
102
|
+
raise ValueError("Intensity must be non-negative.")
|
|
103
|
+
self._intensity = value
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def distance(self) -> float:
|
|
107
|
+
return self._distance
|
|
108
|
+
|
|
109
|
+
@distance.setter
|
|
110
|
+
def distance(self, value: float):
|
|
111
|
+
if value < 0:
|
|
112
|
+
raise ValueError("Distance must be non-negative.")
|
|
113
|
+
self._distance = value
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def angle(self) -> float:
|
|
117
|
+
return self._angle
|
|
118
|
+
|
|
119
|
+
@angle.setter
|
|
120
|
+
def angle(self, value: float):
|
|
121
|
+
if not (0 < value <= math.pi / 2):
|
|
122
|
+
raise ValueError("Angle must be between 0 and π/2 radians.")
|
|
123
|
+
self._angle = value
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def penumbra(self) -> float:
|
|
127
|
+
return self._penumbra
|
|
128
|
+
|
|
129
|
+
@penumbra.setter
|
|
130
|
+
def penumbra(self, value: float):
|
|
131
|
+
if not (0 <= value <= 1):
|
|
132
|
+
raise ValueError("Penumbra must be between 0 and 1.")
|
|
133
|
+
self._penumbra = value
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def decay(self) -> float:
|
|
137
|
+
return self._decay
|
|
138
|
+
|
|
139
|
+
@decay.setter
|
|
140
|
+
def decay(self, value: float):
|
|
141
|
+
if value < 0:
|
|
142
|
+
raise ValueError("Decay must be non-negative.")
|
|
143
|
+
self._decay = value
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from compas.colors import Color
|
|
4
|
+
from compas.geometry import Point
|
|
5
|
+
from compas.geometry import Vector
|
|
6
|
+
|
|
7
|
+
from .light import Light
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Sunlight(Light):
|
|
11
|
+
"""
|
|
12
|
+
A class representing sunlight in a 3D scene.
|
|
13
|
+
|
|
14
|
+
The Sunlight class is a type of light source that simulates sunlight. It is defined
|
|
15
|
+
by its color, position, direction, intensity, and an optional helper for visualization.
|
|
16
|
+
|
|
17
|
+
Attributes
|
|
18
|
+
----------
|
|
19
|
+
color : :class:`compas.colors.Color`
|
|
20
|
+
The color of the sunlight. Defaults to white.
|
|
21
|
+
point : :class:`compas.geometry.Point`
|
|
22
|
+
The position of the sunlight source in 3D space. Defaults to the origin (0, 0, 0).
|
|
23
|
+
direction : :class:`compas.geometry.Vector`
|
|
24
|
+
The direction vector of the sunlight. Defaults to (-1, -1, -1).
|
|
25
|
+
intensity : float
|
|
26
|
+
The intensity of the sunlight. Defaults to 500.
|
|
27
|
+
helper : bool
|
|
28
|
+
A flag indicating whether a helper visualization is enabled. Defaults to False.
|
|
29
|
+
guid : str
|
|
30
|
+
A unique identifier for the sunlight instance, automatically generated.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
color: Color = Color.white(),
|
|
36
|
+
point: Point = Point(0, 0, 0),
|
|
37
|
+
direction: Vector = Vector(-1, -1, -1),
|
|
38
|
+
intensity: float = 500,
|
|
39
|
+
helper: bool = False,
|
|
40
|
+
**kwargs,
|
|
41
|
+
):
|
|
42
|
+
super().__init__(**kwargs)
|
|
43
|
+
self.color = color
|
|
44
|
+
self.point = point
|
|
45
|
+
self.direction = direction
|
|
46
|
+
self.intensity = intensity
|
|
47
|
+
self.helper = helper
|
|
48
|
+
self.guid = str(uuid.uuid4())
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def target(self) -> Point:
|
|
52
|
+
return Point(
|
|
53
|
+
self.point.x + self.direction.x,
|
|
54
|
+
self.point.y + self.direction.y,
|
|
55
|
+
self.point.z + self.direction.z,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def as_dict(self) -> dict:
|
|
59
|
+
return {
|
|
60
|
+
"dispatch": "light",
|
|
61
|
+
"type": "sunlight",
|
|
62
|
+
"color": self.color.hex,
|
|
63
|
+
"x": self.point.x,
|
|
64
|
+
"y": self.point.y,
|
|
65
|
+
"z": self.point.z,
|
|
66
|
+
"tx": self.target.x,
|
|
67
|
+
"ty": self.target.y,
|
|
68
|
+
"tz": self.target.z,
|
|
69
|
+
"intensity": self.intensity,
|
|
70
|
+
"helper": self.helper,
|
|
71
|
+
"guid": self.guid,
|
|
72
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from uuid import uuid4
|
|
2
|
+
|
|
3
|
+
from compas.colors import Color
|
|
4
|
+
|
|
5
|
+
from .generic_material import GenericMaterial
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class LineMaterial(GenericMaterial):
|
|
9
|
+
"""
|
|
10
|
+
Represents the material properties for rendering lines in a 3D scene.
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
color : Color, optional
|
|
15
|
+
The color of the line. Default is blue.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, color: Color = Color.blue(), linewidth: int = 2):
|
|
19
|
+
self.color = color
|
|
20
|
+
self._geometry_guid = ""
|
|
21
|
+
self.guid = str(uuid4())
|
|
22
|
+
|
|
23
|
+
def as_dict(self) -> dict:
|
|
24
|
+
return {
|
|
25
|
+
"dispatch": "material",
|
|
26
|
+
"type": "line_material",
|
|
27
|
+
"geometry_guid": self._geometry_guid,
|
|
28
|
+
"color": self.color.hex,
|
|
29
|
+
"guid": self.guid,
|
|
30
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from uuid import uuid4
|
|
2
|
+
|
|
3
|
+
from compas.colors import Color
|
|
4
|
+
|
|
5
|
+
from .generic_material import GenericMaterial
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Material(GenericMaterial):
|
|
9
|
+
"""
|
|
10
|
+
Represents the standard material properties for a 3D object.
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
color : Color, optional
|
|
15
|
+
The base color of the material. Default is white.
|
|
16
|
+
metalness : float, optional
|
|
17
|
+
The metalness of the material, between 0 and 1. Default is 0 (non-metallic).
|
|
18
|
+
roughness : float, optional
|
|
19
|
+
The roughness of the material, between 0 and 1. Default is 1 (fully rough).
|
|
20
|
+
emissive : Color, optional
|
|
21
|
+
The emissive color of the material. Default is black (no emission).
|
|
22
|
+
emissive_intensity : float, optional
|
|
23
|
+
The intensity of the emissive color. Default is 0 (no emission).
|
|
24
|
+
flat_shading : bool, optional
|
|
25
|
+
Whether to use flat shading. Default is False (smooth shading).
|
|
26
|
+
wireframe : bool, optional
|
|
27
|
+
Whether to render the material as a wireframe. Default is False (solid rendering).
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
color: Color = Color.white(),
|
|
33
|
+
metalness: float = 0,
|
|
34
|
+
roughness: float = 1,
|
|
35
|
+
emissive: Color = Color.black(),
|
|
36
|
+
emissive_intensity: float = 0,
|
|
37
|
+
flat_shading: bool = False,
|
|
38
|
+
wireframe: bool = False,
|
|
39
|
+
transparent: bool = False,
|
|
40
|
+
opacity: float = 1,
|
|
41
|
+
**kwargs,
|
|
42
|
+
):
|
|
43
|
+
super().__init__(**kwargs)
|
|
44
|
+
self.color = color
|
|
45
|
+
self.metalness = metalness
|
|
46
|
+
self.roughness = roughness
|
|
47
|
+
self.emissive = emissive
|
|
48
|
+
self.emissive_intensity = emissive_intensity
|
|
49
|
+
self.flat_shading = flat_shading
|
|
50
|
+
self.wireframe = wireframe
|
|
51
|
+
self._geometry_guid = ""
|
|
52
|
+
self.transparent = transparent
|
|
53
|
+
self.opacity = opacity
|
|
54
|
+
self.guid = str(uuid4())
|
|
55
|
+
|
|
56
|
+
def as_dict(self) -> dict:
|
|
57
|
+
return {
|
|
58
|
+
"dispatch": "material",
|
|
59
|
+
"type": "standard_material",
|
|
60
|
+
"geometry_guid": self._geometry_guid,
|
|
61
|
+
"color": self.color.hex,
|
|
62
|
+
"metalness": self.metalness,
|
|
63
|
+
"roughness": self.roughness,
|
|
64
|
+
"emissive": self.emissive.hex,
|
|
65
|
+
"emissive_intensity": self.emissive_intensity,
|
|
66
|
+
"flat_shading": self.flat_shading,
|
|
67
|
+
"wireframe": self.wireframe,
|
|
68
|
+
"transparent": self.transparent,
|
|
69
|
+
"opacity": self.opacity,
|
|
70
|
+
"guid": self.guid,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def color(self) -> Color:
|
|
75
|
+
return self._color
|
|
76
|
+
|
|
77
|
+
@color.setter
|
|
78
|
+
def color(self, value: Color):
|
|
79
|
+
if not isinstance(value, Color):
|
|
80
|
+
raise TypeError("color must be an instance of Color")
|
|
81
|
+
self._color = value
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def emissive(self) -> Color:
|
|
85
|
+
return self._emissive
|
|
86
|
+
|
|
87
|
+
@emissive.setter
|
|
88
|
+
def emissive(self, value: Color):
|
|
89
|
+
if not isinstance(value, Color):
|
|
90
|
+
raise TypeError("emissive must be an instance of Color")
|
|
91
|
+
self._emissive = value
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def metalness(self) -> float:
|
|
95
|
+
return self._metalness
|
|
96
|
+
|
|
97
|
+
@metalness.setter
|
|
98
|
+
def metalness(self, value: float):
|
|
99
|
+
if not (0 <= value <= 1):
|
|
100
|
+
raise ValueError("metalness must be between 0 and 1")
|
|
101
|
+
self._metalness = value
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def roughness(self) -> float:
|
|
105
|
+
return self._roughness
|
|
106
|
+
|
|
107
|
+
@roughness.setter
|
|
108
|
+
def roughness(self, value: float):
|
|
109
|
+
if not (0 <= value <= 1):
|
|
110
|
+
raise ValueError("roughness must be between 0 and 1")
|
|
111
|
+
self._roughness = value
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def emissive_intensity(self) -> float:
|
|
115
|
+
return self._emissive_intensity
|
|
116
|
+
|
|
117
|
+
@emissive_intensity.setter
|
|
118
|
+
def emissive_intensity(self, value: float):
|
|
119
|
+
if value < 0:
|
|
120
|
+
raise ValueError("emissive_intensity must be non-negative")
|
|
121
|
+
self._emissive_intensity = value
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def flat_shading(self) -> bool:
|
|
125
|
+
return self._flat_shading
|
|
126
|
+
|
|
127
|
+
@flat_shading.setter
|
|
128
|
+
def flat_shading(self, value: bool):
|
|
129
|
+
if not isinstance(value, bool):
|
|
130
|
+
raise TypeError("flat_shading must be a boolean")
|
|
131
|
+
self._flat_shading = value
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def wireframe(self) -> bool:
|
|
135
|
+
return self._wireframe
|
|
136
|
+
|
|
137
|
+
@wireframe.setter
|
|
138
|
+
def wireframe(self, value: bool):
|
|
139
|
+
if not isinstance(value, bool):
|
|
140
|
+
raise TypeError("wireframe must be a boolean")
|
|
141
|
+
self._wireframe = value
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def transparent(self) -> bool:
|
|
145
|
+
return self._transparent
|
|
146
|
+
|
|
147
|
+
@transparent.setter
|
|
148
|
+
def transparent(self, value: bool):
|
|
149
|
+
if not isinstance(value, bool):
|
|
150
|
+
raise TypeError("transparent must be a boolean")
|
|
151
|
+
self._transparent = value
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def opacity(self) -> float:
|
|
155
|
+
return self._opacity
|
|
156
|
+
|
|
157
|
+
@opacity.setter
|
|
158
|
+
def opacity(self, value: float):
|
|
159
|
+
if not (0 <= value <= 1):
|
|
160
|
+
raise ValueError("opacity must be between 0 and 1")
|
|
161
|
+
self._opacity = value
|