Initial commit of ship project
This commit is contained in:
commit
1e74491310
1
.env.example
Normal file
1
.env.example
Normal file
@ -0,0 +1 @@
|
|||||||
|
APP_BASE_PATH = /ship
|
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.env
|
||||||
|
*.log
|
||||||
|
.idea/
|
||||||
|
node_modules/
|
||||||
|
1.bat
|
1689
package-lock.json
generated
Normal file
1689
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
package.json
Normal file
13
package.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"canvas": "^2.11.2",
|
||||||
|
"dotenv": "^16.5.0",
|
||||||
|
"ejs": "^3.1.8",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"mysql2": "^3.2.0",
|
||||||
|
"path": "^0.12.7",
|
||||||
|
"sequelize": "^6.29.1",
|
||||||
|
"socket.io": "^4.6.1",
|
||||||
|
"sweetalert2": "^11.7.3"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/Rock_color.png
Normal file
BIN
public/Rock_color.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 MiB |
BIN
public/Rock_color2.png
Normal file
BIN
public/Rock_color2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 MiB |
BIN
public/Walking.fbx
Normal file
BIN
public/Walking.fbx
Normal file
Binary file not shown.
3
public/assets/models.js
Normal file
3
public/assets/models.js
Normal file
File diff suppressed because one or more lines are too long
2
public/assets/models_man.js
Normal file
2
public/assets/models_man.js
Normal file
File diff suppressed because one or more lines are too long
4
public/assets/textures.js
Normal file
4
public/assets/textures.js
Normal file
File diff suppressed because one or more lines are too long
BIN
public/blue_whale.fbx
Normal file
BIN
public/blue_whale.fbx
Normal file
Binary file not shown.
142
public/css/style.css
Normal file
142
public/css/style.css
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
#c {
|
||||||
|
width: 750px;
|
||||||
|
height: 500px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#canvas_temp, #canvas_temp2{
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
#canvas_temp{
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.top-div {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
font-family: "Arial";
|
||||||
|
font-size: 10px;
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.top-div::after {
|
||||||
|
content: "Загрузка";
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
animation: loading 1s ease-in-out infinite;
|
||||||
|
font-size: 30px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
@keyframes loading{
|
||||||
|
0% {
|
||||||
|
content: "Загрузка\00a0\00a0\00a0";
|
||||||
|
}
|
||||||
|
35% {
|
||||||
|
content: "Загрузка.\00a0\00a0";
|
||||||
|
}
|
||||||
|
65% {
|
||||||
|
content: "Загрузка..\00a0";
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
content: "Загрузка...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a{
|
||||||
|
margin-top: 10px;
|
||||||
|
background: lightgray;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 15px;
|
||||||
|
border: 2px solid gray;
|
||||||
|
}
|
||||||
|
.container{
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.big_container{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.menu_ico{
|
||||||
|
width: 21px;
|
||||||
|
height: 21px;
|
||||||
|
position:absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 22px;
|
||||||
|
z-index: 2;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.menu_ico > div:first-child, .menu_ico > div:first-child:after, .menu_ico > div:first-child:before{
|
||||||
|
width: 12px;
|
||||||
|
height: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.menu_ico > div:first-child{
|
||||||
|
position:absolute;
|
||||||
|
margin-left: 4px;
|
||||||
|
display: inline;
|
||||||
|
background: darkgray;
|
||||||
|
transform: scale(1.7);
|
||||||
|
}
|
||||||
|
.menu_ico > div:first-child:after{
|
||||||
|
position:absolute;
|
||||||
|
content: "";
|
||||||
|
background: darkgray;
|
||||||
|
top: 4px;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
.menu_ico > div:first-child:before{
|
||||||
|
position:absolute;
|
||||||
|
content: "";
|
||||||
|
background: darkgray;
|
||||||
|
top: 8px;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
.slidecontainer {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
background: white;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.menu_ico:hover .slidecontainer{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
#checkbox-container{
|
||||||
|
display: grid;
|
||||||
|
columns: 2;
|
||||||
|
row-gap: 10px;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
.sheet{
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
.hide{
|
||||||
|
display: none;
|
||||||
|
}
|
4074
public/scripts/FBXLoader.js
Normal file
4074
public/scripts/FBXLoader.js
Normal file
File diff suppressed because it is too large
Load Diff
4507
public/scripts/GLTFLoader.js
Normal file
4507
public/scripts/GLTFLoader.js
Normal file
File diff suppressed because it is too large
Load Diff
451
public/scripts/NURBSCurve.js
Normal file
451
public/scripts/NURBSCurve.js
Normal file
@ -0,0 +1,451 @@
|
|||||||
|
|
||||||
|
function findSpan( p, u, U ) {
|
||||||
|
|
||||||
|
const n = U.length - p - 1;
|
||||||
|
|
||||||
|
if ( u >= U[ n ] ) {
|
||||||
|
|
||||||
|
return n - 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( u <= U[ p ] ) {
|
||||||
|
|
||||||
|
return p;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let low = p;
|
||||||
|
let high = n;
|
||||||
|
let mid = Math.floor( ( low + high ) / 2 );
|
||||||
|
|
||||||
|
while ( u < U[ mid ] || u >= U[ mid + 1 ] ) {
|
||||||
|
|
||||||
|
if ( u < U[ mid ] ) {
|
||||||
|
|
||||||
|
high = mid;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
low = mid;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mid = Math.floor( ( low + high ) / 2 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return mid;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate basis functions. See The NURBS Book, page 70, algorithm A2.2
|
||||||
|
|
||||||
|
span : span in which u lies
|
||||||
|
u : parametric point
|
||||||
|
p : degree
|
||||||
|
U : knot vector
|
||||||
|
|
||||||
|
returns array[p+1] with basis functions values.
|
||||||
|
*/
|
||||||
|
function calcBasisFunctions( span, u, p, U ) {
|
||||||
|
|
||||||
|
const N = [];
|
||||||
|
const left = [];
|
||||||
|
const right = [];
|
||||||
|
N[ 0 ] = 1.0;
|
||||||
|
|
||||||
|
for ( let j = 1; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
left[ j ] = u - U[ span + 1 - j ];
|
||||||
|
right[ j ] = U[ span + j ] - u;
|
||||||
|
|
||||||
|
let saved = 0.0;
|
||||||
|
|
||||||
|
for ( let r = 0; r < j; ++ r ) {
|
||||||
|
|
||||||
|
const rv = right[ r + 1 ];
|
||||||
|
const lv = left[ j - r ];
|
||||||
|
const temp = N[ r ] / ( rv + lv );
|
||||||
|
N[ r ] = saved + rv * temp;
|
||||||
|
saved = lv * temp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
N[ j ] = saved;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return N;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate B-Spline curve points. See The NURBS Book, page 82, algorithm A3.1.
|
||||||
|
|
||||||
|
p : degree of B-Spline
|
||||||
|
U : knot vector
|
||||||
|
P : control points (x, y, z, w)
|
||||||
|
u : parametric point
|
||||||
|
|
||||||
|
returns point for given u
|
||||||
|
*/
|
||||||
|
function calcBSplinePoint( p, U, P, u ) {
|
||||||
|
|
||||||
|
const span = findSpan( p, u, U );
|
||||||
|
const N = calcBasisFunctions( span, u, p, U );
|
||||||
|
const C = new Vector4( 0, 0, 0, 0 );
|
||||||
|
|
||||||
|
for ( let j = 0; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
const point = P[ span - p + j ];
|
||||||
|
const Nj = N[ j ];
|
||||||
|
const wNj = point.w * Nj;
|
||||||
|
C.x += point.x * wNj;
|
||||||
|
C.y += point.y * wNj;
|
||||||
|
C.z += point.z * wNj;
|
||||||
|
C.w += point.w * Nj;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return C;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate basis functions derivatives. See The NURBS Book, page 72, algorithm A2.3.
|
||||||
|
|
||||||
|
span : span in which u lies
|
||||||
|
u : parametric point
|
||||||
|
p : degree
|
||||||
|
n : number of derivatives to calculate
|
||||||
|
U : knot vector
|
||||||
|
|
||||||
|
returns array[n+1][p+1] with basis functions derivatives
|
||||||
|
*/
|
||||||
|
function calcBasisFunctionDerivatives( span, u, p, n, U ) {
|
||||||
|
|
||||||
|
const zeroArr = [];
|
||||||
|
for ( let i = 0; i <= p; ++ i )
|
||||||
|
zeroArr[ i ] = 0.0;
|
||||||
|
|
||||||
|
const ders = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i <= n; ++ i )
|
||||||
|
ders[ i ] = zeroArr.slice( 0 );
|
||||||
|
|
||||||
|
const ndu = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i <= p; ++ i )
|
||||||
|
ndu[ i ] = zeroArr.slice( 0 );
|
||||||
|
|
||||||
|
ndu[ 0 ][ 0 ] = 1.0;
|
||||||
|
|
||||||
|
const left = zeroArr.slice( 0 );
|
||||||
|
const right = zeroArr.slice( 0 );
|
||||||
|
|
||||||
|
for ( let j = 1; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
left[ j ] = u - U[ span + 1 - j ];
|
||||||
|
right[ j ] = U[ span + j ] - u;
|
||||||
|
|
||||||
|
let saved = 0.0;
|
||||||
|
|
||||||
|
for ( let r = 0; r < j; ++ r ) {
|
||||||
|
|
||||||
|
const rv = right[ r + 1 ];
|
||||||
|
const lv = left[ j - r ];
|
||||||
|
ndu[ j ][ r ] = rv + lv;
|
||||||
|
|
||||||
|
const temp = ndu[ r ][ j - 1 ] / ndu[ j ][ r ];
|
||||||
|
ndu[ r ][ j ] = saved + rv * temp;
|
||||||
|
saved = lv * temp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ndu[ j ][ j ] = saved;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let j = 0; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
ders[ 0 ][ j ] = ndu[ j ][ p ];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let r = 0; r <= p; ++ r ) {
|
||||||
|
|
||||||
|
let s1 = 0;
|
||||||
|
let s2 = 1;
|
||||||
|
|
||||||
|
const a = [];
|
||||||
|
for ( let i = 0; i <= p; ++ i ) {
|
||||||
|
|
||||||
|
a[ i ] = zeroArr.slice( 0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
a[ 0 ][ 0 ] = 1.0;
|
||||||
|
|
||||||
|
for ( let k = 1; k <= n; ++ k ) {
|
||||||
|
|
||||||
|
let d = 0.0;
|
||||||
|
const rk = r - k;
|
||||||
|
const pk = p - k;
|
||||||
|
|
||||||
|
if ( r >= k ) {
|
||||||
|
|
||||||
|
a[ s2 ][ 0 ] = a[ s1 ][ 0 ] / ndu[ pk + 1 ][ rk ];
|
||||||
|
d = a[ s2 ][ 0 ] * ndu[ rk ][ pk ];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const j1 = ( rk >= - 1 ) ? 1 : - rk;
|
||||||
|
const j2 = ( r - 1 <= pk ) ? k - 1 : p - r;
|
||||||
|
|
||||||
|
for ( let j = j1; j <= j2; ++ j ) {
|
||||||
|
|
||||||
|
a[ s2 ][ j ] = ( a[ s1 ][ j ] - a[ s1 ][ j - 1 ] ) / ndu[ pk + 1 ][ rk + j ];
|
||||||
|
d += a[ s2 ][ j ] * ndu[ rk + j ][ pk ];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( r <= pk ) {
|
||||||
|
|
||||||
|
a[ s2 ][ k ] = - a[ s1 ][ k - 1 ] / ndu[ pk + 1 ][ r ];
|
||||||
|
d += a[ s2 ][ k ] * ndu[ r ][ pk ];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ders[ k ][ r ] = d;
|
||||||
|
|
||||||
|
const j = s1;
|
||||||
|
s1 = s2;
|
||||||
|
s2 = j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = p;
|
||||||
|
|
||||||
|
for ( let k = 1; k <= n; ++ k ) {
|
||||||
|
|
||||||
|
for ( let j = 0; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
ders[ k ][ j ] *= r;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
r *= p - k;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ders;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2.
|
||||||
|
|
||||||
|
p : degree
|
||||||
|
U : knot vector
|
||||||
|
P : control points
|
||||||
|
u : Parametric points
|
||||||
|
nd : number of derivatives
|
||||||
|
|
||||||
|
returns array[d+1] with derivatives
|
||||||
|
*/
|
||||||
|
function calcBSplineDerivatives( p, U, P, u, nd ) {
|
||||||
|
|
||||||
|
const du = nd < p ? nd : p;
|
||||||
|
const CK = [];
|
||||||
|
const span = findSpan( p, u, U );
|
||||||
|
const nders = calcBasisFunctionDerivatives( span, u, p, du, U );
|
||||||
|
const Pw = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i < P.length; ++ i ) {
|
||||||
|
|
||||||
|
const point = P[ i ].clone();
|
||||||
|
const w = point.w;
|
||||||
|
|
||||||
|
point.x *= w;
|
||||||
|
point.y *= w;
|
||||||
|
point.z *= w;
|
||||||
|
|
||||||
|
Pw[ i ] = point;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let k = 0; k <= du; ++ k ) {
|
||||||
|
|
||||||
|
const point = Pw[ span - p ].clone().multiplyScalar( nders[ k ][ 0 ] );
|
||||||
|
|
||||||
|
for ( let j = 1; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
point.add( Pw[ span - p + j ].clone().multiplyScalar( nders[ k ][ j ] ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CK[ k ] = point;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let k = du + 1; k <= nd + 1; ++ k ) {
|
||||||
|
|
||||||
|
CK[ k ] = new Vector4( 0, 0, 0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return CK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate "K over I"
|
||||||
|
|
||||||
|
returns k!/(i!(k-i)!)
|
||||||
|
*/
|
||||||
|
function calcKoverI( k, i ) {
|
||||||
|
|
||||||
|
let nom = 1;
|
||||||
|
|
||||||
|
for ( let j = 2; j <= k; ++ j ) {
|
||||||
|
|
||||||
|
nom *= j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let denom = 1;
|
||||||
|
|
||||||
|
for ( let j = 2; j <= i; ++ j ) {
|
||||||
|
|
||||||
|
denom *= j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let j = 2; j <= k - i; ++ j ) {
|
||||||
|
|
||||||
|
denom *= j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate derivatives (0-nd) of rational curve. See The NURBS Book, page 127, algorithm A4.2.
|
||||||
|
|
||||||
|
Pders : result of function calcBSplineDerivatives
|
||||||
|
|
||||||
|
returns array with derivatives for rational curve.
|
||||||
|
*/
|
||||||
|
function calcRationalCurveDerivatives( Pders ) {
|
||||||
|
|
||||||
|
const nd = Pders.length;
|
||||||
|
const Aders = [];
|
||||||
|
const wders = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i < nd; ++ i ) {
|
||||||
|
|
||||||
|
const point = Pders[ i ];
|
||||||
|
Aders[ i ] = new Vector3( point.x, point.y, point.z );
|
||||||
|
wders[ i ] = point.w;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const CK = [];
|
||||||
|
|
||||||
|
for ( let k = 0; k < nd; ++ k ) {
|
||||||
|
|
||||||
|
const v = Aders[ k ].clone();
|
||||||
|
|
||||||
|
for ( let i = 1; i <= k; ++ i ) {
|
||||||
|
|
||||||
|
v.sub( CK[ k - i ].clone().multiplyScalar( calcKoverI( k, i ) * wders[ i ] ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CK[ k ] = v.divideScalar( wders[ 0 ] );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return CK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate NURBS curve derivatives. See The NURBS Book, page 127, algorithm A4.2.
|
||||||
|
|
||||||
|
p : degree
|
||||||
|
U : knot vector
|
||||||
|
P : control points in homogeneous space
|
||||||
|
u : parametric points
|
||||||
|
nd : number of derivatives
|
||||||
|
|
||||||
|
returns array with derivatives.
|
||||||
|
*/
|
||||||
|
function calcNURBSDerivatives( p, U, P, u, nd ) {
|
||||||
|
|
||||||
|
const Pders = calcBSplineDerivatives( p, U, P, u, nd );
|
||||||
|
return calcRationalCurveDerivatives( Pders );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3.
|
||||||
|
|
||||||
|
p1, p2 : degrees of B-Spline surface
|
||||||
|
U1, U2 : knot vectors
|
||||||
|
P : control points (x, y, z, w)
|
||||||
|
u, v : parametric values
|
||||||
|
|
||||||
|
returns point for given (u, v)
|
||||||
|
*/
|
||||||
|
function calcSurfacePoint( p, q, U, V, P, u, v, target ) {
|
||||||
|
|
||||||
|
const uspan = findSpan( p, u, U );
|
||||||
|
const vspan = findSpan( q, v, V );
|
||||||
|
const Nu = calcBasisFunctions( uspan, u, p, U );
|
||||||
|
const Nv = calcBasisFunctions( vspan, v, q, V );
|
||||||
|
const temp = [];
|
||||||
|
|
||||||
|
for ( let l = 0; l <= q; ++ l ) {
|
||||||
|
|
||||||
|
temp[ l ] = new Vector4( 0, 0, 0, 0 );
|
||||||
|
for ( let k = 0; k <= p; ++ k ) {
|
||||||
|
|
||||||
|
const point = P[ uspan - p + k ][ vspan - q + l ].clone();
|
||||||
|
const w = point.w;
|
||||||
|
point.x *= w;
|
||||||
|
point.y *= w;
|
||||||
|
point.z *= w;
|
||||||
|
temp[ l ].add( point.multiplyScalar( Nu[ k ] ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sw = new Vector4( 0, 0, 0, 0 );
|
||||||
|
for ( let l = 0; l <= q; ++ l ) {
|
||||||
|
|
||||||
|
Sw.add( temp[ l ].multiplyScalar( Nv[ l ] ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Sw.divideScalar( Sw.w );
|
||||||
|
target.set( Sw.x, Sw.y, Sw.z );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
450
public/scripts/NURBSUtils.js
Normal file
450
public/scripts/NURBSUtils.js
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
|
||||||
|
function findSpan( p, u, U ) {
|
||||||
|
|
||||||
|
const n = U.length - p - 1;
|
||||||
|
|
||||||
|
if ( u >= U[ n ] ) {
|
||||||
|
|
||||||
|
return n - 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( u <= U[ p ] ) {
|
||||||
|
|
||||||
|
return p;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let low = p;
|
||||||
|
let high = n;
|
||||||
|
let mid = Math.floor( ( low + high ) / 2 );
|
||||||
|
|
||||||
|
while ( u < U[ mid ] || u >= U[ mid + 1 ] ) {
|
||||||
|
|
||||||
|
if ( u < U[ mid ] ) {
|
||||||
|
|
||||||
|
high = mid;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
low = mid;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mid = Math.floor( ( low + high ) / 2 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return mid;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate basis functions. See The NURBS Book, page 70, algorithm A2.2
|
||||||
|
|
||||||
|
span : span in which u lies
|
||||||
|
u : parametric point
|
||||||
|
p : degree
|
||||||
|
U : knot vector
|
||||||
|
|
||||||
|
returns array[p+1] with basis functions values.
|
||||||
|
*/
|
||||||
|
function calcBasisFunctions( span, u, p, U ) {
|
||||||
|
|
||||||
|
const N = [];
|
||||||
|
const left = [];
|
||||||
|
const right = [];
|
||||||
|
N[ 0 ] = 1.0;
|
||||||
|
|
||||||
|
for ( let j = 1; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
left[ j ] = u - U[ span + 1 - j ];
|
||||||
|
right[ j ] = U[ span + j ] - u;
|
||||||
|
|
||||||
|
let saved = 0.0;
|
||||||
|
|
||||||
|
for ( let r = 0; r < j; ++ r ) {
|
||||||
|
|
||||||
|
const rv = right[ r + 1 ];
|
||||||
|
const lv = left[ j - r ];
|
||||||
|
const temp = N[ r ] / ( rv + lv );
|
||||||
|
N[ r ] = saved + rv * temp;
|
||||||
|
saved = lv * temp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
N[ j ] = saved;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return N;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate B-Spline curve points. See The NURBS Book, page 82, algorithm A3.1.
|
||||||
|
|
||||||
|
p : degree of B-Spline
|
||||||
|
U : knot vector
|
||||||
|
P : control points (x, y, z, w)
|
||||||
|
u : parametric point
|
||||||
|
|
||||||
|
returns point for given u
|
||||||
|
*/
|
||||||
|
function calcBSplinePoint( p, U, P, u ) {
|
||||||
|
|
||||||
|
const span = findSpan( p, u, U );
|
||||||
|
const N = calcBasisFunctions( span, u, p, U );
|
||||||
|
const C = new Vector4( 0, 0, 0, 0 );
|
||||||
|
|
||||||
|
for ( let j = 0; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
const point = P[ span - p + j ];
|
||||||
|
const Nj = N[ j ];
|
||||||
|
const wNj = point.w * Nj;
|
||||||
|
C.x += point.x * wNj;
|
||||||
|
C.y += point.y * wNj;
|
||||||
|
C.z += point.z * wNj;
|
||||||
|
C.w += point.w * Nj;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return C;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate basis functions derivatives. See The NURBS Book, page 72, algorithm A2.3.
|
||||||
|
|
||||||
|
span : span in which u lies
|
||||||
|
u : parametric point
|
||||||
|
p : degree
|
||||||
|
n : number of derivatives to calculate
|
||||||
|
U : knot vector
|
||||||
|
|
||||||
|
returns array[n+1][p+1] with basis functions derivatives
|
||||||
|
*/
|
||||||
|
function calcBasisFunctionDerivatives( span, u, p, n, U ) {
|
||||||
|
|
||||||
|
const zeroArr = [];
|
||||||
|
for ( let i = 0; i <= p; ++ i )
|
||||||
|
zeroArr[ i ] = 0.0;
|
||||||
|
|
||||||
|
const ders = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i <= n; ++ i )
|
||||||
|
ders[ i ] = zeroArr.slice( 0 );
|
||||||
|
|
||||||
|
const ndu = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i <= p; ++ i )
|
||||||
|
ndu[ i ] = zeroArr.slice( 0 );
|
||||||
|
|
||||||
|
ndu[ 0 ][ 0 ] = 1.0;
|
||||||
|
|
||||||
|
const left = zeroArr.slice( 0 );
|
||||||
|
const right = zeroArr.slice( 0 );
|
||||||
|
|
||||||
|
for ( let j = 1; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
left[ j ] = u - U[ span + 1 - j ];
|
||||||
|
right[ j ] = U[ span + j ] - u;
|
||||||
|
|
||||||
|
let saved = 0.0;
|
||||||
|
|
||||||
|
for ( let r = 0; r < j; ++ r ) {
|
||||||
|
|
||||||
|
const rv = right[ r + 1 ];
|
||||||
|
const lv = left[ j - r ];
|
||||||
|
ndu[ j ][ r ] = rv + lv;
|
||||||
|
|
||||||
|
const temp = ndu[ r ][ j - 1 ] / ndu[ j ][ r ];
|
||||||
|
ndu[ r ][ j ] = saved + rv * temp;
|
||||||
|
saved = lv * temp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ndu[ j ][ j ] = saved;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let j = 0; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
ders[ 0 ][ j ] = ndu[ j ][ p ];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let r = 0; r <= p; ++ r ) {
|
||||||
|
|
||||||
|
let s1 = 0;
|
||||||
|
let s2 = 1;
|
||||||
|
|
||||||
|
const a = [];
|
||||||
|
for ( let i = 0; i <= p; ++ i ) {
|
||||||
|
|
||||||
|
a[ i ] = zeroArr.slice( 0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
a[ 0 ][ 0 ] = 1.0;
|
||||||
|
|
||||||
|
for ( let k = 1; k <= n; ++ k ) {
|
||||||
|
|
||||||
|
let d = 0.0;
|
||||||
|
const rk = r - k;
|
||||||
|
const pk = p - k;
|
||||||
|
|
||||||
|
if ( r >= k ) {
|
||||||
|
|
||||||
|
a[ s2 ][ 0 ] = a[ s1 ][ 0 ] / ndu[ pk + 1 ][ rk ];
|
||||||
|
d = a[ s2 ][ 0 ] * ndu[ rk ][ pk ];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const j1 = ( rk >= - 1 ) ? 1 : - rk;
|
||||||
|
const j2 = ( r - 1 <= pk ) ? k - 1 : p - r;
|
||||||
|
|
||||||
|
for ( let j = j1; j <= j2; ++ j ) {
|
||||||
|
|
||||||
|
a[ s2 ][ j ] = ( a[ s1 ][ j ] - a[ s1 ][ j - 1 ] ) / ndu[ pk + 1 ][ rk + j ];
|
||||||
|
d += a[ s2 ][ j ] * ndu[ rk + j ][ pk ];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( r <= pk ) {
|
||||||
|
|
||||||
|
a[ s2 ][ k ] = - a[ s1 ][ k - 1 ] / ndu[ pk + 1 ][ r ];
|
||||||
|
d += a[ s2 ][ k ] * ndu[ r ][ pk ];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ders[ k ][ r ] = d;
|
||||||
|
|
||||||
|
const j = s1;
|
||||||
|
s1 = s2;
|
||||||
|
s2 = j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = p;
|
||||||
|
|
||||||
|
for ( let k = 1; k <= n; ++ k ) {
|
||||||
|
|
||||||
|
for ( let j = 0; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
ders[ k ][ j ] *= r;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
r *= p - k;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ders;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2.
|
||||||
|
|
||||||
|
p : degree
|
||||||
|
U : knot vector
|
||||||
|
P : control points
|
||||||
|
u : Parametric points
|
||||||
|
nd : number of derivatives
|
||||||
|
|
||||||
|
returns array[d+1] with derivatives
|
||||||
|
*/
|
||||||
|
function calcBSplineDerivatives( p, U, P, u, nd ) {
|
||||||
|
|
||||||
|
const du = nd < p ? nd : p;
|
||||||
|
const CK = [];
|
||||||
|
const span = findSpan( p, u, U );
|
||||||
|
const nders = calcBasisFunctionDerivatives( span, u, p, du, U );
|
||||||
|
const Pw = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i < P.length; ++ i ) {
|
||||||
|
|
||||||
|
const point = P[ i ].clone();
|
||||||
|
const w = point.w;
|
||||||
|
|
||||||
|
point.x *= w;
|
||||||
|
point.y *= w;
|
||||||
|
point.z *= w;
|
||||||
|
|
||||||
|
Pw[ i ] = point;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let k = 0; k <= du; ++ k ) {
|
||||||
|
|
||||||
|
const point = Pw[ span - p ].clone().multiplyScalar( nders[ k ][ 0 ] );
|
||||||
|
|
||||||
|
for ( let j = 1; j <= p; ++ j ) {
|
||||||
|
|
||||||
|
point.add( Pw[ span - p + j ].clone().multiplyScalar( nders[ k ][ j ] ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CK[ k ] = point;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let k = du + 1; k <= nd + 1; ++ k ) {
|
||||||
|
|
||||||
|
CK[ k ] = new Vector4( 0, 0, 0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return CK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate "K over I"
|
||||||
|
|
||||||
|
returns k!/(i!(k-i)!)
|
||||||
|
*/
|
||||||
|
function calcKoverI( k, i ) {
|
||||||
|
|
||||||
|
let nom = 1;
|
||||||
|
|
||||||
|
for ( let j = 2; j <= k; ++ j ) {
|
||||||
|
|
||||||
|
nom *= j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let denom = 1;
|
||||||
|
|
||||||
|
for ( let j = 2; j <= i; ++ j ) {
|
||||||
|
|
||||||
|
denom *= j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let j = 2; j <= k - i; ++ j ) {
|
||||||
|
|
||||||
|
denom *= j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate derivatives (0-nd) of rational curve. See The NURBS Book, page 127, algorithm A4.2.
|
||||||
|
|
||||||
|
Pders : result of function calcBSplineDerivatives
|
||||||
|
|
||||||
|
returns array with derivatives for rational curve.
|
||||||
|
*/
|
||||||
|
function calcRationalCurveDerivatives( Pders ) {
|
||||||
|
|
||||||
|
const nd = Pders.length;
|
||||||
|
const Aders = [];
|
||||||
|
const wders = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i < nd; ++ i ) {
|
||||||
|
|
||||||
|
const point = Pders[ i ];
|
||||||
|
Aders[ i ] = new Vector3( point.x, point.y, point.z );
|
||||||
|
wders[ i ] = point.w;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const CK = [];
|
||||||
|
|
||||||
|
for ( let k = 0; k < nd; ++ k ) {
|
||||||
|
|
||||||
|
const v = Aders[ k ].clone();
|
||||||
|
|
||||||
|
for ( let i = 1; i <= k; ++ i ) {
|
||||||
|
|
||||||
|
v.sub( CK[ k - i ].clone().multiplyScalar( calcKoverI( k, i ) * wders[ i ] ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CK[ k ] = v.divideScalar( wders[ 0 ] );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return CK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate NURBS curve derivatives. See The NURBS Book, page 127, algorithm A4.2.
|
||||||
|
|
||||||
|
p : degree
|
||||||
|
U : knot vector
|
||||||
|
P : control points in homogeneous space
|
||||||
|
u : parametric points
|
||||||
|
nd : number of derivatives
|
||||||
|
|
||||||
|
returns array with derivatives.
|
||||||
|
*/
|
||||||
|
function calcNURBSDerivatives( p, U, P, u, nd ) {
|
||||||
|
|
||||||
|
const Pders = calcBSplineDerivatives( p, U, P, u, nd );
|
||||||
|
return calcRationalCurveDerivatives( Pders );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3.
|
||||||
|
|
||||||
|
p1, p2 : degrees of B-Spline surface
|
||||||
|
U1, U2 : knot vectors
|
||||||
|
P : control points (x, y, z, w)
|
||||||
|
u, v : parametric values
|
||||||
|
|
||||||
|
returns point for given (u, v)
|
||||||
|
*/
|
||||||
|
function calcSurfacePoint( p, q, U, V, P, u, v, target ) {
|
||||||
|
|
||||||
|
const uspan = findSpan( p, u, U );
|
||||||
|
const vspan = findSpan( q, v, V );
|
||||||
|
const Nu = calcBasisFunctions( uspan, u, p, U );
|
||||||
|
const Nv = calcBasisFunctions( vspan, v, q, V );
|
||||||
|
const temp = [];
|
||||||
|
|
||||||
|
for ( let l = 0; l <= q; ++ l ) {
|
||||||
|
|
||||||
|
temp[ l ] = new Vector4( 0, 0, 0, 0 );
|
||||||
|
for ( let k = 0; k <= p; ++ k ) {
|
||||||
|
|
||||||
|
const point = P[ uspan - p + k ][ vspan - q + l ].clone();
|
||||||
|
const w = point.w;
|
||||||
|
point.x *= w;
|
||||||
|
point.y *= w;
|
||||||
|
point.z *= w;
|
||||||
|
temp[ l ].add( point.multiplyScalar( Nu[ k ] ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sw = new Vector4( 0, 0, 0, 0 );
|
||||||
|
for ( let l = 0; l <= q; ++ l ) {
|
||||||
|
|
||||||
|
Sw.add( temp[ l ].multiplyScalar( Nv[ l ] ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Sw.divideScalar( Sw.w );
|
||||||
|
target.set( Sw.x, Sw.y, Sw.z );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
1079
public/scripts/OrbitControls.js
Normal file
1079
public/scripts/OrbitControls.js
Normal file
File diff suppressed because it is too large
Load Diff
230
public/scripts/ShadowMapViewer.js
Normal file
230
public/scripts/ShadowMapViewer.js
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
const UnpackDepthRGBAShader = {
|
||||||
|
|
||||||
|
name: 'UnpackDepthRGBAShader',
|
||||||
|
|
||||||
|
uniforms: {
|
||||||
|
|
||||||
|
'tDiffuse': { value: null },
|
||||||
|
'opacity': { value: 1.0 }
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
vertexShader: /* glsl */`
|
||||||
|
|
||||||
|
varying vec2 vUv;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
vUv = uv;
|
||||||
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||||
|
|
||||||
|
}`,
|
||||||
|
|
||||||
|
fragmentShader: /* glsl */`
|
||||||
|
|
||||||
|
uniform float opacity;
|
||||||
|
|
||||||
|
uniform sampler2D tDiffuse;
|
||||||
|
|
||||||
|
varying vec2 vUv;
|
||||||
|
|
||||||
|
#include <packing>
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
float depth = 1.0 - unpackRGBAToDepth( texture2D( tDiffuse, vUv ) );
|
||||||
|
gl_FragColor = vec4( vec3( depth ), opacity );
|
||||||
|
|
||||||
|
}`
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a helper for visualising a given light's shadow map.
|
||||||
|
* It works for shadow casting lights: DirectionalLight and SpotLight.
|
||||||
|
* It renders out the shadow map and displays it on a HUD.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* 1) Import ShadowMapViewer into your app.
|
||||||
|
*
|
||||||
|
* 2) Create a shadow casting light and name it optionally:
|
||||||
|
* let light = new DirectionalLight( 0xffffff, 1 );
|
||||||
|
* light.castShadow = true;
|
||||||
|
* light.name = 'Sun';
|
||||||
|
*
|
||||||
|
* 3) Create a shadow map viewer for that light and set its size and position optionally:
|
||||||
|
* let shadowMapViewer = new ShadowMapViewer( light );
|
||||||
|
* shadowMapViewer.size.set( 128, 128 ); //width, height default: 256, 256
|
||||||
|
* shadowMapViewer.position.set( 10, 10 ); //x, y in pixel default: 0, 0 (top left corner)
|
||||||
|
*
|
||||||
|
* 4) Render the shadow map viewer in your render loop:
|
||||||
|
* shadowMapViewer.render( renderer );
|
||||||
|
*
|
||||||
|
* 5) Optionally: Update the shadow map viewer on window resize:
|
||||||
|
* shadowMapViewer.updateForWindowResize();
|
||||||
|
*
|
||||||
|
* 6) If you set the position or size members directly, you need to call shadowMapViewer.update();
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ShadowMapViewer {
|
||||||
|
|
||||||
|
constructor( light ) {
|
||||||
|
|
||||||
|
//- Internals
|
||||||
|
const scope = this;
|
||||||
|
const doRenderLabel = ( light.name !== undefined && light.name !== '' );
|
||||||
|
let userAutoClearSetting;
|
||||||
|
|
||||||
|
//Holds the initial position and dimension of the HUD
|
||||||
|
const frame = {
|
||||||
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
width: 256,
|
||||||
|
height: 256
|
||||||
|
};
|
||||||
|
|
||||||
|
const camera = new OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 10 );
|
||||||
|
camera.position.set( 0, 0, 2 );
|
||||||
|
const scene = new Scene();
|
||||||
|
|
||||||
|
//HUD for shadow map
|
||||||
|
const shader = UnpackDepthRGBAShader;
|
||||||
|
|
||||||
|
const uniforms = UniformsUtils.clone( shader.uniforms );
|
||||||
|
const material = new ShaderMaterial( {
|
||||||
|
uniforms: uniforms,
|
||||||
|
vertexShader: shader.vertexShader,
|
||||||
|
fragmentShader: shader.fragmentShader
|
||||||
|
} );
|
||||||
|
const plane = new PlaneGeometry( frame.width, frame.height );
|
||||||
|
window.mesh = new Mesh( plane, material );
|
||||||
|
|
||||||
|
scene.add( mesh );
|
||||||
|
|
||||||
|
|
||||||
|
//Label for light's name
|
||||||
|
let labelCanvas, labelMesh;
|
||||||
|
|
||||||
|
if ( doRenderLabel ) {
|
||||||
|
|
||||||
|
labelCanvas = document.createElement( 'canvas' );
|
||||||
|
|
||||||
|
const context = labelCanvas.getContext( '2d' );
|
||||||
|
context.font = 'Bold 20px Arial';
|
||||||
|
|
||||||
|
const labelWidth = context.measureText( light.name ).width;
|
||||||
|
labelCanvas.width = labelWidth;
|
||||||
|
labelCanvas.height = 25; //25 to account for g, p, etc.
|
||||||
|
|
||||||
|
context.font = 'Bold 20px Arial';
|
||||||
|
context.fillStyle = 'rgba( 255, 0, 0, 1 )';
|
||||||
|
context.fillText( light.name, 0, 20 );
|
||||||
|
|
||||||
|
const labelTexture = new CanvasTexture( labelCanvas );
|
||||||
|
|
||||||
|
const labelMaterial = new MeshBasicMaterial( { map: labelTexture, side: DoubleSide, transparent: true } );
|
||||||
|
|
||||||
|
const labelPlane = new PlaneGeometry( labelCanvas.width, labelCanvas.height );
|
||||||
|
labelMesh = new Mesh( labelPlane, labelMaterial );
|
||||||
|
|
||||||
|
scene.add( labelMesh );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function resetPosition() {
|
||||||
|
|
||||||
|
scope.position.set( scope.position.x, scope.position.y );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//- API
|
||||||
|
// Set to false to disable displaying this shadow map
|
||||||
|
this.enabled = true;
|
||||||
|
|
||||||
|
// Set the size of the displayed shadow map on the HUD
|
||||||
|
this.size = {
|
||||||
|
width: frame.width,
|
||||||
|
height: frame.height,
|
||||||
|
set: function ( width, height ) {
|
||||||
|
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
|
||||||
|
mesh.scale.set( this.width / frame.width, this.height / frame.height, 1 );
|
||||||
|
|
||||||
|
//Reset the position as it is off when we scale stuff
|
||||||
|
resetPosition();
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the position of the displayed shadow map on the HUD
|
||||||
|
this.position = {
|
||||||
|
x: frame.x,
|
||||||
|
y: frame.y,
|
||||||
|
set: function ( x, y ) {
|
||||||
|
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
|
||||||
|
const width = scope.size.width;
|
||||||
|
const height = scope.size.height;
|
||||||
|
|
||||||
|
mesh.position.set( - window.innerWidth / 2 + width / 2 + this.x, window.innerHeight / 2 - height / 2 - this.y, 0 );
|
||||||
|
|
||||||
|
if ( doRenderLabel ) labelMesh.position.set( mesh.position.x, mesh.position.y - scope.size.height / 2 + labelCanvas.height / 2, 0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.render = function ( renderer ) {
|
||||||
|
|
||||||
|
if ( this.enabled ) {
|
||||||
|
|
||||||
|
//Because a light's .shadowMap is only initialised after the first render pass
|
||||||
|
//we have to make sure the correct map is sent into the shader, otherwise we
|
||||||
|
//always end up with the scene's first added shadow casting light's shadowMap
|
||||||
|
//in the shader
|
||||||
|
//See: https://github.com/mrdoob/three.js/issues/5932
|
||||||
|
uniforms.tDiffuse.value = light.shadow.map.texture;
|
||||||
|
|
||||||
|
userAutoClearSetting = renderer.autoClear;
|
||||||
|
renderer.autoClear = false; // To allow render overlay
|
||||||
|
renderer.clearDepth();
|
||||||
|
renderer.render( scene, camera );
|
||||||
|
renderer.autoClear = userAutoClearSetting; //Restore user's setting
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
this.updateForWindowResize = function () {
|
||||||
|
|
||||||
|
if ( this.enabled ) {
|
||||||
|
|
||||||
|
camera.left = window.innerWidth / - 2;
|
||||||
|
camera.right = window.innerWidth / 2;
|
||||||
|
camera.top = window.innerHeight / 2;
|
||||||
|
camera.bottom = window.innerHeight / - 2;
|
||||||
|
camera.updateProjectionMatrix();
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
this.update = function () {
|
||||||
|
|
||||||
|
this.position.set( this.position.x, this.position.y );
|
||||||
|
this.size.set( this.size.width, this.size.height );
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//Force an update to set position/size
|
||||||
|
this.update();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
441
public/scripts/SkeletonUtils.js
Normal file
441
public/scripts/SkeletonUtils.js
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
|
||||||
|
var AnimationClip = THREE.AnimationClip;
|
||||||
|
var AnimationMixer = THREE.AnimationMixer;
|
||||||
|
var Matrix4 = THREE.Matrix4;
|
||||||
|
var Quaternion = THREE.Quaternion;
|
||||||
|
var QuaternionKeyframeTrack = THREE.QuaternionKeyframeTrack;
|
||||||
|
var SkeletonHelper = THREE.SkeletonHelper;
|
||||||
|
var Vector3 = THREE.Vector3;
|
||||||
|
var VectorKeyframeTrack = THREE.VectorKeyframeTrack;
|
||||||
|
|
||||||
|
function getBoneName( bone, options ) {
|
||||||
|
|
||||||
|
if ( options.getBoneName !== undefined ) {
|
||||||
|
|
||||||
|
return options.getBoneName( bone );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return options.names[ bone.name ];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function retarget( target, source, options = {} ) {
|
||||||
|
|
||||||
|
const quat = new Quaternion(),
|
||||||
|
scale = new Vector3(),
|
||||||
|
relativeMatrix = new Matrix4(),
|
||||||
|
globalMatrix = new Matrix4();
|
||||||
|
|
||||||
|
options.preserveBoneMatrix = options.preserveBoneMatrix !== undefined ? options.preserveBoneMatrix : true;
|
||||||
|
options.preserveBonePositions = options.preserveBonePositions !== undefined ? options.preserveBonePositions : true;
|
||||||
|
options.useTargetMatrix = options.useTargetMatrix !== undefined ? options.useTargetMatrix : false;
|
||||||
|
options.hip = options.hip !== undefined ? options.hip : 'hip';
|
||||||
|
options.hipInfluence = options.hipInfluence !== undefined ? options.hipInfluence : new Vector3( 1, 1, 1 );
|
||||||
|
options.scale = options.scale !== undefined ? options.scale : 1;
|
||||||
|
options.names = options.names || {};
|
||||||
|
|
||||||
|
const sourceBones = source.isObject3D ? source.skeleton.bones : getBones( source ),
|
||||||
|
bones = target.isObject3D ? target.skeleton.bones : getBones( target );
|
||||||
|
|
||||||
|
let bone, name, boneTo,
|
||||||
|
bonesPosition;
|
||||||
|
|
||||||
|
// reset bones
|
||||||
|
|
||||||
|
if ( target.isObject3D ) {
|
||||||
|
|
||||||
|
target.skeleton.pose();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
options.useTargetMatrix = true;
|
||||||
|
options.preserveBoneMatrix = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( options.preserveBonePositions ) {
|
||||||
|
|
||||||
|
bonesPosition = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i < bones.length; i ++ ) {
|
||||||
|
|
||||||
|
bonesPosition.push( bones[ i ].position.clone() );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( options.preserveBoneMatrix ) {
|
||||||
|
|
||||||
|
// reset matrix
|
||||||
|
|
||||||
|
target.updateMatrixWorld();
|
||||||
|
|
||||||
|
target.matrixWorld.identity();
|
||||||
|
|
||||||
|
// reset children matrix
|
||||||
|
|
||||||
|
for ( let i = 0; i < target.children.length; ++ i ) {
|
||||||
|
|
||||||
|
target.children[ i ].updateMatrixWorld( true );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let i = 0; i < bones.length; ++ i ) {
|
||||||
|
|
||||||
|
bone = bones[ i ];
|
||||||
|
name = getBoneName( bone, options );
|
||||||
|
|
||||||
|
boneTo = getBoneByName( name, sourceBones );
|
||||||
|
|
||||||
|
globalMatrix.copy( bone.matrixWorld );
|
||||||
|
|
||||||
|
if ( boneTo ) {
|
||||||
|
|
||||||
|
boneTo.updateMatrixWorld();
|
||||||
|
|
||||||
|
if ( options.useTargetMatrix ) {
|
||||||
|
|
||||||
|
relativeMatrix.copy( boneTo.matrixWorld );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
relativeMatrix.copy( target.matrixWorld ).invert();
|
||||||
|
relativeMatrix.multiply( boneTo.matrixWorld );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore scale to extract rotation
|
||||||
|
|
||||||
|
scale.setFromMatrixScale( relativeMatrix );
|
||||||
|
relativeMatrix.scale( scale.set( 1 / scale.x, 1 / scale.y, 1 / scale.z ) );
|
||||||
|
|
||||||
|
// apply to global matrix
|
||||||
|
|
||||||
|
globalMatrix.makeRotationFromQuaternion( quat.setFromRotationMatrix( relativeMatrix ) );
|
||||||
|
|
||||||
|
if ( target.isObject3D ) {
|
||||||
|
|
||||||
|
if ( options.localOffsets ) {
|
||||||
|
|
||||||
|
if ( options.localOffsets[ bone.name ] ) {
|
||||||
|
|
||||||
|
globalMatrix.multiply( options.localOffsets[ bone.name ] );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
globalMatrix.copyPosition( relativeMatrix );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( name === options.hip ) {
|
||||||
|
|
||||||
|
globalMatrix.elements[ 12 ] *= options.scale * options.hipInfluence.x;
|
||||||
|
globalMatrix.elements[ 13 ] *= options.scale * options.hipInfluence.y;
|
||||||
|
globalMatrix.elements[ 14 ] *= options.scale * options.hipInfluence.z;
|
||||||
|
|
||||||
|
if ( options.hipPosition !== undefined ) {
|
||||||
|
|
||||||
|
globalMatrix.elements[ 12 ] += options.hipPosition.x * options.scale;
|
||||||
|
globalMatrix.elements[ 13 ] += options.hipPosition.y * options.scale;
|
||||||
|
globalMatrix.elements[ 14 ] += options.hipPosition.z * options.scale;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( bone.parent ) {
|
||||||
|
|
||||||
|
bone.matrix.copy( bone.parent.matrixWorld ).invert();
|
||||||
|
bone.matrix.multiply( globalMatrix );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
bone.matrix.copy( globalMatrix );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
|
||||||
|
|
||||||
|
bone.updateMatrixWorld();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( options.preserveBonePositions ) {
|
||||||
|
|
||||||
|
for ( let i = 0; i < bones.length; ++ i ) {
|
||||||
|
|
||||||
|
bone = bones[ i ];
|
||||||
|
name = getBoneName( bone, options ) || bone.name;
|
||||||
|
|
||||||
|
if ( name !== options.hip ) {
|
||||||
|
|
||||||
|
bone.position.copy( bonesPosition[ i ] );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( options.preserveBoneMatrix ) {
|
||||||
|
|
||||||
|
// restore matrix
|
||||||
|
|
||||||
|
target.updateMatrixWorld( true );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function retargetClip( target, source, clip, options = {} ) {
|
||||||
|
|
||||||
|
options.useFirstFramePosition = options.useFirstFramePosition !== undefined ? options.useFirstFramePosition : false;
|
||||||
|
|
||||||
|
// Calculate the fps from the source clip based on the track with the most frames, unless fps is already provided.
|
||||||
|
options.fps = options.fps !== undefined ? options.fps : ( Math.max( ...clip.tracks.map( track => track.times.length ) ) / clip.duration );
|
||||||
|
options.names = options.names || [];
|
||||||
|
|
||||||
|
if ( ! source.isObject3D ) {
|
||||||
|
|
||||||
|
source = getHelperFromSkeleton( source );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const numFrames = Math.round( clip.duration * ( options.fps / 1000 ) * 1000 ),
|
||||||
|
delta = clip.duration / ( numFrames - 1 ),
|
||||||
|
convertedTracks = [],
|
||||||
|
mixer = new AnimationMixer( source ),
|
||||||
|
bones = getBones( target.skeleton ),
|
||||||
|
boneDatas = [];
|
||||||
|
|
||||||
|
let positionOffset,
|
||||||
|
bone, boneTo, boneData,
|
||||||
|
name;
|
||||||
|
|
||||||
|
mixer.clipAction( clip ).play();
|
||||||
|
|
||||||
|
// trim
|
||||||
|
|
||||||
|
let start = 0, end = numFrames;
|
||||||
|
|
||||||
|
if ( options.trim !== undefined ) {
|
||||||
|
|
||||||
|
start = Math.round( options.trim[ 0 ] * options.fps );
|
||||||
|
end = Math.min( Math.round( options.trim[ 1 ] * options.fps ), numFrames ) - start;
|
||||||
|
|
||||||
|
mixer.update( options.trim[ 0 ] );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
mixer.update( 0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
source.updateMatrixWorld();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
for ( let frame = 0; frame < end; ++ frame ) {
|
||||||
|
|
||||||
|
const time = frame * delta;
|
||||||
|
|
||||||
|
retarget( target, source, options );
|
||||||
|
|
||||||
|
for ( let j = 0; j < bones.length; ++ j ) {
|
||||||
|
|
||||||
|
bone = bones[ j ];
|
||||||
|
name = getBoneName( bone, options ) || bone.name;
|
||||||
|
boneTo = getBoneByName( name, source.skeleton );
|
||||||
|
|
||||||
|
if ( boneTo ) {
|
||||||
|
|
||||||
|
boneData = boneDatas[ j ] = boneDatas[ j ] || { bone: bone };
|
||||||
|
|
||||||
|
if ( options.hip === name ) {
|
||||||
|
|
||||||
|
if ( ! boneData.pos ) {
|
||||||
|
|
||||||
|
boneData.pos = {
|
||||||
|
times: new Float32Array( end ),
|
||||||
|
values: new Float32Array( end * 3 )
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( options.useFirstFramePosition ) {
|
||||||
|
|
||||||
|
if ( frame === 0 ) {
|
||||||
|
|
||||||
|
positionOffset = bone.position.clone();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bone.position.sub( positionOffset );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
boneData.pos.times[ frame ] = time;
|
||||||
|
|
||||||
|
bone.position.toArray( boneData.pos.values, frame * 3 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! boneData.quat ) {
|
||||||
|
|
||||||
|
boneData.quat = {
|
||||||
|
times: new Float32Array( end ),
|
||||||
|
values: new Float32Array( end * 4 )
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
boneData.quat.times[ frame ] = time;
|
||||||
|
|
||||||
|
bone.quaternion.toArray( boneData.quat.values, frame * 4 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( frame === end - 2 ) {
|
||||||
|
|
||||||
|
// last mixer update before final loop iteration
|
||||||
|
// make sure we do not go over or equal to clip duration
|
||||||
|
mixer.update( delta - 0.0000001 );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
mixer.update( delta );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
source.updateMatrixWorld();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( let i = 0; i < boneDatas.length; ++ i ) {
|
||||||
|
|
||||||
|
boneData = boneDatas[ i ];
|
||||||
|
|
||||||
|
if ( boneData ) {
|
||||||
|
|
||||||
|
if ( boneData.pos ) {
|
||||||
|
|
||||||
|
convertedTracks.push( new VectorKeyframeTrack(
|
||||||
|
'.bones[' + boneData.bone.name + '].position',
|
||||||
|
boneData.pos.times,
|
||||||
|
boneData.pos.values
|
||||||
|
) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
convertedTracks.push( new QuaternionKeyframeTrack(
|
||||||
|
'.bones[' + boneData.bone.name + '].quaternion',
|
||||||
|
boneData.quat.times,
|
||||||
|
boneData.quat.values
|
||||||
|
) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mixer.uncacheAction( clip );
|
||||||
|
|
||||||
|
return new AnimationClip( clip.name, - 1, convertedTracks );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function clone( source ) {
|
||||||
|
|
||||||
|
const sourceLookup = new Map();
|
||||||
|
const cloneLookup = new Map();
|
||||||
|
|
||||||
|
const clone = source.clone();
|
||||||
|
|
||||||
|
parallelTraverse( source, clone, function ( sourceNode, clonedNode ) {
|
||||||
|
|
||||||
|
sourceLookup.set( clonedNode, sourceNode );
|
||||||
|
cloneLookup.set( sourceNode, clonedNode );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
clone.traverse( function ( node ) {
|
||||||
|
|
||||||
|
if ( ! node.isSkinnedMesh ) return;
|
||||||
|
|
||||||
|
const clonedMesh = node;
|
||||||
|
const sourceMesh = sourceLookup.get( node );
|
||||||
|
const sourceBones = sourceMesh.skeleton.bones;
|
||||||
|
|
||||||
|
clonedMesh.skeleton = sourceMesh.skeleton.clone();
|
||||||
|
clonedMesh.bindMatrix.copy( sourceMesh.bindMatrix );
|
||||||
|
|
||||||
|
clonedMesh.skeleton.bones = sourceBones.map( function ( bone ) {
|
||||||
|
|
||||||
|
return cloneLookup.get( bone );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
clonedMesh.bind( clonedMesh.skeleton, clonedMesh.bindMatrix );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal helper
|
||||||
|
|
||||||
|
function getBoneByName( name, skeleton ) {
|
||||||
|
|
||||||
|
for ( let i = 0, bones = getBones( skeleton ); i < bones.length; i ++ ) {
|
||||||
|
|
||||||
|
if ( name === bones[ i ].name )
|
||||||
|
|
||||||
|
return bones[ i ];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBones( skeleton ) {
|
||||||
|
|
||||||
|
return Array.isArray( skeleton ) ? skeleton : skeleton.bones;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getHelperFromSkeleton( skeleton ) {
|
||||||
|
|
||||||
|
const source = new SkeletonHelper( skeleton.bones[ 0 ] );
|
||||||
|
source.skeleton = skeleton;
|
||||||
|
|
||||||
|
return source;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function parallelTraverse( a, b, callback ) {
|
||||||
|
|
||||||
|
callback( a, b );
|
||||||
|
|
||||||
|
for ( let i = 0; i < a.children.length; i ++ ) {
|
||||||
|
|
||||||
|
parallelTraverse( a.children[ i ], b.children[ i ], callback );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
retarget,
|
||||||
|
retargetClip,
|
||||||
|
clone,
|
||||||
|
};
|
2474
public/scripts/fflate.module.js
Normal file
2474
public/scripts/fflate.module.js
Normal file
File diff suppressed because it is too large
Load Diff
1700
public/scripts/main.js
Normal file
1700
public/scripts/main.js
Normal file
File diff suppressed because it is too large
Load Diff
35459
public/scripts/three.js
Normal file
35459
public/scripts/three.js
Normal file
File diff suppressed because one or more lines are too long
51464
public/scripts/three.module.js
Normal file
51464
public/scripts/three.module.js
Normal file
File diff suppressed because one or more lines are too long
395
public/scripts/water.js
Normal file
395
public/scripts/water.js
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
( function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Work based on :
|
||||||
|
* https://github.com/Slayvin: Flat mirror for three.js
|
||||||
|
* https://home.adelphi.edu/~stemkoski/ : An implementation of water shader based on the flat mirror
|
||||||
|
* http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Water extends THREE.Mesh {
|
||||||
|
|
||||||
|
constructor( geometry, options = {} ) {
|
||||||
|
|
||||||
|
super( geometry );
|
||||||
|
this.isWater = true;
|
||||||
|
const scope = this;
|
||||||
|
const textureWidth = options.textureWidth !== undefined ? options.textureWidth : 512;
|
||||||
|
const textureHeight = options.textureHeight !== undefined ? options.textureHeight : 512;
|
||||||
|
const clipBias = options.clipBias !== undefined ? options.clipBias : 0.0;
|
||||||
|
const alpha = options.alpha !== undefined ? options.alpha : 1.0;
|
||||||
|
const time = options.time !== undefined ? options.time : 0.0;
|
||||||
|
const wave_time = options.wave_time !== undefined ? options.wave_time : 0.0;
|
||||||
|
const normalSampler = options.waterNormals !== undefined ? options.waterNormals : null;
|
||||||
|
const sunDirection = options.sunDirection !== undefined ? options.sunDirection : new THREE.Vector3( 0.70707, 0.70707, 0.0 );
|
||||||
|
const sunColor = new THREE.Color( options.sunColor !== undefined ? options.sunColor : 0xffffff );
|
||||||
|
const waterColor = new THREE.Color( options.waterColor !== undefined ? options.waterColor : 0x7F7F7F );
|
||||||
|
const eye = options.eye !== undefined ? options.eye : new THREE.Vector3( 0, 0, 0 );
|
||||||
|
const distortionScale = options.distortionScale !== undefined ? options.distortionScale : 20.0;
|
||||||
|
const side = options.side !== undefined ? options.side : THREE.FrontSide;
|
||||||
|
const fog = options.fog !== undefined ? options.fog : false; //
|
||||||
|
|
||||||
|
const mirrorPlane = new THREE.Plane();
|
||||||
|
const normal = new THREE.Vector3();
|
||||||
|
const mirrorWorldPosition = new THREE.Vector3();
|
||||||
|
const cameraWorldPosition = new THREE.Vector3();
|
||||||
|
const rotationMatrix = new THREE.Matrix4();
|
||||||
|
const lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
|
||||||
|
const clipPlane = new THREE.Vector4();
|
||||||
|
const view = new THREE.Vector3();
|
||||||
|
const target = new THREE.Vector3();
|
||||||
|
const q = new THREE.Vector4();
|
||||||
|
const textureMatrix = new THREE.Matrix4();
|
||||||
|
const mirrorCamera = new THREE.PerspectiveCamera();
|
||||||
|
const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight );
|
||||||
|
window.mirrorShader = {
|
||||||
|
uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib[ 'fog' ], THREE.UniformsLib[ 'lights' ], {
|
||||||
|
'normalSampler': {
|
||||||
|
value: null
|
||||||
|
},
|
||||||
|
'mirrorSampler': {
|
||||||
|
value: null
|
||||||
|
},
|
||||||
|
'alpha': {
|
||||||
|
value: 1.0
|
||||||
|
},
|
||||||
|
'time': {
|
||||||
|
value: 0.0
|
||||||
|
},
|
||||||
|
'wave_time': {
|
||||||
|
value: 0.0
|
||||||
|
},
|
||||||
|
'size': {
|
||||||
|
value: 1.0
|
||||||
|
},
|
||||||
|
'distortionScale': {
|
||||||
|
value: 20.0
|
||||||
|
},
|
||||||
|
'textureMatrix': {
|
||||||
|
value: new THREE.Matrix4()
|
||||||
|
},
|
||||||
|
'sunColor': {
|
||||||
|
value: new THREE.Color( 0x7F7F7F )
|
||||||
|
},
|
||||||
|
'sunDirection': {
|
||||||
|
value: new THREE.Vector3( 0.70707, 0.70707, 0 )
|
||||||
|
},
|
||||||
|
'eye': {
|
||||||
|
value: new THREE.Vector3()
|
||||||
|
},
|
||||||
|
'waterColor': {
|
||||||
|
value: new THREE.Color( 0x555555 )
|
||||||
|
}
|
||||||
|
} ] ),
|
||||||
|
vertexShader:
|
||||||
|
/* glsl */
|
||||||
|
`
|
||||||
|
uniform mat4 textureMatrix;
|
||||||
|
uniform float time;
|
||||||
|
uniform float wave_time;
|
||||||
|
|
||||||
|
varying vec4 mirrorCoord;
|
||||||
|
varying vec4 worldPosition;
|
||||||
|
varying vec2 vUv;
|
||||||
|
|
||||||
|
#include <common>
|
||||||
|
#include <fog_pars_vertex>
|
||||||
|
#include <shadowmap_pars_vertex>
|
||||||
|
#include <logdepthbuf_pars_vertex>
|
||||||
|
|
||||||
|
vec3 mod289(vec3 x) {
|
||||||
|
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 mod289(vec4 x) {
|
||||||
|
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 permute(vec4 x) {
|
||||||
|
return mod289(((x*34.0)+1.0)*x);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 taylorInvSqrt(vec4 r)
|
||||||
|
{
|
||||||
|
return 1.79284291400159 - 0.85373472095314 * r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float snoise(vec3 v) {
|
||||||
|
const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
|
||||||
|
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
|
||||||
|
|
||||||
|
// First corner
|
||||||
|
vec3 i = floor(v + dot(v, C.yyy) );
|
||||||
|
vec3 x0 = v - i + dot(i, C.xxx) ;
|
||||||
|
|
||||||
|
// Other corners
|
||||||
|
vec3 g = step(x0.yzx, x0.xyz);
|
||||||
|
vec3 l = 1.0 - g;
|
||||||
|
vec3 i1 = min( g.xyz, l.zxy );
|
||||||
|
vec3 i2 = max( g.xyz, l.zxy );
|
||||||
|
|
||||||
|
// x0 = x0 - 0.0 + 0.0 * C.xxx;
|
||||||
|
// x1 = x0 - i1 + 1.0 * C.xxx;
|
||||||
|
// x2 = x0 - i2 + 2.0 * C.xxx;
|
||||||
|
// x3 = x0 - 1.0 + 3.0 * C.xxx;
|
||||||
|
vec3 x1 = x0 - i1 + C.xxx;
|
||||||
|
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
|
||||||
|
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
|
||||||
|
|
||||||
|
// Permutations
|
||||||
|
i = mod289(i);
|
||||||
|
vec4 p = permute( permute( permute(
|
||||||
|
i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
|
||||||
|
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
|
||||||
|
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
|
||||||
|
|
||||||
|
// Gradients: 7x7 points over a square, mapped onto an octahedron.
|
||||||
|
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
|
||||||
|
float n_ = 0.142857142857; // 1.0/7.0
|
||||||
|
vec3 ns = n_ * D.wyz - D.xzx;
|
||||||
|
|
||||||
|
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
|
||||||
|
|
||||||
|
vec4 x_ = floor(j * ns.z);
|
||||||
|
vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
|
||||||
|
|
||||||
|
vec4 x = x_ *ns.x + ns.yyyy;
|
||||||
|
vec4 y = y_ *ns.x + ns.yyyy;
|
||||||
|
vec4 h = 1.0 - abs(x) - abs(y);
|
||||||
|
|
||||||
|
vec4 b0 = vec4( x.xy, y.xy );
|
||||||
|
vec4 b1 = vec4( x.zw, y.zw );
|
||||||
|
|
||||||
|
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
|
||||||
|
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
|
||||||
|
vec4 s0 = floor(b0)*2.0 + 1.0;
|
||||||
|
vec4 s1 = floor(b1)*2.0 + 1.0;
|
||||||
|
vec4 sh = -step(h, vec4(0.0));
|
||||||
|
|
||||||
|
vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
|
||||||
|
vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
|
||||||
|
|
||||||
|
vec3 p0 = vec3(a0.xy,h.x);
|
||||||
|
vec3 p1 = vec3(a0.zw,h.y);
|
||||||
|
vec3 p2 = vec3(a1.xy,h.z);
|
||||||
|
vec3 p3 = vec3(a1.zw,h.w);
|
||||||
|
|
||||||
|
// Normalise gradients
|
||||||
|
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
|
||||||
|
p0 *= norm.x;
|
||||||
|
p1 *= norm.y;
|
||||||
|
p2 *= norm.z;
|
||||||
|
p3 *= norm.w;
|
||||||
|
|
||||||
|
// Mix final noise value
|
||||||
|
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
|
||||||
|
m = m * m;
|
||||||
|
return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
|
||||||
|
dot(p2,x2), dot(p3,x3) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
mirrorCoord = modelMatrix * vec4( position, 1.0 );
|
||||||
|
worldPosition = mirrorCoord.xyzw;
|
||||||
|
mirrorCoord = textureMatrix * mirrorCoord;
|
||||||
|
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
||||||
|
gl_Position = projectionMatrix * mvPosition;
|
||||||
|
|
||||||
|
vUv = uv;
|
||||||
|
|
||||||
|
vec3 pos = position;
|
||||||
|
float noiseFreq = 3.5;
|
||||||
|
float noiseAmp = 0.45;
|
||||||
|
vec3 noisePos = vec3(pos.x * noiseFreq + time, pos.y, pos.z);
|
||||||
|
pos.z += snoise(noisePos) * noiseAmp;
|
||||||
|
|
||||||
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.);
|
||||||
|
|
||||||
|
#include <beginnormal_vertex>
|
||||||
|
#include <defaultnormal_vertex>
|
||||||
|
#include <logdepthbuf_vertex>
|
||||||
|
#include <fog_vertex>
|
||||||
|
#include <shadowmap_vertex>
|
||||||
|
}`,
|
||||||
|
fragmentShader:
|
||||||
|
/* glsl */
|
||||||
|
`
|
||||||
|
uniform sampler2D mirrorSampler;
|
||||||
|
uniform float alpha;
|
||||||
|
uniform float time;
|
||||||
|
uniform float size;
|
||||||
|
uniform float distortionScale;
|
||||||
|
uniform sampler2D normalSampler;
|
||||||
|
uniform vec3 sunColor;
|
||||||
|
uniform vec3 sunDirection;
|
||||||
|
uniform vec3 eye;
|
||||||
|
uniform vec3 waterColor;
|
||||||
|
|
||||||
|
varying vec4 mirrorCoord;
|
||||||
|
varying vec4 worldPosition;
|
||||||
|
|
||||||
|
vec4 getNoise( vec2 uv ) {
|
||||||
|
vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0);
|
||||||
|
vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 );
|
||||||
|
vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 );
|
||||||
|
vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 );
|
||||||
|
vec4 noise = texture2D( normalSampler, uv0 ) +
|
||||||
|
texture2D( normalSampler, uv1 ) +
|
||||||
|
texture2D( normalSampler, uv2 ) +
|
||||||
|
texture2D( normalSampler, uv3 );
|
||||||
|
return noise * 0.5 - 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor ) {
|
||||||
|
vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) );
|
||||||
|
float direction = max( 0.0, dot( eyeDirection, reflection ) );
|
||||||
|
specularColor += pow( direction, shiny ) * sunColor * spec;
|
||||||
|
diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <common>
|
||||||
|
#include <packing>
|
||||||
|
#include <bsdfs>
|
||||||
|
#include <fog_pars_fragment>
|
||||||
|
#include <logdepthbuf_pars_fragment>
|
||||||
|
#include <lights_pars_begin>
|
||||||
|
#include <shadowmap_pars_fragment>
|
||||||
|
#include <shadowmask_pars_fragment>
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
#include <logdepthbuf_fragment>
|
||||||
|
vec4 noise = getNoise( worldPosition.xz * size );
|
||||||
|
vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) );
|
||||||
|
|
||||||
|
vec3 diffuseLight = vec3(0.0);
|
||||||
|
vec3 specularLight = vec3(0.0);
|
||||||
|
|
||||||
|
vec3 worldToEye = eye-worldPosition.xyz;
|
||||||
|
vec3 eyeDirection = normalize( worldToEye );
|
||||||
|
sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight );
|
||||||
|
|
||||||
|
float distance = length(worldToEye);
|
||||||
|
|
||||||
|
vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale;
|
||||||
|
vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.w + distortion ) );
|
||||||
|
|
||||||
|
float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 );
|
||||||
|
float rf0 = 0.3;
|
||||||
|
float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 );
|
||||||
|
vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor;
|
||||||
|
vec3 albedo = mix( ( sunColor * diffuseLight * 0.3 + scatter ) * getShadowMask(), ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance);
|
||||||
|
vec3 outgoingLight = albedo;
|
||||||
|
gl_FragColor = vec4( outgoingLight, alpha );
|
||||||
|
|
||||||
|
#include <tonemapping_fragment>
|
||||||
|
#include <fog_fragment>
|
||||||
|
}`
|
||||||
|
};
|
||||||
|
const material = new THREE.ShaderMaterial( {
|
||||||
|
fragmentShader: mirrorShader.fragmentShader,
|
||||||
|
vertexShader: mirrorShader.vertexShader,
|
||||||
|
uniforms: THREE.UniformsUtils.clone( mirrorShader.uniforms ),
|
||||||
|
lights: true,
|
||||||
|
side: side,
|
||||||
|
fog: fog
|
||||||
|
} );
|
||||||
|
material.uniforms[ 'mirrorSampler' ].value = renderTarget.texture;
|
||||||
|
material.uniforms[ 'textureMatrix' ].value = textureMatrix;
|
||||||
|
material.uniforms[ 'alpha' ].value = alpha;
|
||||||
|
material.uniforms[ 'time' ].value = time;
|
||||||
|
material.uniforms[ 'wave_time' ].value = time;
|
||||||
|
material.uniforms[ 'normalSampler' ].value = normalSampler;
|
||||||
|
material.uniforms[ 'sunColor' ].value = sunColor;
|
||||||
|
material.uniforms[ 'waterColor' ].value = waterColor;
|
||||||
|
material.uniforms[ 'sunDirection' ].value = sunDirection;
|
||||||
|
material.uniforms[ 'distortionScale' ].value = distortionScale;
|
||||||
|
material.uniforms[ 'eye' ].value = eye;
|
||||||
|
scope.material = material;
|
||||||
|
|
||||||
|
scope.onBeforeRender = function ( renderer, scene, camera ) {
|
||||||
|
|
||||||
|
mirrorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
|
||||||
|
cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
|
||||||
|
rotationMatrix.extractRotation( scope.matrixWorld );
|
||||||
|
normal.set( 0, 0, 1 );
|
||||||
|
normal.applyMatrix4( rotationMatrix );
|
||||||
|
view.subVectors( mirrorWorldPosition, cameraWorldPosition ); // Avoid rendering when mirror is facing away
|
||||||
|
|
||||||
|
if ( view.dot( normal ) > 0 ) return;
|
||||||
|
view.reflect( normal ).negate();
|
||||||
|
view.add( mirrorWorldPosition );
|
||||||
|
rotationMatrix.extractRotation( camera.matrixWorld );
|
||||||
|
lookAtPosition.set( 0, 0, - 1 );
|
||||||
|
lookAtPosition.applyMatrix4( rotationMatrix );
|
||||||
|
lookAtPosition.add( cameraWorldPosition );
|
||||||
|
target.subVectors( mirrorWorldPosition, lookAtPosition );
|
||||||
|
target.reflect( normal ).negate();
|
||||||
|
target.add( mirrorWorldPosition );
|
||||||
|
mirrorCamera.position.copy( view );
|
||||||
|
mirrorCamera.up.set( 0, 1, 0 );
|
||||||
|
mirrorCamera.up.applyMatrix4( rotationMatrix );
|
||||||
|
mirrorCamera.up.reflect( normal );
|
||||||
|
mirrorCamera.lookAt( target );
|
||||||
|
mirrorCamera.far = camera.far; // Used in WebGLBackground
|
||||||
|
|
||||||
|
mirrorCamera.updateMatrixWorld();
|
||||||
|
mirrorCamera.projectionMatrix.copy( camera.projectionMatrix ); // Update the texture matrix
|
||||||
|
|
||||||
|
textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
|
||||||
|
textureMatrix.multiply( mirrorCamera.projectionMatrix );
|
||||||
|
textureMatrix.multiply( mirrorCamera.matrixWorldInverse ); // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
|
||||||
|
// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
|
||||||
|
|
||||||
|
mirrorPlane.setFromNormalAndCoplanarPoint( normal, mirrorWorldPosition );
|
||||||
|
mirrorPlane.applyMatrix4( mirrorCamera.matrixWorldInverse );
|
||||||
|
clipPlane.set( mirrorPlane.normal.x, mirrorPlane.normal.y, mirrorPlane.normal.z, mirrorPlane.constant );
|
||||||
|
const projectionMatrix = mirrorCamera.projectionMatrix;
|
||||||
|
q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
|
||||||
|
q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
|
||||||
|
q.z = - 1.0;
|
||||||
|
q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // Calculate the scaled plane vector
|
||||||
|
|
||||||
|
clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); // Replacing the third row of the projection matrix
|
||||||
|
|
||||||
|
projectionMatrix.elements[ 2 ] = clipPlane.x;
|
||||||
|
projectionMatrix.elements[ 6 ] = clipPlane.y;
|
||||||
|
projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
|
||||||
|
projectionMatrix.elements[ 14 ] = clipPlane.w;
|
||||||
|
eye.setFromMatrixPosition( camera.matrixWorld ); // Render
|
||||||
|
|
||||||
|
const currentRenderTarget = renderer.getRenderTarget();
|
||||||
|
const currentXrEnabled = renderer.xr.enabled;
|
||||||
|
const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
|
||||||
|
scope.visible = false;
|
||||||
|
renderer.xr.enabled = false; // Avoid camera modification and recursion
|
||||||
|
|
||||||
|
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
|
||||||
|
|
||||||
|
renderer.setRenderTarget( renderTarget );
|
||||||
|
renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
|
||||||
|
|
||||||
|
if ( renderer.autoClear === false ) renderer.clear();
|
||||||
|
renderer.render( scene, mirrorCamera );
|
||||||
|
scope.visible = true;
|
||||||
|
renderer.xr.enabled = currentXrEnabled;
|
||||||
|
renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
|
||||||
|
renderer.setRenderTarget( currentRenderTarget ); // Restore viewport
|
||||||
|
|
||||||
|
const viewport = camera.viewport;
|
||||||
|
|
||||||
|
if ( viewport !== undefined ) {
|
||||||
|
|
||||||
|
renderer.state.viewport( viewport );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
THREE.Water = Water;
|
||||||
|
|
||||||
|
} )();
|
BIN
public/seagull.glb
Normal file
BIN
public/seagull.glb
Normal file
Binary file not shown.
435
public/shaders/shaders.js
Normal file
435
public/shaders/shaders.js
Normal file
@ -0,0 +1,435 @@
|
|||||||
|
const island_vertecies = `
|
||||||
|
#include <common>
|
||||||
|
#include <shadowmap_pars_vertex>
|
||||||
|
|
||||||
|
varying vec3 vNormal;
|
||||||
|
varying vec3 vViewDir;
|
||||||
|
varying vec2 vUv;
|
||||||
|
varying vec3 FragPos;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vUv = uv;
|
||||||
|
#include <beginnormal_vertex>
|
||||||
|
#include <defaultnormal_vertex>
|
||||||
|
|
||||||
|
#include <begin_vertex>
|
||||||
|
|
||||||
|
#include <worldpos_vertex>
|
||||||
|
#include <shadowmap_vertex>
|
||||||
|
|
||||||
|
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
|
||||||
|
vec4 viewPosition = viewMatrix * modelPosition;
|
||||||
|
vec4 clipPosition = projectionMatrix * viewPosition;
|
||||||
|
|
||||||
|
vNormal = normalize(normal);
|
||||||
|
// vNormal = normalize(normalMatrix * normal);
|
||||||
|
vViewDir = normalize(-viewPosition.xyz);
|
||||||
|
|
||||||
|
FragPos = vec3(modelMatrix * vec4(position, 1.0));
|
||||||
|
|
||||||
|
gl_Position = clipPosition;
|
||||||
|
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
const island_fragments = `
|
||||||
|
#include <common>
|
||||||
|
#include <packing>
|
||||||
|
#include <lights_pars_begin>
|
||||||
|
#include <shadowmap_pars_fragment>
|
||||||
|
#include <shadowmask_pars_fragment>
|
||||||
|
|
||||||
|
uniform sampler2D texture1;
|
||||||
|
uniform sampler2D texture2;
|
||||||
|
uniform sampler2D texture3;
|
||||||
|
uniform float intensity;
|
||||||
|
uniform float pointLightsPosX;
|
||||||
|
uniform float pointLightsPosY;
|
||||||
|
uniform float pointLightsPosZ;
|
||||||
|
|
||||||
|
varying vec3 vNormal;
|
||||||
|
varying vec3 FragPos;
|
||||||
|
varying vec2 vUv;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 pointLightsPos = vec3(9.0, 10.0, -16.0);
|
||||||
|
vec3 pointLightsColor = pointLights[0].color;
|
||||||
|
|
||||||
|
|
||||||
|
vec4 t1 = texture2D( texture1, vUv );
|
||||||
|
vec4 t2 = texture2D( texture2, vUv );
|
||||||
|
vec4 t3 = texture2D( texture3, vUv );
|
||||||
|
|
||||||
|
vec4 interrim = mix( t1, t2, t2.a );
|
||||||
|
vec4 interrim2 = mix( interrim, t3, t3.a );
|
||||||
|
|
||||||
|
// vec3 lightDir = normalize(pointLightsPos - FragPos);
|
||||||
|
vec3 lightDir = normalize(pointLightsPos);
|
||||||
|
|
||||||
|
float diff = max(dot(vNormal, -lightDir), 0.0);
|
||||||
|
vec3 diffuse = diff * pointLightsColor * interrim2.rgb;
|
||||||
|
|
||||||
|
vec3 result = ( (ambientLightColor + diffuse) / 14.0);
|
||||||
|
vec4 color = vec4(result, 1.0);
|
||||||
|
|
||||||
|
gl_FragColor = vec4(color);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const palm_vertecies = `
|
||||||
|
#define STANDARD
|
||||||
|
uniform float uTime;
|
||||||
|
varying vec3 vViewPosition;
|
||||||
|
#ifdef USE_TRANSMISSION
|
||||||
|
varying vec3 vWorldPosition;
|
||||||
|
#endif
|
||||||
|
#include <common>
|
||||||
|
#include <uv_pars_vertex>
|
||||||
|
#include <uv2_pars_vertex>
|
||||||
|
#include <displacementmap_pars_vertex>
|
||||||
|
#include <color_pars_vertex>
|
||||||
|
#include <fog_pars_vertex>
|
||||||
|
#include <normal_pars_vertex>
|
||||||
|
#include <morphtarget_pars_vertex>
|
||||||
|
#include <skinning_pars_vertex>
|
||||||
|
#include <shadowmap_pars_vertex>
|
||||||
|
#include <logdepthbuf_pars_vertex>
|
||||||
|
#include <clipping_planes_pars_vertex>
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
#include <uv_vertex>
|
||||||
|
#include <uv2_vertex>
|
||||||
|
#include <color_vertex>
|
||||||
|
#include <morphcolor_vertex>
|
||||||
|
#include <beginnormal_vertex>
|
||||||
|
#include <morphnormal_vertex>
|
||||||
|
#include <skinbase_vertex>
|
||||||
|
#include <skinnormal_vertex>
|
||||||
|
#include <defaultnormal_vertex>
|
||||||
|
#include <normal_vertex>
|
||||||
|
#include <begin_vertex>
|
||||||
|
#include <morphtarget_vertex>
|
||||||
|
#include <skinning_vertex>
|
||||||
|
#include <displacementmap_vertex>
|
||||||
|
#include <project_vertex>
|
||||||
|
#include <logdepthbuf_vertex>
|
||||||
|
#include <clipping_planes_vertex>
|
||||||
|
vViewPosition = - mvPosition.xyz;
|
||||||
|
#include <worldpos_vertex>
|
||||||
|
#include <shadowmap_vertex>
|
||||||
|
#include <fog_vertex>
|
||||||
|
|
||||||
|
vUv = uv;
|
||||||
|
|
||||||
|
vec3 delta = normal * sin(position.x * position.y * uTime * 0.0001) * 10.0;
|
||||||
|
vec3 newPosition = position + delta;
|
||||||
|
|
||||||
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
|
||||||
|
|
||||||
|
#ifdef USE_TRANSMISSION
|
||||||
|
vWorldPosition = worldPosition.xyz;
|
||||||
|
#endif
|
||||||
|
}`;
|
||||||
|
const palm_fragments = `
|
||||||
|
#define STANDARD
|
||||||
|
#ifdef PHYSICAL
|
||||||
|
#define IOR
|
||||||
|
#define SPECULAR
|
||||||
|
#endif
|
||||||
|
uniform vec3 diffuse;
|
||||||
|
uniform vec3 emissive;
|
||||||
|
uniform float roughness;
|
||||||
|
uniform float metalness;
|
||||||
|
uniform float opacity;
|
||||||
|
#ifdef IOR
|
||||||
|
uniform float ior;
|
||||||
|
#endif
|
||||||
|
#ifdef SPECULAR
|
||||||
|
uniform float specularIntensity;
|
||||||
|
uniform vec3 specularColor;
|
||||||
|
#ifdef USE_SPECULARINTENSITYMAP
|
||||||
|
uniform sampler2D specularIntensityMap;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SPECULARCOLORMAP
|
||||||
|
uniform sampler2D specularColorMap;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef USE_CLEARCOAT
|
||||||
|
uniform float clearcoat;
|
||||||
|
uniform float clearcoatRoughness;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_IRIDESCENCE
|
||||||
|
uniform float iridescence;
|
||||||
|
uniform float iridescenceIOR;
|
||||||
|
uniform float iridescenceThicknessMinimum;
|
||||||
|
uniform float iridescenceThicknessMaximum;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SHEEN
|
||||||
|
uniform vec3 sheenColor;
|
||||||
|
uniform float sheenRoughness;
|
||||||
|
#ifdef USE_SHEENCOLORMAP
|
||||||
|
uniform sampler2D sheenColorMap;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SHEENROUGHNESSMAP
|
||||||
|
uniform sampler2D sheenRoughnessMap;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
varying vec3 vViewPosition;
|
||||||
|
#include <common>
|
||||||
|
#include <packing>
|
||||||
|
#include <dithering_pars_fragment>
|
||||||
|
#include <color_pars_fragment>
|
||||||
|
#include <uv_pars_fragment>
|
||||||
|
#include <uv2_pars_fragment>
|
||||||
|
#include <map_pars_fragment>
|
||||||
|
#include <alphamap_pars_fragment>
|
||||||
|
#include <alphatest_pars_fragment>
|
||||||
|
#include <aomap_pars_fragment>
|
||||||
|
#include <lightmap_pars_fragment>
|
||||||
|
#include <emissivemap_pars_fragment>
|
||||||
|
#include <bsdfs>
|
||||||
|
#include <iridescence_fragment>
|
||||||
|
#include <cube_uv_reflection_fragment>
|
||||||
|
#include <envmap_common_pars_fragment>
|
||||||
|
#include <envmap_physical_pars_fragment>
|
||||||
|
#include <fog_pars_fragment>
|
||||||
|
#include <lights_pars_begin>
|
||||||
|
#include <normal_pars_fragment>
|
||||||
|
#include <lights_physical_pars_fragment>
|
||||||
|
#include <transmission_pars_fragment>
|
||||||
|
#include <shadowmap_pars_fragment>
|
||||||
|
#include <bumpmap_pars_fragment>
|
||||||
|
#include <normalmap_pars_fragment>
|
||||||
|
#include <clearcoat_pars_fragment>
|
||||||
|
#include <iridescence_pars_fragment>
|
||||||
|
#include <roughnessmap_pars_fragment>
|
||||||
|
#include <metalnessmap_pars_fragment>
|
||||||
|
#include <logdepthbuf_pars_fragment>
|
||||||
|
#include <clipping_planes_pars_fragment>
|
||||||
|
void main() {
|
||||||
|
#include <clipping_planes_fragment>
|
||||||
|
vec4 diffuseColor = vec4( diffuse, opacity );
|
||||||
|
ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
|
||||||
|
vec3 totalEmissiveRadiance = emissive;
|
||||||
|
#include <logdepthbuf_fragment>
|
||||||
|
#include <map_fragment>
|
||||||
|
#include <color_fragment>
|
||||||
|
#include <alphamap_fragment>
|
||||||
|
#include <alphatest_fragment>
|
||||||
|
#include <roughnessmap_fragment>
|
||||||
|
#include <metalnessmap_fragment>
|
||||||
|
#include <normal_fragment_begin>
|
||||||
|
#include <normal_fragment_maps>
|
||||||
|
#include <clearcoat_normal_fragment_begin>
|
||||||
|
#include <clearcoat_normal_fragment_maps>
|
||||||
|
#include <emissivemap_fragment>
|
||||||
|
#include <lights_physical_fragment>
|
||||||
|
#include <lights_fragment_begin>
|
||||||
|
#include <lights_fragment_maps>
|
||||||
|
#include <lights_fragment_end>
|
||||||
|
#include <aomap_fragment>
|
||||||
|
vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;
|
||||||
|
vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;
|
||||||
|
#include <transmission_fragment>
|
||||||
|
vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;
|
||||||
|
#ifdef USE_SHEEN
|
||||||
|
float sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );
|
||||||
|
outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_CLEARCOAT
|
||||||
|
float dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );
|
||||||
|
vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );
|
||||||
|
outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;
|
||||||
|
#endif
|
||||||
|
#include <output_fragment>
|
||||||
|
#include <tonemapping_fragment>
|
||||||
|
#include <encodings_fragment>
|
||||||
|
#include <fog_fragment>
|
||||||
|
#include <premultiplied_alpha_fragment>
|
||||||
|
#include <dithering_fragment>
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
const particle_vertecies = `
|
||||||
|
attribute float rots;
|
||||||
|
varying float vRots;
|
||||||
|
varying vec3 pos;
|
||||||
|
varying vec2 vUv;
|
||||||
|
uniform float time;
|
||||||
|
attribute float size;
|
||||||
|
uniform float scale;
|
||||||
|
#include <common>
|
||||||
|
#include <color_pars_vertex>
|
||||||
|
#include <fog_pars_vertex>
|
||||||
|
#include <morphtarget_pars_vertex>
|
||||||
|
#include <logdepthbuf_pars_vertex>
|
||||||
|
#include <clipping_planes_pars_vertex>
|
||||||
|
|
||||||
|
vec3 mod289(vec3 x) {
|
||||||
|
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 mod289(vec4 x) {
|
||||||
|
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 permute(vec4 x) {
|
||||||
|
return mod289(((x*34.0)+1.0)*x);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 taylorInvSqrt(vec4 r)
|
||||||
|
{
|
||||||
|
return 1.79284291400159 - 0.85373472095314 * r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float snoise(vec3 v) {
|
||||||
|
const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
|
||||||
|
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
|
||||||
|
|
||||||
|
// First corner
|
||||||
|
vec3 i = floor(v + dot(v, C.yyy) );
|
||||||
|
vec3 x0 = v - i + dot(i, C.xxx) ;
|
||||||
|
|
||||||
|
// Other corners
|
||||||
|
vec3 g = step(x0.yzx, x0.xyz);
|
||||||
|
vec3 l = 1.0 - g;
|
||||||
|
vec3 i1 = min( g.xyz, l.zxy );
|
||||||
|
vec3 i2 = max( g.xyz, l.zxy );
|
||||||
|
|
||||||
|
// x0 = x0 - 0.0 + 0.0 * C.xxx;
|
||||||
|
// x1 = x0 - i1 + 1.0 * C.xxx;
|
||||||
|
// x2 = x0 - i2 + 2.0 * C.xxx;
|
||||||
|
// x3 = x0 - 1.0 + 3.0 * C.xxx;
|
||||||
|
vec3 x1 = x0 - i1 + C.xxx;
|
||||||
|
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
|
||||||
|
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
|
||||||
|
|
||||||
|
// Permutations
|
||||||
|
i = mod289(i);
|
||||||
|
vec4 p = permute( permute( permute(
|
||||||
|
i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
|
||||||
|
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
|
||||||
|
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
|
||||||
|
|
||||||
|
// Gradients: 7x7 points over a square, mapped onto an octahedron.
|
||||||
|
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
|
||||||
|
float n_ = 0.142857142857; // 1.0/7.0
|
||||||
|
vec3 ns = n_ * D.wyz - D.xzx;
|
||||||
|
|
||||||
|
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
|
||||||
|
|
||||||
|
vec4 x_ = floor(j * ns.z);
|
||||||
|
vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
|
||||||
|
|
||||||
|
vec4 x = x_ *ns.x + ns.yyyy;
|
||||||
|
vec4 y = y_ *ns.x + ns.yyyy;
|
||||||
|
vec4 h = 1.0 - abs(x) - abs(y);
|
||||||
|
|
||||||
|
vec4 b0 = vec4( x.xy, y.xy );
|
||||||
|
vec4 b1 = vec4( x.zw, y.zw );
|
||||||
|
|
||||||
|
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
|
||||||
|
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
|
||||||
|
vec4 s0 = floor(b0)*2.0 + 1.0;
|
||||||
|
vec4 s1 = floor(b1)*2.0 + 1.0;
|
||||||
|
vec4 sh = -step(h, vec4(0.0));
|
||||||
|
|
||||||
|
vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
|
||||||
|
vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
|
||||||
|
|
||||||
|
vec3 p0 = vec3(a0.xy,h.x);
|
||||||
|
vec3 p1 = vec3(a0.zw,h.y);
|
||||||
|
vec3 p2 = vec3(a1.xy,h.z);
|
||||||
|
vec3 p3 = vec3(a1.zw,h.w);
|
||||||
|
|
||||||
|
// Normalise gradients
|
||||||
|
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
|
||||||
|
p0 *= norm.x;
|
||||||
|
p1 *= norm.y;
|
||||||
|
p2 *= norm.z;
|
||||||
|
p3 *= norm.w;
|
||||||
|
|
||||||
|
// Mix final noise value
|
||||||
|
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
|
||||||
|
m = m * m;
|
||||||
|
return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
|
||||||
|
dot(p2,x2), dot(p3,x3) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
#include <color_vertex>
|
||||||
|
#include <morphcolor_vertex>
|
||||||
|
#include <begin_vertex>
|
||||||
|
#include <morphtarget_vertex>
|
||||||
|
#include <project_vertex>
|
||||||
|
gl_PointSize = size;
|
||||||
|
pos = position;
|
||||||
|
float noiseFreq = 3.5;
|
||||||
|
float noiseAmp = 0.15;
|
||||||
|
vec3 noisePos = vec3(pos.x * noiseFreq + ${Math.random() * 0.5 + 0.1}, pos.y, pos.z);
|
||||||
|
gl_Position.x += snoise(noisePos) * noiseAmp * 10.0;
|
||||||
|
gl_Position.y += snoise(noisePos) * noiseAmp * 1.0;
|
||||||
|
#ifdef USE_SIZEATTENUATION
|
||||||
|
bool isPerspective = isPerspectiveMatrix( projectionMatrix );
|
||||||
|
if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );
|
||||||
|
#endif
|
||||||
|
#include <logdepthbuf_vertex>
|
||||||
|
#include <clipping_planes_vertex>
|
||||||
|
#include <worldpos_vertex>
|
||||||
|
#include <fog_vertex>
|
||||||
|
vRots = rots;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
const particle_fragments = `
|
||||||
|
varying float vRots;
|
||||||
|
uniform sampler2D tDiffuse;
|
||||||
|
varying vec2 vUv;
|
||||||
|
uniform vec3 diffuse;
|
||||||
|
uniform float opacity;
|
||||||
|
varying vec3 pos;
|
||||||
|
|
||||||
|
#include <common>
|
||||||
|
#include <color_pars_fragment>
|
||||||
|
#include <map_particle_pars_fragment>
|
||||||
|
#include <alphatest_pars_fragment>
|
||||||
|
#include <fog_pars_fragment>
|
||||||
|
#include <logdepthbuf_pars_fragment>
|
||||||
|
#include <clipping_planes_pars_fragment>
|
||||||
|
|
||||||
|
// float rand(vec2 co)
|
||||||
|
// {
|
||||||
|
// float a = 12.9898;
|
||||||
|
// float b = 78.233;
|
||||||
|
// float c = 43758.5453;
|
||||||
|
// float dt= dot(co.xy ,vec2(a,b));
|
||||||
|
// float sn= mod(dt,3.14);
|
||||||
|
// return fract(sin(sn) * c);
|
||||||
|
// }
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
#include <clipping_planes_fragment>
|
||||||
|
vec3 outgoingLight = vec3( 0.0 );
|
||||||
|
vec4 diffuseColor = vec4( diffuse, opacity );
|
||||||
|
|
||||||
|
if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;
|
||||||
|
|
||||||
|
// outgoingLight = diffuseColor.rgb + sin(rand(vec2( time, time) ) );
|
||||||
|
// gl_FragColor.a = 0.1;
|
||||||
|
// gl_FragColor = texture2D(tDiffuse, vUv);
|
||||||
|
// gl_FragColor.r = 256.0;
|
||||||
|
// gl_FragColor.g = 256.0;
|
||||||
|
// gl_FragColor = diffuseColor;
|
||||||
|
|
||||||
|
#include <logdepthbuf_fragment>
|
||||||
|
#include <map_particle_fragment>
|
||||||
|
#include <color_fragment>
|
||||||
|
#include <alphatest_fragment>
|
||||||
|
|
||||||
|
outgoingLight = diffuseColor.rgb + rand(vec2( pos.x, pos.y) ) ;
|
||||||
|
|
||||||
|
#include <output_fragment>
|
||||||
|
#include <tonemapping_fragment>
|
||||||
|
#include <encodings_fragment>
|
||||||
|
#include <fog_fragment>
|
||||||
|
#include <premultiplied_alpha_fragment>
|
||||||
|
}
|
||||||
|
`
|
47
ship.js
Normal file
47
ship.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// const {sequelize, DataTypes} = require('./db/sql_connection');
|
||||||
|
require('dotenv').config({ path: require('node:path').resolve(process.cwd(), '.env') });
|
||||||
|
const APP_BASE_PATH = process.env.APP_BASE_PATH || "";
|
||||||
|
const express = require("express");
|
||||||
|
const app = express(); //
|
||||||
|
// const fs = require("fs");
|
||||||
|
const http = require("http").createServer(app);
|
||||||
|
const io = require("socket.io")(http);
|
||||||
|
// const path = require("path");
|
||||||
|
|
||||||
|
var id = [];
|
||||||
|
var obj_collection = {};
|
||||||
|
|
||||||
|
http.listen(process.env.PORT, process.env.HOST, function () {
|
||||||
|
console.log("game server is started");
|
||||||
|
})
|
||||||
|
|
||||||
|
io.on("connection", function (socket) {
|
||||||
|
console.log("user " + socket.id + " is connected");
|
||||||
|
socket.on("mouseclick", (coords) => {
|
||||||
|
console.log("coords");
|
||||||
|
console.log(coords);
|
||||||
|
socket.broadcast.emit("coords", coords);
|
||||||
|
id[socket.id] = coords.id;
|
||||||
|
obj_collection[coords.id] = coords;
|
||||||
|
})
|
||||||
|
socket.on("disconnect", () => {
|
||||||
|
console.log("user " + socket.id + " is disconnected");
|
||||||
|
socket.broadcast.emit("remove", id[socket.id]);
|
||||||
|
|
||||||
|
delete obj_collection[id[socket.id]];
|
||||||
|
delete id[socket.id];
|
||||||
|
})
|
||||||
|
socket.on("loaded", () => {
|
||||||
|
console.log("loaded");
|
||||||
|
io.emit("send_objects", obj_collection);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.set("view engine", "ejs");
|
||||||
|
app.use(express.static("public"));
|
||||||
|
app.use(express.json({extended: false}));
|
||||||
|
app.get("/", (req, res) => {
|
||||||
|
res.render("game", {
|
||||||
|
base_path: APP_BASE_PATH,
|
||||||
|
});
|
||||||
|
});
|
0
tmp/restart.txt
Normal file
0
tmp/restart.txt
Normal file
108
views/game.ejs
Normal file
108
views/game.ejs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<meta Content-Type: application/javascript; charset=UTF-8>
|
||||||
|
<link rel="stylesheet" type="text/css" href="./css/style.css">
|
||||||
|
<body>
|
||||||
|
<div class="big_container">
|
||||||
|
<div class="menu_ico">
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
<div class="slidecontainer">
|
||||||
|
<div id="sheet1" class="sheet">
|
||||||
|
<small>Поворот сцены — мышь + зажата левая нопка</small>
|
||||||
|
<br>
|
||||||
|
<small>Перемещение сцены — мышь + левая кнопка + shift</small>
|
||||||
|
<br>
|
||||||
|
<small>Масштаб — прокрутка или зажатие колесика</small>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<div>Море</div>
|
||||||
|
<input id="range" type="range" min="1" max="50" value="1" class="slider">
|
||||||
|
</div>
|
||||||
|
<div id="sheet2" class="sheet hide">
|
||||||
|
<small>Клик выделяет кубик — точку границы коллизии</small>
|
||||||
|
<br>
|
||||||
|
<small>Мышь + зажатая левая кнопка — перемещение кубика</small>
|
||||||
|
<br>
|
||||||
|
<small>Кнопка "Проверить" активирует движение корабля</small>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<div>Море</div>
|
||||||
|
<input id="range" type="range" min="1" max="50" value="1" class="slider">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="checkbox-container">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="map" name="map" />
|
||||||
|
<label for="map">Карта</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="collision_edit" name="collision_edit" />
|
||||||
|
<label for="collision_edit">Редактировать коллизию</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="collision_edit2" name="collision_edit" disabled = "true" checked />
|
||||||
|
<label for="collision_edit2">Обход по кривой Лагранжа</label>
|
||||||
|
<button id="lagr_test" disabled = "true">Проверить путь</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="radio" id="border_left" name="border" value="left" />
|
||||||
|
<label for="border_left">Левая граница</label>
|
||||||
|
|
||||||
|
<input type="radio" id="border_right" name="border" value="right" checked/>
|
||||||
|
<label for="border_right">Правая граница</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container">
|
||||||
|
<canvas id="c"></canvas>
|
||||||
|
<canvas id="canvas_temp"></canvas>
|
||||||
|
<canvas id="canvas_temp2"></canvas>
|
||||||
|
<div class="top-div"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
window.container = document.querySelector(".container");
|
||||||
|
window.canvas = document.querySelector('#c');
|
||||||
|
window.canvas2 = document.querySelector('#canvas_temp');
|
||||||
|
window.ctx2 = canvas2.getContext("2d");
|
||||||
|
canvas2.width = 750;
|
||||||
|
canvas2.height = 500;
|
||||||
|
|
||||||
|
window.canvas3 = document.querySelector('#canvas_temp2');
|
||||||
|
window.ctx3 = canvas3.getContext("2d");
|
||||||
|
canvas3.width = 750;
|
||||||
|
canvas3.height = 500;
|
||||||
|
// container.appendChild(canvas2);
|
||||||
|
window.loading_text = document.querySelector('.top-div');
|
||||||
|
|
||||||
|
const base_path = "<%=base_path%>";
|
||||||
|
</script>
|
||||||
|
<script src="./scripts/three.js"></script>
|
||||||
|
|
||||||
|
<script src="<%=base_path%>/socket.io/socket.io.js"></script>
|
||||||
|
<script src="./scripts/three.module.js"></script>
|
||||||
|
<script src="./scripts/OrbitControls.js"></script>
|
||||||
|
<script src="./scripts/GLTFLoader.js"></script>
|
||||||
|
<script src="./scripts/fflate.module.js"></script>
|
||||||
|
<script src="./scripts/NURBSUtils.js"></script>
|
||||||
|
<script src="./scripts/NURBSCurve.js"></script>
|
||||||
|
<script src="./scripts/FBXLoader.js"></script>
|
||||||
|
<script src="./assets/textures.js"></script>
|
||||||
|
<script src="./assets/models.js"></script>
|
||||||
|
<script src="./assets/models_man.js"></script>
|
||||||
|
<script src="./scripts/water.js"></script>
|
||||||
|
|
||||||
|
<script src='./shaders/shaders.js'>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type='module'>
|
||||||
|
import * as SkeletonUtils from './scripts/SkeletonUtils.js';
|
||||||
|
window.SkeletonUtils = SkeletonUtils;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="./scripts/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user