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, 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
const boxDesc = view.addMesh<BoxMeshDesc>({
box: {
width: 100,
height: 100,
depth: 100,
color: new Color().setHex(0xff0000),
},
position: { x: 0, y: 0, z: 1000 },
});

All Mesh Descriptors have the following basic settings:

PropertyTypeDefaultDescription
idstringAuto-generatedUnique identifier for the object
visiblebooleantrueToggle visibility of the object
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

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,
degreeToRadian,
} 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: degreeToRadian(35.681236), // Latitude (radians)
lng: degreeToRadian(139.767125), // Longitude (radians)
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,
},
});

Setting Rotation Along the Earth’s Surface

Section titled “Setting Rotation Along the Earth’s Surface”

To place a mesh along the Earth’s surface, obtain the surface normal vector using geodeticSurfaceNormal() and compute the rotation.

import {
geodeticToVector3,
geodeticSurfaceNormal,
degreeToRadian,
} from "@navaramap/three";
import { GLTFModelDesc } from "@navaramap/three_default_descs";
import { Vector3, Quaternion, Euler } from "three";
// GLTFModelDesc must be registered
// Compute position
const lat = degreeToRadian(35.681236);
const lng = degreeToRadian(139.767125);
const height = 0;
const position = geodeticToVector3({ lat, lng, height });
// Get the surface normal vector
const normal = geodeticSurfaceNormal({ lat, lng, height });
// Compute rotation to align the Y-axis (up direction) with the normal
const up = new Vector3(0, 1, 0);
const quaternion = new Quaternion().setFromUnitVectors(up, normal);
const euler = new Euler().setFromQuaternion(quaternion);
// Place the model along the Earth's surface
const modelDesc = view.addMesh<GLTFModelDesc>({
gltfModel: {
url: "/models/building.gltf",
},
position: { x: position.x, y: position.y, z: position.z },
rotation: { x: euler.x, y: euler.y, z: euler.z },
});

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,
degreeToRadian,
} from "@navaramap/three";
import { Vector3 } from "three";
const position = geodeticToVector3({
lat: degreeToRadian(35.681236),
lng: degreeToRadian(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() and radianToDegree().

import {
vector3ToGeodetic,
radianToDegree,
} from "@navaramap/three";
// Get the current position of the mesh
const worldPosition = meshDesc.ref.getWorldPosition();
// Convert from ECEF to geodetic coordinates
const geodetic = vector3ToGeodetic(worldPosition);
// Convert from radians to degrees
const latitude = radianToDegree(geodetic.lat);
const longitude = radianToDegree(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.