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