vkf_sphere Module

Spheres and ellipsoids: a textured celestial body, as OpenFrames' Sphere.

The body is centered on its frame's origin (or at set_sphere_position, turned by set_sphere_attitude, e.g. to orient a texture). Its shape is a sphere of radius, or an ellipsoid with semi-axes radius * sphere_scale; the ellipsoid is built directly (exact normals, geodetic texture mapping; see vkf_geometry), where OpenFrames scales a sphere. The texture is an equirectangular image (longitude -180 to 180, north at the top). The color is used when there is no texture.

Lighting: the body is lit by the scene's lights (a frame's light source, e.g. the Sun, or the window's light), with a material (set_material; OpenFrames' default: no specular reflection). The night texture shows where the surface is lit weakly (the night side: city lights), as OpenFrames' setNightTextureMap: weighted by 1 - the lit color (the material's ambient and diffuse colors in the lights' colors and intensities, and its emission), per channel and per pixel, so a brighter light narrows the band where the day fades into the night, and ambient light dims the night texture. The twilight (set_twilight; not in OpenFrames; default none: the light ends at the terminator) extends the diffuse light past the terminator, to where the light is a given angle below the horizon, fading out: e.g. sunlight scattered by an atmosphere.

Translucency (not in OpenFrames): set_opacity (default 1, opaque) below 1 draws the body translucent: lit as usual, blended over what is behind it, drawn after the opaque scene (farthest first: VSG's depth-sorted bin) without writing depth, front faces only. Whether it is translucent is decided when a window first shows it (as the textures); its opacity can then change at any time (through the material's alpha).

