Created
April 15, 2016 03:41
-
-
Save kdrnic/e026873bd238a77d275a0fb4f46ea886 to your computer and use it in GitHub Desktop.
test2.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
<html> | |
<head> | |
</head> | |
<body onload="Start()"> | |
<!-- | |
<input type="button" onclick="AddBox()" value="Spawn crate"><input type="button" onmousedown="mouseD=true" onmouseup="mouseD=false" value="Spawn crates continuously"><br> | |
--> | |
<div id="screenArea" style="position: relative; background-image: url(loading.gif); width: 640px; height: 480px;"></div> | |
<br> | |
<pre> | |
Controls | |
Left/right - rotate player | |
Up/down - accelerate player | |
Space - jump | |
Ctrl - Throw ball | |
T - Third person camera | |
P - First person camera | |
</pre> | |
<script src="three.js"></script> | |
<script src="ammo.js"></script> | |
<script src="TrackballControls.js"></script> | |
<!-- <script src="FirstPersonControls.js"></script> --> | |
<script src="keycodes.js"></script> | |
<script> | |
var frameTime = 1000 / 60; | |
var mouseD = false; | |
var physFrame = 0; | |
var gfxFrame = 0; | |
var oldPhysFrame = 0; | |
var oldGfxFrame = 0; | |
var physFPS = 60; | |
var gfxFPS = 60; | |
var pressed = []; | |
var BIT = (b => 1 << b); | |
var colNull = 0; | |
var colWall = BIT(3); | |
var colPlr = BIT(1); | |
var colBall = BIT(2); | |
var colRay = BIT(0); | |
function Timestamp(){ | |
return window.performance && window.performance.now ? window.performance.now() : new Date().getTime(); | |
} | |
function InitPhysics(){ | |
var collisionConfiguration = new Ammo.btDefaultCollisionConfiguration(); | |
var dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration); | |
var overlappingPairCache = new Ammo.btDbvtBroadphase(); | |
var solver = new Ammo.btSequentialImpulseConstraintSolver(); | |
dynamicsWorld = new Ammo.btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration); | |
force.setValue(0, -10, 0); | |
dynamicsWorld.setGravity(force); | |
} | |
function MakePlayerBody(){ | |
var playerShape = new Ammo.btCapsuleShape(0.5, 1); | |
var playerMass = 1.0; | |
var playerInertia = new Ammo.btVector3(0, 0, 0); | |
playerShape.calculateLocalInertia(playerMass, playerInertia); | |
var playerInfo = new Ammo.btRigidBodyConstructionInfo(playerMass, 0, playerShape, playerInertia); | |
playerBody = new Ammo.btRigidBody(playerInfo); | |
dynamicsWorld.addRigidBody(playerBody, colPlr, colWall); | |
ResetPlayerBody(); | |
var playerGeometry = new THREE.CylinderGeometry(0.5, 0.5, 1, 16); | |
var sphereGeometry = new THREE.SphereGeometry(0.5, 16, 8); | |
sphereGeometry.translate(0, 0.5, 0); | |
playerGeometry.merge(sphereGeometry); | |
sphereGeometry.translate(0, -1, 0); | |
playerGeometry.merge(sphereGeometry); | |
var playerMaterial = new THREE.MeshBasicMaterial({color: "red"}); | |
playerBody.setAngularFactor(new Ammo.btVector3(0, 0.1, 0)); | |
playerMesh = new THREE.Mesh(playerGeometry, playerMaterial); | |
scene.add(playerMesh); | |
playerMesh.add(povCamera); | |
} | |
function ResetPlayerBody(){ | |
playerBody.getWorldTransform().setIdentity(); | |
playerBody.getWorldTransform().getOrigin().setValue(0, 10, 0); | |
playerBody.getLinearVelocity().setValue(0, 0, 0); | |
playerBody.getAngularVelocity().setValue(0, 0, 0); | |
playerBody.activate(true); | |
} | |
function MakeBall(){ | |
var pT = playerBody.getWorldTransform(); | |
var pPos = pT.getOrigin(); | |
var pRot = pT.getRotation(); | |
var ball = {}; | |
if(typeof ballInfo == "undefined"){ | |
var ballShape = new Ammo.btSphereShape(0.25); | |
var ballMass = 0.5; | |
var ballInertia = new Ammo.btVector3(0, 0, 0); | |
ballShape.calculateLocalInertia(ballMass, ballInertia); | |
ballInfo = new Ammo.btRigidBodyConstructionInfo(ballMass, 0, ballShape, ballInertia); | |
} | |
ball.body = new Ammo.btRigidBody(ballInfo); | |
ball.body.getWorldTransform().setOrigin(new Ammo.btVector3(pPos.x(), pPos.y(), pPos.z())); | |
ball.body.getWorldTransform().setRotation(new Ammo.btQuaternion(pRot.x(), pRot.y(), pRot.z(), pRot.w())); | |
dynamicsWorld.addRigidBody(ball.body, colBall, colWall | colBall); | |
SetForceLocal(ball.body, 0, 100 / 60, -200 / 60); | |
ball.body.applyImpulse(force); | |
ball.mesh = new THREE.Mesh(ballGeometry, ballMaterial); | |
scene.add(ball.mesh); | |
balls.push(ball); | |
} | |
function MakeLevelBody(){ | |
var _levelMesh = new Ammo.btTriangleMesh(); | |
var geo = levelMesh.geometry; | |
var _vertices = geo.vertices.map(v => new Ammo.btVector3(v.x, v.y, v.z)); | |
for(var faceI in geo.faces){ | |
var face = geo.faces[faceI]; | |
_levelMesh.addTriangle(_vertices[face.a], _vertices[face.b], _vertices[face.c]); | |
} | |
var levelShape = new Ammo.btBvhTriangleMeshShape(_levelMesh, true); | |
var levelInfo = new Ammo.btRigidBodyConstructionInfo(0, 0, levelShape, new Ammo.btVector3(0, 0, 0)); | |
levelBody = new Ammo.btRigidBody(levelInfo); | |
dynamicsWorld.addRigidBody(levelBody, colWall, colPlr | colBall | colRay); | |
} | |
function Start(){ | |
window.addEventListener("keyup", function (event){ | |
pressed[event.keyCode] = false; | |
}); | |
window.addEventListener("keydown", function (event){ | |
pressed[event.keyCode] = true; | |
}); | |
scene = new THREE.Scene(); | |
trackCamera = new THREE.PerspectiveCamera(75, 640/480, 0.1, 1000); | |
povCamera = new THREE.PerspectiveCamera(75, 640/480, 0.1, 1000); | |
activeCamera = povCamera; | |
renderer = new THREE.WebGLRenderer(); | |
renderer.setSize(640, 480); | |
document.getElementById("screenArea").appendChild(renderer.domElement); | |
trackCamera.position.set(0, 4, 8); | |
trackControls = new THREE.TrackballControls(trackCamera, renderer.domElement); | |
trackControls.rotateSpeed = 1.0; | |
trackControls.zoomSpeed = 1.2; | |
trackControls.panSpeed = 0.8; | |
trackControls.noZoom = false; | |
trackControls.noPan = false; | |
trackControls.staticMoving = true; | |
trackControls.dynamicDampingFactor = 0.3; | |
trackControls.keys = [65, 83, 68]; | |
var loader = new THREE.JSONLoader(); | |
loader.load('level.json', function (geometry, materials){ | |
levelMesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load('checkers.png'), side: THREE.DoubleSide})); | |
scene.add(levelMesh); | |
}); | |
InitPhysics(); | |
renderer.domElement.style.position = "absolute"; | |
fpsDiv = document.createElement("div"); | |
fpsDiv.style.position = "absolute"; | |
fpsDiv.style.color = "white"; | |
fpsDiv.style.width = "120px"; | |
fpsDiv.style.height = "32px"; | |
document.getElementById("screenArea").appendChild(fpsDiv); | |
setInterval(function(){ | |
physFPS = physFrame - oldPhysFrame; | |
gfxFPS = gfxFrame - oldGfxFrame; | |
oldPhysFrame = physFrame; | |
oldGfxFrame = gfxFrame; | |
fpsDiv.innerHTML = physFPS.toString() + " FPS logic <br>" + gfxFPS + " FPS graphics<br>" + balls.length + " balls"; | |
}, 1000); | |
ballMaterial = new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load('ball.png')}); | |
ballGeometry = new THREE.SphereGeometry(0.25, 10, 5); | |
balls = []; | |
lastFrameTime = Timestamp(); | |
setTimeout(Update, 0.95 * frameTime); | |
requestAnimationFrame(Render); | |
} | |
var force = new Ammo.btVector3(0,0,0); | |
function ApplyLocalForce(body, x, y, z){ | |
force.setValue(x, y, z); | |
body.activate(true); | |
body.applyCentralLocalForce(force); | |
} | |
function SetForceLocal(body, x, y, z){ | |
force.setValue(x, y, z); | |
var t = body.getWorldTransform(); | |
var b = t.getBasis(); | |
force.setValue(force.dot(b.getRow(0)), force.dot(b.getRow(1)), force.dot(b.getRow(2))); | |
} | |
function BodyTransformToScene(body, object){ | |
var t = body.getWorldTransform(); | |
var pos = t.getOrigin(); | |
var rot = t.getRotation(); | |
object.position.set(pos.x(), pos.y(), pos.z()); | |
object.quaternion.set(rot.x(), rot.y(), rot.z(), rot.w()); | |
} | |
function Render(){ | |
for(var i in balls){ | |
BodyTransformToScene(balls[i].body, balls[i].mesh); | |
} | |
if(typeof playerBody != "undefined"){ | |
BodyTransformToScene(playerBody, playerMesh); | |
} | |
gfxFrame++; | |
trackControls.update(); | |
renderer.render(scene, activeCamera); | |
requestAnimationFrame(Render); | |
} | |
oldCtrl = false; | |
rayFromVector = new Ammo.btVector3(); | |
rayToVector = new Ammo.btVector3(); | |
function Update(){ | |
var t = Timestamp(); | |
while(t - lastFrameTime < frameTime){ | |
t = Timestamp(); | |
} | |
lastFrameTime = Timestamp(); | |
if((typeof levelMesh != "undefined") && (typeof levelBody == "undefined")){ | |
MakeLevelBody(); | |
MakePlayerBody(); | |
} | |
physFrame++; | |
if(typeof playerBody != "undefined"){ | |
if(pressed[keyCodes.VK_LEFT]){ | |
force.setValue(0, 10, 0); | |
playerBody.activate(true); | |
playerBody.applyTorque(force); | |
} | |
if(pressed[keyCodes.VK_RIGHT]){ | |
force.setValue(0, -10, 0); | |
playerBody.activate(true); | |
playerBody.applyTorque(force); | |
} | |
if(pressed[keyCodes.VK_UP]){ | |
ApplyLocalForce(playerBody, 0, 0, -10); | |
} | |
if(pressed[keyCodes.VK_DOWN]){ | |
ApplyLocalForce(playerBody, 0, 0, 10); | |
} | |
if(pressed[keyCodes.VK_SPACE]){ | |
var res = new Ammo.ClosestRayResultCallback(); | |
var pPos = playerBody.getWorldTransform().getOrigin(); | |
rayFromVector.setValue(pPos.x(), pPos.y(), pPos.z()); | |
rayToVector.setValue(pPos.x(), pPos.y() - 1.001, pPos.z()); | |
dynamicsWorld.rayTest(rayFromVector, rayToVector, res); | |
if(res.hasHit()){ | |
jumpFrame = physFrame; | |
SetForceLocal(playerBody, 0, 5, 0); | |
playerBody.activate(true); | |
playerBody.applyImpulse(force); | |
} | |
Ammo.destroy(res); | |
} | |
if(pressed[keyCodes.VK_CONTROL] && (!oldCtrl)){ | |
MakeBall(); | |
} | |
if(pressed[keyCodes.VK_T]){ | |
activeCamera = trackCamera; | |
} | |
if(pressed[keyCodes.VK_P]){ | |
activeCamera = povCamera; | |
} | |
if(pressed[keyCodes.VK_R]){ | |
ResetPlayerBody(); | |
} | |
oldCtrl = pressed[keyCodes.VK_CONTROL]; | |
playerBody.getAngularVelocity().setY(playerBody.getAngularVelocity().y() * 0.95); | |
} | |
dynamicsWorld.stepSimulation(frameTime / 1000, 10); | |
setTimeout(Update, Math.max((0.95 * frameTime) - (Timestamp() - lastFrameTime), 0)); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment