fix merge
This commit is contained in:
@@ -58,6 +58,7 @@
|
||||
"rollup-plugin-terser": "^5.3.0",
|
||||
"sapper": "^0.27.12",
|
||||
"svelte": "^3.20.1",
|
||||
"svelte-lazy": "^0.1.10",
|
||||
"svelte-preprocess": "^3.7.1"
|
||||
},
|
||||
"browserslist": [
|
||||
|
||||
75
pnpm-lock.yaml
generated
75
pnpm-lock.yaml
generated
@@ -7,6 +7,7 @@ dependencies:
|
||||
polka: 1.0.0-next.11
|
||||
scroll-out: 2.2.8
|
||||
sirv: 0.4.2
|
||||
svelte-lazy: 0.1.10
|
||||
swipe-listener: 1.1.0
|
||||
devDependencies:
|
||||
'@babel/core': 7.9.0
|
||||
@@ -72,7 +73,7 @@ packages:
|
||||
gensync: 1.0.0-beta.1
|
||||
json5: 2.1.3
|
||||
lodash: 4.17.15
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
semver: 5.7.1
|
||||
source-map: 0.5.7
|
||||
dev: true
|
||||
@@ -698,7 +699,7 @@ packages:
|
||||
'@babel/core': 7.9.0
|
||||
'@babel/helper-module-imports': 7.8.3
|
||||
'@babel/helper-plugin-utils': 7.8.3
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
semver: 5.7.1
|
||||
dev: true
|
||||
peerDependencies:
|
||||
@@ -917,7 +918,7 @@ packages:
|
||||
estree-walker: 1.0.1
|
||||
is-reference: 1.1.4
|
||||
magic-string: 0.25.7
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
rollup: 2.6.1
|
||||
dev: true
|
||||
engines:
|
||||
@@ -932,7 +933,7 @@ packages:
|
||||
'@types/resolve': 0.0.8
|
||||
builtin-modules: 3.1.0
|
||||
is-module: 1.0.0
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
rollup: 2.6.1
|
||||
dev: true
|
||||
engines:
|
||||
@@ -1159,7 +1160,7 @@ packages:
|
||||
/autoprefixer/9.7.6:
|
||||
dependencies:
|
||||
browserslist: 4.11.1
|
||||
caniuse-lite: 1.0.30001040
|
||||
caniuse-lite: 1.0.30001042
|
||||
chalk: 2.4.2
|
||||
normalize-range: 0.1.2
|
||||
num2fraction: 1.2.2
|
||||
@@ -1191,7 +1192,7 @@ packages:
|
||||
glob: 7.1.6
|
||||
pkg-up: 3.1.0
|
||||
reselect: 4.0.0
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
dev: true
|
||||
engines:
|
||||
node: '>= 8.0.0'
|
||||
@@ -1239,8 +1240,8 @@ packages:
|
||||
integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
/browserslist/4.11.1:
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001040
|
||||
electron-to-chromium: 1.3.403
|
||||
caniuse-lite: 1.0.30001042
|
||||
electron-to-chromium: 1.3.412
|
||||
node-releases: 1.1.53
|
||||
pkg-up: 2.0.0
|
||||
dev: true
|
||||
@@ -1319,10 +1320,10 @@ packages:
|
||||
node: '>=0.10.0'
|
||||
resolution:
|
||||
integrity: sha1-MvxLn82vhF/N9+c7uXysImHwqwo=
|
||||
/caniuse-lite/1.0.30001040:
|
||||
/caniuse-lite/1.0.30001042:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-Ep0tEPeI5wCvmJNrXjE3etgfI+lkl1fTDU6Y3ZH1mhrjkPlVI9W4pcKbMo+BQLpEWKVYYp2EmYaRsqpPC3k7lQ==
|
||||
integrity: sha512-igMQ4dlqnf4tWv0xjaaE02op9AJ2oQzXKjWf4EuAHFN694Uo9/EfPVIPJcmn2WkU9RqozCxx5e2KPcVClHDbDw==
|
||||
/caseless/0.12.0:
|
||||
dev: true
|
||||
resolution:
|
||||
@@ -1378,10 +1379,10 @@ packages:
|
||||
node: '>=8'
|
||||
resolution:
|
||||
integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
|
||||
/cli-width/2.2.0:
|
||||
/cli-width/2.2.1:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
|
||||
integrity: sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
|
||||
/cliui/3.2.0:
|
||||
dependencies:
|
||||
string-width: 1.0.2
|
||||
@@ -1670,10 +1671,10 @@ packages:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
|
||||
/electron-to-chromium/1.3.403:
|
||||
/electron-to-chromium/1.3.412:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-JaoxV4RzdBAZOnsF4dAlZ2ijJW72MbqO5lNfOBHUWiBQl3Rwe+mk2RCUMrRI3rSClLJ8HSNQNqcry12H+0ZjFw==
|
||||
integrity: sha512-4bVdSeJScR8fT7ERveLWbxemY5uXEHVseqMRyORosiKcTUSGtVwBkV8uLjXCqoFLeImA57Z9hbz3TOid01U4Hw==
|
||||
/emoji-regex/7.0.3:
|
||||
dev: true
|
||||
resolution:
|
||||
@@ -1760,7 +1761,7 @@ packages:
|
||||
/eslint-import-resolver-node/0.3.3:
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==
|
||||
@@ -1797,7 +1798,7 @@ packages:
|
||||
minimatch: 3.0.4
|
||||
object.values: 1.1.1
|
||||
read-pkg-up: 2.0.0
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
dev: true
|
||||
engines:
|
||||
node: '>=4'
|
||||
@@ -1811,7 +1812,7 @@ packages:
|
||||
eslint-utils: 2.0.0
|
||||
ignore: 5.1.4
|
||||
minimatch: 3.0.4
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
semver: 6.3.0
|
||||
dev: true
|
||||
engines:
|
||||
@@ -1884,7 +1885,7 @@ packages:
|
||||
eslint-utils: 1.4.3
|
||||
eslint-visitor-keys: 1.1.0
|
||||
espree: 6.2.1
|
||||
esquery: 1.2.0
|
||||
esquery: 1.3.1
|
||||
esutils: 2.0.3
|
||||
file-entry-cache: 5.0.1
|
||||
functional-red-black-tree: 1.0.1
|
||||
@@ -1934,14 +1935,14 @@ packages:
|
||||
hasBin: true
|
||||
resolution:
|
||||
integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
|
||||
/esquery/1.2.0:
|
||||
/esquery/1.3.1:
|
||||
dependencies:
|
||||
estraverse: 5.0.0
|
||||
estraverse: 5.1.0
|
||||
dev: true
|
||||
engines:
|
||||
node: '>=8.0'
|
||||
node: '>=0.10'
|
||||
resolution:
|
||||
integrity: sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q==
|
||||
integrity: sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==
|
||||
/esrecurse/4.2.1:
|
||||
dependencies:
|
||||
estraverse: 4.3.0
|
||||
@@ -1956,12 +1957,12 @@ packages:
|
||||
node: '>=4.0'
|
||||
resolution:
|
||||
integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
|
||||
/estraverse/5.0.0:
|
||||
/estraverse/5.1.0:
|
||||
dev: true
|
||||
engines:
|
||||
node: '>=4.0'
|
||||
resolution:
|
||||
integrity: sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==
|
||||
integrity: sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==
|
||||
/estree-walker/0.6.1:
|
||||
dev: true
|
||||
resolution:
|
||||
@@ -2336,7 +2337,7 @@ packages:
|
||||
graceful-fs: 4.2.3
|
||||
inherits: 2.0.4
|
||||
map-limit: 0.0.1
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-Ogm179MCazwIRyEqs3g3EOY4Y3XIAa0yl8J5RE9rJC6QH1w8weVOp2RZu0mvnYy/2xIas1w166YR2eZdDkWQxg==
|
||||
@@ -2352,7 +2353,7 @@ packages:
|
||||
glslify-bundle: 5.1.1
|
||||
glslify-deps: 1.3.1
|
||||
minimist: 1.2.5
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
stack-trace: 0.0.9
|
||||
static-eval: 2.0.5
|
||||
through2: 2.0.5
|
||||
@@ -2435,7 +2436,7 @@ packages:
|
||||
he: 1.2.0
|
||||
param-case: 2.1.1
|
||||
relateurl: 0.2.7
|
||||
uglify-js: 3.8.1
|
||||
uglify-js: 3.9.1
|
||||
dev: true
|
||||
engines:
|
||||
node: '>=6'
|
||||
@@ -2558,7 +2559,7 @@ packages:
|
||||
ansi-escapes: 4.3.1
|
||||
chalk: 3.0.0
|
||||
cli-cursor: 3.1.0
|
||||
cli-width: 2.2.0
|
||||
cli-width: 2.2.1
|
||||
external-editor: 3.1.0
|
||||
figures: 3.2.0
|
||||
lodash: 4.17.15
|
||||
@@ -3128,7 +3129,7 @@ packages:
|
||||
/normalize-package-data/2.5.0:
|
||||
dependencies:
|
||||
hosted-git-info: 2.8.8
|
||||
resolve: 1.15.1
|
||||
resolve: 1.16.0
|
||||
semver: 5.7.1
|
||||
validate-npm-package-license: 3.0.4
|
||||
dev: true
|
||||
@@ -3680,7 +3681,7 @@ packages:
|
||||
dependencies:
|
||||
autoprefixer: 9.7.6
|
||||
browserslist: 4.11.1
|
||||
caniuse-lite: 1.0.30001040
|
||||
caniuse-lite: 1.0.30001042
|
||||
css-blank-pseudo: 0.1.4
|
||||
css-has-pseudo: 0.10.0
|
||||
css-prefers-color-scheme: 3.1.1
|
||||
@@ -4044,12 +4045,12 @@ packages:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha1-3ZV5gufnNt699TtYpN2RdUV13UY=
|
||||
/resolve/1.15.1:
|
||||
/resolve/1.16.0:
|
||||
dependencies:
|
||||
path-parse: 1.0.6
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==
|
||||
integrity: sha512-LarL/PIKJvc09k1jaeT4kQb/8/7P+qV4qSnN2K80AES+OHdfZELAKVOBjxsvtToT/uLOfFbvYvKfZmV8cee7nA==
|
||||
/restore-cursor/3.1.0:
|
||||
dependencies:
|
||||
onetime: 5.1.0
|
||||
@@ -4544,6 +4545,10 @@ packages:
|
||||
node: '>=8'
|
||||
resolution:
|
||||
integrity: sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
|
||||
/svelte-lazy/0.1.10:
|
||||
dev: false
|
||||
resolution:
|
||||
integrity: sha512-3MobAvIUe345ZNREDvy/3tsfZMzPcSW+fE7osCVtGOAFeQ25haqQoZhT2c6qxxnWB7oVlTXTHCfEatzAGJi0fQ==
|
||||
/svelte-preprocess/3.7.1_svelte@3.20.1:
|
||||
dependencies:
|
||||
'@types/pug': 2.0.4
|
||||
@@ -4710,16 +4715,15 @@ packages:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
/uglify-js/3.8.1:
|
||||
/uglify-js/3.9.1:
|
||||
dependencies:
|
||||
commander: 2.20.3
|
||||
source-map: 0.6.1
|
||||
dev: true
|
||||
engines:
|
||||
node: '>=0.8.0'
|
||||
hasBin: true
|
||||
resolution:
|
||||
integrity: sha512-W7KxyzeaQmZvUFbGj4+YFshhVrMBGSg2IbcYAjGWGvx8DHvJMclbTDMpffdxFUGPBHjIytk7KJUR/KUXstUGDw==
|
||||
integrity: sha512-JUPoL1jHsc9fOjVFHdQIhqEEJsQvfKDjlubcCilu8U26uZ73qOg8VsN8O1jbuei44ZPlwL7kmbAdM4tzaUvqnA==
|
||||
/unicode-canonical-property-names-ecmascript/1.0.4:
|
||||
dev: true
|
||||
engines:
|
||||
@@ -4925,5 +4929,6 @@ specifiers:
|
||||
scroll-out: ^2.2.8
|
||||
sirv: ^0.4.2
|
||||
svelte: ^3.20.1
|
||||
svelte-lazy: ^0.1.10
|
||||
svelte-preprocess: ^3.7.1
|
||||
swipe-listener: ^1.1.0
|
||||
|
||||
@@ -130,20 +130,21 @@ export default {
|
||||
/*
|
||||
** Service worker
|
||||
*/
|
||||
serviceworker: {
|
||||
input: sapperConfig.serviceworker.input(),
|
||||
output: sapperConfig.serviceworker.output(),
|
||||
plugins: [
|
||||
resolve(),
|
||||
aliases,
|
||||
replace({
|
||||
'process.browser': true,
|
||||
...replaceOptions
|
||||
}),
|
||||
commonjs(),
|
||||
!dev && terser()
|
||||
],
|
||||
|
||||
onwarn,
|
||||
}
|
||||
// ...(!dev && {
|
||||
// serviceworker: {
|
||||
// input: sapperConfig.serviceworker.input(),
|
||||
// output: sapperConfig.serviceworker.output(),
|
||||
// plugins: [
|
||||
// resolve(),
|
||||
// aliases,
|
||||
// replace({
|
||||
// 'process.browser': true,
|
||||
// ...replaceOptions
|
||||
// }),
|
||||
// commonjs(),
|
||||
// !dev && terser()
|
||||
// ],
|
||||
// onwarn,
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export const animateIn = scope => {
|
||||
const tl = anime.timeline({
|
||||
easing: 'easeOutQuart',
|
||||
duration: animDuration,
|
||||
delay: animDelay,
|
||||
// delay: animDelay,
|
||||
autoplay: false
|
||||
})
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export const animateIn = () => {
|
||||
duration: animDuration
|
||||
})
|
||||
|
||||
// Parallax on scroll
|
||||
// Title: Parallax on scroll
|
||||
const translate = anime({
|
||||
targets: '#title-houses',
|
||||
translateX: ['7%', '-15%'],
|
||||
|
||||
@@ -40,8 +40,7 @@ export const animateIn = () => {
|
||||
// Illustration
|
||||
tl.add({
|
||||
targets: '.place__illustration',
|
||||
scale: [1.1, 1],
|
||||
translateX: ['-50%', '-50%'],
|
||||
scale: [1.05, 1],
|
||||
translateZ: [0, 0],
|
||||
opacity: [0, 1]
|
||||
}, 0)
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
import GeometryBuffer from './GeometryBuffer';
|
||||
import * as vec3 from './glMatrix/vec3';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class BoxGeometryBuffer extends GeometryBuffer {
|
||||
|
||||
constructor(gl, options) {
|
||||
|
||||
super(gl, 4.);
|
||||
|
||||
options = Object.assign({},{
|
||||
width: 10,
|
||||
height: 10,
|
||||
depth: 10,
|
||||
widthSegments: 1,
|
||||
heightSegments: 1,
|
||||
depthSegments: 1
|
||||
}, options);
|
||||
|
||||
// buffers
|
||||
var indices = [];
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
var colors = []
|
||||
|
||||
var numberOfVertices = 0;
|
||||
var vertexCounter = 0;
|
||||
|
||||
function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY ) {
|
||||
|
||||
vertexCounter = 0;
|
||||
|
||||
var segmentWidth = width / gridX;
|
||||
var segmentHeight = height / gridY;
|
||||
var widthHalf = width / 2;
|
||||
var heightHalf = height / 2;
|
||||
var depthHalf = depth / 2;
|
||||
var gridX1 = gridX + 1;
|
||||
var gridY1 = gridY + 1;
|
||||
var ix, iy;
|
||||
|
||||
var vector = vec3.create();
|
||||
|
||||
// generate vertices, normals and uvs
|
||||
|
||||
for ( iy = 0; iy < gridY1; iy ++ ) {
|
||||
|
||||
var y = iy * segmentHeight - heightHalf;
|
||||
|
||||
for ( ix = 0; ix < gridX1; ix ++ ) {
|
||||
|
||||
var x = ix * segmentWidth - widthHalf;
|
||||
|
||||
vector[ u ] = x * udir;
|
||||
vector[ v ] = y * vdir;
|
||||
vector[ w ] = depthHalf;
|
||||
vertices.push( vector[0], vector[1], vector[2] );
|
||||
|
||||
vector[ u ] = 1.;
|
||||
vector[ v ] = 1.;
|
||||
vector[ w ] = 1.;
|
||||
|
||||
vector[ u ] = 0;
|
||||
vector[ v ] = 0;
|
||||
vector[ w ] = depth > 0 ? 1 : -1;
|
||||
normals.push( vector[0], vector[1], vector[2] );
|
||||
|
||||
uvs.push( ix / gridX, 1 - ( iy / gridY ) );
|
||||
|
||||
colors.push( 1, 1, 1 );
|
||||
|
||||
vertexCounter += 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for ( iy = 0; iy < gridY; iy ++ ) {
|
||||
for ( ix = 0; ix < gridX; ix ++ ) {
|
||||
var a = numberOfVertices + ix + gridX1 * iy;
|
||||
var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
|
||||
var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
|
||||
var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
|
||||
// faces
|
||||
indices.push( a, b, d );
|
||||
indices.push( b, c, d );
|
||||
}
|
||||
}
|
||||
|
||||
numberOfVertices += vertexCounter;
|
||||
}
|
||||
|
||||
|
||||
// build each side of the box geometry
|
||||
buildPlane( 2, 1, 0, - 1, - 1, options.depth, options.height, options.width, Math.floor(options.depthSegments), Math.floor(options.heightSegments) ); // px
|
||||
buildPlane( 2, 1, 0, 1, - 1, options.depth, options.height, - options.width, Math.floor(options.depthSegments), Math.floor(options.heightSegments) ); // nx
|
||||
buildPlane( 0, 2, 1, 1, 1, options.width, options.depth, options.height, Math.floor(options.widthSegments), Math.floor(options.depthSegments) ); // py
|
||||
buildPlane( 0, 2, 1, 1, - 1, options.width, options.depth, - options.height, Math.floor(options.widthSegments), Math.floor(options.depthSegments) ); // ny
|
||||
buildPlane( 0, 1, 2, 1, - 1, options.width, options.height, options.depth, Math.floor(options.widthSegments), Math.floor(options.heightSegments) ); // pz
|
||||
buildPlane( 0, 1, 2, - 1, - 1, options.width, options.height, - options.depth, Math.floor(options.widthSegments), Math.floor(options.heightSegments) ); // nz
|
||||
|
||||
|
||||
// build geometry
|
||||
this.length = numberOfVertices;
|
||||
|
||||
this.addAttribute( 'index', new Uint16Array( indices ), 1 );
|
||||
this.addAttribute( 'position', new Float32Array( vertices ), 3 );
|
||||
this.addAttribute( 'normal', new Float32Array( normals ), 3 );
|
||||
this.addAttribute( 'uv', new Float32Array( uvs ), 2 );
|
||||
this.addAttribute( 'color', new Float32Array( colors ), 3 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BoxGeometryBuffer;
|
||||
@@ -319,75 +319,9 @@ class Camera extends Object3d {
|
||||
this.position[0] = Math.sin(this.currTheta) * Math.cos(this.phi) * this._cameraDistance;
|
||||
this.position[1] = Math.sin(this.phi) * this._cameraDistance;
|
||||
this.position[2] = Math.cos(this.currTheta) * Math.cos(this.phi) * this._cameraDistance;
|
||||
this.lookAt[0] = 0.000000001//this.pointerXMove / -100;
|
||||
this.lookAt[1] = 0.000000001//this.pointerYMove / 100;
|
||||
this.lookAt[2] = 0.000000001
|
||||
super.render();
|
||||
}
|
||||
}
|
||||
|
||||
else if (this.firstPerson)
|
||||
{
|
||||
|
||||
if (this._canUpdate || force) {
|
||||
|
||||
var time = Date.now();
|
||||
var delta = ( time - this.time ) / 1000;
|
||||
this.prevTime = time;
|
||||
this._velocity[0] -= this._velocity[0] * 10.0 * delta;
|
||||
this._velocity[1] -= this._velocity[1] * 10.0 * delta;
|
||||
this._velocity[2] -= this._velocity[2] * 10.0 * delta;
|
||||
|
||||
if (this.position[1] < 0 && this._velocity[1] < 0) {
|
||||
this._velocity[1] = 0;
|
||||
this.position[1] = 0
|
||||
}
|
||||
|
||||
if ( this._moveForward ) this._velocity[2] -= (this.moveSpeed) * delta;
|
||||
if ( this._moveBackward ) this._velocity[2] += (this.moveSpeed) * delta;
|
||||
if ( this._moveLeft ) this._velocity[0] -= (this.moveSpeed) * delta;
|
||||
if ( this._moveRight ) this._velocity[0] += (this.moveSpeed) * delta;
|
||||
|
||||
this._camera[0] = this._velocity[0];
|
||||
this._camera[1] = this._velocity[1];
|
||||
this._camera[2] = this._velocity[2];
|
||||
|
||||
this.currTheta += (this.theta - this.currTheta) * 0.2;
|
||||
this.currPhi += (this.phi - this.currPhi) * 0.2;
|
||||
|
||||
//first we reset position to center and rotate the camera
|
||||
this._oldPosition[0] = this.position[0];
|
||||
this._oldPosition[1] = this.position[1];
|
||||
this._oldPosition[2] = this.position[2];
|
||||
this.position[0] = 0;
|
||||
this.position[1] = 0;
|
||||
this.position[2] = 0;
|
||||
this.lookAt[0] = Math.sin(this.currTheta) * Math.cos(this.currPhi) * this._cameraDistance ;
|
||||
this.lookAt[1] = Math.sin(this.currPhi) * this._cameraDistance * -1 ;
|
||||
this.lookAt[2] = Math.cos(this.currTheta) * Math.cos(this.currPhi) * this._cameraDistance ;
|
||||
this.updateMatrix()
|
||||
|
||||
|
||||
//then we translate the camera based on velocity to folow view direction
|
||||
var _matrix = mat4.create();
|
||||
mat4.copy(_matrix, this.matrix);
|
||||
mat4.translate( _matrix, _matrix, this._camera);
|
||||
var _pos = vec3.create()
|
||||
mat4.getTranslation(_pos, _matrix);
|
||||
this.position[0] = this._oldPosition[0] + _pos[0]
|
||||
this.position[1] = this._oldPosition[1] + _pos[1]
|
||||
this.position[2] = this._oldPosition[2] + _pos[2]
|
||||
this.lookAt[0] = Math.sin(this.currTheta) * Math.cos(this.currPhi) * this._cameraDistance + this.position[0];
|
||||
this.lookAt[1] = Math.sin(this.currPhi) * this._cameraDistance * -1 + this.position[1];
|
||||
this.lookAt[2] = Math.cos(this.currTheta) * Math.cos(this.currPhi) * this._cameraDistance + this.position[2];
|
||||
this.updateMatrix();
|
||||
this.updateWorldMatrix();
|
||||
|
||||
this.time = time;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
super.render();
|
||||
}
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
import uuid from './utils/uuid';
|
||||
import getFilter from './utils/getFilter';
|
||||
import isPowerOf2 from './utils/isPowerOf2';
|
||||
|
||||
class CubeTexture {
|
||||
|
||||
constructor(gl, options) {
|
||||
|
||||
options = Object.assign({}, {
|
||||
format: gl.RGBA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
width: 1,
|
||||
height: 1,
|
||||
linear: true,
|
||||
mipmap: false,
|
||||
miplinear: false,
|
||||
wrapS: gl.CLAMP_TO_EDGE,
|
||||
wrapT: gl.CLAMP_TO_EDGE,
|
||||
urls: null
|
||||
}, options);
|
||||
|
||||
this._uid = uuid();//debug purpose
|
||||
this.gl = gl;
|
||||
this.width = options.width;
|
||||
this.height = options.height;
|
||||
this.format = options.format;
|
||||
this.type = options.type;
|
||||
|
||||
var floatTextures = gl.getExtension('OES_texture_float');
|
||||
var floatTextureLinearFiltering = gl.getExtension('OES_texture_float_linear');
|
||||
|
||||
if (!floatTextures) {
|
||||
throw('trying to create a FrameBuffer of with gl.FLOAT type but there\s no floating point texture support');
|
||||
return;
|
||||
}
|
||||
|
||||
this._texture = this.gl.createTexture();
|
||||
gl.bindTexture( gl.TEXTURE_CUBE_MAP, this._texture);
|
||||
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, this.format, this.width, this.height, 0, this.format, this.type, new Uint8Array(new Array(this.width*this.height*4)));
|
||||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, this.format, this.width, this.height, 0, this.format, this.type, new Uint8Array(new Array(this.width*this.height*4)));
|
||||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, this.format, this.width, this.height, 0, this.format, this.type, new Uint8Array(new Array(this.width*this.height*4)));
|
||||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, this.format, this.width, this.height, 0, this.format, this.type, new Uint8Array(new Array(this.width*this.height*4)));
|
||||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, this.format, this.width, this.height, 0, this.format, this.type, new Uint8Array(new Array(this.width*this.height*4)));
|
||||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, this.format, this.width, this.height, 0, this.format, this.type, new Uint8Array(new Array(this.width*this.height*4)));
|
||||
gl.bindTexture( gl.TEXTURE_CUBE_MAP, null);
|
||||
|
||||
// /**
|
||||
// * add getter and setter to update texture_wrap when this.wrap changes
|
||||
// */
|
||||
// Object.defineProperty(this, 'wrapS', {
|
||||
// set: (value) => {
|
||||
// this.gl.bindTexture( this.gl.TEXTURE_CUBE_MAP, this._texture);
|
||||
// this.gl.texParameteri( this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_S, value );
|
||||
// }
|
||||
// });
|
||||
// Object.defineProperty(this, 'wrapT', {
|
||||
// set: (value) => {
|
||||
// this.gl.bindTexture( this.gl.TEXTURE_CUBE_MAP, this._texture);
|
||||
// this.gl.texParameteri( this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_T, value );
|
||||
// }
|
||||
// });
|
||||
// //nPOT texture can't repeat
|
||||
// this.wrapS = options.wrapS;
|
||||
// this.wrapT = options.wrapT;
|
||||
|
||||
//nPOT texture cannot mipmap
|
||||
// this.setFilter( options.linear, options.mipmap, options.mipmapLinear );
|
||||
|
||||
if (options.urls !== null) {
|
||||
this.load(options.urls);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
load(urls) {
|
||||
var faces = [
|
||||
this.gl.TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||
this.gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||
this.gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
|
||||
this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||
this.gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
|
||||
this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z
|
||||
];
|
||||
for (let i = 0; i < urls.length; i++) {
|
||||
let face = faces[i];
|
||||
let image = new Image();
|
||||
image.onload = ()=> {
|
||||
image.onload = null;
|
||||
// this.bindFaceImage(face, image);
|
||||
this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, this._texture);
|
||||
this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);
|
||||
this.gl.texImage2D(face, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, image);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
||||
}
|
||||
image.src = urls[i];
|
||||
}
|
||||
}
|
||||
|
||||
bindFaceImage(face, image) {
|
||||
this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, this._texture);
|
||||
this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);
|
||||
if (image._texture) {
|
||||
this.gl.texImage2D(face, 0, this.format, image.width, image.height, 0, this.format, this.type, image._texture);
|
||||
}
|
||||
else {
|
||||
this.gl.texImage2D(face, 0, this.format, image.width, image.height, 0, this.format, this.type, image);
|
||||
}
|
||||
}
|
||||
|
||||
bindFaceFrameBuffer(face, frameBuffer) {
|
||||
this.gl.bindTexture( this.gl.TEXTURE_CUBE_MAP, this._texture);
|
||||
this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, frameBuffer.fbo );
|
||||
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, face, this._texture, 0);
|
||||
let status_code = this.gl.checkFramebufferStatus(this.gl.FRAMEBUFFER);
|
||||
if (status_code != this.gl.FRAMEBUFFER_COMPLETE) {
|
||||
if (status_code == this.gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT) {
|
||||
console.log('GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT');
|
||||
}
|
||||
if (status_code == this.gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS) {
|
||||
console.log('FRAMEBUFFER_INCOMPLETE_DIMENSIONS: Not all attached images have the same width and height.');
|
||||
}
|
||||
if (status_code == this.gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
|
||||
console.log('FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: No images are attached to the framebuffer.');
|
||||
}
|
||||
} else {
|
||||
console.log("success");
|
||||
}
|
||||
// this.gl.bindTexture( this.gl.TEXTURE_CUBE_MAP, null );
|
||||
this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, null );
|
||||
frameBuffer.unbind();
|
||||
}
|
||||
|
||||
bind(unit) {
|
||||
if( unit !== undefined ){
|
||||
this.gl.activeTexture( this.gl.TEXTURE0 + (0|unit) );
|
||||
}
|
||||
this.gl.bindTexture( this.gl.TEXTURE_CUBE_MAP, this._texture );
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.gl.deleteTexture( this._texture );
|
||||
this._texture = null;
|
||||
this.gl = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CubeTexture;
|
||||
@@ -1,64 +0,0 @@
|
||||
class DepthTexture {
|
||||
|
||||
constructor(gl, options) {
|
||||
|
||||
let supportsDepthTexture = gl.getExtension("WEBGL_depth_texture");
|
||||
|
||||
if (!supportsDepthTexture) {
|
||||
throw("FrameBuffer useDepthTexture:true => Cannot render depth to texture, the browser doesnt support WEBKIT_WEBGL_depth_texture extension")
|
||||
}
|
||||
|
||||
options = Object.assign({}, {
|
||||
width: 1,
|
||||
height: 1,
|
||||
type: gl.UNSIGNED_SHORT
|
||||
}, options);
|
||||
|
||||
this.gl = gl;
|
||||
this.width = options.width;
|
||||
this.height = options.height;
|
||||
this.type = options.type;
|
||||
|
||||
var floatTextures = gl.getExtension('OES_texture_float');
|
||||
var floatTextureLinearFiltering = gl.getExtension('OES_texture_float_linear');
|
||||
|
||||
if (!floatTextures && this.type == gl.FLOAT) {
|
||||
throw('trying to create a DepthTexture of gl.FLOAT type but there\s no floating point texture support');
|
||||
return;
|
||||
}
|
||||
|
||||
this._texture = this.gl.createTexture();
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.DEPTH_COMPONENT, this.width, this.height, 0, this.gl.DEPTH_COMPONENT, this.type, null);
|
||||
gl.bindTexture( gl.TEXTURE_2D, null);
|
||||
|
||||
}
|
||||
|
||||
bind(unit) {
|
||||
if (unit !== void 0) {
|
||||
this.gl.activeTexture( this.gl.TEXTURE0 + (0|unit) );
|
||||
}
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.gl.deleteTexture( this._texture );
|
||||
this._texture = null;
|
||||
this.gl = null;
|
||||
}
|
||||
|
||||
resize(w, h) {
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.DEPTH_COMPONENT, this.width, this.height, 0, this.gl.DEPTH_COMPONENT, this.type, null);
|
||||
gl.bindTexture( gl.TEXTURE_2D, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default DepthTexture;
|
||||
@@ -1,231 +0,0 @@
|
||||
import getFilter from './utils/getFilter';
|
||||
import isPowerOf2 from './utils/isPowerOf2';
|
||||
|
||||
class FrameBuffer {
|
||||
|
||||
constructor ( gl, options ) {
|
||||
|
||||
this.options = Object.assign({},{
|
||||
format: gl.RGBA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
linear: true,
|
||||
mipmap: false,
|
||||
mipmapLinear: false,
|
||||
wrapS: gl.CLAMP_TO_EDGE,
|
||||
wrapT: gl.CLAMP_TO_EDGE,
|
||||
depthTexture: null
|
||||
}, options);
|
||||
|
||||
this.gl = gl;
|
||||
|
||||
this.width = this.options.width;
|
||||
this.height = this.options.height;
|
||||
this.format = this.options.format;
|
||||
this.type = this.options.type;
|
||||
this.linear = this.options.linear;
|
||||
this.mipmap = this.options.mipmap;
|
||||
this.mipmapLinear = this.options.mipmapLinear;
|
||||
|
||||
if (this.type == gl.FLOAT) {
|
||||
var floatTextures = gl.getExtension('OES_texture_float');
|
||||
var floatTextureLinearFiltering = gl.getExtension('OES_texture_float_linear');
|
||||
if (!floatTextures) {
|
||||
console.warn('trying to create a FrameBuffer of with gl.FLOAT type but there\s no floating point texture support. trying HALF_FLOAT');
|
||||
this.type = "HALF_FLOAT"
|
||||
}
|
||||
}
|
||||
|
||||
if (this.type == "HALF_FLOAT") {
|
||||
var halfFloatTexturesExt = gl.getExtension('OES_texture_half_float');
|
||||
var halfFloatTextureLinearFiltering = gl.getExtension('OES_texture_half_float_linear');
|
||||
if (!halfFloatTexturesExt) {
|
||||
console.warn('trying to create a texture of with gl.HALF_FLOAT type but there\s no half floating point texture support; falling bck to UNSIGNED_BYTE type');
|
||||
this.type = gl.UNSIGNED_BYTE;
|
||||
}
|
||||
else {
|
||||
this.type = halfFloatTexturesExt.HALF_FLOAT_OES;
|
||||
this.isHalfFloat = true;
|
||||
}
|
||||
}
|
||||
|
||||
this._texture = this.gl.createTexture();
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
|
||||
|
||||
if (this.type == this.gl.FLOAT) {
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, new Float32Array( new Array(this.width * this.height * 4) ));
|
||||
}
|
||||
else if (this.isHalfFloat) {
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, null);
|
||||
}
|
||||
else {
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, new Uint8Array( new Array(this.width * this.height * 4) ));
|
||||
}
|
||||
|
||||
/**
|
||||
* add getter and setter to update texture_wrap when this.wrap changes
|
||||
*/
|
||||
Object.defineProperty(this, 'wrapS', {
|
||||
set: (value) => {
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
|
||||
this.gl.texParameteri( this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, value );
|
||||
}
|
||||
});
|
||||
Object.defineProperty(this, 'wrapT', {
|
||||
set: (value) => {
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
|
||||
this.gl.texParameteri( this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, value );
|
||||
}
|
||||
});
|
||||
|
||||
//nPOT texture can't repeat
|
||||
this.wrapS = this.options.wrapS;
|
||||
this.wrapT = this.options.wrapT;
|
||||
|
||||
var isPOT = isPowerOf2(this.width) && isPowerOf2(this.height);
|
||||
if (!isPOT) {
|
||||
this.wrapS = gl.CLAMP_TO_EDGE;
|
||||
this.wrapT = gl.CLAMP_TO_EDGE;
|
||||
this.mipmap = false;
|
||||
this.mipmapLinear = false;
|
||||
}
|
||||
|
||||
//nPOT texture cannot mipmap
|
||||
this.setFilter( this.linear, this.mipmap, this.mipmapLinear );
|
||||
|
||||
|
||||
if (!this.options.depthTexture) {
|
||||
this.renderbuffer = this.gl.createRenderbuffer();
|
||||
this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
this.gl.renderbufferStorage(this.gl.RENDERBUFFER, this.gl.DEPTH_COMPONENT16, this.width, this.height);
|
||||
}
|
||||
|
||||
this.fbo = this.gl.createFramebuffer();
|
||||
this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, this.fbo );
|
||||
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this._texture, 0);
|
||||
|
||||
if (this.options.depthTexture) {
|
||||
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.TEXTURE_2D, this.options.depthTexture._texture, 0);
|
||||
}
|
||||
else {
|
||||
this.gl.framebufferRenderbuffer(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
}
|
||||
|
||||
this.unbind();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* [setFilter description]
|
||||
* @param {[type]} linear [description]
|
||||
* @param {[type]} mipmap [description]
|
||||
* @param {[type]} mipmapLinear [description]
|
||||
*/
|
||||
setFilter(linear, mipmap, mipmapLinear) {
|
||||
var gl = this.gl;
|
||||
var filter = getFilter( !!linear, !!mipmap, !!mipmapLinear);
|
||||
gl.bindTexture( gl.TEXTURE_2D, this._texture);
|
||||
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, getFilter( !!linear, false, false ) );
|
||||
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter );
|
||||
}
|
||||
|
||||
resize(w, h) {
|
||||
|
||||
if( this.width !== w || this.height !== h ) {
|
||||
this.width = w|0;
|
||||
this.height = h|0;
|
||||
}
|
||||
|
||||
var isPOT = isPowerOf2(this.width) && isPowerOf2(this.height);
|
||||
if (!isPOT) {
|
||||
this.wrapS = this.gl.CLAMP_TO_EDGE;
|
||||
this.wrapT = this.gl.CLAMP_TO_EDGE;
|
||||
this.mipmap = false;
|
||||
this.mipmapLinear = false;
|
||||
this.setFilter( this.linear, this.mipmap, this.mipmapLinear );
|
||||
}
|
||||
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
|
||||
// this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, new Uint8Array( new Array(this.width * this.height * 4) ));
|
||||
|
||||
if (this.type == this.gl.FLOAT) {
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, new Float32Array( new Array(this.width * this.height * 4) ));
|
||||
}
|
||||
else if (this.isHalfFloat) {
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, null);
|
||||
}
|
||||
else {
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, new Uint8Array( new Array(this.width * this.height * 4) ));
|
||||
}
|
||||
|
||||
|
||||
if (this.options.depthTexture) {
|
||||
this.depthTexture.resize(this.width, this.height);
|
||||
// this.gl.bindTexture(this.gl.TEXTURE_2D, this._depthTexture);
|
||||
// this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.DEPTH_COMPONENT, this.width, this.height, 0, this.gl.DEPTH_COMPONENT, this.gl.UNSIGNED_SHORT, null);
|
||||
}
|
||||
|
||||
this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, this.fbo );
|
||||
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this._texture, 0);
|
||||
|
||||
if (this.options.depthTexture) {
|
||||
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.TEXTURE_2D, this.options.depthTexture._texture, 0);
|
||||
}
|
||||
else {
|
||||
this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
this.gl.renderbufferStorage(this.gl.RENDERBUFFER, this.gl.DEPTH_COMPONENT16, this.width, this.height);
|
||||
this.gl.framebufferRenderbuffer(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
}
|
||||
|
||||
this.unbind();
|
||||
}
|
||||
|
||||
bindFrame() {
|
||||
this.gl.viewport( 0, 0, this.width, this.height );
|
||||
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.fbo);
|
||||
if (!this.options.depthTexture) {
|
||||
this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
}
|
||||
else {
|
||||
this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
this.gl.renderbufferStorage(this.gl.RENDERBUFFER, this.gl.DEPTH_COMPONENT16, this.width, this.height);
|
||||
this.gl.framebufferRenderbuffer(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
}
|
||||
this.clear();
|
||||
}
|
||||
|
||||
bind(unit) {
|
||||
if (unit !== void 0) {
|
||||
this.gl.activeTexture( this.gl.TEXTURE0 + (0|unit) );
|
||||
}
|
||||
// else {
|
||||
// this.gl.activeTexture( this.gl.TEXTURE0 );
|
||||
// }
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
|
||||
}
|
||||
|
||||
unbind() {
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, null);
|
||||
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
|
||||
if (!this.options.depthTexture) {
|
||||
this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, null);
|
||||
}
|
||||
}
|
||||
|
||||
clear(color, depth, stencil) {
|
||||
var bits = 0;
|
||||
if ( color === void 0 || color ) bits |= this.gl.COLOR_BUFFER_BIT;
|
||||
if ( depth === void 0 || depth ) bits |= this.gl.DEPTH_BUFFER_BIT;
|
||||
if ( stencil === void 0 || stencil ) bits |= this.gl.STENCIL_BUFFER_BIT;
|
||||
this.gl.clear( bits );
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.gl.deleteFramebuffer( this.fbo );
|
||||
this.fbo = null;
|
||||
this.gl = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default FrameBuffer;
|
||||
@@ -1,74 +0,0 @@
|
||||
import Texture from './Texture';
|
||||
|
||||
class FrameBuffer extends Texture {
|
||||
|
||||
constructor ( gl, options ) {
|
||||
|
||||
super(gl, options);
|
||||
|
||||
this.fbo = this.gl.createFramebuffer();
|
||||
this.renderbuffer = this.gl.createRenderbuffer();
|
||||
|
||||
this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, this.fbo );
|
||||
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this._texture, 0);
|
||||
|
||||
this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
this.gl.renderbufferStorage(this.gl.RENDERBUFFER, this.gl.DEPTH_COMPONENT16, this.width, this.height);
|
||||
this.gl.framebufferRenderbuffer(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
|
||||
this.unbind();
|
||||
|
||||
}
|
||||
|
||||
resize( w, h ){
|
||||
|
||||
if( this.width !== w || this.height !== h ) {
|
||||
this.width = w|0;
|
||||
this.height = h|0;
|
||||
}
|
||||
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, null);
|
||||
// this.gl.framebufferTexture2D( this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this._texture, 0 );
|
||||
|
||||
this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, this.fbo );
|
||||
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this._texture, 0);
|
||||
|
||||
this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
this.gl.renderbufferStorage(this.gl.RENDERBUFFER, this.gl.DEPTH_COMPONENT16, this.width, this.height);
|
||||
this.gl.framebufferRenderbuffer(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
|
||||
this.unbind();
|
||||
|
||||
}
|
||||
|
||||
bindFrame() {
|
||||
this.gl.viewport( 0, 0, this.width, this.height );
|
||||
this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.renderbuffer);
|
||||
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.fbo);
|
||||
this.clear();
|
||||
}
|
||||
|
||||
unbind() {
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, null);
|
||||
this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, null);
|
||||
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
|
||||
}
|
||||
|
||||
clear(color, depth, stencil) {
|
||||
var bits = 0;
|
||||
if ( color === void 0 || color ) bits |= this.gl.COLOR_BUFFER_BIT;
|
||||
if ( depth === void 0 || depth ) bits |= this.gl.DEPTH_BUFFER_BIT;
|
||||
if ( stencil === void 0 || stencil ) bits |= this.gl.STENCIL_BUFFER_BIT;
|
||||
this.gl.clear( bits );
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.gl.deleteFramebuffer( this.fbo );
|
||||
this.fbo = null;
|
||||
this.gl = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FrameBuffer;
|
||||
@@ -1,207 +0,0 @@
|
||||
import uuid from './utils/uuid';
|
||||
import isPowerOf2 from './utils/isPowerOf2';
|
||||
import RGBEParser from './RGBEParser';
|
||||
|
||||
|
||||
import parseHDR from 'parse-hdr';
|
||||
|
||||
|
||||
function toArrayBuffer (buffer) {
|
||||
var ab = new ArrayBuffer(buffer.length)
|
||||
var view = new Uint8Array(ab)
|
||||
for (var i = 0; i < buffer.length; ++i) {
|
||||
view[i] = buffer[i]
|
||||
}
|
||||
return ab
|
||||
}
|
||||
|
||||
function BinaryLoad(){
|
||||
// this is just a helper class to ease BinaryLoad calls
|
||||
var _this = this;
|
||||
this.xmlhttp = new XMLHttpRequest();
|
||||
this.get = function(url, callback){
|
||||
_this.xmlhttp.onreadystatechange = function(){
|
||||
if(_this.xmlhttp.readyState === 4){
|
||||
callback(_this.xmlhttp.response, _this.xmlhttp.status);
|
||||
}
|
||||
};
|
||||
_this.xmlhttp.open('GET', url, true);
|
||||
_this.xmlhttp.responseType = 'arraybuffer'
|
||||
_this.xmlhttp.send();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function RGBEByteToRGBFloat( sourceArray, sourceOffset, destArray, destOffset ) {
|
||||
var e = sourceArray[ sourceOffset + 3 ];
|
||||
var scale = Math.pow( 2.0, e - 128.0 ) / 255.0;
|
||||
destArray[ destOffset + 0 ] = sourceArray[ sourceOffset + 0 ] * scale;
|
||||
destArray[ destOffset + 1 ] = sourceArray[ sourceOffset + 1 ] * scale;
|
||||
destArray[ destOffset + 2 ] = sourceArray[ sourceOffset + 2 ] * scale;
|
||||
};
|
||||
|
||||
var RGBEByteToRGBHalf = ( function () {
|
||||
// Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410
|
||||
var floatView = new Float32Array( 1 );
|
||||
var int32View = new Int32Array( floatView.buffer );
|
||||
/* This method is faster than the OpenEXR implementation (very often
|
||||
* used, eg. in Ogre), with the additional benefit of rounding, inspired
|
||||
* by James Tursa?s half-precision code. */
|
||||
function toHalf( val ) {
|
||||
floatView[ 0 ] = val;
|
||||
var x = int32View[ 0 ];
|
||||
var bits = ( x >> 16 ) & 0x8000; /* Get the sign */
|
||||
var m = ( x >> 12 ) & 0x07ff; /* Keep one extra bit for rounding */
|
||||
var e = ( x >> 23 ) & 0xff; /* Using int is faster here */
|
||||
/* If zero, or denormal, or exponent underflows too much for a denormal
|
||||
* half, return signed zero. */
|
||||
if ( e < 103 ) return bits;
|
||||
/* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
|
||||
if ( e > 142 ) {
|
||||
bits |= 0x7c00;
|
||||
/* If exponent was 0xff and one mantissa bit was set, it means NaN,
|
||||
* not Inf, so make sure we set one mantissa bit too. */
|
||||
bits |= ( ( e == 255 ) ? 0 : 1 ) && ( x & 0x007fffff );
|
||||
return bits;
|
||||
}
|
||||
/* If exponent underflows but not too much, return a denormal */
|
||||
if ( e < 113 ) {
|
||||
m |= 0x0800;
|
||||
/* Extra rounding may overflow and set mantissa to 0 and exponent
|
||||
* to 1, which is OK. */
|
||||
bits |= ( m >> ( 114 - e ) ) + ( ( m >> ( 113 - e ) ) & 1 );
|
||||
return bits;
|
||||
|
||||
}
|
||||
bits |= ( ( e - 112 ) << 10 ) | ( m >> 1 );
|
||||
/* Extra rounding. An overflow will set mantissa to 0 and increment
|
||||
* the exponent, which is OK. */
|
||||
bits += m & 1;
|
||||
return bits;
|
||||
}
|
||||
return function ( sourceArray, sourceOffset, destArray, destOffset ) {
|
||||
var e = sourceArray[ sourceOffset + 3 ];
|
||||
var scale = Math.pow( 2.0, e - 128.0 ) / 255.0;
|
||||
destArray[ destOffset + 0 ] = toHalf( sourceArray[ sourceOffset + 0 ] * scale );
|
||||
destArray[ destOffset + 1 ] = toHalf( sourceArray[ sourceOffset + 1 ] * scale );
|
||||
destArray[ destOffset + 2 ] = toHalf( sourceArray[ sourceOffset + 2 ] * scale );
|
||||
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
|
||||
class HDRTexture {
|
||||
|
||||
constructor(gl, options) {
|
||||
|
||||
options = Object.assign({}, {
|
||||
format: gl.RGBA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
width: 1,
|
||||
height: 1,
|
||||
linear: false,
|
||||
mipmap: false,
|
||||
miplinear: false,
|
||||
wrapS: gl.CLAMP_TO_EDGE,
|
||||
wrapT: gl.CLAMP_TO_EDGE,
|
||||
url: null,
|
||||
onReady:()=>{}
|
||||
}, options);
|
||||
|
||||
this.options = options
|
||||
|
||||
this._uid = uuid();//debug purpose
|
||||
this.gl = gl;
|
||||
this.width = options.width;
|
||||
this.height = options.height;
|
||||
this.format = options.format;
|
||||
this.type = options.type;
|
||||
|
||||
var floatTextures = gl.getExtension('OES_texture_float');
|
||||
var floatTextureLinearFiltering = gl.getExtension('OES_texture_float_linear');
|
||||
|
||||
if (!floatTextures) {
|
||||
throw('trying to create a FrameBuffer of with gl.FLOAT type but there\s no floating point texture support');
|
||||
return;
|
||||
}
|
||||
|
||||
this._texture = this.gl.createTexture();
|
||||
gl.bindTexture( gl.TEXTURE_2D, this._texture);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, this.options.format, this.width, this.height, 0, this.options.format, this.gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 255]));
|
||||
gl.bindTexture( gl.TEXTURE_2D, null);
|
||||
|
||||
if (this.options.url) {
|
||||
this.load(this.options.url)
|
||||
}
|
||||
}
|
||||
|
||||
load(url) {
|
||||
console.log("HDRTexture.load", url)
|
||||
new BinaryLoad().get(url, (data, status)=>{
|
||||
|
||||
if (status === 200) {
|
||||
// var arrBuffer = toArrayBuffer(data);
|
||||
var texData = RGBEParser(data);
|
||||
// if ( this.options.type === this.gl.FLOAT ) {
|
||||
// var numElements = ( texData.data.length / 4 ) * 3;
|
||||
// var floatdata = new Float32Array( numElements );
|
||||
// for ( var j = 0; j < numElements; j ++ ) {
|
||||
// RGBEByteToRGBFloat( texData.data, j * 4, floatdata, j * 3 );
|
||||
// }
|
||||
// texData.data = floatdata;
|
||||
// } else if ( this.options.type === this.gl.HALF_FLOAT ) {
|
||||
// var numElements = ( texData.data.length / 4 ) * 3;
|
||||
// var halfdata = new Uint16Array( numElements );
|
||||
// for ( var j = 0; j < numElements; j ++ ) {
|
||||
// RGBEByteToRGBHalf( texData.data, j * 4, halfdata, j * 3 );
|
||||
// }
|
||||
// texData.data = halfdata;
|
||||
// }
|
||||
this.gl.bindTexture( this.gl.TEXTURE_2D, this._texture);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
|
||||
this.width = texData.width
|
||||
this.height = texData.height
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.options.format, texData.width, texData.height, 0, this.options.format, this.options.type, texData.data);
|
||||
this.gl.bindTexture( this.gl.TEXTURE_2D, null);
|
||||
|
||||
this.options.onReady()
|
||||
|
||||
}
|
||||
else {
|
||||
error = true;
|
||||
console.error('An error has occurred and the HDR "' + url + '" could not be downloaded.');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
bind(unit) {
|
||||
if (!this.gl) {
|
||||
return;
|
||||
}
|
||||
//unit is sent by the Program and defined by the unfirom order in the shaders;
|
||||
if (unit !== void 0) {
|
||||
this.gl.activeTexture( this.gl.TEXTURE0 + (0|unit) );
|
||||
}
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this._texture);
|
||||
}
|
||||
|
||||
delete() {
|
||||
if (this.gl) {
|
||||
this.gl.deleteTexture( this._texture );
|
||||
}
|
||||
this._texture = null;
|
||||
this.gl = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default HDRTexture;
|
||||
@@ -1,84 +0,0 @@
|
||||
import {GeometryBuffer} from 'beam';
|
||||
import {ArrayBuffer} from 'beam';
|
||||
|
||||
class Ajax {
|
||||
constructor() {
|
||||
this.xmlhttp = new XMLHttpRequest();
|
||||
this.get = (url, callback)=>{
|
||||
this.xmlhttp.onreadystatechange = ()=>{
|
||||
if(this.xmlhttp.readyState === 4){
|
||||
callback(this.xmlhttp.responseText, this.xmlhttp.status);
|
||||
}
|
||||
};
|
||||
this.xmlhttp.open('GET', url, true);
|
||||
this.xmlhttp.send();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class JSONGeometryBuffer extends GeometryBuffer {
|
||||
constructor(gl, options) {
|
||||
super(gl, 4.);
|
||||
this.gl = gl;
|
||||
options = Object.assign({},{
|
||||
src: null,
|
||||
onLoaded: ()=>{}
|
||||
}, options);
|
||||
this.options = options;
|
||||
// buffers
|
||||
this.indices = [];
|
||||
this.vertices = [];
|
||||
this.normals = [];
|
||||
this.uvs = [];
|
||||
// build geometry
|
||||
this.length = 0;
|
||||
this.addAttribute( 'index', new Uint16Array( this.indices ), 1 );
|
||||
this.addAttribute( 'position', new Float32Array( this.vertices ), 3 );
|
||||
this.addAttribute( 'normal', new Float32Array( this.normals ), 3 );
|
||||
this.addAttribute( 'uv', new Float32Array( this.uvs ), 2 );
|
||||
new Ajax().get(options.src, (data, status)=>{
|
||||
if (status !== 200) {
|
||||
console.error('An error has occurred while download JSON: ' + this.props.src);
|
||||
throw '';
|
||||
}
|
||||
else {
|
||||
this._onDataLoaded(JSON.parse(data))
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_onDataLoaded(meshes) {
|
||||
this.attributes = {}
|
||||
this.indices = meshes.indices
|
||||
this.vertices = meshes.vertices
|
||||
this.normals = meshes.vertexNormals
|
||||
this.uvs = meshes.textures
|
||||
let needsUvs, needsNormals;
|
||||
if (this.uvs.length == 0) {
|
||||
needsUvs = true;
|
||||
}
|
||||
if (this.normals.length == 0) {
|
||||
needsNormals = true;
|
||||
}
|
||||
for (let i=0; i<this.vertices.length/3;i++) {
|
||||
if (needsUvs) {
|
||||
this.uvs.push( 0,0 )
|
||||
}
|
||||
if (needsNormals) {
|
||||
this.normals.push( 0,1,0 );
|
||||
}
|
||||
}
|
||||
this.attributes['index'] = new ArrayBuffer(this.gl, new Uint16Array(this.indices), 1, true);
|
||||
this.attributes['position'] = new ArrayBuffer(this.gl, new Float32Array(this.vertices), 3, false);
|
||||
this.attributes['normal'] = new ArrayBuffer(this.gl, new Float32Array(this.normals), 3, false);
|
||||
this.attributes['uv'] = new ArrayBuffer(this.gl, new Float32Array(this.uvs), 2, false);
|
||||
// this.computeBoundingSphere();
|
||||
this.options.onLoaded()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default JSONGeometryBuffer;
|
||||
@@ -1,98 +0,0 @@
|
||||
import {Object3d} from 'beam';
|
||||
import {vec3, mat4} from 'beam';
|
||||
import {Camera} from 'beam';
|
||||
|
||||
|
||||
class Light extends Object3d {
|
||||
|
||||
constructor(options={}) {
|
||||
|
||||
options = Object.assign({},{
|
||||
|
||||
color: [1,1,1],
|
||||
direction: [-1,-1,0],
|
||||
position: [1,1,1],
|
||||
intensity: 1,
|
||||
distance: 1000000,
|
||||
decay: 1,
|
||||
angle: Math.PI/4,
|
||||
exponent: 1,
|
||||
castShadow: false,
|
||||
penumbra: 0,
|
||||
lookAt: vec3.create(),
|
||||
|
||||
shadowMap: true,
|
||||
shadowMapWidth: 256,
|
||||
shadowMapHeight: 256,
|
||||
|
||||
}, options)
|
||||
|
||||
super(options)
|
||||
|
||||
this.color = options.color;
|
||||
this.intensity = options.intensity;
|
||||
this.position = options.position;
|
||||
this.distance = options.distance;
|
||||
this.decay = options.decay;
|
||||
this.angle = options.angle;
|
||||
this.exponent = options.exponent;
|
||||
this.penumbra = options.penumbra;
|
||||
this.castShadow = options.castShadow;
|
||||
this.lookAt = options.lookAt;
|
||||
|
||||
if (options.shadowMap) {
|
||||
this.shadowMap = true;
|
||||
this._cacheAngle = this.angle;
|
||||
this.shadowMapCamera = new Camera({
|
||||
near: 1,
|
||||
far: this.distance,
|
||||
type: 'perspective',
|
||||
fov: ( 2 * this.angle ) * 180 / Math.PI,
|
||||
aspect: 1,
|
||||
});
|
||||
this.shadowMapCamera.lookAt = vec3.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
update() {
|
||||
|
||||
this.updateMatrix();
|
||||
this.updateWorldMatrix();
|
||||
|
||||
if (this.shadowMap) {
|
||||
|
||||
// if (this._cacheAngle !== this.angle) {
|
||||
// this._cacheAngle = this.angle;
|
||||
this.shadowMapCamera.fov = ( 2 * this.angle ) * 180 / Math.PI;
|
||||
this.shadowMapCamera.updateProjectionMatrix()
|
||||
// }
|
||||
|
||||
//TODO: make the camera a child of the light object
|
||||
// instead of copy all props
|
||||
this.shadowMapCamera.position[0] = this.position[0];
|
||||
this.shadowMapCamera.position[1] = this.position[1];
|
||||
this.shadowMapCamera.position[2] = this.position[2];
|
||||
|
||||
this.shadowMapCamera.lookAt[0] = this.lookAt[0];
|
||||
this.shadowMapCamera.lookAt[1] = this.lookAt[1];
|
||||
this.shadowMapCamera.lookAt[2] = this.lookAt[2];
|
||||
|
||||
this.shadowMapCamera.rotation[0] = this.rotation[0];
|
||||
this.shadowMapCamera.rotation[1] = this.rotation[1];
|
||||
this.shadowMapCamera.rotation[2] = this.rotation[2];
|
||||
|
||||
this.shadowMapCamera.updateMatrix()
|
||||
this.shadowMapCamera.updateWorldMatrix()
|
||||
// mat4.copy(this.shadowMapCamera.matrix, this.matrix);
|
||||
// mat4.copy(this.shadowMapCamera.worldMatrix, this.worldMatrix);
|
||||
// mat4.copy(this.shadowMapCamera.inverseWorldMatrix, this.inverseWorldMatrix);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default Light;
|
||||
@@ -1,33 +0,0 @@
|
||||
export default {
|
||||
|
||||
cache: {
|
||||
|
||||
},
|
||||
|
||||
loadImage (url, callback) {
|
||||
|
||||
if (this.cache[url] !== void 0) {
|
||||
callback( this.cache[url] );
|
||||
return;
|
||||
}
|
||||
|
||||
var image = new Image();
|
||||
|
||||
image.onload = ()=>{
|
||||
image.onload = null;
|
||||
image.onerror = null;
|
||||
this.cache[url] = image;
|
||||
callback(image);
|
||||
}
|
||||
|
||||
image.onerror = ()=>{
|
||||
image.onload = null;
|
||||
image.onerror = null;
|
||||
console.warn('Cannot load image :' + url);
|
||||
}
|
||||
|
||||
image.src = url;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
import {GeometryBuffer} from 'beam';
|
||||
import {vec3} from 'beam';
|
||||
import OBJ from "./webgl-obj-loader"
|
||||
import {ArrayBuffer} from 'beam';
|
||||
|
||||
class ObjGeometryBuffer extends GeometryBuffer {
|
||||
constructor(gl, options) {
|
||||
super(gl, 4.);
|
||||
this.gl = gl;
|
||||
options = Object.assign({},{
|
||||
src: null,
|
||||
onLoaded: ()=>{}
|
||||
}, options);
|
||||
this.options = options;
|
||||
// buffers
|
||||
this.indices = [];
|
||||
this.vertices = [];
|
||||
this.normals = [];
|
||||
this.uvs = [];
|
||||
// build geometry
|
||||
this.length = 0;
|
||||
this.addAttribute( 'index', new Uint16Array( this.indices ), 1 );
|
||||
this.addAttribute( 'position', new Float32Array( this.vertices ), 3 );
|
||||
this.addAttribute( 'normal', new Float32Array( this.normals ), 3 );
|
||||
this.addAttribute( 'uv', new Float32Array( this.uvs ), 2 );
|
||||
this.onObjLoaded = this.onObjLoaded.bind(this);
|
||||
if (options.lod) {
|
||||
OBJ.downloadMeshes(options.lod, this.onObjLoaded)
|
||||
}
|
||||
else {
|
||||
OBJ.downloadMeshes([options.src], this.onObjLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
onObjLoaded(meshes) {
|
||||
|
||||
this.attributes = {}
|
||||
this.indices = meshes[0].indices
|
||||
this.vertices = meshes[0].vertices
|
||||
this.normals = meshes[0].vertexNormals
|
||||
this.uvs = meshes[0].textures
|
||||
let needsUvs, needsNormals;
|
||||
if (this.uvs.length == 0) {
|
||||
needsUvs = true;
|
||||
}
|
||||
if (this.normals.length == 0) {
|
||||
needsNormals = true;
|
||||
}
|
||||
for (let i=0; i<this.vertices.length/3;i++) {
|
||||
if (needsUvs) {
|
||||
this.uvs.push( 0,0 )
|
||||
}
|
||||
if (needsNormals) {
|
||||
this.normals.push( 0,1,0 );
|
||||
}
|
||||
}
|
||||
this.attributes['index'] = new ArrayBuffer(this.gl, new Uint16Array(this.indices), 1, true);
|
||||
this.attributes['position'] = new ArrayBuffer(this.gl, new Float32Array(this.vertices), 3, false);
|
||||
this.attributes['normal'] = new ArrayBuffer(this.gl, new Float32Array(this.normals), 3, false);
|
||||
this.attributes['uv'] = new ArrayBuffer(this.gl, new Float32Array(this.uvs), 2, false);
|
||||
// this.computeBoundingSphere();
|
||||
this.options.onLoaded()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default ObjGeometryBuffer;
|
||||
@@ -3,16 +3,6 @@ import * as mat3 from './glMatrix/mat3';
|
||||
import * as quat from './glMatrix/quat';
|
||||
import * as vec3 from './glMatrix/vec3';
|
||||
|
||||
// var objects = []
|
||||
|
||||
// function needsUpdateLoop() {
|
||||
// requestAnimationFrame(needsUpdateLoop);
|
||||
// for (let i=0; i<objects.length; i++) {
|
||||
// objects[i].needsUpdate = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
// needsUpdateLoop();
|
||||
|
||||
class Object3d {
|
||||
|
||||
@@ -94,12 +84,8 @@ class Object3d {
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
//update once per frame
|
||||
//TODO: use Raf
|
||||
// if (needsUpdate) {
|
||||
this.updateMatrix();
|
||||
this.updateWorldMatrix();
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -130,40 +116,26 @@ class Object3d {
|
||||
this.up
|
||||
);
|
||||
|
||||
// var _rotMat4 = mat4.create();
|
||||
// mat4.multiply(_rotMat4, _rotMat4, this._lookAtMat4);
|
||||
// mat4.getRotation( this._quaternion, _rotMat4);
|
||||
|
||||
// mat4.identity(this._invLookatMat4);
|
||||
mat4.invert(this.matrix, this.matrix);
|
||||
// mat4.copy(this._rotationMat4, this._invLookatMat4);
|
||||
|
||||
mat4.scale(this.matrix, this.matrix, this.scale);
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
mat4.scale(this.matrix, this.matrix, this.scale);
|
||||
mat4.multiply(this.matrix, this.matrix, this._rotationMat4);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
updateWorldMatrix() {
|
||||
if (this.parent) {
|
||||
// mat4.multiply(this.worldMatrix, this.matrix, this.parent.worldMatrix);
|
||||
mat4.multiply(this.worldMatrix, this.parent.worldMatrix, this.matrix );
|
||||
}
|
||||
else{
|
||||
this.worldMatrix = this.matrix;
|
||||
}
|
||||
|
||||
mat4.invert(this.inverseWorldMatrix, this.worldMatrix);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
import Loader from './Loader';
|
||||
import Mesh from './Mesh';
|
||||
import Material from './Material';
|
||||
import Texture from './Texture';
|
||||
import GeometryBuffer from './GeometryBuffer';
|
||||
import FrameBuffer from './FrameBuffer';
|
||||
|
||||
import particleVertexShader from './shaders/particle-vs.glsl';
|
||||
import particleFragmentShader from './shaders/particle-fs.glsl';
|
||||
|
||||
class ParticleSystem extends Mesh {
|
||||
|
||||
constructor(gl, options) {
|
||||
|
||||
super();
|
||||
|
||||
this.gl = gl;
|
||||
|
||||
options = Object.assign({}, {
|
||||
width: 10,
|
||||
height: 10,
|
||||
depth: 10,
|
||||
map: null,
|
||||
count: 100
|
||||
}, options);
|
||||
|
||||
this.count = options.count;
|
||||
this.width = options.width;
|
||||
this.heigth = options.heigth;
|
||||
this.depth = options.depth;
|
||||
|
||||
this.material = new Material(this.gl, {
|
||||
blend: true,
|
||||
map: options.map,
|
||||
vertexShader: particleVertexShader,
|
||||
fragmentShader: particleFragmentShader,
|
||||
});
|
||||
|
||||
// this.material.map = this.texture;
|
||||
|
||||
|
||||
this.indices = []
|
||||
this.vertices = []
|
||||
this.normals = []
|
||||
this.colors = []
|
||||
this.uvs = []
|
||||
this.vertexIndices = [];
|
||||
this.particleIndices = [];
|
||||
|
||||
|
||||
var index = 0;
|
||||
var particleIndex = 0;
|
||||
|
||||
for ( var i = 0, l = this.count; i<l; i++) {
|
||||
|
||||
this.vertices.push( Math.random() * this.width - (this.width/2) );
|
||||
this.vertices.push( Math.random() * this.heigth - (this.heigth/2) );
|
||||
this.vertices.push( Math.random() * this.depth - (this.depth/2) );
|
||||
|
||||
this.normals.push(0);
|
||||
this.normals.push(1);
|
||||
this.normals.push(1);
|
||||
|
||||
this.colors.push(1);
|
||||
this.colors.push(1);
|
||||
this.colors.push(1);
|
||||
|
||||
this.vertexIndices.push(index);
|
||||
|
||||
this.particleIndices.push(particleIndex);
|
||||
|
||||
index++;
|
||||
if(index > 3){
|
||||
index = 0;
|
||||
particleIndex++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (let m=0,n=0;n<this.count;m+=6,n+=4) {
|
||||
|
||||
this.indices.push(n+0);
|
||||
this.indices.push(n+2);
|
||||
this.indices.push(n+1);
|
||||
this.indices.push(n+2);
|
||||
this.indices.push(n+3);
|
||||
this.indices.push(n+1);
|
||||
|
||||
this.uvs.push(0);
|
||||
this.uvs.push(1);
|
||||
this.uvs.push(1);
|
||||
this.uvs.push(1);
|
||||
this.uvs.push(0);
|
||||
this.uvs.push(0);
|
||||
this.uvs.push(1);
|
||||
this.uvs.push(0);
|
||||
|
||||
}
|
||||
|
||||
this.geometry = new GeometryBuffer(this.gl, this.count);
|
||||
|
||||
this.geometry.addAttribute( 'index', new Uint16Array( this.indices ), 1 );
|
||||
this.geometry.addAttribute( 'position', new Float32Array( this.vertices ), 3 );
|
||||
this.geometry.addAttribute( 'color', new Float32Array( this.colors ), 3 );
|
||||
this.geometry.addAttribute( 'normal', new Float32Array( this.normals ), 3 );
|
||||
this.geometry.addAttribute( 'uv', new Float32Array( this.uvs ), 2,'ParticleSystem' );
|
||||
this.geometry.addAttribute( 'particleIndex', new Float32Array( this.particleIndices ), 1 );
|
||||
this.geometry.addAttribute( 'vertexIndex', new Float32Array( this.vertexIndices ), 1 );
|
||||
|
||||
this.geometry.length = this.vertexIndices.length;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default ParticleSystem;
|
||||
@@ -1,331 +0,0 @@
|
||||
|
||||
// adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html
|
||||
export default function parse( buffer ) {
|
||||
|
||||
var
|
||||
/* return codes for rgbe routines */
|
||||
RGBE_RETURN_SUCCESS = 0,
|
||||
RGBE_RETURN_FAILURE = - 1,
|
||||
|
||||
/* default error routine. change this to change error handling */
|
||||
rgbe_read_error = 1,
|
||||
rgbe_write_error = 2,
|
||||
rgbe_format_error = 3,
|
||||
rgbe_memory_error = 4,
|
||||
|
||||
rgbe_error = function ( rgbe_error_code, msg ) {
|
||||
switch ( rgbe_error_code ) {
|
||||
case rgbe_read_error: console.error( "THREE.RGBELoader Read Error: " + ( msg || '' ) );
|
||||
break;
|
||||
case rgbe_write_error: console.error( "THREE.RGBELoader Write Error: " + ( msg || '' ) );
|
||||
break;
|
||||
case rgbe_format_error: console.error( "THREE.RGBELoader Bad File Format: " + ( msg || '' ) );
|
||||
break;
|
||||
default:
|
||||
case rgbe_memory_error: console.error( "THREE.RGBELoader: Error: " + ( msg || '' ) );
|
||||
|
||||
}
|
||||
return RGBE_RETURN_FAILURE;
|
||||
},
|
||||
|
||||
/* offsets to red, green, and blue components in a data (float) pixel */
|
||||
RGBE_DATA_RED = 0,
|
||||
RGBE_DATA_GREEN = 1,
|
||||
RGBE_DATA_BLUE = 2,
|
||||
|
||||
/* number of floats per pixel, use 4 since stored in rgba image format */
|
||||
RGBE_DATA_SIZE = 4,
|
||||
|
||||
/* flags indicating which fields in an rgbe_header_info are valid */
|
||||
RGBE_VALID_PROGRAMTYPE = 1,
|
||||
RGBE_VALID_FORMAT = 2,
|
||||
RGBE_VALID_DIMENSIONS = 4,
|
||||
|
||||
NEWLINE = "\n",
|
||||
|
||||
fgets = function ( buffer, lineLimit, consume ) {
|
||||
|
||||
lineLimit = ! lineLimit ? 1024 : lineLimit;
|
||||
var p = buffer.pos,
|
||||
i = - 1, len = 0, s = '', chunkSize = 128,
|
||||
chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) )
|
||||
;
|
||||
while ( ( 0 > ( i = chunk.indexOf( NEWLINE ) ) ) && ( len < lineLimit ) && ( p < buffer.byteLength ) ) {
|
||||
|
||||
s += chunk; len += chunk.length;
|
||||
p += chunkSize;
|
||||
chunk += String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );
|
||||
|
||||
}
|
||||
|
||||
if ( - 1 < i ) {
|
||||
|
||||
/*for (i=l-1; i>=0; i--) {
|
||||
byteCode = m.charCodeAt(i);
|
||||
if (byteCode > 0x7f && byteCode <= 0x7ff) byteLen++;
|
||||
else if (byteCode > 0x7ff && byteCode <= 0xffff) byteLen += 2;
|
||||
if (byteCode >= 0xDC00 && byteCode <= 0xDFFF) i--; //trail surrogate
|
||||
}*/
|
||||
if ( false !== consume ) buffer.pos += len + i + 1;
|
||||
return s + chunk.slice( 0, i );
|
||||
|
||||
}
|
||||
return false;
|
||||
|
||||
},
|
||||
|
||||
/* minimal header reading. modify if you want to parse more information */
|
||||
RGBE_ReadHeader = function ( buffer ) {
|
||||
|
||||
var line, match,
|
||||
|
||||
// regexes to parse header info fields
|
||||
magic_token_re = /^#\?(\S+)$/,
|
||||
gamma_re = /^\s*GAMMA\s*=\s*(\d+(\.\d+)?)\s*$/,
|
||||
exposure_re = /^\s*EXPOSURE\s*=\s*(\d+(\.\d+)?)\s*$/,
|
||||
format_re = /^\s*FORMAT=(\S+)\s*$/,
|
||||
dimensions_re = /^\s*\-Y\s+(\d+)\s+\+X\s+(\d+)\s*$/,
|
||||
|
||||
// RGBE format header struct
|
||||
header = {
|
||||
|
||||
valid: 0, /* indicate which fields are valid */
|
||||
|
||||
string: '', /* the actual header string */
|
||||
|
||||
comments: '', /* comments found in header */
|
||||
|
||||
programtype: 'RGBE', /* listed at beginning of file to identify it after "#?". defaults to "RGBE" */
|
||||
|
||||
format: '', /* RGBE format, default 32-bit_rle_rgbe */
|
||||
|
||||
gamma: 1.0, /* image has already been gamma corrected with given gamma. defaults to 1.0 (no correction) */
|
||||
|
||||
exposure: 1.0, /* a value of 1.0 in an image corresponds to <exposure> watts/steradian/m^2. defaults to 1.0 */
|
||||
|
||||
width: 0, height: 0 /* image dimensions, width/height */
|
||||
|
||||
};
|
||||
|
||||
if ( buffer.pos >= buffer.byteLength || ! ( line = fgets( buffer ) ) ) {
|
||||
|
||||
return rgbe_error( rgbe_read_error, "no header found" );
|
||||
|
||||
}
|
||||
/* if you want to require the magic token then uncomment the next line */
|
||||
if ( ! ( match = line.match( magic_token_re ) ) ) {
|
||||
|
||||
return rgbe_error( rgbe_format_error, "bad initial token" );
|
||||
|
||||
}
|
||||
header.valid |= RGBE_VALID_PROGRAMTYPE;
|
||||
header.programtype = match[ 1 ];
|
||||
header.string += line + "\n";
|
||||
|
||||
while ( true ) {
|
||||
|
||||
line = fgets( buffer );
|
||||
if ( false === line ) break;
|
||||
header.string += line + "\n";
|
||||
|
||||
if ( '#' === line.charAt( 0 ) ) {
|
||||
|
||||
header.comments += line + "\n";
|
||||
continue; // comment line
|
||||
|
||||
}
|
||||
|
||||
if ( match = line.match( gamma_re ) ) {
|
||||
|
||||
header.gamma = parseFloat( match[ 1 ], 10 );
|
||||
|
||||
}
|
||||
if ( match = line.match( exposure_re ) ) {
|
||||
|
||||
header.exposure = parseFloat( match[ 1 ], 10 );
|
||||
|
||||
}
|
||||
if ( match = line.match( format_re ) ) {
|
||||
|
||||
header.valid |= RGBE_VALID_FORMAT;
|
||||
header.format = match[ 1 ];//'32-bit_rle_rgbe';
|
||||
|
||||
}
|
||||
if ( match = line.match( dimensions_re ) ) {
|
||||
|
||||
header.valid |= RGBE_VALID_DIMENSIONS;
|
||||
header.height = parseInt( match[ 1 ], 10 );
|
||||
header.width = parseInt( match[ 2 ], 10 );
|
||||
|
||||
}
|
||||
|
||||
if ( ( header.valid & RGBE_VALID_FORMAT ) && ( header.valid & RGBE_VALID_DIMENSIONS ) ) break;
|
||||
|
||||
}
|
||||
|
||||
if ( ! ( header.valid & RGBE_VALID_FORMAT ) ) {
|
||||
|
||||
return rgbe_error( rgbe_format_error, "missing format specifier" );
|
||||
|
||||
}
|
||||
if ( ! ( header.valid & RGBE_VALID_DIMENSIONS ) ) {
|
||||
|
||||
return rgbe_error( rgbe_format_error, "missing image size specifier" );
|
||||
|
||||
}
|
||||
|
||||
return header;
|
||||
|
||||
},
|
||||
|
||||
RGBE_ReadPixels_RLE = function ( buffer, w, h ) {
|
||||
|
||||
var data_rgba, offset, pos, count, byteValue,
|
||||
scanline_buffer, ptr, ptr_end, i, l, off, isEncodedRun,
|
||||
scanline_width = w, num_scanlines = h, rgbeStart
|
||||
;
|
||||
|
||||
if (
|
||||
// run length encoding is not allowed so read flat
|
||||
( ( scanline_width < 8 ) || ( scanline_width > 0x7fff ) ) ||
|
||||
// this file is not run length encoded
|
||||
( ( 2 !== buffer[ 0 ] ) || ( 2 !== buffer[ 1 ] ) || ( buffer[ 2 ] & 0x80 ) )
|
||||
) {
|
||||
|
||||
// return the flat buffer
|
||||
return new Uint8Array( buffer );
|
||||
|
||||
}
|
||||
|
||||
if ( scanline_width !== ( ( buffer[ 2 ] << 8 ) | buffer[ 3 ] ) ) {
|
||||
|
||||
return rgbe_error( rgbe_format_error, "wrong scanline width" );
|
||||
|
||||
}
|
||||
|
||||
data_rgba = new Uint8Array( 4 * w * h );
|
||||
|
||||
if ( ! data_rgba || ! data_rgba.length ) {
|
||||
|
||||
return rgbe_error( rgbe_memory_error, "unable to allocate buffer space" );
|
||||
|
||||
}
|
||||
|
||||
offset = 0; pos = 0; ptr_end = 4 * scanline_width;
|
||||
rgbeStart = new Uint8Array( 4 );
|
||||
scanline_buffer = new Uint8Array( ptr_end );
|
||||
|
||||
// read in each successive scanline
|
||||
while ( ( num_scanlines > 0 ) && ( pos < buffer.byteLength ) ) {
|
||||
|
||||
if ( pos + 4 > buffer.byteLength ) {
|
||||
|
||||
return rgbe_error( rgbe_read_error );
|
||||
|
||||
}
|
||||
|
||||
rgbeStart[ 0 ] = buffer[ pos ++ ];
|
||||
rgbeStart[ 1 ] = buffer[ pos ++ ];
|
||||
rgbeStart[ 2 ] = buffer[ pos ++ ];
|
||||
rgbeStart[ 3 ] = buffer[ pos ++ ];
|
||||
|
||||
if ( ( 2 != rgbeStart[ 0 ] ) || ( 2 != rgbeStart[ 1 ] ) || ( ( ( rgbeStart[ 2 ] << 8 ) | rgbeStart[ 3 ] ) != scanline_width ) ) {
|
||||
|
||||
return rgbe_error( rgbe_format_error, "bad rgbe scanline format" );
|
||||
|
||||
}
|
||||
|
||||
// read each of the four channels for the scanline into the buffer
|
||||
// first red, then green, then blue, then exponent
|
||||
ptr = 0;
|
||||
while ( ( ptr < ptr_end ) && ( pos < buffer.byteLength ) ) {
|
||||
|
||||
count = buffer[ pos ++ ];
|
||||
isEncodedRun = count > 128;
|
||||
if ( isEncodedRun ) count -= 128;
|
||||
|
||||
if ( ( 0 === count ) || ( ptr + count > ptr_end ) ) {
|
||||
|
||||
return rgbe_error( rgbe_format_error, "bad scanline data" );
|
||||
|
||||
}
|
||||
|
||||
if ( isEncodedRun ) {
|
||||
|
||||
// a (encoded) run of the same value
|
||||
byteValue = buffer[ pos ++ ];
|
||||
for ( i = 0; i < count; i ++ ) {
|
||||
|
||||
scanline_buffer[ ptr ++ ] = byteValue;
|
||||
|
||||
}
|
||||
//ptr += count;
|
||||
|
||||
} else {
|
||||
|
||||
// a literal-run
|
||||
scanline_buffer.set( buffer.subarray( pos, pos + count ), ptr );
|
||||
ptr += count; pos += count;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// now convert data from buffer into rgba
|
||||
// first red, then green, then blue, then exponent (alpha)
|
||||
l = scanline_width; //scanline_buffer.byteLength;
|
||||
for ( i = 0; i < l; i ++ ) {
|
||||
|
||||
off = 0;
|
||||
data_rgba[ offset ] = scanline_buffer[ i + off ];
|
||||
off += scanline_width; //1;
|
||||
data_rgba[ offset + 1 ] = scanline_buffer[ i + off ];
|
||||
off += scanline_width; //1;
|
||||
data_rgba[ offset + 2 ] = scanline_buffer[ i + off ];
|
||||
off += scanline_width; //1;
|
||||
data_rgba[ offset + 3 ] = scanline_buffer[ i + off ];
|
||||
offset += 4;
|
||||
|
||||
}
|
||||
|
||||
num_scanlines --;
|
||||
|
||||
}
|
||||
|
||||
return data_rgba;
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
var byteArray = new Uint8Array( buffer ),
|
||||
byteLength = byteArray.byteLength;
|
||||
byteArray.pos = 0;
|
||||
var rgbe_header_info = RGBE_ReadHeader( byteArray );
|
||||
|
||||
if ( RGBE_RETURN_FAILURE !== rgbe_header_info ) {
|
||||
|
||||
var w = rgbe_header_info.width,
|
||||
h = rgbe_header_info.height,
|
||||
image_rgba_data = RGBE_ReadPixels_RLE( byteArray.subarray( byteArray.pos ), w, h )
|
||||
;
|
||||
if ( RGBE_RETURN_FAILURE !== image_rgba_data ) {
|
||||
|
||||
return {
|
||||
width: w,
|
||||
height: h,
|
||||
data: image_rgba_data,
|
||||
header: rgbe_header_info.string,
|
||||
gamma: rgbe_header_info.gamma,
|
||||
exposure: rgbe_header_info.exposure,
|
||||
format: 'RGBA', // handled as THREE.RGBAFormat in shaders
|
||||
type: 'UnsignedByteType'
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
|
||||
};
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
import {Light} from 'beam'
|
||||
import {Container} from 'beam'
|
||||
import {vec3, mat4} from 'beam'
|
||||
|
||||
|
||||
var objects = []
|
||||
|
||||
function needsUpdateLoop() {
|
||||
requestAnimationFrame(needsUpdateLoop);
|
||||
for (let i=0; i<objects.length; i++) {
|
||||
objects[i]._needsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
needsUpdateLoop();
|
||||
|
||||
class Scene extends Container {
|
||||
|
||||
constructor() {
|
||||
|
||||
super();
|
||||
|
||||
this.lights = [];
|
||||
|
||||
this.defines = {}
|
||||
this.uniforms = {
|
||||
|
||||
lightAngleCos: [],
|
||||
lightColor: [],
|
||||
lightDecay: [],
|
||||
lightDirection: [],
|
||||
lightDistance: [],
|
||||
lightExponent: [],
|
||||
lightPosition: [],
|
||||
lightPenumbraCos: [],
|
||||
|
||||
};
|
||||
|
||||
//used to overide materials on all objects in the scene by the gven material
|
||||
this.overrideMaterial = null;
|
||||
|
||||
//gl-matrix used typed arrays which are generaly faster but slower on creation time
|
||||
//so we create them once and reuse them on each frame
|
||||
this._lightColor = vec3.create();
|
||||
this._lightPosition = vec3.create();
|
||||
this._lightDirection = vec3.create();
|
||||
|
||||
this._needsUpdate = true;
|
||||
objects.push(this)
|
||||
|
||||
}
|
||||
|
||||
add(obj) {
|
||||
if (obj instanceof Light) {
|
||||
this.lights.push( obj );
|
||||
}
|
||||
else {
|
||||
super.add(obj)
|
||||
}
|
||||
}
|
||||
|
||||
render(camera) {
|
||||
|
||||
if(this._needsUpdate){
|
||||
this.uniforms.lightAngleCos = []
|
||||
this.uniforms.lightColor = []
|
||||
this.uniforms.lightDecay = []
|
||||
this.uniforms.lightDirection = []
|
||||
this.uniforms.lightDistance = []
|
||||
this.uniforms.lightExponent = []
|
||||
this.uniforms.lightPosition = []
|
||||
this.uniforms.lightPenumbraCos = []
|
||||
|
||||
//build light uniforms
|
||||
for (let i=0; i<this.lights.length; i++) {
|
||||
|
||||
this.lights[i].update();
|
||||
|
||||
this.uniforms.lightAngleCos.push( Math.cos(this.lights[i].angle) )
|
||||
this.uniforms.lightDecay.push(this.lights[i].decay);
|
||||
this.uniforms.lightDistance.push(this.lights[i].distance)
|
||||
this.uniforms.lightExponent.push(this.lights[i].exponent)
|
||||
this.uniforms.lightPenumbraCos.push(Math.cos( this.lights[i].angle * ( 1 - this.lights[i].penumbra ) ) );
|
||||
|
||||
//compute light color from color and intensity
|
||||
vec3.copy(this._lightColor, this.lights[i].color);
|
||||
vec3.scale(this._lightColor, this._lightColor, this.lights[i].intensity)
|
||||
this.uniforms.lightColor.push(this._lightColor[0],this._lightColor[1],this._lightColor[2]);
|
||||
|
||||
//retrieve light world position
|
||||
vec3.set(this._lightPosition, this.lights[i].worldMatrix[12], this.lights[i].worldMatrix[13], this.lights[i].worldMatrix[14])
|
||||
this.uniforms.lightPosition.push(this._lightPosition[0],this._lightPosition[1],this._lightPosition[2]);
|
||||
|
||||
//retrieve light world direction
|
||||
vec3.copy( this._lightDirection, this._lightPosition )
|
||||
vec3.subtract(this._lightDirection, this._lightDirection, this.lights[i].lookAt);
|
||||
vec3.normalize(this._lightDirection, this._lightDirection);
|
||||
this.uniforms.lightDirection.push(this._lightDirection[0],this._lightDirection[1],this._lightDirection[2]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.defines.NUM_LIGHTS = this.lights.length;
|
||||
// this.uniforms = Object.assign({},uniforms, this.uniforms);
|
||||
|
||||
this._needsUpdate = false;
|
||||
|
||||
super.render(camera, this);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Scene;
|
||||
@@ -1,35 +0,0 @@
|
||||
import Loader from './Loader';
|
||||
import Mesh from './Mesh';
|
||||
import Material from './Material';
|
||||
import Texture from './Texture';
|
||||
import PlaneGeometryBuffer from './PlaneGeometryBuffer';
|
||||
|
||||
class Sprite extends Mesh {
|
||||
|
||||
constructor(gl, url) {
|
||||
|
||||
super();
|
||||
|
||||
this.gl = gl;
|
||||
|
||||
Loader.loadImage(url, (image)=>{
|
||||
|
||||
this.texture = Texture.fromImage( this.gl, image );
|
||||
|
||||
this.material = new Material(this.gl, {
|
||||
blend: true
|
||||
});
|
||||
this.material.map = this.texture;
|
||||
|
||||
this.geometry = new PlaneGeometryBuffer(this.gl, {
|
||||
width: Math.floor(image.width/10),
|
||||
height: Math.floor(image.height/10),
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Sprite;
|
||||
@@ -1,5 +1,4 @@
|
||||
import uuid from './utils/uuid';
|
||||
|
||||
import getFilter from './utils/getFilter';
|
||||
import isPowerOf2 from './utils/isPowerOf2';
|
||||
|
||||
@@ -9,12 +8,10 @@ class Texture {
|
||||
|
||||
constructor(gl, options) {
|
||||
|
||||
|
||||
if (!gl) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.options = Object.assign({}, {
|
||||
format: gl.RGBA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
@@ -132,7 +129,7 @@ class Texture {
|
||||
bindImage(img) {
|
||||
|
||||
if (!this.gl) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
this.width = img.width;
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import GeometryBuffer from './GeometryBuffer';
|
||||
|
||||
class TriangleGeometryBuffer extends GeometryBuffer {
|
||||
|
||||
constructor(gl) {
|
||||
|
||||
super(gl, 3.);
|
||||
|
||||
this.addAttribute('position', new Float32Array([
|
||||
-1.0, -1.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
1.0, -1.0, 0.0
|
||||
]), 3);
|
||||
|
||||
this.addAttribute('uv', new Float32Array([
|
||||
0.0, 0.0,
|
||||
0.5, 1.0,
|
||||
1.0, 0.0,
|
||||
]), 2, 'triangle');
|
||||
|
||||
this.addAttribute('color', new Float32Array([
|
||||
1.0, 1.0, 1.0,
|
||||
1.0, 1.0, 1.0,
|
||||
1.0, 1.0, 1.0
|
||||
]), 3);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TriangleGeometryBuffer;
|
||||
@@ -1,68 +0,0 @@
|
||||
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
const _GLMAT_EPSILON = 0.000001;
|
||||
const _GLMAT_RANDOM = Math.random;
|
||||
var _GLMAT_ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
|
||||
|
||||
/**
|
||||
* @class Common utilities
|
||||
* @name glMatrix
|
||||
*/
|
||||
const _glMatrix = {};
|
||||
|
||||
/**
|
||||
* Sets the type of array used when creating new vectors and matricies
|
||||
*
|
||||
* @param {Type} type Array type, such as Float32Array or Array
|
||||
*/
|
||||
_glMatrix.setMatrixArrayType = function(type) {
|
||||
_GLMAT_ARRAY_TYPE = type;
|
||||
}
|
||||
|
||||
|
||||
var degree = Math.PI / 180;
|
||||
|
||||
/**
|
||||
* Convert Degree To Radian
|
||||
*
|
||||
* @param {Number} Angle in Degrees
|
||||
*/
|
||||
_glMatrix.toRadian = function(a){
|
||||
return a * degree;
|
||||
}
|
||||
|
||||
export var GLMAT_ARRAY_TYPE = _GLMAT_ARRAY_TYPE;
|
||||
export var GLMAT_EPSILON = _GLMAT_EPSILON;
|
||||
export var GLMAT_RANDOM = _GLMAT_RANDOM;
|
||||
export var glMatrix = _glMatrix;
|
||||
|
||||
// if(typeof(exports) !== 'undefined') {
|
||||
// exports.GLMAT_ARRAY_TYPE = GLMAT_ARRAY_TYPE;
|
||||
// exports.GLMAT_EPSILON = GLMAT_EPSILON;
|
||||
// exports.GLMAT_RANDOM = GLMAT_RANDOM;
|
||||
// exports.glMatrix = glMatrix;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
import {GLMAT_ARRAY_TYPE} from "./common";
|
||||
|
||||
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/**
|
||||
* @class 2x2 Matrix
|
||||
* @name mat2
|
||||
*/
|
||||
var mat2 = {};
|
||||
|
||||
/**
|
||||
* Creates a new identity mat2
|
||||
*
|
||||
* @returns {mat2} a new 2x2 matrix
|
||||
*/
|
||||
mat2.create = function() {
|
||||
var out = new GLMAT_ARRAY_TYPE(4);
|
||||
out[0] = 1;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new mat2 initialized with values from an existing matrix
|
||||
*
|
||||
* @param {mat2} a matrix to clone
|
||||
* @returns {mat2} a new 2x2 matrix
|
||||
*/
|
||||
mat2.clone = function(a) {
|
||||
var out = new GLMAT_ARRAY_TYPE(4);
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy the values from one mat2 to another
|
||||
*
|
||||
* @param {mat2} out the receiving matrix
|
||||
* @param {mat2} a the source matrix
|
||||
* @returns {mat2} out
|
||||
*/
|
||||
mat2.copy = function(out, a) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a mat2 to the identity matrix
|
||||
*
|
||||
* @param {mat2} out the receiving matrix
|
||||
* @returns {mat2} out
|
||||
*/
|
||||
mat2.identity = function(out) {
|
||||
out[0] = 1;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transpose the values of a mat2
|
||||
*
|
||||
* @param {mat2} out the receiving matrix
|
||||
* @param {mat2} a the source matrix
|
||||
* @returns {mat2} out
|
||||
*/
|
||||
mat2.transpose = function(out, a) {
|
||||
// If we are transposing ourselves we can skip a few steps but have to cache some values
|
||||
if (out === a) {
|
||||
var a1 = a[1];
|
||||
out[1] = a[2];
|
||||
out[2] = a1;
|
||||
} else {
|
||||
out[0] = a[0];
|
||||
out[1] = a[2];
|
||||
out[2] = a[1];
|
||||
out[3] = a[3];
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inverts a mat2
|
||||
*
|
||||
* @param {mat2} out the receiving matrix
|
||||
* @param {mat2} a the source matrix
|
||||
* @returns {mat2} out
|
||||
*/
|
||||
mat2.invert = function(out, a) {
|
||||
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
|
||||
|
||||
// Calculate the determinant
|
||||
det = a0 * a3 - a2 * a1;
|
||||
|
||||
if (!det) {
|
||||
return null;
|
||||
}
|
||||
det = 1.0 / det;
|
||||
|
||||
out[0] = a3 * det;
|
||||
out[1] = -a1 * det;
|
||||
out[2] = -a2 * det;
|
||||
out[3] = a0 * det;
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the adjugate of a mat2
|
||||
*
|
||||
* @param {mat2} out the receiving matrix
|
||||
* @param {mat2} a the source matrix
|
||||
* @returns {mat2} out
|
||||
*/
|
||||
mat2.adjoint = function(out, a) {
|
||||
// Caching this value is nessecary if out == a
|
||||
var a0 = a[0];
|
||||
out[0] = a[3];
|
||||
out[1] = -a[1];
|
||||
out[2] = -a[2];
|
||||
out[3] = a0;
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the determinant of a mat2
|
||||
*
|
||||
* @param {mat2} a the source matrix
|
||||
* @returns {Number} determinant of a
|
||||
*/
|
||||
mat2.determinant = function (a) {
|
||||
return a[0] * a[3] - a[2] * a[1];
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiplies two mat2's
|
||||
*
|
||||
* @param {mat2} out the receiving matrix
|
||||
* @param {mat2} a the first operand
|
||||
* @param {mat2} b the second operand
|
||||
* @returns {mat2} out
|
||||
*/
|
||||
mat2.multiply = function (out, a, b) {
|
||||
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
|
||||
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
|
||||
out[0] = a0 * b0 + a1 * b2;
|
||||
out[1] = a0 * b1 + a1 * b3;
|
||||
out[2] = a2 * b0 + a3 * b2;
|
||||
out[3] = a2 * b1 + a3 * b3;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link mat2.multiply}
|
||||
* @function
|
||||
*/
|
||||
mat2.mul = mat2.multiply;
|
||||
|
||||
/**
|
||||
* Rotates a mat2 by the given angle
|
||||
*
|
||||
* @param {mat2} out the receiving matrix
|
||||
* @param {mat2} a the matrix to rotate
|
||||
* @param {Number} rad the angle to rotate the matrix by
|
||||
* @returns {mat2} out
|
||||
*/
|
||||
mat2.rotate = function (out, a, rad) {
|
||||
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
|
||||
s = Math.sin(rad),
|
||||
c = Math.cos(rad);
|
||||
out[0] = a0 * c + a1 * s;
|
||||
out[1] = a0 * -s + a1 * c;
|
||||
out[2] = a2 * c + a3 * s;
|
||||
out[3] = a2 * -s + a3 * c;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scales the mat2 by the dimensions in the given vec2
|
||||
*
|
||||
* @param {mat2} out the receiving matrix
|
||||
* @param {mat2} a the matrix to rotate
|
||||
* @param {vec2} v the vec2 to scale the matrix by
|
||||
* @returns {mat2} out
|
||||
**/
|
||||
mat2.scale = function(out, a, v) {
|
||||
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
|
||||
v0 = v[0], v1 = v[1];
|
||||
out[0] = a0 * v0;
|
||||
out[1] = a1 * v1;
|
||||
out[2] = a2 * v0;
|
||||
out[3] = a3 * v1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a string representation of a mat2
|
||||
*
|
||||
* @param {mat2} mat matrix to represent as a string
|
||||
* @returns {String} string representation of the matrix
|
||||
*/
|
||||
mat2.str = function (a) {
|
||||
return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
|
||||
};
|
||||
|
||||
export default mat2;
|
||||
@@ -1,253 +0,0 @@
|
||||
import {GLMAT_ARRAY_TYPE} from "./common";
|
||||
|
||||
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/**
|
||||
* @class 2x3 Matrix
|
||||
* @name mat2d
|
||||
*
|
||||
* @description
|
||||
* A mat2d contains six elements defined as:
|
||||
* <pre>
|
||||
* [a, b,
|
||||
* c, d,
|
||||
* tx,ty]
|
||||
* </pre>
|
||||
* This is a short form for the 3x3 matrix:
|
||||
* <pre>
|
||||
* [a, b, 0
|
||||
* c, d, 0
|
||||
* tx,ty,1]
|
||||
* </pre>
|
||||
* The last column is ignored so the array is shorter and operations are faster.
|
||||
*/
|
||||
var mat2d = {};
|
||||
|
||||
/**
|
||||
* Creates a new identity mat2d
|
||||
*
|
||||
* @returns {mat2d} a new 2x3 matrix
|
||||
*/
|
||||
mat2d.create = function() {
|
||||
var out = new GLMAT_ARRAY_TYPE(6);
|
||||
out[0] = 1;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 1;
|
||||
out[4] = 0;
|
||||
out[5] = 0;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new mat2d initialized with values from an existing matrix
|
||||
*
|
||||
* @param {mat2d} a matrix to clone
|
||||
* @returns {mat2d} a new 2x3 matrix
|
||||
*/
|
||||
mat2d.clone = function(a) {
|
||||
var out = new GLMAT_ARRAY_TYPE(6);
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
out[4] = a[4];
|
||||
out[5] = a[5];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy the values from one mat2d to another
|
||||
*
|
||||
* @param {mat2d} out the receiving matrix
|
||||
* @param {mat2d} a the source matrix
|
||||
* @returns {mat2d} out
|
||||
*/
|
||||
mat2d.copy = function(out, a) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
out[4] = a[4];
|
||||
out[5] = a[5];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a mat2d to the identity matrix
|
||||
*
|
||||
* @param {mat2d} out the receiving matrix
|
||||
* @returns {mat2d} out
|
||||
*/
|
||||
mat2d.identity = function(out) {
|
||||
out[0] = 1;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 1;
|
||||
out[4] = 0;
|
||||
out[5] = 0;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inverts a mat2d
|
||||
*
|
||||
* @param {mat2d} out the receiving matrix
|
||||
* @param {mat2d} a the source matrix
|
||||
* @returns {mat2d} out
|
||||
*/
|
||||
mat2d.invert = function(out, a) {
|
||||
var aa = a[0], ab = a[1], ac = a[2], ad = a[3],
|
||||
atx = a[4], aty = a[5];
|
||||
|
||||
var det = aa * ad - ab * ac;
|
||||
if(!det){
|
||||
return null;
|
||||
}
|
||||
det = 1.0 / det;
|
||||
|
||||
out[0] = ad * det;
|
||||
out[1] = -ab * det;
|
||||
out[2] = -ac * det;
|
||||
out[3] = aa * det;
|
||||
out[4] = (ac * aty - ad * atx) * det;
|
||||
out[5] = (ab * atx - aa * aty) * det;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the determinant of a mat2d
|
||||
*
|
||||
* @param {mat2d} a the source matrix
|
||||
* @returns {Number} determinant of a
|
||||
*/
|
||||
mat2d.determinant = function (a) {
|
||||
return a[0] * a[3] - a[1] * a[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiplies two mat2d's
|
||||
*
|
||||
* @param {mat2d} out the receiving matrix
|
||||
* @param {mat2d} a the first operand
|
||||
* @param {mat2d} b the second operand
|
||||
* @returns {mat2d} out
|
||||
*/
|
||||
mat2d.multiply = function (out, a, b) {
|
||||
var aa = a[0], ab = a[1], ac = a[2], ad = a[3],
|
||||
atx = a[4], aty = a[5],
|
||||
ba = b[0], bb = b[1], bc = b[2], bd = b[3],
|
||||
btx = b[4], bty = b[5];
|
||||
|
||||
out[0] = aa*ba + ab*bc;
|
||||
out[1] = aa*bb + ab*bd;
|
||||
out[2] = ac*ba + ad*bc;
|
||||
out[3] = ac*bb + ad*bd;
|
||||
out[4] = ba*atx + bc*aty + btx;
|
||||
out[5] = bb*atx + bd*aty + bty;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link mat2d.multiply}
|
||||
* @function
|
||||
*/
|
||||
mat2d.mul = mat2d.multiply;
|
||||
|
||||
|
||||
/**
|
||||
* Rotates a mat2d by the given angle
|
||||
*
|
||||
* @param {mat2d} out the receiving matrix
|
||||
* @param {mat2d} a the matrix to rotate
|
||||
* @param {Number} rad the angle to rotate the matrix by
|
||||
* @returns {mat2d} out
|
||||
*/
|
||||
mat2d.rotate = function (out, a, rad) {
|
||||
var aa = a[0],
|
||||
ab = a[1],
|
||||
ac = a[2],
|
||||
ad = a[3],
|
||||
atx = a[4],
|
||||
aty = a[5],
|
||||
st = Math.sin(rad),
|
||||
ct = Math.cos(rad);
|
||||
|
||||
out[0] = aa*ct + ab*st;
|
||||
out[1] = -aa*st + ab*ct;
|
||||
out[2] = ac*ct + ad*st;
|
||||
out[3] = -ac*st + ct*ad;
|
||||
out[4] = ct*atx + st*aty;
|
||||
out[5] = ct*aty - st*atx;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scales the mat2d by the dimensions in the given vec2
|
||||
*
|
||||
* @param {mat2d} out the receiving matrix
|
||||
* @param {mat2d} a the matrix to translate
|
||||
* @param {vec2} v the vec2 to scale the matrix by
|
||||
* @returns {mat2d} out
|
||||
**/
|
||||
mat2d.scale = function(out, a, v) {
|
||||
var vx = v[0], vy = v[1];
|
||||
out[0] = a[0] * vx;
|
||||
out[1] = a[1] * vy;
|
||||
out[2] = a[2] * vx;
|
||||
out[3] = a[3] * vy;
|
||||
out[4] = a[4] * vx;
|
||||
out[5] = a[5] * vy;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Translates the mat2d by the dimensions in the given vec2
|
||||
*
|
||||
* @param {mat2d} out the receiving matrix
|
||||
* @param {mat2d} a the matrix to translate
|
||||
* @param {vec2} v the vec2 to translate the matrix by
|
||||
* @returns {mat2d} out
|
||||
**/
|
||||
mat2d.translate = function(out, a, v) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
out[4] = a[4] + v[0];
|
||||
out[5] = a[5] + v[1];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a string representation of a mat2d
|
||||
*
|
||||
* @param {mat2d} a matrix to represent as a string
|
||||
* @returns {String} string representation of the matrix
|
||||
*/
|
||||
mat2d.str = function (a) {
|
||||
return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
|
||||
a[3] + ', ' + a[4] + ', ' + a[5] + ')';
|
||||
};
|
||||
|
||||
export default mat2d;
|
||||
@@ -1,478 +0,0 @@
|
||||
import {GLMAT_ARRAY_TYPE} from "./common";
|
||||
|
||||
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/**
|
||||
* @class 3x3 Matrix
|
||||
* @name mat3
|
||||
*/
|
||||
var mat3 = {};
|
||||
|
||||
/**
|
||||
* Creates a new identity mat3
|
||||
*
|
||||
* @returns {mat3} a new 3x3 matrix
|
||||
*/
|
||||
mat3.create = function() {
|
||||
var out = new GLMAT_ARRAY_TYPE(9);
|
||||
out[0] = 1;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 0;
|
||||
out[4] = 1;
|
||||
out[5] = 0;
|
||||
out[6] = 0;
|
||||
out[7] = 0;
|
||||
out[8] = 1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copies the upper-left 3x3 values into the given mat3.
|
||||
*
|
||||
* @param {mat3} out the receiving 3x3 matrix
|
||||
* @param {mat4} a the source 4x4 matrix
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.fromMat4 = function(out, a) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[4];
|
||||
out[4] = a[5];
|
||||
out[5] = a[6];
|
||||
out[6] = a[8];
|
||||
out[7] = a[9];
|
||||
out[8] = a[10];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new mat3 initialized with values from an existing matrix
|
||||
*
|
||||
* @param {mat3} a matrix to clone
|
||||
* @returns {mat3} a new 3x3 matrix
|
||||
*/
|
||||
mat3.clone = function(a) {
|
||||
var out = new GLMAT_ARRAY_TYPE(9);
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
out[4] = a[4];
|
||||
out[5] = a[5];
|
||||
out[6] = a[6];
|
||||
out[7] = a[7];
|
||||
out[8] = a[8];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy the values from one mat3 to another
|
||||
*
|
||||
* @param {mat3} out the receiving matrix
|
||||
* @param {mat3} a the source matrix
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.copy = function(out, a) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
out[4] = a[4];
|
||||
out[5] = a[5];
|
||||
out[6] = a[6];
|
||||
out[7] = a[7];
|
||||
out[8] = a[8];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a mat3 to the identity matrix
|
||||
*
|
||||
* @param {mat3} out the receiving matrix
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.identity = function(out) {
|
||||
out[0] = 1;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 0;
|
||||
out[4] = 1;
|
||||
out[5] = 0;
|
||||
out[6] = 0;
|
||||
out[7] = 0;
|
||||
out[8] = 1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transpose the values of a mat3
|
||||
*
|
||||
* @param {mat3} out the receiving matrix
|
||||
* @param {mat3} a the source matrix
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.transpose = function(out, a) {
|
||||
// If we are transposing ourselves we can skip a few steps but have to cache some values
|
||||
if (out === a) {
|
||||
var a01 = a[1], a02 = a[2], a12 = a[5];
|
||||
out[1] = a[3];
|
||||
out[2] = a[6];
|
||||
out[3] = a01;
|
||||
out[5] = a[7];
|
||||
out[6] = a02;
|
||||
out[7] = a12;
|
||||
} else {
|
||||
out[0] = a[0];
|
||||
out[1] = a[3];
|
||||
out[2] = a[6];
|
||||
out[3] = a[1];
|
||||
out[4] = a[4];
|
||||
out[5] = a[7];
|
||||
out[6] = a[2];
|
||||
out[7] = a[5];
|
||||
out[8] = a[8];
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inverts a mat3
|
||||
*
|
||||
* @param {mat3} out the receiving matrix
|
||||
* @param {mat3} a the source matrix
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.invert = function(out, a) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2],
|
||||
a10 = a[3], a11 = a[4], a12 = a[5],
|
||||
a20 = a[6], a21 = a[7], a22 = a[8],
|
||||
|
||||
b01 = a22 * a11 - a12 * a21,
|
||||
b11 = -a22 * a10 + a12 * a20,
|
||||
b21 = a21 * a10 - a11 * a20,
|
||||
|
||||
// Calculate the determinant
|
||||
det = a00 * b01 + a01 * b11 + a02 * b21;
|
||||
|
||||
if (!det) {
|
||||
return null;
|
||||
}
|
||||
det = 1.0 / det;
|
||||
|
||||
out[0] = b01 * det;
|
||||
out[1] = (-a22 * a01 + a02 * a21) * det;
|
||||
out[2] = (a12 * a01 - a02 * a11) * det;
|
||||
out[3] = b11 * det;
|
||||
out[4] = (a22 * a00 - a02 * a20) * det;
|
||||
out[5] = (-a12 * a00 + a02 * a10) * det;
|
||||
out[6] = b21 * det;
|
||||
out[7] = (-a21 * a00 + a01 * a20) * det;
|
||||
out[8] = (a11 * a00 - a01 * a10) * det;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the adjugate of a mat3
|
||||
*
|
||||
* @param {mat3} out the receiving matrix
|
||||
* @param {mat3} a the source matrix
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.adjoint = function(out, a) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2],
|
||||
a10 = a[3], a11 = a[4], a12 = a[5],
|
||||
a20 = a[6], a21 = a[7], a22 = a[8];
|
||||
|
||||
out[0] = (a11 * a22 - a12 * a21);
|
||||
out[1] = (a02 * a21 - a01 * a22);
|
||||
out[2] = (a01 * a12 - a02 * a11);
|
||||
out[3] = (a12 * a20 - a10 * a22);
|
||||
out[4] = (a00 * a22 - a02 * a20);
|
||||
out[5] = (a02 * a10 - a00 * a12);
|
||||
out[6] = (a10 * a21 - a11 * a20);
|
||||
out[7] = (a01 * a20 - a00 * a21);
|
||||
out[8] = (a00 * a11 - a01 * a10);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the determinant of a mat3
|
||||
*
|
||||
* @param {mat3} a the source matrix
|
||||
* @returns {Number} determinant of a
|
||||
*/
|
||||
mat3.determinant = function (a) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2],
|
||||
a10 = a[3], a11 = a[4], a12 = a[5],
|
||||
a20 = a[6], a21 = a[7], a22 = a[8];
|
||||
|
||||
return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiplies two mat3's
|
||||
*
|
||||
* @param {mat3} out the receiving matrix
|
||||
* @param {mat3} a the first operand
|
||||
* @param {mat3} b the second operand
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.multiply = function (out, a, b) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2],
|
||||
a10 = a[3], a11 = a[4], a12 = a[5],
|
||||
a20 = a[6], a21 = a[7], a22 = a[8],
|
||||
|
||||
b00 = b[0], b01 = b[1], b02 = b[2],
|
||||
b10 = b[3], b11 = b[4], b12 = b[5],
|
||||
b20 = b[6], b21 = b[7], b22 = b[8];
|
||||
|
||||
out[0] = b00 * a00 + b01 * a10 + b02 * a20;
|
||||
out[1] = b00 * a01 + b01 * a11 + b02 * a21;
|
||||
out[2] = b00 * a02 + b01 * a12 + b02 * a22;
|
||||
|
||||
out[3] = b10 * a00 + b11 * a10 + b12 * a20;
|
||||
out[4] = b10 * a01 + b11 * a11 + b12 * a21;
|
||||
out[5] = b10 * a02 + b11 * a12 + b12 * a22;
|
||||
|
||||
out[6] = b20 * a00 + b21 * a10 + b22 * a20;
|
||||
out[7] = b20 * a01 + b21 * a11 + b22 * a21;
|
||||
out[8] = b20 * a02 + b21 * a12 + b22 * a22;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link mat3.multiply}
|
||||
* @function
|
||||
*/
|
||||
mat3.mul = mat3.multiply;
|
||||
|
||||
/**
|
||||
* Translate a mat3 by the given vector
|
||||
*
|
||||
* @param {mat3} out the receiving matrix
|
||||
* @param {mat3} a the matrix to translate
|
||||
* @param {vec2} v vector to translate by
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.translate = function(out, a, v) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2],
|
||||
a10 = a[3], a11 = a[4], a12 = a[5],
|
||||
a20 = a[6], a21 = a[7], a22 = a[8],
|
||||
x = v[0], y = v[1];
|
||||
|
||||
out[0] = a00;
|
||||
out[1] = a01;
|
||||
out[2] = a02;
|
||||
|
||||
out[3] = a10;
|
||||
out[4] = a11;
|
||||
out[5] = a12;
|
||||
|
||||
out[6] = x * a00 + y * a10 + a20;
|
||||
out[7] = x * a01 + y * a11 + a21;
|
||||
out[8] = x * a02 + y * a12 + a22;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rotates a mat3 by the given angle
|
||||
*
|
||||
* @param {mat3} out the receiving matrix
|
||||
* @param {mat3} a the matrix to rotate
|
||||
* @param {Number} rad the angle to rotate the matrix by
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.rotate = function (out, a, rad) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2],
|
||||
a10 = a[3], a11 = a[4], a12 = a[5],
|
||||
a20 = a[6], a21 = a[7], a22 = a[8],
|
||||
|
||||
s = Math.sin(rad),
|
||||
c = Math.cos(rad);
|
||||
|
||||
out[0] = c * a00 + s * a10;
|
||||
out[1] = c * a01 + s * a11;
|
||||
out[2] = c * a02 + s * a12;
|
||||
|
||||
out[3] = c * a10 - s * a00;
|
||||
out[4] = c * a11 - s * a01;
|
||||
out[5] = c * a12 - s * a02;
|
||||
|
||||
out[6] = a20;
|
||||
out[7] = a21;
|
||||
out[8] = a22;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scales the mat3 by the dimensions in the given vec2
|
||||
*
|
||||
* @param {mat3} out the receiving matrix
|
||||
* @param {mat3} a the matrix to rotate
|
||||
* @param {vec2} v the vec2 to scale the matrix by
|
||||
* @returns {mat3} out
|
||||
**/
|
||||
mat3.scale = function(out, a, v) {
|
||||
var x = v[0], y = v[1];
|
||||
|
||||
out[0] = x * a[0];
|
||||
out[1] = x * a[1];
|
||||
out[2] = x * a[2];
|
||||
|
||||
out[3] = y * a[3];
|
||||
out[4] = y * a[4];
|
||||
out[5] = y * a[5];
|
||||
|
||||
out[6] = a[6];
|
||||
out[7] = a[7];
|
||||
out[8] = a[8];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copies the values from a mat2d into a mat3
|
||||
*
|
||||
* @param {mat3} out the receiving matrix
|
||||
* @param {mat2d} a the matrix to copy
|
||||
* @returns {mat3} out
|
||||
**/
|
||||
mat3.fromMat2d = function(out, a) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = 0;
|
||||
|
||||
out[3] = a[2];
|
||||
out[4] = a[3];
|
||||
out[5] = 0;
|
||||
|
||||
out[6] = a[4];
|
||||
out[7] = a[5];
|
||||
out[8] = 1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates a 3x3 matrix from the given quaternion
|
||||
*
|
||||
* @param {mat3} out mat3 receiving operation result
|
||||
* @param {quat} q Quaternion to create matrix from
|
||||
*
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.fromQuat = function (out, q) {
|
||||
var x = q[0], y = q[1], z = q[2], w = q[3],
|
||||
x2 = x + x,
|
||||
y2 = y + y,
|
||||
z2 = z + z,
|
||||
|
||||
xx = x * x2,
|
||||
xy = x * y2,
|
||||
xz = x * z2,
|
||||
yy = y * y2,
|
||||
yz = y * z2,
|
||||
zz = z * z2,
|
||||
wx = w * x2,
|
||||
wy = w * y2,
|
||||
wz = w * z2;
|
||||
|
||||
out[0] = 1 - (yy + zz);
|
||||
out[3] = xy + wz;
|
||||
out[6] = xz - wy;
|
||||
|
||||
out[1] = xy - wz;
|
||||
out[4] = 1 - (xx + zz);
|
||||
out[7] = yz + wx;
|
||||
|
||||
out[2] = xz + wy;
|
||||
out[5] = yz - wx;
|
||||
out[8] = 1 - (xx + yy);
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
|
||||
*
|
||||
* @param {mat3} out mat3 receiving operation result
|
||||
* @param {mat4} a Mat4 to derive the normal matrix from
|
||||
*
|
||||
* @returns {mat3} out
|
||||
*/
|
||||
mat3.normalFromMat4 = function (out, a) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
|
||||
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
|
||||
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
|
||||
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
|
||||
|
||||
b00 = a00 * a11 - a01 * a10,
|
||||
b01 = a00 * a12 - a02 * a10,
|
||||
b02 = a00 * a13 - a03 * a10,
|
||||
b03 = a01 * a12 - a02 * a11,
|
||||
b04 = a01 * a13 - a03 * a11,
|
||||
b05 = a02 * a13 - a03 * a12,
|
||||
b06 = a20 * a31 - a21 * a30,
|
||||
b07 = a20 * a32 - a22 * a30,
|
||||
b08 = a20 * a33 - a23 * a30,
|
||||
b09 = a21 * a32 - a22 * a31,
|
||||
b10 = a21 * a33 - a23 * a31,
|
||||
b11 = a22 * a33 - a23 * a32,
|
||||
|
||||
// Calculate the determinant
|
||||
det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
||||
|
||||
if (!det) {
|
||||
return null;
|
||||
}
|
||||
det = 1.0 / det;
|
||||
|
||||
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
|
||||
out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
|
||||
out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
|
||||
|
||||
out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
|
||||
out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
|
||||
out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
|
||||
|
||||
out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
|
||||
out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
|
||||
out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a string representation of a mat3
|
||||
*
|
||||
* @param {mat3} mat matrix to represent as a string
|
||||
* @returns {String} string representation of the matrix
|
||||
*/
|
||||
mat3.str = function (a) {
|
||||
return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
|
||||
a[3] + ', ' + a[4] + ', ' + a[5] + ', ' +
|
||||
a[6] + ', ' + a[7] + ', ' + a[8] + ')';
|
||||
};
|
||||
|
||||
export default mat3;
|
||||
@@ -1,908 +0,0 @@
|
||||
import {GLMAT_ARRAY_TYPE} from "./common";
|
||||
import {GLMAT_EPSILON} from "./common";
|
||||
|
||||
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/**
|
||||
* @class 4x4 Matrix
|
||||
* @name mat4
|
||||
*/
|
||||
var mat4 = {};
|
||||
|
||||
/**
|
||||
* Creates a new identity mat4
|
||||
*
|
||||
* @returns {mat4} a new 4x4 matrix
|
||||
*/
|
||||
mat4.create = function() {
|
||||
var out = new GLMAT_ARRAY_TYPE(16);
|
||||
out[0] = 1;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 0;
|
||||
out[4] = 0;
|
||||
out[5] = 1;
|
||||
out[6] = 0;
|
||||
out[7] = 0;
|
||||
out[8] = 0;
|
||||
out[9] = 0;
|
||||
out[10] = 1;
|
||||
out[11] = 0;
|
||||
out[12] = 0;
|
||||
out[13] = 0;
|
||||
out[14] = 0;
|
||||
out[15] = 1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new mat4 initialized with values from an existing matrix
|
||||
*
|
||||
* @param {mat4} a matrix to clone
|
||||
* @returns {mat4} a new 4x4 matrix
|
||||
*/
|
||||
mat4.clone = function(a) {
|
||||
var out = new GLMAT_ARRAY_TYPE(16);
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
out[4] = a[4];
|
||||
out[5] = a[5];
|
||||
out[6] = a[6];
|
||||
out[7] = a[7];
|
||||
out[8] = a[8];
|
||||
out[9] = a[9];
|
||||
out[10] = a[10];
|
||||
out[11] = a[11];
|
||||
out[12] = a[12];
|
||||
out[13] = a[13];
|
||||
out[14] = a[14];
|
||||
out[15] = a[15];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy the values from one mat4 to another
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the source matrix
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.copy = function(out, a) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
out[4] = a[4];
|
||||
out[5] = a[5];
|
||||
out[6] = a[6];
|
||||
out[7] = a[7];
|
||||
out[8] = a[8];
|
||||
out[9] = a[9];
|
||||
out[10] = a[10];
|
||||
out[11] = a[11];
|
||||
out[12] = a[12];
|
||||
out[13] = a[13];
|
||||
out[14] = a[14];
|
||||
out[15] = a[15];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a mat4 to the identity matrix
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.identity = function(out) {
|
||||
out[0] = 1;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 0;
|
||||
out[4] = 0;
|
||||
out[5] = 1;
|
||||
out[6] = 0;
|
||||
out[7] = 0;
|
||||
out[8] = 0;
|
||||
out[9] = 0;
|
||||
out[10] = 1;
|
||||
out[11] = 0;
|
||||
out[12] = 0;
|
||||
out[13] = 0;
|
||||
out[14] = 0;
|
||||
out[15] = 1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transpose the values of a mat4
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the source matrix
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.transpose = function(out, a) {
|
||||
// If we are transposing ourselves we can skip a few steps but have to cache some values
|
||||
if (out === a) {
|
||||
var a01 = a[1], a02 = a[2], a03 = a[3],
|
||||
a12 = a[6], a13 = a[7],
|
||||
a23 = a[11];
|
||||
|
||||
out[1] = a[4];
|
||||
out[2] = a[8];
|
||||
out[3] = a[12];
|
||||
out[4] = a01;
|
||||
out[6] = a[9];
|
||||
out[7] = a[13];
|
||||
out[8] = a02;
|
||||
out[9] = a12;
|
||||
out[11] = a[14];
|
||||
out[12] = a03;
|
||||
out[13] = a13;
|
||||
out[14] = a23;
|
||||
} else {
|
||||
out[0] = a[0];
|
||||
out[1] = a[4];
|
||||
out[2] = a[8];
|
||||
out[3] = a[12];
|
||||
out[4] = a[1];
|
||||
out[5] = a[5];
|
||||
out[6] = a[9];
|
||||
out[7] = a[13];
|
||||
out[8] = a[2];
|
||||
out[9] = a[6];
|
||||
out[10] = a[10];
|
||||
out[11] = a[14];
|
||||
out[12] = a[3];
|
||||
out[13] = a[7];
|
||||
out[14] = a[11];
|
||||
out[15] = a[15];
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inverts a mat4
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the source matrix
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.invert = function(out, a) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
|
||||
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
|
||||
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
|
||||
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
|
||||
|
||||
b00 = a00 * a11 - a01 * a10,
|
||||
b01 = a00 * a12 - a02 * a10,
|
||||
b02 = a00 * a13 - a03 * a10,
|
||||
b03 = a01 * a12 - a02 * a11,
|
||||
b04 = a01 * a13 - a03 * a11,
|
||||
b05 = a02 * a13 - a03 * a12,
|
||||
b06 = a20 * a31 - a21 * a30,
|
||||
b07 = a20 * a32 - a22 * a30,
|
||||
b08 = a20 * a33 - a23 * a30,
|
||||
b09 = a21 * a32 - a22 * a31,
|
||||
b10 = a21 * a33 - a23 * a31,
|
||||
b11 = a22 * a33 - a23 * a32,
|
||||
|
||||
// Calculate the determinant
|
||||
det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
||||
|
||||
if (!det) {
|
||||
return null;
|
||||
}
|
||||
det = 1.0 / det;
|
||||
|
||||
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
|
||||
out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
|
||||
out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
|
||||
out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
|
||||
out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
|
||||
out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
|
||||
out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
|
||||
out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
|
||||
out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
|
||||
out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
|
||||
out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
|
||||
out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
|
||||
out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
|
||||
out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
|
||||
out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
|
||||
out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the adjugate of a mat4
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the source matrix
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.adjoint = function(out, a) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
|
||||
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
|
||||
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
|
||||
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
|
||||
|
||||
out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
|
||||
out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
|
||||
out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
|
||||
out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
|
||||
out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
|
||||
out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
|
||||
out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
|
||||
out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
|
||||
out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
|
||||
out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
|
||||
out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
|
||||
out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
|
||||
out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
|
||||
out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
|
||||
out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
|
||||
out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the determinant of a mat4
|
||||
*
|
||||
* @param {mat4} a the source matrix
|
||||
* @returns {Number} determinant of a
|
||||
*/
|
||||
mat4.determinant = function (a) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
|
||||
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
|
||||
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
|
||||
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
|
||||
|
||||
b00 = a00 * a11 - a01 * a10,
|
||||
b01 = a00 * a12 - a02 * a10,
|
||||
b02 = a00 * a13 - a03 * a10,
|
||||
b03 = a01 * a12 - a02 * a11,
|
||||
b04 = a01 * a13 - a03 * a11,
|
||||
b05 = a02 * a13 - a03 * a12,
|
||||
b06 = a20 * a31 - a21 * a30,
|
||||
b07 = a20 * a32 - a22 * a30,
|
||||
b08 = a20 * a33 - a23 * a30,
|
||||
b09 = a21 * a32 - a22 * a31,
|
||||
b10 = a21 * a33 - a23 * a31,
|
||||
b11 = a22 * a33 - a23 * a32;
|
||||
|
||||
// Calculate the determinant
|
||||
return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiplies two mat4's
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the first operand
|
||||
* @param {mat4} b the second operand
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.multiply = function (out, a, b) {
|
||||
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
|
||||
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
|
||||
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
|
||||
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
|
||||
|
||||
// Cache only the current line of the second matrix
|
||||
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
|
||||
out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
|
||||
out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
|
||||
out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
|
||||
out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
|
||||
|
||||
b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
|
||||
out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
|
||||
out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
|
||||
out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
|
||||
out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
|
||||
|
||||
b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
|
||||
out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
|
||||
out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
|
||||
out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
|
||||
out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
|
||||
|
||||
b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
|
||||
out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
|
||||
out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
|
||||
out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
|
||||
out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link mat4.multiply}
|
||||
* @function
|
||||
*/
|
||||
mat4.mul = mat4.multiply;
|
||||
|
||||
/**
|
||||
* Translate a mat4 by the given vector
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the matrix to translate
|
||||
* @param {vec3} v vector to translate by
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.translate = function (out, a, v) {
|
||||
var x = v[0], y = v[1], z = v[2],
|
||||
a00, a01, a02, a03,
|
||||
a10, a11, a12, a13,
|
||||
a20, a21, a22, a23;
|
||||
|
||||
if (a === out) {
|
||||
out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
|
||||
out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
|
||||
out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
|
||||
out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
|
||||
} else {
|
||||
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
|
||||
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
|
||||
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
|
||||
|
||||
out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
|
||||
out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
|
||||
out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
|
||||
|
||||
out[12] = a00 * x + a10 * y + a20 * z + a[12];
|
||||
out[13] = a01 * x + a11 * y + a21 * z + a[13];
|
||||
out[14] = a02 * x + a12 * y + a22 * z + a[14];
|
||||
out[15] = a03 * x + a13 * y + a23 * z + a[15];
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scales the mat4 by the dimensions in the given vec3
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the matrix to scale
|
||||
* @param {vec3} v the vec3 to scale the matrix by
|
||||
* @returns {mat4} out
|
||||
**/
|
||||
mat4.scale = function(out, a, v) {
|
||||
var x = v[0], y = v[1], z = v[2];
|
||||
|
||||
out[0] = a[0] * x;
|
||||
out[1] = a[1] * x;
|
||||
out[2] = a[2] * x;
|
||||
out[3] = a[3] * x;
|
||||
out[4] = a[4] * y;
|
||||
out[5] = a[5] * y;
|
||||
out[6] = a[6] * y;
|
||||
out[7] = a[7] * y;
|
||||
out[8] = a[8] * z;
|
||||
out[9] = a[9] * z;
|
||||
out[10] = a[10] * z;
|
||||
out[11] = a[11] * z;
|
||||
out[12] = a[12];
|
||||
out[13] = a[13];
|
||||
out[14] = a[14];
|
||||
out[15] = a[15];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rotates a mat4 by the given angle
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the matrix to rotate
|
||||
* @param {Number} rad the angle to rotate the matrix by
|
||||
* @param {vec3} axis the axis to rotate around
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.rotate = function (out, a, rad, axis) {
|
||||
var x = axis[0], y = axis[1], z = axis[2],
|
||||
len = Math.sqrt(x * x + y * y + z * z),
|
||||
s, c, t,
|
||||
a00, a01, a02, a03,
|
||||
a10, a11, a12, a13,
|
||||
a20, a21, a22, a23,
|
||||
b00, b01, b02,
|
||||
b10, b11, b12,
|
||||
b20, b21, b22;
|
||||
|
||||
if (Math.abs(len) < GLMAT_EPSILON) { return null; }
|
||||
|
||||
len = 1 / len;
|
||||
x *= len;
|
||||
y *= len;
|
||||
z *= len;
|
||||
|
||||
s = Math.sin(rad);
|
||||
c = Math.cos(rad);
|
||||
t = 1 - c;
|
||||
|
||||
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
|
||||
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
|
||||
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
|
||||
|
||||
// Construct the elements of the rotation matrix
|
||||
b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
|
||||
b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
|
||||
b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
|
||||
|
||||
// Perform rotation-specific matrix multiplication
|
||||
out[0] = a00 * b00 + a10 * b01 + a20 * b02;
|
||||
out[1] = a01 * b00 + a11 * b01 + a21 * b02;
|
||||
out[2] = a02 * b00 + a12 * b01 + a22 * b02;
|
||||
out[3] = a03 * b00 + a13 * b01 + a23 * b02;
|
||||
out[4] = a00 * b10 + a10 * b11 + a20 * b12;
|
||||
out[5] = a01 * b10 + a11 * b11 + a21 * b12;
|
||||
out[6] = a02 * b10 + a12 * b11 + a22 * b12;
|
||||
out[7] = a03 * b10 + a13 * b11 + a23 * b12;
|
||||
out[8] = a00 * b20 + a10 * b21 + a20 * b22;
|
||||
out[9] = a01 * b20 + a11 * b21 + a21 * b22;
|
||||
out[10] = a02 * b20 + a12 * b21 + a22 * b22;
|
||||
out[11] = a03 * b20 + a13 * b21 + a23 * b22;
|
||||
|
||||
if (a !== out) { // If the source and destination differ, copy the unchanged last row
|
||||
out[12] = a[12];
|
||||
out[13] = a[13];
|
||||
out[14] = a[14];
|
||||
out[15] = a[15];
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rotates a matrix by the given angle around the X axis
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the matrix to rotate
|
||||
* @param {Number} rad the angle to rotate the matrix by
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.rotateX = function (out, a, rad) {
|
||||
var s = Math.sin(rad),
|
||||
c = Math.cos(rad),
|
||||
a10 = a[4],
|
||||
a11 = a[5],
|
||||
a12 = a[6],
|
||||
a13 = a[7],
|
||||
a20 = a[8],
|
||||
a21 = a[9],
|
||||
a22 = a[10],
|
||||
a23 = a[11];
|
||||
|
||||
if (a !== out) { // If the source and destination differ, copy the unchanged rows
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
out[12] = a[12];
|
||||
out[13] = a[13];
|
||||
out[14] = a[14];
|
||||
out[15] = a[15];
|
||||
}
|
||||
|
||||
// Perform axis-specific matrix multiplication
|
||||
out[4] = a10 * c + a20 * s;
|
||||
out[5] = a11 * c + a21 * s;
|
||||
out[6] = a12 * c + a22 * s;
|
||||
out[7] = a13 * c + a23 * s;
|
||||
out[8] = a20 * c - a10 * s;
|
||||
out[9] = a21 * c - a11 * s;
|
||||
out[10] = a22 * c - a12 * s;
|
||||
out[11] = a23 * c - a13 * s;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rotates a matrix by the given angle around the Y axis
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the matrix to rotate
|
||||
* @param {Number} rad the angle to rotate the matrix by
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.rotateY = function (out, a, rad) {
|
||||
var s = Math.sin(rad),
|
||||
c = Math.cos(rad),
|
||||
a00 = a[0],
|
||||
a01 = a[1],
|
||||
a02 = a[2],
|
||||
a03 = a[3],
|
||||
a20 = a[8],
|
||||
a21 = a[9],
|
||||
a22 = a[10],
|
||||
a23 = a[11];
|
||||
|
||||
if (a !== out) { // If the source and destination differ, copy the unchanged rows
|
||||
out[4] = a[4];
|
||||
out[5] = a[5];
|
||||
out[6] = a[6];
|
||||
out[7] = a[7];
|
||||
out[12] = a[12];
|
||||
out[13] = a[13];
|
||||
out[14] = a[14];
|
||||
out[15] = a[15];
|
||||
}
|
||||
|
||||
// Perform axis-specific matrix multiplication
|
||||
out[0] = a00 * c - a20 * s;
|
||||
out[1] = a01 * c - a21 * s;
|
||||
out[2] = a02 * c - a22 * s;
|
||||
out[3] = a03 * c - a23 * s;
|
||||
out[8] = a00 * s + a20 * c;
|
||||
out[9] = a01 * s + a21 * c;
|
||||
out[10] = a02 * s + a22 * c;
|
||||
out[11] = a03 * s + a23 * c;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rotates a matrix by the given angle around the Z axis
|
||||
*
|
||||
* @param {mat4} out the receiving matrix
|
||||
* @param {mat4} a the matrix to rotate
|
||||
* @param {Number} rad the angle to rotate the matrix by
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.rotateZ = function (out, a, rad) {
|
||||
var s = Math.sin(rad),
|
||||
c = Math.cos(rad),
|
||||
a00 = a[0],
|
||||
a01 = a[1],
|
||||
a02 = a[2],
|
||||
a03 = a[3],
|
||||
a10 = a[4],
|
||||
a11 = a[5],
|
||||
a12 = a[6],
|
||||
a13 = a[7];
|
||||
|
||||
if (a !== out) { // If the source and destination differ, copy the unchanged last row
|
||||
out[8] = a[8];
|
||||
out[9] = a[9];
|
||||
out[10] = a[10];
|
||||
out[11] = a[11];
|
||||
out[12] = a[12];
|
||||
out[13] = a[13];
|
||||
out[14] = a[14];
|
||||
out[15] = a[15];
|
||||
}
|
||||
|
||||
// Perform axis-specific matrix multiplication
|
||||
out[0] = a00 * c + a10 * s;
|
||||
out[1] = a01 * c + a11 * s;
|
||||
out[2] = a02 * c + a12 * s;
|
||||
out[3] = a03 * c + a13 * s;
|
||||
out[4] = a10 * c - a00 * s;
|
||||
out[5] = a11 * c - a01 * s;
|
||||
out[6] = a12 * c - a02 * s;
|
||||
out[7] = a13 * c - a03 * s;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a matrix from a quaternion rotation and vector translation
|
||||
* This is equivalent to (but much faster than):
|
||||
*
|
||||
* mat4.identity(dest);
|
||||
* mat4.translate(dest, vec);
|
||||
* var quatMat = mat4.create();
|
||||
* quat4.toMat4(quat, quatMat);
|
||||
* mat4.multiply(dest, quatMat);
|
||||
*
|
||||
* @param {mat4} out mat4 receiving operation result
|
||||
* @param {quat4} q Rotation quaternion
|
||||
* @param {vec3} v Translation vector
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.fromRotationTranslation = function (out, q, v) {
|
||||
// Quaternion math
|
||||
var x = q[0], y = q[1], z = q[2], w = q[3],
|
||||
x2 = x + x,
|
||||
y2 = y + y,
|
||||
z2 = z + z,
|
||||
|
||||
xx = x * x2,
|
||||
xy = x * y2,
|
||||
xz = x * z2,
|
||||
yy = y * y2,
|
||||
yz = y * z2,
|
||||
zz = z * z2,
|
||||
wx = w * x2,
|
||||
wy = w * y2,
|
||||
wz = w * z2;
|
||||
|
||||
out[0] = 1 - (yy + zz);
|
||||
out[1] = xy + wz;
|
||||
out[2] = xz - wy;
|
||||
out[3] = 0;
|
||||
out[4] = xy - wz;
|
||||
out[5] = 1 - (xx + zz);
|
||||
out[6] = yz + wx;
|
||||
out[7] = 0;
|
||||
out[8] = xz + wy;
|
||||
out[9] = yz - wx;
|
||||
out[10] = 1 - (xx + yy);
|
||||
out[11] = 0;
|
||||
out[12] = v[0];
|
||||
out[13] = v[1];
|
||||
out[14] = v[2];
|
||||
out[15] = 1;
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates a 4x4 matrix from the given quaternion
|
||||
*
|
||||
* @param {mat4} out mat4 receiving operation result
|
||||
* @param {quat} q Quaternion to create matrix from
|
||||
*
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.fromQuat = function (out, q) {
|
||||
var x = q[0], y = q[1], z = q[2], w = q[3],
|
||||
x2 = x + x,
|
||||
y2 = y + y,
|
||||
z2 = z + z,
|
||||
|
||||
xx = x * x2,
|
||||
xy = x * y2,
|
||||
xz = x * z2,
|
||||
yy = y * y2,
|
||||
yz = y * z2,
|
||||
zz = z * z2,
|
||||
wx = w * x2,
|
||||
wy = w * y2,
|
||||
wz = w * z2;
|
||||
|
||||
out[0] = 1 - (yy + zz);
|
||||
out[1] = xy + wz;
|
||||
out[2] = xz - wy;
|
||||
out[3] = 0;
|
||||
|
||||
out[4] = xy - wz;
|
||||
out[5] = 1 - (xx + zz);
|
||||
out[6] = yz + wx;
|
||||
out[7] = 0;
|
||||
|
||||
out[8] = xz + wy;
|
||||
out[9] = yz - wx;
|
||||
out[10] = 1 - (xx + yy);
|
||||
out[11] = 0;
|
||||
|
||||
out[12] = 0;
|
||||
out[13] = 0;
|
||||
out[14] = 0;
|
||||
out[15] = 1;
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a frustum matrix with the given bounds
|
||||
*
|
||||
* @param {mat4} out mat4 frustum matrix will be written into
|
||||
* @param {Number} left Left bound of the frustum
|
||||
* @param {Number} right Right bound of the frustum
|
||||
* @param {Number} bottom Bottom bound of the frustum
|
||||
* @param {Number} top Top bound of the frustum
|
||||
* @param {Number} near Near bound of the frustum
|
||||
* @param {Number} far Far bound of the frustum
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.frustum = function (out, left, right, bottom, top, near, far) {
|
||||
var rl = 1 / (right - left),
|
||||
tb = 1 / (top - bottom),
|
||||
nf = 1 / (near - far);
|
||||
out[0] = (near * 2) * rl;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 0;
|
||||
out[4] = 0;
|
||||
out[5] = (near * 2) * tb;
|
||||
out[6] = 0;
|
||||
out[7] = 0;
|
||||
out[8] = (right + left) * rl;
|
||||
out[9] = (top + bottom) * tb;
|
||||
out[10] = (far + near) * nf;
|
||||
out[11] = -1;
|
||||
out[12] = 0;
|
||||
out[13] = 0;
|
||||
out[14] = (far * near * 2) * nf;
|
||||
out[15] = 0;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a perspective projection matrix with the given bounds
|
||||
*
|
||||
* @param {mat4} out mat4 frustum matrix will be written into
|
||||
* @param {number} fovy Vertical field of view in radians
|
||||
* @param {number} aspect Aspect ratio. typically viewport width/height
|
||||
* @param {number} near Near bound of the frustum
|
||||
* @param {number} far Far bound of the frustum
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.perspective = function (out, fovy, aspect, near, far) {
|
||||
var f = 1.0 / Math.tan(fovy / 2),
|
||||
nf = 1 / (near - far);
|
||||
out[0] = f / aspect;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 0;
|
||||
out[4] = 0;
|
||||
out[5] = f;
|
||||
out[6] = 0;
|
||||
out[7] = 0;
|
||||
out[8] = 0;
|
||||
out[9] = 0;
|
||||
out[10] = (far + near) * nf;
|
||||
out[11] = -1;
|
||||
out[12] = 0;
|
||||
out[13] = 0;
|
||||
out[14] = (2 * far * near) * nf;
|
||||
out[15] = 0;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a orthogonal projection matrix with the given bounds
|
||||
*
|
||||
* @param {mat4} out mat4 frustum matrix will be written into
|
||||
* @param {number} left Left bound of the frustum
|
||||
* @param {number} right Right bound of the frustum
|
||||
* @param {number} bottom Bottom bound of the frustum
|
||||
* @param {number} top Top bound of the frustum
|
||||
* @param {number} near Near bound of the frustum
|
||||
* @param {number} far Far bound of the frustum
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.ortho = function (out, left, right, bottom, top, near, far) {
|
||||
var lr = 1 / (left - right),
|
||||
bt = 1 / (bottom - top),
|
||||
nf = 1 / (near - far);
|
||||
out[0] = -2 * lr;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 0;
|
||||
out[4] = 0;
|
||||
out[5] = -2 * bt;
|
||||
out[6] = 0;
|
||||
out[7] = 0;
|
||||
out[8] = 0;
|
||||
out[9] = 0;
|
||||
out[10] = 2 * nf;
|
||||
out[11] = 0;
|
||||
out[12] = (left + right) * lr;
|
||||
out[13] = (top + bottom) * bt;
|
||||
out[14] = (far + near) * nf;
|
||||
out[15] = 1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a look-at matrix with the given eye position, focal point, and up axis
|
||||
*
|
||||
* @param {mat4} out mat4 frustum matrix will be written into
|
||||
* @param {vec3} eye Position of the viewer
|
||||
* @param {vec3} center Point the viewer is looking at
|
||||
* @param {vec3} up vec3 pointing up
|
||||
* @returns {mat4} out
|
||||
*/
|
||||
mat4.lookAt = function (out, eye, center, up) {
|
||||
var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
|
||||
eyex = eye[0],
|
||||
eyey = eye[1],
|
||||
eyez = eye[2],
|
||||
upx = up[0],
|
||||
upy = up[1],
|
||||
upz = up[2],
|
||||
centerx = center[0],
|
||||
centery = center[1],
|
||||
centerz = center[2];
|
||||
|
||||
if (Math.abs(eyex - centerx) < GLMAT_EPSILON &&
|
||||
Math.abs(eyey - centery) < GLMAT_EPSILON &&
|
||||
Math.abs(eyez - centerz) < GLMAT_EPSILON) {
|
||||
return mat4.identity(out);
|
||||
}
|
||||
|
||||
z0 = eyex - centerx;
|
||||
z1 = eyey - centery;
|
||||
z2 = eyez - centerz;
|
||||
|
||||
len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
|
||||
z0 *= len;
|
||||
z1 *= len;
|
||||
z2 *= len;
|
||||
|
||||
x0 = upy * z2 - upz * z1;
|
||||
x1 = upz * z0 - upx * z2;
|
||||
x2 = upx * z1 - upy * z0;
|
||||
len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
|
||||
if (!len) {
|
||||
x0 = 0;
|
||||
x1 = 0;
|
||||
x2 = 0;
|
||||
} else {
|
||||
len = 1 / len;
|
||||
x0 *= len;
|
||||
x1 *= len;
|
||||
x2 *= len;
|
||||
}
|
||||
|
||||
y0 = z1 * x2 - z2 * x1;
|
||||
y1 = z2 * x0 - z0 * x2;
|
||||
y2 = z0 * x1 - z1 * x0;
|
||||
|
||||
len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
|
||||
if (!len) {
|
||||
y0 = 0;
|
||||
y1 = 0;
|
||||
y2 = 0;
|
||||
} else {
|
||||
len = 1 / len;
|
||||
y0 *= len;
|
||||
y1 *= len;
|
||||
y2 *= len;
|
||||
}
|
||||
|
||||
out[0] = x0;
|
||||
out[1] = y0;
|
||||
out[2] = z0;
|
||||
out[3] = 0;
|
||||
out[4] = x1;
|
||||
out[5] = y1;
|
||||
out[6] = z1;
|
||||
out[7] = 0;
|
||||
out[8] = x2;
|
||||
out[9] = y2;
|
||||
out[10] = z2;
|
||||
out[11] = 0;
|
||||
out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
|
||||
out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
|
||||
out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
|
||||
out[15] = 1;
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a string representation of a mat4
|
||||
*
|
||||
* @param {mat4} mat matrix to represent as a string
|
||||
* @returns {String} string representation of the matrix
|
||||
*/
|
||||
mat4.str = function (a) {
|
||||
return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
|
||||
a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
|
||||
a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' +
|
||||
a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
|
||||
};
|
||||
|
||||
export default mat4;
|
||||
@@ -1,531 +0,0 @@
|
||||
import {GLMAT_ARRAY_TYPE} from "./common";
|
||||
import vec3 from "./vec3";
|
||||
import vec4 from "./vec4";
|
||||
import mat3 from "./mat3";
|
||||
|
||||
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/**
|
||||
* @class Quaternion
|
||||
* @name quat
|
||||
*/
|
||||
var quat = {};
|
||||
|
||||
/**
|
||||
* Creates a new identity quat
|
||||
*
|
||||
* @returns {quat} a new quaternion
|
||||
*/
|
||||
quat.create = function() {
|
||||
var out = new GLMAT_ARRAY_TYPE(4);
|
||||
out[0] = 0;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a quaternion to represent the shortest rotation from one
|
||||
* vector to another.
|
||||
*
|
||||
* Both vectors are assumed to be unit length.
|
||||
*
|
||||
* @param {quat} out the receiving quaternion.
|
||||
* @param {vec3} a the initial vector
|
||||
* @param {vec3} b the destination vector
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.rotationTo = (function() {
|
||||
var tmpvec3 = vec3.create();
|
||||
var xUnitVec3 = vec3.fromValues(1,0,0);
|
||||
var yUnitVec3 = vec3.fromValues(0,1,0);
|
||||
|
||||
return function(out, a, b) {
|
||||
var dot = vec3.dot(a, b);
|
||||
if (dot < -0.999999) {
|
||||
vec3.cross(tmpvec3, xUnitVec3, a);
|
||||
if (vec3.length(tmpvec3) < 0.000001)
|
||||
vec3.cross(tmpvec3, yUnitVec3, a);
|
||||
vec3.normalize(tmpvec3, tmpvec3);
|
||||
quat.setAxisAngle(out, tmpvec3, Math.PI);
|
||||
return out;
|
||||
} else if (dot > 0.999999) {
|
||||
out[0] = 0;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 1;
|
||||
return out;
|
||||
} else {
|
||||
vec3.cross(tmpvec3, a, b);
|
||||
out[0] = tmpvec3[0];
|
||||
out[1] = tmpvec3[1];
|
||||
out[2] = tmpvec3[2];
|
||||
out[3] = 1 + dot;
|
||||
return quat.normalize(out, out);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Sets the specified quaternion with values corresponding to the given
|
||||
* axes. Each axis is a vec3 and is expected to be unit length and
|
||||
* perpendicular to all other specified axes.
|
||||
*
|
||||
* @param {vec3} view the vector representing the viewing direction
|
||||
* @param {vec3} right the vector representing the local "right" direction
|
||||
* @param {vec3} up the vector representing the local "up" direction
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.setAxes = (function() {
|
||||
var matr = mat3.create();
|
||||
|
||||
return function(out, view, right, up) {
|
||||
matr[0] = right[0];
|
||||
matr[3] = right[1];
|
||||
matr[6] = right[2];
|
||||
|
||||
matr[1] = up[0];
|
||||
matr[4] = up[1];
|
||||
matr[7] = up[2];
|
||||
|
||||
matr[2] = view[0];
|
||||
matr[5] = view[1];
|
||||
matr[8] = view[2];
|
||||
|
||||
return quat.normalize(out, quat.fromMat3(out, matr));
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Creates a new quat initialized with values from an existing quaternion
|
||||
*
|
||||
* @param {quat} a quaternion to clone
|
||||
* @returns {quat} a new quaternion
|
||||
* @function
|
||||
*/
|
||||
quat.clone = vec4.clone;
|
||||
|
||||
/**
|
||||
* Creates a new quat initialized with the given values
|
||||
*
|
||||
* @param {Number} x X component
|
||||
* @param {Number} y Y component
|
||||
* @param {Number} z Z component
|
||||
* @param {Number} w W component
|
||||
* @returns {quat} a new quaternion
|
||||
* @function
|
||||
*/
|
||||
quat.fromValues = vec4.fromValues;
|
||||
|
||||
/**
|
||||
* Copy the values from one quat to another
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {quat} a the source quaternion
|
||||
* @returns {quat} out
|
||||
* @function
|
||||
*/
|
||||
quat.copy = vec4.copy;
|
||||
|
||||
/**
|
||||
* Set the components of a quat to the given values
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {Number} x X component
|
||||
* @param {Number} y Y component
|
||||
* @param {Number} z Z component
|
||||
* @param {Number} w W component
|
||||
* @returns {quat} out
|
||||
* @function
|
||||
*/
|
||||
quat.set = vec4.set;
|
||||
|
||||
/**
|
||||
* Set a quat to the identity quaternion
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.identity = function(out) {
|
||||
out[0] = 0;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 1;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a quat from the given angle and rotation axis,
|
||||
* then returns it.
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {vec3} axis the axis around which to rotate
|
||||
* @param {Number} rad the angle in radians
|
||||
* @returns {quat} out
|
||||
**/
|
||||
quat.setAxisAngle = function(out, axis, rad) {
|
||||
rad = rad * 0.5;
|
||||
var s = Math.sin(rad);
|
||||
out[0] = s * axis[0];
|
||||
out[1] = s * axis[1];
|
||||
out[2] = s * axis[2];
|
||||
out[3] = Math.cos(rad);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds two quat's
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {quat} a the first operand
|
||||
* @param {quat} b the second operand
|
||||
* @returns {quat} out
|
||||
* @function
|
||||
*/
|
||||
quat.add = vec4.add;
|
||||
|
||||
/**
|
||||
* Multiplies two quat's
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {quat} a the first operand
|
||||
* @param {quat} b the second operand
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.multiply = function(out, a, b) {
|
||||
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
|
||||
bx = b[0], by = b[1], bz = b[2], bw = b[3];
|
||||
|
||||
out[0] = ax * bw + aw * bx + ay * bz - az * by;
|
||||
out[1] = ay * bw + aw * by + az * bx - ax * bz;
|
||||
out[2] = az * bw + aw * bz + ax * by - ay * bx;
|
||||
out[3] = aw * bw - ax * bx - ay * by - az * bz;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link quat.multiply}
|
||||
* @function
|
||||
*/
|
||||
quat.mul = quat.multiply;
|
||||
|
||||
/**
|
||||
* Scales a quat by a scalar number
|
||||
*
|
||||
* @param {quat} out the receiving vector
|
||||
* @param {quat} a the vector to scale
|
||||
* @param {Number} b amount to scale the vector by
|
||||
* @returns {quat} out
|
||||
* @function
|
||||
*/
|
||||
quat.scale = vec4.scale;
|
||||
|
||||
/**
|
||||
* Rotates a quaternion by the given angle about the X axis
|
||||
*
|
||||
* @param {quat} out quat receiving operation result
|
||||
* @param {quat} a quat to rotate
|
||||
* @param {number} rad angle (in radians) to rotate
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.rotateX = function (out, a, rad) {
|
||||
rad *= 0.5;
|
||||
|
||||
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
|
||||
bx = Math.sin(rad), bw = Math.cos(rad);
|
||||
|
||||
out[0] = ax * bw + aw * bx;
|
||||
out[1] = ay * bw + az * bx;
|
||||
out[2] = az * bw - ay * bx;
|
||||
out[3] = aw * bw - ax * bx;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rotates a quaternion by the given angle about the Y axis
|
||||
*
|
||||
* @param {quat} out quat receiving operation result
|
||||
* @param {quat} a quat to rotate
|
||||
* @param {number} rad angle (in radians) to rotate
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.rotateY = function (out, a, rad) {
|
||||
rad *= 0.5;
|
||||
|
||||
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
|
||||
by = Math.sin(rad), bw = Math.cos(rad);
|
||||
|
||||
out[0] = ax * bw - az * by;
|
||||
out[1] = ay * bw + aw * by;
|
||||
out[2] = az * bw + ax * by;
|
||||
out[3] = aw * bw - ay * by;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rotates a quaternion by the given angle about the Z axis
|
||||
*
|
||||
* @param {quat} out quat receiving operation result
|
||||
* @param {quat} a quat to rotate
|
||||
* @param {number} rad angle (in radians) to rotate
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.rotateZ = function (out, a, rad) {
|
||||
rad *= 0.5;
|
||||
|
||||
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
|
||||
bz = Math.sin(rad), bw = Math.cos(rad);
|
||||
|
||||
out[0] = ax * bw + ay * bz;
|
||||
out[1] = ay * bw - ax * bz;
|
||||
out[2] = az * bw + aw * bz;
|
||||
out[3] = aw * bw - az * bz;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the W component of a quat from the X, Y, and Z components.
|
||||
* Assumes that quaternion is 1 unit in length.
|
||||
* Any existing W component will be ignored.
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {quat} a quat to calculate W component of
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.calculateW = function (out, a) {
|
||||
var x = a[0], y = a[1], z = a[2];
|
||||
|
||||
out[0] = x;
|
||||
out[1] = y;
|
||||
out[2] = z;
|
||||
out[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the dot product of two quat's
|
||||
*
|
||||
* @param {quat} a the first operand
|
||||
* @param {quat} b the second operand
|
||||
* @returns {Number} dot product of a and b
|
||||
* @function
|
||||
*/
|
||||
quat.dot = vec4.dot;
|
||||
|
||||
/**
|
||||
* Performs a linear interpolation between two quat's
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {quat} a the first operand
|
||||
* @param {quat} b the second operand
|
||||
* @param {Number} t interpolation amount between the two inputs
|
||||
* @returns {quat} out
|
||||
* @function
|
||||
*/
|
||||
quat.lerp = vec4.lerp;
|
||||
|
||||
/**
|
||||
* Performs a spherical linear interpolation between two quat
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {quat} a the first operand
|
||||
* @param {quat} b the second operand
|
||||
* @param {Number} t interpolation amount between the two inputs
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.slerp = function (out, a, b, t) {
|
||||
// benchmarks:
|
||||
// http://jsperf.com/quaternion-slerp-implementations
|
||||
|
||||
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
|
||||
bx = b[0], by = b[1], bz = b[2], bw = b[3];
|
||||
|
||||
var omega, cosom, sinom, scale0, scale1;
|
||||
|
||||
// calc cosine
|
||||
cosom = ax * bx + ay * by + az * bz + aw * bw;
|
||||
// adjust signs (if necessary)
|
||||
if ( cosom < 0.0 ) {
|
||||
cosom = -cosom;
|
||||
bx = - bx;
|
||||
by = - by;
|
||||
bz = - bz;
|
||||
bw = - bw;
|
||||
}
|
||||
// calculate coefficients
|
||||
if ( (1.0 - cosom) > 0.000001 ) {
|
||||
// standard case (slerp)
|
||||
omega = Math.acos(cosom);
|
||||
sinom = Math.sin(omega);
|
||||
scale0 = Math.sin((1.0 - t) * omega) / sinom;
|
||||
scale1 = Math.sin(t * omega) / sinom;
|
||||
} else {
|
||||
// "from" and "to" quaternions are very close
|
||||
// ... so we can do a linear interpolation
|
||||
scale0 = 1.0 - t;
|
||||
scale1 = t;
|
||||
}
|
||||
// calculate final values
|
||||
out[0] = scale0 * ax + scale1 * bx;
|
||||
out[1] = scale0 * ay + scale1 * by;
|
||||
out[2] = scale0 * az + scale1 * bz;
|
||||
out[3] = scale0 * aw + scale1 * bw;
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the inverse of a quat
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {quat} a quat to calculate inverse of
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.invert = function(out, a) {
|
||||
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
|
||||
dot = a0*a0 + a1*a1 + a2*a2 + a3*a3,
|
||||
invDot = dot ? 1.0/dot : 0;
|
||||
|
||||
// TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
|
||||
|
||||
out[0] = -a0*invDot;
|
||||
out[1] = -a1*invDot;
|
||||
out[2] = -a2*invDot;
|
||||
out[3] = a3*invDot;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the conjugate of a quat
|
||||
* If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {quat} a quat to calculate conjugate of
|
||||
* @returns {quat} out
|
||||
*/
|
||||
quat.conjugate = function (out, a) {
|
||||
out[0] = -a[0];
|
||||
out[1] = -a[1];
|
||||
out[2] = -a[2];
|
||||
out[3] = a[3];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the length of a quat
|
||||
*
|
||||
* @param {quat} a vector to calculate length of
|
||||
* @returns {Number} length of a
|
||||
* @function
|
||||
*/
|
||||
quat.length = vec4.length;
|
||||
|
||||
/**
|
||||
* Alias for {@link quat.length}
|
||||
* @function
|
||||
*/
|
||||
quat.len = quat.length;
|
||||
|
||||
/**
|
||||
* Calculates the squared length of a quat
|
||||
*
|
||||
* @param {quat} a vector to calculate squared length of
|
||||
* @returns {Number} squared length of a
|
||||
* @function
|
||||
*/
|
||||
quat.squaredLength = vec4.squaredLength;
|
||||
|
||||
/**
|
||||
* Alias for {@link quat.squaredLength}
|
||||
* @function
|
||||
*/
|
||||
quat.sqrLen = quat.squaredLength;
|
||||
|
||||
/**
|
||||
* Normalize a quat
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {quat} a quaternion to normalize
|
||||
* @returns {quat} out
|
||||
* @function
|
||||
*/
|
||||
quat.normalize = vec4.normalize;
|
||||
|
||||
/**
|
||||
* Creates a quaternion from the given 3x3 rotation matrix.
|
||||
*
|
||||
* NOTE: The resultant quaternion is not normalized, so you should be sure
|
||||
* to renormalize the quaternion yourself where necessary.
|
||||
*
|
||||
* @param {quat} out the receiving quaternion
|
||||
* @param {mat3} m rotation matrix
|
||||
* @returns {quat} out
|
||||
* @function
|
||||
*/
|
||||
quat.fromMat3 = function(out, m) {
|
||||
// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
|
||||
// article "Quaternion Calculus and Fast Animation".
|
||||
var fTrace = m[0] + m[4] + m[8];
|
||||
var fRoot;
|
||||
|
||||
if ( fTrace > 0.0 ) {
|
||||
// |w| > 1/2, may as well choose w > 1/2
|
||||
fRoot = Math.sqrt(fTrace + 1.0); // 2w
|
||||
out[3] = 0.5 * fRoot;
|
||||
fRoot = 0.5/fRoot; // 1/(4w)
|
||||
out[0] = (m[7]-m[5])*fRoot;
|
||||
out[1] = (m[2]-m[6])*fRoot;
|
||||
out[2] = (m[3]-m[1])*fRoot;
|
||||
} else {
|
||||
// |w| <= 1/2
|
||||
var i = 0;
|
||||
if ( m[4] > m[0] )
|
||||
i = 1;
|
||||
if ( m[8] > m[i*3+i] )
|
||||
i = 2;
|
||||
var j = (i+1)%3;
|
||||
var k = (i+2)%3;
|
||||
|
||||
fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0);
|
||||
out[i] = 0.5 * fRoot;
|
||||
fRoot = 0.5 / fRoot;
|
||||
out[3] = (m[k*3+j] - m[j*3+k]) * fRoot;
|
||||
out[j] = (m[j*3+i] + m[i*3+j]) * fRoot;
|
||||
out[k] = (m[k*3+i] + m[i*3+k]) * fRoot;
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a string representation of a quatenion
|
||||
*
|
||||
* @param {quat} vec vector to represent as a string
|
||||
* @returns {String} string representation of the vector
|
||||
*/
|
||||
quat.str = function (a) {
|
||||
return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
|
||||
};
|
||||
|
||||
export default quat;
|
||||
@@ -1,538 +0,0 @@
|
||||
import {GLMAT_ARRAY_TYPE} from "./common";
|
||||
import {GLMAT_RANDOM} from "./common";
|
||||
|
||||
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/**
|
||||
* @class 2 Dimensional Vector
|
||||
* @name vec2
|
||||
*/
|
||||
var vec2 = {};
|
||||
|
||||
/**
|
||||
* Creates a new, empty vec2
|
||||
*
|
||||
* @returns {vec2} a new 2D vector
|
||||
*/
|
||||
vec2.create = function() {
|
||||
var out = new GLMAT_ARRAY_TYPE(2);
|
||||
out[0] = 0;
|
||||
out[1] = 0;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new vec2 initialized with values from an existing vector
|
||||
*
|
||||
* @param {vec2} a vector to clone
|
||||
* @returns {vec2} a new 2D vector
|
||||
*/
|
||||
vec2.clone = function(a) {
|
||||
var out = new GLMAT_ARRAY_TYPE(2);
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new vec2 initialized with the given values
|
||||
*
|
||||
* @param {Number} x X component
|
||||
* @param {Number} y Y component
|
||||
* @returns {vec2} a new 2D vector
|
||||
*/
|
||||
vec2.fromValues = function(x, y) {
|
||||
var out = new GLMAT_ARRAY_TYPE(2);
|
||||
out[0] = x;
|
||||
out[1] = y;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy the values from one vec2 to another
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the source vector
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.copy = function(out, a) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the components of a vec2 to the given values
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {Number} x X component
|
||||
* @param {Number} y Y component
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.set = function(out, x, y) {
|
||||
out[0] = x;
|
||||
out[1] = y;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds two vec2's
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.add = function(out, a, b) {
|
||||
out[0] = a[0] + b[0];
|
||||
out[1] = a[1] + b[1];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtracts vector b from vector a
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.subtract = function(out, a, b) {
|
||||
out[0] = a[0] - b[0];
|
||||
out[1] = a[1] - b[1];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec2.subtract}
|
||||
* @function
|
||||
*/
|
||||
vec2.sub = vec2.subtract;
|
||||
|
||||
/**
|
||||
* Multiplies two vec2's
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.multiply = function(out, a, b) {
|
||||
out[0] = a[0] * b[0];
|
||||
out[1] = a[1] * b[1];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec2.multiply}
|
||||
* @function
|
||||
*/
|
||||
vec2.mul = vec2.multiply;
|
||||
|
||||
|
||||
/**
|
||||
* Divides two vec2's
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.divide = function(out, a, b) {
|
||||
out[0] = a[0] / b[0];
|
||||
out[1] = a[1] / b[1];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec2.divide}
|
||||
* @function
|
||||
*/
|
||||
vec2.div = vec2.divide;
|
||||
|
||||
/**
|
||||
* Returns the minimum of two vec2's
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.min = function(out, a, b) {
|
||||
out[0] = Math.min(a[0], b[0]);
|
||||
out[1] = Math.min(a[1], b[1]);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the maximum of two vec2's
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.max = function(out, a, b) {
|
||||
out[0] = Math.max(a[0], b[0]);
|
||||
out[1] = Math.max(a[1], b[1]);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scales a vec2 by a scalar number
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the vector to scale
|
||||
* @param {Number} b amount to scale the vector by
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.scale = function(out, a, b) {
|
||||
out[0] = a[0] * b;
|
||||
out[1] = a[1] * b;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds two vec2's after scaling the second operand by a scalar value
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @param {Number} scale the amount to scale b by before adding
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.scaleAndAdd = function(out, a, b, scale) {
|
||||
out[0] = a[0] + (b[0] * scale);
|
||||
out[1] = a[1] + (b[1] * scale);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the euclidian distance between two vec2's
|
||||
*
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @returns {Number} distance between a and b
|
||||
*/
|
||||
vec2.distance = function(a, b) {
|
||||
var x = b[0] - a[0],
|
||||
y = b[1] - a[1];
|
||||
return Math.sqrt(x*x + y*y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec2.distance}
|
||||
* @function
|
||||
*/
|
||||
vec2.dist = vec2.distance;
|
||||
|
||||
/**
|
||||
* Calculates the squared euclidian distance between two vec2's
|
||||
*
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @returns {Number} squared distance between a and b
|
||||
*/
|
||||
vec2.squaredDistance = function(a, b) {
|
||||
var x = b[0] - a[0],
|
||||
y = b[1] - a[1];
|
||||
return x*x + y*y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec2.squaredDistance}
|
||||
* @function
|
||||
*/
|
||||
vec2.sqrDist = vec2.squaredDistance;
|
||||
|
||||
/**
|
||||
* Calculates the length of a vec2
|
||||
*
|
||||
* @param {vec2} a vector to calculate length of
|
||||
* @returns {Number} length of a
|
||||
*/
|
||||
vec2.length = function (a) {
|
||||
var x = a[0],
|
||||
y = a[1];
|
||||
return Math.sqrt(x*x + y*y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec2.length}
|
||||
* @function
|
||||
*/
|
||||
vec2.len = vec2.length;
|
||||
|
||||
/**
|
||||
* Calculates the squared length of a vec2
|
||||
*
|
||||
* @param {vec2} a vector to calculate squared length of
|
||||
* @returns {Number} squared length of a
|
||||
*/
|
||||
vec2.squaredLength = function (a) {
|
||||
var x = a[0],
|
||||
y = a[1];
|
||||
return x*x + y*y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec2.squaredLength}
|
||||
* @function
|
||||
*/
|
||||
vec2.sqrLen = vec2.squaredLength;
|
||||
|
||||
/**
|
||||
* Negates the components of a vec2
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a vector to negate
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.negate = function(out, a) {
|
||||
out[0] = -a[0];
|
||||
out[1] = -a[1];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize a vec2
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a vector to normalize
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.normalize = function(out, a) {
|
||||
var x = a[0],
|
||||
y = a[1];
|
||||
var len = x*x + y*y;
|
||||
if (len > 0) {
|
||||
//TODO: evaluate use of glm_invsqrt here?
|
||||
len = 1 / Math.sqrt(len);
|
||||
out[0] = a[0] * len;
|
||||
out[1] = a[1] * len;
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the dot product of two vec2's
|
||||
*
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @returns {Number} dot product of a and b
|
||||
*/
|
||||
vec2.dot = function (a, b) {
|
||||
return a[0] * b[0] + a[1] * b[1];
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the cross product of two vec2's
|
||||
* Note that the cross product must by definition produce a 3D vector
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec2.cross = function(out, a, b) {
|
||||
var z = a[0] * b[1] - a[1] * b[0];
|
||||
out[0] = out[1] = 0;
|
||||
out[2] = z;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs a linear interpolation between two vec2's
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the first operand
|
||||
* @param {vec2} b the second operand
|
||||
* @param {Number} t interpolation amount between the two inputs
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.lerp = function (out, a, b, t) {
|
||||
var ax = a[0],
|
||||
ay = a[1];
|
||||
out[0] = ax + t * (b[0] - ax);
|
||||
out[1] = ay + t * (b[1] - ay);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a random vector with the given scale
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.random = function (out, scale) {
|
||||
scale = scale || 1.0;
|
||||
var r = GLMAT_RANDOM() * 2.0 * Math.PI;
|
||||
out[0] = Math.cos(r) * scale;
|
||||
out[1] = Math.sin(r) * scale;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the vec2 with a mat2
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the vector to transform
|
||||
* @param {mat2} m matrix to transform with
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.transformMat2 = function(out, a, m) {
|
||||
var x = a[0],
|
||||
y = a[1];
|
||||
out[0] = m[0] * x + m[2] * y;
|
||||
out[1] = m[1] * x + m[3] * y;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the vec2 with a mat2d
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the vector to transform
|
||||
* @param {mat2d} m matrix to transform with
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.transformMat2d = function(out, a, m) {
|
||||
var x = a[0],
|
||||
y = a[1];
|
||||
out[0] = m[0] * x + m[2] * y + m[4];
|
||||
out[1] = m[1] * x + m[3] * y + m[5];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the vec2 with a mat3
|
||||
* 3rd vector component is implicitly '1'
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the vector to transform
|
||||
* @param {mat3} m matrix to transform with
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.transformMat3 = function(out, a, m) {
|
||||
var x = a[0],
|
||||
y = a[1];
|
||||
out[0] = m[0] * x + m[3] * y + m[6];
|
||||
out[1] = m[1] * x + m[4] * y + m[7];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the vec2 with a mat4
|
||||
* 3rd vector component is implicitly '0'
|
||||
* 4th vector component is implicitly '1'
|
||||
*
|
||||
* @param {vec2} out the receiving vector
|
||||
* @param {vec2} a the vector to transform
|
||||
* @param {mat4} m matrix to transform with
|
||||
* @returns {vec2} out
|
||||
*/
|
||||
vec2.transformMat4 = function(out, a, m) {
|
||||
var x = a[0],
|
||||
y = a[1];
|
||||
out[0] = m[0] * x + m[4] * y + m[12];
|
||||
out[1] = m[1] * x + m[5] * y + m[13];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform some operation over an array of vec2s.
|
||||
*
|
||||
* @param {Array} a the array of vectors to iterate over
|
||||
* @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
|
||||
* @param {Number} offset Number of elements to skip at the beginning of the array
|
||||
* @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
|
||||
* @param {Function} fn Function to call for each vector in the array
|
||||
* @param {Object} [arg] additional argument to pass to fn
|
||||
* @returns {Array} a
|
||||
* @function
|
||||
*/
|
||||
vec2.forEach = (function() {
|
||||
var vec = vec2.create();
|
||||
|
||||
return function(a, stride, offset, count, fn, arg) {
|
||||
var i, l;
|
||||
if(!stride) {
|
||||
stride = 2;
|
||||
}
|
||||
|
||||
if(!offset) {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if(count) {
|
||||
l = Math.min((count * stride) + offset, a.length);
|
||||
} else {
|
||||
l = a.length;
|
||||
}
|
||||
|
||||
for(i = offset; i < l; i += stride) {
|
||||
vec[0] = a[i]; vec[1] = a[i+1];
|
||||
fn(vec, vec, arg);
|
||||
a[i] = vec[0]; a[i+1] = vec[1];
|
||||
}
|
||||
|
||||
return a;
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Returns a string representation of a vector
|
||||
*
|
||||
* @param {vec2} vec vector to represent as a string
|
||||
* @returns {String} string representation of the vector
|
||||
*/
|
||||
vec2.str = function (a) {
|
||||
return 'vec2(' + a[0] + ', ' + a[1] + ')';
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
vec2.multiplyScalar = function(out, a, b) {
|
||||
out[0] = a[0] * b;
|
||||
out[1] = a[1] * b;
|
||||
return out;
|
||||
};
|
||||
|
||||
vec2.clear = function(out) {
|
||||
out[0] = 0;
|
||||
out[1] = 0;
|
||||
return out;
|
||||
};
|
||||
|
||||
vec2.addXY = function(out, a, x, y) {
|
||||
out[0] = a[0] + x;
|
||||
out[1] = a[1] + y;
|
||||
return out;
|
||||
};
|
||||
|
||||
|
||||
export default vec2;
|
||||
|
||||
@@ -1,562 +0,0 @@
|
||||
import {GLMAT_ARRAY_TYPE} from "./common";
|
||||
import {GLMAT_RANDOM} from "./common";
|
||||
|
||||
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/**
|
||||
* @class 3 Dimensional Vector
|
||||
* @name vec3
|
||||
*/
|
||||
var vec3 = {};
|
||||
|
||||
/**
|
||||
* Creates a new, empty vec3
|
||||
*
|
||||
* @returns {vec3} a new 3D vector
|
||||
*/
|
||||
vec3.create = function() {
|
||||
var out = new GLMAT_ARRAY_TYPE(3);
|
||||
out[0] = 0;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new vec3 initialized with values from an existing vector
|
||||
*
|
||||
* @param {vec3} a vector to clone
|
||||
* @returns {vec3} a new 3D vector
|
||||
*/
|
||||
vec3.clone = function(a) {
|
||||
var out = new GLMAT_ARRAY_TYPE(3);
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new vec3 initialized with the given values
|
||||
*
|
||||
* @param {Number} x X component
|
||||
* @param {Number} y Y component
|
||||
* @param {Number} z Z component
|
||||
* @returns {vec3} a new 3D vector
|
||||
*/
|
||||
vec3.fromValues = function(x, y, z) {
|
||||
var out = new GLMAT_ARRAY_TYPE(3);
|
||||
out[0] = x;
|
||||
out[1] = y;
|
||||
out[2] = z;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy the values from one vec3 to another
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the source vector
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.copy = function(out, a) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the components of a vec3 to the given values
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {Number} x X component
|
||||
* @param {Number} y Y component
|
||||
* @param {Number} z Z component
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.set = function(out, x, y, z) {
|
||||
out[0] = x;
|
||||
out[1] = y;
|
||||
out[2] = z;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds two vec3's
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.add = function(out, a, b) {
|
||||
out[0] = a[0] + b[0];
|
||||
out[1] = a[1] + b[1];
|
||||
out[2] = a[2] + b[2];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtracts vector b from vector a
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.subtract = function(out, a, b) {
|
||||
out[0] = a[0] - b[0];
|
||||
out[1] = a[1] - b[1];
|
||||
out[2] = a[2] - b[2];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec3.subtract}
|
||||
* @function
|
||||
*/
|
||||
vec3.sub = vec3.subtract;
|
||||
|
||||
/**
|
||||
* Multiplies two vec3's
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.multiply = function(out, a, b) {
|
||||
out[0] = a[0] * b[0];
|
||||
out[1] = a[1] * b[1];
|
||||
out[2] = a[2] * b[2];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec3.multiply}
|
||||
* @function
|
||||
*/
|
||||
vec3.mul = vec3.multiply;
|
||||
|
||||
/**
|
||||
* Divides two vec3's
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.divide = function(out, a, b) {
|
||||
out[0] = a[0] / b[0];
|
||||
out[1] = a[1] / b[1];
|
||||
out[2] = a[2] / b[2];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec3.divide}
|
||||
* @function
|
||||
*/
|
||||
vec3.div = vec3.divide;
|
||||
|
||||
/**
|
||||
* Returns the minimum of two vec3's
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.min = function(out, a, b) {
|
||||
out[0] = Math.min(a[0], b[0]);
|
||||
out[1] = Math.min(a[1], b[1]);
|
||||
out[2] = Math.min(a[2], b[2]);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the maximum of two vec3's
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.max = function(out, a, b) {
|
||||
out[0] = Math.max(a[0], b[0]);
|
||||
out[1] = Math.max(a[1], b[1]);
|
||||
out[2] = Math.max(a[2], b[2]);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scales a vec3 by a scalar number
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the vector to scale
|
||||
* @param {Number} b amount to scale the vector by
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.scale = function(out, a, b) {
|
||||
out[0] = a[0] * b;
|
||||
out[1] = a[1] * b;
|
||||
out[2] = a[2] * b;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds two vec3's after scaling the second operand by a scalar value
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @param {Number} scale the amount to scale b by before adding
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.scaleAndAdd = function(out, a, b, scale) {
|
||||
out[0] = a[0] + (b[0] * scale);
|
||||
out[1] = a[1] + (b[1] * scale);
|
||||
out[2] = a[2] + (b[2] * scale);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the euclidian distance between two vec3's
|
||||
*
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @returns {Number} distance between a and b
|
||||
*/
|
||||
vec3.distance = function(a, b) {
|
||||
var x = b[0] - a[0],
|
||||
y = b[1] - a[1],
|
||||
z = b[2] - a[2];
|
||||
return Math.sqrt(x*x + y*y + z*z);
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec3.distance}
|
||||
* @function
|
||||
*/
|
||||
vec3.dist = vec3.distance;
|
||||
|
||||
/**
|
||||
* Calculates the squared euclidian distance between two vec3's
|
||||
*
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @returns {Number} squared distance between a and b
|
||||
*/
|
||||
vec3.squaredDistance = function(a, b) {
|
||||
var x = b[0] - a[0],
|
||||
y = b[1] - a[1],
|
||||
z = b[2] - a[2];
|
||||
return x*x + y*y + z*z;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec3.squaredDistance}
|
||||
* @function
|
||||
*/
|
||||
vec3.sqrDist = vec3.squaredDistance;
|
||||
|
||||
/**
|
||||
* Calculates the length of a vec3
|
||||
*
|
||||
* @param {vec3} a vector to calculate length of
|
||||
* @returns {Number} length of a
|
||||
*/
|
||||
vec3.length = function (a) {
|
||||
var x = a[0],
|
||||
y = a[1],
|
||||
z = a[2];
|
||||
return Math.sqrt(x*x + y*y + z*z);
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec3.length}
|
||||
* @function
|
||||
*/
|
||||
vec3.len = vec3.length;
|
||||
|
||||
/**
|
||||
* Calculates the squared length of a vec3
|
||||
*
|
||||
* @param {vec3} a vector to calculate squared length of
|
||||
* @returns {Number} squared length of a
|
||||
*/
|
||||
vec3.squaredLength = function (a) {
|
||||
var x = a[0],
|
||||
y = a[1],
|
||||
z = a[2];
|
||||
return x*x + y*y + z*z;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec3.squaredLength}
|
||||
* @function
|
||||
*/
|
||||
vec3.sqrLen = vec3.squaredLength;
|
||||
|
||||
/**
|
||||
* Negates the components of a vec3
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a vector to negate
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.negate = function(out, a) {
|
||||
out[0] = -a[0];
|
||||
out[1] = -a[1];
|
||||
out[2] = -a[2];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize a vec3
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a vector to normalize
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.normalize = function(out, a) {
|
||||
var x = a[0],
|
||||
y = a[1],
|
||||
z = a[2];
|
||||
var len = x*x + y*y + z*z;
|
||||
if (len > 0) {
|
||||
//TODO: evaluate use of glm_invsqrt here?
|
||||
len = 1 / Math.sqrt(len);
|
||||
out[0] = a[0] * len;
|
||||
out[1] = a[1] * len;
|
||||
out[2] = a[2] * len;
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the dot product of two vec3's
|
||||
*
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @returns {Number} dot product of a and b
|
||||
*/
|
||||
vec3.dot = function (a, b) {
|
||||
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the cross product of two vec3's
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.cross = function(out, a, b) {
|
||||
var ax = a[0], ay = a[1], az = a[2],
|
||||
bx = b[0], by = b[1], bz = b[2];
|
||||
|
||||
out[0] = ay * bz - az * by;
|
||||
out[1] = az * bx - ax * bz;
|
||||
out[2] = ax * by - ay * bx;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs a linear interpolation between two vec3's
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the first operand
|
||||
* @param {vec3} b the second operand
|
||||
* @param {Number} t interpolation amount between the two inputs
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.lerp = function (out, a, b, t) {
|
||||
var ax = a[0],
|
||||
ay = a[1],
|
||||
az = a[2];
|
||||
out[0] = ax + t * (b[0] - ax);
|
||||
out[1] = ay + t * (b[1] - ay);
|
||||
out[2] = az + t * (b[2] - az);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a random vector with the given scale
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.random = function (out, scale) {
|
||||
scale = scale || 1.0;
|
||||
|
||||
var r = GLMAT_RANDOM() * 2.0 * Math.PI;
|
||||
var z = (GLMAT_RANDOM() * 2.0) - 1.0;
|
||||
var zScale = Math.sqrt(1.0-z*z) * scale;
|
||||
|
||||
out[0] = Math.cos(r) * zScale;
|
||||
out[1] = Math.sin(r) * zScale;
|
||||
out[2] = z * scale;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the vec3 with a mat4.
|
||||
* 4th vector component is implicitly '1'
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the vector to transform
|
||||
* @param {mat4} m matrix to transform with
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.transformMat4 = function(out, a, m) {
|
||||
var x = a[0], y = a[1], z = a[2];
|
||||
out[0] = m[0] * x + m[4] * y + m[8] * z + m[12];
|
||||
out[1] = m[1] * x + m[5] * y + m[9] * z + m[13];
|
||||
out[2] = m[2] * x + m[6] * y + m[10] * z + m[14];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the vec3 with a mat3.
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the vector to transform
|
||||
* @param {mat4} m the 3x3 matrix to transform with
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.transformMat3 = function(out, a, m) {
|
||||
var x = a[0], y = a[1], z = a[2];
|
||||
out[0] = x * m[0] + y * m[3] + z * m[6];
|
||||
out[1] = x * m[1] + y * m[4] + z * m[7];
|
||||
out[2] = x * m[2] + y * m[5] + z * m[8];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the vec3 with a quat
|
||||
*
|
||||
* @param {vec3} out the receiving vector
|
||||
* @param {vec3} a the vector to transform
|
||||
* @param {quat} q quaternion to transform with
|
||||
* @returns {vec3} out
|
||||
*/
|
||||
vec3.transformQuat = function(out, a, q) {
|
||||
// benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations
|
||||
|
||||
var x = a[0], y = a[1], z = a[2],
|
||||
qx = q[0], qy = q[1], qz = q[2], qw = q[3],
|
||||
|
||||
// calculate quat * vec
|
||||
ix = qw * x + qy * z - qz * y,
|
||||
iy = qw * y + qz * x - qx * z,
|
||||
iz = qw * z + qx * y - qy * x,
|
||||
iw = -qx * x - qy * y - qz * z;
|
||||
|
||||
// calculate result * inverse quat
|
||||
out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
||||
out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
||||
out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform some operation over an array of vec3s.
|
||||
*
|
||||
* @param {Array} a the array of vectors to iterate over
|
||||
* @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
|
||||
* @param {Number} offset Number of elements to skip at the beginning of the array
|
||||
* @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
|
||||
* @param {Function} fn Function to call for each vector in the array
|
||||
* @param {Object} [arg] additional argument to pass to fn
|
||||
* @returns {Array} a
|
||||
* @function
|
||||
*/
|
||||
vec3.forEach = (function() {
|
||||
var vec = vec3.create();
|
||||
|
||||
return function(a, stride, offset, count, fn, arg) {
|
||||
var i, l;
|
||||
if(!stride) {
|
||||
stride = 3;
|
||||
}
|
||||
|
||||
if(!offset) {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if(count) {
|
||||
l = Math.min((count * stride) + offset, a.length);
|
||||
} else {
|
||||
l = a.length;
|
||||
}
|
||||
|
||||
for(i = offset; i < l; i += stride) {
|
||||
vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2];
|
||||
fn(vec, vec, arg);
|
||||
a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2];
|
||||
}
|
||||
|
||||
return a;
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Returns a string representation of a vector
|
||||
*
|
||||
* @param {vec3} vec vector to represent as a string
|
||||
* @returns {String} string representation of the vector
|
||||
*/
|
||||
vec3.str = function (a) {
|
||||
return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
|
||||
};
|
||||
|
||||
|
||||
|
||||
vec3.multiplyScalar = function(out, a, b) {
|
||||
out[0] = a[0] * b;
|
||||
out[1] = a[1] * b;
|
||||
out[2] = a[2] * b;
|
||||
return out;
|
||||
};
|
||||
|
||||
vec3.clear = function(out) {
|
||||
out[0] = 0;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
return out;
|
||||
};
|
||||
|
||||
vec3.addXYZ = function(out, a, x, y, z) {
|
||||
out[0] = a[0] + x;
|
||||
out[1] = a[1] + y;
|
||||
out[2] = a[2] + z;
|
||||
return out;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export default vec3;
|
||||
@@ -1,526 +0,0 @@
|
||||
import {GLMAT_ARRAY_TYPE} from "./common";
|
||||
import {GLMAT_RANDOM} from "./common";
|
||||
|
||||
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/**
|
||||
* @class 4 Dimensional Vector
|
||||
* @name vec4
|
||||
*/
|
||||
var vec4 = {};
|
||||
|
||||
/**
|
||||
* Creates a new, empty vec4
|
||||
*
|
||||
* @returns {vec4} a new 4D vector
|
||||
*/
|
||||
vec4.create = function() {
|
||||
var out = new GLMAT_ARRAY_TYPE(4);
|
||||
out[0] = 0;
|
||||
out[1] = 0;
|
||||
out[2] = 0;
|
||||
out[3] = 0;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new vec4 initialized with values from an existing vector
|
||||
*
|
||||
* @param {vec4} a vector to clone
|
||||
* @returns {vec4} a new 4D vector
|
||||
*/
|
||||
vec4.clone = function(a) {
|
||||
var out = new GLMAT_ARRAY_TYPE(4);
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new vec4 initialized with the given values
|
||||
*
|
||||
* @param {Number} x X component
|
||||
* @param {Number} y Y component
|
||||
* @param {Number} z Z component
|
||||
* @param {Number} w W component
|
||||
* @returns {vec4} a new 4D vector
|
||||
*/
|
||||
vec4.fromValues = function(x, y, z, w) {
|
||||
var out = new GLMAT_ARRAY_TYPE(4);
|
||||
out[0] = x;
|
||||
out[1] = y;
|
||||
out[2] = z;
|
||||
out[3] = w;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy the values from one vec4 to another
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the source vector
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.copy = function(out, a) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the components of a vec4 to the given values
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {Number} x X component
|
||||
* @param {Number} y Y component
|
||||
* @param {Number} z Z component
|
||||
* @param {Number} w W component
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.set = function(out, x, y, z, w) {
|
||||
out[0] = x;
|
||||
out[1] = y;
|
||||
out[2] = z;
|
||||
out[3] = w;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds two vec4's
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.add = function(out, a, b) {
|
||||
out[0] = a[0] + b[0];
|
||||
out[1] = a[1] + b[1];
|
||||
out[2] = a[2] + b[2];
|
||||
out[3] = a[3] + b[3];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtracts vector b from vector a
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.subtract = function(out, a, b) {
|
||||
out[0] = a[0] - b[0];
|
||||
out[1] = a[1] - b[1];
|
||||
out[2] = a[2] - b[2];
|
||||
out[3] = a[3] - b[3];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec4.subtract}
|
||||
* @function
|
||||
*/
|
||||
vec4.sub = vec4.subtract;
|
||||
|
||||
/**
|
||||
* Multiplies two vec4's
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.multiply = function(out, a, b) {
|
||||
out[0] = a[0] * b[0];
|
||||
out[1] = a[1] * b[1];
|
||||
out[2] = a[2] * b[2];
|
||||
out[3] = a[3] * b[3];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec4.multiply}
|
||||
* @function
|
||||
*/
|
||||
vec4.mul = vec4.multiply;
|
||||
|
||||
/**
|
||||
* Divides two vec4's
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.divide = function(out, a, b) {
|
||||
out[0] = a[0] / b[0];
|
||||
out[1] = a[1] / b[1];
|
||||
out[2] = a[2] / b[2];
|
||||
out[3] = a[3] / b[3];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec4.divide}
|
||||
* @function
|
||||
*/
|
||||
vec4.div = vec4.divide;
|
||||
|
||||
/**
|
||||
* Returns the minimum of two vec4's
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.min = function(out, a, b) {
|
||||
out[0] = Math.min(a[0], b[0]);
|
||||
out[1] = Math.min(a[1], b[1]);
|
||||
out[2] = Math.min(a[2], b[2]);
|
||||
out[3] = Math.min(a[3], b[3]);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the maximum of two vec4's
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.max = function(out, a, b) {
|
||||
out[0] = Math.max(a[0], b[0]);
|
||||
out[1] = Math.max(a[1], b[1]);
|
||||
out[2] = Math.max(a[2], b[2]);
|
||||
out[3] = Math.max(a[3], b[3]);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scales a vec4 by a scalar number
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the vector to scale
|
||||
* @param {Number} b amount to scale the vector by
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.scale = function(out, a, b) {
|
||||
out[0] = a[0] * b;
|
||||
out[1] = a[1] * b;
|
||||
out[2] = a[2] * b;
|
||||
out[3] = a[3] * b;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds two vec4's after scaling the second operand by a scalar value
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @param {Number} scale the amount to scale b by before adding
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.scaleAndAdd = function(out, a, b, scale) {
|
||||
out[0] = a[0] + (b[0] * scale);
|
||||
out[1] = a[1] + (b[1] * scale);
|
||||
out[2] = a[2] + (b[2] * scale);
|
||||
out[3] = a[3] + (b[3] * scale);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the euclidian distance between two vec4's
|
||||
*
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @returns {Number} distance between a and b
|
||||
*/
|
||||
vec4.distance = function(a, b) {
|
||||
var x = b[0] - a[0],
|
||||
y = b[1] - a[1],
|
||||
z = b[2] - a[2],
|
||||
w = b[3] - a[3];
|
||||
return Math.sqrt(x*x + y*y + z*z + w*w);
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec4.distance}
|
||||
* @function
|
||||
*/
|
||||
vec4.dist = vec4.distance;
|
||||
|
||||
/**
|
||||
* Calculates the squared euclidian distance between two vec4's
|
||||
*
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @returns {Number} squared distance between a and b
|
||||
*/
|
||||
vec4.squaredDistance = function(a, b) {
|
||||
var x = b[0] - a[0],
|
||||
y = b[1] - a[1],
|
||||
z = b[2] - a[2],
|
||||
w = b[3] - a[3];
|
||||
return x*x + y*y + z*z + w*w;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec4.squaredDistance}
|
||||
* @function
|
||||
*/
|
||||
vec4.sqrDist = vec4.squaredDistance;
|
||||
|
||||
/**
|
||||
* Calculates the length of a vec4
|
||||
*
|
||||
* @param {vec4} a vector to calculate length of
|
||||
* @returns {Number} length of a
|
||||
*/
|
||||
vec4.length = function (a) {
|
||||
var x = a[0],
|
||||
y = a[1],
|
||||
z = a[2],
|
||||
w = a[3];
|
||||
return Math.sqrt(x*x + y*y + z*z + w*w);
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec4.length}
|
||||
* @function
|
||||
*/
|
||||
vec4.len = vec4.length;
|
||||
|
||||
/**
|
||||
* Calculates the squared length of a vec4
|
||||
*
|
||||
* @param {vec4} a vector to calculate squared length of
|
||||
* @returns {Number} squared length of a
|
||||
*/
|
||||
vec4.squaredLength = function (a) {
|
||||
var x = a[0],
|
||||
y = a[1],
|
||||
z = a[2],
|
||||
w = a[3];
|
||||
return x*x + y*y + z*z + w*w;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias for {@link vec4.squaredLength}
|
||||
* @function
|
||||
*/
|
||||
vec4.sqrLen = vec4.squaredLength;
|
||||
|
||||
/**
|
||||
* Negates the components of a vec4
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a vector to negate
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.negate = function(out, a) {
|
||||
out[0] = -a[0];
|
||||
out[1] = -a[1];
|
||||
out[2] = -a[2];
|
||||
out[3] = -a[3];
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize a vec4
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a vector to normalize
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.normalize = function(out, a) {
|
||||
var x = a[0],
|
||||
y = a[1],
|
||||
z = a[2],
|
||||
w = a[3];
|
||||
var len = x*x + y*y + z*z + w*w;
|
||||
if (len > 0) {
|
||||
len = 1 / Math.sqrt(len);
|
||||
out[0] = a[0] * len;
|
||||
out[1] = a[1] * len;
|
||||
out[2] = a[2] * len;
|
||||
out[3] = a[3] * len;
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the dot product of two vec4's
|
||||
*
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @returns {Number} dot product of a and b
|
||||
*/
|
||||
vec4.dot = function (a, b) {
|
||||
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs a linear interpolation between two vec4's
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the first operand
|
||||
* @param {vec4} b the second operand
|
||||
* @param {Number} t interpolation amount between the two inputs
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.lerp = function (out, a, b, t) {
|
||||
var ax = a[0],
|
||||
ay = a[1],
|
||||
az = a[2],
|
||||
aw = a[3];
|
||||
out[0] = ax + t * (b[0] - ax);
|
||||
out[1] = ay + t * (b[1] - ay);
|
||||
out[2] = az + t * (b[2] - az);
|
||||
out[3] = aw + t * (b[3] - aw);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a random vector with the given scale
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.random = function (out, scale) {
|
||||
scale = scale || 1.0;
|
||||
|
||||
//TODO: This is a pretty awful way of doing this. Find something better.
|
||||
out[0] = GLMAT_RANDOM();
|
||||
out[1] = GLMAT_RANDOM();
|
||||
out[2] = GLMAT_RANDOM();
|
||||
out[3] = GLMAT_RANDOM();
|
||||
vec4.normalize(out, out);
|
||||
vec4.scale(out, out, scale);
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the vec4 with a mat4.
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the vector to transform
|
||||
* @param {mat4} m matrix to transform with
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.transformMat4 = function(out, a, m) {
|
||||
var x = a[0], y = a[1], z = a[2], w = a[3];
|
||||
out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
|
||||
out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
|
||||
out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
|
||||
out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the vec4 with a quat
|
||||
*
|
||||
* @param {vec4} out the receiving vector
|
||||
* @param {vec4} a the vector to transform
|
||||
* @param {quat} q quaternion to transform with
|
||||
* @returns {vec4} out
|
||||
*/
|
||||
vec4.transformQuat = function(out, a, q) {
|
||||
var x = a[0], y = a[1], z = a[2],
|
||||
qx = q[0], qy = q[1], qz = q[2], qw = q[3],
|
||||
|
||||
// calculate quat * vec
|
||||
ix = qw * x + qy * z - qz * y,
|
||||
iy = qw * y + qz * x - qx * z,
|
||||
iz = qw * z + qx * y - qy * x,
|
||||
iw = -qx * x - qy * y - qz * z;
|
||||
|
||||
// calculate result * inverse quat
|
||||
out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
||||
out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
||||
out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform some operation over an array of vec4s.
|
||||
*
|
||||
* @param {Array} a the array of vectors to iterate over
|
||||
* @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
|
||||
* @param {Number} offset Number of elements to skip at the beginning of the array
|
||||
* @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
|
||||
* @param {Function} fn Function to call for each vector in the array
|
||||
* @param {Object} [arg] additional argument to pass to fn
|
||||
* @returns {Array} a
|
||||
* @function
|
||||
*/
|
||||
vec4.forEach = (function() {
|
||||
var vec = vec4.create();
|
||||
|
||||
return function(a, stride, offset, count, fn, arg) {
|
||||
var i, l;
|
||||
if(!stride) {
|
||||
stride = 4;
|
||||
}
|
||||
|
||||
if(!offset) {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if(count) {
|
||||
l = Math.min((count * stride) + offset, a.length);
|
||||
} else {
|
||||
l = a.length;
|
||||
}
|
||||
|
||||
for(i = offset; i < l; i += stride) {
|
||||
vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3];
|
||||
fn(vec, vec, arg);
|
||||
a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3];
|
||||
}
|
||||
|
||||
return a;
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Returns a string representation of a vector
|
||||
*
|
||||
* @param {vec4} vec vector to represent as a string
|
||||
* @returns {String} string representation of the vector
|
||||
*/
|
||||
vec4.str = function (a) {
|
||||
return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
|
||||
};
|
||||
|
||||
export default vec4;
|
||||
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
import * as mat2 from "./glMatrix/mat2";
|
||||
import * as mat2d from "./glMatrix/mat2d";
|
||||
import * as mat3 from "./glMatrix/mat3";
|
||||
import * as mat4 from "./glMatrix/mat4";
|
||||
import * as quat from "./glMatrix/quat";
|
||||
import * as vec2 from "./glMatrix/vec2";
|
||||
import * as vec3 from "./glMatrix/vec3";
|
||||
import * as vec4 from "./glMatrix/vec4";
|
||||
export { mat2, mat2d, mat3, mat4, quat, vec2, vec3, vec4 };
|
||||
|
||||
export {default as ArrayBuffer} from './ArrayBuffer';
|
||||
export {default as Program} from './Program';
|
||||
export {default as Material} from './Material';
|
||||
@@ -8,20 +18,6 @@ export {default as Renderer} from './Renderer';
|
||||
export {default as Camera} from './Camera';
|
||||
export {default as Object3d} from './Object3d';
|
||||
|
||||
import * as mat2 from "./glMatrix/mat2";
|
||||
import * as mat2d from "./glMatrix/mat2d";
|
||||
import * as mat3 from "./glMatrix/mat3";
|
||||
import * as mat4 from "./glMatrix/mat4";
|
||||
import * as quat from "./glMatrix/quat";
|
||||
import * as vec2 from "./glMatrix/vec2";
|
||||
import * as vec3 from "./glMatrix/vec3";
|
||||
import * as vec4 from "./glMatrix/vec4";
|
||||
export {
|
||||
mat2, mat2d, mat3, mat4,
|
||||
quat,
|
||||
vec2, vec3, vec4,
|
||||
};
|
||||
|
||||
export {default as GeometryBuffer} from './GeometryBuffer';
|
||||
export {default as PlaneGeometryBuffer} from './PlaneGeometryBuffer';
|
||||
export {default as SphereGeometryBuffer} from './SphereGeometryBuffer';
|
||||
@@ -1,11 +0,0 @@
|
||||
precision highp float;
|
||||
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main(void) {
|
||||
|
||||
vec4 outColor = vec4(1., 0., 0., 1.0);
|
||||
gl_FragColor = outColor;
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
// simulation
|
||||
varying vec2 vUv;
|
||||
|
||||
uniform sampler2D tPositions;
|
||||
uniform sampler2D tOrigin;
|
||||
uniform sampler2D tTarget;
|
||||
uniform sampler2D tVelocity;
|
||||
|
||||
uniform float timer;
|
||||
|
||||
uniform float targetSpeed;
|
||||
|
||||
uniform vec3 meshPosition;
|
||||
|
||||
|
||||
|
||||
uniform float width;
|
||||
uniform float height;
|
||||
uniform float depth;
|
||||
|
||||
void main() {
|
||||
|
||||
vec3 pos = texture2D( tPositions, vUv ).xyz;
|
||||
vec3 velocity = texture2D( tVelocity, vUv ).xyz;
|
||||
vec3 target = texture2D( tTarget, vUv ).xyz;
|
||||
|
||||
pos += velocity;
|
||||
|
||||
// if (target.x == 0.
|
||||
// && target.y == 0.
|
||||
// && target.z == 0. ) {
|
||||
// //no target sepcified
|
||||
// }
|
||||
// else{
|
||||
// pos.x += (target.x - pos.x) * targetSpeed;
|
||||
// pos.y += (target.y - pos.y) * targetSpeed;
|
||||
// pos.z += (target.z - pos.z) * targetSpeed;
|
||||
// }
|
||||
|
||||
//pos.z += meshPosition.z;
|
||||
|
||||
//GROUND
|
||||
// if (pos.y < 0.0) {
|
||||
// pos.y = 0.0;
|
||||
// }
|
||||
|
||||
if( pos.y > height * .5) {
|
||||
pos.y = height * -.5 + 1.;
|
||||
}
|
||||
if (pos.y < height * -.5) {
|
||||
pos.y = height * .5 - 1.;
|
||||
}
|
||||
if (pos.x > width * .5) {
|
||||
pos.x = width * -.5;
|
||||
}
|
||||
if (pos.x < width * -.5) {
|
||||
pos.x = width * .5;
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(pos, 1.0);
|
||||
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
// simulation
|
||||
varying vec2 vUv;
|
||||
|
||||
uniform sampler2D tPositions;
|
||||
uniform sampler2D tOrigin;
|
||||
uniform sampler2D tTarget;
|
||||
uniform sampler2D tVelocity;
|
||||
uniform sampler2D tForce;
|
||||
|
||||
uniform float timer;
|
||||
uniform vec3 collisionMouse;
|
||||
uniform float forceTarget;
|
||||
uniform float delta;
|
||||
|
||||
uniform int useMouse;
|
||||
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
|
||||
uniform float gravityStrength;
|
||||
uniform float windStrength;
|
||||
uniform float targetStrength;
|
||||
|
||||
void main() {
|
||||
|
||||
float damping = 1.0 - 0.006;
|
||||
float attractionForce = -10000000.0;
|
||||
float attractionRadius = 5000.0;
|
||||
|
||||
vec3 pos = texture2D( tPositions, vUv ).xyz * 1.0 - 0.5;
|
||||
vec3 velocity = texture2D( tVelocity, vUv ).xyz* 1.0 - 0.5;
|
||||
|
||||
// // //???
|
||||
// // velocity *= 0.5;
|
||||
|
||||
vec3 force = vec3(0.0);
|
||||
|
||||
// target
|
||||
vec3 target = texture2D( tTarget, vUv ).xyz;
|
||||
|
||||
if (target.x != 0.
|
||||
&& target.y != 0.
|
||||
&& target.z != 0. ) {
|
||||
|
||||
float targetDx = pos.x - target.x;
|
||||
float targetDy = pos.y - target.y;
|
||||
float targetDz = pos.z - target.z;
|
||||
|
||||
float targetRadiusSq = 10.0 * 10.0;
|
||||
|
||||
float targetDistSq = (targetDx*targetDx + targetDy*targetDy + targetDz*targetDz);
|
||||
|
||||
if (targetDistSq > 0.1) {//avoid shake
|
||||
vec3 attractionTarget = vec3( target.x, target.y, target.z );
|
||||
attractionTarget -= pos;
|
||||
attractionTarget = normalize( attractionTarget );
|
||||
attractionTarget *= targetDistSq * targetStrength;
|
||||
|
||||
force += attractionTarget;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* COMPUTE FORCE
|
||||
*/
|
||||
// if (useMouse == 1) {
|
||||
// float dx = pos.x - collisionMouse.x;
|
||||
// float dy = pos.y - collisionMouse.y;
|
||||
// float dz = pos.z - collisionMouse.z;
|
||||
|
||||
// float distSq = (dx*dx + dy*dy + dz*dz);
|
||||
// float attractionRadiusSq = attractionRadius*attractionRadius;
|
||||
|
||||
// if (distSq > 0.000004 && distSq < attractionRadiusSq) {
|
||||
|
||||
// float ratio = (1.0 - distSq / attractionRadiusSq); //dist / attractionRadius;
|
||||
|
||||
// vec3 attractionBehaviourForce = vec3( collisionMouse.x, collisionMouse.y, collisionMouse.z );
|
||||
|
||||
// attractionBehaviourForce -= pos;
|
||||
|
||||
// attractionBehaviourForce = normalize( attractionBehaviourForce );
|
||||
|
||||
// attractionBehaviourForce *= ratio;
|
||||
// attractionBehaviourForce *= attractionForce;
|
||||
|
||||
// force += attractionBehaviourForce;
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
//GRAVITY
|
||||
vec3 gravityForce = vec3(0., -1., 0.);
|
||||
gravityForce *= gravityStrength;
|
||||
force += gravityForce;
|
||||
|
||||
//wind
|
||||
vec3 windForce = vec3(1., 0., 0.);
|
||||
windForce *= windStrength;
|
||||
force += windForce;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* COMPUTE VELOCITY [EULER INTEGRATE]
|
||||
*/
|
||||
|
||||
vec3 oldVelocity = vec3( velocity.x, velocity.y, velocity.z );
|
||||
|
||||
vec3 newForce = force * timer;
|
||||
vec3 newVelocity = velocity + newForce;
|
||||
|
||||
newVelocity *= damping;
|
||||
|
||||
oldVelocity += newVelocity;
|
||||
oldVelocity *= 0.5 * timer;
|
||||
|
||||
|
||||
// particle.old.p.copy(particle.p);
|
||||
// particle.old.v.copy(particle.v);
|
||||
|
||||
// particle.a.multiplyScalar(1 / particle.mass);
|
||||
// particle.v.add(particle.a.multiplyScalar(time));
|
||||
// particle.p.add(particle.old.v.multiplyScalar(time));
|
||||
// if (damping){
|
||||
// particle.v.multiplyScalar(damping);
|
||||
// }
|
||||
// particle.a.clear();
|
||||
|
||||
|
||||
|
||||
gl_FragColor = vec4( oldVelocity, 1.0 );
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
|
||||
attribute vec2 uv;
|
||||
attribute vec3 color;
|
||||
attribute vec3 position;
|
||||
attribute float vertexIndex;
|
||||
attribute float particleIndex;
|
||||
|
||||
|
||||
uniform mat4 uMVMatrix;
|
||||
uniform mat4 uPMatrix;
|
||||
// uniform float pointSize;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = uv;
|
||||
|
||||
vec3 newPosition = position;
|
||||
|
||||
if (vertexIndex == 0.0) {
|
||||
newPosition += vec3(-1.,1.,0.);
|
||||
}
|
||||
else if (vertexIndex == 1.0) {
|
||||
newPosition += vec3(1.,1.,0.);
|
||||
}
|
||||
else if (vertexIndex == 2.0) {
|
||||
newPosition += vec3(-1.,-1.,0.);
|
||||
}
|
||||
else if (vertexIndex == 3.0) {
|
||||
newPosition += vec3(1.,-1.,0.);
|
||||
}
|
||||
|
||||
newPosition *= 10.;
|
||||
|
||||
gl_Position = uPMatrix * uMVMatrix * vec4( newPosition, 1.0 );
|
||||
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
export default function isPowerOf2(value) {
|
||||
return (value & (value - 1)) == 0;
|
||||
}
|
||||
@@ -4,28 +4,17 @@ var uuid = new Array( 36 );
|
||||
var rnd = 0, r;
|
||||
|
||||
export default function generateUUID() {
|
||||
|
||||
for ( var i = 0; i < 36; i ++ ) {
|
||||
|
||||
if ( i === 8 || i === 13 || i === 18 || i === 23 ) {
|
||||
|
||||
uuid[ i ] = '-';
|
||||
|
||||
} else if ( i === 14 ) {
|
||||
|
||||
uuid[ i ] = '4';
|
||||
|
||||
} else {
|
||||
|
||||
if ( rnd <= 0x02 ) rnd = 0x2000000 + ( Math.random() * 0x1000000 ) | 0;
|
||||
r = rnd & 0xf;
|
||||
rnd = rnd >> 4;
|
||||
uuid[ i ] = chars[ ( i === 19 ) ? ( r & 0x3 ) | 0x8 : r ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return uuid.join( '' );
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,396 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2013 Aaron Boman and aaronboman.com
|
||||
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.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var OBJ = {};
|
||||
|
||||
/**
|
||||
* The main Mesh class. The constructor will parse through the OBJ file data
|
||||
* and collect the vertex, vertex normal, texture, and face information. This
|
||||
* information can then be used later on when creating your VBOs. See
|
||||
* OBJ.initMeshBuffers for an example of how to use the newly created Mesh
|
||||
*
|
||||
* @class Mesh
|
||||
* @constructor
|
||||
*
|
||||
* @param {String} objectData a string representation of an OBJ file with newlines preserved.
|
||||
*/
|
||||
OBJ.Mesh = function (objectData) {
|
||||
|
||||
|
||||
/*
|
||||
The OBJ file format does a sort of compression when saving a model in a
|
||||
program like Blender. There are at least 3 sections (4 including textures)
|
||||
within the file. Each line in a section begins with the same string:
|
||||
* 'v': indicates vertex section
|
||||
* 'vn': indicates vertex normal section
|
||||
* 'f': indicates the faces section
|
||||
* 'vt': indicates vertex texture section (if textures were used on the model)
|
||||
Each of the above sections (except for the faces section) is a list/set of
|
||||
unique vertices.
|
||||
|
||||
Each line of the faces section contains a list of
|
||||
(vertex, [texture], normal) groups
|
||||
Some examples:
|
||||
// the texture index is optional, both formats are possible for models
|
||||
// without a texture applied
|
||||
f 1/25 18/46 12/31
|
||||
f 1//25 18//46 12//31
|
||||
|
||||
// A 3 vertex face with texture indices
|
||||
f 16/92/11 14/101/22 1/69/1
|
||||
|
||||
// A 4 vertex face
|
||||
f 16/92/11 40/109/40 38/114/38 14/101/22
|
||||
|
||||
The first two lines are examples of a 3 vertex face without a texture applied.
|
||||
The second is an example of a 3 vertex face with a texture applied.
|
||||
The third is an example of a 4 vertex face. Note: a face can contain N
|
||||
number of vertices.
|
||||
|
||||
Each number that appears in one of the groups is a 1-based index
|
||||
corresponding to an item from the other sections (meaning that indexing
|
||||
starts at one and *not* zero).
|
||||
|
||||
For example:
|
||||
`f 16/92/11` is saying to
|
||||
- take the 16th element from the [v] vertex array
|
||||
- take the 92nd element from the [vt] texture array
|
||||
- take the 11th element from the [vn] normal array
|
||||
and together they make a unique vertex.
|
||||
Using all 3+ unique Vertices from the face line will produce a polygon.
|
||||
|
||||
Now, you could just go through the OBJ file and create a new vertex for
|
||||
each face line and WebGL will draw what appears to be the same model.
|
||||
However, vertices will be overlapped and duplicated all over the place.
|
||||
|
||||
Consider a cube in 3D space centered about the origin and each side is
|
||||
2 units long. The front face (with the positive Z-axis pointing towards
|
||||
you) would have a Top Right vertex (looking orthogonal to its normal)
|
||||
mapped at (1,1,1) The right face would have a Top Left vertex (looking
|
||||
orthogonal to its normal) at (1,1,1) and the top face would have a Bottom
|
||||
Right vertex (looking orthogonal to its normal) at (1,1,1). Each face
|
||||
has a vertex at the same coordinates, however, three distinct vertices
|
||||
will be drawn at the same spot.
|
||||
|
||||
To solve the issue of duplicate Vertices (the `(vertex, [texture], normal)`
|
||||
groups), while iterating through the face lines, when a group is encountered
|
||||
the whole group string ('16/92/11') is checked to see if it exists in the
|
||||
packed.hashindices object, and if it doesn't, the indices it specifies
|
||||
are used to look up each attribute in the corresponding attribute arrays
|
||||
already created. The values are then copied to the corresponding unpacked
|
||||
array (flattened to play nice with WebGL's ELEMENT_ARRAY_BUFFER indexing),
|
||||
the group string is added to the hashindices set and the current unpacked
|
||||
index is used as this hashindices value so that the group of elements can
|
||||
be reused. The unpacked index is incremented. If the group string already
|
||||
exists in the hashindices object, its corresponding value is the index of
|
||||
that group and is appended to the unpacked indices array.
|
||||
*/
|
||||
var verts = [], vertNormals = [], textures = [], unpacked = {};
|
||||
// unpacking stuff
|
||||
unpacked.verts = [];
|
||||
unpacked.norms = [];
|
||||
unpacked.textures = [];
|
||||
unpacked.hashindices = {};
|
||||
unpacked.indices = [];
|
||||
unpacked.index = 0;
|
||||
// array of lines separated by the newline
|
||||
var lines = objectData.split('\n');
|
||||
|
||||
var VERTEX_RE = /^v\s/;
|
||||
var NORMAL_RE = /^vn\s/;
|
||||
var TEXTURE_RE = /^vt\s/;
|
||||
var FACE_RE = /^f\s/;
|
||||
var WHITESPACE_RE = /\s+/;
|
||||
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var line = lines[i].trim();
|
||||
var elements = line.split(WHITESPACE_RE);
|
||||
elements.shift();
|
||||
|
||||
if (VERTEX_RE.test(line)) {
|
||||
// if this is a vertex
|
||||
verts.push.apply(verts, elements);
|
||||
} else if (NORMAL_RE.test(line)) {
|
||||
// if this is a vertex normal
|
||||
vertNormals.push.apply(vertNormals, elements);
|
||||
} else if (TEXTURE_RE.test(line)) {
|
||||
// if this is a texture
|
||||
textures.push.apply(textures, elements);
|
||||
} else if (FACE_RE.test(line)) {
|
||||
// if this is a face
|
||||
/*
|
||||
split this face into an array of vertex groups
|
||||
for example:
|
||||
f 16/92/11 14/101/22 1/69/1
|
||||
becomes:
|
||||
['16/92/11', '14/101/22', '1/69/1'];
|
||||
*/
|
||||
var quad = false;
|
||||
for (var j = 0, eleLen = elements.length; j < eleLen; j++){
|
||||
|
||||
// Triangulating quads
|
||||
// quad: 'f v0/t0/vn0 v1/t1/vn1 v2/t2/vn2 v3/t3/vn3/'
|
||||
// corresponding triangles:
|
||||
// 'f v0/t0/vn0 v1/t1/vn1 v2/t2/vn2'
|
||||
// 'f v2/t2/vn2 v3/t3/vn3 v0/t0/vn0'
|
||||
if(j === 3 && !quad) {
|
||||
// add v2/t2/vn2 in again before continuing to 3
|
||||
j = 2;
|
||||
quad = true;
|
||||
}
|
||||
|
||||
if (elements[j] in unpacked.hashindices) {
|
||||
unpacked.indices.push(unpacked.hashindices[elements[j]]);
|
||||
}
|
||||
else {
|
||||
|
||||
//if no slah found in elemnt, it uses another syntax for faces:
|
||||
if ( !/\//.test(elements[ j ]) ) {
|
||||
|
||||
unpacked.indices.push( elements[ j ] );
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
/*
|
||||
Each element of the face line array is a vertex which has its
|
||||
attributes delimited by a forward slash. This will separate
|
||||
each attribute into another array:
|
||||
'19/92/11'
|
||||
becomes:
|
||||
vertex = ['19', '92', '11'];
|
||||
where
|
||||
vertex[0] is the vertex index
|
||||
vertex[1] is the texture index
|
||||
vertex[2] is the normal index
|
||||
Think of faces having Vertices which are comprised of the
|
||||
attributes location (v), texture (vt), and normal (vn).
|
||||
*/
|
||||
var vertex = elements[ j ].split( '/' );
|
||||
/*
|
||||
The verts, textures, and vertNormals arrays each contain a
|
||||
flattend array of coordinates.
|
||||
|
||||
Because it gets confusing by referring to vertex and then
|
||||
vertex (both are different in my descriptions) I will explain
|
||||
what's going on using the vertexNormals array:
|
||||
|
||||
vertex[2] will contain the one-based index of the vertexNormals
|
||||
section (vn). One is subtracted from this index number to play
|
||||
nice with javascript's zero-based array indexing.
|
||||
|
||||
Because vertexNormal is a flattened array of x, y, z values,
|
||||
simple pointer arithmetic is used to skip to the start of the
|
||||
vertexNormal, then the offset is added to get the correct
|
||||
component: +0 is x, +1 is y, +2 is z.
|
||||
|
||||
This same process is repeated for verts and textures.
|
||||
*/
|
||||
// vertex position
|
||||
unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + 0]);
|
||||
unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + 1]);
|
||||
unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + 2]);
|
||||
// vertex textures
|
||||
if (textures.length) {
|
||||
unpacked.textures.push(+textures[(vertex[1] - 1) * 2 + 0]);
|
||||
unpacked.textures.push(+textures[(vertex[1] - 1) * 2 + 1]);
|
||||
}
|
||||
// vertex normals
|
||||
unpacked.norms.push(+vertNormals[(vertex[2] - 1) * 3 + 0]);
|
||||
unpacked.norms.push(+vertNormals[(vertex[2] - 1) * 3 + 1]);
|
||||
unpacked.norms.push(+vertNormals[(vertex[2] - 1) * 3 + 2]);
|
||||
// add the newly created vertex to the list of indices
|
||||
unpacked.hashindices[elements[j]] = unpacked.index;
|
||||
unpacked.indices.push(unpacked.index);
|
||||
// increment the counter
|
||||
unpacked.index += 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if(j === 3 && quad) {
|
||||
// add v0/t0/vn0 onto the second triangle
|
||||
unpacked.indices.push( unpacked.hashindices[elements[0]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.vertices = unpacked.verts;
|
||||
this.vertexNormals = unpacked.norms;
|
||||
this.textures = unpacked.textures;
|
||||
this.indices = unpacked.indices;
|
||||
}
|
||||
|
||||
var Ajax = function(){
|
||||
// this is just a helper class to ease ajax calls
|
||||
var _this = this;
|
||||
this.xmlhttp = new XMLHttpRequest();
|
||||
|
||||
this.get = function(url, callback){
|
||||
_this.xmlhttp.onreadystatechange = function(){
|
||||
if(_this.xmlhttp.readyState === 4){
|
||||
callback(_this.xmlhttp.responseText, _this.xmlhttp.status);
|
||||
}
|
||||
};
|
||||
_this.xmlhttp.open('GET', url, true);
|
||||
_this.xmlhttp.send();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes in an object of `mesh_name`, `'/url/to/OBJ/file'` pairs and a callback
|
||||
* function. Each OBJ file will be ajaxed in and automatically converted to
|
||||
* an OBJ.Mesh. When all files have successfully downloaded the callback
|
||||
* function provided will be called and passed in an object containing
|
||||
* the newly created meshes.
|
||||
*
|
||||
* **Note:** In order to use this function as a way to download meshes, a
|
||||
* webserver of some sort must be used.
|
||||
*
|
||||
* @param {Object} nameAndURLs an object where the key is the name of the mesh and the value is the url to that mesh's OBJ file
|
||||
*
|
||||
* @param {Function} completionCallback should contain a function that will take one parameter: an object array where the keys will be the unique object name and the value will be a Mesh object
|
||||
*
|
||||
* @param {Object} meshes In case other meshes are loaded separately or if a previously declared variable is desired to be used, pass in a (possibly empty) json object of the pattern: { '<mesh_name>': OBJ.Mesh }
|
||||
*
|
||||
*/
|
||||
OBJ.downloadMeshes = function (nameAndURLs, completionCallback, meshes){
|
||||
|
||||
|
||||
|
||||
// the total number of meshes. this is used to implement "blocking"
|
||||
var semaphore = Object.keys(nameAndURLs).length;
|
||||
// if error is true, an alert will given
|
||||
var error = false;
|
||||
// this is used to check if all meshes have been downloaded
|
||||
// if meshes is supplied, then it will be populated, otherwise
|
||||
// a new object is created. this will be passed into the completionCallback
|
||||
if(meshes === undefined) meshes = {};
|
||||
// loop over the mesh_name,url key,value pairs
|
||||
for(var mesh_name in nameAndURLs){
|
||||
if(nameAndURLs.hasOwnProperty(mesh_name)){
|
||||
new Ajax().get(nameAndURLs[mesh_name], (function(name) {
|
||||
return function (data, status) {
|
||||
if (status === 200) {
|
||||
meshes[name] = new OBJ.Mesh(data);
|
||||
}
|
||||
else {
|
||||
error = true;
|
||||
console.error('An error has occurred and the mesh "' +
|
||||
nameAndURLs + '" could not be downloaded.');
|
||||
}
|
||||
// the request has finished, decrement the counter
|
||||
semaphore--;
|
||||
if (semaphore === 0) {
|
||||
if (error) {
|
||||
// if an error has occurred, the user is notified here and the
|
||||
// callback is not called
|
||||
console.error('An error has occurred and one or meshes has not been ' +
|
||||
'downloaded. The execution of the script has terminated.');
|
||||
throw '';
|
||||
}
|
||||
// there haven't been any errors in retrieving the meshes
|
||||
// call the callback
|
||||
completionCallback(meshes);
|
||||
}
|
||||
}
|
||||
})(mesh_name));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var _buildBuffer = function( gl, type, data, itemSize ){
|
||||
var buffer = gl.createBuffer();
|
||||
var arrayView = type === gl.ARRAY_BUFFER ? Float32Array : Uint16Array;
|
||||
gl.bindBuffer(type, buffer);
|
||||
gl.bufferData(type, new arrayView(data), gl.STATIC_DRAW);
|
||||
buffer.itemSize = itemSize;
|
||||
buffer.numItems = data.length / itemSize;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in the WebGL context and a Mesh, then creates and appends the buffers
|
||||
* to the mesh object as attributes.
|
||||
*
|
||||
* @param {WebGLRenderingContext} gl the `canvas.getContext('webgl')` context instance
|
||||
* @param {Mesh} mesh a single `OBJ.Mesh` instance
|
||||
*
|
||||
* The newly created mesh attributes are:
|
||||
*
|
||||
* Attrbute | Description
|
||||
* :--- | ---
|
||||
* **normalBuffer** |contains the model's Vertex Normals
|
||||
* normalBuffer.itemSize |set to 3 items
|
||||
* normalBuffer.numItems |the total number of vertex normals
|
||||
* |
|
||||
* **textureBuffer** |contains the model's Texture Coordinates
|
||||
* textureBuffer.itemSize |set to 2 items
|
||||
* textureBuffer.numItems |the number of texture coordinates
|
||||
* |
|
||||
* **vertexBuffer** |contains the model's Vertex Position Coordinates (does not include w)
|
||||
* vertexBuffer.itemSize |set to 3 items
|
||||
* vertexBuffer.numItems |the total number of vertices
|
||||
* |
|
||||
* **indexBuffer** |contains the indices of the faces
|
||||
* indexBuffer.itemSize |is set to 1
|
||||
* indexBuffer.numItems |the total number of indices
|
||||
*
|
||||
* A simple example (a lot of steps are missing, so don't copy and paste):
|
||||
*
|
||||
* var gl = canvas.getContext('webgl'),
|
||||
* mesh = OBJ.Mesh(obj_file_data);
|
||||
* // compile the shaders and create a shader program
|
||||
* var shaderProgram = gl.createProgram();
|
||||
* // compilation stuff here
|
||||
* ...
|
||||
* // make sure you have vertex, vertex normal, and texture coordinate
|
||||
* // attributes located in your shaders and attach them to the shader program
|
||||
* shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
|
||||
* gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
|
||||
*
|
||||
* shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
|
||||
* gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);
|
||||
*
|
||||
* shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
|
||||
* gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
|
||||
*
|
||||
* // create and initialize the vertex, vertex normal, and texture coordinate buffers
|
||||
* // and save on to the mesh object
|
||||
* OBJ.initMeshBuffers(gl, mesh);
|
||||
*
|
||||
* // now to render the mesh
|
||||
* gl.bindBuffer(gl.ARRAY_BUFFER, mesh.vertexBuffer);
|
||||
* gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, mesh.vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
*
|
||||
* gl.bindBuffer(gl.ARRAY_BUFFER, mesh.textureBuffer);
|
||||
* gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, mesh.textureBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
*
|
||||
* gl.bindBuffer(gl.ARRAY_BUFFER, mesh.normalBuffer);
|
||||
* gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, mesh.normalBuffer.itemSize, gl.FLOAT, false, 0, 0);
|
||||
*
|
||||
* gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.mesh.indexBuffer);
|
||||
* gl.drawElements(gl.TRIANGLES, model.mesh.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
|
||||
*/
|
||||
OBJ.initMeshBuffers = function( gl, mesh ){
|
||||
mesh.normalBuffer = _buildBuffer(gl, gl.ARRAY_BUFFER, mesh.vertexNormals, 3);
|
||||
mesh.textureBuffer = _buildBuffer(gl, gl.ARRAY_BUFFER, mesh.textures, 2);
|
||||
mesh.vertexBuffer = _buildBuffer(gl, gl.ARRAY_BUFFER, mesh.vertices, 3);
|
||||
mesh.indexBuffer = _buildBuffer(gl, gl.ELEMENT_ARRAY_BUFFER, mesh.indices, 1);
|
||||
}
|
||||
|
||||
OBJ.deleteMeshBuffers = function( gl, mesh ){
|
||||
gl.deleteBuffer(mesh.normalBuffer);
|
||||
gl.deleteBuffer(mesh.textureBuffer);
|
||||
gl.deleteBuffer(mesh.vertexBuffer);
|
||||
gl.deleteBuffer(mesh.indexBuffer);
|
||||
}
|
||||
|
||||
export default OBJ;
|
||||
|
||||
@@ -54,7 +54,6 @@ void main(void) {
|
||||
outColor = diffuseColor * vec3(NdotL) + diffuseColor * ambient * (1.-NdotL);
|
||||
|
||||
|
||||
// outColor = pow(outColor, vec3(1.0 / 2.2));
|
||||
gl_FragColor = vec4( outColor, 1. );
|
||||
}
|
||||
`
|
||||
|
||||
@@ -9,6 +9,7 @@ uniform mat4 uMVMatrix;
|
||||
uniform mat4 uMMatrix;
|
||||
uniform mat4 uPMatrix;
|
||||
uniform mat4 uNormalMatrix;
|
||||
uniform float uCameraOffsetY;
|
||||
|
||||
varying vec2 vUv;
|
||||
varying vec3 vNormal;
|
||||
@@ -16,8 +17,10 @@ varying vec3 vPos;
|
||||
|
||||
void main(void) {
|
||||
vUv = uv;
|
||||
vNormal = (vec4(normal, 0.) * uNormalMatrix).rgb;
|
||||
vPos = (vec4(vPos, 1.) * uMMatrix).rgb;
|
||||
vNormal = (uNormalMatrix * vec4(normal, 1.)).rgb;
|
||||
vPos = (uMMatrix * vec4(position, 1.)).rgb;
|
||||
gl_Position = uPMatrix * uMVMatrix * vec4( position, 1.0 );
|
||||
|
||||
gl_Position[1] += uCameraOffsetY * gl_Position.w;
|
||||
}
|
||||
`
|
||||
@@ -1,22 +1,15 @@
|
||||
import { Renderer } from './beam'
|
||||
import { Camera } from './beam'
|
||||
import { vec2, vec3, mat4 } from './beam'
|
||||
import { Container, Mesh, Material, Texture, SphereGeometryBuffer } from './beam'
|
||||
import settings from './settings'
|
||||
import { Container, Mesh, Material, Texture, SphereGeometryBuffer, PlaneGeometryBuffer } from './beam'
|
||||
|
||||
// Shaders in strings
|
||||
// GLSL shaders as strings
|
||||
import GlobeVS from './globe-vs'
|
||||
import GlobeFS from './globe-fs'
|
||||
|
||||
const hexToRgb = hex => {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
|
||||
return result ? [
|
||||
parseInt(result[1], 16) / 255,
|
||||
parseInt(result[2], 16) / 255,
|
||||
parseInt(result[3], 16) / 255
|
||||
] : [0,0,0]
|
||||
}
|
||||
const FOV = 1;
|
||||
|
||||
/** get 3D position on a sphere from longitute lattitude */
|
||||
const lonLatToVector3 = (lng, lat) => {
|
||||
const phi = (90 - lat) * (Math.PI / 180)
|
||||
const theta = (lng + 180) * (Math.PI / 180)
|
||||
@@ -27,19 +20,20 @@ const lonLatToVector3 = (lng, lat) => {
|
||||
}
|
||||
|
||||
class WebglGlobe {
|
||||
|
||||
// Constructor
|
||||
constructor (options) {
|
||||
// Camera position cache
|
||||
this.cameraX = 0
|
||||
this.cameraY = 0
|
||||
this.cameraZ = 0
|
||||
|
||||
this.options = options
|
||||
|
||||
this.$el = options.el//the Dom reference node
|
||||
this.options = options
|
||||
this.options.autoRotationSpeed = this.options.autoRotationSpeed || 0
|
||||
this.options.scrollSmoothing = this.options.scrollSmoothing || 0.5 // smooth the globe position to avoid janks on scroll(lower==smoother)
|
||||
this.options.cameraDistance = this.options.cameraDistance || 1 //a multiplier to move camera backward or forward
|
||||
this.referenceHeight = 1;//used to set camera distance from globe where referenceHeight == window height
|
||||
this._canUpdate = false
|
||||
|
||||
this.cities = options.markers//list of cities with their options
|
||||
|
||||
this.$el = options.el
|
||||
this.cities = options.markers
|
||||
let gl
|
||||
let canvas = document.createElement('canvas')
|
||||
try { gl = canvas.getContext('webgl') }
|
||||
@@ -51,21 +45,44 @@ class WebglGlobe {
|
||||
if (this.supportWebgl) {
|
||||
this.buildWebglScene()
|
||||
this.resize()
|
||||
// this.initPointer()
|
||||
}
|
||||
}
|
||||
|
||||
// Build
|
||||
buildWebglScene () {
|
||||
this.renderer = new Renderer({
|
||||
alpha: this.alpha,
|
||||
antialias: window.innerWidth < 768 ? true : false,// this.antialias,
|
||||
})
|
||||
this.$el.appendChild(this.renderer.canvas)
|
||||
|
||||
// Load texture
|
||||
this.renderer = new Renderer({
|
||||
//to allow transparent background on webgl canvas
|
||||
alpha: true,
|
||||
//only enable antialiasing if screen is small with no retina(for performances reasons)
|
||||
antialias: window.innerWidth < 768 || !window.devicePixelRatio == 1 ? true : false,
|
||||
})
|
||||
|
||||
// we put the canvas at the end of body tag as 'position:fixed'
|
||||
// this is to avoid having a too big canvas if the globe needs to be very large:
|
||||
// so instead we move the globe as we scroll
|
||||
this.renderer.canvas.style.position = 'fixed'
|
||||
this.renderer.canvas.style.top = 0
|
||||
this.renderer.canvas.style.left = 0
|
||||
this.renderer.canvas.style.pointerEvents = 'none'
|
||||
this.renderer.canvas.style.zIndex = 100
|
||||
document.body.appendChild(this.renderer.canvas)
|
||||
|
||||
// The markers DOM nodes wrapper
|
||||
// this wrapper is added just next to the canvas, at the end of body tag
|
||||
this.$markerWrapper = document.createElement('div')
|
||||
this.$markerWrapper.classList.add('markerWrapper')
|
||||
this.$markerWrapper.style.position = 'fixed'
|
||||
this.$markerWrapper.style.top = 0
|
||||
this.$markerWrapper.style.left = 0
|
||||
this.$markerWrapper.style.pointerEvents = 'none'
|
||||
this.$markerWrapper.style.zIndex = 101
|
||||
document.body.appendChild(this.$markerWrapper)
|
||||
|
||||
// Load worldmap texture
|
||||
this.texture = Texture.fromUrl(this.renderer.gl, this.options.texture, {
|
||||
loaded: () => {
|
||||
//TODO: use only one RAF if possible
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
this.imageLoaded = true
|
||||
@@ -78,64 +95,67 @@ class WebglGlobe {
|
||||
|
||||
// Setup camera
|
||||
this.camera = new Camera({
|
||||
fov: settings.fov,
|
||||
near: 1,
|
||||
far: settings.cameraFar,
|
||||
fov: 1,
|
||||
near: 0.1,
|
||||
far: 1000,
|
||||
type: 'perspective',
|
||||
orbitControl: true,
|
||||
firstPerson: false,
|
||||
lookAt: [0,0,0],
|
||||
position: [0,0, (this.options.cameraDistance) / 2 / Math.tan(Math.PI * settings.fov / 360)],
|
||||
position: [0,0,0],
|
||||
pointerParent: this.$el
|
||||
})
|
||||
this.camera.lookAt = vec3.create()
|
||||
this.inverseViewProjectionMatrix = mat4.create()
|
||||
|
||||
/**
|
||||
* used to compute screen position of markers,
|
||||
* to move the corresponding DOM nodes
|
||||
*/
|
||||
this.viewProjectionMatrix = mat4.create()
|
||||
this.cameraDirection = vec3.create()
|
||||
this.cameraPosition = vec3.create()
|
||||
|
||||
this.globeMesh = new Mesh()
|
||||
this.globeMesh.material = new Material(this.renderer.gl, {
|
||||
uniforms: {
|
||||
tInput: this.texture
|
||||
tInput: this.texture,
|
||||
uCameraOffsetY: 0,
|
||||
},
|
||||
vertexShader: GlobeVS,
|
||||
fragmentShader: GlobeFS,
|
||||
// depthTest: true
|
||||
})
|
||||
this.globeMesh.geometry = new SphereGeometryBuffer(this.renderer.gl, {
|
||||
radius: 1,
|
||||
radius: this.referenceHeight/2,
|
||||
widthSegments: 100, heightSegments: 100
|
||||
})
|
||||
this.scene.add(this.globeMesh)
|
||||
|
||||
|
||||
// this.refPlane = new Mesh()
|
||||
// this.refPlane.material = new Material(this.renderer.gl, {
|
||||
// uniforms: {
|
||||
// color: [0,1,0]
|
||||
// }
|
||||
// })
|
||||
// this.refPlane.geometry = new PlaneGeometryBuffer(this.renderer.gl, {
|
||||
// width: this.referenceHeight, height: this.referenceHeight
|
||||
// })
|
||||
// this.scene.add(this.refPlane)
|
||||
|
||||
|
||||
/**
|
||||
* Create DOM nodes for markers and 3D positions
|
||||
*/
|
||||
this.markers = []
|
||||
let markers = this.cities
|
||||
|
||||
// Instance all markers
|
||||
for (let i = 0; i < markers.length; i++) {
|
||||
let markerMesh = new Mesh();
|
||||
markerMesh.material = new Material(this.renderer.gl, {
|
||||
blend: true,
|
||||
uniforms: {
|
||||
color: hexToRgb('#FF6C89'),
|
||||
alpha: 0,
|
||||
}
|
||||
})
|
||||
markerMesh.geometry = new SphereGeometryBuffer(this.renderer.gl, {
|
||||
radius: 0.01,
|
||||
widthSegments: 10, heightSegments: 10
|
||||
})
|
||||
|
||||
// Position marker
|
||||
let p = lonLatToVector3(markers[i].lng, markers[i].lat)
|
||||
markerMesh.position[0] = p[0]
|
||||
markerMesh.position[1] = p[1]
|
||||
markerMesh.position[2] = p[2]
|
||||
this.scene.add(markerMesh)
|
||||
|
||||
// Wrap marker in link
|
||||
let el = document.createElement('a')
|
||||
el.style.pointerEvents = 'auto'
|
||||
el.setAttribute('href', '/location/' + markers[i].countrySlug + '/' + markers[i].slug)
|
||||
el.setAttribute('sapper-noscroll', '')
|
||||
if (markers[i].className) el.classList.add( markers[i].className )
|
||||
@@ -170,9 +190,9 @@ class WebglGlobe {
|
||||
el.addEventListener('animationend', () => el.classList.remove('hover'))
|
||||
|
||||
// Append marker to HTML
|
||||
this.$el.appendChild(el)
|
||||
this.$markerWrapper.appendChild(el)
|
||||
|
||||
this.markers.push({
|
||||
mesh: markerMesh,
|
||||
el: el,
|
||||
position: p,
|
||||
screenPosition: [0,0]
|
||||
@@ -182,117 +202,99 @@ class WebglGlobe {
|
||||
|
||||
// Resize method
|
||||
resize () {
|
||||
this.width = this.$el.clientWidth
|
||||
this.height = this.$el.clientHeight
|
||||
|
||||
// console.log('GLOBE RESIZE', this.width, this.height)
|
||||
|
||||
settings.resolution[0] = this.width //* settings.devicePixelRatio
|
||||
settings.resolution[1] = this.height //* settings.devicePixelRatio
|
||||
if (!this.supportWebgl) {
|
||||
return
|
||||
}
|
||||
this.renderer.setPixelRatio(1)//window.innerWidth < 768 ? 1 : settings.devicePixelRatio)
|
||||
this.renderer.resize(settings.resolution[0], settings.resolution[1])
|
||||
this.camera.aspect = settings.resolution[0] / settings.resolution[1]
|
||||
|
||||
this.width = window ? window.innerWidth : 0
|
||||
this.height = window ? window.innerHeight : 0
|
||||
|
||||
//remove retina on small screen(aka mobile) to boost perfs
|
||||
this.renderer.setPixelRatio( window.innerWidth < 768 ? 1 : window.devicePixelRatio)
|
||||
this.renderer.resize(this.width , this.height)
|
||||
|
||||
//update camera aspect ratio
|
||||
this.camera.aspect = this.width / this.height
|
||||
this.camera.updateProjectionMatrix()
|
||||
|
||||
this.camera.lookAt[0] = 0
|
||||
this.camera.lookAt[1] = 0
|
||||
this.camera.lookAt[2] = 0
|
||||
this.camera.rotation[0] = 0
|
||||
this.camera.rotation[1] = 0
|
||||
this.camera.rotation[2] = 0
|
||||
this.camera.position[0] = 0
|
||||
this.camera.position[1] = 0
|
||||
this.camera.position[2] = (3) / 2 / Math.tan(Math.PI * settings.fov / 360)
|
||||
this.camera.render()
|
||||
//at which distance to put the camera when rotating arounf the globe
|
||||
this.camera._cameraDistance = (this.referenceHeight * this.options.cameraDistance) / 2 / Math.tan(Math.PI * FOV / 360);
|
||||
this.camera.update(true)
|
||||
|
||||
vec3.set(this.cameraPosition, this.camera.worldMatrix[12], this.camera.worldMatrix[13], this.camera.worldMatrix[14])
|
||||
vec3.copy(this.cameraDirection, this.camera.lookAt)
|
||||
vec3.subtract(this.cameraDirection, this.cameraDirection, this.cameraPosition)
|
||||
vec3.normalize(this.cameraDirection, this.cameraDirection)
|
||||
mat4.copy(this.viewProjectionMatrix, this.camera.projectionMatrix)
|
||||
mat4.multiply(this.viewProjectionMatrix, this.viewProjectionMatrix, this.camera.inverseWorldMatrix)
|
||||
/**
|
||||
* When markers are behind the globe, clamp their position
|
||||
* to this size to make them move along the circle edge
|
||||
*/
|
||||
this.circleScreenSize = (this.height / 2) * (1 / this.options.cameraDistance);
|
||||
}
|
||||
|
||||
let refPos = vec3.create()
|
||||
vec3.set(refPos, 0, 1, 0)
|
||||
vec3.transformMat4(refPos, refPos, this.viewProjectionMatrix)
|
||||
let refx = ((refPos[0] + 1) / 2) * this.width
|
||||
let refy = (1. - (refPos[1] + 1) / 2) * this.height
|
||||
/**
|
||||
* As the camera rotates arount the globe, we cant simply move the Y position of the camera or the globe
|
||||
* Instead, we move the globe vertex inside the vertex shadder after compute the project on screen, so we pass the 'scroll' position to a uniform
|
||||
*/
|
||||
updateCameraPos(y) {
|
||||
y *= 2;
|
||||
if (this.globeMesh.material.uniforms.uCameraOffsetY) {
|
||||
this.globeMesh.material.uniforms.uCameraOffsetY.value += ( y - this.globeMesh.material.uniforms.uCameraOffsetY.value ) * this.options.scrollSmoothing
|
||||
}
|
||||
}
|
||||
|
||||
let dir2 = vec2.create()
|
||||
vec2.set(dir2, refx, refy)
|
||||
let center2 = vec2.create()
|
||||
vec2.set(center2, this.width / 2, this.height / 2)
|
||||
let dir2d2 = vec2.clone(dir2, dir2)
|
||||
vec2.subtract(dir2d2, dir2d2, center2)
|
||||
this.circleScreenSize = vec2.length(dir2d2) * 1.04
|
||||
/**
|
||||
* Flag to stop rendering the webgl if the globe isnt visible
|
||||
* This helps saving perfs and battery
|
||||
*/
|
||||
enable() {
|
||||
this._canUpdate = true
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._canUpdate = false
|
||||
}
|
||||
|
||||
// Update
|
||||
update () {
|
||||
|
||||
|
||||
if (!this.supportWebgl) {
|
||||
if (!this.supportWebgl || !this._canUpdate || !this.imageLoaded) {
|
||||
return
|
||||
}
|
||||
|
||||
// Manually call this as we prevent the camera from update between passes
|
||||
//compute the camera view-projection matrix to use it on the markers
|
||||
this.camera.update()
|
||||
vec3.set(this.cameraPosition, this.camera.worldMatrix[12], this.camera.worldMatrix[13], this.camera.worldMatrix[14])
|
||||
vec3.copy(this.cameraDirection, this.camera.lookAt)
|
||||
vec3.subtract(this.cameraDirection, this.cameraDirection, this.cameraPosition)
|
||||
vec3.normalize(this.cameraDirection, this.cameraDirection)
|
||||
mat4.copy(this.viewProjectionMatrix, this.camera.projectionMatrix)
|
||||
mat4.multiply(this.viewProjectionMatrix, this.viewProjectionMatrix, this.camera.inverseWorldMatrix)
|
||||
mat4.invert(this.inverseViewProjectionMatrix, this.viewProjectionMatrix)
|
||||
|
||||
// let needsUpdate = false
|
||||
// if (this.cameraX != this.camera.worldMatrix[12] ||
|
||||
// this.cameraY != this.camera.worldMatrix[13] ||
|
||||
// this.cameraZ != this.camera.worldMatrix[14]
|
||||
// ) {
|
||||
// this.cameraX = this.camera.worldMatrix[12]
|
||||
// this.cameraY = this.camera.worldMatrix[13]
|
||||
// this.cameraZ = this.camera.worldMatrix[14]
|
||||
// needsUpdate = true
|
||||
// }
|
||||
let needsUpdate = true;
|
||||
//Auto rotate the globe
|
||||
this.globeMesh.rotation[1] = this.options.autoRotationSpeed
|
||||
this.globeMesh.updateMatrix()
|
||||
this.globeMesh.updateWorldMatrix()
|
||||
|
||||
|
||||
if (!needsUpdate && this.imageLoaded) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
this.globeMesh.rotation[0] = 0
|
||||
this.globeMesh.rotation[1] += this.options.autoRotationSpeed;
|
||||
this.globeMesh.rotation[2] = 0
|
||||
|
||||
let screenPos = vec3.create()
|
||||
let screenPos = vec3.create()
|
||||
this.markers.forEach((marker, i) => {
|
||||
|
||||
//get marker 3D position and project it on screen to get 2D position
|
||||
vec3.set(screenPos, marker.position[0], marker.position[1], marker.position[2])
|
||||
|
||||
vec3.transformMat4(screenPos, screenPos, this.globeMesh.worldMatrix)
|
||||
|
||||
vec3.transformMat4(screenPos, screenPos, this.viewProjectionMatrix)
|
||||
|
||||
//marker 2D screen position (starting from top left corner of screen)
|
||||
let x = ((screenPos[0] + 1) / 2) * this.width
|
||||
let y = (1. - (screenPos[1] + 1) / 2) * this.height
|
||||
|
||||
//compute marker Normal
|
||||
let N = vec3.create()
|
||||
vec3.set(N, marker.position[0], marker.position[1], marker.position[2])
|
||||
vec3.transformMat4(N, N, this.globeMesh.worldMatrix)
|
||||
vec3.normalize(N, N)
|
||||
|
||||
//compute view vector (camera direction)
|
||||
let V = vec3.create()
|
||||
vec3.set(V, marker.position[0], marker.position[1], marker.position[2])
|
||||
vec3.subtract(V, V, this.cameraPosition)
|
||||
vec3.normalize(V, V)
|
||||
|
||||
//behind
|
||||
//the marker is behind the globe: clamp it to the globe edge
|
||||
if (vec3.dot(V, N) * -1 < 0) {
|
||||
let dir = vec2.create()
|
||||
vec2.set(dir, x, y)
|
||||
@@ -306,15 +308,15 @@ class WebglGlobe {
|
||||
marker.el.style.transform = `translate(${dir2d[0]}px, ${dir2d[1]}px) translateZ(0)`
|
||||
marker.el.classList.remove('is-active')
|
||||
}
|
||||
//marker is in front of the globe; update 2D position
|
||||
else {
|
||||
//vec3.dot(V, N) * -1 < 0 ? (1 - vec3.dot(V, N) / 0.1) : 1;//Math.max(0, vec3.dot(N, V));
|
||||
marker.el.style.transform = `translate(${x}px, ${y}px) translateZ(0)`
|
||||
marker.el.classList.add('is-active')
|
||||
}
|
||||
// marker.el.style.opacity = 1.
|
||||
})
|
||||
|
||||
this.renderer.clearColor(0,0,0,0)
|
||||
//render webgl frame
|
||||
this.renderer.clearColor(0,0,0,0)//[RGBA] alpha is set to 0 to have a transparent background on the webgl
|
||||
this.renderer.clear()
|
||||
this.renderer.render(this.scene, this.camera)
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
var params = {
|
||||
debug: true,
|
||||
fov: 45,
|
||||
devicePixelRatio: window.devicePixelRatio,
|
||||
resolution: [window.innerWidth, window.innerHeight],
|
||||
focalLength: 2.415,
|
||||
cameraFar: 1000,
|
||||
gammaCorrection: true,
|
||||
}
|
||||
|
||||
|
||||
export default params;
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
var support = {};
|
||||
|
||||
var tests = {
|
||||
touch: function () {
|
||||
return 'ontouchstart' in window || /*|| (navigator.maxTouchPoints > 0)*/navigator.msMaxTouchPoints > 0;
|
||||
},
|
||||
//IE10 Pointers
|
||||
msPointer: function () {
|
||||
return !!window.navigator.msPointerEnabled;
|
||||
},
|
||||
//IE11 Pointers
|
||||
pointer: function () {
|
||||
return !!window.navigator.pointerEnabled;
|
||||
},
|
||||
pointerdown: function () {
|
||||
return this.touch() ? 'touchstart' : this.pointer() ? 'pointerdown' : this.msPointer() ? 'MSPointerDown' : 'mousedown';
|
||||
},
|
||||
pointerup: function () {
|
||||
return this.touch() ? 'touchend' : this.pointer() ? 'pointerup' : this.msPointer() ? 'MSPointerUp' : 'mouseup';
|
||||
},
|
||||
pointermove: function () {
|
||||
return this.touch() ? 'touchmove' : this.pointer() ? 'pointermove' : this.msPointer() ? 'MSPointerMove' : 'mousemove';
|
||||
},
|
||||
pointerenter: function () {
|
||||
return this.touch() ? 'touchstart' : this.pointer() ? 'pointerenter' : this.msPointer() ? 'MSPointerEnter' : 'mouseenter';
|
||||
},
|
||||
pointerleave: function () {
|
||||
return this.touch() ? 'touchend' : this.pointer() ? 'pointerleave' : this.msPointer() ? 'MSPointerLeave' : 'mouseleave';
|
||||
},
|
||||
pointerover: function () {
|
||||
return this.touch() ? 'touchstart' : this.pointer() ? 'pointerover' : this.msPointer() ? 'MSPointerOver' : 'mouseover';
|
||||
},
|
||||
pointerout: function () {
|
||||
return this.touch() ? 'touchend' : this.pointer() ? 'pointerout' : this.msPointer() ? 'MSPointerOut' : 'mouseout';
|
||||
}
|
||||
};
|
||||
|
||||
var featureName;
|
||||
for (var feature in tests) {
|
||||
if (tests.hasOwnProperty(feature)) {
|
||||
featureName = feature;
|
||||
support[featureName] = tests[feature]();
|
||||
}
|
||||
}
|
||||
|
||||
export default support
|
||||
@@ -1,14 +1,38 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import { locations } from 'utils/store'
|
||||
import ScrollOut from 'scroll-out'
|
||||
|
||||
function getPosition (node, scope) {
|
||||
var root = scope || document;
|
||||
var offsetTop = node.offsetTop;
|
||||
var offsetLeft = node.offsetLeft;
|
||||
while (node && node.offsetParent && node.offsetParent != document && node !== root && root !== node.offsetParent ) {
|
||||
offsetTop += node.offsetParent.offsetTop;
|
||||
offsetLeft += node.offsetParent.offsetLeft;
|
||||
node = node.offsetParent;
|
||||
}
|
||||
return {
|
||||
top: offsetTop,
|
||||
left: offsetLeft
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Props
|
||||
export let type = ''
|
||||
// export let type = ''
|
||||
let scope
|
||||
let globe
|
||||
let containerTop = 0
|
||||
let containerHeight = 0
|
||||
let winHeight = window ? window.innerHeight : 0
|
||||
|
||||
// Functions
|
||||
const resize = () => {
|
||||
winHeight = window ? window.innerHeight : 0
|
||||
if (scope) {
|
||||
containerTop = getPosition( scope ).top
|
||||
containerHeight = scope.clientHeight
|
||||
}
|
||||
globe.resize()
|
||||
globe.update()
|
||||
}
|
||||
@@ -17,22 +41,41 @@
|
||||
globe.update()
|
||||
}
|
||||
|
||||
const onScroll = (e)=> {
|
||||
let scrollDiff = (containerTop + window.innerHeight + (containerHeight - window.innerHeight) /2 ) - document.documentElement.scrollTop
|
||||
let scrollRatio = 1 - ( scrollDiff / window.innerHeight )
|
||||
|
||||
globe && globe.updateCameraPos( scrollRatio )
|
||||
}
|
||||
/*
|
||||
** Run code when mounted
|
||||
*/
|
||||
onMount(async () => {
|
||||
// For browser only
|
||||
|
||||
const globeScroll = ScrollOut({
|
||||
once: false,
|
||||
targets: scope,
|
||||
// threshold: 1,
|
||||
onShown: () => {
|
||||
globe.enable()
|
||||
},
|
||||
onHidden: () => {
|
||||
globe.disable()
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
let InteractiveGlobe
|
||||
if (process.browser) {
|
||||
// Import libraries and code
|
||||
let Globe
|
||||
await import('globe').then(module => Globe = module.default)
|
||||
|
||||
await import('globe/index').then(module => InteractiveGlobe = module.default)
|
||||
// Init the globe from library
|
||||
globe = new Globe({
|
||||
globe = new InteractiveGlobe({
|
||||
el: scope,
|
||||
cameraDistance: 1.5,
|
||||
autoRotationSpeed: -0.01,
|
||||
texture: `/img/globe/map-${window.innerWidth >= 992 ? '4k' : '2k'}.png`,
|
||||
scrollSmoothing: 0.5,
|
||||
texture: `/img/globe/map-${window.innerWidth > 1440 && window.devicePixelRatio > 1 ? '4k' : '2k'}.png`,
|
||||
markers: [...$locations.map(location => {
|
||||
return {
|
||||
name: location.name,
|
||||
@@ -44,7 +87,6 @@
|
||||
className: location.slug === 'marseille' ? 'is-left' : '',
|
||||
}
|
||||
})],
|
||||
cameraDistance: 3,
|
||||
onLinkClicked: () => {}
|
||||
})
|
||||
|
||||
@@ -55,12 +97,14 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<svelte:window on:resize={resize} />
|
||||
<svelte:window on:resize={resize} on:scroll={onScroll} />
|
||||
|
||||
{#if type === 'part'}
|
||||
<!-- {#if type === 'part'}
|
||||
<div class="globe__cut">
|
||||
<div class="globe" bind:this={scope} />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="globe" bind:this={scope} />
|
||||
{/if}
|
||||
{/if} -->
|
||||
|
||||
<div class="globe" bind:this={scope} />
|
||||
@@ -8,7 +8,6 @@
|
||||
// Props and variables
|
||||
export let photo
|
||||
export let index
|
||||
export let layout = 'list'
|
||||
let scope
|
||||
|
||||
// Default size for the image
|
||||
@@ -54,10 +53,10 @@
|
||||
<source media="(min-width: 768px)" data-srcset={getThumbnail(private_hash, 992)}>
|
||||
<source media="(min-width: 500px)" data-srcset={getThumbnail(private_hash, 650)}>
|
||||
<source media="(min-width: 300px)" data-srcset={getThumbnail(private_hash, 400)}>
|
||||
<img src={getThumbnail(private_hash, 900)}
|
||||
<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="
|
||||
width={defaultWidth} height={defaultHeight}
|
||||
alt={imgAlt}
|
||||
class:lazyload={layout === 'list'}
|
||||
class="lazyload"
|
||||
/>
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
import { getThumbnail, formatDate } from 'utils/functions'
|
||||
// Dependencies
|
||||
import SwipeListener from 'swipe-listener'
|
||||
import lazySizes from 'lazysizes'
|
||||
// Animations
|
||||
import { animateIn } from 'animations/Carousel'
|
||||
// Components
|
||||
@@ -159,7 +158,7 @@
|
||||
<source media="(min-width: 800px)" data-srcset={getThumbnail(image.private_hash, 900)}>
|
||||
<source media="(min-width: 500px)" data-srcset={getThumbnail(image.private_hash, 600)}>
|
||||
<source media="(min-width: 300px)" data-srcset={getThumbnail(image.private_hash, 400)}>
|
||||
<img src={getThumbnail(image.private_hash, 900)}
|
||||
<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="
|
||||
alt="{name}, {location.name}, {location.country.name}"
|
||||
width={defaultWidth} height={defaultHeight}
|
||||
class:lazyload={
|
||||
|
||||
@@ -26,22 +26,24 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<section class="page">
|
||||
<div class="wrap">
|
||||
<div class="page__top">
|
||||
<a href="/" class="button-control button-control--pink dir-left">
|
||||
<IconArrow direction="left" color="#fff" class="icon" />
|
||||
<IconArrow direction="left" color="#fff" class="icon" hidden="true" />
|
||||
</a>
|
||||
<main class="housesof" class:is-transitioning={!$pageReady}>
|
||||
<section class="page">
|
||||
<div class="wrap">
|
||||
<div class="page__top">
|
||||
<a href="/" class="button-control button-control--pink dir-left">
|
||||
<IconArrow direction="left" color="#fff" class="icon" />
|
||||
<IconArrow direction="left" color="#fff" class="icon" hidden="true" />
|
||||
</a>
|
||||
|
||||
<TitleSite />
|
||||
<TitleSite />
|
||||
</div>
|
||||
|
||||
<div class="page__description style-description">
|
||||
<p>Oh no… Looks like something wrong just happened. Like a nasty error {status}.</p>
|
||||
<Button href="/" class="button" text="Go back to homepage" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page__description style-description">
|
||||
<p>Oh no… Looks like something wrong just happened. Like a nasty error {status}.</p>
|
||||
<Button href="/" class="button" text="Go back to homepage" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</section>
|
||||
<Footer />
|
||||
</section>
|
||||
</main>
|
||||
@@ -63,7 +63,6 @@
|
||||
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import { fade } from 'svelte/transition'
|
||||
import { stores } from '@sapper/app'
|
||||
import {
|
||||
apiEndpoints,
|
||||
@@ -73,17 +72,44 @@
|
||||
locations,
|
||||
pageReady
|
||||
} from 'utils/store'
|
||||
// Dependencies
|
||||
import lazySizes from 'lazysizes'
|
||||
// Components
|
||||
import AnalyticsTracker from 'utils/AnalyticsTracker'
|
||||
import Transition from 'utils/Transition'
|
||||
|
||||
// Variables
|
||||
const { page } = stores()
|
||||
let AnalyticsTracker
|
||||
|
||||
// Settings
|
||||
lazySizes.cfg.lazyClass = 'lazyload'
|
||||
|
||||
/*
|
||||
** Head stuff
|
||||
*/
|
||||
// Preconnect
|
||||
const preconnect = [
|
||||
'https://api.housesof.world',
|
||||
'https://www.googletagmanager.com',
|
||||
'https://stats.g.doubleclick.net',
|
||||
'https://www.google-analytics.com',
|
||||
]
|
||||
// Preload assets
|
||||
const preload = {
|
||||
fonts: [
|
||||
'/fonts/G-Light.woff2',
|
||||
'/fonts/G-Regular.woff2',
|
||||
'/fonts/G-Semibold.woff2',
|
||||
'/fonts/M-Extralight.woff2',
|
||||
'/fonts/M-Light.woff2',
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Manipulate data
|
||||
*/
|
||||
if ($countries) {
|
||||
if ($countries) {
|
||||
// Replace each countrie's continent by the database
|
||||
$countries.forEach(count => count.continent = $continents.find(cont => cont.id === count.continent.id))
|
||||
|
||||
@@ -101,12 +127,6 @@
|
||||
if ($locations) {
|
||||
$locations.forEach(loc => loc.country = $countries.find(cont => cont.id === loc.country.id))
|
||||
}
|
||||
|
||||
|
||||
onMount(async () => {
|
||||
const gaTracker = await import('utils/AnalyticsTracker')
|
||||
AnalyticsTracker = gaTracker.default
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" global>
|
||||
@@ -115,14 +135,17 @@
|
||||
|
||||
<svelte:head>
|
||||
<link rel="canonical" href={`https://${$page.host}${$page.path}`} />
|
||||
{#each preconnect as host}
|
||||
<link rel="preconnect" href={host} crossorigin>
|
||||
<link rel="dns-prefetch" href={host}>
|
||||
{/each}
|
||||
{#each preload.fonts as font}
|
||||
<link rel="preload" href={font} as="font" type="font/woff2" crossorigin>
|
||||
{/each}
|
||||
</svelte:head>
|
||||
|
||||
<main class="housesof"
|
||||
class:is-transitioning={!$pageReady}
|
||||
in:fade={{ duration: 600 }}
|
||||
out:fade={{ duration: 600 }}
|
||||
>
|
||||
<slot></slot>
|
||||
</main>
|
||||
<slot></slot>
|
||||
|
||||
<svelte:component this={AnalyticsTracker} {stores} id={process.env.CONFIG.GA_TRACKER_ID} />
|
||||
<Transition />
|
||||
|
||||
<AnalyticsTracker {stores} id={process.env.CONFIG.GA_TRACKER_ID} />
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
site,
|
||||
currentLocation,
|
||||
currentPhotos,
|
||||
pageReady
|
||||
pageReady,
|
||||
pageAnimation
|
||||
} from 'utils/store'
|
||||
// Components
|
||||
import IconArrow from 'atoms/IconArrow'
|
||||
@@ -20,6 +21,7 @@
|
||||
|
||||
// Variables
|
||||
const { page } = stores()
|
||||
pageAnimation.set(animateIn)
|
||||
|
||||
// Reset current location
|
||||
currentLocation.set()
|
||||
@@ -46,7 +48,7 @@
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<Transition {animateIn}>
|
||||
<main class="housesof" class:is-transitioning={!$pageReady}>
|
||||
<section class="page explore">
|
||||
<div class="wrap">
|
||||
<div class="page__top">
|
||||
@@ -69,4 +71,4 @@
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</Transition>
|
||||
</main>
|
||||
@@ -9,12 +9,12 @@
|
||||
import InteractiveGlobe from 'molecules/InteractiveGlobe'
|
||||
import Footer from 'organisms/Footer'
|
||||
import SocialMetas from 'utils/SocialMetas'
|
||||
import Transition from 'utils/Transition'
|
||||
// Animations
|
||||
import { animateIn } from 'animations/page'
|
||||
|
||||
// Variables
|
||||
const { page } = stores()
|
||||
pageAnimation.set(animateIn)
|
||||
|
||||
|
||||
/*
|
||||
@@ -37,7 +37,7 @@
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<Transition {animateIn}>
|
||||
<main class="housesof" class:is-transitioning={!$pageReady}>
|
||||
<section class="page">
|
||||
<div class="wrap">
|
||||
<div class="page__top">
|
||||
@@ -80,4 +80,4 @@
|
||||
|
||||
<Footer />
|
||||
</section>
|
||||
</Transition>
|
||||
</main>
|
||||
@@ -29,9 +29,12 @@
|
||||
site,
|
||||
currentLocation,
|
||||
currentPhotos,
|
||||
pageReady
|
||||
pageReady,
|
||||
pageAnimation
|
||||
} from 'utils/store'
|
||||
import { charsToSpan, smoothScroll } from 'utils/functions'
|
||||
// Dependencies
|
||||
import Lazy from 'svelte-lazy'
|
||||
// Components
|
||||
import Button from 'atoms/Button'
|
||||
import IconGlobeSmall from 'atoms/IconGlobeSmall'
|
||||
@@ -42,9 +45,9 @@
|
||||
import Locations from 'organisms/Locations'
|
||||
import Footer from 'organisms/Footer'
|
||||
import SocialMetas from 'utils/SocialMetas'
|
||||
import Transition from 'utils/Transition'
|
||||
// Animations
|
||||
import { animateIn } from 'animations/index'
|
||||
pageAnimation.set(animateIn)
|
||||
|
||||
// Props and Variables
|
||||
export let photos = ''
|
||||
@@ -75,7 +78,7 @@
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<Transition animateIn={animateIn}>
|
||||
<main class="housesof" class:is-transitioning={!$pageReady}>
|
||||
<section class="intro">
|
||||
<div class="anim-mask">
|
||||
<div class="anim title-parallax" id="title-houses">
|
||||
@@ -112,7 +115,11 @@
|
||||
<p>{$site.explore_globe}</p>
|
||||
</div>
|
||||
|
||||
<InteractiveGlobe />
|
||||
{#if process.browser}
|
||||
<Lazy offset={window.innerHeight}>
|
||||
<InteractiveGlobe />
|
||||
</Lazy>
|
||||
{/if}
|
||||
|
||||
<div class="anim-mask anim-title">
|
||||
<h1 class="title-massive title-parallax" id="title-world" aria-label="World">
|
||||
@@ -124,4 +131,4 @@
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</Transition>
|
||||
</main>
|
||||
@@ -29,11 +29,10 @@
|
||||
locations,
|
||||
currentLocation,
|
||||
currentPhotos,
|
||||
pageReady
|
||||
pageReady,
|
||||
pageAnimation
|
||||
} from 'utils/store'
|
||||
import { formatDate, relativeTime, getThumbnail } from 'utils/functions'
|
||||
// Dependencies
|
||||
import lazySizes from 'lazysizes'
|
||||
// Components
|
||||
import IconGlobe from 'atoms/IconGlobe'
|
||||
import IconGlobeSmall from 'atoms/IconGlobeSmall'
|
||||
@@ -51,6 +50,7 @@
|
||||
// Props and variables
|
||||
export let photos
|
||||
const { page } = stores()
|
||||
pageAnimation.set(animateIn)
|
||||
let layoutSetting
|
||||
let windowWidth
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
|
||||
<svelte:window bind:innerWidth={windowWidth} />
|
||||
|
||||
<Transition {animateIn}>
|
||||
<main class="housesof" class:is-transitioning={!$pageReady}>
|
||||
<section class="place">
|
||||
<div class="place__title">
|
||||
<h1 class="title-location title-location--big" aria-label="Houses of {location.name}">
|
||||
@@ -146,7 +146,7 @@
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
{#if photos}
|
||||
{#if photos.length}
|
||||
<p class="updated style-caps">
|
||||
<strong>Updated</strong>
|
||||
<time datetime={dateUpdatedDatetime} title={dateUpdatedFull}>{dateUpdatedRelative}</time>
|
||||
@@ -159,11 +159,12 @@
|
||||
</div>
|
||||
|
||||
{#if illu_desktop || illu_mobile}
|
||||
<div class="place__illustration"
|
||||
style="{`--url-desktop: ${illu_desktop ? `url(${illu_desktop.full_url});` : undefined}`}
|
||||
{`--url-desktop-2x: ${illu_desktop_2x ? `url(${illu_desktop_2x.full_url});` : undefined}`}
|
||||
{`--url-mobile: ${illu_mobile ? `url(${illu_mobile.full_url});` : undefined}`}"
|
||||
/>
|
||||
<div class="place__illustration">
|
||||
<div style="{`--url-desktop: ${illu_desktop ? `url(${illu_desktop.full_url});` : undefined}`}
|
||||
{`--url-desktop-2x: ${illu_desktop_2x ? `url(${illu_desktop_2x.full_url});` : undefined}`}
|
||||
{`--url-mobile: ${illu_mobile ? `url(${illu_mobile.full_url});` : undefined}`}"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
@@ -172,7 +173,7 @@
|
||||
<aside class="photos__side">
|
||||
<Switcher type="switcher--side" />
|
||||
|
||||
{#if photos}
|
||||
{#if photos.length}
|
||||
<p class="updated style-caps">
|
||||
<strong>Updated</strong>
|
||||
<time datetime={dateUpdatedDatetime} title={dateUpdatedFull}>{dateUpdatedRelative}</time>
|
||||
@@ -184,16 +185,11 @@
|
||||
{#if photos}
|
||||
<div class="photos__view wrap">
|
||||
{#each paginatedPhotos as photo, index}
|
||||
<Photo
|
||||
photo={photo}
|
||||
index={photos.length - photos.indexOf(photo)}
|
||||
layout={layoutSetting}
|
||||
/>
|
||||
<Photo {photo} index={photos.length - photos.indexOf(photo)} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<Pagination
|
||||
{photos} {paginatedPhotos} {photosPerPage}
|
||||
<Pagination {photos} {paginatedPhotos} {photosPerPage}
|
||||
on:updatePagination={updatePagination}
|
||||
/>
|
||||
|
||||
@@ -205,4 +201,4 @@
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</Transition>
|
||||
</main>
|
||||
@@ -36,7 +36,8 @@
|
||||
locations,
|
||||
currentLocation,
|
||||
currentPhotos,
|
||||
pageReady
|
||||
pageReady,
|
||||
pageAnimation
|
||||
} from 'utils/store'
|
||||
import { getThumbnail } from 'utils/functions'
|
||||
|
||||
@@ -56,6 +57,7 @@
|
||||
|
||||
// Variables
|
||||
const { page } = stores()
|
||||
pageAnimation.set(animateIn)
|
||||
let windowWidth
|
||||
let gotoLink
|
||||
let currentPhoto = photos.find(photo => photo.slug === $page.params.photo)
|
||||
@@ -100,7 +102,7 @@
|
||||
|
||||
<svelte:window bind:innerWidth={windowWidth} />
|
||||
|
||||
<Transition {animateIn}>
|
||||
<main class="housesof" class:is-transitioning={!$pageReady}>
|
||||
<section class="viewer">
|
||||
<div class="viewer__top">
|
||||
<p class="tip">Tap for fullscreen</p>
|
||||
@@ -120,12 +122,11 @@
|
||||
<a href="/" bind:this={gotoLink} aria-hidden="true" hidden class="hidden" sapper-noscroll> </a>
|
||||
</div>
|
||||
|
||||
<Carousel
|
||||
<Carousel {photos}
|
||||
viewer="true"
|
||||
photos={photos}
|
||||
on:photoChange={photoChanged}
|
||||
/>
|
||||
|
||||
<Fullscreen />
|
||||
</section>
|
||||
</Transition>
|
||||
</main>
|
||||
@@ -14,16 +14,16 @@
|
||||
|
||||
// Globe
|
||||
.globe {
|
||||
margin-top: -96px;
|
||||
margin-bottom: -160px;
|
||||
// margin-top: -96px;
|
||||
// margin-bottom: -160px;
|
||||
|
||||
@include breakpoint (sm) {
|
||||
margin-bottom: calc(-120px - 6vw);
|
||||
}
|
||||
@include breakpoint (xl) {
|
||||
margin-top: -176px;
|
||||
margin-bottom: -240px;
|
||||
}
|
||||
// @include breakpoint (sm) {
|
||||
// margin-bottom: calc(-120px - 6vw);
|
||||
// }
|
||||
// @include breakpoint (xl) {
|
||||
// margin-top: -176px;
|
||||
// margin-bottom: -240px;
|
||||
// }
|
||||
}
|
||||
|
||||
// Browse
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
transition: opacity 0.4s $ease-quart;
|
||||
transition: opacity 0.3s $ease-quart;
|
||||
will-change: opacity;
|
||||
|
||||
&.is-transitioning {
|
||||
|
||||
@@ -8,6 +8,21 @@
|
||||
cursor: grab;
|
||||
user-select: none;
|
||||
|
||||
////DEBUG////
|
||||
background: rgba(255,0,0,0.2);
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
background: blue;
|
||||
position: absolute;
|
||||
left: 0; top: 50%;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
margin-top:-1px;
|
||||
}
|
||||
////END DEBUG////
|
||||
|
||||
|
||||
@include breakpoint (sm) {
|
||||
height: 140vw;
|
||||
}
|
||||
@@ -23,94 +38,93 @@
|
||||
height: 35vw;
|
||||
min-height: 400px;
|
||||
padding: 0;
|
||||
|
||||
// Partial globe
|
||||
.globe {
|
||||
margin-top: -18vw;
|
||||
}
|
||||
}
|
||||
|
||||
// Marker
|
||||
.marker {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 100%;
|
||||
opacity: 1;
|
||||
background: #ff6c89;
|
||||
will-change: transform;
|
||||
|
||||
span {
|
||||
transition: color 0.4s $ease-quart;
|
||||
}
|
||||
|
||||
// Hover glow effect
|
||||
&.hover {
|
||||
animation: globeMarkerPulse 1s;
|
||||
}
|
||||
|
||||
// Label
|
||||
&__label {
|
||||
position: absolute;
|
||||
bottom: -230%;
|
||||
left: 230%;
|
||||
color: transparent;
|
||||
}
|
||||
// Location city
|
||||
&__city {
|
||||
font-family: $font-serif;
|
||||
font-size: rem(24px);
|
||||
line-height: 1;
|
||||
}
|
||||
// Location country
|
||||
&__country {
|
||||
display: block;
|
||||
opacity: 0.8;
|
||||
font-family: $font-sans;
|
||||
font-size: rem(10px);
|
||||
line-height: 1;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
// Active
|
||||
&.is-active {
|
||||
&, span {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.marker {
|
||||
&__city {
|
||||
color: #FF6C89;
|
||||
}
|
||||
&__country {
|
||||
color: $color-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.marker.is-left {
|
||||
.marker__label {
|
||||
left: auto;
|
||||
right: 360%;
|
||||
}
|
||||
.marker__country {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
// Grabbing
|
||||
&.is-grabbing {
|
||||
cursor: grabbing;
|
||||
// .globe {
|
||||
// margin-top: -18vw;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// Marker
|
||||
.marker {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 100%;
|
||||
opacity: 1;
|
||||
background: #ff6c89;
|
||||
will-change: transform;
|
||||
|
||||
span {
|
||||
transition: color 0.4s $ease-quart;
|
||||
}
|
||||
|
||||
// Hover glow effect
|
||||
&.hover {
|
||||
animation: globeMarkerPulse 1s;
|
||||
}
|
||||
|
||||
// Label
|
||||
&__label {
|
||||
position: absolute;
|
||||
bottom: -230%;
|
||||
left: 230%;
|
||||
color: transparent;
|
||||
}
|
||||
// Location city
|
||||
&__city {
|
||||
font-family: $font-serif;
|
||||
font-size: rem(24px);
|
||||
line-height: 1;
|
||||
}
|
||||
// Location country
|
||||
&__country {
|
||||
display: block;
|
||||
opacity: 0.8;
|
||||
font-family: $font-sans;
|
||||
font-size: rem(10px);
|
||||
line-height: 1;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
// Active
|
||||
&.is-active {
|
||||
&, span {
|
||||
opacity: 1;
|
||||
}
|
||||
.marker {
|
||||
&__city {
|
||||
color: #FF6C89;
|
||||
}
|
||||
&__country {
|
||||
color: $color-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.marker.is-left {
|
||||
.marker__label {
|
||||
left: auto;
|
||||
right: 360%;
|
||||
}
|
||||
.marker__country {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
// Grabbing
|
||||
.markerWrapper.is-grabbing {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Part globe
|
||||
.globe--part {
|
||||
|
||||
@@ -79,16 +79,16 @@
|
||||
}
|
||||
|
||||
// Globe
|
||||
.globe {
|
||||
margin-bottom: calc(-200px - 8vw);
|
||||
// .globe {
|
||||
// margin-bottom: calc(-200px - 8vw);
|
||||
|
||||
@include breakpoint (sm) {
|
||||
margin-bottom: calc(-100px - 28vw);
|
||||
}
|
||||
@include breakpoint (xl) {
|
||||
margin-bottom: -550px;
|
||||
}
|
||||
}
|
||||
// @include breakpoint (sm) {
|
||||
// margin-bottom: calc(-100px - 28vw);
|
||||
// }
|
||||
// @include breakpoint (xl) {
|
||||
// margin-bottom: -550px;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Browse
|
||||
.browse {
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
}
|
||||
|
||||
// Globe
|
||||
.globe__cut {
|
||||
margin-top: 8vw;
|
||||
}
|
||||
// .globe__cut {
|
||||
// margin-top: 8vw;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -165,24 +165,32 @@
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
max-width: 1920px;
|
||||
height: 100%;
|
||||
transform: translateX(-50%);
|
||||
transform-origin: 0 0;
|
||||
background-image: var(--url-mobile);
|
||||
background-position: 0 0;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
will-change: transform, opacity;
|
||||
|
||||
@include breakpoint (sm) {
|
||||
background-image: var(--url-desktop);
|
||||
}
|
||||
@media (min-width: $screen-sm) and (-webkit-min-device-pixel-ratio: 2),
|
||||
(min-width: $screen-sm) and (min-resolution: 192dpi) {
|
||||
background-image: var(--url-desktop-2x);
|
||||
div {
|
||||
position: relative;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: translateX(-50%);
|
||||
transform-origin: 0 0;
|
||||
background-image: var(--url-mobile);
|
||||
background-position: 0 0;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
|
||||
@include breakpoint (sm) {
|
||||
background-image: var(--url-desktop);
|
||||
}
|
||||
@media (min-width: $screen-sm) and (-webkit-min-device-pixel-ratio: 2),
|
||||
(min-width: $screen-sm) and (min-resolution: 192dpi) {
|
||||
background-image: var(--url-desktop-2x);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,20 +10,6 @@
|
||||
<link rel="icon" type="image/png" sizes="64x64" href="/img/favicon.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/img/siteicon.png">
|
||||
|
||||
<link rel="preconnect" href="https://api.housesof.world" crossorigin>
|
||||
<link rel="dns-prefetch" href="https://api.housesof.world">
|
||||
<link rel="preconnect" href="https://www.googletagmanager.com" crossorigin>
|
||||
<link rel="dns-prefetch" href="https://www.googletagmanager.com">
|
||||
<link rel="preconnect" href="https://stats.g.doubleclick.net" crossorigin>
|
||||
<link rel="dns-prefetch" href="https://stats.g.doubleclick.net">
|
||||
<link rel="preconnect" href="https://www.google-analytics.com" crossorigin>
|
||||
<link rel="dns-prefetch" href="https://www.google-analytics.com">
|
||||
<link rel="preload" href="/fonts/G-Light.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/G-Regular.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/G-Semibold.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/M-Extralight.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/M-Light.woff2" as="font" type="font/woff2" crossorigin>
|
||||
|
||||
%sapper.base%
|
||||
%sapper.head%
|
||||
%sapper.styles%
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import { fly, fade } from 'svelte/transition'
|
||||
import { quartInOut, quartOut } from 'svelte/easing'
|
||||
import { stores } from '@sapper/app'
|
||||
import { pageReady, firstLoad, animDelayPanel } from 'utils/store'
|
||||
import {
|
||||
pageReady,
|
||||
pageAnimation,
|
||||
animDuration,
|
||||
animDelay,
|
||||
animPanelDelay
|
||||
} from 'utils/store'
|
||||
const { page } = stores()
|
||||
$: animateIn = $pageAnimation
|
||||
|
||||
// Animations
|
||||
import { panelBackgroundOut } from 'animations/Transition'
|
||||
@@ -14,44 +20,57 @@
|
||||
import IconGlobe from 'atoms/IconGlobe'
|
||||
|
||||
// Props and Variables
|
||||
export let animateIn = scope => {}
|
||||
let scope
|
||||
let show = false
|
||||
let firstLoad = true
|
||||
let previousPage = ''
|
||||
|
||||
// Check if path is excluded
|
||||
const isExcluded = path => path.includes(['/viewer/'])
|
||||
|
||||
// Listen for route change
|
||||
page.subscribe(page => {
|
||||
// Show transition if page is not excluded
|
||||
if (!isExcluded(previousPage) || !isExcluded(page.path)) {
|
||||
pageReady.set(false)
|
||||
process.browser && requestAnimationFrame(() => show = false)
|
||||
}
|
||||
|
||||
// Update page for viewer navigation checking
|
||||
previousPage = page.path
|
||||
})
|
||||
|
||||
// Listen for when a route is mounted
|
||||
pageReady.subscribe(loaded => {
|
||||
loaded && setTimeout(() => {
|
||||
// Display page content
|
||||
show = true
|
||||
// Change loader icon as the loader shown already
|
||||
firstLoad.set(false)
|
||||
// Scroll to page top
|
||||
window.scrollTo(0,0)
|
||||
// Run the page animation / after a tiny delay
|
||||
requestAnimationFrame(() => animateIn(scope))
|
||||
}, animDelayPanel)
|
||||
if (loaded) {
|
||||
setTimeout(() => {
|
||||
// Show transition
|
||||
show = true
|
||||
// Run the page animation
|
||||
process.browser && requestAnimationFrame(() => animateIn())
|
||||
// Change loader icon as the loader shown already
|
||||
firstLoad = false
|
||||
// Scroll to page top
|
||||
window.scrollTo(0,0)
|
||||
}, firstLoad ? animPanelDelay : 600)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if show || !process.browser}
|
||||
<slot />
|
||||
|
||||
{:else}
|
||||
{#if !show}
|
||||
<div class="transition" id="transition" aria-hidden="true" bind:this={scope}>
|
||||
<div class="transition__loader"
|
||||
in:fly={{ y: 32, duration: 1000, easing: quartOut }}
|
||||
out:fly={{ y: -window.innerHeight/2, duration: 1400, easing: quartInOut }}
|
||||
in:fly={{ y: 24, duration: 800, easing: quartOut }}
|
||||
out:fly={{ y: -window.innerHeight/2, duration: animDuration, easing: quartInOut }}
|
||||
>
|
||||
{#if $firstLoad}
|
||||
{#if firstLoad}
|
||||
<TitleSite init={true} />
|
||||
{:else}
|
||||
<IconGlobe width="44" color="#fff" animated="true" />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="transition__background"
|
||||
in:fade={{ duration: 600, easing: quartInOut }}
|
||||
out:panelBackgroundOut={{ duration: 1400 }}
|
||||
out:panelBackgroundOut={{ duration: animDuration }}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -1,10 +1,11 @@
|
||||
|
||||
import { apiEndpoints } from './store'
|
||||
|
||||
|
||||
/*
|
||||
** Get thumbnail from API
|
||||
*/
|
||||
export const getThumbnail = (id, width, height, type = 'crop', quality = 75) => {
|
||||
export const getThumbnail = (id, width, height, type = 'crop', quality = 80) => {
|
||||
const ratio = 1.5
|
||||
width = !width ? Math.round(height * ratio) : width
|
||||
height = !height ? Math.round(width / ratio) : height
|
||||
|
||||
@@ -25,14 +25,14 @@ export let currentPhotos = writable()
|
||||
|
||||
// State
|
||||
export let pageReady = writable(false, () => {})
|
||||
export let firstLoad = writable(true)
|
||||
export let fullscreen = writable()
|
||||
export let fullscreen = writable(undefined, () => {})
|
||||
|
||||
|
||||
/* ==========================================================================
|
||||
Animation related
|
||||
========================================================================== */
|
||||
export const animDelay = 800
|
||||
export const animDelayPanel = 1000
|
||||
export let pageAnimation = writable(() => {}, () => {})
|
||||
export const animDelay = 900
|
||||
export const animPanelDelay = 900
|
||||
export const animDuration = 1400
|
||||
export const animDurationLong = 1800
|
||||
|
||||
BIN
static/img/globe/map-3k.png
Normal file
BIN
static/img/globe/map-3k.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Reference in New Issue
Block a user