Texture files are found with find_data_file (a path, or a name on VKFRAMES_DATA_PATH, e.g. data/'s 2k_earth_daymap.jpg and 2k_earth_nightmap.jpg). The textures and the mesh resolution are read when a window first shows the sphere: set them before that. The radius, scale, color and material can change at any time: the meshes are built once, then scaled by their transform (radii / the built radii), and the color is applied through the material (the shaders multiply the vertex color, white here, by the diffuse color).

Level of detail (set_auto_lod, on by default; OpenFrames' setAutoLOD): the body has meshes of 32, 64, ... 1024 segments around (half as many from pole to pole), and each view draws the coarsest whose facets stay within half a pixel of the true outline (src/vsg/vkf_layer.cpp: SphereLod), so that the body isn't faceted however close the view. Meshes are built when a view first wants them (the 128-segment one at once), in the sphere's update. Off: one mesh of set_resolution's segments (default 128 x 64).


Uses

  • module~~vkf_sphere~~UsesGraph module~vkf_sphere vkf_sphere iso_c_binding iso_c_binding module~vkf_sphere->iso_c_binding module~vkf_files vkf_files module~vkf_sphere->module~vkf_files module~vkf_frames vkf_frames module~vkf_sphere->module~vkf_frames module~vkf_geometry vkf_geometry module~vkf_sphere->module~vkf_geometry module~vkf_layer vkf_layer module~vkf_sphere->module~vkf_layer module~vkf_math vkf_math module~vkf_sphere->module~vkf_math module~vkf_pick vkf_pick module~vkf_sphere->module~vkf_pick module~vkf_frames->iso_c_binding module~vkf_frames->module~vkf_geometry module~vkf_frames->module~vkf_layer module~vkf_frames->module~vkf_math module~vkf_frames->module~vkf_pick module~vkf_follower vkf_follower module~vkf_frames->module~vkf_follower module~vkf_text vkf_text module~vkf_frames->module~vkf_text module~vkf_trajectory vkf_trajectory module~vkf_frames->module~vkf_trajectory module~vkf_geometry->iso_c_binding module~vkf_geometry->module~vkf_layer module~vkf_geometry->module~vkf_math module~vkf_layer->iso_c_binding iso_fortran_env iso_fortran_env module~vkf_math->iso_fortran_env module~vkf_pick->module~vkf_math module~vkf_follower->module~vkf_math module~vkf_follower->module~vkf_trajectory module~vkf_text->iso_c_binding module~vkf_text->module~vkf_files module~vkf_text->module~vkf_layer module~vkf_text->module~vkf_math module~vkf_trajectory->iso_c_binding module~vkf_trajectory->module~vkf_math module~vkf_trajectory->iso_fortran_env

Used by

  • module~~vkf_sphere~~UsedByGraph module~vkf_sphere vkf_sphere module~vkf_shadow vkf_shadow module~vkf_shadow->module~vkf_sphere module~vkframes vkframes module~vkframes->module~vkf_sphere module~vkframes->module~vkf_shadow

Variables

Type Visibility Attributes Name Initial
integer, private, parameter :: lod_first = 3

the index of the mesh built at once (128 segments)

integer, private, parameter :: lod_segments(6) = [32, 64, 128, 256, 512, 1024]

The level-of-detail meshes: segments around the equator (half as many from pole to pole); the one built at once.


Interfaces

public interface Sphere

The Sphere constructor: Sphere(...) makes one (see new_sphere for its arguments).

  • private function new_sphere(name, radius, color) result(s)

    A sphere named name, of radius radius (default 1) and color color ([r, g, b] or [r, g, b, a]; default white, 90% opaque).

    Arguments

    Type IntentOptional Attributes Name
    character(len=*), intent(in) :: name

    the frame's name

    real(kind=wp), intent(in), optional :: radius

    scene units (default 1)

    real(kind=wp), intent(in), optional :: color(:)

    [r, g, b] or [r, g, b, a] (0 to 1)

    Return Value type(Sphere)


Derived Types

type, public, extends(ReferenceFrame) ::  Sphere

A sphere or ellipsoid (see the module documentation).

Components

Type Visibility Attributes Name Initial
real(kind=wp), private :: ambient_(4) = 1.0_wp

ambient color [r, g, b, a]

logical, private :: auto_lod_ = .true.

level of detail (default on)

real(kind=wp), private :: built_radii(3) = 1.0_wp

the mesh's semi-axes

real(kind=wp), private :: diffuse_(4) = 1.0_wp

diffuse [r, g, b, a] (times the color if no texture)

real(kind=wp), private :: emission_(4) = [0.0_wp, 0.0_wp, 0.0_wp, 1.0_wp]

emission color [r, g, b, a]

type(c_ptr), private :: image = c_null_ptr

the textures, for meshes built later

type(c_ptr), private :: lod_mesh(size(lod_segments)) = c_null_ptr

the level-of-detail meshes (null: not built yet)

type(c_ptr), private :: lod_node = c_null_ptr

chooses among the meshes, per view

type(c_ptr), private :: mesh = c_null_ptr

without level of detail

integer, private :: n_lat = 64

without level of detail

integer, private :: n_lon = 128

without level of detail

type(c_ptr), private :: night = c_null_ptr

the textures, for meshes built later

character(len=:), private, allocatable :: night_texture

night texture file (unallocated or '': none)

real(kind=wp), private :: opacity_ = 1.0_wp

1 opaque; below 1 translucent (see set_opacity)

real(kind=wp), private :: radius_ = 1.0_wp

radius (scene units; default 1)

real(kind=wp), private :: scale_(3) = 1.0_wp

scale along x, y and z: semi-axes radius * scale

real(kind=wp), private :: shininess_ = 0.0_wp

0 to 128 (0: no specular highlight)

logical, private :: shown = .false.

(meshes built later are compiled)

real(kind=wp), private :: specular_(4) = [0.0_wp, 0.0_wp, 0.0_wp, 1.0_wp]

specular color [r, g, b, a]

real(kind=wp), private :: sphere_attitude_(4) = quat_identity

the body's attitude in the frame ([x, y, z, w])

type(c_ptr), private :: sphere_node = c_null_ptr

transform of the body within the frame

real(kind=wp), private :: sphere_position_(3) = 0.0_wp

the body's center in the frame (scene units)

character(len=:), private, allocatable :: texture

texture file (unallocated or '': none)

logical, private :: textured = .false.

(the color is not used)

logical, private :: translucent = .false.

built translucent (opacity below 1 when first shown)

real(kind=wp), private :: twilight_ = 0.0_wp

radians below the horizon (0: none)

Constructor

The Sphere constructor: Sphere(...) makes one (see new_sphere for its arguments).

private function new_sphere (name, radius, color)

A sphere named name, of radius radius (default 1) and color color ([r, g, b] or [r, g, b, a]; default white, 90% opaque).

Type-Bound Procedures

procedure, public :: add_child
procedure, public :: attitude
procedure, public :: auto_lod
procedure, public :: axes_labels_shown
procedure, public :: axes_shown
procedure, public :: axis_label
procedure, public :: bound => sphere_bound
procedure, public :: build_contents => sphere_build_contents
procedure, public :: child
procedure, public :: child_index
procedure, public :: color
procedure, public :: contents_shown
procedure, public :: detach
procedure, public :: follow
procedure, public :: follow_frame
procedure, public :: follower
procedure, public :: frame_info => sphere_frame_info
procedure, public :: frame_string
procedure, public :: has_light_source
procedure, public :: is_following
procedure, public :: label_alignment
procedure, public :: label_font
procedure, public :: label_size
procedure, public :: late_update
procedure, public :: light_ambient
procedure, public :: light_diffuse
procedure, public :: light_source_enabled
procedure, public :: light_specular
procedure, public :: local_matrix
procedure, public :: local_matrix_at
procedure, public :: material
procedure, public :: motion_key
procedure, public :: move_x_axis
procedure, public :: move_y_axis
procedure, public :: move_z_axis
procedure, public :: name
procedure, public :: name_label_on_top
procedure, public :: name_label_shown
procedure, public :: night_texture_map
procedure, public :: node
procedure, public :: num_children
procedure, public :: num_lod_meshes
procedure, public :: num_parents
procedure, public :: opacity
procedure, public :: parent
procedure, public :: parent_index
procedure, public :: pick => sphere_pick
procedure, public :: pickable
procedure, public :: position
procedure, public :: position_of
procedure, public :: radii
procedure, public :: radius
procedure, public :: realize
procedure, public :: remove_child
procedure, public :: reposition_axes
procedure, public :: set_attitude
procedure, public :: set_auto_lod
procedure, public :: set_color => sphere_set_color
procedure, public :: set_label_alignment
procedure, public :: set_label_font
procedure, public :: set_label_size
procedure, public :: set_light_ambient
procedure, public :: set_light_diffuse
procedure, public :: set_light_source_enabled
procedure, public :: set_light_specular
procedure, public :: set_material
procedure, public :: set_name
procedure, public :: set_name_label_on_top
procedure, public :: set_night_texture_map
procedure, public :: set_opacity
procedure, public :: set_pickable
procedure, public :: set_position
procedure, public :: set_radius
procedure, public :: set_resolution
procedure, public :: set_sphere_attitude
procedure, public :: set_sphere_position
procedure, public :: set_sphere_scale
procedure, public :: set_texture_map
procedure, public :: set_twilight
procedure, public :: set_x_label
procedure, public :: set_y_label
procedure, public :: set_z_label
procedure, public :: show_axes
procedure, public :: show_axes_labels
procedure, public :: show_contents
procedure, public :: show_decorations
procedure, public :: show_name_label
procedure, public :: sphere_attitude
procedure, public :: sphere_position
procedure, public :: sphere_scale
procedure, public :: sync
procedure, public :: texture_map
procedure, public :: twilight
procedure, public :: unfollow
procedure, public :: update => sphere_update
procedure, public :: world_matrix
procedure, public :: world_matrix_at

Functions

private pure function auto_lod(self)

Whether level of detail is on.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value logical

private function new_sphere(name, radius, color) result(s)

A sphere named name, of radius radius (default 1) and color color ([r, g, b] or [r, g, b, a]; default white, 90% opaque).

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: name

the frame's name

real(kind=wp), intent(in), optional :: radius

scene units (default 1)

real(kind=wp), intent(in), optional :: color(:)

[r, g, b] or [r, g, b, a] (0 to 1)

Return Value type(Sphere)

private function night_texture_map(self) result(file)

The night texture file ('' for none).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value character(len=:), allocatable

private function num_lod_meshes(self) result(n)

Number of level-of-detail meshes built so far (0 without level of detail).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value integer

private pure function opacity(self)

The body's opacity (set_opacity).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value real(kind=wp)

private pure function radii(self) result(r)

The semi-axes: radius * sphere_scale.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value real(kind=wp), (3)

private pure function radius(self)

The sphere's radius (scene units).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value real(kind=wp)

private function read_texture(self, file) result(image)

An image handle for texture file file (null if none or unreadable).

Arguments

Type IntentOptional Attributes Name
type(Sphere), intent(in) :: self
character(len=:), intent(in), allocatable :: file

found with find_data_file (unallocated or '': none)

Return Value type(c_ptr)

private pure function sphere_attitude(self) result(q)

Attitude of the body in its frame (quaternion [x, y, z, w]).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value real(kind=wp), (4)

private function sphere_frame_info(self) result(info)

What kind of frame this is: 'Sphere'.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value character(len=:), allocatable

private pure function sphere_position(self) result(p)

Position of the body's center in its frame (scene units).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value real(kind=wp), (3)

private pure function sphere_scale(self) result(s)

The scale along the sphere's x, y and z axes.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value real(kind=wp), (3)

private function texture_map(self) result(file)

The texture file ('' for none).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value character(len=:), allocatable

private pure function twilight(self)

The twilight angle (radians below the horizon; 0: none).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self

Return Value real(kind=wp)


Subroutines

private subroutine apply_material(self)

The material, with the diffuse color times the body's color (without a texture), and the twilight, on every mesh built.

Arguments

Type IntentOptional Attributes Name
type(Sphere), intent(inout) :: self

private subroutine apply_material_to(self, mesh)

The material, with the diffuse color times the body's color (without a texture), and the twilight, on mesh mesh (if not null).

Arguments

Type IntentOptional Attributes Name
type(Sphere), intent(in) :: self
type(c_ptr), intent(in) :: mesh

a mesh handle (null: nothing done)

private subroutine build_lod_mesh(self, k, compile)

Build level-of-detail mesh k (lod_segments(k) segments around) and add it to the level-of-detail node (compiled for the windows if compile).

Arguments

Type IntentOptional Attributes Name
type(Sphere), intent(inout) :: self
integer, intent(in) :: k

index into lod_segments

logical, intent(in) :: compile

true: compile it now (the sphere is shown)

private pure subroutine material(self, ambient, diffuse, specular, emission, shininess)

The material (each optional): ambient, diffuse, specular and emission colors and shininess.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self
real(kind=wp), intent(out), optional :: ambient(4)

[r, g, b, a]

real(kind=wp), intent(out), optional :: diffuse(4)

[r, g, b, a]

real(kind=wp), intent(out), optional :: specular(4)

[r, g, b, a]

real(kind=wp), intent(out), optional :: emission(4)

[r, g, b, a]

real(kind=wp), intent(out), optional :: shininess

0 to 128

private subroutine set_auto_lod(self, lod)

Level of detail (default on; see the module documentation): meshes of several resolutions, the one drawn chosen per view. Off: one mesh of set_resolution's segments. Set it before a window shows the sphere.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
logical, intent(in) :: lod

true: level of detail; false: one mesh

private subroutine set_material(self, ambient, diffuse, specular, emission, shininess)

The material (OpenFrames' setMaterial; each optional): ambient, diffuse, specular and emission colors ([r, g, b] or [r, g, b, a], 0 to 1) and shininess (0 to 128: the specular highlight's sharpness; 0 for none). The ambient and diffuse colors scale the body's color or texture (VSG's Phong); the specular color is reflected from the lights' specular parts. Defaults: ambient and diffuse white, no specular reflection or emission.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
real(kind=wp), intent(in), optional :: ambient(:)

[r, g, b(, a)], 0 to 1

real(kind=wp), intent(in), optional :: diffuse(:)

[r, g, b(, a)], 0 to 1

real(kind=wp), intent(in), optional :: specular(:)

[r, g, b(, a)], 0 to 1

real(kind=wp), intent(in), optional :: emission(:)

[r, g, b(, a)], 0 to 1

real(kind=wp), intent(in), optional :: shininess

0 to 128 (< 0: 0)

private subroutine set_night_texture_map(self, file)

The texture for the side away from the light (e.g. city lights; an equirectangular image file as the texture, '' for none), shown where the diffuse light is weak.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
character(len=*), intent(in) :: file

found with find_data_file; '' for none

private subroutine set_opacity(self, opacity)

The body's opacity, 0 (invisible) to 1 (opaque, the default): below 1 it is drawn translucent (see the module documentation). Set below 1 before a window first shows it to make it translucent; then the opacity can change at any time (a translucent body stays translucent, an opaque one opaque).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
real(kind=wp), intent(in) :: opacity

0 to 1

private subroutine set_radius(self, radius)

The sphere's radius (scene units, > 0; default 1); can change at any time.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
real(kind=wp), intent(in) :: radius

scene units (<= 0: ignored)

private subroutine set_resolution(self, n_lon, n_lat)

The mesh resolution without level of detail: segments in longitude and latitude (default 128 x 64).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
integer, intent(in) :: n_lon

segments in longitude (at least 3)

integer, intent(in) :: n_lat

segments in latitude (at least 2)

private subroutine set_sphere_attitude(self, q)

Attitude of the body in its frame (quaternion [x, y, z, w]), e.g. to orient its texture.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
real(kind=wp), intent(in) :: q(4)

quaternion [x, y, z, w] (normalized here)

private subroutine set_sphere_position(self, position)

Position of the body's center in its frame.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
real(kind=wp), intent(in) :: position(3)

scene units

private subroutine set_sphere_scale(self, scale)

Scale the sphere along its x, y and z axes (all > 0), making an ellipsoid with semi-axes radius * scale.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
real(kind=wp), intent(in) :: scale(3)

along x, y and z (all > 0, else ignored)

private subroutine set_texture_map(self, file)

The texture: an equirectangular image file ('' for none).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
character(len=*), intent(in) :: file

found with find_data_file; '' for none

private subroutine set_twilight(self, angle)

The twilight: the diffuse light extended past the terminator to where the light is angle (radians, 0 to 1.5) below the horizon, fading out smoothly (where it meets the light on the day side: the same brightness and slope, so no line shows), and the night texture fading in across it. 0 (the default): none, the light ends at the terminator (an airless body). Not in OpenFrames. Can change at any time.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
real(kind=wp), intent(in) :: angle

radians below the horizon (clamped to 0 to 1.5)

private subroutine sphere_bound(self, center, radius)

The body's bounding sphere: its center, and its largest semi-axis.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in) :: self
real(kind=wp), intent(out) :: center(3)

the bounding sphere, frame coordinates (scene units)

real(kind=wp), intent(out) :: radius

the bounding sphere, frame coordinates (scene units)

private subroutine sphere_build_contents(self, viewer, group)

The body: an ellipsoid mesh under the sphere's transform.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
type(c_ptr), intent(in) :: viewer

a window's viewer (null: headless)

type(c_ptr), intent(in) :: group

the frame's contents group

private subroutine sphere_pick(self, cam, to_root, hits, n)

Picked on the ellipsoid (exact), with the geodetic latitude and longitude of the point hit (in the body's axes: sphere_attitude); else the frame's origin.

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(in), target :: self
type(PickCamera), intent(in) :: cam

the camera and cursor of the pick

real(kind=wp), intent(in) :: to_root(4,4)

the frame's transform to the root frame

type(PickHit), intent(inout), allocatable :: hits(:)

hits so far, in hits(1:n); added to

integer, intent(inout) :: n

number of hits

private subroutine sphere_set_color(self, color)

The body's color (used without a texture); [r, g, b] or [r, g, b, a].

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout) :: self
real(kind=wp), intent(in) :: color(:)

[r, g, b] or [r, g, b, a] (0 to 1)

private recursive subroutine sphere_update(self, t)

Update the frame (followed trajectories, children) and, with level of detail, build the mesh the views have wanted if it isn't built yet (the coarsest with as many segments as wanted, or the finest).

Arguments

Type IntentOptional Attributes Name
class(Sphere), intent(inout), target :: self
real(kind=wp), intent(in) :: t

the scene time

private subroutine update_sphere_transform(self)

The body's transform: its position, attitude and scale (radii / the built radii); nothing before it is built.

Arguments

Type IntentOptional Attributes Name
type(Sphere), intent(inout) :: self