Compare commits
101 Commits
Author | SHA1 | Date |
---|---|---|
|
b56aa0d016 | |
|
eb715144b3 | |
|
480161d9a5 | |
|
31e603e295 | |
|
f3bca60420 | |
|
e91115b0cf | |
|
975b1f4f66 | |
|
889093011e | |
|
ee3341c6b3 | |
|
b52ad3e7b9 | |
|
47f740e3ca | |
|
752ecf63b0 | |
|
599bf0b1d0 | |
|
0d11abb1aa | |
|
96c95a8649 | |
|
26c84115ba | |
|
ef7369228d | |
|
c46d33c57c | |
|
d59f59613f | |
|
b0ff6b41ef | |
|
41569ab1b6 | |
|
5b0425c02d | |
|
6374273055 | |
|
548da33664 | |
|
f3502290c4 | |
|
529f28f781 | |
|
76a7367be6 | |
|
a73b163e4e | |
|
8303fd1810 | |
|
8bf324c925 | |
|
5e70d3d69a | |
|
ae1ec73418 | |
|
40dc533d59 | |
|
afb4645347 | |
|
5c22d5fc87 | |
|
c67efe561e | |
|
d6bacd84c6 | |
|
680e6fe694 | |
|
212b0bc0e0 | |
|
42a8b791a7 | |
|
e0a43e34a2 | |
|
9abdd90a41 | |
|
d10f28c122 | |
|
1beda54b11 | |
|
dd9d7a30f8 | |
|
024051b576 | |
|
2401bfad23 | |
|
80d504370c | |
|
a04eb38f03 | |
|
cb8f17be3e | |
|
49e4c939e6 | |
|
e8177659ac | |
|
11dd93aff6 | |
|
37ffe49cdc | |
|
a4f88fee78 | |
|
0ba07b1dec | |
|
c25969dd94 | |
|
5b806289ce | |
|
98ced74b80 | |
|
ea9380baa5 | |
|
672881cd86 | |
|
3a83436ef2 | |
|
fa214fd967 | |
|
26a7239c91 | |
|
8628734c6a | |
|
d6fb7d1a71 | |
|
1228774174 | |
|
3018c6f5bd | |
|
052e101e1c | |
|
85f1f2474d | |
|
ad74138a7c | |
|
432cb4a5cf | |
|
c212317b72 | |
|
7381928803 | |
|
8eaf3a8b49 | |
|
ba8478fbe5 | |
|
44808a4974 | |
|
337e21226b | |
|
481b33053c | |
|
952e4701e2 | |
|
97f5358f95 | |
|
a8e2a24c43 | |
|
4bf4b32e81 | |
|
d918863297 | |
|
7a86dd1991 | |
|
3ca1bce253 | |
|
c3027370e5 | |
|
8c7c808e16 | |
|
87745300ac | |
|
f1a3628d6e | |
|
094c6f4db0 | |
|
58e3b39fce | |
|
cbfe38ac59 | |
|
e183f91dee | |
|
de7032afe8 | |
|
4ef5184b16 | |
|
4b584783d7 | |
|
0cf0430a5d | |
|
6639ee11d0 | |
|
7be7436321 | |
|
219d333ad9 |
.babelrc.eslintrcpackage-lock.jsonpackage.jsonpostcss.config.jswebpack.config.js
.github/workflows
LICENSEREADME.mdbuild
assets
css
index.htmljs
main.bundle.jsmain.bundle.js.mapruntime.bundle.jsruntime.bundle.js.mapvendors.bundle.jsvendors.bundle.js.LICENSE.txtvendors.bundle.js.map
public
src
html
js
public
116
.eslintrc
116
.eslintrc
|
@ -1,60 +1,60 @@
|
|||
{
|
||||
"rules": {
|
||||
"no-cond-assign": 1,
|
||||
"no-console": 1,
|
||||
"no-constant-condition": 1,
|
||||
"no-control-regex": 1,
|
||||
"no-debugger": 1,
|
||||
"no-dupe-args": 1,
|
||||
"no-dupe-keys": 1,
|
||||
"no-duplicate-case": 1,
|
||||
"no-empty-character-class": 1,
|
||||
"no-empty": 1,
|
||||
"no-ex-assign": 1,
|
||||
"no-extra-boolean-cast": 1,
|
||||
"no-extra-semi": 1,
|
||||
"no-func-assign": 1,
|
||||
"no-inner-declarations": 1,
|
||||
"no-invalid-regexp": 1,
|
||||
"no-irregular-whitespace": 1,
|
||||
"no-negated-in-lhs": 1,
|
||||
"no-obj-calls": 1,
|
||||
"no-regex-spaces": 1,
|
||||
"no-sparse-arrays": 1,
|
||||
"no-unreachable": 1,
|
||||
"use-isnan": 1,
|
||||
"valid-typeof": 1,
|
||||
"no-alert": 1,
|
||||
"no-else-return": 1,
|
||||
"no-eval": 1,
|
||||
"no-extra-bind": 1,
|
||||
"no-fallthrough": 1,
|
||||
"no-octal": 1,
|
||||
"no-proto": 1,
|
||||
"no-redeclare": [1, {"builtinGlobals": true}],
|
||||
"no-useless-call": 1,
|
||||
"no-delete-var": 1,
|
||||
"no-undef-init": 1,
|
||||
"no-undef": 1,
|
||||
"no-unused-vars": 1,
|
||||
"camelcase": 1,
|
||||
"eol-last": 1,
|
||||
"indent": [1, 2, {"SwitchCase": 1}],
|
||||
"no-array-constructor": 1,
|
||||
"no-continue": 1,
|
||||
"no-lonely-if": 1,
|
||||
"no-mixed-spaces-and-tabs": 1,
|
||||
"no-new-object": 1,
|
||||
"no-const-assign": 1,
|
||||
"prefer-const": 1,
|
||||
"prefer-spread": 1
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
}
|
||||
"rules": {
|
||||
"no-cond-assign": 1,
|
||||
"no-console": 1,
|
||||
"no-constant-condition": 1,
|
||||
"no-control-regex": 1,
|
||||
"no-debugger": 1,
|
||||
"no-dupe-args": 1,
|
||||
"no-dupe-keys": 1,
|
||||
"no-duplicate-case": 1,
|
||||
"no-empty-character-class": 1,
|
||||
"no-empty": 1,
|
||||
"no-ex-assign": 1,
|
||||
"no-extra-boolean-cast": 1,
|
||||
"no-extra-semi": 1,
|
||||
"no-func-assign": 1,
|
||||
"no-inner-declarations": 1,
|
||||
"no-invalid-regexp": 1,
|
||||
"no-irregular-whitespace": 1,
|
||||
"no-negated-in-lhs": 1,
|
||||
"no-obj-calls": 1,
|
||||
"no-regex-spaces": 1,
|
||||
"no-sparse-arrays": 1,
|
||||
"no-unreachable": 1,
|
||||
"use-isnan": 1,
|
||||
"valid-typeof": 1,
|
||||
"no-alert": 1,
|
||||
"no-else-return": 1,
|
||||
"no-eval": 1,
|
||||
"no-extra-bind": 1,
|
||||
"no-fallthrough": 1,
|
||||
"no-octal": 1,
|
||||
"no-proto": 1,
|
||||
"no-redeclare": [1, {"builtinGlobals": true}],
|
||||
"no-useless-call": 1,
|
||||
"no-delete-var": 1,
|
||||
"no-undef-init": 1,
|
||||
"no-undef": 1,
|
||||
"no-unused-vars": 1,
|
||||
"camelcase": 1,
|
||||
"eol-last": 1,
|
||||
"indent": [1, 2, {"SwitchCase": 1}],
|
||||
"no-array-constructor": 1,
|
||||
"no-continue": 1,
|
||||
"no-lonely-if": 1,
|
||||
"no-mixed-spaces-and-tabs": 1,
|
||||
"no-new-object": 1,
|
||||
"no-const-assign": 1,
|
||||
"prefer-const": 1,
|
||||
"prefer-spread": 1
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: Node.js CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [10.x, 12.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm ci
|
||||
- run: npm run build --if-present
|
||||
- run: npm test
|
||||
env:
|
||||
CI: true
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Paul Graffam
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
65
README.md
65
README.md
|
@ -1,18 +1,29 @@
|
|||
# Three.js Webpack ES6 Boilerplate
|
||||
[GitHub - paulmg/ThreeJS-Webpack-ES6-Boilerplate/](https://github.com/paulmg/ThreeJS-Webpack-ES6-Boilerplate/)
|
||||
|
||||
A basic boilerplate for a Three.js project including the use of Webpack and ES6 syntax via Babel.
|
||||
|
||||
## This Fork
|
||||
|
||||
* Replace `node-sass` with `sass`.
|
||||
* Do not open browser when running `devServer`.
|
||||
|
||||
## Project Structure
|
||||
* build - Directory for built and compressed files from the npm build script
|
||||
* src - Directory for all dev files
|
||||
* src/css - Contains all SCSS files, that are compiled to `src/public/assets/css`
|
||||
* src/js - All the Three.js app files, with `app.js` as entry point. Compiled to `src/public/assets/js` with webpack
|
||||
* src/js/app/components - Three.js components that get initialized in `main.js`
|
||||
* src/js/app/helpers - Classes that provide ideas on how to set up and work with defaults
|
||||
* src/js/app/managers - Manage complex tasks such as GUI or input
|
||||
* src/js/app/model - Classes that set up the model object
|
||||
* src/js/data - Any data to be imported into app
|
||||
* src/js/utils - Various helpers and vendor classes
|
||||
* src/public - Used by webpack-dev-server to serve content and is copied over to build folder with build command. Place external vendor files here.
|
||||
```
|
||||
build - Directory for built and compressed files from the npm build script
|
||||
src - Directory for all dev files
|
||||
├── css - Contains all SCSS files, that are compiled to `src/public/css`
|
||||
├── js - All the Three.js app files, with `app.js` as entry point. Compiled to `src/public/js` with webpack
|
||||
│ ├── app
|
||||
│ │ ├── components - Three.js components that get initialized in `main.js`
|
||||
│ │ ├── helpers - Classes that provide ideas on how to set up and work with defaults
|
||||
│ │ ├── managers - Manage complex tasks such as GUI or input
|
||||
│ │ └── model - Classes that set up the model object
|
||||
│ ├── data - Any data to be imported into app
|
||||
│ └── utils - Various helpers and vendor classes
|
||||
└── public - Used by webpack-dev-server to serve content. Webpack builds local dev files here.
|
||||
└── assets - Is copied over to build folder with build command. Place external asset files here.
|
||||
```
|
||||
|
||||
## Getting started
|
||||
Install dependencies:
|
||||
|
@ -27,30 +38,28 @@ Then run dev script:
|
|||
npm run dev
|
||||
```
|
||||
|
||||
Spins up a webpack dev server at localhost:8080 and keeps track of all js and sass changes to files. Only reloads automatically upon save of js files.
|
||||
Spins up a webpack dev server at localhost:8080 and keeps track of all js and sass changes to files.
|
||||
|
||||
## Build
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
Cleans existing build folder while linting js folder and then copies over the public folder from src. Then sets environment to production and compiles js and css into build.
|
||||
Cleans existing build folder while linting js folder and copies over the public assets folder from src. Then sets environment to production and compiles js and css into build.
|
||||
|
||||
## Other NPM Scripts
|
||||
You can run any of these individually if you'd like with the npm run command:
|
||||
* prebuild - Cleans build folder and lints `src/js`
|
||||
* clean - Cleans build folder
|
||||
* lint - Runs lint on `src/js` folder and uses `.eslintrc` file in root as linting rules
|
||||
* webpack-server - Create webpack-dev-server with hot-module-replacement
|
||||
* webpack-watch - Run webpack in dev environment with watch
|
||||
* dev:sass - Run node-sass on `src/css` folder and output to `src/public` and watch for changes
|
||||
* dev:js - Run webpack in dev environment without watch
|
||||
* build:dir - Copy files and folders from `src/public` to `build`
|
||||
* build:sass - Run node-sass on `src/css` and output compressed css to `build` folder
|
||||
* build:js - Run webpack in production environment
|
||||
You can run any of these individually if you'd like with the `npm run` command:
|
||||
* `prebuild` - Cleans up build folder and lints `src/js`
|
||||
* `clean` - Cleans build folder
|
||||
* `lint` - Runs lint on the `src/js` folder and uses the `.eslintrc` file in root for linting rules
|
||||
* `webpack-server` - Start up a webpack-dev-server with hot-module-replacement
|
||||
* `webpack-watch` - Run webpack in dev environment with watch
|
||||
* `dev:js` - Run webpack in dev environment without watch
|
||||
* `build:dir` - Copy files and folders from `src/public` to `build`
|
||||
* `build:js` - Run webpack in production environment
|
||||
|
||||
## Input Controls
|
||||
Press H to hide dat.GUI
|
||||
Arrow controls will pan
|
||||
Mouse left click will rotate/right click will pan
|
||||
Scrollwheel zooms in and out
|
||||
* Press H to hide dat.GUI
|
||||
* Arrow controls will pan
|
||||
* Mouse left click will rotate/right click will pan
|
||||
* Scroll wheel zooms in and out
|
||||
|
|
Binary file not shown.
Binary file not shown.
After ![]() (image error) Size: 16 KiB |
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,219 @@
|
|||
{
|
||||
"asset": {
|
||||
"generator": "COLLADA2GLTF",
|
||||
"version": "2.0"
|
||||
},
|
||||
"scene": 0,
|
||||
"scenes": [
|
||||
{
|
||||
"nodes": [
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodes": [
|
||||
{
|
||||
"children": [
|
||||
2,
|
||||
1
|
||||
],
|
||||
"matrix": [
|
||||
0.009999999776482582,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.009999999776482582,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.009999999776482582,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"matrix": [
|
||||
-0.7289686799049377,
|
||||
0.0,
|
||||
-0.6845470666885376,
|
||||
0.0,
|
||||
-0.4252049028873444,
|
||||
0.7836934328079224,
|
||||
0.4527972936630249,
|
||||
0.0,
|
||||
0.5364750623703003,
|
||||
0.6211478114128113,
|
||||
-0.571287989616394,
|
||||
0.0,
|
||||
400.1130065917969,
|
||||
463.2640075683594,
|
||||
-431.0780334472656,
|
||||
1.0
|
||||
],
|
||||
"camera": 0
|
||||
},
|
||||
{
|
||||
"mesh": 0
|
||||
}
|
||||
],
|
||||
"cameras": [
|
||||
{
|
||||
"perspective": {
|
||||
"aspectRatio": 1.5,
|
||||
"yfov": 0.6605925559997559,
|
||||
"zfar": 10000.0,
|
||||
"znear": 1.0
|
||||
},
|
||||
"type": "perspective"
|
||||
}
|
||||
],
|
||||
"meshes": [
|
||||
{
|
||||
"primitives": [
|
||||
{
|
||||
"attributes": {
|
||||
"NORMAL": 1,
|
||||
"POSITION": 2,
|
||||
"TEXCOORD_0": 3
|
||||
},
|
||||
"indices": 0,
|
||||
"mode": 4,
|
||||
"material": 0
|
||||
}
|
||||
],
|
||||
"name": "LOD3spShape"
|
||||
}
|
||||
],
|
||||
"accessors": [
|
||||
{
|
||||
"bufferView": 0,
|
||||
"byteOffset": 0,
|
||||
"componentType": 5123,
|
||||
"count": 12636,
|
||||
"max": [
|
||||
2398
|
||||
],
|
||||
"min": [
|
||||
0
|
||||
],
|
||||
"type": "SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView": 1,
|
||||
"byteOffset": 0,
|
||||
"componentType": 5126,
|
||||
"count": 2399,
|
||||
"max": [
|
||||
0.9995989799499512,
|
||||
0.999580979347229,
|
||||
0.9984359741210938
|
||||
],
|
||||
"min": [
|
||||
-0.9990839958190918,
|
||||
-1.0,
|
||||
-0.9998319745063782
|
||||
],
|
||||
"type": "VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView": 1,
|
||||
"byteOffset": 28788,
|
||||
"componentType": 5126,
|
||||
"count": 2399,
|
||||
"max": [
|
||||
96.17990112304688,
|
||||
163.97000122070313,
|
||||
53.92519760131836
|
||||
],
|
||||
"min": [
|
||||
-69.29850006103516,
|
||||
9.929369926452637,
|
||||
-61.32819747924805
|
||||
],
|
||||
"type": "VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView": 2,
|
||||
"byteOffset": 0,
|
||||
"componentType": 5126,
|
||||
"count": 2399,
|
||||
"max": [
|
||||
0.9833459854125976,
|
||||
0.9800369739532472
|
||||
],
|
||||
"min": [
|
||||
0.026409000158309938,
|
||||
0.01996302604675293
|
||||
],
|
||||
"type": "VEC2"
|
||||
}
|
||||
],
|
||||
"materials": [
|
||||
{
|
||||
"pbrMetallicRoughness": {
|
||||
"baseColorTexture": {
|
||||
"index": 0
|
||||
},
|
||||
"metallicFactor": 0.0
|
||||
},
|
||||
"emissiveFactor": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"name": "blinn3-fx"
|
||||
}
|
||||
],
|
||||
"textures": [
|
||||
{
|
||||
"sampler": 0,
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"images": [
|
||||
{
|
||||
"uri": "DuckCM.png"
|
||||
}
|
||||
],
|
||||
"samplers": [
|
||||
{
|
||||
"magFilter": 9729,
|
||||
"minFilter": 9986,
|
||||
"wrapS": 10497,
|
||||
"wrapT": 10497
|
||||
}
|
||||
],
|
||||
"bufferViews": [
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 76768,
|
||||
"byteLength": 25272,
|
||||
"target": 34963
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 0,
|
||||
"byteLength": 57576,
|
||||
"byteStride": 12,
|
||||
"target": 34962
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 57576,
|
||||
"byteLength": 19192,
|
||||
"byteStride": 8,
|
||||
"target": 34962
|
||||
}
|
||||
],
|
||||
"buffers": [
|
||||
{
|
||||
"byteLength": 102040,
|
||||
"uri": "Duck0.bin"
|
||||
}
|
||||
]
|
||||
}
|
Before ![]() (image error) Size: 636 KiB After ![]() (image error) Size: 636 KiB ![]() ![]() |
|
@ -0,0 +1 @@
|
|||
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0;font:16px/1 sans-serif;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}blockquote,figure,h1,h2,h3,h4,ol,p,ul{margin:0;padding:0}li,main{display:block}h1,h2,h3,h4{font-size:inherit}strong{font-weight:700}a,button{color:inherit;transition:.3s}a{text-decoration:none}button{overflow:visible;border:0;font:inherit;-webkit-font-smoothing:inherit;letter-spacing:inherit;background:none;cursor:pointer}::-moz-focus-inner{padding:0;border:0}:focus{outline:0}img{max-width:100%;height:auto;border:0}body{overflow:hidden}.main{position:relative;width:100%;height:100vh}#loading{position:absolute;top:calc(50% - 8px);left:calc(50% - 35px)}
|
|
@ -0,0 +1 @@
|
|||
<!doctype html><html lang="en"><head><meta charset="UTF-8"><title>Three.js Webpack ES6 Boilerplate</title><script defer="defer" src="js/runtime.bundle.js"></script><script defer="defer" src="js/vendors.bundle.js"></script><script defer="defer" src="js/main.bundle.js"></script><link href="js/../css/main.css" rel="stylesheet"></head><body><section id="appContainer" class="main"><div id="loading">Loading...</div></section></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
(()=>{"use strict";var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var l=t[e]={exports:{}};return r[e].call(l.exports,l,l.exports,o),l.exports}o.m=r,e=[],o.O=(r,t,n,l)=>{if(!t){var a=1/0;for(s=0;s<e.length;s++){for(var[t,n,l]=e[s],i=!0,u=0;u<t.length;u++)(!1&l||a>=l)&&Object.keys(o.O).every((e=>o.O[e](t[u])))?t.splice(u--,1):(i=!1,l<a&&(a=l));i&&(e.splice(s--,1),r=n())}return r}l=l||0;for(var s=e.length;s>0&&e[s-1][2]>l;s--)e[s]=e[s-1];e[s]=[t,n,l]},o.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return o.d(r,{a:r}),r},o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e={666:0};o.O.j=r=>0===e[r];var r=(r,t)=>{var n,l,[a,i,u]=t,s=0;for(n in i)o.o(i,n)&&(o.m[n]=i[n]);for(u&&u(o),r&&r(t);s<a.length;s++)l=a[s],o.o(e,l)&&e[l]&&e[l][0](),e[a[s]]=0;o.O()},t=self.webpackChunkthreejs_es6_webpack_boilerplate=self.webpackChunkthreejs_es6_webpack_boilerplate||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),o.O()})();
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,7 @@
|
|||
/*!
|
||||
* @overview es6-promise - a tiny implementation of Promises/A+.
|
||||
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
|
||||
* @license Licensed under MIT license
|
||||
* See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
|
||||
* @version v4.2.8+1e68dce6
|
||||
*/
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0;font:16px/1 sans-serif;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}h1,h2,h3,h4,p,blockquote,figure,ol,ul{margin:0;padding:0}main,li{display:block}h1,h2,h3,h4{font-size:inherit}strong{font-weight:bold}a,button{color:inherit;transition:.3s}a{text-decoration:none}button{overflow:visible;border:0;font:inherit;-webkit-font-smoothing:inherit;letter-spacing:inherit;background:none;cursor:pointer}::-moz-focus-inner{padding:0;border:0}:focus{outline:0}img{max-width:100%;height:auto;border:0}body{overflow:hidden}.main{position:relative;width:100%;height:100vh}#loading{position:absolute;top:calc(50% - 8px);left:calc(50% - 35px)}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,19 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Three.js Webpack ES6 Boilerplate</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="./assets/css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
<section id="appContainer" class="main">
|
||||
<div id="loading">Loading...</div>
|
||||
</section>
|
||||
|
||||
<script src="./assets/js/rStats.js"></script>
|
||||
<script src="./assets/js/rStats.extras.js"></script>
|
||||
<script src="./assets/js/dat.gui.min.js"></script>
|
||||
<script src="./assets/js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
61
package.json
61
package.json
|
@ -1,42 +1,49 @@
|
|||
{
|
||||
"name": "threejs-es6-webpack-boilerplate",
|
||||
"version": "1.0.0",
|
||||
"version": "1.6.1",
|
||||
"description": "Boilerplate for Three.js projects set up with Babel for ES6 and compiled with webpack",
|
||||
"author": "Paul Graffam",
|
||||
"main": "app.js",
|
||||
"engines": {
|
||||
"node": ">=10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "run-p dev:sass webpack-server webpack-watch",
|
||||
"build": "run-s prebuild build:dir build:js build:sass",
|
||||
"dev": "run-s dev:js webpack-server",
|
||||
"build": "run-s build:dir build:js",
|
||||
"prebuild": "run-s clean lint",
|
||||
"clean": "rimraf build",
|
||||
"lint": "eslint src/js/",
|
||||
"webpack-server": "set NODE_ENV=0&& webpack-dev-server --progress --colors --hot --inline --open",
|
||||
"webpack-watch": "set NODE_ENV=0&& webpack --progress --colors --watch --cache",
|
||||
"dev:sass": "node-sass -w -r src/css/ -o src/public/assets/css/",
|
||||
"dev:js": "set NODE_ENV=0&& webpack",
|
||||
"build:dir": "copyfiles -u 1 src/public/**/* build/",
|
||||
"build:sass": "node-sass --output-style compressed src/css/ -o build/public/assets/css/",
|
||||
"build:js": "set NODE_ENV=1&& webpack"
|
||||
"webpack-server": "webpack serve --env NODE_ENV=dev --progress --color --open --hot",
|
||||
"webpack-watch": "webpack --env NODE_ENV=dev --progress --color --watch --hot",
|
||||
"dev:js": "webpack --env NODE_ENV=dev",
|
||||
"build:dir": "copyfiles -a -u 2 src/public/assets/**/*.* build/",
|
||||
"build:js": "webpack --env NODE_ENV=prod --progress --color"
|
||||
},
|
||||
"dependencies": {
|
||||
"es6-promise": "^4.0.5",
|
||||
"three": "0.81.2",
|
||||
"tween.js": "16.3.0"
|
||||
"@tweenjs/tween.js": "^18.6.4",
|
||||
"es6-promise": "^4.2.8",
|
||||
"three": "^0.126.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.17.0",
|
||||
"babel-loader": "^6.2.5",
|
||||
"babel-preset-es2015": "^6.16.0",
|
||||
"copyfiles": "^1.0.0",
|
||||
"eslint": "^3.7.1",
|
||||
"node-sass": "^3.10.1",
|
||||
"npm-run-all": "^3.0.0",
|
||||
"rimraf": "^2.5.4",
|
||||
"webpack": "^1.13.2",
|
||||
"webpack-dev-middleware": "^1.8.3",
|
||||
"webpack-dev-server": "^1.16.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "6.0.0"
|
||||
"@babel/core": "^7.13.10",
|
||||
"@babel/preset-env": "^7.13.12",
|
||||
"autoprefixer": "^10.2.5",
|
||||
"babel-loader": "^8.2.2",
|
||||
"copyfiles": "^2.4.1",
|
||||
"css-loader": "^5.2.0",
|
||||
"eslint": "^7.22.0",
|
||||
"html-webpack-plugin": "^5.3.1",
|
||||
"mini-css-extract-plugin": "^1.3.9",
|
||||
"sass": "^1.34.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||
"postcss-loader": "^5.2.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"sass-loader": "^11.0.1",
|
||||
"style-loader": "^2.0.0",
|
||||
"terser-webpack-plugin": "^5.1.1",
|
||||
"webpack": "^5.28.0",
|
||||
"webpack-cli": "^4.5.0",
|
||||
"webpack-dev-server": "^4.0.0-beta.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer'),
|
||||
],
|
||||
};
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section id="appContainer" class="main">
|
||||
<div id="loading">Loading...</div>
|
||||
</section>
|
||||
|
||||
<% if (htmlWebpackPlugin.options.env === 'dev') { %>
|
||||
<script src="js/rStats.js"></script>
|
||||
<script src="js/rStats.extras.js"></script>
|
||||
<script src="js/dat.gui.min.js"></script>
|
||||
<% } %>
|
||||
</body>
|
||||
</html>
|
|
@ -2,8 +2,11 @@ import Config from './data/config';
|
|||
import Detector from './utils/detector';
|
||||
import Main from './app/main';
|
||||
|
||||
// Styles
|
||||
import './../css/app.scss';
|
||||
|
||||
// Check environment and set the Config helper
|
||||
if(__ENV__ == 'dev') {
|
||||
if(__ENV__ === 'dev') {
|
||||
console.log('----- RUNNING IN DEV ENVIRONMENT! -----');
|
||||
|
||||
Config.isDev = true;
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as THREE from 'three';
|
|||
|
||||
export default class Animation {
|
||||
constructor(obj, clip) {
|
||||
// Object with animations
|
||||
// Scene that the clip will be applied to
|
||||
this.obj = obj;
|
||||
|
||||
// Initialize animation mixer
|
|
@ -20,8 +20,8 @@ export default class Camera {
|
|||
}
|
||||
|
||||
updateSize(renderer) {
|
||||
// Multiply by dpr in case it is retina device
|
||||
this.threeCamera.aspect = renderer.domElement.width * Config.dpr / renderer.domElement.height * Config.dpr;
|
||||
// Update camera aspect ratio with window aspect ratio
|
||||
this.threeCamera.aspect = renderer.domElement.width / renderer.domElement.height;
|
||||
|
||||
// Always call updateProjectionMatrix on camera change
|
||||
this.threeCamera.updateProjectionMatrix();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import * as THREE from 'three';
|
||||
|
||||
import Material from './material';
|
||||
|
||||
import Config from '../../data/config';
|
||||
|
||||
// This helper class can be used to create and then place geometry in the scene
|
||||
|
@ -12,13 +11,13 @@ export default class Geometry {
|
|||
}
|
||||
|
||||
make(type) {
|
||||
if(type == 'plane') {
|
||||
if(type === 'plane') {
|
||||
return (width, height, widthSegments = 1, heightSegments = 1) => {
|
||||
this.geo = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments);
|
||||
};
|
||||
}
|
||||
|
||||
if(type == 'sphere') {
|
||||
if(type === 'sphere') {
|
||||
return (radius, widthSegments = 32, heightSegments = 32) => {
|
||||
this.geo = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
|
||||
};
|
|
@ -38,9 +38,10 @@ export default class Light {
|
|||
this.directionalLight.shadow.mapSize.height = Config.shadow.mapHeight;
|
||||
|
||||
// Shadow camera helper
|
||||
this.directionalLightHelper = new THREE.CameraHelper(this.directionalLight.shadow.camera);
|
||||
this.directionalLightHelper.visible = Config.shadow.helperEnabled;
|
||||
|
||||
if(Config.isDev) {
|
||||
this.directionalLightHelper = new THREE.CameraHelper(this.directionalLight.shadow.camera);
|
||||
this.directionalLightHelper.visible = Config.shadow.helperEnabled;
|
||||
}
|
||||
// Hemisphere light
|
||||
this.hemiLight = new THREE.HemisphereLight(Config.hemiLight.color, Config.hemiLight.groundColor, Config.hemiLight.intensity);
|
||||
this.hemiLight.position.set(Config.hemiLight.x, Config.hemiLight.y, Config.hemiLight.z);
|
||||
|
@ -55,7 +56,9 @@ export default class Light {
|
|||
|
||||
case 'directional':
|
||||
this.scene.add(this.directionalLight);
|
||||
this.scene.add(this.directionalLightHelper);
|
||||
if(Config.isDev) {
|
||||
this.scene.add(this.directionalLightHelper);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'point':
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import * as THREE from 'three';
|
||||
|
||||
import Config from '../../data/config';
|
||||
|
||||
// USe this class as a helper to set up some default materials
|
||||
export default class Material {
|
||||
constructor(color) {
|
|
@ -24,7 +24,7 @@ export default class Renderer {
|
|||
this.threeRenderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||
|
||||
// Get anisotropy for textures
|
||||
Config.maxAnisotropy = this.threeRenderer.getMaxAnisotropy();
|
||||
Config.maxAnisotropy = this.threeRenderer.capabilities.getMaxAnisotropy();
|
||||
|
||||
// Initial size update set to canvas container
|
||||
this.updateSize();
|
||||
|
|
|
@ -1,24 +1,41 @@
|
|||
import * as THREE from 'three';
|
||||
import { VertexNormalsHelper } from './vertexNormalsHelper';
|
||||
|
||||
// Simple mesh helper that shows edges, wireframes, and face and vertex normals
|
||||
export default class MeshHelper {
|
||||
constructor(scene, mesh) {
|
||||
const wireframe = new THREE.WireframeGeometry(mesh.geometry);
|
||||
const wireLine = new THREE.LineSegments(wireframe);
|
||||
wireLine.material.depthTest = false;
|
||||
wireLine.material.opacity = 0.25;
|
||||
wireLine.material.transparent = true;
|
||||
mesh.add(wireLine);
|
||||
this.mesh = mesh;
|
||||
this.scene = scene;
|
||||
|
||||
const edges = new THREE.EdgesGeometry(mesh.geometry);
|
||||
const edgesLine = new THREE.LineSegments(edges);
|
||||
edgesLine.material.depthTest = false;
|
||||
edgesLine.material.opacity = 0.25;
|
||||
edgesLine.material.transparent = true;
|
||||
mesh.add(edgesLine);
|
||||
const wireframe = new THREE.WireframeGeometry(this.mesh.geometry);
|
||||
this.wireLine = new THREE.LineSegments(wireframe);
|
||||
this.wireLine.material.depthTest = false;
|
||||
this.wireLine.material.opacity = 0.25;
|
||||
this.wireLine.material.transparent = true;
|
||||
|
||||
scene.add(new THREE.BoxHelper(mesh));
|
||||
scene.add(new THREE.FaceNormalsHelper(mesh, 2));
|
||||
scene.add(new THREE.VertexNormalsHelper(mesh, 2));
|
||||
const edges = new THREE.EdgesGeometry(this.mesh.geometry);
|
||||
this.edgesLine = new THREE.LineSegments(edges);
|
||||
this.edgesLine.material.depthTest = false;
|
||||
this.edgesLine.material.opacity = 0.25;
|
||||
this.edgesLine.material.transparent = true;
|
||||
|
||||
this.vertexHelper = new VertexNormalsHelper(this.mesh, 2);
|
||||
this.boxHelper = new THREE.BoxHelper(this.mesh);
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.mesh.add(this.wireLine);
|
||||
this.mesh.add(this.edgesLine);
|
||||
|
||||
this.scene.add(this.vertexHelper);
|
||||
this.scene.add(this.boxHelper);
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.mesh.remove(this.wireLine);
|
||||
this.mesh.remove(this.edgesLine);
|
||||
|
||||
this.scene.remove(this.vertexHelper);
|
||||
this.scene.remove(this.boxHelper);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// Local vars for rStats
|
||||
let rS, bS, glS, tS;
|
||||
|
||||
export default class Stats {
|
||||
constructor(renderer) {
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
setUp() {
|
||||
bS = new BrowserStats();
|
||||
glS = new glStats();
|
||||
tS = new threeStats(this.renderer.threeRenderer);
|
||||
|
||||
rS = new rStats({
|
||||
CSSPath: './css/',
|
||||
userTimingAPI: true,
|
||||
values: {
|
||||
frame: { caption: 'Total frame time (ms)', over: 16, average: true, avgMs: 100 },
|
||||
fps: { caption: 'Framerate (FPS)', below: 30 },
|
||||
calls: { caption: 'Calls (three.js)', over: 3000 },
|
||||
raf: { caption: 'Time since last rAF (ms)', average: true, avgMs: 100 },
|
||||
rstats: { caption: 'rStats update (ms)', average: true, avgMs: 100 },
|
||||
texture: { caption: 'GenTex', average: true, avgMs: 100 }
|
||||
},
|
||||
groups: [
|
||||
{ caption: 'Framerate', values: ['fps', 'raf'] },
|
||||
{ caption: 'Frame Budget', values: ['frame', 'texture', 'setup', 'render'] }
|
||||
],
|
||||
fractions: [
|
||||
{ base: 'frame', steps: ['texture', 'setup', 'render'] }
|
||||
],
|
||||
plugins: [bS, tS]
|
||||
});
|
||||
}
|
||||
|
||||
static start() {
|
||||
rS('frame').start();
|
||||
glS.start();
|
||||
|
||||
rS('rAF').tick();
|
||||
rS('FPS').frame();
|
||||
|
||||
rS('render').start();
|
||||
}
|
||||
|
||||
static end() {
|
||||
rS('render').end(); // render finished
|
||||
rS('frame').end(); // frame finished
|
||||
|
||||
// Local rStats update
|
||||
rS('rStats').start();
|
||||
rS().update();
|
||||
rS('rStats').end();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
import {
|
||||
BufferGeometry,
|
||||
Float32BufferAttribute,
|
||||
LineSegments,
|
||||
LineBasicMaterial,
|
||||
Matrix3,
|
||||
Vector3,
|
||||
} from 'three';
|
||||
|
||||
const _v1 = new Vector3();
|
||||
const _v2 = new Vector3();
|
||||
const _normalMatrix = new Matrix3();
|
||||
const _keys = ['a', 'b', 'c'];
|
||||
|
||||
function VertexNormalsHelper(object, size, hex) {
|
||||
this.object = object;
|
||||
this.size = size !== undefined ? size : 0.1;
|
||||
|
||||
const color = hex !== undefined ? hex : 0xff0000;
|
||||
|
||||
//
|
||||
|
||||
let nNormals = 0;
|
||||
|
||||
const objGeometry = this.object.geometry;
|
||||
|
||||
if (objGeometry && objGeometry.isGeometry) {
|
||||
nNormals = objGeometry.faces.length * 3;
|
||||
} else if (objGeometry && objGeometry.isBufferGeometry) {
|
||||
nNormals = objGeometry.attributes.normal.count;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const geometry = new BufferGeometry();
|
||||
const positions = new Float32BufferAttribute(nNormals * 2 * 3, 3);
|
||||
|
||||
geometry.setAttribute('position', positions);
|
||||
|
||||
LineSegments.call(this, geometry, new LineBasicMaterial({ color: color, toneMapped: false }));
|
||||
|
||||
this.type = 'VertexNormalsHelper';
|
||||
|
||||
//
|
||||
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
VertexNormalsHelper.prototype = Object.create(LineSegments.prototype);
|
||||
VertexNormalsHelper.prototype.constructor = VertexNormalsHelper;
|
||||
|
||||
VertexNormalsHelper.prototype.update = function () {
|
||||
let idx;
|
||||
this.object.updateMatrixWorld(true);
|
||||
|
||||
_normalMatrix.getNormalMatrix(this.object.matrixWorld);
|
||||
|
||||
const matrixWorld = this.object.matrixWorld;
|
||||
const position = this.geometry.attributes.position;
|
||||
|
||||
//
|
||||
|
||||
const objGeometry = this.object.geometry;
|
||||
|
||||
if (objGeometry && objGeometry.isGeometry) {
|
||||
const vertices = objGeometry.vertices;
|
||||
|
||||
const faces = objGeometry.faces;
|
||||
|
||||
idx = 0;
|
||||
|
||||
for (let i = 0, l = faces.length; i < l; i++) {
|
||||
const face = faces[i];
|
||||
|
||||
for (let j = 0, jl = face.vertexNormals.length; j < jl; j++) {
|
||||
const vertex = vertices[face[_keys[j]]];
|
||||
const normal = face.vertexNormals[j];
|
||||
|
||||
_v1.copy(vertex).applyMatrix4(matrixWorld);
|
||||
_v2.copy(normal).applyMatrix3(_normalMatrix).normalize().multiplyScalar(this.size).add(_v1);
|
||||
|
||||
position.setXYZ(idx, _v1.x, _v1.y, _v1.z);
|
||||
|
||||
idx = idx + 1;
|
||||
|
||||
position.setXYZ(idx, _v2.x, _v2.y, _v2.z);
|
||||
|
||||
idx = idx + 1;
|
||||
}
|
||||
}
|
||||
} else if (objGeometry && objGeometry.isBufferGeometry) {
|
||||
const objPos = objGeometry.attributes.position;
|
||||
const objNorm = objGeometry.attributes.normal;
|
||||
|
||||
idx = 0;
|
||||
|
||||
// for simplicity, ignore index and drawcalls, and render every normal
|
||||
|
||||
for (var j = 0, jl = objPos.count; j < jl; j++) {
|
||||
_v1.set(objPos.getX(j), objPos.getY(j), objPos.getZ(j)).applyMatrix4(matrixWorld);
|
||||
_v2.set(objNorm.getX(j), objNorm.getY(j), objNorm.getZ(j));
|
||||
_v2.applyMatrix3(_normalMatrix).normalize().multiplyScalar(this.size).add(_v1);
|
||||
|
||||
position.setXYZ(idx, _v1.x, _v1.y, _v1.z);
|
||||
|
||||
idx = idx + 1;
|
||||
|
||||
position.setXYZ(idx, _v2.x, _v2.y, _v2.z);
|
||||
|
||||
idx = idx + 1;
|
||||
}
|
||||
}
|
||||
|
||||
position.needsUpdate = true;
|
||||
};
|
||||
|
||||
export { VertexNormalsHelper };
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
// Global imports -
|
||||
import * as THREE from 'three';
|
||||
import TWEEN from 'tween.js';
|
||||
import TWEEN from '@tweenjs/tween.js';
|
||||
|
||||
// Local imports -
|
||||
// Components
|
||||
|
@ -8,9 +8,11 @@ import Renderer from './components/renderer';
|
|||
import Camera from './components/camera';
|
||||
import Light from './components/light';
|
||||
import Controls from './components/controls';
|
||||
import Geometry from './components/geometry';
|
||||
|
||||
// Helpers
|
||||
import Geometry from './helpers/geometry';
|
||||
import Stats from './helpers/stats';
|
||||
import MeshHelper from './helpers/meshHelper';
|
||||
|
||||
// Model
|
||||
import Texture from './model/texture';
|
||||
|
@ -24,10 +26,6 @@ import DatGUI from './managers/datGUI';
|
|||
import Config from './../data/config';
|
||||
// -- End of imports
|
||||
|
||||
// Local vars for rStats
|
||||
let rS, bS, glS, tS;
|
||||
|
||||
|
||||
// This class instantiates and ties all of the components together, starts the loading process and renders the main loop
|
||||
export default class Main {
|
||||
constructor(container) {
|
||||
|
@ -46,51 +44,32 @@ export default class Main {
|
|||
Config.dpr = window.devicePixelRatio;
|
||||
}
|
||||
|
||||
// Main renderer instantiation
|
||||
// Main renderer constructor
|
||||
this.renderer = new Renderer(this.scene, container);
|
||||
|
||||
// Components instantiation
|
||||
// Components instantiations
|
||||
this.camera = new Camera(this.renderer.threeRenderer);
|
||||
this.controls = new Controls(this.camera.threeCamera, container);
|
||||
this.light = new Light(this.scene);
|
||||
|
||||
// Create and place lights in scene
|
||||
const lights = ['ambient', 'directional', 'point', 'hemi'];
|
||||
for(let i = 0; i < lights.length; i++) {
|
||||
this.light.place(lights[i]);
|
||||
}
|
||||
lights.forEach((light) => this.light.place(light));
|
||||
|
||||
// Create and place geo in scene
|
||||
this.geometry = new Geometry(this.scene);
|
||||
this.geometry.make('plane')(150, 150, 10, 10);
|
||||
this.geometry.place([0, -20, 0], [Math.PI/2, 0, 0]);
|
||||
this.geometry.place([0, -20, 0], [Math.PI / 2, 0, 0]);
|
||||
|
||||
// Set up rStats if dev environment
|
||||
if(Config.isDev) {
|
||||
bS = new BrowserStats();
|
||||
glS = new glStats();
|
||||
tS = new threeStats(this.renderer.threeRenderer);
|
||||
if(Config.isDev && Config.isShowingStats) {
|
||||
this.stats = new Stats(this.renderer);
|
||||
this.stats.setUp();
|
||||
}
|
||||
|
||||
rS = new rStats({
|
||||
CSSPath: './assets/css/',
|
||||
userTimingAPI: true,
|
||||
values: {
|
||||
frame: { caption: 'Total frame time (ms)', over: 16, average: true, avgMs: 100 },
|
||||
fps: { caption: 'Framerate (FPS)', below: 30 },
|
||||
calls: { caption: 'Calls (three.js)', over: 3000 },
|
||||
raf: { caption: 'Time since last rAF (ms)', average: true, avgMs: 100 },
|
||||
rstats: { caption: 'rStats update (ms)', average: true, avgMs: 100 },
|
||||
texture: { caption: 'GenTex', average: true, avgMs: 100 }
|
||||
},
|
||||
groups: [
|
||||
{ caption: 'Framerate', values: [ 'fps', 'raf' ] },
|
||||
{ caption: 'Frame Budget', values: [ 'frame', 'texture', 'setup', 'render' ] }
|
||||
],
|
||||
fractions: [
|
||||
{ base: 'frame', steps: [ 'texture', 'setup', 'render' ] }
|
||||
],
|
||||
plugins: [bS, tS, glS]
|
||||
});
|
||||
// Set up gui
|
||||
if (Config.isDev) {
|
||||
this.gui = new DatGUI(this)
|
||||
}
|
||||
|
||||
// Instantiate texture class
|
||||
|
@ -102,7 +81,7 @@ export default class Main {
|
|||
|
||||
// Textures loaded, load model
|
||||
this.model = new Model(this.scene, this.manager, this.texture.textures);
|
||||
this.model.load();
|
||||
this.model.load(Config.models[Config.model.selected].type);
|
||||
|
||||
// onProgress callback
|
||||
this.manager.onProgress = (item, loaded, total) => {
|
||||
|
@ -116,7 +95,10 @@ export default class Main {
|
|||
|
||||
// Add dat.GUI controls if dev
|
||||
if(Config.isDev) {
|
||||
new DatGUI(this, this.model.obj);
|
||||
this.meshHelper = new MeshHelper(this.scene, this.model.obj);
|
||||
if (Config.mesh.enableHelper) this.meshHelper.enable();
|
||||
|
||||
this.gui.load(this, this.model.obj);
|
||||
}
|
||||
|
||||
// Everything is now fully loaded
|
||||
|
@ -131,34 +113,22 @@ export default class Main {
|
|||
|
||||
render() {
|
||||
// Render rStats if Dev
|
||||
if(Config.isDev) {
|
||||
rS('frame').start();
|
||||
glS.start();
|
||||
|
||||
rS('rAF').tick();
|
||||
rS('FPS').frame();
|
||||
|
||||
rS('render').start();
|
||||
if(Config.isDev && Config.isShowingStats) {
|
||||
Stats.start();
|
||||
}
|
||||
|
||||
// Call render function and pass in created scene and camera
|
||||
this.renderer.render(this.scene, this.camera.threeCamera);
|
||||
|
||||
// rStats has finished determining render call now
|
||||
if(Config.isDev) {
|
||||
rS('render').end(); // render finished
|
||||
rS('frame').end(); // frame finished
|
||||
|
||||
// Local rStats update
|
||||
rS('rStats').start();
|
||||
rS().update();
|
||||
rS('rStats').end();
|
||||
if(Config.isDev && Config.isShowingStats) {
|
||||
Stats.end();
|
||||
}
|
||||
|
||||
// Delta time is sometimes needed for certain updates
|
||||
//const delta = this.clock.getDelta();
|
||||
|
||||
// Call any vendor or module updates here
|
||||
// Call any vendor or module frame updates here
|
||||
TWEEN.update();
|
||||
this.controls.threeControls.update();
|
||||
|
||||
|
|
|
@ -2,18 +2,27 @@ import Config from '../../data/config';
|
|||
|
||||
// Manages all dat.GUI interactions
|
||||
export default class DatGUI {
|
||||
constructor(main, mesh) {
|
||||
const gui = new dat.GUI();
|
||||
constructor(main) {
|
||||
this.gui = new dat.GUI();
|
||||
|
||||
this.camera = main.camera.threeCamera;
|
||||
this.controls = main.controls.threeControls;
|
||||
this.light = main.light;
|
||||
this.scene = main.scene;
|
||||
|
||||
this.model = null;
|
||||
this.meshHelper = null;
|
||||
}
|
||||
|
||||
load(main, mesh) {
|
||||
/* Global */
|
||||
//gui.close();
|
||||
//this.gui.close();
|
||||
|
||||
this.model = main.model;
|
||||
this.meshHelper = main.meshHelper;
|
||||
|
||||
/* Camera */
|
||||
const cameraFolder = gui.addFolder('Camera');
|
||||
const cameraFolder = this.gui.addFolder('Camera');
|
||||
const cameraFOVGui = cameraFolder.add(Config.camera, 'fov', 0, 180).name('Camera FOV');
|
||||
cameraFOVGui.onChange((value) => {
|
||||
this.controls.enableRotate = false;
|
||||
|
@ -38,13 +47,13 @@ export default class DatGUI {
|
|||
});
|
||||
const cameraFogColorGui = cameraFolder.addColor(Config.fog, 'color').name('Fog Color');
|
||||
cameraFogColorGui.onChange((value) => {
|
||||
main.scene.fog.color.setHex(value);
|
||||
this.scene.fog.color.setHex(value);
|
||||
});
|
||||
const cameraFogNearGui = cameraFolder.add(Config.fog, 'near', 0.000, 0.010).name('Fog Near');
|
||||
cameraFogNearGui.onChange((value) => {
|
||||
this.controls.enableRotate = false;
|
||||
|
||||
main.scene.fog.density = value;
|
||||
this.scene.fog.density = value;
|
||||
});
|
||||
cameraFogNearGui.onFinishChange(() => {
|
||||
this.controls.enableRotate = true;
|
||||
|
@ -52,7 +61,7 @@ export default class DatGUI {
|
|||
|
||||
|
||||
/* Controls */
|
||||
const controlsFolder = gui.addFolder('Controls');
|
||||
const controlsFolder = this.gui.addFolder('Controls');
|
||||
controlsFolder.add(Config.controls, 'autoRotate').name('Auto Rotate').onChange((value) => {
|
||||
this.controls.autoRotate = value;
|
||||
});
|
||||
|
@ -66,8 +75,29 @@ export default class DatGUI {
|
|||
});
|
||||
|
||||
|
||||
/* Model */
|
||||
const modelFolder = this.gui.addFolder('Model');
|
||||
modelFolder.add(Config.model, 'type', [...Config.model.initialTypes]).name('Select Model').onChange((value) => {
|
||||
if (value) {
|
||||
if (Config.mesh.enableHelper)
|
||||
this.meshHelper.disable();
|
||||
|
||||
Config.model.selected = Config.model.initialTypes.indexOf(value);
|
||||
this.unload();
|
||||
this.model.unload();
|
||||
this.model.load(value);
|
||||
}
|
||||
});
|
||||
|
||||
/* Mesh */
|
||||
const meshFolder = gui.addFolder('Mesh');
|
||||
const meshFolder = this.gui.addFolder('Mesh');
|
||||
meshFolder.add(Config.mesh, 'enableHelper', true).name('Enable Helpers').onChange((value) => {
|
||||
if(value) {
|
||||
this.meshHelper.enable();
|
||||
} else {
|
||||
this.meshHelper.disable();
|
||||
}
|
||||
});
|
||||
meshFolder.add(Config.mesh, 'translucent', true).name('Translucent').onChange((value) => {
|
||||
if(value) {
|
||||
mesh.material.transparent = true;
|
||||
|
@ -83,7 +113,7 @@ export default class DatGUI {
|
|||
|
||||
/* Lights */
|
||||
// Ambient Light
|
||||
const ambientLightFolder = gui.addFolder('Ambient Light');
|
||||
const ambientLightFolder = this.gui.addFolder('Ambient Light');
|
||||
ambientLightFolder.add(Config.ambientLight, 'enabled').name('Enabled').onChange((value) => {
|
||||
this.light.ambientLight.visible = value;
|
||||
});
|
||||
|
@ -93,7 +123,7 @@ export default class DatGUI {
|
|||
|
||||
|
||||
// Directional Light
|
||||
const directionalLightFolder = gui.addFolder('Directional Light');
|
||||
const directionalLightFolder = this.gui.addFolder('Directional Light');
|
||||
directionalLightFolder.add(Config.directionalLight, 'enabled').name('Enabled').onChange((value) => {
|
||||
this.light.directionalLight.visible = value;
|
||||
});
|
||||
|
@ -138,7 +168,7 @@ export default class DatGUI {
|
|||
});
|
||||
|
||||
// Shadow Map
|
||||
const shadowFolder = gui.addFolder('Shadow Map');
|
||||
const shadowFolder = this.gui.addFolder('Shadow Map');
|
||||
shadowFolder.add(Config.shadow, 'enabled').name('Enabled').onChange((value) => {
|
||||
this.light.directionalLight.castShadow = value;
|
||||
});
|
||||
|
@ -232,7 +262,7 @@ export default class DatGUI {
|
|||
|
||||
|
||||
// Point Light
|
||||
const pointLightFolder = gui.addFolder('Point Light');
|
||||
const pointLightFolder = this.gui.addFolder('Point Light');
|
||||
pointLightFolder.add(Config.pointLight, 'enabled').name('Enabled').onChange((value) => {
|
||||
this.light.pointLight.visible = value;
|
||||
});
|
||||
|
@ -287,7 +317,7 @@ export default class DatGUI {
|
|||
|
||||
|
||||
// Hemi Light
|
||||
const hemiLightFolder = gui.addFolder('Hemi Light');
|
||||
const hemiLightFolder = this.gui.addFolder('Hemi Light');
|
||||
hemiLightFolder.add(Config.hemiLight, 'enabled').name('Enabled').onChange((value) => {
|
||||
this.light.hemiLight.visible = value;
|
||||
});
|
||||
|
@ -334,4 +364,9 @@ export default class DatGUI {
|
|||
this.controls.enableRotate = true;
|
||||
});
|
||||
}
|
||||
|
||||
unload() {
|
||||
this.gui.destroy();
|
||||
this.gui = new dat.GUI();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import * as THREE from 'three';
|
||||
|
||||
import Material from '../helpers/material';
|
||||
import MeshHelper from '../helpers/meshHelper';
|
||||
import Material from '../components/material';
|
||||
import Helpers from '../../utils/helpers';
|
||||
import { BufferGeometryUtils } from '../../utils/bufferGeometryUtils';
|
||||
import { GLTFLoader } from '../loaders/GLTFLoader';
|
||||
import Config from '../../data/config';
|
||||
|
||||
// Loads in a single object from the config file
|
||||
|
@ -10,40 +11,91 @@ export default class Model {
|
|||
constructor(scene, manager, textures) {
|
||||
this.scene = scene;
|
||||
this.textures = textures;
|
||||
this.manager = manager;
|
||||
|
||||
// Manager is passed in to loader to determine when loading done in main
|
||||
this.loader = new THREE.ObjectLoader(manager);
|
||||
this.obj = null;
|
||||
this.ref = null;
|
||||
}
|
||||
|
||||
load() {
|
||||
// Load model with ObjectLoader
|
||||
this.loader.load(Config.model.path, obj => {
|
||||
obj.traverse(child => {
|
||||
if(child instanceof THREE.Mesh) {
|
||||
// Create material for mesh and set its map to texture by name from preloaded textures
|
||||
const material = new Material(0xffffff).standard;
|
||||
material.map = this.textures.UV;
|
||||
child.material = material;
|
||||
load(type) {
|
||||
// Manager is passed in to loader to determine when loading done in main
|
||||
|
||||
// Set to cast and receive shadow if enabled
|
||||
if(Config.shadow.enabled) {
|
||||
child.receiveShadow = true;
|
||||
child.castShadow = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
switch (type) {
|
||||
case 'gltf':
|
||||
// Load model with selected loader
|
||||
new GLTFLoader(this.manager).load(
|
||||
Config.models[Config.model.selected].path,
|
||||
(gltf) => {
|
||||
const scene = gltf.scene;
|
||||
let mesh;
|
||||
|
||||
// Add mesh helper if Dev
|
||||
if(Config.isDev && Config.mesh.enableHelper) {
|
||||
new MeshHelper(this.scene, obj);
|
||||
}
|
||||
if (Config.shadow.enabled) {
|
||||
scene.traverse(function(node) {
|
||||
if (node.isMesh || node.isLight) node.castShadow = true;
|
||||
if (node.isMesh) {
|
||||
node.material.wireframe = Config.mesh.wireframe;
|
||||
mesh = node;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Set prop to obj
|
||||
this.obj = obj;
|
||||
this.obj = mesh;
|
||||
|
||||
obj.scale.multiplyScalar(Config.model.scale);
|
||||
this.scene.add(obj);
|
||||
}, Helpers.logProgress(), Helpers.logError());
|
||||
BufferGeometryUtils.computeTangents(mesh.geometry);
|
||||
|
||||
var group = new THREE.Group();
|
||||
group.scale.multiplyScalar(0.25);
|
||||
this.scene.add( group );
|
||||
|
||||
this.ref = group;
|
||||
|
||||
// To make sure that the matrixWorld is up to date for the boxhelpers
|
||||
group.updateMatrixWorld(true);
|
||||
group.add(mesh);
|
||||
|
||||
// Add to scene
|
||||
this.scene.add(scene);
|
||||
},
|
||||
Helpers.logProgress(),
|
||||
Helpers.logError()
|
||||
);
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
// Load model with ObjectLoader
|
||||
new THREE.ObjectLoader(this.manager).load(
|
||||
Config.models[Config.model.selected].path,
|
||||
obj => {
|
||||
obj.traverse(child => {
|
||||
if(child instanceof THREE.Mesh) {
|
||||
// Create material for mesh and set its map to texture by name from preloaded textures
|
||||
const material = new Material(0xffffff).standard;
|
||||
material.map = this.textures.UV;
|
||||
child.material = material;
|
||||
|
||||
// Set to cast and receive shadow if enabled
|
||||
if(Config.shadow.enabled) {
|
||||
child.receiveShadow = true;
|
||||
child.castShadow = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Set prop to obj so it can be accessed from outside the class
|
||||
this.obj = obj;
|
||||
this.ref = obj;
|
||||
|
||||
obj.scale.multiplyScalar(Config.models[Config.model.selected].scale);
|
||||
this.scene.add(obj);
|
||||
},
|
||||
Helpers.logProgress(),
|
||||
Helpers.logError()
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unload() {
|
||||
this.scene.remove(this.ref);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import TWEEN from 'tween.js';
|
||||
import TWEEN from '@tweenjs/tween.js';
|
||||
|
||||
// This object contains the state of the app
|
||||
export default {
|
||||
isDev: false,
|
||||
isShowingStats: true,
|
||||
isLoaded: false,
|
||||
isTweening: false,
|
||||
isRotating: true,
|
||||
|
@ -13,17 +14,30 @@ export default {
|
|||
easing: TWEEN.Easing.Quadratic.InOut,
|
||||
duration: 500,
|
||||
model: {
|
||||
path: './assets/models/Teapot.json',
|
||||
scale: 20
|
||||
selected: 0,
|
||||
initialTypes: ['gltf', 'object'],
|
||||
type: 'gltf'
|
||||
},
|
||||
models: [
|
||||
{
|
||||
path: './assets/models/duck.gltf',
|
||||
scale: 20,
|
||||
type: 'gltf'
|
||||
},
|
||||
{
|
||||
path: './assets/models/Teapot.json',
|
||||
scale: 20,
|
||||
type: 'object'
|
||||
}
|
||||
],
|
||||
texture: {
|
||||
path: './assets/textures/',
|
||||
imageFiles: [
|
||||
{name: 'UV', image: 'UV_Grid_Sm.jpg'}
|
||||
{ name: 'UV', image: 'UV_Grid_Sm.jpg' }
|
||||
]
|
||||
},
|
||||
mesh: {
|
||||
enableHelper: false,
|
||||
enableHelper: true,
|
||||
wireframe: false,
|
||||
translucent: false,
|
||||
material: {
|
||||
|
@ -65,7 +79,7 @@ export default {
|
|||
}
|
||||
},
|
||||
ambientLight: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
color: 0x141414
|
||||
},
|
||||
directionalLight: {
|
||||
|
|
|
@ -0,0 +1,702 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
import {
|
||||
BufferAttribute,
|
||||
BufferGeometry,
|
||||
InterleavedBuffer,
|
||||
InterleavedBufferAttribute,
|
||||
TriangleFanDrawMode,
|
||||
TriangleStripDrawMode,
|
||||
TrianglesDrawMode,
|
||||
Vector2,
|
||||
Vector3,
|
||||
} from 'three';
|
||||
|
||||
var BufferGeometryUtils = {
|
||||
computeTangents: function (geometry) {
|
||||
var index = geometry.index;
|
||||
var attributes = geometry.attributes;
|
||||
|
||||
// based on http://www.terathon.com/code/tangent.html
|
||||
// (per vertex tangents)
|
||||
|
||||
if (
|
||||
index === null ||
|
||||
attributes.position === undefined ||
|
||||
attributes.normal === undefined ||
|
||||
attributes.uv === undefined
|
||||
) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .computeTangents() failed. Missing required attributes (index, position, normal or uv)'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var indices = index.array;
|
||||
var positions = attributes.position.array;
|
||||
var normals = attributes.normal.array;
|
||||
var uvs = attributes.uv.array;
|
||||
|
||||
var nVertices = positions.length / 3;
|
||||
|
||||
if (attributes.tangent === undefined) {
|
||||
geometry.setAttribute('tangent', new BufferAttribute(new Float32Array(4 * nVertices), 4));
|
||||
}
|
||||
|
||||
var tangents = attributes.tangent.array;
|
||||
|
||||
var tan1 = [],
|
||||
tan2 = [];
|
||||
|
||||
for (var i = 0; i < nVertices; i++) {
|
||||
tan1[i] = new Vector3();
|
||||
tan2[i] = new Vector3();
|
||||
}
|
||||
|
||||
var vA = new Vector3(),
|
||||
vB = new Vector3(),
|
||||
vC = new Vector3(),
|
||||
uvA = new Vector2(),
|
||||
uvB = new Vector2(),
|
||||
uvC = new Vector2(),
|
||||
sdir = new Vector3(),
|
||||
tdir = new Vector3();
|
||||
|
||||
function handleTriangle(a, b, c) {
|
||||
vA.fromArray(positions, a * 3);
|
||||
vB.fromArray(positions, b * 3);
|
||||
vC.fromArray(positions, c * 3);
|
||||
|
||||
uvA.fromArray(uvs, a * 2);
|
||||
uvB.fromArray(uvs, b * 2);
|
||||
uvC.fromArray(uvs, c * 2);
|
||||
|
||||
vB.sub(vA);
|
||||
vC.sub(vA);
|
||||
|
||||
uvB.sub(uvA);
|
||||
uvC.sub(uvA);
|
||||
|
||||
var r = 1.0 / (uvB.x * uvC.y - uvC.x * uvB.y);
|
||||
|
||||
// silently ignore degenerate uv triangles having coincident or colinear vertices
|
||||
|
||||
if (!isFinite(r)) return;
|
||||
|
||||
sdir.copy(vB).multiplyScalar(uvC.y).addScaledVector(vC, -uvB.y).multiplyScalar(r);
|
||||
tdir.copy(vC).multiplyScalar(uvB.x).addScaledVector(vB, -uvC.x).multiplyScalar(r);
|
||||
|
||||
tan1[a].add(sdir);
|
||||
tan1[b].add(sdir);
|
||||
tan1[c].add(sdir);
|
||||
|
||||
tan2[a].add(tdir);
|
||||
tan2[b].add(tdir);
|
||||
tan2[c].add(tdir);
|
||||
}
|
||||
|
||||
var groups = geometry.groups;
|
||||
|
||||
if (groups.length === 0) {
|
||||
groups = [
|
||||
{
|
||||
start: 0,
|
||||
count: indices.length,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
for (var i = 0, il = groups.length; i < il; ++i) {
|
||||
var group = groups[i];
|
||||
|
||||
var start = group.start;
|
||||
var count = group.count;
|
||||
|
||||
for (var j = start, jl = start + count; j < jl; j += 3) {
|
||||
handleTriangle(indices[j + 0], indices[j + 1], indices[j + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
var tmp = new Vector3(),
|
||||
tmp2 = new Vector3();
|
||||
var n = new Vector3(),
|
||||
n2 = new Vector3();
|
||||
var w, t, test;
|
||||
|
||||
function handleVertex(v) {
|
||||
n.fromArray(normals, v * 3);
|
||||
n2.copy(n);
|
||||
|
||||
t = tan1[v];
|
||||
|
||||
// Gram-Schmidt orthogonalize
|
||||
|
||||
tmp.copy(t);
|
||||
tmp.sub(n.multiplyScalar(n.dot(t))).normalize();
|
||||
|
||||
// Calculate handedness
|
||||
|
||||
tmp2.crossVectors(n2, t);
|
||||
test = tmp2.dot(tan2[v]);
|
||||
w = test < 0.0 ? -1.0 : 1.0;
|
||||
|
||||
tangents[v * 4] = tmp.x;
|
||||
tangents[v * 4 + 1] = tmp.y;
|
||||
tangents[v * 4 + 2] = tmp.z;
|
||||
tangents[v * 4 + 3] = w;
|
||||
}
|
||||
|
||||
for (var i = 0, il = groups.length; i < il; ++i) {
|
||||
var group = groups[i];
|
||||
|
||||
var start = group.start;
|
||||
var count = group.count;
|
||||
|
||||
for (var j = start, jl = start + count; j < jl; j += 3) {
|
||||
handleVertex(indices[j + 0]);
|
||||
handleVertex(indices[j + 1]);
|
||||
handleVertex(indices[j + 2]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array<BufferGeometry>} geometries
|
||||
* @param {Boolean} useGroups
|
||||
* @return {BufferGeometry}
|
||||
*/
|
||||
mergeBufferGeometries: function (geometries, useGroups) {
|
||||
var isIndexed = geometries[0].index !== null;
|
||||
|
||||
var attributesUsed = new Set(Object.keys(geometries[0].attributes));
|
||||
var morphAttributesUsed = new Set(Object.keys(geometries[0].morphAttributes));
|
||||
|
||||
var attributes = {};
|
||||
var morphAttributes = {};
|
||||
|
||||
var morphTargetsRelative = geometries[0].morphTargetsRelative;
|
||||
|
||||
var mergedGeometry = new BufferGeometry();
|
||||
|
||||
var offset = 0;
|
||||
|
||||
for (var i = 0; i < geometries.length; ++i) {
|
||||
var geometry = geometries[i];
|
||||
var attributesCount = 0;
|
||||
|
||||
// ensure that all geometries are indexed, or none
|
||||
|
||||
if (isIndexed !== (geometry.index !== null)) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' +
|
||||
i +
|
||||
'. All geometries must have compatible attributes; make sure index attribute exists among all geometries, or in none of them.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
// gather attributes, exit early if they're different
|
||||
|
||||
for (var name in geometry.attributes) {
|
||||
if (!attributesUsed.has(name)) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' +
|
||||
i +
|
||||
'. All geometries must have compatible attributes; make sure "' +
|
||||
name +
|
||||
'" attribute exists among all geometries, or in none of them.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (attributes[name] === undefined) attributes[name] = [];
|
||||
|
||||
attributes[name].push(geometry.attributes[name]);
|
||||
|
||||
attributesCount++;
|
||||
}
|
||||
|
||||
// ensure geometries have the same number of attributes
|
||||
|
||||
if (attributesCount !== attributesUsed.size) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' +
|
||||
i +
|
||||
'. Make sure all geometries have the same number of attributes.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
// gather morph attributes, exit early if they're different
|
||||
|
||||
if (morphTargetsRelative !== geometry.morphTargetsRelative) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' +
|
||||
i +
|
||||
'. .morphTargetsRelative must be consistent throughout all geometries.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
for (var name in geometry.morphAttributes) {
|
||||
if (!morphAttributesUsed.has(name)) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' +
|
||||
i +
|
||||
'. .morphAttributes must be consistent throughout all geometries.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (morphAttributes[name] === undefined) morphAttributes[name] = [];
|
||||
|
||||
morphAttributes[name].push(geometry.morphAttributes[name]);
|
||||
}
|
||||
|
||||
// gather .userData
|
||||
|
||||
mergedGeometry.userData.mergedUserData = mergedGeometry.userData.mergedUserData || [];
|
||||
mergedGeometry.userData.mergedUserData.push(geometry.userData);
|
||||
|
||||
if (useGroups) {
|
||||
var count;
|
||||
|
||||
if (isIndexed) {
|
||||
count = geometry.index.count;
|
||||
} else if (geometry.attributes.position !== undefined) {
|
||||
count = geometry.attributes.position.count;
|
||||
} else {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' +
|
||||
i +
|
||||
'. The geometry must have either an index or a position attribute'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
mergedGeometry.addGroup(offset, count, i);
|
||||
|
||||
offset += count;
|
||||
}
|
||||
}
|
||||
|
||||
// merge indices
|
||||
|
||||
if (isIndexed) {
|
||||
var indexOffset = 0;
|
||||
var mergedIndex = [];
|
||||
|
||||
for (var i = 0; i < geometries.length; ++i) {
|
||||
var index = geometries[i].index;
|
||||
|
||||
for (var j = 0; j < index.count; ++j) {
|
||||
mergedIndex.push(index.getX(j) + indexOffset);
|
||||
}
|
||||
|
||||
indexOffset += geometries[i].attributes.position.count;
|
||||
}
|
||||
|
||||
mergedGeometry.setIndex(mergedIndex);
|
||||
}
|
||||
|
||||
// merge attributes
|
||||
|
||||
for (var name in attributes) {
|
||||
var mergedAttribute = this.mergeBufferAttributes(attributes[name]);
|
||||
|
||||
if (!mergedAttribute) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed while trying to merge the ' +
|
||||
name +
|
||||
' attribute.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
mergedGeometry.setAttribute(name, mergedAttribute);
|
||||
}
|
||||
|
||||
// merge morph attributes
|
||||
|
||||
for (var name in morphAttributes) {
|
||||
var numMorphTargets = morphAttributes[name][0].length;
|
||||
|
||||
if (numMorphTargets === 0) break;
|
||||
|
||||
mergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};
|
||||
mergedGeometry.morphAttributes[name] = [];
|
||||
|
||||
for (var i = 0; i < numMorphTargets; ++i) {
|
||||
var morphAttributesToMerge = [];
|
||||
|
||||
for (var j = 0; j < morphAttributes[name].length; ++j) {
|
||||
morphAttributesToMerge.push(morphAttributes[name][j][i]);
|
||||
}
|
||||
|
||||
var mergedMorphAttribute = this.mergeBufferAttributes(morphAttributesToMerge);
|
||||
|
||||
if (!mergedMorphAttribute) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed while trying to merge the ' +
|
||||
name +
|
||||
' morphAttribute.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
mergedGeometry.morphAttributes[name].push(mergedMorphAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
return mergedGeometry;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array<BufferAttribute>} attributes
|
||||
* @return {BufferAttribute}
|
||||
*/
|
||||
mergeBufferAttributes: function (attributes) {
|
||||
var TypedArray;
|
||||
var itemSize;
|
||||
var normalized;
|
||||
var arrayLength = 0;
|
||||
|
||||
for (var i = 0; i < attributes.length; ++i) {
|
||||
var attribute = attributes[i];
|
||||
|
||||
if (attribute.isInterleavedBufferAttribute) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. InterleavedBufferAttributes are not supported.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (TypedArray === undefined) TypedArray = attribute.array.constructor;
|
||||
if (TypedArray !== attribute.array.constructor) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (itemSize === undefined) itemSize = attribute.itemSize;
|
||||
if (itemSize !== attribute.itemSize) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (normalized === undefined) normalized = attribute.normalized;
|
||||
if (normalized !== attribute.normalized) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
arrayLength += attribute.array.length;
|
||||
}
|
||||
|
||||
var array = new TypedArray(arrayLength);
|
||||
var offset = 0;
|
||||
|
||||
for (var i = 0; i < attributes.length; ++i) {
|
||||
array.set(attributes[i].array, offset);
|
||||
|
||||
offset += attributes[i].array.length;
|
||||
}
|
||||
|
||||
return new BufferAttribute(array, itemSize, normalized);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array<BufferAttribute>} attributes
|
||||
* @return {Array<InterleavedBufferAttribute>}
|
||||
*/
|
||||
interleaveAttributes: function (attributes) {
|
||||
// Interleaves the provided attributes into an InterleavedBuffer and returns
|
||||
// a set of InterleavedBufferAttributes for each attribute
|
||||
var TypedArray;
|
||||
var arrayLength = 0;
|
||||
var stride = 0;
|
||||
|
||||
// calculate the the length and type of the interleavedBuffer
|
||||
for (var i = 0, l = attributes.length; i < l; ++i) {
|
||||
var attribute = attributes[i];
|
||||
|
||||
if (TypedArray === undefined) TypedArray = attribute.array.constructor;
|
||||
if (TypedArray !== attribute.array.constructor) {
|
||||
console.error('AttributeBuffers of different types cannot be interleaved');
|
||||
return null;
|
||||
}
|
||||
|
||||
arrayLength += attribute.array.length;
|
||||
stride += attribute.itemSize;
|
||||
}
|
||||
|
||||
// Create the set of buffer attributes
|
||||
var interleavedBuffer = new InterleavedBuffer(new TypedArray(arrayLength), stride);
|
||||
var offset = 0;
|
||||
var res = [];
|
||||
var getters = ['getX', 'getY', 'getZ', 'getW'];
|
||||
var setters = ['setX', 'setY', 'setZ', 'setW'];
|
||||
|
||||
for (var j = 0, l = attributes.length; j < l; j++) {
|
||||
var attribute = attributes[j];
|
||||
var itemSize = attribute.itemSize;
|
||||
var count = attribute.count;
|
||||
var iba = new InterleavedBufferAttribute(
|
||||
interleavedBuffer,
|
||||
itemSize,
|
||||
offset,
|
||||
attribute.normalized
|
||||
);
|
||||
res.push(iba);
|
||||
|
||||
offset += itemSize;
|
||||
|
||||
// Move the data for each attribute into the new interleavedBuffer
|
||||
// at the appropriate offset
|
||||
for (var c = 0; c < count; c++) {
|
||||
for (var k = 0; k < itemSize; k++) {
|
||||
iba[setters[k]](c, attribute[getters[k]](c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array<BufferGeometry>} geometry
|
||||
* @return {number}
|
||||
*/
|
||||
estimateBytesUsed: function (geometry) {
|
||||
// Return the estimated memory used by this geometry in bytes
|
||||
// Calculate using itemSize, count, and BYTES_PER_ELEMENT to account
|
||||
// for InterleavedBufferAttributes.
|
||||
var mem = 0;
|
||||
for (var name in geometry.attributes) {
|
||||
var attr = geometry.getAttribute(name);
|
||||
mem += attr.count * attr.itemSize * attr.array.BYTES_PER_ELEMENT;
|
||||
}
|
||||
|
||||
var indices = geometry.getIndex();
|
||||
mem += indices ? indices.count * indices.itemSize * indices.array.BYTES_PER_ELEMENT : 0;
|
||||
return mem;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {BufferGeometry} geometry
|
||||
* @param {number} tolerance
|
||||
* @return {BufferGeometry>}
|
||||
*/
|
||||
mergeVertices: function (geometry, tolerance = 1e-4) {
|
||||
tolerance = Math.max(tolerance, Number.EPSILON);
|
||||
|
||||
// Generate an index buffer if the geometry doesn't have one, or optimize it
|
||||
// if it's already available.
|
||||
var hashToIndex = {};
|
||||
var indices = geometry.getIndex();
|
||||
var positions = geometry.getAttribute('position');
|
||||
var vertexCount = indices ? indices.count : positions.count;
|
||||
|
||||
// next value for triangle indices
|
||||
var nextIndex = 0;
|
||||
|
||||
// attributes and new attribute arrays
|
||||
var attributeNames = Object.keys(geometry.attributes);
|
||||
var attrArrays = {};
|
||||
var morphAttrsArrays = {};
|
||||
var newIndices = [];
|
||||
var getters = ['getX', 'getY', 'getZ', 'getW'];
|
||||
|
||||
// initialize the arrays
|
||||
for (var i = 0, l = attributeNames.length; i < l; i++) {
|
||||
var name = attributeNames[i];
|
||||
|
||||
attrArrays[name] = [];
|
||||
|
||||
var morphAttr = geometry.morphAttributes[name];
|
||||
if (morphAttr) {
|
||||
morphAttrsArrays[name] = new Array(morphAttr.length).fill().map(() => []);
|
||||
}
|
||||
}
|
||||
|
||||
// convert the error tolerance to an amount of decimal places to truncate to
|
||||
var decimalShift = Math.log10(1 / tolerance);
|
||||
var shiftMultiplier = Math.pow(10, decimalShift);
|
||||
for (var i = 0; i < vertexCount; i++) {
|
||||
var index = indices ? indices.getX(i) : i;
|
||||
|
||||
// Generate a hash for the vertex attributes at the current index 'i'
|
||||
var hash = '';
|
||||
for (var j = 0, l = attributeNames.length; j < l; j++) {
|
||||
var name = attributeNames[j];
|
||||
var attribute = geometry.getAttribute(name);
|
||||
var itemSize = attribute.itemSize;
|
||||
|
||||
for (var k = 0; k < itemSize; k++) {
|
||||
// double tilde truncates the decimal value
|
||||
hash += `${~~(attribute[getters[k]](index) * shiftMultiplier)},`;
|
||||
}
|
||||
}
|
||||
|
||||
// Add another reference to the vertex if it's already
|
||||
// used by another index
|
||||
if (hash in hashToIndex) {
|
||||
newIndices.push(hashToIndex[hash]);
|
||||
} else {
|
||||
// copy data to the new index in the attribute arrays
|
||||
for (var j = 0, l = attributeNames.length; j < l; j++) {
|
||||
var name = attributeNames[j];
|
||||
var attribute = geometry.getAttribute(name);
|
||||
var morphAttr = geometry.morphAttributes[name];
|
||||
var itemSize = attribute.itemSize;
|
||||
var newarray = attrArrays[name];
|
||||
var newMorphArrays = morphAttrsArrays[name];
|
||||
|
||||
for (var k = 0; k < itemSize; k++) {
|
||||
var getterFunc = getters[k];
|
||||
newarray.push(attribute[getterFunc](index));
|
||||
|
||||
if (morphAttr) {
|
||||
for (var m = 0, ml = morphAttr.length; m < ml; m++) {
|
||||
newMorphArrays[m].push(morphAttr[m][getterFunc](index));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hashToIndex[hash] = nextIndex;
|
||||
newIndices.push(nextIndex);
|
||||
nextIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate typed arrays from new attribute arrays and update
|
||||
// the attributeBuffers
|
||||
const result = geometry.clone();
|
||||
for (var i = 0, l = attributeNames.length; i < l; i++) {
|
||||
var name = attributeNames[i];
|
||||
var oldAttribute = geometry.getAttribute(name);
|
||||
|
||||
var buffer = new oldAttribute.array.constructor(attrArrays[name]);
|
||||
var attribute = new BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
|
||||
|
||||
result.setAttribute(name, attribute);
|
||||
|
||||
// Update the attribute arrays
|
||||
if (name in morphAttrsArrays) {
|
||||
for (var j = 0; j < morphAttrsArrays[name].length; j++) {
|
||||
var oldMorphAttribute = geometry.morphAttributes[name][j];
|
||||
|
||||
var buffer = new oldMorphAttribute.array.constructor(morphAttrsArrays[name][j]);
|
||||
var morphAttribute = new BufferAttribute(
|
||||
buffer,
|
||||
oldMorphAttribute.itemSize,
|
||||
oldMorphAttribute.normalized
|
||||
);
|
||||
result.morphAttributes[name][j] = morphAttribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// indices
|
||||
|
||||
result.setIndex(newIndices);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {BufferGeometry} geometry
|
||||
* @param {number} drawMode
|
||||
* @return {BufferGeometry>}
|
||||
*/
|
||||
toTrianglesDrawMode: function (geometry, drawMode) {
|
||||
if (drawMode === TrianglesDrawMode) {
|
||||
console.warn(
|
||||
'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.'
|
||||
);
|
||||
return geometry;
|
||||
}
|
||||
|
||||
if (drawMode === TriangleFanDrawMode || drawMode === TriangleStripDrawMode) {
|
||||
var index = geometry.getIndex();
|
||||
|
||||
// generate index if not present
|
||||
|
||||
if (index === null) {
|
||||
var indices = [];
|
||||
|
||||
var position = geometry.getAttribute('position');
|
||||
|
||||
if (position !== undefined) {
|
||||
for (var i = 0; i < position.count; i++) {
|
||||
indices.push(i);
|
||||
}
|
||||
|
||||
geometry.setIndex(indices);
|
||||
index = geometry.getIndex();
|
||||
} else {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.'
|
||||
);
|
||||
return geometry;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var numberOfTriangles = index.count - 2;
|
||||
var newIndices = [];
|
||||
|
||||
if (drawMode === TriangleFanDrawMode) {
|
||||
// gl.TRIANGLE_FAN
|
||||
|
||||
for (var i = 1; i <= numberOfTriangles; i++) {
|
||||
newIndices.push(index.getX(0));
|
||||
newIndices.push(index.getX(i));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
}
|
||||
} else {
|
||||
// gl.TRIANGLE_STRIP
|
||||
|
||||
for (var i = 0; i < numberOfTriangles; i++) {
|
||||
if (i % 2 === 0) {
|
||||
newIndices.push(index.getX(i));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
newIndices.push(index.getX(i + 2));
|
||||
} else {
|
||||
newIndices.push(index.getX(i + 2));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
newIndices.push(index.getX(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newIndices.length / 3 !== numberOfTriangles) {
|
||||
console.error(
|
||||
'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.'
|
||||
);
|
||||
}
|
||||
|
||||
// build final geometry
|
||||
|
||||
var newGeometry = geometry.clone();
|
||||
newGeometry.setIndex(newIndices);
|
||||
newGeometry.clearGroups();
|
||||
|
||||
return newGeometry;
|
||||
}
|
||||
|
||||
console.error('THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:', drawMode);
|
||||
return geometry;
|
||||
},
|
||||
};
|
||||
|
||||
export { BufferGeometryUtils };
|
|
@ -8,7 +8,7 @@ export default class Helpers {
|
|||
const context = scope || this;
|
||||
|
||||
const now = +new Date,
|
||||
args = arguments;
|
||||
args = arguments;
|
||||
|
||||
if(last && now < last + threshhold) {
|
||||
clearTimeout(deferTimer);
|
||||
|
|
|
@ -14,16 +14,16 @@ export default class Keyboard {
|
|||
this.keyCodes = {};
|
||||
|
||||
// bind keyEvents
|
||||
this.domElement.addEventListener('keydown', () => this.onKeyChange(event), false);
|
||||
this.domElement.addEventListener('keyup', () => this.onKeyChange(event), false);
|
||||
this.domElement.addEventListener('keydown', (event) => this.onKeyChange(event), false);
|
||||
this.domElement.addEventListener('keyup', (event) => this.onKeyChange(event), false);
|
||||
|
||||
// bind window blur
|
||||
window.addEventListener('blur', () => this.onBlur, false);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.domElement.removeEventListener('keydown', () => this.onKeyChange(event), false);
|
||||
this.domElement.removeEventListener('keyup', () => this.onKeyChange(event), false);
|
||||
this.domElement.removeEventListener('keydown', (event) => this.onKeyChange(event), false);
|
||||
this.domElement.removeEventListener('keyup', (event) => this.onKeyChange(event), false);
|
||||
|
||||
// unbind window blur event
|
||||
window.removeEventListener('blur', () => this.onBlur, false);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,76 +0,0 @@
|
|||
html {
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font: 16px/1 sans-serif;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased; }
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
p,
|
||||
blockquote,
|
||||
figure,
|
||||
ol,
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
main,
|
||||
li {
|
||||
display: block; }
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
font-size: inherit; }
|
||||
|
||||
strong {
|
||||
font-weight: bold; }
|
||||
|
||||
a,
|
||||
button {
|
||||
color: inherit;
|
||||
transition: .3s; }
|
||||
|
||||
a {
|
||||
text-decoration: none; }
|
||||
|
||||
button {
|
||||
overflow: visible;
|
||||
border: 0;
|
||||
font: inherit;
|
||||
-webkit-font-smoothing: inherit;
|
||||
letter-spacing: inherit;
|
||||
background: none;
|
||||
cursor: pointer; }
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border: 0; }
|
||||
|
||||
:focus {
|
||||
outline: 0; }
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border: 0; }
|
||||
|
||||
body {
|
||||
overflow: hidden; }
|
||||
|
||||
.main {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100vh; }
|
||||
|
||||
#loading {
|
||||
position: absolute;
|
||||
top: calc(50% - 8px);
|
||||
left: calc(50% - 35px); }
|
|
@ -1,86 +0,0 @@
|
|||
.alarm {
|
||||
color: #b70000;
|
||||
text-shadow: 0 0 0 #b70000,
|
||||
0 0 1px #ffffff,
|
||||
0 0 1px #ffffff,
|
||||
0 0 2px #ffffff,
|
||||
0 0 2px #ffffff,
|
||||
0 0 3px #ffffff,
|
||||
0 0 3px #ffffff,
|
||||
0 0 4px #ffffff,
|
||||
0 0 4px #ffffff;
|
||||
}
|
||||
|
||||
.rs-base {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10000;
|
||||
overflow: hidden;
|
||||
padding: 10px;
|
||||
width: 350px;
|
||||
background-color: #222222;
|
||||
font-size: 10px;
|
||||
font-family: 'Roboto Condensed', tahoma, sans-serif;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
.rs-base h1 {
|
||||
margin: 0;
|
||||
margin-bottom: 5px;
|
||||
padding: 0;
|
||||
color: #ffffff;
|
||||
font-size: 1.4em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.rs-base div.rs-group {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.rs-base div.rs-group.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rs-base div.rs-fraction {
|
||||
position: relative;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.rs-base div.rs-fraction p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 120px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.rs-base div.rs-legend {
|
||||
position: absolute;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.rs-base div.rs-counter-base {
|
||||
position: relative;
|
||||
margin: 2px 0;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
.rs-base span.rs-counter-id {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.rs-base div.rs-counter-value {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 90px;
|
||||
width: 30px;
|
||||
height: 1em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.rs-base canvas.rs-canvas {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,265 +0,0 @@
|
|||
window.glStats = function () {
|
||||
|
||||
var _rS = null;
|
||||
|
||||
var _totalDrawArraysCalls = 0,
|
||||
_totalDrawElementsCalls = 0,
|
||||
_totalUseProgramCalls = 0,
|
||||
_totalFaces = 0,
|
||||
_totalVertices = 0,
|
||||
_totalPoints = 0,
|
||||
_totalBindTexures = 0;
|
||||
|
||||
function _h ( f, c ) {
|
||||
return function () {
|
||||
c.apply( this, arguments );
|
||||
f.apply( this, arguments );
|
||||
};
|
||||
}
|
||||
|
||||
WebGLRenderingContext.prototype.drawArrays = _h( WebGLRenderingContext.prototype.drawArrays, function () {
|
||||
_totalDrawArraysCalls++;
|
||||
if ( arguments[ 0 ] == this.POINTS ) _totalPoints += arguments[ 2 ];
|
||||
else _totalVertices += arguments[ 2 ];
|
||||
} );
|
||||
|
||||
WebGLRenderingContext.prototype.drawElements = _h( WebGLRenderingContext.prototype.drawElements, function () {
|
||||
_totalDrawElementsCalls++;
|
||||
_totalFaces += arguments[ 1 ] / 3;
|
||||
_totalVertices += arguments[ 1 ];
|
||||
} );
|
||||
|
||||
WebGLRenderingContext.prototype.useProgram = _h( WebGLRenderingContext.prototype.useProgram, function () {
|
||||
_totalUseProgramCalls++;
|
||||
} );
|
||||
|
||||
WebGLRenderingContext.prototype.bindTexture = _h( WebGLRenderingContext.prototype.bindTexture, function () {
|
||||
_totalBindTexures++;
|
||||
} );
|
||||
|
||||
var _values = {
|
||||
allcalls: {
|
||||
over: 3000,
|
||||
caption: 'Calls (hook)'
|
||||
},
|
||||
drawelements: {
|
||||
caption: 'drawElements (hook)'
|
||||
},
|
||||
drawarrays: {
|
||||
caption: 'drawArrays (hook)'
|
||||
}
|
||||
};
|
||||
|
||||
var _groups = [ {
|
||||
caption: 'WebGL',
|
||||
values: [ 'allcalls', 'drawelements', 'drawarrays', 'useprogram', 'bindtexture', 'glfaces', 'glvertices', 'glpoints' ]
|
||||
} ];
|
||||
|
||||
var _fractions = [ {
|
||||
base: 'allcalls',
|
||||
steps: [ 'drawelements', 'drawarrays' ]
|
||||
} ];
|
||||
|
||||
function _update () {
|
||||
_rS( 'allcalls' ).set( _totalDrawArraysCalls + _totalDrawElementsCalls );
|
||||
_rS( 'drawElements' ).set( _totalDrawElementsCalls );
|
||||
_rS( 'drawArrays' ).set( _totalDrawArraysCalls );
|
||||
_rS( 'bindTexture' ).set( _totalBindTexures );
|
||||
_rS( 'useProgram' ).set( _totalUseProgramCalls );
|
||||
_rS( 'glfaces' ).set( _totalFaces );
|
||||
_rS( 'glvertices' ).set( _totalVertices );
|
||||
_rS( 'glpoints' ).set( _totalPoints );
|
||||
}
|
||||
|
||||
function _start () {
|
||||
_totalDrawArraysCalls = 0;
|
||||
_totalDrawElementsCalls = 0;
|
||||
_totalUseProgramCalls = 0;
|
||||
_totalFaces = 0;
|
||||
_totalVertices = 0;
|
||||
_totalPoints = 0;
|
||||
_totalBindTexures = 0;
|
||||
}
|
||||
|
||||
function _end () {}
|
||||
|
||||
function _attach ( r ) {
|
||||
_rS = r;
|
||||
}
|
||||
|
||||
return {
|
||||
update: _update,
|
||||
start: _start,
|
||||
end: _end,
|
||||
attach: _attach,
|
||||
values: _values,
|
||||
groups: _groups,
|
||||
fractions: _fractions
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
window.threeStats = function ( renderer ) {
|
||||
|
||||
var _rS = null;
|
||||
|
||||
var _values = {
|
||||
'renderer.info.memory.geometries': {
|
||||
caption: 'Geometries'
|
||||
},
|
||||
'renderer.info.memory.textures': {
|
||||
caption: 'Textures'
|
||||
},
|
||||
'renderer.info.programs': {
|
||||
caption: 'Programs'
|
||||
},
|
||||
'renderer.info.render.calls': {
|
||||
caption: 'Calls'
|
||||
},
|
||||
'renderer.info.render.faces': {
|
||||
caption: 'Faces',
|
||||
over: 1000
|
||||
},
|
||||
'renderer.info.render.points': {
|
||||
caption: 'Points'
|
||||
},
|
||||
'renderer.info.render.vertices': {
|
||||
caption: 'Vertices'
|
||||
}
|
||||
};
|
||||
|
||||
var _groups = [ {
|
||||
caption: 'Three.js - Memory',
|
||||
values: [ 'renderer.info.memory.geometries', 'renderer.info.programs', 'renderer.info.memory.textures' ]
|
||||
}, {
|
||||
caption: 'Three.js - Render',
|
||||
values: [ 'renderer.info.render.calls', 'renderer.info.render.faces', 'renderer.info.render.points', 'renderer.info.render.vertices' ]
|
||||
} ];
|
||||
|
||||
var _fractions = [];
|
||||
|
||||
function _update () {
|
||||
|
||||
_rS( 'renderer.info.memory.geometries' ).set( renderer.info.memory.geometries );
|
||||
//_rS( 'renderer.info.programs' ).set( renderer.info.programs.length );
|
||||
_rS( 'renderer.info.memory.textures' ).set( renderer.info.memory.textures );
|
||||
_rS( 'renderer.info.render.calls' ).set( renderer.info.render.calls );
|
||||
_rS( 'renderer.info.render.faces' ).set( renderer.info.render.faces );
|
||||
_rS( 'renderer.info.render.points' ).set( renderer.info.render.points );
|
||||
_rS( 'renderer.info.render.vertices' ).set( renderer.info.render.vertices );
|
||||
|
||||
}
|
||||
|
||||
function _start () {}
|
||||
|
||||
function _end () {}
|
||||
|
||||
function _attach ( r ) {
|
||||
_rS = r;
|
||||
}
|
||||
|
||||
return {
|
||||
update: _update,
|
||||
start: _start,
|
||||
end: _end,
|
||||
attach: _attach,
|
||||
values: _values,
|
||||
groups: _groups,
|
||||
fractions: _fractions
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* From https://github.com/paulirish/memory-stats.js
|
||||
*/
|
||||
|
||||
window.BrowserStats = function () {
|
||||
|
||||
var _rS = null;
|
||||
|
||||
var _usedJSHeapSize = 0,
|
||||
_totalJSHeapSize = 0;
|
||||
|
||||
var memory = {
|
||||
usedJSHeapSize: 0,
|
||||
totalJSHeapSize: 0
|
||||
};
|
||||
|
||||
if ( window.performance && performance.memory )
|
||||
memory = performance.memory;
|
||||
|
||||
if ( memory.totalJSHeapSize === 0 ) {
|
||||
console.warn( 'totalJSHeapSize === 0... performance.memory is only available in Chrome .' );
|
||||
}
|
||||
|
||||
var _values = {
|
||||
memory: {
|
||||
caption: 'Used Memory',
|
||||
average: true,
|
||||
avgMs: 1000,
|
||||
over: 22
|
||||
},
|
||||
total: {
|
||||
caption: 'Total Memory'
|
||||
}
|
||||
};
|
||||
|
||||
var _groups = [ {
|
||||
caption: 'Browser',
|
||||
values: [ 'memory', 'total' ]
|
||||
} ];
|
||||
|
||||
var _fractions = [ {
|
||||
base: 'total',
|
||||
steps: [ 'memory' ]
|
||||
} ];
|
||||
|
||||
var log1024 = Math.log( 1024 );
|
||||
|
||||
function _size ( v ) {
|
||||
|
||||
var precision = 100; //Math.pow(10, 2);
|
||||
var i = Math.floor( Math.log( v ) / log1024 );
|
||||
if( v === 0 ) i = 1;
|
||||
return Math.round( v * precision / Math.pow( 1024, i ) ) / precision; // + ' ' + sizes[i];
|
||||
|
||||
}
|
||||
|
||||
function _update () {
|
||||
_usedJSHeapSize = _size( memory.usedJSHeapSize );
|
||||
_totalJSHeapSize = _size( memory.totalJSHeapSize );
|
||||
|
||||
_rS( 'memory' ).set( _usedJSHeapSize );
|
||||
_rS( 'total' ).set( _totalJSHeapSize );
|
||||
}
|
||||
|
||||
function _start () {
|
||||
_usedJSHeapSize = 0;
|
||||
}
|
||||
|
||||
function _end () {}
|
||||
|
||||
function _attach ( r ) {
|
||||
_rS = r;
|
||||
}
|
||||
|
||||
return {
|
||||
update: _update,
|
||||
start: _start,
|
||||
end: _end,
|
||||
attach: _attach,
|
||||
values: _values,
|
||||
groups: _groups,
|
||||
fractions: _fractions
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
if (typeof module === 'object') {
|
||||
module.exports = {
|
||||
glStats: window.glStats,
|
||||
threeStats: window.threeStats,
|
||||
BrowserStats: window.BrowserStats
|
||||
};
|
||||
}
|
|
@ -1,453 +0,0 @@
|
|||
// performance.now() polyfill from https://gist.github.com/paulirish/5438650
|
||||
'use strict';
|
||||
|
||||
( function () {
|
||||
|
||||
// prepare base perf object
|
||||
if ( typeof window.performance === 'undefined' ) {
|
||||
window.performance = {};
|
||||
}
|
||||
|
||||
if ( !window.performance.now ) {
|
||||
|
||||
var nowOffset = Date.now();
|
||||
|
||||
if ( performance.timing && performance.timing.navigationStart ) {
|
||||
nowOffset = performance.timing.navigationStart;
|
||||
}
|
||||
|
||||
window.performance.now = function now () {
|
||||
return Date.now() - nowOffset;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
if( !window.performance.mark ) {
|
||||
window.performance.mark = function(){}
|
||||
}
|
||||
|
||||
if( !window.performance.measure ) {
|
||||
window.performance.measure = function(){}
|
||||
}
|
||||
|
||||
} )();
|
||||
|
||||
window.rStats = function rStats ( settings ) {
|
||||
|
||||
function iterateKeys ( array, callback ) {
|
||||
var keys = Object.keys( array );
|
||||
for ( var j = 0, l = keys.length; j < l; j++ ) {
|
||||
callback( keys[ j ] );
|
||||
}
|
||||
}
|
||||
|
||||
function importCSS ( url ) {
|
||||
|
||||
var element = document.createElement( 'link' );
|
||||
element.href = url;
|
||||
element.rel = 'stylesheet';
|
||||
element.type = 'text/css';
|
||||
document.getElementsByTagName( 'head' )[ 0 ].appendChild( element );
|
||||
|
||||
}
|
||||
|
||||
var _settings = settings || {};
|
||||
var _colours = _settings.colours || [ '#850700', '#c74900', '#fcb300', '#284280', '#4c7c0c' ];
|
||||
|
||||
var _cssFont = 'https://fonts.googleapis.com/css?family=Roboto+Condensed:400,700,300';
|
||||
var _cssRStats = ( _settings.CSSPath ? _settings.CSSPath : '' ) + 'rStats.css';
|
||||
|
||||
var _css = _settings.css || [ _cssFont, _cssRStats ];
|
||||
_css.forEach(function (uri) {
|
||||
importCSS( uri );
|
||||
});
|
||||
|
||||
if ( !_settings.values ) _settings.values = {};
|
||||
|
||||
var _base, _div, _elHeight = 10, _elWidth = 200;
|
||||
var _perfCounters = {};
|
||||
|
||||
|
||||
function Graph ( _dom, _id, _defArg ) {
|
||||
|
||||
var _def = _defArg || {};
|
||||
var _canvas = document.createElement( 'canvas' ),
|
||||
_ctx = _canvas.getContext( '2d' ),
|
||||
_max = 0,
|
||||
_current = 0;
|
||||
|
||||
var c = _def.color ? _def.color : '#666666';
|
||||
|
||||
var _dotCanvas = document.createElement( 'canvas' ),
|
||||
_dotCtx = _dotCanvas.getContext( '2d' );
|
||||
_dotCanvas.width = 1;
|
||||
_dotCanvas.height = 2 * _elHeight;
|
||||
_dotCtx.fillStyle = '#444444';
|
||||
_dotCtx.fillRect( 0, 0, 1, 2 * _elHeight );
|
||||
_dotCtx.fillStyle = c;
|
||||
_dotCtx.fillRect( 0, _elHeight, 1, _elHeight );
|
||||
_dotCtx.fillStyle = '#ffffff';
|
||||
_dotCtx.globalAlpha = 0.5;
|
||||
_dotCtx.fillRect( 0, _elHeight, 1, 1 );
|
||||
_dotCtx.globalAlpha = 1;
|
||||
|
||||
var _alarmCanvas = document.createElement( 'canvas' ),
|
||||
_alarmCtx = _alarmCanvas.getContext( '2d' );
|
||||
_alarmCanvas.width = 1;
|
||||
_alarmCanvas.height = 2 * _elHeight;
|
||||
_alarmCtx.fillStyle = '#444444';
|
||||
_alarmCtx.fillRect( 0, 0, 1, 2 * _elHeight );
|
||||
_alarmCtx.fillStyle = '#b70000';
|
||||
_alarmCtx.fillRect( 0, _elHeight, 1, _elHeight );
|
||||
_alarmCtx.globalAlpha = 0.5;
|
||||
_alarmCtx.fillStyle = '#ffffff';
|
||||
_alarmCtx.fillRect( 0, _elHeight, 1, 1 );
|
||||
_alarmCtx.globalAlpha = 1;
|
||||
|
||||
function _init () {
|
||||
|
||||
_canvas.width = _elWidth;
|
||||
_canvas.height = _elHeight;
|
||||
_canvas.style.width = _canvas.width + 'px';
|
||||
_canvas.style.height = _canvas.height + 'px';
|
||||
_canvas.className = 'rs-canvas';
|
||||
_dom.appendChild( _canvas );
|
||||
|
||||
_ctx.fillStyle = '#444444';
|
||||
_ctx.fillRect( 0, 0, _canvas.width, _canvas.height );
|
||||
|
||||
}
|
||||
|
||||
function _draw ( v, alarm ) {
|
||||
_current += ( v - _current ) * 0.1;
|
||||
_max *= 0.99;
|
||||
if ( _current > _max ) _max = _current;
|
||||
_ctx.drawImage( _canvas, 1, 0, _canvas.width - 1, _canvas.height, 0, 0, _canvas.width - 1, _canvas.height );
|
||||
if ( alarm ) {
|
||||
_ctx.drawImage( _alarmCanvas, _canvas.width - 1, _canvas.height - _current * _canvas.height / _max - _elHeight );
|
||||
} else {
|
||||
_ctx.drawImage( _dotCanvas, _canvas.width - 1, _canvas.height - _current * _canvas.height / _max - _elHeight );
|
||||
}
|
||||
}
|
||||
|
||||
_init();
|
||||
|
||||
return {
|
||||
draw: _draw
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
function StackGraph ( _dom, _num ) {
|
||||
|
||||
var _canvas = document.createElement( 'canvas' ),
|
||||
_ctx = _canvas.getContext( '2d' );
|
||||
|
||||
function _init () {
|
||||
|
||||
_canvas.width = _elWidth;
|
||||
_canvas.height = _elHeight * _num;
|
||||
_canvas.style.width = _canvas.width + 'px';
|
||||
_canvas.style.height = _canvas.height + 'px';
|
||||
_canvas.className = 'rs-canvas';
|
||||
_dom.appendChild( _canvas );
|
||||
|
||||
_ctx.fillStyle = '#444444';
|
||||
_ctx.fillRect( 0, 0, _canvas.width, _canvas.height );
|
||||
|
||||
}
|
||||
|
||||
function _draw ( v ) {
|
||||
_ctx.drawImage( _canvas, 1, 0, _canvas.width - 1, _canvas.height, 0, 0, _canvas.width - 1, _canvas.height );
|
||||
var th = 0;
|
||||
iterateKeys( v, function ( j ) {
|
||||
var h = v[ j ] * _canvas.height;
|
||||
_ctx.fillStyle = _colours[ j ];
|
||||
_ctx.fillRect( _canvas.width - 1, th, 1, h );
|
||||
th += h;
|
||||
} );
|
||||
}
|
||||
|
||||
_init();
|
||||
|
||||
return {
|
||||
draw: _draw
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
function PerfCounter ( id, group ) {
|
||||
|
||||
var _id = id,
|
||||
_time,
|
||||
_value = 0,
|
||||
_total = 0,
|
||||
_averageValue = 0,
|
||||
_accumValue = 0,
|
||||
_accumStart = performance.now(),
|
||||
_accumSamples = 0,
|
||||
_dom = document.createElement( 'div' ),
|
||||
_spanId = document.createElement( 'span' ),
|
||||
_spanValue = document.createElement( 'div' ),
|
||||
_spanValueText = document.createTextNode( '' ),
|
||||
_def = _settings ? _settings.values[ _id.toLowerCase() ] : null,
|
||||
_graph = new Graph( _dom, _id, _def ),
|
||||
_started = false;
|
||||
|
||||
_dom.className = 'rs-counter-base';
|
||||
|
||||
_spanId.className = 'rs-counter-id';
|
||||
_spanId.textContent = ( _def && _def.caption ) ? _def.caption : _id;
|
||||
|
||||
_spanValue.className = 'rs-counter-value';
|
||||
_spanValue.appendChild( _spanValueText );
|
||||
|
||||
_dom.appendChild( _spanId );
|
||||
_dom.appendChild( _spanValue );
|
||||
if ( group ) group.div.appendChild( _dom );
|
||||
else _div.appendChild( _dom );
|
||||
|
||||
_time = performance.now();
|
||||
|
||||
function _average ( v ) {
|
||||
if ( _def && _def.average ) {
|
||||
_accumValue += v;
|
||||
_accumSamples++;
|
||||
var t = performance.now();
|
||||
if ( t - _accumStart >= ( _def.avgMs || 1000 ) ) {
|
||||
_averageValue = _accumValue / _accumSamples;
|
||||
_accumValue = 0;
|
||||
_accumStart = t;
|
||||
_accumSamples = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _start () {
|
||||
_time = performance.now();
|
||||
if( _settings.userTimingAPI ) performance.mark( _id + '-start' );
|
||||
_started = true;
|
||||
}
|
||||
|
||||
function _end () {
|
||||
_value = performance.now() - _time;
|
||||
if( _settings.userTimingAPI ) {
|
||||
performance.mark( _id + '-end' );
|
||||
if( _started ) {
|
||||
performance.measure( _id, _id + '-start', _id + '-end' );
|
||||
}
|
||||
}
|
||||
_average( _value );
|
||||
}
|
||||
|
||||
function _tick () {
|
||||
_end();
|
||||
_start();
|
||||
}
|
||||
|
||||
function _draw () {
|
||||
var v = ( _def && _def.average ) ? _averageValue : _value;
|
||||
_spanValueText.nodeValue = Math.round( v * 100 ) / 100;
|
||||
var a = ( _def && ( ( _def.below && _value < _def.below ) || ( _def.over && _value > _def.over ) ) );
|
||||
_graph.draw( _value, a );
|
||||
_dom.style.color = a ? '#b70000' : '#ffffff';
|
||||
}
|
||||
|
||||
function _frame () {
|
||||
var t = performance.now();
|
||||
var e = t - _time;
|
||||
_total++;
|
||||
if ( e > 1000 ) {
|
||||
if ( _def && _def.interpolate === false ) {
|
||||
_value = _total;
|
||||
} else {
|
||||
_value = _total * 1000 / e;
|
||||
}
|
||||
_total = 0;
|
||||
_time = t;
|
||||
_average( _value );
|
||||
}
|
||||
}
|
||||
|
||||
function _set ( v ) {
|
||||
_value = v;
|
||||
_average( _value );
|
||||
}
|
||||
|
||||
return {
|
||||
set: _set,
|
||||
start: _start,
|
||||
tick: _tick,
|
||||
end: _end,
|
||||
frame: _frame,
|
||||
value: function () {
|
||||
return _value;
|
||||
},
|
||||
draw: _draw
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
function sample () {
|
||||
|
||||
var _value = 0;
|
||||
|
||||
function _set ( v ) {
|
||||
_value = v;
|
||||
}
|
||||
|
||||
return {
|
||||
set: _set,
|
||||
value: function () {
|
||||
return _value;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
function _perf ( idArg ) {
|
||||
|
||||
var id = idArg.toLowerCase();
|
||||
if ( id === undefined ) id = 'default';
|
||||
if ( _perfCounters[ id ] ) return _perfCounters[ id ];
|
||||
|
||||
var group = null;
|
||||
if ( _settings && _settings.groups ) {
|
||||
iterateKeys( _settings.groups, function ( j ) {
|
||||
var g = _settings.groups[ parseInt( j, 10 ) ];
|
||||
if ( !group && g.values.indexOf( id.toLowerCase() ) !== -1 ) {
|
||||
group = g;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
var p = new PerfCounter( id, group );
|
||||
_perfCounters[ id ] = p;
|
||||
return p;
|
||||
|
||||
}
|
||||
|
||||
function _init () {
|
||||
|
||||
if ( _settings.plugins ) {
|
||||
if ( !_settings.values ) _settings.values = {};
|
||||
if ( !_settings.groups ) _settings.groups = [];
|
||||
if ( !_settings.fractions ) _settings.fractions = [];
|
||||
for ( var j = 0; j < _settings.plugins.length; j++ ) {
|
||||
_settings.plugins[ j ].attach( _perf );
|
||||
iterateKeys( _settings.plugins[ j ].values, function ( k ) {
|
||||
_settings.values[ k ] = _settings.plugins[ j ].values[ k ];
|
||||
} );
|
||||
_settings.groups = _settings.groups.concat( _settings.plugins[ j ].groups );
|
||||
_settings.fractions = _settings.fractions.concat( _settings.plugins[ j ].fractions );
|
||||
}
|
||||
} else {
|
||||
_settings.plugins = {};
|
||||
}
|
||||
|
||||
_base = document.createElement( 'div' );
|
||||
_base.className = 'rs-base';
|
||||
_div = document.createElement( 'div' );
|
||||
_div.className = 'rs-container';
|
||||
_div.style.height = 'auto';
|
||||
_base.appendChild( _div );
|
||||
document.body.appendChild( _base );
|
||||
|
||||
if ( !_settings ) return;
|
||||
|
||||
if ( _settings.groups ) {
|
||||
iterateKeys( _settings.groups, function ( j ) {
|
||||
var g = _settings.groups[ parseInt( j, 10 ) ];
|
||||
var div = document.createElement( 'div' );
|
||||
div.className = 'rs-group';
|
||||
g.div = div;
|
||||
var h1 = document.createElement( 'h1' );
|
||||
h1.textContent = g.caption;
|
||||
h1.addEventListener( 'click', function ( e ) {
|
||||
this.classList.toggle( 'hidden' );
|
||||
e.preventDefault();
|
||||
}.bind( div ) );
|
||||
_div.appendChild( h1 );
|
||||
_div.appendChild( div );
|
||||
} );
|
||||
}
|
||||
|
||||
if ( _settings.fractions ) {
|
||||
iterateKeys( _settings.fractions, function ( j ) {
|
||||
var f = _settings.fractions[ parseInt( j, 10 ) ];
|
||||
var div = document.createElement( 'div' );
|
||||
div.className = 'rs-fraction';
|
||||
var legend = document.createElement( 'div' );
|
||||
legend.className = 'rs-legend';
|
||||
|
||||
var h = 0;
|
||||
iterateKeys( _settings.fractions[ j ].steps, function ( k ) {
|
||||
var p = document.createElement( 'p' );
|
||||
p.textContent = _settings.fractions[ j ].steps[ k ];
|
||||
p.style.color = _colours[ h ];
|
||||
legend.appendChild( p );
|
||||
h++;
|
||||
} );
|
||||
div.appendChild( legend );
|
||||
div.style.height = h * _elHeight + 'px';
|
||||
f.div = div;
|
||||
var graph = new StackGraph( div, h );
|
||||
f.graph = graph;
|
||||
_div.appendChild( div );
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function _update () {
|
||||
|
||||
iterateKeys( _settings.plugins, function ( j ) {
|
||||
_settings.plugins[ j ].update();
|
||||
} );
|
||||
|
||||
iterateKeys( _perfCounters, function ( j ) {
|
||||
_perfCounters[ j ].draw();
|
||||
} );
|
||||
|
||||
if ( _settings && _settings.fractions ) {
|
||||
iterateKeys( _settings.fractions, function ( j ) {
|
||||
var f = _settings.fractions[ parseInt( j, 10 ) ];
|
||||
var v = [];
|
||||
var base = _perfCounters[ f.base.toLowerCase() ];
|
||||
if ( base ) {
|
||||
base = base.value();
|
||||
iterateKeys( _settings.fractions[ j ].steps, function ( k ) {
|
||||
var s = _settings.fractions[ j ].steps[ parseInt( k, 10 ) ].toLowerCase();
|
||||
var val = _perfCounters[ s ];
|
||||
if ( val ) {
|
||||
v.push( val.value() / base );
|
||||
}
|
||||
} );
|
||||
}
|
||||
f.graph.draw( v );
|
||||
} );
|
||||
}
|
||||
|
||||
/*if( _height != _div.clientHeight ) {
|
||||
_height = _div.clientHeight;
|
||||
_base.style.height = _height + 2 * _elHeight + 'px';
|
||||
console.log( _base.clientHeight );
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
_init();
|
||||
|
||||
return function ( id ) {
|
||||
if ( id ) return _perf( id );
|
||||
return {
|
||||
element: _base,
|
||||
update: _update
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
if (typeof module === 'object') {
|
||||
module.exports = window.rStats;
|
||||
}
|
Binary file not shown.
Binary file not shown.
After ![]() (image error) Size: 16 KiB |
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,219 @@
|
|||
{
|
||||
"asset": {
|
||||
"generator": "COLLADA2GLTF",
|
||||
"version": "2.0"
|
||||
},
|
||||
"scene": 0,
|
||||
"scenes": [
|
||||
{
|
||||
"nodes": [
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodes": [
|
||||
{
|
||||
"children": [
|
||||
2,
|
||||
1
|
||||
],
|
||||
"matrix": [
|
||||
0.009999999776482582,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.009999999776482582,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.009999999776482582,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"matrix": [
|
||||
-0.7289686799049377,
|
||||
0.0,
|
||||
-0.6845470666885376,
|
||||
0.0,
|
||||
-0.4252049028873444,
|
||||
0.7836934328079224,
|
||||
0.4527972936630249,
|
||||
0.0,
|
||||
0.5364750623703003,
|
||||
0.6211478114128113,
|
||||
-0.571287989616394,
|
||||
0.0,
|
||||
400.1130065917969,
|
||||
463.2640075683594,
|
||||
-431.0780334472656,
|
||||
1.0
|
||||
],
|
||||
"camera": 0
|
||||
},
|
||||
{
|
||||
"mesh": 0
|
||||
}
|
||||
],
|
||||
"cameras": [
|
||||
{
|
||||
"perspective": {
|
||||
"aspectRatio": 1.5,
|
||||
"yfov": 0.6605925559997559,
|
||||
"zfar": 10000.0,
|
||||
"znear": 1.0
|
||||
},
|
||||
"type": "perspective"
|
||||
}
|
||||
],
|
||||
"meshes": [
|
||||
{
|
||||
"primitives": [
|
||||
{
|
||||
"attributes": {
|
||||
"NORMAL": 1,
|
||||
"POSITION": 2,
|
||||
"TEXCOORD_0": 3
|
||||
},
|
||||
"indices": 0,
|
||||
"mode": 4,
|
||||
"material": 0
|
||||
}
|
||||
],
|
||||
"name": "LOD3spShape"
|
||||
}
|
||||
],
|
||||
"accessors": [
|
||||
{
|
||||
"bufferView": 0,
|
||||
"byteOffset": 0,
|
||||
"componentType": 5123,
|
||||
"count": 12636,
|
||||
"max": [
|
||||
2398
|
||||
],
|
||||
"min": [
|
||||
0
|
||||
],
|
||||
"type": "SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView": 1,
|
||||
"byteOffset": 0,
|
||||
"componentType": 5126,
|
||||
"count": 2399,
|
||||
"max": [
|
||||
0.9995989799499512,
|
||||
0.999580979347229,
|
||||
0.9984359741210938
|
||||
],
|
||||
"min": [
|
||||
-0.9990839958190918,
|
||||
-1.0,
|
||||
-0.9998319745063782
|
||||
],
|
||||
"type": "VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView": 1,
|
||||
"byteOffset": 28788,
|
||||
"componentType": 5126,
|
||||
"count": 2399,
|
||||
"max": [
|
||||
96.17990112304688,
|
||||
163.97000122070313,
|
||||
53.92519760131836
|
||||
],
|
||||
"min": [
|
||||
-69.29850006103516,
|
||||
9.929369926452637,
|
||||
-61.32819747924805
|
||||
],
|
||||
"type": "VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView": 2,
|
||||
"byteOffset": 0,
|
||||
"componentType": 5126,
|
||||
"count": 2399,
|
||||
"max": [
|
||||
0.9833459854125976,
|
||||
0.9800369739532472
|
||||
],
|
||||
"min": [
|
||||
0.026409000158309938,
|
||||
0.01996302604675293
|
||||
],
|
||||
"type": "VEC2"
|
||||
}
|
||||
],
|
||||
"materials": [
|
||||
{
|
||||
"pbrMetallicRoughness": {
|
||||
"baseColorTexture": {
|
||||
"index": 0
|
||||
},
|
||||
"metallicFactor": 0.0
|
||||
},
|
||||
"emissiveFactor": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"name": "blinn3-fx"
|
||||
}
|
||||
],
|
||||
"textures": [
|
||||
{
|
||||
"sampler": 0,
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"images": [
|
||||
{
|
||||
"uri": "DuckCM.png"
|
||||
}
|
||||
],
|
||||
"samplers": [
|
||||
{
|
||||
"magFilter": 9729,
|
||||
"minFilter": 9986,
|
||||
"wrapS": 10497,
|
||||
"wrapT": 10497
|
||||
}
|
||||
],
|
||||
"bufferViews": [
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 76768,
|
||||
"byteLength": 25272,
|
||||
"target": 34963
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 0,
|
||||
"byteLength": 57576,
|
||||
"byteStride": 12,
|
||||
"target": 34962
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 57576,
|
||||
"byteLength": 19192,
|
||||
"byteStride": 8,
|
||||
"target": 34962
|
||||
}
|
||||
],
|
||||
"buffers": [
|
||||
{
|
||||
"byteLength": 102040,
|
||||
"uri": "Duck0.bin"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0;font:16px/1 sans-serif;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}blockquote,figure,h1,h2,h3,h4,ol,p,ul{margin:0;padding:0}li,main{display:block}h1,h2,h3,h4{font-size:inherit}strong{font-weight:700}a,button{color:inherit;transition:.3s}a{text-decoration:none}button{overflow:visible;border:0;font:inherit;-webkit-font-smoothing:inherit;letter-spacing:inherit;background:none;cursor:pointer}::-moz-focus-inner{padding:0;border:0}:focus{outline:0}img{max-width:100%;height:auto;border:0}body{overflow:hidden}.main{position:relative;width:100%;height:100vh}#loading{position:absolute;top:calc(50% - 8px);left:calc(50% - 35px)}
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["webpack://threejs-es6-webpack-boilerplate/./src/css/utils/_normalize.scss","webpack://threejs-es6-webpack-boilerplate/./src/css/app/_base.scss","webpack://threejs-es6-webpack-boilerplate/./src/css/app/_main.scss","webpack://threejs-es6-webpack-boilerplate/./src/css/components/_loading.scss"],"names":[],"mappings":"AAAA;EACE,0BAA0B;EAC1B,8BAA8B;;AAEhC;EACE,SAAS;EACT,uBAAuB;EACvB,kCAAkC;EAClC,mCAAmC;;AAErC;;;;;;;;;EASE,SAAS;EACT,UAAU;;AAEZ;;EAEE,cAAc;;AAEhB;;;;EAIE,kBAAkB;;AAEpB;EACE,iBAAiB;;AAEnB;;EAEE,cAAc;EACd,eAAe;;AAEjB;EACE,qBAAqB;;AAEvB;EACE,iBAAiB;EACjB,SAAS;EACT,aAAa;EACb,+BAA+B;EAC/B,uBAAuB;EACvB,gBAAgB;EAChB,eAAe;;AAEjB;EACE,UAAU;EACV,SAAS;;AAEX;EACE,UAAU;;AAEZ;EACE,eAAe;EACf,YAAY;EACZ,SAAS;;AC9DX;EACE,gBAAgB;;ACDlB;EACE,kBAAkB;EAClB,WAAW;EACX,aAAa;;ACHf;EACE,kBAAkB;EAClB,oBAAoB;EACpB,sBAAsB","file":"../css/main.css","sourcesContent":["html {\r\n -ms-text-size-adjust: 100%;\r\n -webkit-text-size-adjust: 100%;\r\n}\r\nbody {\r\n margin: 0;\r\n font: 16px/1 sans-serif;\r\n -moz-osx-font-smoothing: grayscale;\r\n -webkit-font-smoothing: antialiased;\r\n}\r\nh1,\r\nh2,\r\nh3,\r\nh4,\r\np,\r\nblockquote,\r\nfigure,\r\nol,\r\nul {\r\n margin: 0;\r\n padding: 0;\r\n}\r\nmain,\r\nli {\r\n display: block;\r\n}\r\nh1,\r\nh2,\r\nh3,\r\nh4 {\r\n font-size: inherit;\r\n}\r\nstrong {\r\n font-weight: bold;\r\n}\r\na,\r\nbutton {\r\n color: inherit;\r\n transition: .3s;\r\n}\r\na {\r\n text-decoration: none;\r\n}\r\nbutton {\r\n overflow: visible;\r\n border: 0;\r\n font: inherit;\r\n -webkit-font-smoothing: inherit;\r\n letter-spacing: inherit;\r\n background: none;\r\n cursor: pointer;\r\n}\r\n::-moz-focus-inner {\r\n padding: 0;\r\n border: 0;\r\n}\r\n:focus {\r\n outline: 0;\r\n}\r\nimg {\r\n max-width: 100%;\r\n height: auto;\r\n border: 0;\r\n}\r\n","body {\r\n overflow: hidden;\r\n}\r\n",".main {\r\n position: relative;\r\n width: 100%;\r\n height: 100vh;\r\n}\r\n","#loading {\r\n position: absolute;\r\n top: calc(50% - 8px);\r\n left: calc(50% - 35px);\r\n}\r\n"],"sourceRoot":""}
|
|
@ -1,86 +1,87 @@
|
|||
.alarm {
|
||||
.alarm{
|
||||
color: #b70000;
|
||||
text-shadow: 0 0 0 #b70000,
|
||||
0 0 1px #ffffff,
|
||||
0 0 1px #ffffff,
|
||||
0 0 2px #ffffff,
|
||||
0 0 2px #ffffff,
|
||||
0 0 3px #ffffff,
|
||||
0 0 3px #ffffff,
|
||||
0 0 4px #ffffff,
|
||||
0 0 4px #ffffff;
|
||||
0 0 1px #fff,
|
||||
0 0 1px #fff,
|
||||
0 0 2px #fff,
|
||||
0 0 2px #fff,
|
||||
0 0 3px #fff,
|
||||
0 0 3px #fff,
|
||||
0 0 4px #fff,
|
||||
0 0 4px #fff;
|
||||
}
|
||||
|
||||
.rs-base {
|
||||
.rs-base{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10000;
|
||||
overflow: hidden;
|
||||
padding: 10px;
|
||||
width: 350px;
|
||||
background-color: #222222;
|
||||
background-color: #222;
|
||||
font-size: 10px;
|
||||
font-family: 'Roboto Condensed', tahoma, sans-serif;
|
||||
line-height: 1.2em;
|
||||
width: 350px;
|
||||
font-family: 'Roboto Condensed', tahoma, sans-serif;
|
||||
left: 0;
|
||||
top: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.rs-base h1 {
|
||||
.rs-base h1{
|
||||
margin: 0;
|
||||
margin-bottom: 5px;
|
||||
padding: 0;
|
||||
color: #ffffff;
|
||||
font-size: 1.4em;
|
||||
color: #fff;
|
||||
margin-bottom: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.rs-base div.rs-group {
|
||||
.rs-base div.rs-group{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.rs-base div.rs-group.hidden {
|
||||
.rs-base div.rs-group.hidden{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rs-base div.rs-fraction {
|
||||
.rs-base div.rs-fraction{
|
||||
position: relative;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.rs-base div.rs-fraction p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
.rs-base div.rs-fraction p{
|
||||
width: 120px;
|
||||
text-align: right;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.rs-base div.rs-legend {
|
||||
.rs-base div.rs-legend{
|
||||
position: absolute;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.rs-base div.rs-counter-base {
|
||||
.rs-base div.rs-counter-base{
|
||||
position: relative;
|
||||
margin: 2px 0;
|
||||
height: 1em;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.rs-base span.rs-counter-id {
|
||||
.rs-base span.rs-counter-id{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.rs-base div.rs-counter-value {
|
||||
.rs-base div.rs-counter-value{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 90px;
|
||||
width: 30px;
|
||||
height: 1em;
|
||||
top: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.rs-base canvas.rs-canvas {
|
||||
.rs-base canvas.rs-canvas{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
|
@ -1,19 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Three.js Webpack ES6 Boilerplate</title>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Three.js Webpack ES6 Boilerplate</title>
|
||||
<script defer src="/js/runtime.bundle.js"></script><script defer src="/js/vendors.bundle.js"></script><script defer src="/js/main.bundle.js"></script><link href="/js/../css/main.css" rel="stylesheet"></head>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="./assets/css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
<section id="appContainer" class="main">
|
||||
<div id="loading">Loading...</div>
|
||||
</section>
|
||||
<body>
|
||||
<section id="appContainer" class="main">
|
||||
<div id="loading">Loading...</div>
|
||||
</section>
|
||||
|
||||
<script src="./assets/js/rStats.js"></script>
|
||||
<script src="./assets/js/rStats.extras.js"></script>
|
||||
<script src="./assets/js/dat.gui.min.js"></script>
|
||||
<script src="./assets/js/app.js"></script>
|
||||
</body>
|
||||
|
||||
<script src="js/rStats.js"></script>
|
||||
<script src="js/rStats.extras.js"></script>
|
||||
<script src="js/dat.gui.min.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,147 @@
|
|||
/*! ../../data/config */
|
||||
|
||||
/*! ../../utils/bufferGeometryUtils */
|
||||
|
||||
/*! ../../utils/helpers */
|
||||
|
||||
/*! ../../utils/keyboard */
|
||||
|
||||
/*! ../../utils/orbitControls */
|
||||
|
||||
/*! ../components/material */
|
||||
|
||||
/*! ../loaders/GLTFLoader */
|
||||
|
||||
/*! ./../css/app.scss */
|
||||
|
||||
/*! ./../data/config */
|
||||
|
||||
/*! ./app/main */
|
||||
|
||||
/*! ./components/camera */
|
||||
|
||||
/*! ./components/controls */
|
||||
|
||||
/*! ./components/geometry */
|
||||
|
||||
/*! ./components/light */
|
||||
|
||||
/*! ./components/renderer */
|
||||
|
||||
/*! ./data/config */
|
||||
|
||||
/*! ./helpers/meshHelper */
|
||||
|
||||
/*! ./helpers/stats */
|
||||
|
||||
/*! ./managers/datGUI */
|
||||
|
||||
/*! ./managers/interaction */
|
||||
|
||||
/*! ./material */
|
||||
|
||||
/*! ./model/model */
|
||||
|
||||
/*! ./model/texture */
|
||||
|
||||
/*! ./utils/detector */
|
||||
|
||||
/*! ./vertexNormalsHelper */
|
||||
|
||||
/*! @tweenjs/tween.js */
|
||||
|
||||
/*! es6-promise */
|
||||
|
||||
/*! three */
|
||||
|
||||
/*!***********************!*\
|
||||
!*** ./src/js/app.js ***!
|
||||
\***********************/
|
||||
|
||||
/*!**************************!*\
|
||||
!*** ./src/css/app.scss ***!
|
||||
\**************************/
|
||||
|
||||
/*!****************************!*\
|
||||
!*** ./src/js/app/main.js ***!
|
||||
\****************************/
|
||||
|
||||
/*!*******************************!*\
|
||||
!*** ./src/js/data/config.js ***!
|
||||
\*******************************/
|
||||
|
||||
/*!*********************************!*\
|
||||
!*** ./src/js/utils/helpers.js ***!
|
||||
\*********************************/
|
||||
|
||||
/*!**********************************!*\
|
||||
!*** ./src/js/utils/detector.js ***!
|
||||
\**********************************/
|
||||
|
||||
/*!**********************************!*\
|
||||
!*** ./src/js/utils/keyboard.js ***!
|
||||
\**********************************/
|
||||
|
||||
/*!***********************************!*\
|
||||
!*** ./src/js/app/model/model.js ***!
|
||||
\***********************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/js/app/helpers/stats.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./src/js/app/model/texture.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!***************************************!*\
|
||||
!*** ./src/js/app/managers/datGUI.js ***!
|
||||
\***************************************/
|
||||
|
||||
/*!***************************************!*\
|
||||
!*** ./src/js/utils/orbitControls.js ***!
|
||||
\***************************************/
|
||||
|
||||
/*!****************************************!*\
|
||||
!*** ./src/js/app/components/light.js ***!
|
||||
\****************************************/
|
||||
|
||||
/*!*****************************************!*\
|
||||
!*** ./src/js/app/components/camera.js ***!
|
||||
\*****************************************/
|
||||
|
||||
/*!******************************************!*\
|
||||
!*** ./src/js/app/helpers/meshHelper.js ***!
|
||||
\******************************************/
|
||||
|
||||
/*!******************************************!*\
|
||||
!*** ./src/js/app/loaders/GLTFLoader.js ***!
|
||||
\******************************************/
|
||||
|
||||
/*!*******************************************!*\
|
||||
!*** ./src/js/app/components/controls.js ***!
|
||||
\*******************************************/
|
||||
|
||||
/*!*******************************************!*\
|
||||
!*** ./src/js/app/components/geometry.js ***!
|
||||
\*******************************************/
|
||||
|
||||
/*!*******************************************!*\
|
||||
!*** ./src/js/app/components/material.js ***!
|
||||
\*******************************************/
|
||||
|
||||
/*!*******************************************!*\
|
||||
!*** ./src/js/app/components/renderer.js ***!
|
||||
\*******************************************/
|
||||
|
||||
/*!********************************************!*\
|
||||
!*** ./src/js/app/managers/interaction.js ***!
|
||||
\********************************************/
|
||||
|
||||
/*!*********************************************!*\
|
||||
!*** ./src/js/utils/bufferGeometryUtils.js ***!
|
||||
\*********************************************/
|
||||
|
||||
/*!***************************************************!*\
|
||||
!*** ./src/js/app/helpers/vertexNormalsHelper.js ***!
|
||||
\***************************************************/
|
|
@ -116,9 +116,9 @@ window.threeStats = function ( renderer ) {
|
|||
'renderer.info.render.calls': {
|
||||
caption: 'Calls'
|
||||
},
|
||||
'renderer.info.render.faces': {
|
||||
caption: 'Faces',
|
||||
over: 1000
|
||||
'renderer.info.render.triangles': {
|
||||
caption: 'Triangles',
|
||||
over: 5000
|
||||
},
|
||||
'renderer.info.render.points': {
|
||||
caption: 'Points'
|
||||
|
@ -133,21 +133,18 @@ window.threeStats = function ( renderer ) {
|
|||
values: [ 'renderer.info.memory.geometries', 'renderer.info.programs', 'renderer.info.memory.textures' ]
|
||||
}, {
|
||||
caption: 'Three.js - Render',
|
||||
values: [ 'renderer.info.render.calls', 'renderer.info.render.faces', 'renderer.info.render.points', 'renderer.info.render.vertices' ]
|
||||
values: [ 'renderer.info.render.calls', 'renderer.info.render.triangles', 'renderer.info.render.points' ]
|
||||
} ];
|
||||
|
||||
var _fractions = [];
|
||||
|
||||
function _update () {
|
||||
|
||||
_rS( 'renderer.info.memory.geometries' ).set( renderer.info.memory.geometries );
|
||||
//_rS( 'renderer.info.programs' ).set( renderer.info.programs.length );
|
||||
_rS( 'renderer.info.memory.textures' ).set( renderer.info.memory.textures );
|
||||
_rS( 'renderer.info.render.calls' ).set( renderer.info.render.calls );
|
||||
_rS( 'renderer.info.render.faces' ).set( renderer.info.render.faces );
|
||||
_rS( 'renderer.info.render.points' ).set( renderer.info.render.points );
|
||||
_rS( 'renderer.info.render.vertices' ).set( renderer.info.render.vertices );
|
||||
|
||||
_rS( 'renderer.info.render.triangles' ).set( renderer.info.render.triangles );
|
||||
// _rS( 'renderer.info.render.points' ).set( renderer.info.render.points );
|
||||
}
|
||||
|
||||
function _start () {}
|
|
@ -32,6 +32,32 @@
|
|||
|
||||
} )();
|
||||
|
||||
/**
|
||||
* @class rStats
|
||||
* @param {rStats~Settings} [settings] Settings for the rStats instance.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} rStats~Settings
|
||||
* @property {Array.<String>} [colours] An array of CSS colour values.
|
||||
* @property {String} [CSSPath=''] Base URL where rStats.css is located.
|
||||
* @property {Array.<String>} [css] URLs of CSS or font files to import.
|
||||
* @property {Object.<String, rStats~CounterProperties>} [values] Properties to use for each counter.
|
||||
* @property {Array.<Object>} [groups] Define groups of counters.
|
||||
* @property {Array.<Object>} [fractions] Define stacked counters.
|
||||
* @property {Array.<Object>} [plugins] Additional plugins.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} rStats~CounterProperties
|
||||
* @property {String} [caption] Caption for this counter.
|
||||
* @property {Boolean} [average=false] Whether the values should be averaged.
|
||||
* @property {Number} [avgMs=1000] Duration for which the values should be averaged.
|
||||
* @property {Number} [below] Value below which the graph should be highlighted.
|
||||
* @property {Number} [over] Value over which the graph should be highlighted.
|
||||
* @property {Boolean} [interpolate=true] Whether framerate should be interpolated.
|
||||
*/
|
||||
|
||||
window.rStats = function rStats ( settings ) {
|
||||
|
||||
function iterateKeys ( array, callback ) {
|
||||
|
@ -194,8 +220,6 @@ window.rStats = function rStats ( settings ) {
|
|||
_graph = new Graph( _dom, _id, _def ),
|
||||
_started = false;
|
||||
|
||||
_dom.className = 'rs-counter-base';
|
||||
|
||||
_spanId.className = 'rs-counter-id';
|
||||
_spanId.textContent = ( _def && _def.caption ) ? _def.caption : _id;
|
||||
|
||||
|
@ -250,7 +274,8 @@ window.rStats = function rStats ( settings ) {
|
|||
_spanValueText.nodeValue = Math.round( v * 100 ) / 100;
|
||||
var a = ( _def && ( ( _def.below && _value < _def.below ) || ( _def.over && _value > _def.over ) ) );
|
||||
_graph.draw( _value, a );
|
||||
_dom.style.color = a ? '#b70000' : '#ffffff';
|
||||
_dom.className = a ? 'rs-counter-base alarm' : 'rs-counter-base';
|
||||
|
||||
}
|
||||
|
||||
function _frame () {
|
||||
|
@ -429,10 +454,10 @@ window.rStats = function rStats ( settings ) {
|
|||
}
|
||||
|
||||
/*if( _height != _div.clientHeight ) {
|
||||
_height = _div.clientHeight;
|
||||
_base.style.height = _height + 2 * _elHeight + 'px';
|
||||
console.log( _base.clientHeight );
|
||||
}*/
|
||||
_height = _div.clientHeight;
|
||||
_base.style.height = _height + 2 * _elHeight + 'px';
|
||||
console.log( _base.clientHeight );
|
||||
}*/
|
||||
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,19 @@
|
|||
/*!
|
||||
* @overview es6-promise - a tiny implementation of Promises/A+.
|
||||
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
|
||||
* @license Licensed under MIT license
|
||||
* See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
|
||||
* @version v4.2.8+1e68dce6
|
||||
*/
|
||||
|
||||
/*!**************************************************!*\
|
||||
!*** ./node_modules/three/build/three.module.js ***!
|
||||
\**************************************************/
|
||||
|
||||
/*!******************************************************!*\
|
||||
!*** ./node_modules/es6-promise/dist/es6-promise.js ***!
|
||||
\******************************************************/
|
||||
|
||||
/*!**********************************************************!*\
|
||||
!*** ./node_modules/@tweenjs/tween.js/dist/tween.esm.js ***!
|
||||
\**********************************************************/
|
|
@ -1,84 +1,172 @@
|
|||
// Global imports
|
||||
var webpack = require('webpack'),
|
||||
path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
|
||||
// Paths
|
||||
var entry = './src/js/app.js',
|
||||
includePath = path.join(__dirname, 'src/js'),
|
||||
nodeModulesPath = path.join(__dirname, 'node_modules'),
|
||||
outputPath = path.join(__dirname, 'src/public/assets/js');
|
||||
const entry = './src/js/app.js';
|
||||
const includePath = path.join(__dirname, 'src/js');
|
||||
const nodeModulesPath = path.join(__dirname, 'node_modules');
|
||||
|
||||
// Environment
|
||||
var PROD = JSON.parse(process.env.NODE_ENV || 0);
|
||||
let outputPath = path.join(__dirname, 'src/public/js');
|
||||
let publicPath = '/js/';
|
||||
|
||||
// Dev environment
|
||||
var env = 'dev',
|
||||
time = Date.now(),
|
||||
devtool = 'eval',
|
||||
debug = true,
|
||||
plugins = [
|
||||
new webpack.NoErrorsPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
__ENV__: JSON.stringify(env),
|
||||
___BUILD_TIME___: time
|
||||
})
|
||||
];
|
||||
module.exports = env => {
|
||||
// Dev environment
|
||||
let devtool = 'inline-source-map';
|
||||
let mode = 'development';
|
||||
let stats = 'minimal';
|
||||
let plugins = [
|
||||
new webpack.DefinePlugin({
|
||||
__ENV__: JSON.stringify(env.NODE_ENV)
|
||||
})
|
||||
];
|
||||
|
||||
// Production environment
|
||||
if(PROD) {
|
||||
env = 'prod';
|
||||
devtool = 'hidden-source-map';
|
||||
debug = false;
|
||||
outputPath = __dirname + '/build/public/assets/js';
|
||||
// Prod environment
|
||||
if (env.NODE_ENV === 'prod') {
|
||||
devtool = 'hidden-source-map';
|
||||
mode = 'production';
|
||||
stats = 'none';
|
||||
outputPath = `${__dirname}/build/js`;
|
||||
publicPath = 'js/';
|
||||
}
|
||||
|
||||
uglifyOptions = {
|
||||
sourceMap: false,
|
||||
mangle: true,
|
||||
compress: {
|
||||
drop_console: true
|
||||
},
|
||||
console.log('Webpack build -');
|
||||
console.log(` - ENV: ${env.NODE_ENV}`);
|
||||
console.log(` - outputPath ${outputPath}`);
|
||||
console.log(` - includePath ${includePath}`);
|
||||
console.log(` - nodeModulesPath: ${nodeModulesPath}`);
|
||||
|
||||
return {
|
||||
// Here the application starts executing
|
||||
// and webpack starts bundling
|
||||
entry: [
|
||||
entry
|
||||
],
|
||||
|
||||
// options related to how webpack emits results
|
||||
output: {
|
||||
comments: false
|
||||
// the target directory for all output files
|
||||
// must be an absolute path (use the Node.js path module)
|
||||
path: outputPath,
|
||||
// the url to the output directory resolved relative to the HTML page
|
||||
publicPath,
|
||||
// the filename template for entry chunks
|
||||
filename: '[name].bundle.js',
|
||||
chunkFilename: '[name].bundle.js',
|
||||
},
|
||||
|
||||
// Webpack 4 mode helper
|
||||
mode,
|
||||
|
||||
// configuration regarding modules
|
||||
module: {
|
||||
// rules for modules (configure loaders, parser options, etc.)
|
||||
rules: [
|
||||
{
|
||||
// these are matching conditions, each accepting a regular expression or string
|
||||
// test and include have the same behavior, both must be matched
|
||||
// exclude must not be matched (takes preference over test and include)
|
||||
// Best practices:
|
||||
// - Use RegExp only in test and for filename matching
|
||||
// - Use arrays of absolute paths in include and exclude
|
||||
// - Try to avoid exclude and prefer include
|
||||
test: /\.js?$/,
|
||||
// the loader which should be applied, it'll be resolved relative to the context
|
||||
// -loader suffix is no longer optional in webpack2 for clarity reasons
|
||||
// see webpack 1 upgrade guide
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
include: includePath,
|
||||
exclude: nodeModulesPath,
|
||||
},
|
||||
{
|
||||
test: /\.(s*)css$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
// you can specify a publicPath here
|
||||
// by default it use publicPath in webpackOptions.output
|
||||
publicPath: 'css'
|
||||
}
|
||||
},
|
||||
'css-loader',
|
||||
'postcss-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// options for resolving module requests
|
||||
// (does not apply to resolving to loaders)
|
||||
resolve: {
|
||||
// directories where to look for modules,
|
||||
modules: [
|
||||
'node_modules',
|
||||
path.resolve(__dirname, 'src')
|
||||
],
|
||||
|
||||
// extensions that are used
|
||||
extensions: ['.js', '.json'],
|
||||
},
|
||||
|
||||
performance: {
|
||||
hints: 'warning'
|
||||
},
|
||||
|
||||
// lets you precisely control what bundle information gets displayed
|
||||
stats,
|
||||
|
||||
// enhance debugging by adding meta info for the browser devtools
|
||||
// source-map most detailed at the expense of build speed.
|
||||
devtool,
|
||||
|
||||
devServer: {
|
||||
static: 'src/public',
|
||||
open: false,
|
||||
},
|
||||
|
||||
plugins: plugins.concat(
|
||||
new HtmlWebpackPlugin({
|
||||
title: 'Three.js Webpack ES6 Boilerplate',
|
||||
template: path.join(__dirname, 'src/html/index.html'),
|
||||
filename: '../index.html',
|
||||
env: env.NODE_ENV,
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '../css/[name].css',
|
||||
chunkFilename: '../css/[id].css'
|
||||
})
|
||||
),
|
||||
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin(),
|
||||
new OptimizeCSSAssetsPlugin()
|
||||
],
|
||||
runtimeChunk: 'single',
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
vendor: {
|
||||
test: /[\\\/]node_modules[\\\/]/,
|
||||
name: 'vendors',
|
||||
chunks: 'all'
|
||||
},
|
||||
styles: {
|
||||
name: 'styles',
|
||||
test: /\.css$/,
|
||||
chunks: 'all',
|
||||
enforce: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
plugins.push(new webpack.optimize.UglifyJsPlugin(uglifyOptions));
|
||||
}
|
||||
|
||||
console.log('Webpack build - ENV: ' + env + ' V: ' + time);
|
||||
console.log(' - outputPath ', outputPath);
|
||||
console.log(' - includePath ', includePath);
|
||||
console.log(' - nodeModulesPath ', nodeModulesPath);
|
||||
|
||||
module.exports = {
|
||||
stats: {
|
||||
colors: true
|
||||
},
|
||||
debug: debug,
|
||||
devtool: devtool,
|
||||
devServer: {
|
||||
contentBase: 'src/public'
|
||||
},
|
||||
entry: [
|
||||
entry
|
||||
],
|
||||
output: {
|
||||
path: outputPath,
|
||||
publicPath: 'assets/js',
|
||||
filename: 'app.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.js?$/,
|
||||
loader: 'babel-loader',
|
||||
query: {
|
||||
presets: ['es2015']
|
||||
},
|
||||
include: [
|
||||
includePath, nodeModulesPath
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: plugins
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue