Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Essentials

SIK Physics Gesture Module Animation Raycast

essentials

Overview

This project is a comprehensive collection of foundational concepts and examples for creating lenses in Lens Studio and deploying them on Spectacles using Typescript and Javascript. We strongly recommend the use of Typescript as it is easier to debug and more in line with existing game engines patterns. Each folder contains specific examples and demonstrations that showcase various aspects of lens development and AR interaction.

NOTE: This project will only work for the Spectacles platform. This projects include a comprehensive collection of foundational concepts and examples for creating lenses! Take advantage of this project providing it as LLM Context for your personal projects!

Design Guidelines

Designing Lenses for Spectacles offers all-new possibilities to rethink user interaction with digital spaces and the physical world. Get started using our Design Guidelines

Prerequisites

  • Lens Studio: v5.15.0+
  • Spectacles OS Version: v5.64+
  • Spectacles App iOS: v0.64+
  • Spectacles App Android: v0.64+

To update your Spectacles device and mobile app, please refer to this guide.

You can download the latest version of Lens Studio from here.

The camera feature requires you to use Experimental APIs. Please see Experimental APIs for more details here.

Extended Permissions mode on device must be enabled for enabling some of the Spectacles APIs. Please see Extended Permissions for more details here.

Getting Started

To obtain the project folder, clone the repository.

IMPORTANT: This project uses Git Large Files Support (LFS). Downloading a zip file using the green button on GitHub will not work. You must clone the project with a version of git that has LFS. You can download Git LFS here.

Initial Project Setup

The project should be pre-configured to get you started without any additional steps. However, if you encounter issues in the Logger Panel, please ensure your Lens Studio environment is set up for Spectacles.

Table of Contents

Project Structure

The project is organized into topic-specific folders. Click on each section to expand and see details:

For example:

essentials-gizmos

Exemples are purposefully made for you to modify them or add them to your projects. They highlight a specific logic or mechanics in a legible way.

essentials-press

AccessComponents

Scripts for accessing and modifying components programmatically:

Component Description
AccessComponentOnSceneObject - AccessComponentOnSceneObjectTS.ts: TypeScript implementation for accessing RenderMeshVisual
- AccessComponentOnSceneObjectJS.js: JavaScript equivalent implementation
AccessComponentOnChildSceneObject - AccessComponentOnChildSceneObjectTS.ts: Traverses SceneObject hierarchy for child components
- AccessComponentOnChildSceneObjectJS.js: JavaScript implementation for child components
AccessCustomComponentsUsingTypename - AccessCustomComponentsUsingTypenameTS.ts: Uses @typename decorator for custom components
- AccessCustomComponentsUsingTypenameJS.js: String-based component type names
AccessCustomComponentsUsingRequired - AccessCustomComponentsUsingRequiredTS.ts: Uses required pattern for component access
- CustomComponentTS.ts/CustomComponentJS.js: Example components to be accessed
Cross-language Component Access - AccessJSfromJS_ComponentA/B.js: JS-to-JS component access
- AccessTSfromTS_TSComponentA/B.ts: TS-to-TS component access
- AccessJSfromTSwithDeclaration_*: JS from TS with type declarations
- AccessJSfromTSwithouthDeclaration_*: JS from TS without declarations
- AccessTSfromJS_*: TS components from JS scripts
Animations

Animation tools and examples:

Component Description
LSTween.ts Powerful tweening library with methods:
- rawTween(): Base tween functionality for custom animations
- alphaTo()/alphaFromTo(): Material transparency animation
- textAlphaTo()/textAlphaFromTo(): Text element fading
- colorTo()/colorFromTo(): Color transitions
- moveOffset()/moveToWorld()/moveFromToWorld(): Position animations
- rotateOffset()/rotateToWorld()/rotateFromToWorld(): Rotation animations
- scaleOffset()/scaleToWorld()/scaleFromToWorld(): Scale animations
- enableChange(): Delayed enable/disable state changes
- shaderColorPropertyFromTo()/shaderFloatPropertyFromTo(): Shader animations
RotationInterpolationType.ts Enum for rotation types:
- LERP: Linear interpolation (faster, less accurate)
- SLERP: Spherical linear interpolation (smoother but more intensive)
HookUpButtonsEvents

Scripts for connecting UI button events to actions:

Component Description
HookUpButtonsEventsTS.ts TypeScript implementation:
- Creating callbacks for button trigger events
- Binding to onInteractorTriggerStart/End events
- Instantiating prefabs on button presses
- Managing object lifecycle with destroyDelay
HookUpButtonsEventsJS.js JavaScript equivalent implementation
HookUpGesturesEvents

