Skip to content

Commit 8ed13c8

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

File tree

5 files changed

+79
-37
lines changed

5 files changed

+79
-37
lines changed

flow360/__init__.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,17 @@
109109
Slice,
110110
RenderCameraConfig,
111111
RenderLightingConfig,
112+
RenderEnvironmentConfig,
113+
RenderMaterialConfig,
112114
AmbientLight,
113115
DirectionalLight,
114116
OrthographicProjection,
115117
PerspectiveProjection,
116118
StaticCamera,
117-
OrbitCamera,
118-
SplineCamera,
119-
KeyframeCamera
119+
SolidBackground,
120+
SkyboxBackground,
121+
SkyboxTexture,
122+
PBRMaterial
120123
)
121124
from flow360.component.simulation.outputs.outputs import (
122125
AeroAcousticOutput,

flow360/component/simulation/outputs/output_entities.py

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"""Output for simulation."""
22

33
from abc import ABCMeta
4-
from typing import Literal, Union, Optional
4+
from enum import Enum
5+
from typing import Literal, Union, Optional, List, Dict
56

67
import pydantic as pd
78

@@ -180,21 +181,6 @@ class PointArray2D(_PointEntityBase):
180181
v_number_of_points: int = pd.Field(ge=2, description="The number of points along the v axis.")
181182

182183

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-
198184
# Static camera setup in Cartesian coordinates
199185
class StaticCamera(Flow360BaseModel):
200186
position: LengthType.Point = pd.Field(description="Position of the camera in the scene")
@@ -204,13 +190,15 @@ class StaticCamera(Flow360BaseModel):
204190

205191
# Ortho projection, parallel lines stay parallel
206192
class OrthographicProjection(Flow360BaseModel):
193+
type: str = pd.Field(default="orthographic", frozen=True)
207194
width: LengthType = pd.Field()
208195
near: LengthType = pd.Field()
209196
far: LengthType = pd.Field()
210197

211198

212199
# Perspective projection
213200
class PerspectiveProjection(Flow360BaseModel):
201+
type: str = pd.Field(default="perspective", frozen=True)
214202
fov: AngleType = pd.Field()
215203
near: LengthType = pd.Field()
216204
far: LengthType = pd.Field()
@@ -219,7 +207,7 @@ class PerspectiveProjection(Flow360BaseModel):
219207
# Only basic static camera with ortho projection supported currently
220208
class RenderCameraConfig(Flow360BaseModel):
221209
view: StaticCamera = pd.Field()
222-
projection: OrthographicProjection = pd.Field()
210+
projection: Union[OrthographicProjection, PerspectiveProjection] = pd.Field()
223211

224212

225213
# Ambient light, added by default to all pixels in the scene, simulates global illumination
@@ -228,13 +216,45 @@ class AmbientLight(Flow360BaseModel):
228216
color: Color = pd.Field()
229217

230218

231-
# Ambient light, added by default to all pixels in the scene, simulates global illumination
232219
class DirectionalLight(Flow360BaseModel):
233220
intensity: float = pd.Field()
234221
color: Color = pd.Field()
235222
direction: Vector = pd.Field()
236223

237224

238225
class RenderLightingConfig(Flow360BaseModel):
239-
ambient: AmbientLight = pd.Field()
240226
directional: DirectionalLight = pd.Field()
227+
ambient: Optional[AmbientLight] = pd.Field(None)
228+
229+
230+
class SolidBackground(Flow360BaseModel):
231+
type: str = pd.Field(default="solid", frozen=True)
232+
color: Color = pd.Field()
233+
234+
235+
class SkyboxTexture(str, Enum):
236+
SKY = "sky"
237+
SEA = "sea"
238+
LIGHT = "light"
239+
DARK = "dark"
240+
241+
242+
class SkyboxBackground(Flow360BaseModel):
243+
type: str = pd.Field(default="skybox", frozen=True)
244+
texture: SkyboxTexture = pd.Field(SkyboxTexture.SKY)
245+
246+
247+
class RenderEnvironmentConfig(Flow360BaseModel):
248+
background: Union[SolidBackground, SkyboxBackground] = pd.Field()
249+
250+
251+
class PBRMaterial(Flow360BaseModel):
252+
color: Color = pd.Field([255, 255, 255])
253+
alpha: float = pd.Field(1)
254+
roughness: float = pd.Field(0.5)
255+
f0: Vector = pd.Field((0.03, 0.03, 0.03))
256+
257+
258+
class RenderMaterialConfig(Flow360BaseModel):
259+
materials: List[PBRMaterial] = pd.Field([])
260+
mappings: Dict[str, int] = pd.Field({})

flow360/component/simulation/outputs/outputs.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
Point,
2020
PointArray,
2121
PointArray2D,
22-
Slice, RenderCameraConfig, RenderLightingConfig,
22+
Slice, RenderCameraConfig, RenderLightingConfig, RenderEnvironmentConfig, RenderMaterialConfig,
2323
)
2424
from flow360.component.simulation.outputs.output_fields import (
2525
AllFieldNames,
@@ -495,16 +495,20 @@ class RenderOutput(_AnimationSettings):
495495
name: Optional[str] = pd.Field(
496496
"Render output", description="Name of the `IsosurfaceOutput`."
497497
)
498-
entities: UniqueItemList[Isosurface] = pd.Field(
499-
alias="isosurfaces",
500-
description="List of :class:`~flow360.Isosurface` entities.",
498+
isosurfaces: Optional[UniqueItemList[Isosurface]] = pd.Field(None,
499+
description="List of :class:`~flow360.Isosurface` entities."
500+
)
501+
surfaces: Optional[EntityList[Surface]] = pd.Field(None,
502+
description="List of of :class:`~flow360.Surface` entities."
501503
)
502504
output_fields: UniqueItemList[Union[CommonFieldNames, str]] = pd.Field(
503505
description="List of output variables. Including "
504506
":ref:`universal output variables<UniversalVariablesV2>` and :class:`UserDefinedField`."
505507
)
506508
camera: RenderCameraConfig = pd.Field(description="Camera settings")
507509
lighting: RenderLightingConfig = pd.Field(description="Lighting settings")
510+
environment: RenderEnvironmentConfig = pd.Field(description="Environment settings")
511+
materials: RenderMaterialConfig = pd.Field(description="Material settings")
508512
output_type: Literal["RenderOutput"] = pd.Field("RenderOutput", frozen=True)
509513

510514

flow360/component/simulation/translator/solver_translator.py

Lines changed: 13 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,9 +469,19 @@ 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
}
474486
translated_outputs.append(translated_output)
475487

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)