Skip to content

Commit 3dd8a5f

Browse files
Andrzej KrupkaAndrzej Krupka
authored andcommitted
Add additional config options to render output
1 parent 7b04946 commit 3dd8a5f

File tree

6 files changed

+197
-81
lines changed

6 files changed

+197
-81
lines changed

flow360/__init__.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,26 @@
107107
PointArray,
108108
PointArray2D,
109109
Slice,
110+
)
111+
from flow360.component.simulation.outputs.output_render_types import (
110112
RenderCameraConfig,
111113
RenderLightingConfig,
114+
RenderEnvironmentConfig,
115+
RenderMaterialConfig,
112116
AmbientLight,
113117
DirectionalLight,
114118
OrthographicProjection,
115119
PerspectiveProjection,
116120
StaticCamera,
117-
OrbitCamera,
118-
SplineCamera,
119-
KeyframeCamera
121+
AnimatedCamera,
122+
Keyframe,
123+
SolidBackground,
124+
SkyboxBackground,
125+
SkyboxTexture,
126+
PBRMaterial,
127+
FieldMaterial,
128+
ColorKey,
129+
Transform
120130
)
121131
from flow360.component.simulation.outputs.outputs import (
122132
AeroAcousticOutput,

flow360/component/simulation/outputs/output_entities.py

Lines changed: 3 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
"""Output for simulation."""
22

33
from abc import ABCMeta
4-
from typing import Literal, Union, Optional
4+
from typing import Literal, Union
55

66
import pydantic as pd
77

88
from flow360.component.simulation.framework.base_model import Flow360BaseModel
99
from flow360.component.simulation.framework.entity_base import EntityBase, generate_uuid
1010
from flow360.component.simulation.outputs.output_fields import IsoSurfaceFieldNames
11-
from flow360.component.simulation.unit_system import LengthType, AngleType
12-
from flow360.component.types import Axis, Vector, Color
11+
from flow360.component.simulation.unit_system import LengthType
12+
from flow360.component.types import Axis
1313

1414

1515
class _OutputItemBase(Flow360BaseModel):
@@ -178,63 +178,3 @@ class PointArray2D(_PointEntityBase):
178178
v_axis_vector: LengthType.Axis = pd.Field(description="The scaled v-axis of the parallelogram.")
179179
u_number_of_points: int = pd.Field(ge=2, description="The number of points along the u axis.")
180180
v_number_of_points: int = pd.Field(ge=2, description="The number of points along the v axis.")
181-
182-
183-
# Linear interpolation between keyframes
184-
class KeyframeCamera(Flow360BaseModel):
185-
pass
186-
187-
188-
# Follow a cubic spline curve
189-
class SplineCamera(Flow360BaseModel):
190-
pass
191-
192-
193-
# Orbit a point (start and end points specified in spherical coordinates)
194-
class OrbitCamera(Flow360BaseModel):
195-
pass
196-
197-
198-
# Static camera setup in Cartesian coordinates
199-
class StaticCamera(Flow360BaseModel):
200-
position: LengthType.Point = pd.Field(description="Position of the camera in the scene")
201-
target: LengthType.Point = pd.Field(description="Target point of the camera")
202-
up: Optional[Vector] = pd.Field((0, 1, 0), description="Up vector, if not specified assume Y+")
203-
204-
205-
# Ortho projection, parallel lines stay parallel
206-
class OrthographicProjection(Flow360BaseModel):
207-
width: LengthType = pd.Field()
208-
near: LengthType = pd.Field()
209-
far: LengthType = pd.Field()
210-
211-
212-
# Perspective projection
213-
class PerspectiveProjection(Flow360BaseModel):
214-
fov: AngleType = pd.Field()
215-
near: LengthType = pd.Field()
216-
far: LengthType = pd.Field()
217-
218-
219-
# Only basic static camera with ortho projection supported currently
220-
class RenderCameraConfig(Flow360BaseModel):
221-
view: StaticCamera = pd.Field()
222-
projection: OrthographicProjection = pd.Field()
223-
224-
225-
# Ambient light, added by default to all pixels in the scene, simulates global illumination
226-
class AmbientLight(Flow360BaseModel):
227-
intensity: float = pd.Field()
228-
color: Color = pd.Field()
229-
230-
231-
# Ambient light, added by default to all pixels in the scene, simulates global illumination
232-
class DirectionalLight(Flow360BaseModel):
233-
intensity: float = pd.Field()
234-
color: Color = pd.Field()
235-
direction: Vector = pd.Field()
236-
237-
238-
class RenderLightingConfig(Flow360BaseModel):
239-
ambient: AmbientLight = pd.Field()
240-
directional: DirectionalLight = pd.Field()
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import abc
2+
from enum import Enum
3+
from typing import Optional, List, Union, Dict
4+
5+
from flow360.component.simulation.framework.base_model import Flow360BaseModel
6+
from flow360.component.simulation.unit_system import LengthType, AngleType
7+
8+
import pydantic as pd
9+
10+
from flow360.component.types import Vector, Color
11+
12+
13+
class StaticCamera(Flow360BaseModel):
14+
position: LengthType.Point = pd.Field(description="Position of the camera in the scene")
15+
target: LengthType.Point = pd.Field(description="Target point of the camera")
16+
up: Optional[Vector] = pd.Field(default=(0, 1, 0), description="Up vector, if not specified assume Y+")
17+
18+
19+
class Keyframe(Flow360BaseModel):
20+
time: pd.confloat(ge=0) = pd.Field(0)
21+
view: StaticCamera = pd.Field()
22+
23+
24+
class AnimatedCamera(Flow360BaseModel):
25+
keyframes: List[Keyframe] = pd.Field([])
26+
27+
28+
AllCameraTypes = Union[StaticCamera, AnimatedCamera]
29+
30+
31+
class OrthographicProjection(Flow360BaseModel):
32+
type: str = pd.Field(default="orthographic", frozen=True)
33+
width: LengthType = pd.Field()
34+
near: LengthType = pd.Field()
35+
far: LengthType = pd.Field()
36+
37+
38+
class PerspectiveProjection(Flow360BaseModel):
39+
type: str = pd.Field(default="perspective", frozen=True)
40+
fov: AngleType = pd.Field()
41+
near: LengthType = pd.Field()
42+
far: LengthType = pd.Field()
43+
44+
45+
class RenderCameraConfig(Flow360BaseModel):
46+
view: AllCameraTypes = pd.Field()
47+
projection: Union[OrthographicProjection, PerspectiveProjection] = pd.Field()
48+
49+
50+
class AmbientLight(Flow360BaseModel):
51+
intensity: float = pd.Field()
52+
color: Color = pd.Field()
53+
54+
55+
class DirectionalLight(Flow360BaseModel):
56+
intensity: float = pd.Field()
57+
color: Color = pd.Field()
58+
direction: Vector = pd.Field()
59+
60+
61+
class RenderLightingConfig(Flow360BaseModel):
62+
directional: DirectionalLight = pd.Field()
63+
ambient: Optional[AmbientLight] = pd.Field(None)
64+
65+
66+
class RenderBackgroundBase(Flow360BaseModel, metaclass=abc.ABCMeta):
67+
type: str = pd.Field(default="", frozen=True)
68+
69+
70+
class SolidBackground(RenderBackgroundBase):
71+
type: str = pd.Field(default="solid", frozen=True)
72+
color: Color = pd.Field()
73+
74+
75+
class SkyboxTexture(str, Enum):
76+
SKY = "sky"
77+
78+
79+
class SkyboxBackground(RenderBackgroundBase):
80+
type: str = pd.Field(default="skybox", frozen=True)
81+
texture: SkyboxTexture = pd.Field(SkyboxTexture.SKY)
82+
83+
84+
AllBackgroundTypes = Union[
85+
SolidBackground,
86+
SkyboxBackground
87+
]
88+
89+
90+
class RenderEnvironmentConfig(Flow360BaseModel):
91+
background: AllBackgroundTypes = pd.Field()
92+
93+
94+
class RenderMaterialBase(Flow360BaseModel, metaclass=abc.ABCMeta):
95+
type: str = pd.Field(default="", frozen=True)
96+
97+
98+
class PBRMaterial(RenderMaterialBase):
99+
color: Color = pd.Field(default=[255, 255, 255])
100+
alpha: float = pd.Field(default=1)
101+
roughness: float = pd.Field(default=0.5)
102+
f0: Vector = pd.Field(default=(0.03, 0.03, 0.03))
103+
type: str = pd.Field(default="pbr", frozen=True)
104+
105+
106+
class ColorKey(Flow360BaseModel):
107+
color: Color = pd.Field(default=[255, 255, 255])
108+
value: pd.confloat(ge=0, le=1) = pd.Field(default=0.5)
109+
110+
111+
class FieldMaterial(RenderMaterialBase):
112+
alpha: float = pd.Field(default=1)
113+
output_field: str = pd.Field(default="")
114+
min: float = pd.Field(default=0)
115+
max: float = pd.Field(default=0)
116+
colormap: List[ColorKey] = pd.Field()
117+
type: str = pd.Field(default="field", frozen=True)
118+
119+
120+
AllMaterialTypes = Union[
121+
PBRMaterial,
122+
FieldMaterial
123+
]
124+
125+
126+
class RenderMaterialConfig(Flow360BaseModel):
127+
materials: List[AllMaterialTypes] = pd.Field([])
128+
mappings: Dict[str, int] = pd.Field({})
129+
130+
131+
class Transform(Flow360BaseModel):
132+
translation: LengthType.Point = pd.Field(default=[0, 0, 0])
133+
rotation: AngleType.Vector = pd.Field(default=[0, 0, 0])
134+
scale: Vector = pd.Field(default=[1, 1, 1])

flow360/component/simulation/outputs/outputs.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@
1919
Point,
2020
PointArray,
2121
PointArray2D,
22-
Slice, RenderCameraConfig, RenderLightingConfig,
22+
Slice
23+
)
24+
from flow360.component.simulation.outputs.output_render_types import (
25+
RenderCameraConfig,
26+
RenderLightingConfig,
27+
RenderEnvironmentConfig,
28+
RenderMaterialConfig,
29+
Transform,
2330
)
2431
from flow360.component.simulation.outputs.output_fields import (
2532
AllFieldNames,
@@ -495,16 +502,21 @@ class RenderOutput(_AnimationSettings):
495502
name: Optional[str] = pd.Field(
496503
"Render output", description="Name of the `IsosurfaceOutput`."
497504
)
498-
entities: UniqueItemList[Isosurface] = pd.Field(
499-
alias="isosurfaces",
500-
description="List of :class:`~flow360.Isosurface` entities.",
505+
isosurfaces: Optional[UniqueItemList[Isosurface]] = pd.Field(None,
506+
description="List of :class:`~flow360.Isosurface` entities."
507+
)
508+
surfaces: Optional[EntityList[Surface]] = pd.Field(None,
509+
description="List of of :class:`~flow360.Surface` entities."
501510
)
502511
output_fields: UniqueItemList[Union[CommonFieldNames, str]] = pd.Field(
503512
description="List of output variables. Including "
504513
":ref:`universal output variables<UniversalVariablesV2>` and :class:`UserDefinedField`."
505514
)
506515
camera: RenderCameraConfig = pd.Field(description="Camera settings")
507516
lighting: RenderLightingConfig = pd.Field(description="Lighting settings")
517+
environment: RenderEnvironmentConfig = pd.Field(description="Environment settings")
518+
materials: RenderMaterialConfig = pd.Field(description="Material settings")
519+
transform: Optional[Transform] = pd.Field(None, description="Optional model transform to apply to all entities")
508520
output_type: Literal["RenderOutput"] = pd.Field("RenderOutput", frozen=True)
509521

510522

flow360/component/simulation/translator/solver_translator.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,8 @@ def translate_render_output(output_params: list, injection_function):
457457
for render in renders:
458458
camera = render.camera.model_dump(exclude_none=True, exclude_unset=True, by_alias=True)
459459
lighting = render.lighting.model_dump(exclude_none=True, exclude_unset=True, by_alias=True)
460+
environment = render.environment.model_dump(exclude_none=True, exclude_unset=True, by_alias=True)
461+
materials = render.materials.model_dump(exclude_none=True, exclude_unset=True, by_alias=True)
460462

461463
translated_output = {
462464
"animationFrequency": render.frequency,
@@ -467,10 +469,25 @@ def translate_render_output(output_params: list, injection_function):
467469
translation_func=translate_output_fields,
468470
to_list=False,
469471
entity_injection_func=injection_function,
472+
entity_list_attribute_name="isosurfaces"
473+
),
474+
"surfaces": translate_setting_and_apply_to_all_entities(
475+
[render],
476+
RenderOutput,
477+
translation_func=translate_output_fields,
478+
to_list=False,
479+
entity_list_attribute_name="surfaces"
470480
),
471481
"camera": remove_units_in_dict(camera),
472-
"lighting": remove_units_in_dict(lighting)
482+
"lighting": remove_units_in_dict(lighting),
483+
"environment": remove_units_in_dict(environment),
484+
"materials": remove_units_in_dict(materials),
473485
}
486+
487+
if render.transform:
488+
transform = render.transform.model_dump(exclude_none=True, exclude_unset=True, by_alias=True)
489+
translated_output["transform"] = remove_units_in_dict(transform)
490+
474491
translated_outputs.append(translated_output)
475492

476493
return translated_outputs

flow360/component/simulation/translator/utils.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ def translate_setting_and_apply_to_all_entities(
229229
lump_list_of_entities=False,
230230
use_instance_name_as_key=False,
231231
use_sub_item_as_key=False,
232+
entity_list_attribute_name="entities",
232233
**kwargs,
233234
):
234235
"""
@@ -308,26 +309,28 @@ def translate_setting_and_apply_to_all_entities(
308309
if k.startswith(entity_injection_prefix)
309310
}
310311

312+
313+
311314
# pylint: disable=too-many-nested-blocks
312315
for obj in obj_list:
313316
if class_type and is_exact_instance(obj, class_type):
314-
315317
list_of_entities = []
316-
if "entities" in obj.__class__.model_fields:
317-
if obj.entities is None or (
318-
"stored_entities" in obj.entities.__class__.model_fields
319-
and obj.entities.stored_entities is None
318+
if entity_list_attribute_name in obj.__class__.model_fields:
319+
entities = getattr(obj, entity_list_attribute_name)
320+
if entities is None or (
321+
"stored_entities" in entities.__class__.model_fields
322+
and entities.stored_entities is None
320323
): # unique item list does not allow None "items" for now.
321324
continue
322-
if isinstance(obj.entities, EntityList):
325+
if isinstance(entities, EntityList):
323326
list_of_entities = (
324-
obj.entities.stored_entities
327+
entities.stored_entities
325328
if lump_list_of_entities is False
326-
else [obj.entities]
329+
else [entities]
327330
)
328-
elif isinstance(obj.entities, UniqueItemList):
331+
elif isinstance(entities, UniqueItemList):
329332
list_of_entities = (
330-
obj.entities.items if lump_list_of_entities is False else [obj.entities]
333+
entities.items if lump_list_of_entities is False else [entities]
331334
)
332335
elif "entity_pairs" in obj.__class__.model_fields:
333336
# Note: This is only used in Periodic BC and lump_list_of_entities is not relavant

0 commit comments

Comments
 (0)