diff --git a/package-lock.json b/package-lock.json index 83a3d68..5f604bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "devDependencies": { "@sveltejs/adapter-auto": "^2.0.0", "@sveltejs/kit": "^1.5.0", + "@types/three": "^0.152.1", "svelte": "^3.54.0", "svelte-check": "^3.0.1", "typescript": "^4.9.3", @@ -514,6 +515,12 @@ "vite": "^4.0.0" } }, + "node_modules/@tweenjs/tween.js": { + "version": "18.6.4", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-18.6.4.tgz", + "integrity": "sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ==", + "dev": true + }, "node_modules/@types/cookie": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.1.tgz", @@ -526,6 +533,31 @@ "integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==", "dev": true }, + "node_modules/@types/stats.js": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.0.tgz", + "integrity": "sha512-9w+a7bR8PeB0dCT/HBULU2fMqf6BAzvKbxFboYhmDtDkKPiyXYbjoe2auwsXlEFI7CFNMF1dCv3dFH5Poy9R1w==", + "dev": true + }, + "node_modules/@types/three": { + "version": "0.152.1", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.152.1.tgz", + "integrity": "sha512-PMOCQnx9JRmq+2OUGTPoY9h1hTWD2L7/nmuW/SyNq1Vbq3Lwt3MNdl3wYSa4DvLTGv62NmIXD9jYdAOwohwJyw==", + "dev": true, + "dependencies": { + "@tweenjs/tween.js": "~18.6.4", + "@types/stats.js": "*", + "@types/webxr": "*", + "fflate": "~0.6.9", + "lil-gui": "~0.17.0" + } + }, + "node_modules/@types/webxr": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.2.tgz", + "integrity": "sha512-szL74BnIcok9m7QwYtVmQ+EdIKwbjPANudfuvDrAF8Cljg9MKUlIoc1w5tjj9PMpeSH3U1Xnx//czQybJ0EfSw==", + "dev": true + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -867,6 +899,12 @@ "reusify": "^1.0.4" } }, + "node_modules/fflate": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz", + "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==", + "dev": true + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1232,6 +1270,12 @@ "node": ">=6" } }, + "node_modules/lil-gui": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.17.0.tgz", + "integrity": "sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==", + "dev": true + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", diff --git a/package.json b/package.json index 5c7fac1..285d2b2 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "devDependencies": { "@sveltejs/adapter-auto": "^2.0.0", "@sveltejs/kit": "^1.5.0", + "@types/three": "^0.152.1", "svelte": "^3.54.0", "svelte-check": "^3.0.1", "typescript": "^4.9.3", diff --git a/src/lib/three/Factory/Water.svelte b/src/lib/three/Factory/Water.svelte index af6290b..26078b8 100644 --- a/src/lib/three/Factory/Water.svelte +++ b/src/lib/three/Factory/Water.svelte @@ -4,7 +4,7 @@ import { Water } from "three/examples/jsm/objects/Water.js"; export const WaterFactory = (scene) => { - const waterGeometry = new THREE.PlaneGeometry(5000, 5000); + const waterGeometry = new THREE.PlaneGeometry(1000, 1000, 500, 500); const waterMaterial = { textureWidth: 512, textureHeight: 512, @@ -22,12 +22,32 @@ fog: scene.fog !== undefined, }; const water = new Water(waterGeometry, waterMaterial); + water.name = "ocean" water.rotation.x = -Math.PI / 2; water.wave = () => { water.material.uniforms["time"].value += 1.0 / 60.0; }; + water.activeWave = (hitPoint, hitTime) => { + const deltaTime = performance.now() * 0.01; + if (deltaTime - hitTime > 50) { + return ; + } + const position = water.geometry.attributes.position; + for (let i = 0; i < position.count; i++) { + const vector = new THREE.Vector3(); + const height = Math.exp(-((deltaTime - hitTime) * 0.1)); + vector.fromBufferAttribute(position, i); + const distance = vector.distanceTo(hitPoint); + const effectedDistance = 10; + const wave = Math.cos(deltaTime + distance / 2); + vector.z = height * Math.max(effectedDistance - (distance / 2), 0) * wave; + position.setXYZ(i, vector.x, vector.y, vector.z); + } + position.needsUpdate = true; + }; + return water; }; diff --git a/src/lib/three/scene.svelte b/src/lib/three/scene.svelte index 785c084..c8014ef 100644 --- a/src/lib/three/scene.svelte +++ b/src/lib/three/scene.svelte @@ -25,6 +25,9 @@ export const sun = new SunFactory(scene, sky, water, new THREE.PMREMGenerator(renderer)); let mouse = new THREE.Vector2(); + let hitPoint = new THREE.Vector3(); + let hitTime = performance.now() * 0.01; + const controls = new OrbitControls(camera, renderer.domElement); loader.load( @@ -51,6 +54,7 @@ requestAnimationFrame(animate); water.wave(); + water.activeWave(hitPoint, hitTime); controlCamera(); resize(renderer, camera); renderer.render(scene, camera); @@ -92,6 +96,11 @@ let ray = new THREE.Raycaster(); ray.setFromCamera(mouse, camera); let intersects = ray.intersectObjects(scene.children); + if (intersects[0].object.isWater === true) + { + hitPoint = new THREE.Vector3(water.geometry.parameters.width * (intersects[0].uv.x - 0.5), water.geometry.parameters.height * (intersects[0].uv.y - 0.5), 0); + hitTime = performance.now() * 0.01; + } if ( intersects.length > 0 && intersects[0].object.name === "defaultMaterial_1" @@ -127,7 +136,8 @@ export const createScene = () => { document.querySelector(".app").append(renderer.domElement); resize(renderer, camera); - sun.darken(); + // sun.darken(); + sun.lighten(); animate(); };