This module lets you create object shapes which you can later render with
Scene3d.mesh
or Scene3d.meshWithShadow
by applying a desired material.
IMPORTANT: Mesh
(and Shadow
) values should not be created dynamically
in your view
function, since this is a relatively expensive operation that can
lead to low frame rates or even out-of-memory errors if done repeatedly.
Instead, they should be created only once (in your init
or update
function,
or even as a top-level constant), then stored in your model and reused from
frame to frame.
Note that this does not mean that objects can't move around or change color - you can freely change the material applied to a mesh from frame to frame, and you can use the various provided transformation functions to transform meshes around without having to recreate them.
Scene3d.Types.Mesh coordinates attributes
A Mesh
defines the shape of an object. It consists of a number of
vertices (points that may have additional associated data like normal vectors
and texture coordinates) joined together into triangles or line segments (or
sometimes just displayed as dots).
The two type parameters of the Mesh
type define what coordinate system a mesh
is defined in, and what attributes (in addition to position) are present on each
vertex. For example, a
Mesh WorldCoordinates { normals : () }
refers to a mesh defined in WorldCoordinates
(a type you would typically
define yourself) that has position and normal vector defined at each vertex.
(The ()
type isn't significant; you can think of it as meaning 'present'.)
These type aliases make it easier to write down type annotations for meshes you store in your model or return from a function.
Mesh coordinates {}
A mesh containing vertex positions only.
Mesh coordinates { normals : () }
A mesh with normal vectors at each vertex but no UV (texture) coordinates, meaning that surface appearance will be uniform across the mesh.
Mesh coordinates { uvs : () }
A mesh with UV coordinates at each vertex but no normal vectors (normal vectors are required for any kind of lighting calculation).
Mesh coordinates { normals : ()
, uvs : ()
}
A mesh with both normal vectors and UV coordinates at each vertex, allowing for general-purpose texturing of lit objects.
points : { radius : Quantity Basics.Float Pixels } -> List (Point3d Length.Meters coordinates) -> Plain coordinates
Construct a mesh from a list of points that that will be displayed as separate circular dots, given a particular dot radius in pixels.
lineSegments : List (LineSegment3d Length.Meters coordinates) -> Plain coordinates
Construct a mesh from a list of line segments.
(Note that this particular case, where all the line segments meet end-to-end, could be rendered more efficiently as a polyline).
polyline : Polyline3d Length.Meters coordinates -> Plain coordinates
Construct a mesh from a single polyline.
triangles : List (Triangle3d Length.Meters coordinates) -> Plain coordinates
Construct a plain mesh from a list of triangles.
facets : List (Triangle3d Length.Meters coordinates) -> Uniform coordinates
Construct a mesh from a list of triangles, but generate a normal vector for
each triangle so that matte
and pbr
(materials that react to light) can be used. Note that normal vectors will not
be smoothed, so the resulting mesh will appear to have flat facets,
hence the name.
These functions all use the TriangularMesh
type from the
ianmackenzie/elm-triangular-mesh
package to allow the creation of indexed meshes, where vertices can be shared
between adjacent faces to save on space.
indexedTriangles : TriangularMesh (Point3d Length.Meters coordinates) -> Plain coordinates
Construct a mesh from a TriangularMesh
of plain positions.
indexedFacets : TriangularMesh (Point3d Length.Meters coordinates) -> Uniform coordinates
Construct a mesh from a TriangularMesh
of plain positions, but also
compute a normal vector for each triangle just like with facets
.
indexedFaces : TriangularMesh { position : Point3d Length.Meters coordinates, normal : Vector3d Quantity.Unitless coordinates } -> Uniform coordinates
Construct a mesh from a TriangularMesh
of vertices with positions and
normal vectors.
These functions behave just like their corresponding indexed
versions but
additionally require each vertex to include UV
(texture) coordinates to allow textured materials
to be used.
texturedTriangles : TriangularMesh { position : Point3d Length.Meters coordinates, uv : ( Basics.Float, Basics.Float ) } -> Unlit coordinates
Construct a mesh from a TriangularMesh
of vertices with positions and
texture coordinates.
texturedFacets : TriangularMesh { position : Point3d Length.Meters coordinates, uv : ( Basics.Float, Basics.Float ) } -> Textured coordinates
Construct a mesh from a TriangularMesh
of vertices with positions and
texture coordinates, but additionally compute a normal vector for each triangle.
texturedFaces : TriangularMesh { position : Point3d Length.Meters coordinates, normal : Vector3d Quantity.Unitless coordinates, uv : ( Basics.Float, Basics.Float ) } -> Textured coordinates
Construct a mesh from a TriangularMesh
of vertices with positions, normal
vectors and texture coordinates.
In elm-3d-scene
, to render an object with its shadow you will first need to
construct (and save somewhere) a Shadow
value for that object. You can then
render the object with its shadow using Scene3d.meshWithShadow
.
Scene3d.Types.Shadow coordinates
Represents the shadow of a particular object.
shadow : Mesh coordinates attributes -> Shadow coordinates
Construct a Shadow
value from a given mesh. This is an expensive
operation, so Shadow
values (like Mesh
values) should be stored in your
model (or as top-level constants) instead of constructed dynamically in your
view
function.
cullBackFaces : Mesh coordinates attributes -> Mesh coordinates attributes
Back face culling is a
rendering optimization that cuts down on the number of triangles drawn by not
drawing any triangles that are facing away from the viewer (camera). However,
this only really works if the mesh in question is a closed volume with all faces
having the correct (counterclockwise) winding order.
For example, if render a simple curved surface which might get viewed from
either side, then you wouldn't want to enable back face culling because then the
surface would be invisible from one side! As a result, in elm-3d-scene
back
face culling is disabled by default but you can enable it per-mesh as an
optimization where it is valid.
Note that cullBackFaces
doesn't actually strip out any faces from the mesh,
since which faces are culled depends on the (dynamic) viewing direction - it
simply sets a flag on the mesh that indicates that back face culling should be
performed during rendering.