<head>
<link href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@500&display=swap" rel="stylesheet">
<title>Bell Curve Simution</title>
<!-- Babylon.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/ammo.js"></script>
<script src="https://preview.babylonjs.com/cannon.js"></script>
<script src="https://preview.babylonjs.com/Oimo.js"></script>
<script src="https://preview.babylonjs.com/earcut.min.js"></script>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
<script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
</head>
<body>
<div class="container">
<div class="container"><canvas id="renderCanvas" class="container" /></div>
<div class="footer"><a href="https://hiteshsahu.com/lab">See More in Lab 🧪</a></div>
<div class="header">
<h2>Ammo JS Physics Swing<h2>
</div>
</div>
<div id="fps">0</div>
</body>
<link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet">
#renderCanvas {
position: absolute;
width: 100%;
height: 100%;
touch-action: none;
left: 0%;
right: 0%;
bottom: 0%;
top: 0%;
}
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
font-family: "Rajdhani", sans-serif;
color: white;
font-size: large;
}
a:link,
a:visited {
background-color: #f44336;
color: white;
padding: 14px 25px;
text-align: center;
text-decoration: none;
display: inline-block;
}
.container {
position: relative;
height: 100%;
width: 100%;
}
.header {
position: absolute;
left: 0;
right: 0;
top: 0;
padding-left: 10px;
text-align: center;
}
.footer {
position: absolute;
right: 0;
bottom: 0;
margin: 5px;
padding: 5px;
}
a:hover,
a:active {
background-color: red;
}
.center {
position: absolute;
background-color: #00bfa5;
left: 0%;
right: 0%;
bottom: 0%;
top: 0%;
margin: 10px;
padding: 10px;
}
#fps {
position: absolute;
background-color: black;
border: 2px solid red;
text-align: center;
font-size: 16px;
color: white;
top: 15px;
right: 10px;
width: 60px;
height: 20px;
}
const TEXTURE_FOLDER = "https://www.babylonjs-playground.com/textures/";
const GROUND_SIZE = 50;
const SKYBOX_SIZE = GROUND_SIZE * 10.0;
const nbPoints = 10;
const ropeLength = 35;
const radius = 0.2;
// States
var g_timer = null;
var shouldAnimateCamera = true;
let config = {
animateCamera: true
};
// Views
const divFps = document.getElementById("fps");
const canvas = document.getElementById("renderCanvas");
async function loadDemo() {
// Essential
const engine = new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true
});
const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3.Black();
await Ammo();
var plugin = new BABYLON.AmmoJSPlugin(false);
plugin.setTimeStep(1 / 60);
plugin.setFixedTimeStep(1 / 60);
plugin.setMaxSteps(1);
scene.enablePhysics(new BABYLON.Vector3(0, -100, 0), plugin);
var skybox = BABYLON.MeshBuilder.CreateBox(
"skyBox",
{ size: SKYBOX_SIZE },
scene
);
var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
skyboxMaterial.backFaceCulling = false;
var files = [
TEXTURE_FOLDER + "Space/space_left.jpg",
TEXTURE_FOLDER + "Space/space_up.jpg",
TEXTURE_FOLDER + "Space/space_front.jpg",
TEXTURE_FOLDER + "Space/space_right.jpg",
TEXTURE_FOLDER + "Space/space_down.jpg",
TEXTURE_FOLDER + "Space/space_back.jpg"
];
skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture(
TEXTURE_FOLDER + "skybox",
scene
);
skyboxMaterial.reflectionTexture.coordinatesMode =
BABYLON.Texture.SKYBOX_MODE;
skyboxMaterial.disableLighting = true;
skybox.material = skyboxMaterial;
var spotLight = new BABYLON.SpotLight(
"spotLight",
new BABYLON.Vector3(0, GROUND_SIZE * 3, 0),
new BABYLON.Vector3(0, -1, 0),
Math.PI,
1,
scene
);
spotLight.range = GROUND_SIZE * 5;
spotLight.diffuse = BABYLON.Color3.FromHexString("#e25822");
spotLight.diffuse = new BABYLON.Color3.FromHexString("#F96229"); //(1, 1, 1);
spotLight.specular = new BABYLON.Color3.FromHexString("#FCE13D");
var ambientLight = new BABYLON.HemisphericLight(
"ambientLight",
new BABYLON.Vector3(0, -1, 0),
scene
);
ambientLight.diffuse = new BABYLON.Color3.FromHexString("#F96229");
ambientLight.specular = new BABYLON.Color3.FromHexString("#FCE13D");
ambientLight.intensity = 5;
var camera = new BABYLON.ArcRotateCamera(
"camera",
0,
0,
10,
BABYLON.Vector3.Zero(),
scene
);
camera.setTarget(new BABYLON.Vector3(0, ropeLength / 2, 0));
camera.attachControl(canvas, true);
camera.setPosition(new BABYLON.Vector3(0, GROUND_SIZE, -GROUND_SIZE));
camera.upperRadiusLimit = SKYBOX_SIZE / 2;
var light = new BABYLON.HemisphericLight(
"hemi",
new BABYLON.Vector3(1, 1, 0),
scene
);
var wood = new BABYLON.StandardMaterial("wood", scene);
wood.diffuseTexture = new BABYLON.Texture(
"https://images.pexels.com/photos/172289/pexels-photo-172289.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2g"
);
var blackMat = new BABYLON.StandardMaterial("blackMat", scene);
blackMat.diffuseTexture = new BABYLON.Texture(
"https://images.pexels.com/photos/172292/pexels-photo-172292.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
);
var grass = new BABYLON.StandardMaterial("", scene);
grass.diffuseTexture = new BABYLON.Texture(
"https://images.pexels.com/photos/1587548/pexels-photo-1587548.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
);
var ropeMat = new BABYLON.StandardMaterial("rope", scene);
ropeMat.diffuseColor = new BABYLON.Color3(228 / 255, 108 / 255, 10 / 255);
var ground = BABYLON.MeshBuilder.CreateBox(
"ground",
{ width: GROUND_SIZE * 2, depth: GROUND_SIZE * 2, height: 1 },
scene
);
ground.physicsImpostor = new BABYLON.PhysicsImpostor(
ground,
BABYLON.PhysicsImpostor.BoxImpostor,
{ mass: 0, friction: 0, restitution: 0 },
scene
);
ground.material = grass;
var base = BABYLON.MeshBuilder.CreateCylinder(
"base",
{ height: 3, diameterTop: 4, diameterBottom: 6 },
scene
);
base.position = new BABYLON.Vector3(-18, 2, 0);
base.material = wood;
base.physicsImpostor = new BABYLON.PhysicsImpostor(
base,
BABYLON.PhysicsImpostor.BoxImpostor,
{ mass: 0, friction: 0, restitution: 0 },
scene
);
var upright = BABYLON.MeshBuilder.CreateCylinder(
"upright",
{ height: ropeLength, diameter: 3 },
scene
);
upright.position = new BABYLON.Vector3(-18, ropeLength / 2, 0);
upright.material = wood;
upright.physicsImpostor = new BABYLON.PhysicsImpostor(
upright,
BABYLON.PhysicsImpostor.BoxImpostor,
{ mass: 0, friction: 0, restitution: 0 },
scene
);
var arm = BABYLON.MeshBuilder.CreateCylinder(
"arm",
{ height: 40, diameter: 1 },
scene
);
arm.rotation.z = Math.PI / 2;
arm.position = new BABYLON.Vector3(0, ropeLength, 0);
arm.material = wood;
arm.physicsImpostor = new BABYLON.PhysicsImpostor(
arm,
BABYLON.PhysicsImpostor.BoxImpostor,
{ mass: 0, friction: 0, restitution: 0 },
scene
);
var sphereSize = 6;
let ropeShape = [];
for (var i = 0; i < 2 * Math.PI + 0.1; i += Math.PI / 8) {
ropeShape.push(
new BABYLON.Vector3(Math.cos(i), Math.sin(i), 0).scale(radius)
);
}
let ropePoints = [];
for (var i = 0; i < nbPoints; i++) {
ropePoints.push(
new BABYLON.Vector3(0, ropeLength, 0),
new BABYLON.Vector3(
-2,
ropeLength - ((ropeLength - sphereSize) * i) / nbPoints,
0
)
);
}
var ropeLeft = BABYLON.MeshBuilder.ExtrudeShape(
"ropeLeft",
{ shape: ropeShape, path: ropePoints },
scene
);
ropeLeft.material = ropeMat;
ropeLeft.physicsImpostor = new BABYLON.PhysicsImpostor(
ropeLeft,
BABYLON.PhysicsImpostor.RopeImpostor,
{ mass: 0.1, shape: ropeShape, path: ropePoints },
scene
);
ropeLeft.physicsImpostor.velocityIterations = 10;
ropeLeft.physicsImpostor.positionIterations = 10;
ropeLeft.physicsImpostor.stiffness = 1;
ropePoints = [];
for (var i = 0; i < nbPoints; i++) {
ropePoints.push(
new BABYLON.Vector3(8, ropeLength, 0),
new BABYLON.Vector3(
10,
ropeLength - ((ropeLength - sphereSize) * i) / nbPoints,
0
)
);
}
var ropeRight = BABYLON.MeshBuilder.ExtrudeShape(
"ropeRight",
{ shape: ropeShape, path: ropePoints },
scene
);
ropeRight.material = ropeMat;
ropeRight.physicsImpostor = new BABYLON.PhysicsImpostor(
ropeRight,
BABYLON.PhysicsImpostor.RopeImpostor,
{ mass: 0.1, shape: ropeShape, path: ropePoints },
scene
);
ropeRight.physicsImpostor.velocityIterations = 10;
ropeRight.physicsImpostor.positionIterations = 10;
ropeRight.physicsImpostor.stiffness = 1;
var swingBase = BABYLON.MeshBuilder.CreateBox(
"swingBase",
{ width: 15, depth: 8, height: 1 },
scene
);
swingBase.position = new BABYLON.Vector3(4, 8, 0);
swingBase.material = blackMat;
swingBase.physicsImpostor = new BABYLON.PhysicsImpostor(
swingBase,
BABYLON.PhysicsImpostor.BoxImpostor,
{ mass: 10 },
scene
);
ropeRight.physicsImpostor.addHook(arm.physicsImpostor, 0, 1);
ropeLeft.physicsImpostor.addHook(arm.physicsImpostor, 0, 1);
ropeRight.physicsImpostor.addHook(swingBase.physicsImpostor, 1, 1);
ropeLeft.physicsImpostor.addHook(swingBase.physicsImpostor, 1, 1);
var impulseDirection = new BABYLON.Vector3(1, 0, -1);
var impulseMagnitude = 100;
swingBase.physicsImpostor.applyImpulse(
impulseDirection.scale(impulseMagnitude),
swingBase.getAbsolutePosition()
);
swingBase.actionManager = new BABYLON.ActionManager(scene);
var hl = new BABYLON.HighlightLayer("hl1", scene);
swingBase.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(
BABYLON.ActionManager.OnPickTrigger,
function (bjsevt) {
var impulseDirection = new BABYLON.Vector3(
0, // randomBetween(-1, 1),
0,
randomBetween(-1, 1)
);
var impulseMagnitude = randomBetween(100, 1000);
swingBase.physicsImpostor.applyImpulse(
impulseDirection.scale(impulseMagnitude),
swingBase.getAbsolutePosition()
);
hl.addMesh(swingBase, BABYLON.Color3.Random());
}
)
);
var ticker = 0;
scene.registerBeforeRender(() => {});
var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI(
"UI"
);
var panel = new BABYLON.GUI.StackPanel();
panel.width = "220px";
panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
panel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER;
advancedTexture.addControl(panel);
var header = new BABYLON.GUI.TextBlock();
header.height = "30px";
header.color = "red";
header.text = "Control";
panel.addControl(header);
var rotateCameraHeader = new BABYLON.GUI.TextBlock();
rotateCameraHeader.height = "19px";
rotateCameraHeader.color = "white";
rotateCameraHeader.text = "Animate Camera: ";
panel.addControl(rotateCameraHeader);
var checkbox = new BABYLON.GUI.Checkbox();
checkbox.width = "20px";
checkbox.height = "20px";
checkbox.isChecked = config.animateCamera;
checkbox.color = "green";
checkbox.onIsCheckedChangedObservable.add((value) => {
config.animateCamera = value;
});
panel.addControl(checkbox);
scene.registerBeforeRender(() => {
skybox.rotation.y += 0.0005;
if (shouldAnimateCamera && config.animateCamera) {
camera.alpha += 0.0016;
}
});
scene.onPointerObservable.add((pointerInfo) => {
switch (pointerInfo.type) {
case BABYLON.PointerEventTypes.POINTERDOWN:
if (config.animateCamera && shouldAnimateCamera) {
resetTimer();
}
break;
case BABYLON.PointerEventTypes.POINTERUP:
if (config.animateCamera && shouldAnimateCamera) {
startTimer();
}
break;
case BABYLON.PointerEventTypes.POINTERMOVE:
break;
default:
break;
}
});
engine.runRenderLoop(() => {
if (scene) scene.render();
divFps.innerHTML = engine.getFps().toFixed() + " fps";
});
window.addEventListener("resize", () => {
engine.resize();
});
}
loadDemo();
startTimer = () => {
g_timer = window.setTimeout(() => {
shouldAnimateCamera = true;
}, 5000);
};
resetTimer = () => {
clearTimeout(g_timer);
shouldAnimateCamera = false;
};
randomBetween = (min, max) => {
return min + Math.random() * (max + 1 - min);
};
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.