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).
| 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. |
The Sphere constructor: Sphere(...) makes one (see new_sphere for its
arguments).
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 | Intent | Optional | 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) |
A sphere or ellipsoid (see the module documentation).
| 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) |
The Sphere constructor: Sphere(...) makes one (see new_sphere for its
arguments).
| private function new_sphere (name, radius, color) | A sphere named |
| 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 |
Whether level of detail is on.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
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 | Intent | Optional | 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) |
The night texture file ('' for none).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
Number of level-of-detail meshes built so far (0 without level of detail).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
The body's opacity (set_opacity).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
The semi-axes: radius * sphere_scale.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
The sphere's radius (scene units).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
An image handle for texture file file (null if none or unreadable).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(Sphere), | intent(in) | :: | self | |||
| character(len=:), | intent(in), | allocatable | :: | file |
found with find_data_file (unallocated or '': none) |
Attitude of the body in its frame (quaternion [x, y, z, w]).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
What kind of frame this is: 'Sphere'.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
Position of the body's center in its frame (scene units).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
The scale along the sphere's x, y and z axes.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
The texture file ('' for none).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(in) | :: | self |
The material, with the diffuse color times the body's color (without a texture), and the twilight, on every mesh built.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(Sphere), | intent(inout) | :: | self |
The material, with the diffuse color times the body's color (without a
texture), and the twilight, on mesh mesh (if not null).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(Sphere), | intent(in) | :: | self | |||
| type(c_ptr), | intent(in) | :: | mesh |
a mesh handle (null: nothing done) |
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).
| Type | Intent | Optional | 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) |
The material (each optional): ambient, diffuse, specular and emission colors and shininess.
| Type | Intent | Optional | 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 |
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.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout) | :: | self | |||
| logical, | intent(in) | :: | lod |
true: level of detail; false: one mesh |
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.
| Type | Intent | Optional | 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) |
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.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout) | :: | self | |||
| character(len=*), | intent(in) | :: | file |
found with find_data_file; '' for none |
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).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout) | :: | self | |||
| real(kind=wp), | intent(in) | :: | opacity |
0 to 1 |
The sphere's radius (scene units, > 0; default 1); can change at any time.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout) | :: | self | |||
| real(kind=wp), | intent(in) | :: | radius |
scene units (<= 0: ignored) |
The mesh resolution without level of detail: segments in longitude and latitude (default 128 x 64).
| Type | Intent | Optional | 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) |
Attitude of the body in its frame (quaternion [x, y, z, w]), e.g. to orient its texture.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout) | :: | self | |||
| real(kind=wp), | intent(in) | :: | q(4) |
quaternion [x, y, z, w] (normalized here) |
Position of the body's center in its frame.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout) | :: | self | |||
| real(kind=wp), | intent(in) | :: | position(3) |
scene units |
Scale the sphere along its x, y and z axes (all > 0), making an ellipsoid with semi-axes radius * scale.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout) | :: | self | |||
| real(kind=wp), | intent(in) | :: | scale(3) |
along x, y and z (all > 0, else ignored) |
The texture: an equirectangular image file ('' for none).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout) | :: | self | |||
| character(len=*), | intent(in) | :: | file |
found with find_data_file; '' for none |
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.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout) | :: | self | |||
| real(kind=wp), | intent(in) | :: | angle |
radians below the horizon (clamped to 0 to 1.5) |
The body's bounding sphere: its center, and its largest semi-axis.
| Type | Intent | Optional | 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) |
The body: an ellipsoid mesh under the sphere's transform.
| Type | Intent | Optional | 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 |
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.
| Type | Intent | Optional | 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 |
The body's color (used without a texture); [r, g, b] or [r, g, b, a].
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout) | :: | self | |||
| real(kind=wp), | intent(in) | :: | color(:) |
[r, g, b] or [r, g, b, a] (0 to 1) |
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).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Sphere), | intent(inout), | target | :: | self | ||
| real(kind=wp), | intent(in) | :: | t |
the scene time |
The body's transform: its position, attitude and scale (radii / the built radii); nothing before it is built.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(Sphere), | intent(inout) | :: | self |