BabylonJS - Motore di fisica
Babylon.js ha un sistema di plugin per il motore fisico che aiuta ad aggiungere interazioni alla scena.Mostra la collisione e il rimbalzo tra 2 oggetti e lo rende più simile a un'interazione nella vita reale.La demo mostrerà le palle che si scontrano tra loro e si muovono con la collisione e successivamente il riposo. Notiamo lo stesso comportamento con giochi come il biliardo, dove il giocatore colpisce la palla con il bastone e le palle entrano in collisione con le altre palle e così via.Qui, il Physics Engine cerca di dare una visione realistica delle palle scontrandosi e rimbalzando quando colpiscono la superficie del terreno. Il motore ha classi e AP che aiutano nell'applicazione di applicare impulso, forza, cambio di velocità, funzioni di callback da chiamare quando richiesto e anche quando dobbiamo eseguire determinate azioni se le mesh entrano in collisione con altre mesh.
Ci sono 3 plugin per la fisica che possono essere utilizzati:
- Cannon.js
- Oimo.js
- Energy.js
Demo
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Ball/Ground Demo</title>
<script type = "text/javascript" src="https://cdn.babylonjs.com/Oimo.js"></script>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var v3 = BABYLON.Vector3;
var createScene = function () {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("Camera", 0.86, 1.37, 250, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas);
camera.maxZ = 5000;
camera.lowerRadiusLimit = 120;
camera.upperRadiusLimit = 430;
camera.lowerBetaLimit =0.75;
camera.upperBetaLimit =1.58 ;
new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), scene);
var randomNumber = function (min, max) {
if (min == max) {
return (min);
}
var random = Math.random();
return ((random * (max - min)) + min);
};
var mat = new BABYLON.StandardMaterial("ground", scene);
var t = new BABYLON.Texture("images/gr1.jpg", scene);
t.uScale = t.vScale = 10;
mat.diffuseTexture = t;
mat.specularColor = BABYLON.Color3.Black();
var g = BABYLON.Mesh.CreateBox("ground", 200, scene);
g.position.y = -20;
g.position.x = 0
g.scaling.y = 0.01;
g.material = mat;
scene.enablePhysics(new BABYLON.Vector3(0, -10, 0), new BABYLON.OimoJSPlugin());
g.physicsImpostor = new BABYLON.PhysicsImpostor(g, BABYLON.PhysicsImpostor.BoxImpostor, {
mass: 0,
restitution: 0.9
}, scene);
var getPosition = function(y) {
return new v3(randomNumber(-100, 100), y, randomNumber(-100, 100));
};
var allspheres = [];
var y = 50;
var max = 50;
for (var index = 0; index < max; index++) {
var redSphere = BABYLON.Mesh.CreateSphere("s" + index, 32, 8, scene);
redSphere.position = getPosition(y);
redSphere.physicsImpostor = new BABYLON.PhysicsImpostor(redSphere, BABYLON.PhysicsImpostor.SphereImpostor,{
mass: 1, restitution:0.9
}, scene);
redSphere.physicsImpostor.applyImpulse(new BABYLON.Vector3(1, 2, -1), new BABYLON.Vector3(1, 2, 0));
var redMat = new BABYLON.StandardMaterial("ground", scene);
redMat.diffuseColor = new BABYLON.Color3(0.4, 0.4, 0.4);
redMat.specularColor = new BABYLON.Color3(0.4, 0.4, 0.4);
redMat.emissiveColor = BABYLON.Color3.Red();
redSphere.material = redMat;
// push all spheres in the allspheres variable
allspheres.push(redSphere);
y += 10; // increment height
}
scene.registerBeforeRender(function() {
allspheres.forEach(function(obj) {
// if the sphers falls down its updated again over here
// If object falls
if (obj.position.y < -100) {
obj.position = getPosition(200);
}
});
})
return scene;
};
var scene = createScene();
engine.runRenderLoop(function() {
scene.render();
});
</script>
</body>
</html>
Produzione
La riga di codice sopra genera il seguente output:
In questa demo abbiamo usato l'immagine images/gr1.jpg. Le immagini sono memorizzate in immagini / cartella localmente e vengono anche incollate di seguito per riferimento. Puoi scaricare qualsiasi immagine di tua scelta e utilizzarla nel link demo.
images / gr1.jpg
Spiegazione
scene.enablePhysics(new BABYLON.Vector3(0,-10,0), new BABYLON.OimoJSPlugin());
La riga sopra abilita il plugin Physics. Puoi utilizzare il plugin che preferisci. Abbiamo usato OimoJsplugin ().
g.physicsImpostor = newBABYLON.PhysicsImpostor(g, BABYLON.PhysicsImpostor.BoxImpostor, {
mass: 0,
restitution: 0.9
}, scene);
Per l'interazione, il motore fisico utilizza impostor. Quando applicato all'impostore, la forma dell'oggetto non può essere modificata. In caso di modifica, dovrà essere creato un nuovo impostore.
Per la sfera, imposteremo l'impostore e aggiungeremo anche impulso ad esso per un effetto di rimbalzo come mostrato -
redSphere.physicsImpostor = new BABYLON.PhysicsImpostor(
redSphere, BABYLON.PhysicsImpostor.SphereImpostor, {
mass: 1,
restitution:0.9
}, scene
);
redSphere.physicsImpostor.applyImpulse(
new BABYLON.Vector3(1, 2, -1),
new BABYLON.Vector3(1, 2, 0)
);
Parametri per PhysicsImposter
Considera i seguenti parametri per gli effetti fisici:
Oggetto
Qui è l'oggetto su cui vuoi applicare l'interazione. Ad esempio, sfera, scatola, ecc.
genere
Il tipo può essere uno dei seguenti:
- BABYLON.PhysicsImpostor.SphereImpostor;
- BABYLON.PhysicsImpostor.BoxImpostor;
- BABYLON.PhysicsImpostor.PlaneImpostor;
- BABYLON.PhysicsImpostor.MeshImpostor;
- BABYLON.PhysicsImpostor.CylinderImpostor;
- BABYLON.PhysicsImpostor.ParticleImpostor;
- BABYLON.PhysicsImpostor.HeightmapImpostor;
Massa
L'unico parametro obbligatorio è la massa, che è la massa dell'oggetto in kg. Uno 0 come valore creerà un impostore statico, ottimo per i pavimenti.
Restituzione
Questa è la quantità di forza che il corpo "restituirà" in caso di collisione. Un valore basso non creerà rimbalzi e un valore di 1 sarà un'interazione molto rimbalzante.
scene.registerBeforeRender(function() {
allspheres.forEach(function(obj) {
// if the sphers falls down its updated again over here
// If object falls
if (obj.position.y < -100) {
obj.position = getPosition(200);
}
});
})
Il codice sopra riportato riporta le sfere cadute a terra. Continua ad aggiornare il terreno per qualsiasi sfera caduta. Prova la demo sopra nel browser per vedere l'effetto Fisica.