@ifset html
<A NAME="Solid">
@end ifset
@code{(require 'solid)}
@ifset html
</A>
@end ifset
@ftindex solids
@ftindex solid
@ftindex solid-modeling

@noindent
@uref{http://people.csail.mit.edu/jaffer/Solid/#Example} gives an
example use of this package.


@defun vrml node @dots{}
Returns the VRML97 string (including header) of the concatenation
of strings @var{nodes}, @dots{}.
@end defun


@defun vrml-append node1 node2 @dots{}
Returns the concatenation with interdigitated newlines of
strings @var{node1}, @var{node2}, @dots{}.
@end defun


@defun vrml-to-file file node @dots{}
Writes to file named @var{file} the VRML97 string (including header) of
the concatenation of strings @var{nodes}, @dots{}.
@end defun


@defun world:info title info @dots{}
Returns a VRML97 string setting the title of the file in which
it appears to @var{title}.  Additional strings @var{info}, @dots{} are comments.
@end defun

@noindent

VRML97 strings passed to @code{vrml} and @code{vrml-to-file} as
arguments will appear in the resulting VRML code.  This string turns
off the headlight at the viewpoint:
@example
" NavigationInfo @{headlight FALSE@}"
@end example


@defun scene:panorama front right back left top bottom
Specifies the distant images on the inside faces of the cube
enclosing the virtual world.
@end defun


@defun scene:sphere colors angles


@var{colors} is a list of color objects.  Each may be of type
@ref{Color Data-Type, color}, a 24-bit sRGB integer, or a list of 3
numbers between 0.0 and 1.0.

@var{angles} is a list of non-increasing angles the same length as
@var{colors}.  Each angle is between 90 and -90 degrees.  If 90 or -90 are not
elements of @var{angles}, then the color at the zenith and nadir are taken from
the colors paired with the angles nearest them.

@code{scene:sphere} fills horizontal bands with interpolated colors on the background
sphere encasing the world.
@end defun


@defun scene:sky-and-dirt
Returns a blue and brown background sphere encasing the world.
@end defun


@defun scene:sky-and-grass
Returns a blue and green background sphere encasing the world.
@end defun


@defun scene:sun latitude julian-day hour turbidity strength


@defunx scene:sun latitude julian-day hour turbidity

@var{latitude} is the virtual place's latitude in degrees.  @var{julian-day} is an integer from
0 to 366, the day of the year.  @var{hour} is a real number from 0 to 24 for
the time of day; 12 is noon.  @var{turbidity} is the degree of fogginess described
in @xref{Daylight, turbidity}.

@code{scene:sun} returns a bright yellow, distant sphere where the sun would be at
@var{hour} on @var{julian-day} at @var{latitude}.  If @var{strength} is positive, included is a light source of @var{strength}
(default 1).
@end defun


@defun scene:overcast latitude julian-day hour turbidity strength


@defunx scene:overcast latitude julian-day hour turbidity

@var{latitude} is the virtual place's latitude in degrees.  @var{julian-day} is an integer from
0 to 366, the day of the year.  @var{hour} is a real number from 0 to 24 for
the time of day; 12 is noon.  @var{turbidity} is the degree of cloudiness described
in @xref{Daylight, turbidity}.

@code{scene:overcast} returns an overcast sky as it might look at @var{hour} on @var{julian-day} at @var{latitude}.  If @var{strength}
is positive, included is an ambient light source of @var{strength} (default 1).
@end defun

@noindent
Viewpoints are objects in the virtual world, and can be transformed
individually or with solid objects.


@defun scene:viewpoint name distance compass pitch


@defunx scene:viewpoint name distance compass
Returns a viewpoint named @var{name} facing the origin and placed @var{distance} from it.
@var{compass} is a number from 0 to 360 giving the compass heading.  @var{pitch} is a
number from -90 to 90, defaulting to 0, specifying the angle from the
horizontal.
@end defun


@defun scene:viewpoints proximity
Returns 6 viewpoints, one at the center of each face of a cube
with sides 2 * @var{proximity}, centered on the origin.
@end defun

@subheading Light Sources

@noindent
In VRML97, lights shine only on objects within the same children node
and descendants of that node.  Although it would have been convenient
to let light direction be rotated by @code{solid:rotation}, this
restricts a rotated light's visibility to objects rotated with it.

@noindent
To workaround this limitation, these directional light source
procedures accept either Cartesian or spherical coordinates for
direction.  A spherical coordinate is a list @code{(@var{theta}
@var{azimuth})}; where @var{theta} is the angle in degrees from the
zenith, and @var{azimuth} is the angle in degrees due west of south.

@noindent
It is sometimes useful for light sources to be brighter than @samp{1}.
When @var{intensity} arguments are greater than 1, these functions
gang multiple sources to reach the desired strength.


@defun light:ambient color intensity


@defunx light:ambient color
Ambient light shines on all surfaces with which it is grouped.

@var{color} is a an object of type @ref{Color Data-Type, color}, a 24-bit sRGB
integer, or a list of 3 numbers between 0.0 and 1.0.  If @var{color} is #f,
then the default color will be used.  @var{intensity} is a real non-negative number
defaulting to @samp{1}.

@code{light:ambient} returns a light source or sources of @var{color} with total strength of @var{intensity}
(or 1 if omitted).
@end defun


@defun light:directional color direction intensity


@defunx light:directional color direction

@defunx light:directional color
Directional light shines parallel rays with uniform intensity on all
objects with which it is grouped.

@var{color} is a an object of type @ref{Color Data-Type, color}, a 24-bit sRGB
integer, or a list of 3 numbers between 0.0 and 1.0.  If @var{color} is #f,
then the default color will be used.

@var{direction} must be a list or vector of 2 or 3 numbers specifying the direction
to this light.  If @var{direction} has 2 numbers, then these numbers are the angle
from zenith and the azimuth in degrees; if @var{direction} has 3 numbers, then
these are taken as a Cartesian vector specifying the direction to the
light source.  The default direction is upwards; thus its light will
shine down.

@var{intensity} is a real non-negative number defaulting to @samp{1}.

@code{light:directional} returns a light source or sources of @var{color} with total strength of @var{intensity},
shining from @var{direction}.
@end defun


@defun light:beam attenuation radius aperture peak


@defunx light:beam attenuation radius aperture

@defunx light:beam attenuation radius

@defunx light:beam attenuation

@var{attenuation} is a list or vector of three nonnegative real numbers specifying
the reduction of intensity, the reduction of intensity with distance,
and the reduction of intensity as the square of distance.  @var{radius} is the
distance beyond which the light does not shine.  @var{radius} defaults to
@samp{100}.

@var{aperture} is a real number between 0 and 180, the angle centered on the
light's axis through which it sheds some light.  @var{peak} is a real number
between 0 and 90, the angle of greatest illumination.
@end defun


@defun light:point location color intensity beam


@defunx light:point location color intensity

@defunx light:point location color

@defunx light:point location

Point light radiates from @var{location}, intensity decreasing with distance,
towards all objects with which it is grouped.

@var{color} is a an object of type @ref{Color Data-Type, color}, a 24-bit sRGB
integer, or a list of 3 numbers between 0.0 and 1.0.  If @var{color} is #f,
then the default color will be used.  @var{intensity} is a real non-negative number
defaulting to @samp{1}.  @var{beam} is a structure returned by
@code{light:beam} or #f.

@code{light:point} returns a light source or sources at @var{location} of @var{color} with total strength
@var{intensity} and @var{beam} properties.  Note that the pointlight itself is not visible.
To make it so, place an object with emissive appearance at @var{location}.
@end defun


@defun light:spot location direction color intensity beam


@defunx light:spot location direction color intensity

@defunx light:spot location direction color

@defunx light:spot location direction

@defunx light:spot location

Spot light radiates from @var{location} towards @var{direction}, intensity decreasing with
distance, illuminating objects with which it is grouped.

@var{direction} must be a list or vector of 2 or 3 numbers specifying the direction
to this light.  If @var{direction} has 2 numbers, then these numbers are the angle
from zenith and the azimuth in degrees; if @var{direction} has 3 numbers, then
these are taken as a Cartesian vector specifying the direction to the
light source.  The default direction is upwards; thus its light will
shine down.

@var{color} is a an object of type @ref{Color Data-Type, color}, a 24-bit sRGB
integer, or a list of 3 numbers between 0.0 and 1.0.  If @var{color} is #f,
then the default color will be used.

@var{intensity} is a real non-negative number defaulting to @samp{1}.

@code{light:spot} returns a light source or sources at @var{location} of @var{direction} with total strength
@var{color}.  Note that the spotlight itself is not visible.  To make it so,
place an object with emissive appearance at @var{location}.
@end defun

@subheading Object Primitives


@defun solid:box geometry appearance


@defunx solid:box geometry
@var{geometry} must be a number or a list or vector of three numbers.  If @var{geometry} is a
number, the @code{solid:box} returns a cube with sides of length @var{geometry} centered on the
origin.  Otherwise, @code{solid:box} returns a rectangular box with dimensions @var{geometry}
centered on the origin.  @var{appearance} determines the surface properties of the
returned object.
@end defun


@defun solid:lumber geometry appearance

Returns a box of the specified @var{geometry}, but with the y-axis of a texture
specified in @var{appearance} being applied along the longest dimension in @var{geometry}.
@end defun


@defun solid:cylinder radius height appearance


@defunx solid:cylinder radius height
Returns a right cylinder with dimensions @code{(abs @var{radius})} and @code{(abs @var{height})}
centered on the origin.  If @var{height} is positive, then the cylinder ends
will be capped.  If @var{radius} is negative, then only the ends will appear.
@var{appearance} determines the surface properties of the returned
object.
@end defun


@defun solid:disk radius thickness appearance


@defunx solid:disk radius thickness
@var{thickness} must be a positive real number.  @code{solid:disk} returns a circular disk
with dimensions @var{radius} and @var{thickness} centered on the origin.  @var{appearance} determines the
surface properties of the returned object.
@end defun


@defun solid:cone radius height appearance


@defunx solid:cone radius height
Returns an isosceles cone with dimensions @var{radius} and @var{height} centered on
the origin.  @var{appearance} determines the surface properties of the returned
object.
@end defun


@defun solid:pyramid side height appearance


@defunx solid:pyramid side height
Returns an isosceles pyramid with dimensions @var{side} and @var{height} centered on
the origin.  @var{appearance} determines the surface properties of the returned
object.
@end defun


@defun solid:sphere radius appearance


@defunx solid:sphere radius
Returns a sphere of radius @var{radius} centered on the origin.  @var{appearance} determines
the surface properties of the returned object.
@end defun


@defun solid:ellipsoid geometry appearance


@defunx solid:ellipsoid geometry
@var{geometry} must be a number or a list or vector of three numbers.  If @var{geometry} is a
number, the @code{solid:ellipsoid} returns a sphere of diameter @var{geometry} centered on the origin.
Otherwise, @code{solid:ellipsoid} returns an ellipsoid with diameters @var{geometry} centered on the
origin.  @var{appearance} determines the surface properties of the returned object.
@end defun


@defun solid:polyline coordinates appearance


@defunx solid:polyline coordinates
@var{coordinates} must be a list or vector of coordinate lists or vectors
specifying the x, y, and z coordinates of points.  @code{solid:polyline} returns lines
connecting successive pairs of points.  If called with one argument,
then the polyline will be white.  If @var{appearance} is given, then the polyline
will have its emissive color only; being black if @var{appearance} does not have
an emissive color.

The following code will return a red line between points at
@code{(1 2 3)} and @code{(4 5 6)}:
@example
(solid:polyline '((1 2 3) (4 5 6)) (solid:color #f 0 #f 0 '(1 0 0)))
@end example
@end defun


@defun solid:prism xz-array y appearance


@defunx solid:prism xz-array y
@var{xz-array} must be an @var{n}-by-2 array holding a sequence of coordinates
tracing a non-intersecting clockwise loop in the x-z plane.  @code{solid:prism} will
close the sequence if the first and last coordinates are not the
same.

@code{solid:prism} returns a capped prism @var{y} long.
@end defun


@defun solid:basrelief width height depth colorray appearance


@defunx solid:basrelief width height depth appearance

@defunx solid:basrelief width height depth
One of @var{width}, @var{height}, or @var{depth} must be a 2-dimensional array; the others must
be real numbers giving the length of the basrelief in those
dimensions.  The rest of this description assumes that @var{height} is an
array of heights.

@code{solid:basrelief} returns a @var{width} by @var{depth} basrelief solid with heights per array @var{height} with
the buttom surface centered on the origin.

If present, @var{appearance} determines the surface properties of the returned
object.  If present, @var{colorray} must be an array of objects of type
@ref{Color Data-Type, color}, 24-bit sRGB integers or lists of 3
numbers between 0.0 and 1.0.

If @var{colorray}'s dimensions match @var{height}, then each element of @var{colorray} paints its
corresponding vertex of @var{height}.  If @var{colorray} has all dimensions one smaller
than @var{height}, then each element of @var{colorray} paints the corresponding face of
@var{height}.  Other dimensions for @var{colorray} are in error.
@end defun


@defun solid:text fontstyle str len appearance


@defunx solid:text fontstyle str len

@var{fontstyle} must be a value returned by @code{solid:font}.

@var{str} must be a string or list of strings.

@var{len} must be #f, a nonnegative integer, or list of nonnegative
integers.

@var{appearance}, if given, determines the surface properties of the returned
object.

@code{solid:text} returns a two-sided, flat text object positioned in the Z=0 plane
of the local coordinate system
@end defun

@subheading Surface Attributes


@defun solid:color diffuseColor ambientIntensity specularColor shininess emissiveColor transparency


@defunx solid:color diffuseColor ambientIntensity specularColor shininess emissiveColor

@defunx solid:color diffuseColor ambientIntensity specularColor shininess

@defunx solid:color diffuseColor ambientIntensity specularColor

@defunx solid:color diffuseColor ambientIntensity

@defunx solid:color diffuseColor

Returns an @dfn{appearance}, the optical properties of the objects
@cindex appearance
with which it is associated.  @var{ambientIntensity}, @var{shininess}, and @var{transparency} must be numbers between 0
and 1.  @var{diffuseColor}, @var{specularColor}, and @var{emissiveColor} are objects of type @ref{Color Data-Type, color},
24-bit sRGB integers or lists of 3 numbers between 0.0 and 1.0.
If a color argument is omitted or #f, then the default color will be used.
@end defun


@defun solid:texture image color scale rotation center translation


@defunx solid:texture image color scale rotation center

@defunx solid:texture image color scale rotation

@defunx solid:texture image color scale

@defunx solid:texture image color

@defunx solid:texture image

Returns an @dfn{appearance}, the optical properties of the objects
@cindex appearance
with which it is associated.  @var{image} is a string naming a JPEG or PNG
image resource.  @var{color} is #f, a color, or the string returned by
@code{solid:color}.  The rest of the optional arguments specify
2-dimensional transforms applying to the @var{image}.

@var{scale} must be #f, a number, or list or vector of 2 numbers specifying the
scale to apply to @var{image}.  @var{rotation} must be #f or the number of degrees to
rotate @var{image}.  @var{center} must be #f or a list or vector of 2 numbers specifying
the center of @var{image} relative to the @var{image} dimensions.  @var{translation} must be #f or a
list or vector of 2 numbers specifying the translation to apply to @var{image}.
@end defun


@defun solid:font family style justify size spacing language direction

Returns a fontstyle object suitable for passing as an argument to
@code{solid:text}.  Any of the arguments may be #f, in which case
its default value, which is first in each list of allowed values, is
used.

@var{family} is a case-sensitive string naming a font; @samp{SERIF},
@samp{SANS}, and @samp{TYPEWRITER} are supported at the minimum.

@var{style} is a case-sensitive string @samp{PLAIN}, @samp{BOLD},
@samp{ITALIC}, or @samp{BOLDITALIC}.

@var{justify} is a case-sensitive string @samp{FIRST}, @samp{BEGIN},
@samp{MIDDLE}, or @samp{END}; or a list of one or two case-sensitive
strings (same choices).  The mechanics of @var{justify} get complicated; it is
explained by tables 6.2 to 6.7 of
@url{http://www.web3d.org/x3d/specifications/vrml/ISO-IEC-14772-IS-VRML97WithAmendment1/part1/nodesRef.html#Table6.2}


@var{size} is the extent, in the non-advancing direction, of the text.
@var{size} defaults to 1.

@var{spacing} is the ratio of the line (or column) offset to @var{size}.
@var{spacing} defaults to 1.

@var{language} is the RFC-1766 language name.

@var{direction} is a list of two numbers: @w{@code{(@var{x} @var{y})}}.  If
@w{@code{(> (abs @var{x}) (abs @var{y}))}}, then the text will be
arrayed horizontally; otherwise vertically.  The direction in which
characters are arrayed is determined by the sign of the major axis:
positive @var{x} being left-to-right; positive @var{y} being
top-to-bottom.
@end defun

@subheading Aggregating Objects


@defun solid:center-row-of number solid spacing
Returns a row of @var{number} @var{solid} objects spaced evenly @var{spacing} apart.
@end defun


@defun solid:center-array-of number-a number-b solid spacing-a spacing-b
Returns @var{number-b} rows, @var{spacing-b} apart, of @var{number-a} @var{solid} objects @var{spacing-a} apart.
@end defun


@defun solid:center-pile-of number-a number-b number-c solid spacing-a spacing-b spacing-c
Returns @var{number-c} planes, @var{spacing-c} apart, of @var{number-b} rows, @var{spacing-b} apart, of @var{number-a} @var{solid} objects @var{spacing-a} apart.
@end defun


@defun solid:arrow center

@var{center} must be a list or vector of three numbers.  Returns an upward
pointing metallic arrow centered at @var{center}.


@end defun
@defun solid:arrow
Returns an upward pointing metallic arrow centered at the origin.
@end defun

@subheading Spatial Transformations


@defun solid:translation center solid @dots{}
@var{center} must be a list or vector of three numbers.  @code{solid:translation} Returns an
aggregate of @var{solids}, @dots{} with their origin moved to @var{center}.
@end defun


@defun solid:scale scale solid @dots{}
@var{scale} must be a number or a list or vector of three numbers.  @code{solid:scale}
Returns an aggregate of @var{solids}, @dots{} scaled per @var{scale}.
@end defun


@defun solid:rotation axis angle solid @dots{}
@var{axis} must be a list or vector of three numbers.  @code{solid:rotation} Returns an
aggregate of @var{solids}, @dots{} rotated @var{angle} degrees around the axis @var{axis}.
@end defun

