Simulación del navegador de física



En este artículo quiero describir las soluciones existentes para crear aplicaciones con simulaciones físicas, comparar su rendimiento y las herramientas proporcionadas.

Introduccion


Los siguientes motores serán considerados en el artículo:

Ammo.js
Cannon.js
Oimo.js
box2dweb
Unity3D WebGL

El objetivo principal era elegir el motor más productivo, conveniente y liviano para desarrollar juegos y aplicaciones utilizando simulaciones físicas.

Ammo.js


Es un puerto del motor de física Bullet en javascript que utiliza el compilador Emscripten y, según los desarrolladores, tiene una funcionalidad casi idéntica. La funcionalidad de Ammo.js es realmente extensa. Para trabajar con él, necesita una biblioteca separada para la visualización. El más utilizado es Three.js. Además, cada ciclo de redibujado tendrá que sincronizar manualmente la posición y la rotación de cada objeto en la escena con su modelo físico, el motor no hace esto automáticamente.

En cuanto al rendimiento, no es demasiado alto, pero no habrá reducciones notables de fps en la mayoría de los proyectos.

La API a veces puede ser bastante confusa y la documentación realmente no ayuda.
En general, una muy buena herramienta que continúa desarrollándose y desarrollándose aún más.

Cannon.js


Cannon.js es un motor de física ligera de código abierto. A diferencia del anterior, originalmente se escribió en JavaScript y le permite utilizar todas sus funciones y optimizaciones. De hecho, es difícil decir si esto es más o menos, ya que el código compilado puede ser mucho más eficiente que escribirlo desde cero. Sin embargo, cannon.js se considera más compacto, más productivo y también más fácil de entender en comparación con ammo.js, pero no tiene tantas funciones. En la práctica, su rendimiento suele ser aproximadamente el mismo.

El proceso de trabajar con el motor es bastante simple:

//   var world = new CANNON.World(); world.gravity.set(0, 0, -9.82); //   (   ) //        var radius = 1; var sphereBody = new CANNON.Body({ mass: 5, position: new CANNON.Vec3(0, 0, 10), shape: new CANNON.Sphere(radius) }); world.addBody(sphereBody); var fixedTimeStep = 1.0 / 60.0; var maxSubSteps = 3; //    var lastTime; (function simloop(time){ requestAnimationFrame(simloop); if(lastTime !== undefined){ var dt = (time - lastTime) / 1000; world.step(fixedTimeStep, dt, maxSubSteps); } lastTime = time; })(); 

También se requiere una biblioteca gráfica de terceros para el trabajo, y cada ciclo de renderizado tendrá que mover manualmente el objeto correspondiente en la escena a la ubicación del objeto físico.

 mesh.position.x = body.position.x; mesh.position.y = body.position.y; mesh.position.z = body.position.z; mesh.quaternion.x = body.quaternion.x; mesh.quaternion.y = body.quaternion.y; mesh.quaternion.z = body.quaternion.z; mesh.quaternion.w = body.quaternion.w; 

Por el momento, el motor prácticamente no se está desarrollando, la última actividad en el repositorio del proyecto hace más de 2 años, y en ese momento el motor apenas comenzaba a desarrollarse, por lo que en algunos lugares puede no funcionar.

Oimo.js


Oimo.js es una versión del motor OimoPhysics reescrito en javascript puro. En comparación con otras soluciones, tiene muy buen rendimiento y precisión, pero solo admite geometría primitiva (cubos y esferas). Se incluye en Babylon.js, un marco para renderizar gráficos 2D y 3D, por lo que no se requieren bibliotecas adicionales.

 //   world = new OIMO.World({ timestep: 1/60, iterations: 8, broadphase: 2, worldscale: 1, random: true, info: false, gravity: [0,-9.8,0] }); //    var body = world.add({ type:'sphere', size:[1,1,1], pos:[0,0,0], rot:[0,0,90], move:true, density: 1, friction: 0.2, restitution: 0.2, belongsTo: 1, collidesWith: 0xffffffff; }); var body = world.add({ type:'jointHinge', body1: "b1", body2: "b1", }); world.step(); //           myMesh.position.copy( body.getPosition() ); myMesh.quaternion.copy( body.getQuaternion() ); 

