File: backface_prop.py

package info (click to toggle)
python-pyvista 0.46.4-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 176,968 kB
  • sloc: python: 94,346; sh: 216; makefile: 70
file content (144 lines) | stat: -rw-r--r-- 4,910 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
"""
.. _backface_prop_example:

Setting Backface Properties
~~~~~~~~~~~~~~~~~~~~~~~~~~~

By default front and backface rendering uses the same properties. In certain
situations it can be useful to set different properties for backfaces than
for frontfaces.

One straightforward example is when a closed (or close enough) surface has a
different color on the inside. Note that the notion of "inside" and "outside"
depend on the orientation of the surface normals:
"""

# sphinx_gallery_thumbnail_number = 1

# sphinx_gallery_start_ignore
# backface properties do not work in interactive
from __future__ import annotations

PYVISTA_GALLERY_FORCE_STATIC = True
# sphinx_gallery_end_ignore

import numpy as np

import pyvista as pv
from pyvista import examples

mesh = pv.ParametricEllipsoid(min_v=np.pi / 2 - 0.2, max_v=np.pi / 2 + 0.2)

# create a shifted copy with flipped normals
mesh_inside_out = mesh.translate((0, 0, 1), inplace=False)
mesh_inside_out.compute_normals(flip_normals=True, inplace=True)
meshes = mesh + mesh_inside_out

backface_params = dict(color='orangered')
meshes.plot(color='aquamarine', backface_params=backface_params, smooth_shading=True)


# %%
# A more interesting use case is helping visualize the orientation of complex,
# self-intersecting surfaces. For instance :func:`Catalan's minimal surface
# <pyvista.ParametricCatalanMinimal>` has a complex shape, and coloring the
# front and backfaces differently helps viewers comprehend the intricate
# structure of the surface. This example also demonstrates use of the
# :attr:`backface_prop <pyvista.Actor.backface_prop>` property of the
# :class:`pyvista.Actor` class.

catalan = pv.ParametricCatalanMinimal()
plotter = pv.Plotter()
actor = plotter.add_mesh(catalan, color='dodgerblue', smooth_shading=True)
bprop = actor.backface_prop
bprop.color = 'forestgreen'
bprop.specular = 1.0
bprop.specular_power = 50.0
plotter.show()


# %%
# In the case of non-orientable surfaces, adding specific backface properties can
# make the non-orientable quality very obvious by the emergence of "seams"
# where the face properties are discontinuous.

henneberg = pv.ParametricHenneberg().scale(0.25, inplace=False)
klein = pv.ParametricKlein().rotate_z(150, inplace=False).translate((6, 0, 0), inplace=False)
meshes = henneberg + klein

backface_params = dict(color='mediumseagreen', specular=1.0, specular_power=50.0)
meshes.plot(color='gold', backface_params=backface_params, smooth_shading=True)


# %%
# Of course we aren't constrained to only setting distinct colors for backfaces;
# most :class:`pyvista.Property` attributes can be overridden. However, some of
# these have no effect, while others merely don't make any sense. For instance,
# most objects have the same opacity no matter which direction you look at them.
# Here is a GIF animation circling around such an asymmetrically opaque Möbius
# strip:

mobius = pv.ParametricMobius().rotate_z(-90, inplace=False)
backface_params = dict(opacity=0.5)
plotter = pv.Plotter()
plotter.add_mesh(mobius, color='deepskyblue', backface_params=backface_params, smooth_shading=True)
plotter.open_gif('mobius_semiopaque.gif')

viewup = [0, 0, 1]
orbit = plotter.generate_orbital_path(n_points=24, shift=0.0, viewup=viewup)
plotter.orbit_on_path(orbit, write_frames=True, viewup=viewup, step=0.02)


# %%
# Apply Backface Properties to Textured Meshes
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Backface textures can also be applied to meshes that have textures applied to
# them. For this example we load the globe texture with
# :func:`pyvista.examples.load_globe() <pyvista.examples.examples.load_globe>`,
# clip it, and then apply a different color to the interior surface.
#
# The lighting has been disabled for this example to demonstrate how you can
# make the interior of the surface appear occluded without any directional
# lighting simply by providing a different color for backface.

globe = examples.load_globe()
texture = examples.load_globe_texture()
clipped = globe.clip(normal='z', value=4.37e9)

pl = pv.Plotter()
pl.add_mesh(
    clipped,
    backface_params={'color': [0.2, 0.2, 0.2]},
    lighting=False,
    smooth_shading=True,
    texture=texture,
)
pl.show()


# %%
# Backface Properties and Physically Based Rendering
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Note that backfaces are automatically culled when physically based rendering
# is enabled, regardless of the settings of backface parameters.

sphere = pv.Sphere()
clipped_sphere = sphere.clip(normal='z', value=0.4)

pl = pv.Plotter()
pl.set_environment_texture(examples.download_sky_box_cube_map())
pl.add_mesh(
    clipped_sphere,
    backface_params={'color': 'r'},
    pbr=True,
    metallic=1.0,
    roughness=0.2,
)
pl.show()


# %%
# See also the :ref:`sphere_eversion_example` example which relies on
# distinguishing the inside and the outside of a sphere.
#
# .. tags:: plot