Gesture recognition and event binding:

Component Description
HookUpGesturesEventsTS.ts TypeScript implementation:
- Using SIK.HandInputData.getHand() for hand tracking
- Implementing callbacks for hand gestures like pinch
- Moving objects in response to gesture events
- Smooth interpolation for object movement
HookUpGesturesEventsJS.js JavaScript equivalent implementation
Instantiation

Scripts for dynamically creating and destroying objects:

Category Components
Circle-based Instantiation - CircleAreaInstantiatorTS.ts/JS.js: Random objects in circular area
- CirclePerimeterInstantiatorTS.ts/JS.js: Objects around circle perimeter
- CirclePerimeterInstantiatorWithFixedArcLengthTS.ts/JS.js: Consistent spacing
- CircleSlicingInstantiatorTS.ts/JS.js: Objects in circle slices
Line and Grid Instantiation - InstantiateAlongLineTS.ts/JS.js: Objects along a straight line
- InstantiateAlongLineWithFixedDistanceTS.ts/JS.js: Uniform spacing
- InstantiateOn2DGridsTS.ts/JS.js: 2D grid of objects
- InstantiateOn3DGridsTS.ts/JS.js: 3D grid of objects
Random Placement - RandomPointsInsideBoxTS.ts/JS.js: Objects within a 3D box volume
- RandomPointsInsideSphereTS.ts/JS.js: Objects within spherical volume
- RandomPointsOnBoxSurfaceTS.ts/JS.js: Objects on box surface
- RandomPointsOnSphereSurfaceTS.ts/JS.js: Objects on sphere surface
Basic Instantiation - SimpleCircleAreaInstantiatorTS.ts/JS.js: Simplified circle instantiation
- SimpleColliderInstantiatorTS.ts/JS.js: Objects with colliders
- SquareAreaInstantiatorTS.ts/JS.js: Objects in square area
MiniDemos

Small, focused demonstrations:

Demo Description
Archery - ArcheryProjectileManagerTS.ts: Projectile physics for arrows
- TargetCounterTS.ts: Score tracking for arrow hits
- RotateTargetTS.ts: Target rotation for difficulty variation
DirectionShadows - DirectionalWorldQuery.ts: World-aware shadow placement
- ScaleBasedOnDistance.ts: Shadow sizing by distance
- Line.ts: Visualization of projection rays
DotProduct - DotProductDemoTS.ts: Vector math operations
- findDirectionality(): Camera-object direction checking
- exampleCheckIfNeededToRecenter(): View-based repositioning
- Vector utilities (angle, dot, cross, reflect, project)
DragAndDrop - DragAndDrop.ts: Object dragging implementation
- Interactable component integration
- InteractableManipulation event handling
- Physics body modifications
- Visual feedback during manipulation
Basic3DPanel - PanelManagerTS.ts: 3D panel with raycast interaction and scale animations
- Raycasting for intersection detection
- LSTween scale animations on interaction
- Hover state tracking
PreviousNext - PreviousNext.ts: Paginated content navigation
- Event-based navigation controls
- Element visibility management
- Smooth transition animations
RaycastHover - RaycastHover.ts: Hover effects using raycasting
- Collision detection for UI elements
- Visual feedback on hover states
- Interactive UI element implementation
RaycastPainter - RaycastPainterTS.ts: Surface painting with raycasts
- RaycastColorChangerTS.ts: Dynamic material color changes
- Point-based drawing mechanics
- Visual feedback for interaction points
SnapSaber - SnapSaberGlobalManager.ts: Global game state management
- SnapSaberCollisionHandler.ts: Physics-based collision detection
- SnapSaberInstantiator.ts: Dynamic target generation
- Score tracking and game mechanics
Physics-Collision

Physics simulations and collision detection:

Component Description
SoftPressControllerTS.ts/JS.js Physics-based press interaction
- Collision detection for press events
- Physics forces for realistic pressing
- Configurable sensitivity parameters
Raycast

Raycasting implementation and interaction:

Component Description
SimpleRaycastTS.ts Core raycast functionality
- Probe creation for world raycasting
- Intersection detection with colliders
- Ray hit position calculation
- Configurable ray parameters
- Object attachment to hit positions
RuntimeGizmos

Visual tools for runtime object manipulation:

