{"id":29795937,"url":"https://github.com/jumpingkeycaps/model3dviewer","last_synced_at":"2025-07-28T05:03:36.361Z","repository":{"id":297120995,"uuid":"976149478","full_name":"JumpingKeyCaps/Model3dViewer","owner":"JumpingKeyCaps","description":"Proof of Concept Android app demonstrating how to embed interactive 3D models (STL \u0026 glTF) into a Jetpack Compose UI using a WebView and Three.js. Includes real-time scene configuration, model loading, and orientation control via device sensors.","archived":false,"fork":false,"pushed_at":"2025-06-03T23:46:26.000Z","size":43145,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-04T07:16:38.802Z","etag":null,"topics":["3d-models","androidview","compose","glb","gltf","javascript","kotlin-android","orbitcontrols","sensors","stl","three-js","webview"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JumpingKeyCaps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-01T15:32:18.000Z","updated_at":"2025-06-03T23:46:27.000Z","dependencies_parsed_at":"2025-06-04T07:26:53.477Z","dependency_job_id":null,"html_url":"https://github.com/JumpingKeyCaps/Model3dViewer","commit_stats":null,"previous_names":["jumpingkeycaps/model3dviewer"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/JumpingKeyCaps/Model3dViewer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JumpingKeyCaps%2FModel3dViewer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JumpingKeyCaps%2FModel3dViewer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JumpingKeyCaps%2FModel3dViewer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JumpingKeyCaps%2FModel3dViewer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JumpingKeyCaps","download_url":"https://codeload.github.com/JumpingKeyCaps/Model3dViewer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JumpingKeyCaps%2FModel3dViewer/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267464522,"owners_count":24091505,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d-models","androidview","compose","glb","gltf","javascript","kotlin-android","orbitcontrols","sensors","stl","three-js","webview"],"created_at":"2025-07-28T05:01:19.357Z","updated_at":"2025-07-28T05:03:36.352Z","avatar_url":"https://github.com/JumpingKeyCaps.png","language":"JavaScript","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/logoapp.png\" alt=\"Logo\" width=\"477\" height=\"333\"\u003e\n\u003c/p\u003e\n\n# Model3DViewer\n\n\n![Kotlin](https://img.shields.io/badge/Kotlin-7F52FF?logo=kotlin\u0026logoColor=white)\n![Jetpack Compose](https://img.shields.io/badge/Jetpack%20Compose-4285F4?logo=jetpackcompose\u0026logoColor=white)\n![three.js](https://img.shields.io/badge/three.js-000000?logo=three.js\u0026logoColor=white)\n![WebView](https://img.shields.io/badge/WebView-AndroidView-green)\n![3D File Support](https://img.shields.io/badge/STL%20%7C%20GLTF%20%7C%20GLB-supported-8E44AD)\n![Offline Mode](https://img.shields.io/badge/Offline-Available-brightgreen)\n![Sensors](https://img.shields.io/badge/Sensors-Gyro%20%2B%20Accel%20%2B%20Magneto-blue)\n\n**Model3DViewer** is a mobile Android application that demonstrates how to render and manipulate **3D models** using a **WebView** embedded in a **Jetpack Compose** interface.\n\nThis is a **Proof of Concept (POC)** that combines native Android capabilities with web-based 3D rendering powered by **three.js**.\n\n---\n\n## 🚀 Project Overview\n\n**Context**:  \nIntegrating immersive 3D visualizations in modern Android apps can enhance user interaction and design. This project shows how to embed and control 3D content using `three.js` inside a native Jetpack Compose app.\n\n**Objectives**:  \n- Render 3D models in an Android WebView.\n- Enable interaction via touch gestures and sensors.\n- Implement reusable Compose screens for various use cases.\n- Showcase a bridge between Kotlin and JavaScript.\n- Ensure offline rendering by bundling all 3D scripts locally.\n\n---\n\n## ⚙️ Main Features\n\n- Render **3D models** (STL, GLTF, GLB) with **three.js** inside a WebView.\n- Use **OrbitControls** for touch-based interaction (rotate, zoom).\n- Load custom 3D files from **device storage**.\n- Display the 3D model **above the UI** with a transparent WebView.\n- Rotate the model using **device sensors** (gyroscope, accelerometer, magnetometer).\n- Configure lighting and camera through a dynamic bottom sheet.\n- Full support for **offline mode** (no network required).\n\n---\n\n## 📈 Development Tasks\n\n| Step | Goal | Outcome |\n| :--- | :--- | :--- |\n| **Project Setup** | Compose + WebView integration | Jetpack Compose linked with embedded WebView |\n| **three.js Integration** | Render 3D content | Scene loaded using local JS files |\n| **Model Interaction** | OrbitControls + File picker | Custom 3D models loadable from gallery |\n| **Sensor Control** | Real-world rotation support | Model reacts to device orientation |\n| **Bridge Implementation** | Communication Kotlin ⇄ JS | Custom commands via `evaluateJavascript()` |\n| **Polish \u0026 Documentation** | Clean code + visual assets | Screenshots and full README written |\n\n---\n\n## 🛠️ Tech Stack\n\n- **Language**: Kotlin\n- **UI**: Jetpack Compose\n- **Architecture**: MVVM (loosely)\n- **3D Rendering**: [three.js](https://threejs.org/)\n- **Web Integration**: Android WebView\n- **3D File Support**: STL, GLTF, GLB\n- **Sensor Fusion**: Gyroscope, Accelerometer, Magnetometer\n- **Testing**: Manual \u0026 Visual (POC stage)\n- **IDE**: Android Studio Giraffe\n\n---\n\n## 📸 Screenshots\n\n| Girl 3d model | Racquet 3d model | Sumo 3d model | \n|:---:|:---:|:---:|\n| ![Girl](screenshots/girly.gif) | ![Racquet](screenshots/rackette.gif) | ![Sumo](screenshots/sumo.gif) | \n\n| Scene 3d model | Burger 3d model | Loader | \n|:---:|:---:|:---:|\n| ![Scene](screenshots/scene.gif) | ![Burger](screenshots/burger.gif) | ![Loader](screenshots/loadmodel.gif) | \n\n---\n\n## 🧩 Integration of three.js \u0026 Module Handling\n\nDuring development, one of the main challenges was using **three.js modules** in a WebView context. Since **WebViews in Android do not support ES6 module syntax (e.g., `import { OrbitControls } from 'three/examples/jsm/...')**, we had to find an alternative approach.\n\n### 🛠 Solutions Implemented\n\n- All necessary three.js scripts (including `three.min.js`, `OrbitControls.js`, `GLTFLoader.js`, etc.) were **manually downloaded and bundled** inside the `/assets` folder of the Android app.\n- Instead of using `import` statements, we switched to **global script loading via `\u003cscript\u003e` tags**, maintaining compatibility with the WebView runtime.\n- 3D model loading, scene creation, and interaction logic were written inside a local `index.html` file, using global references to three.js components.\n\n### 📦 Advantages\n\n- Full **offline support**, no CDN or internet required.\n- Avoids CORS or MIME-type issues when loading modules locally.\n- Works seamlessly across all Android versions supporting WebView.\n\n### ⚠️ Known Limitations\n\n- Can’t use modern ES Modules (`import`) or NPM-based three.js structure (Android JS file locker, so i use the oldi 0.125.0 build).\n- Debugging JavaScript inside WebView can be limited compared to browser tools.\n- Need to keep scripts updated manually if three.js releases new features or fixes.\n\nThis approach ensures **maximum compatibility** while preserving the power of three.js in a constrained Android WebView environment.\n\n---\n\n## 🎯 Final Result\n\n✅ Embedded 3D models directly in a Jetpack Compose UI.  \n✅ Works entirely offline with locally bundled JS.  \n✅ Advanced interaction via touch and sensors.  \n✅ Modular, reusable Composable screens for 3D rendering.  \n✅ Complete separation between native and Web logic through a communication bridge.\n\n---\n\n\n---\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjumpingkeycaps%2Fmodel3dviewer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjumpingkeycaps%2Fmodel3dviewer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjumpingkeycaps%2Fmodel3dviewer/lists"}