1+ <!DOCTYPE html>
2+ < html lang ="en ">
3+
4+ < head >
5+ < meta charset ="utf-8 ">
6+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
7+ < meta http-equiv ="x-ua-compatible " content ="ie=edge ">
8+ < title > 3D Gaussian Splats - Drop-in example</ title >
9+ < script type ="text/javascript " src ="js/util.js "> </ script >
10+ < script type ="importmap ">
11+ {
12+ "imports" : {
13+ "three" : "./lib/three.module.js" ,
14+ "@mkkellogg/gaussian-splats-3d" : "./lib/gaussian-splats-3d.module.js"
15+ }
16+ }
17+ </ script >
18+ < style >
19+
20+ body {
21+ background-color : # 000000 ;
22+ height : 100vh ;
23+ margin : 0px ;
24+ }
25+
26+ </ style >
27+
28+ </ head >
29+
30+ < body >
31+ < script type ="module ">
32+ import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d' ;
33+ import * as THREE from 'three' ;
34+
35+ function setupRenderer ( ) {
36+ const renderWidth = 800 ;
37+ const renderHeight = 600 ;
38+
39+ const rootElement = document . createElement ( 'div' ) ;
40+ rootElement . style . width = renderWidth + 'px' ;
41+ rootElement . style . height = renderHeight + 'px' ;
42+ rootElement . style . position = 'relative' ;
43+ rootElement . style . left = '50%' ;
44+ rootElement . style . top = '50%' ;
45+ rootElement . style . transform = 'translate(-50%, -50%)' ;
46+ document . body . appendChild ( rootElement ) ;
47+
48+ const renderer = new THREE . WebGLRenderer ( {
49+ antialias : false
50+ } ) ;
51+ renderer . setSize ( renderWidth , renderHeight ) ;
52+ rootElement . appendChild ( renderer . domElement ) ;
53+
54+ return {
55+ 'renderer' : renderer ,
56+ 'renderWidth' : renderWidth ,
57+ 'renderHeight' : renderHeight
58+ }
59+ }
60+
61+ function setupCamera ( renderWidth , renderHeight ) {
62+ const camera = new THREE . PerspectiveCamera ( 65 , renderWidth / renderHeight , 0.1 , 500 ) ;
63+ camera . position . copy ( new THREE . Vector3 ( ) . fromArray ( [ - 1 , - 4 , 6 ] ) ) ;
64+ camera . lookAt ( new THREE . Vector3 ( ) . fromArray ( [ 0 , 4 , - 0 ] ) ) ;
65+ camera . up = new THREE . Vector3 ( ) . fromArray ( [ 0 , - 1 , - 0.6 ] ) . normalize ( ) ;
66+ return camera ;
67+ }
68+
69+ function setupThreeScene ( ) {
70+ const threeScene = new THREE . Scene ( ) ;
71+ const boxColor = 0xBBBBBB ;
72+ const boxGeometry = new THREE . BoxGeometry ( 2 , 2 , 2 ) ;
73+ const boxMesh = new THREE . Mesh ( boxGeometry , new THREE . MeshBasicMaterial ( { 'color' : boxColor } ) ) ;
74+ threeScene . add ( boxMesh ) ;
75+ boxMesh . position . set ( 3 , 2 , 2 ) ;
76+ return threeScene ;
77+ }
78+
79+ function setupControls ( camera , renderer ) {
80+ const controls = new GaussianSplats3D . OrbitControls ( camera , renderer . domElement ) ;
81+ controls . rotateSpeed = 0.5 ;
82+ controls . maxPolarAngle = Math . PI * .75 ;
83+ controls . minPolarAngle = 0.1 ;
84+ controls . enableDamping = true ;
85+ controls . dampingFactor = 0.05 ;
86+ return controls ;
87+ }
88+
89+ const { renderer, renderWidth, renderHeight} = setupRenderer ( ) ;
90+ const camera = setupCamera ( renderWidth , renderHeight ) ;
91+ const threeScene = setupThreeScene ( ) ;
92+ const controls = setupControls ( camera , renderer ) ;
93+
94+ const viewer = new GaussianSplats3D . DropInViewer ( {
95+ 'dynamicScene' : true
96+ } ) ;
97+ viewer . addSplatScenes ( [
98+ {
99+ 'path' : 'assets/data/garden/garden.ksplat' ,
100+ 'splatAlphaRemovalThreshold' : 20 ,
101+ } ,
102+ {
103+ 'path' : 'assets/data/bonsai/bonsai_trimmed.ksplat' ,
104+ 'splatAlphaRemovalThreshold' : 20 ,
105+ } ,
106+ {
107+ 'path' : 'assets/data/bonsai/bonsai_trimmed.ksplat' ,
108+ 'splatAlphaRemovalThreshold' : 20 ,
109+ }
110+ ] , true ) . then ( ( ) => {
111+
112+ threeScene . add ( viewer ) ;
113+
114+ const bonsaiCount = 2 ;
115+ const bonsaiStartIndex = 1 ;
116+ const rotationAxis = new THREE . Vector3 ( 0 , - 1 , - 0.6 ) . normalize ( ) ;
117+ const baseQuaternion = new THREE . Quaternion ( - 0.147244 , - 0.07617 , 0.14106 , 0.9760 ) ;
118+ const rotationQuaternion = new THREE . Quaternion ( ) ;
119+ const quaternion = new THREE . Quaternion ( ) ;
120+ const orbitCenter = new THREE . Vector3 ( 0.416161 , 1.385 , 1.145 ) ;
121+ const horizontalOffsetVector = new THREE . Vector3 ( ) ;
122+ const position = new THREE . Vector3 ( ) ;
123+ const scale = new THREE . Vector3 ( 1.25 , 1.25 , 1.25 ) ;
124+
125+ // generate splat mesh parent objects
126+ const sphereGeometry = new THREE . SphereGeometry ( 0.25 , 8 , 8 ) ;
127+ const material = new THREE . MeshBasicMaterial ( { color : 0xff0000 } ) ;
128+ const meshA = new THREE . Mesh ( sphereGeometry , material ) ;
129+ const meshB = new THREE . Mesh ( sphereGeometry , material ) ;
130+
131+ // add splat mesh parent objects to the scene
132+ threeScene . add ( meshA ) ;
133+ threeScene . add ( meshB ) ;
134+
135+ // You can modify the transform components (position, quaternion, scale) of a SplatScene
136+ // directly like any three.js object OR you can just attach them to another three.js object
137+ // and they will be transformed accordingly. Below we are going with the latter approach.
138+ // The splat scenes at index 1 & 2 are (by default) children of viewer.splatMesh, so we
139+ // re-parent them to meshA and meshB respectively.
140+ meshA . add ( viewer . getSplatScene ( 1 ) ) ;
141+ meshB . add ( viewer . getSplatScene ( 2 ) ) ;
142+
143+ let startTime = performance . now ( ) / 1000.0 ;
144+ requestAnimationFrame ( update ) ;
145+ function update ( ) {
146+ requestAnimationFrame ( update ) ;
147+ const timeDelta = performance . now ( ) / 1000.0 - startTime ;
148+ for ( let i = bonsaiStartIndex ; i < bonsaiStartIndex + bonsaiCount ; i ++ ) {
149+
150+ // calculate parent mesh positions & orientations
151+ const angle = timeDelta * 0.25 + ( Math . PI * 2 ) * ( i / bonsaiCount ) ;
152+ const height = Math . cos ( timeDelta + ( Math . PI * 2 ) * ( i / bonsaiCount ) ) * 0.5 + 3 ;
153+ rotationQuaternion . setFromAxisAngle ( rotationAxis , angle ) ;
154+ horizontalOffsetVector . set ( 3 , 0 , 0 ) . applyQuaternion ( rotationQuaternion ) ;
155+
156+ // apply mesh position, orientation and scale
157+ const mesh = ( i % 2 === 0 ) ? meshA : meshB ;
158+ mesh . position . copy ( rotationAxis ) . multiplyScalar ( height ) . add ( horizontalOffsetVector ) . add ( orbitCenter ) ;
159+ mesh . quaternion . copy ( baseQuaternion ) . premultiply ( rotationQuaternion ) ;
160+ mesh . scale . copy ( scale ) ;
161+
162+ // perform standard three.js update and render
163+ controls . update ( ) ;
164+ renderer . render ( threeScene , camera ) ;
165+
166+ }
167+ }
168+ } ) ;
169+
170+ </ script >
171+ </ body >
172+
173+ </ html >
0 commit comments