Component Description
Line.ts Line renderer example
ClosedPolyline.ts Line renderer example for closed polyline
Spline.ts Line renderer example for closed Spline
Circle.ts Line renderer example for closed Circles
Snap

Intelligent surface and element snapping functionality:

Component Description
SnapToPlaneTS.ts/JS.js Object placement on planes:
- Automatic calculation of the closest point on a plane
- Configurable snap distance threshold
- Transform-based plane normal calculation
- Support for separate snapping and distance objects
SnapToLineTS.ts/JS.js Object alignment to linear paths:
- Projection-based snapping to line segments
- Point-to-line distance calculations
- Configurable snap distance threshold
- Clamped projection within line segment
Solvers

Positional and behavioral solving mechanisms for AR placement and interaction:

Category Components
Positioning Solvers DirectionalSolver.ts: Position objects along specific directional constraints
- Customizable offset and smoothing parameters
- Constraint-based positioning along defined axes

FollowSolver.ts: Objects following targets with configurable smoothing
- Position and rotation tracking with damping
- Configurable follow speed and deadzone
- Supports both immediate and smooth transitions

LookAtSolver.ts: Objects facing specific targets
- Axis-constrained look direction
- Customizable up vector alignment
- Smooth rotation interpolation

SurfaceSolver.ts: Objects positioned on detected surfaces
- Ground plane detection and alignment
- Normal-based orientation adjustment
- Height offset configuration

RadialSolver.ts: Radial object arrangement patterns
- Circular/spherical distribution around focal points
- Customizable radius and segment count
- Even distribution or weighted placement options
Event-based Solvers SharpTurnTS.ts/JS.js: Detect sharp directional changes
- Position history tracking with configurable frame count
- Dot product calculation for turn detection
- Event callbacks for detected sharp turns
- Minimum vertex distance filtering

DistanceEventsTS.ts/JS.js: Distance threshold event triggers
- Multiple threshold configuration
- Event callbacks for entering/exiting distance ranges
- Percentage-based range events (0-1 scale)
- Dynamic script function invocation via string references

DistanceEventsCallbacks.ts: Example callback implementations
- showElement/hideElement for UI management
- triggerAnimation for distance-based animations
- Custom callback templates for extending functionality
Utility Solvers InBetweenRotationUtilityTS.ts/JS.js: Calculate intermediary rotations
- Slerp-based rotation between two directions
- Forward vector extraction from transforms
- Quaternion-based rotation calculations
- Automated in-between positioning for objects

The solvers package provides composable components for precise object manipulation in AR environments. Each solver is designed to address specific spatial challenges and can be combined for complex behaviors. They follow consistent patterns:

  • Event-driven architecture with clean callback interfaces
  • Configurable parameters exposed through component inputs
  • Both TypeScript and JavaScript implementations for flexibility
  • Extensible design supporting custom event handling

These solvers are particularly useful for creating responsive AR experiences that react to user movement, handle complex spatial relationships, and maintain proper object positioning in dynamically changing environments.

Getting Started

To explore these examples:

  1. Open the project in Lens Studio
  2. Navigate to the specific topic folder you're interested in
  3. Each example is self-contained with its own scripts and scenes
  4. Most examples can be run directly or inspected to understand the implementation

Key Concepts

Click to expand all key concepts
Concept Details
Component Interaction • Direct component access using getComponent()
• Accessing components across language boundaries (TS/JS)
• Custom component type handling with @typename
User Input • Button press detection and handling
• Hand tracking with pinch gestures
• Touch input detection and processing
Physics and Collision • Collision detection between objects
• Physics-based interactions
• Force application and physical responses
Animation • Tweening libraries for smooth motion (LSTween)
• Property animations (color, transparency, size)
• Rotation and position interpolation
Object Instantiation • Prefab instantiation patterns
• Spatial distribution algorithms
• Object lifecycle management
Raycasting • Ray creation and management
• Hit detection and processing
• Dynamic object positioning along rays
Manipulation • Direct manipulation with hand tracking
• Indirect manipulation with ray-based interaction
• Multi-hand scaling and rotation
Snapping Systems • Line snapping for path-based positioning
• Plane snapping for surface placement
• UI element snapping for organized layouts
• World surface snapping with physics

Interaction Patterns

