Skip to content

3D Geometry

Overview

M2ArGeometry is the sealed base class for all 3D primitives rendered in world space. It implements IM2Transformable4x4 for full 3D matrix transforms.

Geometry Types

Class Object Type Description
M2ArMesh Triangle mesh Textured or solid-color triangle mesh (OBJ models, custom shapes)
M2ArLines Line segments 3D wireframe lines
M2ArPoints Point cloud Individual points in 3D space

M2ArMesh

The primary 3D drawable - a triangle mesh with optional UV texture mapping.

Creating a Mesh

// From raw vertex positions and indices
val vertices = floatArrayOf(
    0f, 0f, 0f,    // vertex 0
    1f, 0f, 0f,    // vertex 1
    0.5f, 1f, 0f   // vertex 2
)
val indices = intArrayOf(0, 1, 2)
val mesh = M2ArMesh(vertices, indices)

Textured Mesh

// With UV coordinates and an image texture
val uvs = floatArrayOf(
    0f, 0f,    // vertex 0 UV
    1f, 0f,    // vertex 1 UV
    0.5f, 1f   // vertex 2 UV
)
val mesh = M2ArMesh(vertices, indices, uvs, myImageResource)

Using M2Vertex

val verts = arrayOf(
    M2Vertex(0f, 0f, 0f, u = 0f, v = 0f),
    M2Vertex(1f, 0f, 0f, u = 1f, v = 0f),
    M2Vertex(0.5f, 1f, 0f, u = 0.5f, v = 1f)
)
val mesh = M2ArMesh(verts, indices)

3D Transforms

All M2ArGeometry subclasses support full 4x4 transforms:

// Translate in world space (ENU)
mesh.translate(east = 1f, north = 0f, up = 0.5f)

// Rotate around the object's own position
mesh.rotateLocal(angleDegrees = 90f, axis = floatArrayOf(0f, 0f, 1f))

// Rotate around the world origin
mesh.rotateWorld(angleDegrees = 45f, axis = floatArrayOf(0f, 1f, 0f))

// Scale uniformly
mesh.scale(factor = 2f)

// Orient as a billboard facing the user
mesh.asBillboard(hDeg = 30f, vDeg = 10f, distance = 5f, scale = 1f)

Animated Transforms

// Animate translation to a target position
mesh.translateToWithAnimation(
    to = floatArrayOf(2f, 3f, 1f),
    duration = 1000L
) {
    // onFinished callback
}

// Animate to the user's current eye position
mesh.translateToEyePositionWithAnimation(
    duration = 800L,
    distance = 3f,
    quaternion = currentQuaternion
) {
    // onFinished
}

Lighting

Apply Lambert shading to meshes using M2ArLight:

val light = M2ArLight(east = 0f, north = 0f, up = 10f)

// Apply to a single mesh
mesh.setLightSource(light)

// Or apply to all meshes in a scene
arScene.setLightSource(light)

M2ArLines and M2ArPoints

// 3D line segments
val linePoints = floatArrayOf(
    0f, 0f, 0f,   1f, 1f, 1f,   // line 1
    1f, 1f, 1f,   2f, 0f, 0f    // line 2
)
val lines = M2ArLines(linePoints, intArrayOf(0, 1, 2, 3))
lines.setStyle(penThickness = 3f, penShape = PenShape.Round)

// 3D point cloud
val points = M2ArPoints(pointPositions, pointIndices)
points.setStyle(penThickness = 5f, penShape = PenShape.Round)

Hit Testing

M2ArMesh supports three hit testing strategies:

Strategy Description
Bounding sphere Fast approximate test
AABB Axis-aligned bounding box
Per-triangle Exact Moller-Trumbore ray-triangle intersection with back-face culling
// Fast bounding sphere test
val hit = mesh.hitTest(rayDirection, HitTestType.BoundingSphere)

// Exact per-triangle test
val hit = mesh.triangleHitTest(rayDirection)

Loading OBJ Files

Use M2ArFactory3D to load Wavefront OBJ models:

// Load OBJ with material (MTL) file
val scene = M2ArFactory3D.fromObjFile("model.obj")

// Load OBJ with PNG texture from a directory
val meshes = M2ArFactory3D.fromObjFileSimple("models/myModel")

See OBJ File for loading OBJ models.

Ready-Made Primitives

M2ArFactory3D provides factory methods for common shapes:

val cube = M2ArFactory3D.makeCube()
val arrow = M2ArFactory3D.makeArrow()
val texturedCube = M2ArFactory3D.texturedCube(myImageResource)

See Also

  • ArScreen - Screen base class for AR content
  • AR Panels - HUD-style content in world space
  • OBJ File - Import Wavefront OBJ models