Skip to content

Latest commit

ย 

History

178 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŒŒ Spatial

Spatial Logo

Spatial Banner

Kotlin Android Compose Architecture Status License

Declarative 3D Rendering for Android inspired by Jetpack Compose

Modern โ€ข Reactive โ€ข Cinematic โ€ข GPU-Abstracted


๐Ÿ“œ License

Spatial is licensed under the PolyForm Shield License 1.0.0.

You may embed Spatial in your own applications โ€” including commercial apps โ€” free of charge, modify it for that purpose, and redistribute it with your application, as long as you keep the required copyright and license notices.

You may not copy, fork, or rebrand this codebase to publish a competing 3D library, SDK, or practical substitute for Spatial, and you may not remove or obscure authorship.

Copyright ยฉ 2024โ€“2026 Daniel Imbert (danielitoCode). See LICENSE and NOTICE for the full terms.


โœจ Vision

Spatial is a modern declarative 3D rendering library for Android inspired by Jetpack Compose.

Its goal is to make 3D scene creation feel as natural and expressive as Compose, while completely hiding the complexity of OpenGL and GPU pipelines from the developer.

For a more detailed explanation: https://deepwiki.com/danielitoCode/Spatial

Spatial is not intended to become a full game engine.

Instead, it focuses on:

  • Declarative scene composition
  • Smooth cinematic motion
  • State-driven rendering
  • Compose-first APIs
  • Natural gestures
  • Modular rendering architecture
  • Clean GPU abstraction

๐ŸŽฏ Core #1 Goals

Core #1 exposes its public Compose API from the root com.elitec.spatial_compose package.

Public consumer entry points

For Pilar 1, application and playground consumers should depend on :spatial-compose as the public facade for scene authoring. Load GLB assets with Element.Model(model = ModelResource.fromRawResource(R.raw.my_model), ...); spatial-compose delegates parsing internally, so consumers should not depend directly on :spatial-geometry unless they are building a dedicated diagnostic parser screen.

Material changes for rendered primitives or GLB models should be expressed through Modifier3D.color(...) for simple flat colors or Modifier3D.material(...) when a caller needs to pass the public material data object. The :spatial-material module is reserved for the material implementation and future texture/shader metadata APIs; apps should add implementation(project(":spatial-material")) only after a deliberate public material API is exposed from that module.


Current status

Core #1 remains In Development. This status must only change when the Core #1 contracts and tests are closed and passing against the real public API. Until then, README badges, phase notes, and release messaging must not describe Core #1 as complete or stable.