Click to expand all interaction patterns
Pattern Implementation
Selection • Raycast-based selection with visual feedback
• Hover states for interactive elements
• Selection event propagation
Manipulation • Single-handed manipulation for position/rotation
• Two-handed manipulation for scaling
• Constraint-based manipulation (axis locking)
Dragging and Dropping • Physics-aware dragging
• Object placement logic
• Visual feedback during dragging operations
Button Interaction • Button event handling
• Action delegation
• Visual feedback for button states
Gesture Recognition • Hand gesture tracking
• Gesture event processing
• Multi-gesture coordination
Snapping • Element-to-element snapping with "sticky" zones
• World surface placement with grid alignment
• Visual previews during snap operations
• Smooth animation transitions when snapping
Navigation • Previous/next navigation patterns
• Pagination of content
• Scroll view interactions with momentum

Development Patterns

Click to expand all development patterns
Pattern Implementation
Component Communication • Direct component referencing
• Event-based communication
• Dependency injection
• Global manager patterns (SnapSaber example)
Code Organization • TypeScript/JavaScript interoperability
• Module-based structuring
• Interface-driven development
Performance Optimization • Efficient raycast usage
• Event pooling
• Object pooling for instantiation
• Buffered world queries for stability
State Management • Singleton-based global state (via global scope)
• Component-based local state
• Event-driven state changes

Notes

  • These examples demonstrate foundational concepts that can be combined and built upon for more complex lenses
  • Each example is designed to focus on a specific concept for clarity
  • The code follows best practices for Lens Studio development
  • The SpectaclesInteractionKit provides reusable components for common interaction patterns on Spectacles
  • Many demos showcase cross-language compatibility between TypeScript and JavaScript

Materials and Resources

The project includes several material assets (PBR.mat, etc.) and textures that are used throughout the examples. These can be reused in your own projects as needed.

Code Examples

Component Access (TypeScript)
// Accessing a component on the current SceneObject
const visual = this.getComponent("Component.RenderMeshVisual") as RenderMeshVisual;
visual.enabled = false;

// Accessing a component on a child SceneObject using getChild()
const childObj = this.sceneObject.getChild("Button");
const childVisual = childObj.getComponent("Component.RenderMeshVisual") as RenderMeshVisual;
Animation with LSTween
// Import the tweening library
import { LSTween, EasingFunction } from './LSTween';

// Scale animation
LSTween.scaleToWorld(
    this.sceneObject,
    new vec3(1.2, 1.2, 1.2),
    0.5,
    EasingFunction.OutBack
);

// Color transition
const material = this.getComponent("Component.RenderMeshVisual").getMaterial(0);
LSTween.colorTo(
    material,
    "diffuse",
    new vec4(1, 0, 0, 1),
    0.3,
    EasingFunction.Linear
);
Snapping Objects to Planes
// With SnapToPlaneTS component:
// 1. Create a reference plane object
// 2. Configure inputs:
//    - planeTransform: The object defining the plane
//    - snappingObject: The object to snap
//    - snapDistance: How close objects need to be to snap

// Runtime usage of SnapToPlaneTS:
update() {
    // Get positions
    const objectPosition = this.distanceObject.getTransform().getWorldPosition();
    const planePosition = this.planeTransform.getTransform().getWorldPosition();
    
    // Calculate plane normal from transform
    const planeNormal = this.calculatePlaneNormal();
    
    // Find closest point on plane
    const closestPoint = this.getClosestPointOnPlane(objectPosition, planePosition, planeNormal);
    
    // Check distance and snap if close enough
    if (objectPosition.distance(closestPoint) <= this.snapDistance) {
        this.snappingObject.getTransform().setWorldPosition(closestPoint);
    }
}
Hand Gesture Detection
// Get hand tracking data
private leftHand = SIK.HandInputData.getHand("left");

onStart() {
    // Create an event callback for pinch detection
    const onPinchDownCallback = () => {
        // Handle pinch gesture
        this.handlePinchDown();
    };
    
    // Register the callback with the hand tracking system
    this.leftHand.onPinchDown.add(onPinchDownCallback);
}

// Handler for pinch gesture
private handlePinchDown() {
    // Move object, trigger animation, etc.
    const handPosition = this.leftHand.indexTip.position;
    this.moveObjectTo(handPosition);
}

Testing the Lens

In Lens Studio Editor

Check out all of the single SceneObjects 1 by 1 and get what you need.

In Spectacles Device

To install your Lens on your device, refer to the guide provided here.

Support

If you have any questions or need assistance, please don't hesitate to reach out. Our community is here to help, and you can connect with us and ask for support here. We look forward to hearing from you and are excited to assist you on your journey!

Contributing

Feel free to provide improvements or suggestions or directly contributing via merge request. By sharing insights, you help everyone else build better Lenses.


Built with 👻 by the Spectacles team