Una gran desventaja del motor no es la documentación de muy alta calidad, pero los desarrolladores continúan trabajando en ello.

Por el momento, el motor continúa desarrollándose.

box2dweb


box2dweb es el puerto javascript box2d. Como su nombre lo indica, se especializa en simular física 2D. A pesar de esto, box2dweb es una herramienta bastante poderosa que no se queda atrás de sus contrapartes tridimensionales. Por ejemplo, el motor incluye sistemas extremadamente convenientes para detectar colisiones y simular conexiones (restricción).

En cuanto al rendimiento, debe intentar escribir un código no óptimo para que aparezcan las reducciones de fps.

De las ventajas, también vale la pena mencionar la simplicidad de la API y la documentación conveniente.

Unidad3d


Unity3D es un popular motor de juegos multiplataforma. Incluye un sencillo y conveniente editor de arrastrar y soltar y un extenso kit de herramientas para crear contenido 3D. La última versión del motor para escribir la lógica del juego es compatible con C #.

Unity tiene una simulación física incorporada, para esto utiliza el motor PhysX incorporado de NVIDIA. PhysX proporciona una amplia funcionalidad para simular la física de sólidos, líquidos y tejidos, y tiene un rendimiento muy bueno, aunque se cancelan muchas ventajas cuando se trabaja en aceleradores gráficos que no sean NVIDIA. Un hecho extremadamente agradable es que desde el 3 de diciembre de 2018, el código fuente del motor está disponible bajo la licencia abierta BSD-3, sin embargo, el motor es demasiado complejo para intentar reescribirlo usted mismo o comprender su dispositivo, por lo que la documentación ayudará aquí mejor.

Unity terminó en esta lista, ya que es posible construir un proyecto en él bajo WebGL. Para hacer esto, simplemente seleccione el elemento apropiado en la configuración de compilación.



Sin embargo, la versión WebGL de Unity, debido a los detalles de su arquitectura (traduciendo el código de C # a C ++ y luego a JavaScript), tiene varios problemas con el rendimiento, el consumo de memoria y la capacidad de trabajo en dispositivos móviles, y no parece que los desarrolladores vayan a hacer esto. algo que hacer pronto Por lo tanto, esta opción no es popular y no la consideraré en detalle.

Comparación de rendimiento


Comparemos el rendimiento de los motores por la forma en que manejan el procesamiento de colisiones de una gran cantidad de objetos. El navegador utilizado es Firefox 64.0.2 x64.
Motorfps al procesar 100 objetosfps al procesar 500 objetosfps al procesar 1000 objetos
ammo.js40-5025-2715-25
cannon.js30-4020-2515-20
oimo.js45-5535-4035-40

Según los resultados de la prueba, Oimo.js muestra el mejor rendimiento.

Por supuesto, estos resultados no proporcionan una evaluación adecuada de la productividad, ya que dependen de muchos factores de terceros, pero un estudio completo requeriría mucho más tiempo, y no me propuse ese objetivo. Además, es notable que el rendimiento de todos los motores comparados es bastante pequeño, por lo que estas soluciones no son adecuadas para escribir lejos de cada juego, pero son adecuadas para crear demostraciones pequeñas.

Conclusión


En general, la elección de un motor en particular depende de la tarea. Si necesita un motor fácil de entender y aprender, Cannon.js u Oimo.js. es muy adecuado. Si se requiere más funcionalidad, es mejor usar Ammo.js. En ciertas situaciones, si no se requiere un gran rendimiento, puede intentar usar Unity.

Source: https://habr.com/ru/post/es436192/


All Articles