Skip to content

Commit 16cee37

Browse files
Andrzej Krupkaandrzej-krupka
authored andcommitted
Add additional config options to render output
1 parent b2ba940 commit 16cee37

File tree

6 files changed

+215
-81
lines changed

6 files changed

+215
-81
lines changed

flow360/__init__.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,23 +123,34 @@
123123
PointArray,
124124
PointArray2D,
125125
Slice,
126-
RenderCameraConfig,
127-
RenderLightingConfig,
126+
)
127+
from flow360.component.simulation.outputs.output_render_types import (
128128
AmbientLight,
129+
AnimatedCamera,
130+
ColorKey,
129131
DirectionalLight,
132+
FieldMaterial,
133+
Keyframe,
130134
OrthographicProjection,
135+
PBRMaterial,
131136
PerspectiveProjection,
137+
RenderCameraConfig,
138+
RenderEnvironmentConfig,
139+
RenderLightingConfig,
140+
RenderMaterialConfig,
141+
SkyboxBackground,
142+
SkyboxTexture,
143+
SolidBackground,
132144
StaticCamera,
133-
OrbitCamera,
134-
SplineCamera,
135-
KeyframeCamera
145+
Transform,
136146
)
137147
from flow360.component.simulation.outputs.outputs import (
138148
AeroAcousticOutput,
139149
IsosurfaceOutput,
140150
MovingStatistic,
141151
Observer,
142152
ProbeOutput,
153+
RenderOutput,
143154
SliceOutput,
144155
StreamlineOutput,
145156
SurfaceIntegralOutput,
@@ -155,7 +166,6 @@
155166
TimeAverageVolumeOutput,
156167
UserDefinedField,
157168
VolumeOutput,
158-
RenderOutput
159169
)
160170
from flow360.component.simulation.primitives import (
161171
AxisymmetricBody,

flow360/component/simulation/outputs/output_entities.py

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -289,63 +289,3 @@ class PointArray2D(_PointEntityBase):
289289
v_axis_vector: LengthType.Axis = pd.Field(description="The scaled v-axis of the parallelogram.")
290290
u_number_of_points: int = pd.Field(ge=2, description="The number of points along the u axis.")
291291
v_number_of_points: int = pd.Field(ge=2, description="The number of points along the v axis.")
292-
293-
294-
# Linear interpolation between keyframes
295-
class KeyframeCamera(Flow360BaseModel):
296-
pass
297-
298-
299-
# Follow a cubic spline curve
300-
class SplineCamera(Flow360BaseModel):
301-
pass
302-
303-
304-
# Orbit a point (start and end points specified in spherical coordinates)
305-
class OrbitCamera(Flow360BaseModel):
306-
pass
307-
308-
309-
# Static camera setup in Cartesian coordinates
310-
class StaticCamera(Flow360BaseModel):
311-
position: LengthType.Point = pd.Field(description="Position of the camera in the scene")
312-
target: LengthType.Point = pd.Field(description="Target point of the camera")
313-
up: Optional[Vector] = pd.Field((0, 1, 0), description="Up vector, if not specified assume Y+")
314-
315-
316-
# Ortho projection, parallel lines stay parallel
317-
class OrthographicProjection(Flow360BaseModel):
318-
width: LengthType = pd.Field()
319-
near: LengthType = pd.Field()
320-
far: LengthType = pd.Field()
321-
322-
323-
# Perspective projection
324-
class PerspectiveProjection(Flow360BaseModel):
325-
fov: AngleType = pd.Field()
326-
near: LengthType = pd.Field()
327-
far: LengthType = pd.Field()
328-
329-
330-
# Only basic static camera with ortho projection supported currently
331-
class RenderCameraConfig(Flow360BaseModel):
332-
view: StaticCamera = pd.Field()
333-
projection: OrthographicProjection = pd.Field()
334-
335-
336-
# Ambient light, added by default to all pixels in the scene, simulates global illumination
337-
class AmbientLight(Flow360BaseModel):
338-
intensity: float = pd.Field()
339-
color: Color = pd.Field()
340-
341-
342-
# Ambient light, added by default to all pixels in the scene, simulates global illumination
343-
class DirectionalLight(Flow360BaseModel):
344-
intensity: float = pd.Field()
345-
color: Color = pd.Field()
346-
direction: Vector = pd.Field()
347-
348-
349-
class RenderLightingConfig(Flow360BaseModel):
350-
ambient: AmbientLight = pd.Field()
351-
directional: DirectionalLight = pd.Field()
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import abc
2+
from enum import Enum
3+
from typing import Dict, List, Optional, Union
4+
5+
import pydantic as pd
6+
7+
from flow360.component.simulation.framework.base_model import Flow360BaseModel
8+
from flow360.component.simulation.unit_system import AngleType, LengthType
9+
from flow360.component.types import Color, Vector
10+
11+
12+
class StaticCamera(Flow360BaseModel):
13+
position: LengthType.Point = pd.Field(description="Position of the camera in the scene")
14+
target: LengthType.Point = pd.Field(description="Target point of the camera")
15+
up: Optional[Vector] = pd.Field(
16+
default=(0, 1, 0), description="Up vector, if not specified assume Y+"
17+
)
18+
19+
20+
class Keyframe(Flow360BaseModel):
21+
time: pd.confloat(ge=0) = pd.Field(0)
22+
view: StaticCamera = pd.Field()
23+
24+
25+
class AnimatedCamera(Flow360BaseModel):
26+
keyframes: List[Keyframe] = pd.Field([])
27+
28+
29+
AllCameraTypes = Union[StaticCamera, AnimatedCamera]
30+
31+
32+
class OrthographicProjection(Flow360BaseModel):
33+
type: str = pd.Field(default="orthographic", frozen=True)
34+
width: LengthType = pd.Field()
35+
near: LengthType = pd.Field()
36+
far: LengthType = pd.Field()
37+
38+
39+
class PerspectiveProjection(Flow360BaseModel):
40+
type: str = pd.Field(default="perspective", frozen=True)
41+
fov: AngleType = pd.Field()
42+
near: LengthType = pd.Field()
43+
far: LengthType = pd.Field()
44+
45+
46+
class RenderCameraConfig(Flow360BaseModel):
47+
view: AllCameraTypes = pd.Field()
48+
projection: Union[OrthographicProjection, PerspectiveProjection] = pd.Field()
49+
50+
51+
class AmbientLight(Flow360BaseModel):
52+
intensity: float = pd.Field()
53+
color: Color = pd.Field()
54+
55+
56+
class DirectionalLight(Flow360BaseModel):
57+
intensity: float = pd.Field()
58+
color: Color = pd.Field()
59+
direction: Vector = pd.Field()
60+
61+
62+
class RenderLightingConfig(Flow360BaseModel):
63+
directional: DirectionalLight = pd.Field()
64+
ambient: Optional[AmbientLight] = pd.Field(None)
65+
66+
67+
class RenderBackgroundBase(Flow360BaseModel, metaclass=abc.ABCMeta):
68+
type: str = pd.Field(default="", frozen=True)
69+
70+
71+
class SolidBackground(RenderBackgroundBase):
72+
type: str = pd.Field(default="solid", frozen=True)
73+
color: Color = pd.Field()
74+
75+
76+
class SkyboxTexture(str, Enum):
77+
SKY = "sky"
78+
79+
80+
class SkyboxBackground(RenderBackgroundBase):
81+
type: str = pd.Field(default="skybox", frozen=True)
82+
texture: SkyboxTexture = pd.Field(SkyboxTexture.SKY)
83+
84+
85+
AllBackgroundTypes = Union[SolidBackground, SkyboxBackground]
86+
87+
88+
class RenderEnvironmentConfig(Flow360BaseModel):
89+
background: AllBackgroundTypes = pd.Field()
90+
91+
92+
class RenderMaterialBase(Flow360BaseModel, metaclass=abc.ABCMeta):
93+
type: str = pd.Field(default="", frozen=True)
94+
95+
96+
class PBRMaterial(RenderMaterialBase):
97+
color: Color = pd.Field(default=[255, 255, 255])
98+
alpha: float = pd.Field(default=1)
99+
roughness: float = pd.Field(default=0.5)
100+
f0: Vector = pd.Field(default=(0.03, 0.03, 0.03))
101+
type: str = pd.Field(default="pbr", frozen=True)
102+
103+
104+
class ColorKey(Flow360BaseModel):
105+
color: Color = pd.Field(default=[255, 255, 255])
106+
value: pd.confloat(ge=0, le=1) = pd.Field(default=0.5)
107+
108+
109+
class FieldMaterial(RenderMaterialBase):
110+
alpha: float = pd.Field(default=1)
111+
output_field: str = pd.Field(default="")
112+
min: float = pd.Field(default=0)
113+
max: float = pd.Field(default=0)
114+
colormap: List[ColorKey] = pd.Field()
115+
type: str = pd.Field(default="field", frozen=True)
116+
117+
118+
AllMaterialTypes = Union[PBRMaterial, FieldMaterial]
119+
120+
121+
class RenderMaterialConfig(Flow360BaseModel):
122+
materials: List[AllMaterialTypes] = pd.Field([])
123+
mappings: Dict[str, int] = pd.Field({})
124+
125+
126+
class Transform(Flow360BaseModel):
127+
translation: LengthType.Point = pd.Field(default=[0, 0, 0])
128+
rotation: AngleType.Vector = pd.Field(default=[0, 0, 0])
129+
scale: Vector = pd.Field(default=[1, 1, 1])

flow360/component/simulation/outputs/outputs.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
Point,
2222
PointArray,
2323
PointArray2D,
24-
RenderCameraConfig,
25-
RenderLightingConfig,
2624
Slice,
2725
)
2826
from flow360.component.simulation.outputs.output_fields import (
@@ -34,6 +32,13 @@
3432
VolumeFieldNames,
3533
get_field_values,
3634
)
35+
from flow360.component.simulation.outputs.output_render_types import (
36+
RenderCameraConfig,
37+
RenderEnvironmentConfig,
38+
RenderLightingConfig,
39+
RenderMaterialConfig,
40+
Transform,
41+
)
3742
from flow360.component.simulation.primitives import (
3843
GhostCircularPlane,
3944
GhostSphere,
@@ -697,16 +702,23 @@ class RenderOutput(_AnimationSettings):
697702
"""
698703

699704
name: Optional[str] = pd.Field("Render output", description="Name of the `IsosurfaceOutput`.")
700-
entities: UniqueItemList[Isosurface] = pd.Field(
701-
alias="isosurfaces",
702-
description="List of :class:`~flow360.Isosurface` entities.",
705+
isosurfaces: Optional[UniqueItemList[Isosurface]] = pd.Field(
706+
None, description="List of :class:`~flow360.Isosurface` entities."
707+
)
708+
surfaces: Optional[EntityList[Surface]] = pd.Field(
709+
None, description="List of of :class:`~flow360.Surface` entities."
703710
)
704711
output_fields: UniqueItemList[Union[CommonFieldNames, str]] = pd.Field(
705712
description="List of output variables. Including "
706713
":ref:`universal output variables<UniversalVariablesV2>` and :class:`UserDefinedField`."
707714
)
708715
camera: RenderCameraConfig = pd.Field(description="Camera settings")
709716
lighting: RenderLightingConfig = pd.Field(description="Lighting settings")
717+
environment: RenderEnvironmentConfig = pd.Field(description="Environment settings")
718+
materials: RenderMaterialConfig = pd.Field(description="Material settings")
719+
transform: Optional[Transform] = pd.Field(
720+
None, description="Optional model transform to apply to all entities"
721+
)
710722
output_type: Literal["RenderOutput"] = pd.Field("RenderOutput", frozen=True)
711723

712724

flow360/component/simulation/translator/solver_translator.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,10 @@ def init_output_base(obj_list, class_type: Type, is_average: bool):
193193
class_type,
194194
"output_format",
195195
)
196-
if not no_format:
197-
assert output_format is not None
198-
if output_format == "both":
199-
output_format = "paraview,tecplot"
200-
base["outputFormat"] = output_format
196+
assert output_format is not None
197+
if output_format == "both":
198+
output_format = "paraview,tecplot"
199+
base["outputFormat"] = output_format
201200

202201
if is_average:
203202
base = init_average_output(base, obj_list, class_type)
@@ -587,6 +586,12 @@ def translate_render_output(output_params: list, injection_function):
587586
for render in renders:
588587
camera = render.camera.model_dump(exclude_none=True, exclude_unset=True, by_alias=True)
589588
lighting = render.lighting.model_dump(exclude_none=True, exclude_unset=True, by_alias=True)
589+
environment = render.environment.model_dump(
590+
exclude_none=True, exclude_unset=True, by_alias=True
591+
)
592+
materials = render.materials.model_dump(
593+
exclude_none=True, exclude_unset=True, by_alias=True
594+
)
590595

591596
translated_output = {
592597
"animationFrequency": render.frequency,
@@ -597,10 +602,27 @@ def translate_render_output(output_params: list, injection_function):
597602
translation_func=translate_output_fields,
598603
to_list=False,
599604
entity_injection_func=injection_function,
605+
entity_list_attribute_name="isosurfaces",
606+
),
607+
"surfaces": translate_setting_and_apply_to_all_entities(
608+
[render],
609+
RenderOutput,
610+
translation_func=translate_output_fields,
611+
to_list=False,
612+
entity_list_attribute_name="surfaces",
600613
),
601614
"camera": remove_units_in_dict(camera),
602615
"lighting": remove_units_in_dict(lighting),
616+
"environment": remove_units_in_dict(environment),
617+
"materials": remove_units_in_dict(materials),
603618
}
619+
620+
if render.transform:
621+
transform = render.transform.model_dump(
622+
exclude_none=True, exclude_unset=True, by_alias=True
623+
)
624+
translated_output["transform"] = remove_units_in_dict(transform)
625+
604626
translated_outputs.append(translated_output)
605627

606628
return translated_outputs

0 commit comments

Comments
 (0)