-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
camera controllers improvements; bugfix; (#19)
* added shooter example * upgraded three.js * fixed putting random color on generated primitive with provided texture * example code adjustments * Revert "upgraded three.js" This reverts commit 451dedd. * input controllers adjustments * added collision margin to engine and ammo factory * minor improvements * minor improvements * elastic free camera movement * elastic free camera movement * finalized elastic free camera movement * added elasticity to orbit camera controller and free camera rotation * code alignment * minor adjustments
- Loading branch information
Showing
26 changed files
with
5,222 additions
and
101 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<meta charset='utf-8'> | ||
<title>GG example</title> | ||
<meta name='viewport' content='width=device-width,initial-scale=1'> | ||
</head> | ||
<body> | ||
<style> | ||
body { | ||
color: #000; | ||
font-family: Monospace; | ||
text-align: center; | ||
background-color: #bfd1e5; | ||
margin: 0px; | ||
overflow: hidden; | ||
font-size: 150% | ||
} | ||
|
||
#message { | ||
position: absolute; | ||
width: 100%; | ||
top: 0; | ||
padding-top: 1em; | ||
color: #777; | ||
font-size: 80% | ||
} | ||
|
||
#blocker { | ||
position: absolute; | ||
width: 100%; | ||
height: 100%; | ||
background-color: rgba(0, 0, 0, 0.65); | ||
padding-top: 10em; | ||
color: #FFF; | ||
text-shadow: 1px 1px 20px #000; | ||
pointer-events: none; | ||
} | ||
|
||
[hidden] { | ||
display: none | ||
} | ||
|
||
div.info { | ||
color: #BBB; | ||
font-size: 80% | ||
} | ||
|
||
a { | ||
color: #b7bd6f; | ||
cursor: pointer; | ||
pointer-events: all; | ||
} | ||
#container { | ||
position: absolute; | ||
} | ||
</style> | ||
<div id='container'> | ||
<canvas id='gg'></canvas> | ||
</div> | ||
<div id='message' hidden> | ||
Mouse and W, A, S, D = move<br /> | ||
CLICK = shoot balls<br /> | ||
Press ESC to pause | ||
</div> | ||
<div id='blocker'> | ||
<span style='font-size:250%'>Click to play</span> | ||
<br /><br /> | ||
Mouse and W, A, S, D = move<br /> | ||
CLICK = shoot balls<br /> | ||
Press ESC to pause | ||
<br /><br /><br /><br /> | ||
<div class='info'> | ||
<a href='http://static.componenthouse.com/webgl-shooter/main.html' target='_new'>Original demo</a> | ||
<br /><br /> | ||
Author of the original demo: <a href='https://www.linkedin.com/in/hugovteixeira' target='_new'>Hugo Teixeira</a> | ||
| <a href='https://componenthouse.com/2016/11/08/having-fun-with-typescript-threejs-and-ammo-js/' target='_new'>Read | ||
Full Article</a> | ||
| <a href='https://github.com/hvidal/WebGL-Shooter' target='_new'>Source Code</a> | ||
<br /><br /> | ||
Ported to <a href='https://github.com/AndyGura/gg-web-engine' target='_new'>GG web engine</a> | ||
by <a href='https://github.com/AndyGura' target='_new'>Andy Gura</a> | ||
| <a href='https://github.com/AndyGura/gg-web-engine/tree/main/examples/shooter-three-ammo' target='_new'>Source | ||
Code</a> | ||
</div> | ||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import { FreeCameraController, Gg3dWorld, GgStatic, Pnt3, Qtrn } from '@gg-web-engine/core'; | ||
import { ThreeSceneComponent, ThreeVisualTypeDocRepo } from '@gg-web-engine/three'; | ||
import { AmbientLight, DirectionalLight, Mesh, MeshPhongMaterial, RepeatWrapping, TextureLoader } from 'three'; | ||
import { AmmoPhysicsTypeDocRepo, AmmoWorldComponent } from '@gg-web-engine/ammo'; | ||
|
||
const world = new Gg3dWorld< | ||
ThreeVisualTypeDocRepo, | ||
AmmoPhysicsTypeDocRepo, | ||
ThreeSceneComponent, | ||
AmmoWorldComponent | ||
>( | ||
new ThreeSceneComponent(), | ||
new AmmoWorldComponent(), | ||
); | ||
world.physicsWorld.maxSubSteps = 10; | ||
world.physicsWorld.fixedTimeStep = null; | ||
|
||
GgStatic.instance.showStats = true; | ||
// GgStatic.instance.devConsoleEnabled = true; | ||
|
||
world.init().then(async () => { | ||
// init graphics | ||
const canvas = document.getElementById('gg')! as HTMLCanvasElement; | ||
const renderer = world.addRenderer( | ||
world.visualScene.factory.createPerspectiveCamera({ fov: 45, frustrum: { near: 0.2, far: 1000 } }), | ||
canvas, | ||
{ background: 0xBFD1E5 }, | ||
); | ||
renderer.camera.position = { x: 40, y: 40, z: 25 }; | ||
renderer.camera.rotation = Qtrn.lookAt(renderer.camera.position, { x: 0, y: 0, z: 10 }, Pnt3.Z); | ||
|
||
const dirLight = new DirectionalLight(0xffffff, 2.5); | ||
dirLight.castShadow = true; | ||
dirLight.position.set(50, 50, 100); | ||
const d = 100; | ||
dirLight.shadow.camera.left = -d; | ||
dirLight.shadow.camera.right = d; | ||
dirLight.shadow.camera.top = d; | ||
dirLight.shadow.camera.bottom = -d; | ||
dirLight.shadow.camera.near = 2; | ||
dirLight.shadow.camera.far = 500; | ||
dirLight.shadow.mapSize.x = 4096; | ||
dirLight.shadow.mapSize.y = 4096; | ||
world.visualScene.nativeScene.add(dirLight); | ||
|
||
const ambientLight = new AmbientLight(0x606060); | ||
world.visualScene.nativeScene.add(ambientLight); | ||
|
||
const textureLoader = new TextureLoader(); | ||
// create objects | ||
const [groundTexture, brickTexture] = await Promise.all([ | ||
textureLoader.loadAsync('https://gg-web-demos.guraklgames.com/assets/shooter/cement.jpg'), | ||
textureLoader.loadAsync('https://gg-web-demos.guraklgames.com/assets/shooter/brick.jpg'), | ||
]); | ||
groundTexture.wrapS = brickTexture.wrapS = RepeatWrapping; | ||
groundTexture.wrapT = brickTexture.wrapT = RepeatWrapping; | ||
groundTexture.repeat.set(5, 5); | ||
|
||
let material = [ | ||
new MeshPhongMaterial({ color: 0xB7B7B7, map: brickTexture }), | ||
new MeshPhongMaterial({ color: 0xAAAAAA, map: brickTexture }), | ||
new MeshPhongMaterial({ color: 0xA4A4A4, map: brickTexture }), | ||
new MeshPhongMaterial({ color: 0x979797, map: brickTexture }), | ||
new MeshPhongMaterial({ color: 0x949494, map: brickTexture }), | ||
new MeshPhongMaterial({ color: 0x909090, map: brickTexture }), | ||
]; | ||
const brickMass = 20; | ||
|
||
const createWall_X_axis = (startX: number, endX: number, y: number, zCount: number, shift: boolean) => { | ||
for (let z = 0; z <= zCount; z += 1.5) { | ||
let offsetX = shift ? 1.5 : 0; | ||
shift = !shift; | ||
for (let x = startX; x <= endX; x += 3) { | ||
const item = world.addPrimitiveRigidBody({ | ||
shape: { shape: 'BOX', dimensions: { x: 3, y: 1.5, z: 1.5 }, collisionMargin: 0.05 }, | ||
body: { dynamic: true, mass: brickMass }, | ||
}, { x: x + offsetX, y, z: z + 0.75 }, Qtrn.O, { castShadow: true, receiveShadow: true }); | ||
const materialIndex = Math.floor(Math.random() * material.length); | ||
(item.object3D.nativeMesh as Mesh).material = material[materialIndex]; | ||
} | ||
} | ||
}; | ||
|
||
const createWall_Y_axis = (startY: number, endY: number, x: number, zCount: number, shift: boolean) => { | ||
const quat = Qtrn.fromAngle(Pnt3.Z, Math.PI / 2); | ||
for (let z = 0; z <= zCount; z += 1.5) { | ||
let offsetY = shift ? 1.5 : 0; | ||
shift = !shift; | ||
for (let y = startY; y <= endY; y += 3) { | ||
const item = world.addPrimitiveRigidBody({ | ||
shape: { shape: 'BOX', dimensions: { x: 3, y: 1.5, z: 1.5 }, collisionMargin: 0.05 }, | ||
body: { dynamic: true, mass: brickMass }, | ||
}, { x, y: y + offsetY, z: z + 0.75 }, Qtrn.O, { castShadow: true, receiveShadow: true }); | ||
item.rotation = quat; | ||
const materialIndex = Math.floor(Math.random() * material.length); | ||
(item.object3D.nativeMesh as Mesh).material = material[materialIndex]; | ||
} | ||
} | ||
}; | ||
createWall_X_axis(-8.25, 8.25, -9.75, 15, true); | ||
createWall_X_axis(-8.25, 8.25, 11.25, 15, false); | ||
createWall_Y_axis(-9, 9, -9, 15, false); | ||
createWall_Y_axis(-9, 9, 9, 15, true); | ||
|
||
world.addPrimitiveRigidBody( | ||
{ | ||
shape: { shape: 'BOX', dimensions: { x: 100, y: 100, z: 1 }, collisionMargin: 0.05 }, | ||
body: { dynamic: false, mass: 0 }, | ||
}, | ||
{ x: 0, y: 0, z: -0.5 }, | ||
Qtrn.O, | ||
{ shading: 'phong', castShadow: true, receiveShadow: true, diffuse: groundTexture }, | ||
); | ||
|
||
const cameraController = new FreeCameraController( | ||
world.keyboardInput, | ||
renderer, | ||
{ | ||
keymap: 'wasd', | ||
mouseOptions: { canvas, pointerLock: true }, | ||
cameraLinearSpeed: 50, | ||
cameraMovementElasticity: 100, | ||
cameraRotationSensitivity: 0.8, | ||
ignoreMouseUnlessPointerLocked: true, | ||
ignoreKeyboardUnlessPointerLocked: true, | ||
}); | ||
world.addEntity(cameraController); | ||
|
||
|
||
let ballMaterial = new MeshPhongMaterial({ color: 0x202020 }); | ||
|
||
window.addEventListener('mousedown', (event) => { | ||
let element = <Element> event.target; | ||
if (element.nodeName == 'A' || world.isPaused) | ||
return; | ||
else { | ||
let ball = world.addPrimitiveRigidBody( | ||
{ | ||
body: { mass: 10 }, shape: { shape: 'SPHERE', radius: 1.2, collisionMargin: 0.05 }, | ||
}, | ||
renderer.position, | ||
Qtrn.O, | ||
{ castShadow: true, receiveShadow: true }, | ||
); | ||
(ball.object3D.nativeMesh as Mesh).material = ballMaterial; | ||
|
||
ball.objectBody.linearVelocity = Pnt3.rot(Pnt3.scalarMult(Pnt3.nZ, 80), renderer.rotation); | ||
} | ||
}, false); | ||
|
||
world.start(); | ||
|
||
cameraController.mouseInput.isPointerLocked$.subscribe((l) => { | ||
if (l) { | ||
world.resumeWorld(); | ||
document.getElementById('blocker').style.display = 'none'; | ||
document.getElementById('message').style.display = 'block'; | ||
} else { | ||
document.getElementById('blocker').style.display = 'block'; | ||
document.getElementById('message').style.display = 'none'; | ||
world.pauseWorld(); | ||
} | ||
}); | ||
}); |
Oops, something went wrong.