├── LICENSE ├── base.css ├── index.html ├── main.js └── resources ├── fire.jpg ├── fire.png ├── negx.jpg ├── negy.jpg ├── negz.jpg ├── posx.jpg ├── posy.jpg ├── posz.jpg ├── readme.txt └── rocket ├── Rocket_Ship_01.bin └── Rocket_Ship_01.gltf /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 simondevyoutube 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /base.css: -------------------------------------------------------------------------------- 1 | body { 2 | width: 100%; 3 | height: 100%; 4 | position: absolute; 5 | background: #000000; 6 | margin: 0; 7 | padding: 0; 8 | overscroll-behavior: none; 9 | } 10 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Basic 3D World 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118/build/three.module.js'; 2 | 3 | import {GLTFLoader} from 'https://cdn.jsdelivr.net/npm/three@0.118.1/examples/jsm/loaders/GLTFLoader.js'; 4 | import {OrbitControls} from 'https://cdn.jsdelivr.net/npm/three@0.118/examples/jsm/controls/OrbitControls.js'; 5 | 6 | 7 | const _VS = ` 8 | uniform float pointMultiplier; 9 | 10 | attribute float size; 11 | attribute float angle; 12 | attribute vec4 colour; 13 | 14 | varying vec4 vColour; 15 | varying vec2 vAngle; 16 | 17 | void main() { 18 | vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); 19 | 20 | gl_Position = projectionMatrix * mvPosition; 21 | gl_PointSize = size * pointMultiplier / gl_Position.w; 22 | 23 | vAngle = vec2(cos(angle), sin(angle)); 24 | vColour = colour; 25 | }`; 26 | 27 | const _FS = ` 28 | 29 | uniform sampler2D diffuseTexture; 30 | 31 | varying vec4 vColour; 32 | varying vec2 vAngle; 33 | 34 | void main() { 35 | vec2 coords = (gl_PointCoord - 0.5) * mat2(vAngle.x, vAngle.y, -vAngle.y, vAngle.x) + 0.5; 36 | gl_FragColor = texture2D(diffuseTexture, coords) * vColour; 37 | }`; 38 | 39 | 40 | class LinearSpline { 41 | constructor(lerp) { 42 | this._points = []; 43 | this._lerp = lerp; 44 | } 45 | 46 | AddPoint(t, d) { 47 | this._points.push([t, d]); 48 | } 49 | 50 | Get(t) { 51 | let p1 = 0; 52 | 53 | for (let i = 0; i < this._points.length; i++) { 54 | if (this._points[i][0] >= t) { 55 | break; 56 | } 57 | p1 = i; 58 | } 59 | 60 | const p2 = Math.min(this._points.length - 1, p1 + 1); 61 | 62 | if (p1 == p2) { 63 | return this._points[p1][1]; 64 | } 65 | 66 | return this._lerp( 67 | (t - this._points[p1][0]) / ( 68 | this._points[p2][0] - this._points[p1][0]), 69 | this._points[p1][1], this._points[p2][1]); 70 | } 71 | } 72 | 73 | 74 | class ParticleSystem { 75 | constructor(params) { 76 | const uniforms = { 77 | diffuseTexture: { 78 | value: new THREE.TextureLoader().load('./resources/fire.png') 79 | }, 80 | pointMultiplier: { 81 | value: window.innerHeight / (2.0 * Math.tan(0.5 * 60.0 * Math.PI / 180.0)) 82 | } 83 | }; 84 | 85 | this._material = new THREE.ShaderMaterial({ 86 | uniforms: uniforms, 87 | vertexShader: _VS, 88 | fragmentShader: _FS, 89 | blending: THREE.AdditiveBlending, 90 | depthTest: true, 91 | depthWrite: false, 92 | transparent: true, 93 | vertexColors: true 94 | }); 95 | 96 | this._camera = params.camera; 97 | this._particles = []; 98 | 99 | this._geometry = new THREE.BufferGeometry(); 100 | this._geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3)); 101 | this._geometry.setAttribute('size', new THREE.Float32BufferAttribute([], 1)); 102 | this._geometry.setAttribute('colour', new THREE.Float32BufferAttribute([], 4)); 103 | this._geometry.setAttribute('angle', new THREE.Float32BufferAttribute([], 1)); 104 | 105 | this._points = new THREE.Points(this._geometry, this._material); 106 | 107 | params.parent.add(this._points); 108 | 109 | this._alphaSpline = new LinearSpline((t, a, b) => { 110 | return a + t * (b - a); 111 | }); 112 | this._alphaSpline.AddPoint(0.0, 0.0); 113 | this._alphaSpline.AddPoint(0.1, 1.0); 114 | this._alphaSpline.AddPoint(0.6, 1.0); 115 | this._alphaSpline.AddPoint(1.0, 0.0); 116 | 117 | this._colourSpline = new LinearSpline((t, a, b) => { 118 | const c = a.clone(); 119 | return c.lerp(b, t); 120 | }); 121 | this._colourSpline.AddPoint(0.0, new THREE.Color(0xFFFF80)); 122 | this._colourSpline.AddPoint(1.0, new THREE.Color(0xFF8080)); 123 | 124 | this._sizeSpline = new LinearSpline((t, a, b) => { 125 | return a + t * (b - a); 126 | }); 127 | this._sizeSpline.AddPoint(0.0, 1.0); 128 | this._sizeSpline.AddPoint(0.5, 5.0); 129 | this._sizeSpline.AddPoint(1.0, 1.0); 130 | 131 | document.addEventListener('keyup', (e) => this._onKeyUp(e), false); 132 | 133 | this._UpdateGeometry(); 134 | } 135 | 136 | _onKeyUp(event) { 137 | switch(event.keyCode) { 138 | case 32: // SPACE 139 | this._AddParticles(); 140 | break; 141 | } 142 | } 143 | 144 | _AddParticles(timeElapsed) { 145 | if (!this.gdfsghk) { 146 | this.gdfsghk = 0.0; 147 | } 148 | this.gdfsghk += timeElapsed; 149 | const n = Math.floor(this.gdfsghk * 75.0); 150 | this.gdfsghk -= n / 75.0; 151 | 152 | for (let i = 0; i < n; i++) { 153 | const life = (Math.random() * 0.75 + 0.25) * 10.0; 154 | this._particles.push({ 155 | position: new THREE.Vector3( 156 | (Math.random() * 2 - 1) * 1.0, 157 | (Math.random() * 2 - 1) * 1.0, 158 | (Math.random() * 2 - 1) * 1.0), 159 | size: (Math.random() * 0.5 + 0.5) * 4.0, 160 | colour: new THREE.Color(), 161 | alpha: 1.0, 162 | life: life, 163 | maxLife: life, 164 | rotation: Math.random() * 2.0 * Math.PI, 165 | velocity: new THREE.Vector3(0, -15, 0), 166 | }); 167 | } 168 | } 169 | 170 | _UpdateGeometry() { 171 | const positions = []; 172 | const sizes = []; 173 | const colours = []; 174 | const angles = []; 175 | 176 | for (let p of this._particles) { 177 | positions.push(p.position.x, p.position.y, p.position.z); 178 | colours.push(p.colour.r, p.colour.g, p.colour.b, p.alpha); 179 | sizes.push(p.currentSize); 180 | angles.push(p.rotation); 181 | } 182 | 183 | this._geometry.setAttribute( 184 | 'position', new THREE.Float32BufferAttribute(positions, 3)); 185 | this._geometry.setAttribute( 186 | 'size', new THREE.Float32BufferAttribute(sizes, 1)); 187 | this._geometry.setAttribute( 188 | 'colour', new THREE.Float32BufferAttribute(colours, 4)); 189 | this._geometry.setAttribute( 190 | 'angle', new THREE.Float32BufferAttribute(angles, 1)); 191 | 192 | this._geometry.attributes.position.needsUpdate = true; 193 | this._geometry.attributes.size.needsUpdate = true; 194 | this._geometry.attributes.colour.needsUpdate = true; 195 | this._geometry.attributes.angle.needsUpdate = true; 196 | } 197 | 198 | _UpdateParticles(timeElapsed) { 199 | for (let p of this._particles) { 200 | p.life -= timeElapsed; 201 | } 202 | 203 | this._particles = this._particles.filter(p => { 204 | return p.life > 0.0; 205 | }); 206 | 207 | for (let p of this._particles) { 208 | const t = 1.0 - p.life / p.maxLife; 209 | 210 | p.rotation += timeElapsed * 0.5; 211 | p.alpha = this._alphaSpline.Get(t); 212 | p.currentSize = p.size * this._sizeSpline.Get(t); 213 | p.colour.copy(this._colourSpline.Get(t)); 214 | 215 | p.position.add(p.velocity.clone().multiplyScalar(timeElapsed)); 216 | 217 | const drag = p.velocity.clone(); 218 | drag.multiplyScalar(timeElapsed * 0.1); 219 | drag.x = Math.sign(p.velocity.x) * Math.min(Math.abs(drag.x), Math.abs(p.velocity.x)); 220 | drag.y = Math.sign(p.velocity.y) * Math.min(Math.abs(drag.y), Math.abs(p.velocity.y)); 221 | drag.z = Math.sign(p.velocity.z) * Math.min(Math.abs(drag.z), Math.abs(p.velocity.z)); 222 | p.velocity.sub(drag); 223 | } 224 | 225 | this._particles.sort((a, b) => { 226 | const d1 = this._camera.position.distanceTo(a.position); 227 | const d2 = this._camera.position.distanceTo(b.position); 228 | 229 | if (d1 > d2) { 230 | return -1; 231 | } 232 | 233 | if (d1 < d2) { 234 | return 1; 235 | } 236 | 237 | return 0; 238 | }); 239 | } 240 | 241 | Step(timeElapsed) { 242 | this._AddParticles(timeElapsed); 243 | this._UpdateParticles(timeElapsed); 244 | this._UpdateGeometry(); 245 | } 246 | } 247 | 248 | class ParticleSystemDemo { 249 | constructor() { 250 | this._Initialize(); 251 | } 252 | 253 | _Initialize() { 254 | this._threejs = new THREE.WebGLRenderer({ 255 | antialias: true, 256 | }); 257 | this._threejs.shadowMap.enabled = true; 258 | this._threejs.shadowMap.type = THREE.PCFSoftShadowMap; 259 | this._threejs.setPixelRatio(window.devicePixelRatio); 260 | this._threejs.setSize(window.innerWidth, window.innerHeight); 261 | 262 | document.body.appendChild(this._threejs.domElement); 263 | 264 | window.addEventListener('resize', () => { 265 | this._OnWindowResize(); 266 | }, false); 267 | 268 | const fov = 60; 269 | const aspect = 1920 / 1080; 270 | const near = 1.0; 271 | const far = 1000.0; 272 | this._camera = new THREE.PerspectiveCamera(fov, aspect, near, far); 273 | this._camera.position.set(25, 10, 0); 274 | 275 | this._scene = new THREE.Scene(); 276 | 277 | let light = new THREE.DirectionalLight(0xFFFFFF, 1.0); 278 | light.position.set(20, 100, 10); 279 | light.target.position.set(0, 0, 0); 280 | light.castShadow = true; 281 | light.shadow.bias = -0.001; 282 | light.shadow.mapSize.width = 2048; 283 | light.shadow.mapSize.height = 2048; 284 | light.shadow.camera.near = 0.1; 285 | light.shadow.camera.far = 500.0; 286 | light.shadow.camera.near = 0.5; 287 | light.shadow.camera.far = 500.0; 288 | light.shadow.camera.left = 100; 289 | light.shadow.camera.right = -100; 290 | light.shadow.camera.top = 100; 291 | light.shadow.camera.bottom = -100; 292 | this._scene.add(light); 293 | 294 | light = new THREE.AmbientLight(0x101010); 295 | this._scene.add(light); 296 | 297 | const controls = new OrbitControls( 298 | this._camera, this._threejs.domElement); 299 | controls.target.set(0, 0, 0); 300 | controls.update(); 301 | 302 | const loader = new THREE.CubeTextureLoader(); 303 | const texture = loader.load([ 304 | './resources/posx.jpg', 305 | './resources/negx.jpg', 306 | './resources/posy.jpg', 307 | './resources/negy.jpg', 308 | './resources/posz.jpg', 309 | './resources/negz.jpg', 310 | ]); 311 | this._scene.background = texture; 312 | 313 | this._particles = new ParticleSystem({ 314 | parent: this._scene, 315 | camera: this._camera, 316 | }); 317 | 318 | this._LoadModel(); 319 | 320 | this._previousRAF = null; 321 | this._RAF(); 322 | } 323 | 324 | _LoadModel() { 325 | const loader = new GLTFLoader(); 326 | loader.load('./resources/rocket/Rocket_Ship_01.gltf', (gltf) => { 327 | gltf.scene.traverse(c => { 328 | c.castShadow = true; 329 | }); 330 | this._scene.add(gltf.scene); 331 | }); 332 | } 333 | 334 | _OnWindowResize() { 335 | this._camera.aspect = window.innerWidth / window.innerHeight; 336 | this._camera.updateProjectionMatrix(); 337 | this._threejs.setSize(window.innerWidth, window.innerHeight); 338 | } 339 | 340 | _RAF() { 341 | requestAnimationFrame((t) => { 342 | if (this._previousRAF === null) { 343 | this._previousRAF = t; 344 | } 345 | 346 | this._RAF(); 347 | 348 | this._threejs.render(this._scene, this._camera); 349 | this._Step(t - this._previousRAF); 350 | this._previousRAF = t; 351 | }); 352 | } 353 | 354 | _Step(timeElapsed) { 355 | const timeElapsedS = timeElapsed * 0.001; 356 | 357 | this._particles.Step(timeElapsedS); 358 | } 359 | } 360 | 361 | 362 | let _APP = null; 363 | 364 | window.addEventListener('DOMContentLoaded', () => { 365 | _APP = new ParticleSystemDemo(); 366 | }); 367 | -------------------------------------------------------------------------------- /resources/fire.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondevyoutube/ThreeJS_Tutorial_ParticleSystems/c222f41b6cfdece8a32af097f66f9b66a59646da/resources/fire.jpg -------------------------------------------------------------------------------- /resources/fire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondevyoutube/ThreeJS_Tutorial_ParticleSystems/c222f41b6cfdece8a32af097f66f9b66a59646da/resources/fire.png -------------------------------------------------------------------------------- /resources/negx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondevyoutube/ThreeJS_Tutorial_ParticleSystems/c222f41b6cfdece8a32af097f66f9b66a59646da/resources/negx.jpg -------------------------------------------------------------------------------- /resources/negy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondevyoutube/ThreeJS_Tutorial_ParticleSystems/c222f41b6cfdece8a32af097f66f9b66a59646da/resources/negy.jpg -------------------------------------------------------------------------------- /resources/negz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondevyoutube/ThreeJS_Tutorial_ParticleSystems/c222f41b6cfdece8a32af097f66f9b66a59646da/resources/negz.jpg -------------------------------------------------------------------------------- /resources/posx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondevyoutube/ThreeJS_Tutorial_ParticleSystems/c222f41b6cfdece8a32af097f66f9b66a59646da/resources/posx.jpg -------------------------------------------------------------------------------- /resources/posy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondevyoutube/ThreeJS_Tutorial_ParticleSystems/c222f41b6cfdece8a32af097f66f9b66a59646da/resources/posy.jpg -------------------------------------------------------------------------------- /resources/posz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondevyoutube/ThreeJS_Tutorial_ParticleSystems/c222f41b6cfdece8a32af097f66f9b66a59646da/resources/posz.jpg -------------------------------------------------------------------------------- /resources/readme.txt: -------------------------------------------------------------------------------- 1 | Author 2 | ====== 3 | 4 | This is the work of Emil Persson, aka Humus. 5 | http://www.humus.name 6 | 7 | 8 | 9 | License 10 | ======= 11 | 12 | This work is licensed under a Creative Commons Attribution 3.0 Unported License. 13 | http://creativecommons.org/licenses/by/3.0/ 14 | -------------------------------------------------------------------------------- /resources/rocket/Rocket_Ship_01.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simondevyoutube/ThreeJS_Tutorial_ParticleSystems/c222f41b6cfdece8a32af097f66f9b66a59646da/resources/rocket/Rocket_Ship_01.bin -------------------------------------------------------------------------------- /resources/rocket/Rocket_Ship_01.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "accessors" : [ 3 | { 4 | "bufferView" : 0, 5 | "componentType" : 5123, 6 | "count" : 624, 7 | "max" : [ 623 ], 8 | "min" : [ 0 ], 9 | "name" : "buffer-0-accessor-indices-buffer-0-mesh-0", 10 | "type" : "SCALAR" 11 | }, 12 | { 13 | "bufferView" : 2, 14 | "componentType" : 5126, 15 | "count" : 624, 16 | "max" : [ 3.294547080993652, 9.564169883728027, 3.294547080993652 ], 17 | "min" : [ -3.294547080993652, 0, -3.294547080993652 ], 18 | "name" : "buffer-0-accessor-position-buffer-0-mesh-0", 19 | "type" : "VEC3" 20 | }, 21 | { 22 | "bufferView" : 2, 23 | "byteOffset" : 7488, 24 | "componentType" : 5126, 25 | "count" : 624, 26 | "max" : [ 1, 0.7847999930381775, 1 ], 27 | "min" : [ -1, -0.9914000034332275, -1 ], 28 | "name" : "buffer-0-accessor-normal-buffer-0-mesh-0", 29 | "type" : "VEC3" 30 | }, 31 | { 32 | "bufferView" : 1, 33 | "componentType" : 5126, 34 | "count" : 0, 35 | "max" : [ 0, 0 ], 36 | "min" : [ 0, 0 ], 37 | "name" : "buffer-0-accessor-texcoord-buffer-0-mesh-0", 38 | "type" : "VEC2" 39 | }, 40 | { 41 | "bufferView" : 3, 42 | "componentType" : 5126, 43 | "count" : 0, 44 | "max" : [ 0, 0, 0, 0 ], 45 | "min" : [ 0, 0, 0, 0 ], 46 | "name" : "buffer-0-accessor-color-buffer-0-mesh-0", 47 | "type" : "VEC4" 48 | }, 49 | { 50 | "bufferView" : 0, 51 | "byteOffset" : 1248, 52 | "componentType" : 5123, 53 | "count" : 240, 54 | "max" : [ 239 ], 55 | "min" : [ 0 ], 56 | "name" : "buffer-0-accessor-indices-buffer-0-mesh-0", 57 | "type" : "SCALAR" 58 | }, 59 | { 60 | "bufferView" : 2, 61 | "byteOffset" : 14976, 62 | "componentType" : 5126, 63 | "count" : 240, 64 | "max" : [ 1.958153963088989, 6.53810977935791, 1.958153963088989 ], 65 | "min" : [ -1.958153963088989, 0, -1.958153963088989 ], 66 | "name" : "buffer-0-accessor-position-buffer-0-mesh-0", 67 | "type" : "VEC3" 68 | }, 69 | { 70 | "bufferView" : 2, 71 | "byteOffset" : 17856, 72 | "componentType" : 5126, 73 | "count" : 240, 74 | "max" : [ 0.9232000112533569, 0.1186000034213066, 0.9232000112533569 ], 75 | "min" : [ -0.9232000112533569, -1, -0.9232000112533569 ], 76 | "name" : "buffer-0-accessor-normal-buffer-0-mesh-0", 77 | "type" : "VEC3" 78 | }, 79 | { 80 | "bufferView" : 1, 81 | "componentType" : 5126, 82 | "count" : 0, 83 | "max" : [ 0, 0 ], 84 | "min" : [ 0, 0 ], 85 | "name" : "buffer-0-accessor-texcoord-buffer-0-mesh-0", 86 | "type" : "VEC2" 87 | }, 88 | { 89 | "bufferView" : 3, 90 | "componentType" : 5126, 91 | "count" : 0, 92 | "max" : [ 0, 0, 0, 0 ], 93 | "min" : [ 0, 0, 0, 0 ], 94 | "name" : "buffer-0-accessor-color-buffer-0-mesh-0", 95 | "type" : "VEC4" 96 | }, 97 | { 98 | "bufferView" : 0, 99 | "byteOffset" : 1728, 100 | "componentType" : 5123, 101 | "count" : 1056, 102 | "max" : [ 1055 ], 103 | "min" : [ 0 ], 104 | "name" : "buffer-0-accessor-indices-buffer-0-mesh-0", 105 | "type" : "SCALAR" 106 | }, 107 | { 108 | "bufferView" : 2, 109 | "byteOffset" : 20736, 110 | "componentType" : 5126, 111 | "count" : 1056, 112 | "max" : [ 2.062674045562744, 6.647388935089111, 2.062674045562744 ], 113 | "min" : [ -2.062674045562744, 0, -2.062674045562744 ], 114 | "name" : "buffer-0-accessor-position-buffer-0-mesh-0", 115 | "type" : "VEC3" 116 | }, 117 | { 118 | "bufferView" : 2, 119 | "byteOffset" : 33408, 120 | "componentType" : 5126, 121 | "count" : 1056, 122 | "max" : [ 1, 1, 1 ], 123 | "min" : [ -1, -1, -1 ], 124 | "name" : "buffer-0-accessor-normal-buffer-0-mesh-0", 125 | "type" : "VEC3" 126 | }, 127 | { 128 | "bufferView" : 1, 129 | "componentType" : 5126, 130 | "count" : 0, 131 | "max" : [ 0, 0 ], 132 | "min" : [ 0, 0 ], 133 | "name" : "buffer-0-accessor-texcoord-buffer-0-mesh-0", 134 | "type" : "VEC2" 135 | }, 136 | { 137 | "bufferView" : 3, 138 | "componentType" : 5126, 139 | "count" : 0, 140 | "max" : [ 0, 0, 0, 0 ], 141 | "min" : [ 0, 0, 0, 0 ], 142 | "name" : "buffer-0-accessor-color-buffer-0-mesh-0", 143 | "type" : "VEC4" 144 | }, 145 | { 146 | "bufferView" : 0, 147 | "byteOffset" : 3840, 148 | "componentType" : 5123, 149 | "count" : 480, 150 | "max" : [ 479 ], 151 | "min" : [ 0 ], 152 | "name" : "buffer-0-accessor-indices-buffer-0-mesh-0", 153 | "type" : "SCALAR" 154 | }, 155 | { 156 | "bufferView" : 2, 157 | "byteOffset" : 46080, 158 | "componentType" : 5126, 159 | "count" : 480, 160 | "max" : [ 0.8525949716567993, 9.915228843688965, 0.8525949716567993 ], 161 | "min" : [ -0.8525949716567993, 0, -0.8525949716567993 ], 162 | "name" : "buffer-0-accessor-position-buffer-0-mesh-0", 163 | "type" : "VEC3" 164 | }, 165 | { 166 | "bufferView" : 2, 167 | "byteOffset" : 51840, 168 | "componentType" : 5126, 169 | "count" : 480, 170 | "max" : [ 0.9239000082015991, 0.9775999784469604, 0.9239000082015991 ], 171 | "min" : [ -0.9239000082015991, -1, -0.9239000082015991 ], 172 | "name" : "buffer-0-accessor-normal-buffer-0-mesh-0", 173 | "type" : "VEC3" 174 | }, 175 | { 176 | "bufferView" : 1, 177 | "componentType" : 5126, 178 | "count" : 0, 179 | "max" : [ 0, 0 ], 180 | "min" : [ 0, 0 ], 181 | "name" : "buffer-0-accessor-texcoord-buffer-0-mesh-0", 182 | "type" : "VEC2" 183 | }, 184 | { 185 | "bufferView" : 3, 186 | "componentType" : 5126, 187 | "count" : 0, 188 | "max" : [ 0, 0, 0, 0 ], 189 | "min" : [ 0, 0, 0, 0 ], 190 | "name" : "buffer-0-accessor-color-buffer-0-mesh-0", 191 | "type" : "VEC4" 192 | }, 193 | { 194 | "bufferView" : 0, 195 | "byteOffset" : 4800, 196 | "componentType" : 5123, 197 | "count" : 96, 198 | "max" : [ 95 ], 199 | "min" : [ 0 ], 200 | "name" : "buffer-0-accessor-indices-buffer-0-mesh-0", 201 | "type" : "SCALAR" 202 | }, 203 | { 204 | "bufferView" : 2, 205 | "byteOffset" : 57600, 206 | "componentType" : 5126, 207 | "count" : 96, 208 | "max" : [ 1.929389953613281, 5.365962982177734, 1.92612898349762 ], 209 | "min" : [ -1.929389953613281, 0, -1.92612898349762 ], 210 | "name" : "buffer-0-accessor-position-buffer-0-mesh-0", 211 | "type" : "VEC3" 212 | }, 213 | { 214 | "bufferView" : 2, 215 | "byteOffset" : 58752, 216 | "componentType" : 5126, 217 | "count" : 96, 218 | "max" : [ 1, 0, 1 ], 219 | "min" : [ -1, 0, -1 ], 220 | "name" : "buffer-0-accessor-normal-buffer-0-mesh-0", 221 | "type" : "VEC3" 222 | }, 223 | { 224 | "bufferView" : 1, 225 | "componentType" : 5126, 226 | "count" : 0, 227 | "max" : [ 0, 0 ], 228 | "min" : [ 0, 0 ], 229 | "name" : "buffer-0-accessor-texcoord-buffer-0-mesh-0", 230 | "type" : "VEC2" 231 | }, 232 | { 233 | "bufferView" : 3, 234 | "componentType" : 5126, 235 | "count" : 0, 236 | "max" : [ 0, 0, 0, 0 ], 237 | "min" : [ 0, 0, 0, 0 ], 238 | "name" : "buffer-0-accessor-color-buffer-0-mesh-0", 239 | "type" : "VEC4" 240 | } 241 | ], 242 | "asset" : { 243 | "generator" : "Obj2GltfConverter", 244 | "version" : "2.0" 245 | }, 246 | "bufferViews" : [ 247 | { 248 | "buffer" : 0, 249 | "byteLength" : 4992, 250 | "byteStride" : 0, 251 | "name" : "buffer-0-bufferview-ushort", 252 | "target" : 34963 253 | }, 254 | { 255 | "buffer" : 0, 256 | "byteLength" : 1, 257 | "name" : "buffer-0-bufferview-vec2" 258 | }, 259 | { 260 | "buffer" : 0, 261 | "byteLength" : 59904, 262 | "byteOffset" : 4992, 263 | "byteStride" : 12, 264 | "name" : "buffer-0-bufferview-vec3", 265 | "target" : 34962 266 | }, 267 | { 268 | "buffer" : 0, 269 | "byteLength" : 1, 270 | "name" : "buffer-0-bufferview-vec4" 271 | } 272 | ], 273 | "buffers" : [ 274 | { 275 | "byteLength" : 64896, 276 | "name" : "buffer-0", 277 | "uri" : "Rocket_Ship_01.bin" 278 | } 279 | ], 280 | "materials" : [ 281 | { 282 | "doubleSided" : true, 283 | "name" : "F44336", 284 | "pbrMetallicRoughness" : { 285 | "baseColorFactor" : [ 0.956863, 0.262745, 0.211765, 1 ], 286 | "metallicFactor" : 0, 287 | "roughnessFactor" : 0.7448017359246658 288 | } 289 | }, 290 | { 291 | "doubleSided" : true, 292 | "name" : "FFFFFF", 293 | "pbrMetallicRoughness" : { 294 | "metallicFactor" : 0, 295 | "roughnessFactor" : 0.7448017359246658 296 | } 297 | }, 298 | { 299 | "doubleSided" : true, 300 | "name" : "455A64", 301 | "pbrMetallicRoughness" : { 302 | "baseColorFactor" : [ 0.270588, 0.352941, 0.392157, 1 ], 303 | "metallicFactor" : 0, 304 | "roughnessFactor" : 0.7448017359246658 305 | } 306 | }, 307 | { 308 | "doubleSided" : true, 309 | "name" : "78909C", 310 | "pbrMetallicRoughness" : { 311 | "baseColorFactor" : [ 0.470588, 0.564706, 0.611765, 1 ], 312 | "metallicFactor" : 0, 313 | "roughnessFactor" : 0.7448017359246658 314 | } 315 | }, 316 | { 317 | "doubleSided" : true, 318 | "name" : "80DEEA", 319 | "pbrMetallicRoughness" : { 320 | "baseColorFactor" : [ 0.501961, 0.870588, 0.917647, 1 ], 321 | "metallicFactor" : 0, 322 | "roughnessFactor" : 0.7448017359246658 323 | } 324 | } 325 | ], 326 | "meshes" : [ 327 | { 328 | "name" : "buffer-0-mesh-0", 329 | "primitives" : [ 330 | { 331 | "attributes" : { 332 | "NORMAL" : 2, 333 | "POSITION" : 1, 334 | "TEXCOORD_0" : 3 335 | }, 336 | "indices" : 0, 337 | "material" : 0 338 | }, 339 | { 340 | "attributes" : { 341 | "NORMAL" : 7, 342 | "POSITION" : 6, 343 | "TEXCOORD_0" : 8 344 | }, 345 | "indices" : 5, 346 | "material" : 1 347 | }, 348 | { 349 | "attributes" : { 350 | "NORMAL" : 12, 351 | "POSITION" : 11, 352 | "TEXCOORD_0" : 13 353 | }, 354 | "indices" : 10, 355 | "material" : 2 356 | }, 357 | { 358 | "attributes" : { 359 | "NORMAL" : 17, 360 | "POSITION" : 16, 361 | "TEXCOORD_0" : 18 362 | }, 363 | "indices" : 15, 364 | "material" : 3 365 | }, 366 | { 367 | "attributes" : { 368 | "NORMAL" : 22, 369 | "POSITION" : 21, 370 | "TEXCOORD_0" : 23 371 | }, 372 | "indices" : 20, 373 | "material" : 4 374 | } 375 | ] 376 | } 377 | ], 378 | "nodes" : [ 379 | { 380 | "mesh" : 0, 381 | "name" : "node-0" 382 | } 383 | ], 384 | "scenes" : [ 385 | { 386 | "name" : "scene-0", 387 | "nodes" : [ 0 ] 388 | } 389 | ] 390 | } 391 | --------------------------------------------------------------------------------