Included

  • Essential 3D primitives
  • Orbit camera
  • Smooth zoom
  • Inertia and damping
  • Declarative scene API
  • Basic camera/transform motion system
  • Gesture system
  • Flat-color material rendering (no active lighting/shading in Core #1)
  • Material abstraction
  • Units system
  • GPU abstraction layer
  • Compose integration

Intentionally Excluded

  • Physics
  • ECS
  • PBR
  • Shadows
  • Real lighting and shaded light evaluation
  • Vulkan
  • Skeletal animation
  • Post-processing
  • Advanced animation timelines and clip sequencing
  • Multiplayer systems
  • Editor tooling

๐Ÿšง Over Core #1

These items are explicitly outside the Core #1 scope and must not be pulled into Core #1 API, renderer, or test commitments:

  • PBR
  • Shadows
  • Active lights in shaders
  • Object animation
  • External model loading
  • Advanced picking

Core #1 Lighting Decision

Core #1 keeps lighting as contracts only. LightData exists so scene, light, and future renderer modules can agree on shape, direction, color, and intensity metadata, but Core #1 does not transport lights through the render frame and does not evaluate real lighting in shaders.

The active Core #1 renderer supports flat-color materials: the material color is passed directly to the shader without directional, ambient, point, or physically based light contribution.


๐Ÿง  Core Philosophy

Spatial follows a strict design philosophy:

Declarative

Scenes describe state.


Reactive

State changes update rendering automatically.


Compose-first

Inspired by Compose mental models and APIs.


Cinematic

Motion quality matters more than feature quantity.


Opinionated

Good defaults and minimal boilerplate.


๐Ÿงฉ Core #1 public API

Core #1 exposes its stable public Compose API from the root com.elitec.spatial_compose package. Implementation packages remain split internally, but application code should prefer these root imports.

Public imports

import com.elitec.spatial_compose.CameraState
import com.elitec.spatial_compose.Element
import com.elitec.spatial_compose.GestureSensitivity
import com.elitec.spatial_compose.Gestures
import com.elitec.spatial_compose.Modifier3D
import com.elitec.spatial_compose.MotionSpec
import com.elitec.spatial_compose.Scene
import com.elitec.spatial_compose.SceneGestures
import com.elitec.spatial_compose.rememberCameraState

A real Android render host is supplied by the runtime adapter:

import com.elitec.spatial_compose_runtime_adapter.DefaultSceneRenderHostFactory

Compilable Compose example

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.elitec.spatial_compose.Element
import com.elitec.spatial_compose.Gestures
import com.elitec.spatial_compose.Modifier3D
import com.elitec.spatial_compose.Scene
import com.elitec.spatial_compose_runtime_adapter.DefaultSceneRenderHostFactory
import com.elitec.spatial_units.deg
import com.elitec.spatial_compose.rememberCameraState
import com.elitec.spatial_units.meters

@Composable
fun CoreOneScene() {
    val cameraState = rememberCameraState(
        yaw = 20f.deg,
        pitch = (-12f).deg,
        zoom = 1.25f,
    )
    Scene(
        modifier = Modifier.fillMaxSize(),
        renderHostFactory = DefaultSceneRenderHostFactory,
        cameraState = cameraState,
        gestures = Gestures.orbitAndZoom(),
    ) {
        Element.Cube(
            modifier = Modifier3D.Default
                .size(2f.meters)
                .position(0f.meters, 0f.meters, (-5f).meters),
        )

        Element.Sphere(
            modifier = Modifier3D.Default
                .size(1f.meters)
                .position(3f.meters, 0f.meters, (-8f).meters),
        )
    }
}

๐Ÿ—๏ธ Architecture

Spatial uses a hybrid architecture:

Clean Architecture

Feature First

Rendering-Oriented Pragmatism

The architecture prioritizes:

  • Ownership boundaries
  • Module independence
  • Rendering performance
  • Scalability
  • Low coupling
  • Maintainability

Spatial avoids unnecessary enterprise abstractions such as:

  • Excessive repositories
  • DTO overengineering
  • Artificial use cases
  • Massive inheritance hierarchies

๐Ÿงญ Scene3D Split

The old monolithic Scene3D responsibility is now documented as a thin public facade plus internal feature slices:

  • components/Scene.kt owns the Compose Scene composable, Android view hosting, render-host lifecycle, gesture modifier wiring, scene graph collection, and frame submission.
  • scene/* owns scene graph construction and conversion: SceneBuilder, SceneContentScope, SceneNode, gesture configuration, render host contracts, graph remembering, and renderable-node adapters.
  • modifier/* owns Modifier3D, gesture input modifiers, and conversion from declarative transforms to model matrices.
  • state/* owns CameraState and rememberCameraState.
  • core/Element.kt owns the primitive element facade (Element.Cube, Element.Sphere, and Element.Plane).
  • Scene3D.kt remains the root-package public API facade that re-exports the stable Core #1 symbols from com.elitec.spatial_compose.

๐Ÿ“ฆ Workspace Structure

spatial/
โ”‚
โ”œโ”€โ”€ app/
โ”‚
โ”œโ”€โ”€ spatial-renderer/
โ”œโ”€โ”€ spatial-scene/
โ”œโ”€โ”€ spatial-camera/
โ”œโ”€โ”€ spatial-motion/
โ”œโ”€โ”€ spatial-gesture/
โ”œโ”€โ”€ spatial-material/
โ”œโ”€โ”€ spatial-geometry/
โ”œโ”€โ”€ spatial-light/
โ”œโ”€โ”€ spatial-math/
โ”œโ”€โ”€ spatial-units/
โ”œโ”€โ”€ spatial-compose/
โ””โ”€โ”€ spatial-core/

๐Ÿงฑ Module Responsibilities

app/

Type

Android Application

Purpose

Playground and showcase application.

Used for:

  • Rendering validation
  • Gesture testing
  • Motion tuning
  • FPS monitoring
  • Demo scenes
  • Visual experimentation

spatial-renderer/

Type

Android Library

Purpose

Shared Core #1 motion primitives for basic camera and transform animation.

Responsibilities

  • Basic camera/transform interpolation
  • Shared easing curves
  • Shared camera animation duration planning
  • Runtime/Compose motion parity helpers

Out of scope for Core #1

  • Skeletal animation
  • Advanced keyframe timelines
  • Clip blending and sequencer-style orchestration

Internal Features

renderer/
 โ”œโ”€โ”€ shader/
 โ”œโ”€โ”€ pipeline/
 โ”œโ”€โ”€ buffer/
 โ”œโ”€โ”€ texture/
 โ”œโ”€โ”€ framebuffer/
 โ”œโ”€โ”€ renderloop/
 โ””โ”€โ”€ context/

spatial-scene/

Type

Kotlin Library

Purpose

Scene graph and hierarchical structure.

Responsibilities

  • Node hierarchy
  • Transform propagation
  • Traversal
  • Visibility management
  • Dirty flags
  • Parent-child relationships

spatial-camera/

Type

Kotlin Library

Purpose

Camera behavior and cinematic motion.

Responsibilities

  • Orbit camera
  • Pan
  • Zoom
  • Damping
  • Inertia
  • Smooth transitions
  • Projection systems

Internal Features

camera/
 โ”œโ”€โ”€ orbit/
 โ”œโ”€โ”€ zoom/
 โ”œโ”€โ”€ inertia/
 โ”œโ”€โ”€ interpolation/
 โ””โ”€โ”€ projection/

spatial-motion/

Type

Kotlin Library

Purpose

Animation and motion engine.

Responsibilities

  • Animation timelines
  • Interpolation
  • Spring systems
  • Easing
  • Transitions
  • Motion orchestration

spatial-gesture/

Type

Android Library

Purpose

Touch and gesture input system.

Responsibilities

  • Multi-touch
  • Pinch zoom
  • Orbit gestures
  • Velocity tracking
  • Gesture smoothing
  • MotionEvent handling

spatial-material/

Type

Kotlin Library

Purpose

Material abstraction layer.

Responsibilities

  • Flat-color materials for Core #1
  • Texture materials (future)
  • Shader metadata (future)
  • Material bindings
  • Lighting properties as metadata only; active light evaluation is outside Core #1

spatial-geometry/

Type

Kotlin Library

Purpose

Mesh and primitive generation.

Responsibilities

  • Cube generation
  • Sphere generation
  • Cylinder generation
  • Plane generation
  • Mesh data
  • Normals
  • UV coordinates

spatial-light/

Type

Kotlin Library

Purpose

Lighting models.

Responsibilities

  • Light contracts and helper factories
  • Directional light metadata
  • Light intensity metadata
  • Light direction metadata

Out of scope for Core #1

  • Active lighting in shaders
  • Shaded material evaluation
  • Shadows

spatial-math/

Type

Kotlin Library

Purpose

Pure mathematical foundation.

Responsibilities

  • Vec2
  • Vec3
  • Vec4
  • Quaternion
  • Matrix4
  • Projection math

Important

This module must remain:

  • Lightweight
  • Pure Kotlin
  • Allocation-friendly
  • Dependency-free

spatial-units/

Type

Kotlin Library

Purpose

Consistent spatial units system.

Responsibilities

  • Meters
  • Centimeters
  • Degrees
  • Unit conversions
  • Spatial consistency

Example

1.meters
45.deg
50.cm

spatial-compose/

Type

Android Library

Purpose

Declarative Compose integration layer.

Responsibilities

  • Scene composables
  • Element composables
  • Modifier3D
  • remember states
  • Compose adapters

Important

This module does NOT render directly.

It orchestrates:

  • state
  • composition
  • declarative APIs

spatial-core/

Type

Kotlin Library

Purpose

Core orchestration and public contracts.

Responsibilities

  • Public APIs
  • Module orchestration
  • Shared contracts
  • Engine coordination

๐Ÿ”„ Dependency Direction

Compose
   โ†“
Core
   โ†“
Scene
   โ†“
Renderer

Rules:

  • High-level modules never depend on UI.
  • Renderer never knows Compose.
  • Scene never knows Android.
  • Math remains framework-independent.

๐Ÿงช Development Workflow

Spatial is developed using a parallel playground application.

Recommended workflow

Modify renderer
      โ†“
Run playground
      โ†“
Validate motion
      โ†“
Tune gestures
      โ†“
Refactor APIs
      โ†“
Repeat

๐ŸŽฎ Playground Purpose

The playground app acts as:

  • Rendering sandbox
  • Motion laboratory
  • Camera tuning environment
  • FPS validator
  • Material previewer
  • Demo showcase

๐Ÿงฐ Technology Stack

Core Technologies

  • Kotlin
  • OpenGL ES 3.0+
  • Jetpack Compose
  • Coroutines
  • Gradle Kotlin DSL

Dependency Injection

Recommended:

  • Koin (limited usage)

Use DI ONLY for:

  • Renderer services
  • Shader registries
  • Texture caches
  • Motion orchestrators

Avoid DI for:

  • Vec3
  • Matrix4
  • Geometry
  • Units
  • Transforms

๐Ÿ“ Units System

Spatial avoids arbitrary floats whenever possible.

Example:

Modifier3D
    .size(2.meters)
    .rotateY(45.deg)

This improves:

  • readability
  • spatial consistency
  • API ergonomics

๐ŸŽฅ Motion System

Motion quality is one of Spatial's highest priorities.

Core #1 focuses heavily on:

  • smooth orbit camera
  • cinematic transitions
  • natural zoom
  • inertia
  • damping
  • interpolation

The renderer should feel premium even with simple cubes.


๐Ÿš€ Development Phases

Phase 1

Rendering foundations:

  • EGL
  • OpenGL setup
  • Triangle rendering
  • Render loop

Phase 2

Math engine:

  • Vec3
  • Matrix4
  • Quaternion

Phase 3

Camera system:

  • Orbit
  • Zoom
  • Inertia
  • Gestures

Phase 4

Scene graph:

  • Nodes
  • Hierarchy
  • Traversal

Phase 5

Geometry:

  • Cube
  • Sphere
  • Plane
  • Cylinder

Phase 6

Materials:

  • Solid materials
  • Texture materials
  • Basic lighting

Phase 7

Compose DSL:

  • Scene
  • Element
  • Modifier3D

Phase 8

Basic motion system:

  • animateTo for camera/transform changes
  • interpolation
    • shared easing/duration planning

Advanced timelines, skeletal animation, and clip sequencing are intentionally outside Core #1.


Phase 9

Polish:

  • smooth gestures
  • frame pacing
  • shader caching
  • lifecycle cleanup

Phase 10

Showcase playground.


โœ… Core #1 Success Criteria

Core #1 is complete when:

  • Primitives render correctly
  • Camera feels cinematic
  • Zoom feels smooth
  • Gestures feel natural
  • Motion transitions work
  • Compose integration works
  • API feels elegant
  • 60 FPS remain stable
  • OpenGL complexity stays hidden

๐Ÿ”ฎ Long-Term Vision

Potential future expansions:

  • glTF loading
  • PBR
  • Real lighting and shaded light evaluation
  • Shadows
  • Vulkan backend
  • Compose Multiplatform
  • Spatial UI
  • Physics integration
  • WebGPU backend

๐Ÿ’ก Guiding Principle

Less GPU complexity. More declarative intent.


Spatial โ€” Declarative 3D Rendering for Android

Built for modern Android graphics experimentation.

License: PolyForm Shield 1.0.0 ยท ยฉ 2024โ€“2026 Daniel Imbert (danielitoCode)

About

Spatial is a declarative 3D rendering library for Android inspired by Jetpack Compose, designed to completely hide the complexity of OpenGL and provide a modern, smooth, state-driven experience for building 3D scenes. It allows creating 3D worlds through a simple and expressive API based on components like Scene, Element, and Modifier3D

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages