Skip to content

Mesh Descriptor

MeshDesc is a descriptor type for adding 3D mesh objects to the scene. It can display various 3D objects.

All mesh descriptors inherit from MeshDesc, which provides common properties such as position, rotation, scale, matrix, matrixWorld, geodetic, and pickable. See the MeshDesc page for details on transform composition, picking, and coordinate transformation.

The following MeshDescriptor types are available in navara_three:

Descriptor TypeDescription
ArclineMeshDescA Descriptor that draws arc-shaped lines connecting two points
BoxMeshDescA Descriptor that draws box geometry
InstancedBoxMeshDescA GPU-instanced Descriptor that renders multiple boxes in a single draw call
CylinderMeshDescA Descriptor that draws cylinder geometry
InstancedCylinderMeshDescA GPU-instanced Descriptor that renders multiple cylinders in a single draw call
GLTFModelDescA Descriptor that loads and displays GLTF/GLB format 3D models
InstancedGltfModelMeshDescA GPU-instanced Descriptor that renders multiple copies of a GLTF/GLB model
GlowGlobeMeshDescA Descriptor that displays a Fresnel-effect glow around the globe
PlaneMeshDescA Descriptor that draws plane geometry
InstancedPlaneMeshDescA GPU-instanced Descriptor that renders multiple planes in a single draw call
RainMeshDescA Descriptor that displays rain particle effects
SkyBoxMeshDescA Descriptor that draws a simple skybox
SkyMeshDescA Descriptor that draws the sky, sun, and moon using atmospheric scattering
SmoothLineMeshDescA Descriptor that draws smooth lines using Catmull-Rom curves
SnowMeshDescA Descriptor that displays snow particle effects
SphereMeshDescA Descriptor that draws sphere geometry
SplatMeshDescA Descriptor that renders 3D Gaussian Splat assets via SparkJS
InstancedSphereMeshDescA GPU-instanced Descriptor that renders multiple spheres in a single draw call
StarsDescA Descriptor that draws a starry sky
TubeMeshDescA Descriptor that draws tube geometry
AxesHelperDescA debug helper Descriptor that visualizes the 3 axes
ArrowHelperDescA debug helper Descriptor that visualizes vector directions

A mesh descriptor is added by registering the descriptor class and then calling the view.addMesh() method:

import ThreeView, { Color } from "@navaramap/three";
import { BoxMeshDesc } from "@navaramap/three-default-descs";
const view = new ThreeView();
// Register the descriptor class
view.registerMesh("box", BoxMeshDesc);
await view.init();
// Add a BoxMeshDesc at a longitude / latitude (degrees) and height (meters)
const boxDesc = view.addMesh<BoxMeshDesc>({
box: {
width: 100,
height: 100,
depth: 100,
color: new Color().setHex(0xff0000),
},
geodetic: { lng: 139.767125, lat: 35.681236, height: 1000 },
});

All Mesh Descriptors have the following basic settings:

PropertyTypeDefaultDescription
idstringAuto-generatedUnique identifier for the object
visiblebooleantrueToggle visibility of the object
geodeticGeodeticPlacement-Geographic placement: lng / lat in degrees, height in meters, plus heading / pitch / roll / scale / heightReference. See Geographic Placement
position{ x: number, y: number, z: number }-Position of the mesh (ECEF coordinate system)
rotation{ x: number, y: number, z: number }-Rotation of the mesh (Euler angles, radians)
scale{ x: number, y: number, z: number }-Scale of the mesh

To place a mesh at a longitude / latitude you normally do not need any conversion: set the geodetic property instead, as in the example above (see Geographic Placement). The functions below are the low-level layer for working with ECEF coordinates directly.

The position property of MeshDesc uses the ECEF (Earth-Centered, Earth-Fixed) coordinate system. To convert from latitude/longitude/altitude (geodetic coordinates) to the ECEF coordinate system, use the geodeticToVector3() function.

import ThreeView, {
Color,
geodeticToVector3,
} from "@navaramap/three";
import { SphereMeshDesc } from "@navaramap/three-default-descs";
const view = new ThreeView();
view.registerMesh("sphere", SphereMeshDesc);
await view.init();
// Convert from latitude/longitude/altitude to ECEF coordinates
const position = geodeticToVector3({
lat: 35.681236, // Latitude (degrees)
lng: 139.767125, // Longitude (degrees)
height: 200, // Altitude (meters)
});
// Add a mesh descriptor with the converted coordinates
const sphereDesc = view.addMesh<SphereMeshDesc>({
sphere: {
radius: 100,
color: new Color().setHex(0x00aaff),
},
position: {
x: position.x,
y: position.y,
z: position.z,
},
});

geodetic builds the surface-aligned frame for you: the mesh stands upright at the given longitude / latitude, and heading turns the asset’s front (glTF +Z) clockwise from north. An unmodified glTF asset needs no up-axis correction.

import { GLTFModelDesc } from "@navaramap/three-default-descs";
// GLTFModelDesc must be registered
// Place the model upright on the Earth's surface, facing north-east
const modelDesc = view.addMesh<GLTFModelDesc>({
gltfModel: {
url: "/models/building.gltf",
},
geodetic: { lng: 139.767125, lat: 35.681236, heading: 45 },
});

For frames geodetic does not build (ENU, NED and others), compose a matrixWorld with the tangent-frame helpers.

Using ENU (East-North-Up) Coordinate System

Section titled “Using ENU (East-North-Up) Coordinate System”

To place meshes using a local coordinate system (ENU: East-North-Up), use eastNorthUpToFixedFrame().

import {
geodeticToVector3,
eastNorthUpToFixedFrame,
} from "@navaramap/three";
import { Vector3 } from "three";
const position = geodeticToVector3({
lat: 35.681236,
lng: 139.767125,
height: 0,
});
// Get the ENU transformation matrix
const enuMatrix = eastNorthUpToFixedFrame(position);
// Extract east and north direction vectors from the ENU matrix
const east = new Vector3().setFromMatrixColumn(enuMatrix, 0).normalize();
const north = new Vector3().setFromMatrixColumn(enuMatrix, 1).normalize();
// Compute a position 100m to the east
const offsetPosition = position.clone().add(east.multiplyScalar(100));

Reverse Conversion from ECEF to Geodetic Coordinates

Section titled “Reverse Conversion from ECEF to Geodetic Coordinates”

To convert back from ECEF coordinates to latitude/longitude/altitude, use vector3ToGeodetic().

import { vector3ToGeodetic } from "@navaramap/three";
// Get the current position of the mesh
const worldPosition = meshDesc.ref.getWorldPosition();
// Convert from ECEF to geodetic coordinates (degrees)
const geodetic = vector3ToGeodetic(worldPosition);
const latitude = geodetic.lat;
const longitude = geodetic.lng;
const height = geodetic.height;
console.log(`Latitude: ${latitude}°, Longitude: ${longitude}°, Altitude: ${height}m`);
FunctionDescription
geodeticToVector3()Converts geodetic coordinates (latitude/longitude/altitude) to ECEF coordinates (Vector3)
vector3ToGeodetic()Converts ECEF coordinates (Vector3) to geodetic coordinates
degreeToRadian()Converts degrees to radians
radianToDegree()Converts radians to degrees
geodeticSurfaceNormal()Gets the Earth’s surface normal vector at the specified position
eastNorthUpToFixedFrame()Gets the transformation matrix to the ENU coordinate system

For details, see navara_three_api.

For detailed usage, refer to the documentation for each descriptor type.