dimforge / rapier.js Goto Github PK
View Code? Open in Web Editor NEWOfficial JavaScript bindings for the Rapier physics engine.
Home Page: https://rapier.rs
License: Apache License 2.0
Official JavaScript bindings for the Rapier physics engine.
Home Page: https://rapier.rs
License: Apache License 2.0
1, i have tested and it seems i can pass indices
as null
to ColliderDesc.polyline
and it works normally.
so should be just a mistake in the TS declration file?
2, dynamic polyline does not fall
i guess because it does not have density so no mass so not falling. please just ignore this if it's expected so.
Hi, I have been trying to build a robot simulator with Rapier.js. Thanks for the great tool.
I was trying to use joint motors. Here is how to use them in the documentation:
let joint = world.createImpulseJoint(params, body1, body2);
(joint as RAPIER.PrismaticImpulseJoint).configureMotorVelocity(1.0, 0.5);
(joint as RAPIER.PrismaticImpulseJoint)
seems like a TypeScript grammar, but my project is in vanilla JavaScript, so the webpack complains about the grammar.
I wonder whether there is way to use joint motors without TypeScript?
I tried to use joint.rawSet.jointConfigureMotorPosition
, but I couldn't find RawJointAxis
, which is the second parameter of that function.
when you call lockRotations
on an existing created dynamic rigidBody on the fly, the body will no longer move.
but call lockRotations
from the creation desc when creating it, later the created body will be locked and can be moved which works fine.
a clue if it will help:
1, lock rotation from creation rigidbodyDesc.lockRotations() will work fine (but can't unlock later by calling lockRotations(false)).
2, call lockRotations on the fly, it will lock both rotation & translation, but can unlock later.
I'm struggling with kind of an insane bug right now, or perhaps it's just undefined behavior, but i am not receiving any results of a raycast if step has not been called at least once.
The use case is I am restoring a snapshot and immediately casting and getting null.
const world = new World({x: 0.0, y: -9.81, z: 0.0});
const colliderDesc = ColliderDesc.cuboid(10, 10, 10);
const body = world.createRigidBody(RigidBodyDesc.newStatic());
const collider = world.createCollider(colliderDesc, body.handle);
world.step();
const result = world.castRay(new Ray(new Vector3(0, 20, 0), new Vector3(0, -1, 0)), 100, true, 0xfffffffff);
console.log(!!result); /*true, but would be false if I commented out step*/
const world2 = World.restoreSnapshot(world.takeSnapshot());
const result2 = world2.castRay(new Ray(new Vector3(0, 20, 0), new Vector3(0, -1, 0)), 100, true, 0xfffffffff);
console.log(!!result2); /*false*/
If this is the intended behavior, is there any thoughts on a way to "pump the gas" without explicitly calling step and pushing the simulation forward?
This is when using 0.8.0-alpha.1 @dimforge/rapier2d
Previously it has worked as intended and returned the created joint.
If taking the example from the docs:
let params = RAPIER.JointData.revolute({ x: 0.0, y: 1.0 }, { x: 0.0, y: -3.0 });
let joint = world.createImpulseJoint(params, body1, body2);
joint would be undefined if trying to create a revolute joint. It works fine when using fixed or prismatic. The joint is created and can be found in the world using world.impulseJoints.forEachJointHandle or world.impulseJoints.forEachJoint, but world.impulseJoints.get() will return undefined.
@dimforge/rapier2d 0.8.0-alpha.1
I was having problems getting limits to work properly with a prismatic joint, while trying to figure it out it seems that the following methods: limitsEnabled, limitesMax and LimitsMin are undefined.
According to the typescript these should be there. The same is true for the Revolute joint, typescript says they should be there, but they appear to be undefined.
1, colliding error when touches polygonline
kinematic body (no matter positionbased or velocitybased)
as the pic shows, the ball moving from right to left, error will throw out when it touches the polygonline.
it seems the same position in the step. not sure what happened. it seems almost all the errors are thrown from here.
2, kinematic does not collide with heightfield (static, the green line in the image)
it will just go through the heightfield line (same as the last bug report: #61)
Calls to change the shape of a collider cause the engine to crash.
You can check it with this simple instruciton:
collider.setShape(new RAPIER.Ball(2));
vendors-physics.js:67 Uncaught Error: null pointer passed to rust
at C.wbg.__wbindgen_throw (vendors-physics.js:67)
at 0032afe2:0xbf704
at 0032afe2:0xbf711
at 0032afe2:0xbab75
at u.free (vendors-physics.js:67)
at A.setShape (vendors-physics.js:67)
vendors-physics.js is just the Webpack chunk I created to load RAPIER dynamically.
@dimforge/rapier2d 0.8.0-alpha.1
The enum for RAPIER.JointType.Revolute has a value of 0, but the .type() method on a revolute joint returns 3.
Hi guys, first of all, thanks for the great library you are working on.
I'm using 0.8.0-alpha.0
version of rapier.js.
I have a ground as a static body and two dynamic bodies. I've added colliders of these bodies to one collision group and set active contact events on them with the code below:
collider.setCollisionGroups(0x00010001)
collider.setActiveEvents(
RAPIER.ActiveEvents.CONTACT_EVENTS
)
I've created an event queue and added one dummy contact event handler:
const eventQueue = new RAPIER.EventQueue(true)
eventQueue.drainContactEvents((handle1, handle2, started) => {
/* Handle the contact event. */
console.log(handle1, handle2, started)
})
in a render loop I pass eventQueue as a parameter to the step method:
world.step(eventQueue)
One of the dynamic bodies is a character controlled by a keyboard/mouse.
The problem is, that regardless of the way I collide these bodies the contact events handler with console.log is not called.
Do I do something wrong, or is it something missing in the alpha version of the library? Thanks.
When using webpack's source-map-loader
in development mode, the plugin is unable to see Rapier's source files and provides many warnings:
./node_modules/@dimforge/rapier3d/dynamics/index.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from '/Users/duane/Projects/relm5/node_modules/@dimforge/rapier3d/dynamics/index.ts' file: Error: ENOENT: no such file or directory, open '/Users/duane/Projects/relm5/node_modules/@dimforge/rapier3d/dynamics/index.ts' client:135
./node_modules/@dimforge/rapier3d/dynamics/integration_parameters.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from '/Users/duane/Projects/relm5/node_modules/@dimforge/rapier3d/dynamics/integration_parameters.ts' file: Error: ENOENT: no such file or directory, open '/Users/duane/Projects/relm5/node_modules/@dimforge/rapier3d/dynamics/integration_parameters.ts'
...
Could these files be included in the npm package in order to help with stack trace debugging?
after some research i found that some libs from c++ has their wasm released with simd supported.
i think this is a good feature which can improve the effeicency when running on web.
hope this can be adopted, thank you very much.
the collider.parent()
will always return a valid value even it does not have a parent (the default return value is 0)
and 0 is actually a valid body handle in the world (the first body).
The current JS bindings need to be reworked to address the following problems:
rigidBody.linvel()
will return a Vector
which has to be explicitly freed by the end-user with vector.free()
. This is very bad because it is very easy to forget to free something, which will ultimately lead to leaks.World
structure which is convenient but will become quite limited in the future once rapier exposes more pipelines than the physics pipeline.In order to address these problems, we should modify our bindings by splitting them into two elements:
RigidBodySet
, ColliderSet
, PhysicsPipeline
, etc. but not the colliders and rigidbodies for example. This will solve the manual-memory management mentioned in 1 because it will automatically free transient objects that could have been easily forgotten by the end-user.Another bonus of the high-level bindings is that they will allow us to design a more JS-idomatic API by defining, e.g., builder patterns.
This change will necessarily be a breaking change. However we should attempt to limit as much as possible the amount of breaking changes. To do so we will:
World
structure in the high-level bindings. This structure will work like the current monolithic World
so that existing code wont suffer too much from this binding rewrite. At some point in the future we may end up making World
as deprecated.0.2.0
to show that a breaking change happened.Hello, the 2D Demos and 3D Demos seem to run fine at first glance, but selecting a different "demo" from the dropdown seems to double the speed of the simulation.
I noticed that the speed seems to be reset when selecting the "keva tower" 3D demo and then switching to another demo.
Also you can quickly reproduce this issue by pressing "restart" multiple times.
In the rapier3d-compat build the raw.d.ts
file contains export * from "../pkg3d/rapier_wasm3d";
which does not exist in the distributed package. In the rapier3d
build, this file is export * from "./rapier_wasm3d";
which would work just fine in the compat build.
This line is added for the rapier3d
build here but I don't see a corresponding line for the compat build.
This results in typescript errors when building projects against the compat build such as:
node_modules/@dimforge/rapier3d-compat/dynamics/ccd_solver.d.ts:1:10 - error TS2305: Module '"../raw"' has no exported member 'RawCCDSolver'.
1 import { RawCCDSolver } from "../raw";
I found this old reddit thread: https://www.reddit.com/r/javascript/comments/hn0vd2/i_started_writing_a_testbed_to_compare/
from (presumably) @sebcrozet which states that you were putting together a comparison with "Ammo.js/Cannon.js/Oimo.js/PhysX-js". The link now 404s. Is this comparison still around?
I'm currently evaluating .js physics engines for use in a beginner-friendly online game maker, and this is exactly the sort of comparison I was hoping to find.
const staticCenterBody = context.createBody(RigidBodyType.Static);
const tumblerBox = context.createBody(RigidBodyType.Dynamic);
const ballJointParam = JointData.revolute(VectorOps.new(cx, cy), VectorOps.new(cx, cy));
const ballJoint = context.world.createImpulseJoint(ballJointParam, staticCenterBody, tumblerBox) as RevoluteImpulseJoint;
ballJoint.configureMotorVelocity(cfg.angularVelocity, cfg.angularVelocity);
1, here if i want to retrieve the start point / end point of a segment (the c
)
it returns undefined.
c.a
, c.b
, c.vertices()
all returns undefined
2, triangle shape does not return a,b,c
too
c.a, c.b, c.c
, c.vertices()
, all returns undefined
3, all rounded shape, if you want to retrieve its round radius, all undefined
for example roundCuboid.roundRadius()
will return undefined
Feature request.
Add a method that allows to apply a force on a rigidbody at an offset. This is basically a applyForceAtPoint()
(and others, like impulses), but in local space of a rigidbody instead of world space.
I'm getting the following error:
Uncaught RuntimeError: unreachable
at std::panicking::rust_panic_with_hook::h9d91fa0fae16500f (http://localhost:3000/0c0ef481b8428110185b.module.wasm:wasm-function[788]:0x108529)
at std::panicking::begin_panic_handler::{{closure}}::h2d82b5b2db976f3f (http://localhost:3000/0c0ef481b8428110185b.module.wasm:wasm-function[897]:0x10d32a)
at std::sys_common::backtrace::__rust_end_short_backtrace::h24539600b7e2452c (http://localhost:3000/0c0ef481b8428110185b.module.wasm:wasm-function[1245]:0x114d35)
at rust_begin_unwind (http://localhost:3000/0c0ef481b8428110185b.module.wasm:wasm-function[1161]:0x113c87)
at core::panicking::panic_fmt::h91d2023e5afe1929 (http://localhost:3000/0c0ef481b8428110185b.module.wasm:wasm-function[1247]:0x114d99)
at core::panicking::panic::h5da66f104e83c46a (http://localhost:3000/0c0ef481b8428110185b.module.wasm:wasm-function[1111]:0x112e78)
at rapier3d::geometry::broad_phase_multi_sap::sap_axis::SAPAxis::batch_insert::h22440a950023a6c1 (http://localhost:3000/0c0ef481b8428110185b.module.wasm:wasm-function[58]:0x6e464)
at rapier3d::geometry::broad_phase_multi_sap::broad_phase::BroadPhase::update::hcb9a53f41ef84931 (http://localhost:3000/0c0ef481b8428110185b.module.wasm:wasm-function[46]:0x5b78c)
at rapier3d::pipeline::physics_pipeline::PhysicsPipeline::detect_collisions::he6a99ba9c9b1190f (http://localhost:3000/0c0ef481b8428110185b.module.wasm:wasm-function[321]:0xdbb17)
at rapier3d::pipeline::physics_pipeline::PhysicsPipeline::step::h0bcdada6b45b091e (http://localhost:3000/0c0ef481b8428110185b.module.wasm:wasm-function[45]:0x59992)
What is interesting is that if I fill the heightmap with all zeroes, I don't get this error. If I pass in real terrain data I do.
Even more strangely, if I multiply the data by a small constant (.01) the error goes away, but I multiply by (.99) it happens. So basically it is as if the magnitude of what is in the array matters. I've tried a bunch of other combinations, it's completely consistent but I can't figure out the pattern.
Note: it took me a few hours to even get this stack dump, as I had to build the library locally in order to turn on debug symbols, and I had to fuss with it to get it to build on my system.
The way I am building the height map isn't very interesting either:
/** Physics object representing a height field such as terrain. */
export class PhysicsHeightField {
#body: RigidBody;
#collider: Collider | null = null;
constructor(private rapier3d: R, private world: World, position: Vector2) {
// TODO: Add friction and such.
const rbDesc = rapier3d.RigidBodyDesc.newDynamic().setTranslation(position.x, 0, position.y);
this.#body = this.world.createRigidBody(rbDesc);
}
public dispose() {
if (this.#collider) {
this.world.removeCollider(this.#collider);
this.#collider = null;
}
this.world.removeRigidBody(this.#body);
}
public setHeights(heights: Float32Array) {
// Remove previous collider, if any.
if (this.#collider) {
this.world.removeCollider(this.#collider);
}
// Generate new height map from data.
const clDesc = this.rapier3d.ColliderDesc.heightfield(
PLOT_LENGTH,
PLOT_LENGTH,
heights,
terrainScale
);
this.#collider = this.world.createCollider(clDesc, this.#body.handle);
}
}
I noticed when using @dimforge/rapier2d
that the Collider.activeHooks()
return type was void
when it should be ActiveHooks
. I'm not familiar with the Rapier build process, so I hope this is the correct repo to propose a fix.
@dimforge/rapier2d/geometry/collider.d.ts:
107 /**
108 * Get the physics hooks active for this collider.
109 */
110 activeHooks(): void;
Patch:
diff --git a/src.ts/geometry/collider.ts b/src.ts/geometry/collider.ts
index 5f0220e..b2e1642 100644
--- a/src.ts/geometry/collider.ts
+++ b/src.ts/geometry/collider.ts
@@ -192,7 +192,7 @@ export class Collider {
/**
* Get the physics hooks active for this collider.
*/
- public activeHooks() {
+ public activeHooks(): ActiveHooks {
return this.rawSet.coActiveHooks(this.handle);
}
I only see the user-data API in the Rust section of the docs, and I can't find any mention of it in TypeScript types. It looks like it's not exposed in the JS version of the library yet, and would be very useful to have. Is it possible to add it to the JS lib? Thank you!
usually we will attach some user data to a collider / rigidbody, for example my sprite / my entity etc.
body.userData = a;
collider.userData = b;
so this will be a very convenient attribute. and it exists in a lot of physics engines already too.
so hope you can add it for us please.
thank you very much.
As someone interested in building games for the web platform and XR, I'm really excited to find this library! Existing solutions are either feature-complete and fast (Ammo) or easy to use (Cannon) - but not both, it seems. Rapier is looking delightful in all respects.
I understand it's relatively early in the project, but are there plans yet to expose contact position and normal? I noticed this information has been provided recently in the Rust project, and I'm curious if there's any way I could help bring it into the JS bindings as well. I'm not so familiar with Rust but I know my way around TS and would love to learn how that bridge works.
I'm trying to draw all the colliders in the world but I'm having trouble getting the properties of some of the shapes.
world.forEachCollider(c => {
switch (c.shapeType()) {
case ShapeType.Cuboid:
console.log("Cuboid", c.halfExtents())
break
case ShapeType.RoundCuboid:
console.log("RoundCuboid", c.halfExtents())
break
For cuboids it works fine, ir prints: Cuboid AA {x: 100, y: 0.25}
but for round cuboids it prints RoundCuboid null
Here is a small reproduction https://codesandbox.io/s/stupefied-galileo-9zz4f?file=/src/index.ts
The same happens for the 2D version.
to do sweep test between two shapes, this method is missing from collider (or a static method like castShape(p0, r0, shape0, p1, r1, shape1, vel, maxToi)
)
just like last update, collider.castRay/intersectsXXXX
has been done for intersection test.
this method is for the similar purpose: move my character, which is a key feature.
thank you very much.
I'm trying to create a 2D heightfield but it throws a unreachable error at runtime for no apparent reason.
...
const rigidBody = this.world.createRigidBody(rigidBodyDesc);
const colliderDesc = RAPIER.ColliderDesc.heightfield(new Float32Array([ 2, 3 ]), { x: 50.0, y: 1.0 });
const collider = this.world.createCollider(colliderDesc, rigidBody.handle);
...
Also, on the testbed heightfield.js
example it passes an array to the heights
parameters, but on Typescript it requires a Float32Array
. Anyway, the testbed example also doesn't work:
let ground_size = {x: 50.0, y: 1.0};
let nsubdivs = 100;
let heights = [];
heights.push(40.0);
for (let i = 1; i < nsubdivs; ++i) {
heights.push(Math.cos(i * ground_size.x / (nsubdivs)) * 2.0);
}
heights.push(40.0);
...
const colliderDesc = RAPIER.ColliderDesc.heightfield(new Float32Array(heights), ground_size);
const collider = this.world.createCollider(colliderDesc, rigidBody.handle);
...
I'm using the latest version of Rapier2D (0.7.6).
Right now there are two ways to initialize rapier.js: The 'rapier-compat' package, or (for lack of a better name) the 'vanilla' version.
The reason that rapier-compat exists is to allow use with bundlers that have trouble loading .wasm resources. However, this compatibility comes at a price: the entire .wasm resource is encoded as text. While this works, it is not ideal.
Right now the only bundler (that I know of) that can handle the 'vanilla' version of rapier.js is Webpack 4. Webpack 5 will not work, nor will Snowpack. Rollup uses a strategy similar to rapier-compat, encoding the resource as text. I have not tried Parcel, Vite, or any of the other bundlers, but I imagine they have similar issues.
However, there is a third option, which is to not depend on a bundler encoding at all. This is in fact the recommended option for snowpack, as shown in this guide. This technique loads the .wasm resource directly using the browser fetch
API, and then once the promise resolves, it manually bootstraps the JavaScript wrappers around the WASM resource.
However, doing it this way means that the .wasm resource will not be available until after the fetch promise resolves. Unfortunately, the current rapier.js TypeScript code imports the raw bundle as a static resource - that is, it assume that the WASM code is already ready at the time that the JavaScript code is imported. So this option will not work with the current rapier.js code.
To support this use case, it would be necessary to change the way that the rapier.js World object, and the objects within it, are constructed. Instead of statically importing all of the references to WASM classes, these would need to be passed in as part of the constructor call. Possibly it would make sense to define a TypeScript interface which has the same shape to "import * from 'raw'" and pass that object around to each class that is constructed.
Also, a lot of the import { symbol }
statements would be changed to import type { symbol }
to let the TypeScript compiler know that we're only interested in the type definitions, not the values of the imports. "import type" statements are always removed from the output JavaScript, so this prevents the .wasm resources from being accidentally dereferenced too early.
This is not a huge change, but unfortunately it is a backwards-incompatible one. The strategy proposed here is not that different from the way JavaScript clients use Rapier already - you have to have a handle to the rapier object before you can create a world, rb, collider, or anything else other than the basic math types.
So, the docs leave a lot out - in particular, simply importing the rapier3d from npm isn't going to work without configuring your bundler (webpack, rollup, etc.) to handle wasm files. I've spent a couple hours trying to get it to work with snowpack - it kept complaining that the .wasm file was not a JavaScript file; switched over to webpack and got a similar error. Then I tried installing wasm-loader, but that doesn't work either - I get _rapier_wasm3d_bg_wasm__WEBPACK_IMPORTED_MODULE_0__.rawintegrationparameters_new is not a function
. I'm guessing that I need to find a different loader, but I have no idea which loader I should use.
Hello, I'm trying to try out rapier with Vite as my bundler. Vite supports direct wasm imports, so I'm wondering if some of its magic isn't working with how rapier is bundled.
When I try to import it (either as async or a standard ESM format) I can see types in my IDE, but my code doesn't run in the browser, with this error:
The requested module '/@fs/GitHub/test/@dimforge/rapier2d/rapier_wasm2d_bg.wasm?import' does not provide an export named '__wbg_rawbroadphase_free'
I'm happy to do some legwork to figure this out, but I'm not sure what else to try, are there any clues in there?
Edit: using the compat package works as expected, so I'll do that in the meantime
When I query for intersectionsWithRay on an empty ColliderSet, I get the following RuntimeError:
cb4a7832f88eb109b422.module.wasm:0x109724 Uncaught RuntimeError: unreachable
at http://localhost:8080/build/cb4a7832f88eb109b422.module.wasm:wasm-function[803]:0x109724
at http://localhost:8080/build/cb4a7832f88eb109b422.module.wasm:wasm-function[901]:0x10d9ac
at http://localhost:8080/build/cb4a7832f88eb109b422.module.wasm:wasm-function[1248]:0x115602
at http://localhost:8080/build/cb4a7832f88eb109b422.module.wasm:wasm-function[1181]:0x1148e8
at http://localhost:8080/build/cb4a7832f88eb109b422.module.wasm:wasm-function[1250]:0x115666
at http://localhost:8080/build/cb4a7832f88eb109b422.module.wasm:wasm-function[1011]:0x110f3e
at http://localhost:8080/build/cb4a7832f88eb109b422.module.wasm:wasm-function[115]:0xa2fcc
at rawquerypipeline_intersectionsWithRay (http://localhost:8080/build/cb4a7832f88eb109b422.module.wasm:wasm-function[734]:0x1055fd)
at RawQueryPipeline.intersectionsWithRay (http://localhost:8080/build/0.0.js:5740:105)
at QueryPipeline.push.../node_modules/@dimforge/rapier3d/pipeline/query_pipeline.js.QueryPipeline.intersectionsWithRay (http://localhost:8080/build/0.0.js:3244:18)
In my world loop, I need to check that colliders.len() > 0
to proceed:
const colliders = this.physics.world.colliders;
if (colliders.len() > 0) {
this.physics.world.intersectionsWithRay(
colliders,
rayDown,
MAX_GROUND_TOI,
true,
AVATAR_INTERACTION,
(isect) => {
// ... callback code ...
return true;
}
);
}
I notice that the rapier.rs 3d demo crashes iOS Safari (14.0.1) and iOS Chrome (87).
Unfortunately, it crashes the browser (no console logs, no crash traces), so it's difficult to say what's causing the problem.
The error message in Safari is "A problem repeatedly occurred on [url]". In Chrome the error message is "Can't open this page" with an "aww snap" crash icon ().
Using rapier2d-compat version 0.7.6
// World contains some static and dynamic body
world.forEachRigidBody(body =>{
const collidersLength = body.numColliders();
for (let i = 0; i < collidersLength; i++) {
const collider = world.getCollider(body.collider(i));
drawBody(ctx, collider, body);
}
if (body.bodyType() === RAPIER.RigidBodyType.Static) {
return
}
const bodyPosition = body.translation();
const bodyMass = body.mass();
world.forEachRigidBody(otherBody => {
if (body.handle === otherBody.handle) {
return
}
const otherBodyMass = otherBody.mass();
const otherBodyPosition = otherBody.translation();
const distance = getDistance(otherBodyPosition, bodyPosition);
const forceDirection = getDirection(
otherBodyPosition,
bodyPosition
);
const forceMagnitude = getGravitationalForce(
otherBodyMass,
bodyMass,
distance
);
try {
body.applyForce(
new RAPIER.Vector2(
(Math.sin(forceDirection) * forceMagnitude) /
Math.sqrt(bodyMass),
(Math.cos(forceDirection) * forceMagnitude) /
Math.sqrt(bodyMass)
),
true
);
} catch (error) {
console.error(error);
}
})
})
This code always throws as soon as I have 2 bodies (1 static & 1 dynamic, 2 statics, 2 dynamics, whatever) with the error recursive use of an object detected which would lead to unsafe aliasing in rust
.
The error also happens with forEachRigidBodyHandle
The same code using forEachCollider works (but I wanna use forEachRigidBody because some bodies have multiple colliders)
world.forEachCollider((collider) => {
const body = world.getRigidBody(collider.parent());
drawBody(ctx, collider, body);
if (body.bodyType() === RAPIER.RigidBodyType.Static) {
return;
}
const bodyPosition = body.translation();
const bodyMass = body.mass();
world.forEachCollider((otherCollider) => {
const otherBody = world.getRigidBody(otherCollider.parent());
if (body.handle === otherBody.handle) {
return;
}
const otherBodyMass = otherBody.mass();
const otherBodyPosition = otherBody.translation();
const distance = getDistance(otherBodyPosition, bodyPosition);
const forceDirection = getDirection(
otherBodyPosition,
bodyPosition
);
const forceMagnitude = getGravitationalForce(
otherBodyMass,
bodyMass,
distance
);
try {
body.applyForce(
new RAPIER.Vector2(
(Math.sin(forceDirection) * forceMagnitude) /
Math.sqrt(bodyMass),
(Math.cos(forceDirection) * forceMagnitude) /
Math.sqrt(bodyMass)
),
true
);
} catch (error) {
console.error(error);
}
});
});
In 0.7.1 (3d-compat), I'm seeing this error:
Uncaught (in promise) ReferenceError: Buffer is not defined
While awaiting Rapier.init()
.
Buffer
seems undefined in this commit, but not sure if there's some global definition somewhere: https://github.com/viridia/rapier.js/blob/40ef3dc75208f1936ac3b41520e99d8dec20d805/rapier-compat/src3d/init.ts#L10
Seems like it's gone in master
: https://github.com/viridia/rapier.js/blob/master/rapier-compat/src3d/init.ts
So maybe it just needs a new version pushed? Or maybe I'm importing incorrectly - neither of the following work for me:
import * as Rapier from "@dimforge/rapier3d-compat";
async function main() {
await Rapier.init();
}
import Rapier from "@dimforge/rapier3d-compat";
async function main() {
await Rapier.init();
}
The first one worked in 0.7.0. Thanks for any help!
sed: 1: "pkg//rapier.d.ts": extra characters at the end of p command
The 'sed' command on OSX is the bsd version, not the gnu version. See this SO topic: https://stackoverflow.com/questions/16745988/sed-command-with-i-option-in-place-editing-works-fine-on-ubuntu-but-not-mac
Currently the build script requires the user to have previously installed the TypeScript compiler. This is a recipe for trouble - there is no guarantee that the version of TypeScript that the user has installed is one that will work with the current version of rapier.js.
The standard practice in the npm world is to declare "typescript" as a dependency in package.json. This allows the compiler version to be explicitly specified. You can then call "npx tsc" in your shell script (after running "npm install") to invoke the version of tsc that has been installed with the project.
Even better would be to eliminate the shell scripts entirely and just make the build commands npm scripts in package.json, so that "npm run build" builds the project.
This will of course require adding a package.json file to the rapier.js repo. That can either live at the top level or in the individual directories for rapier2d and rapier3d.
I'm using rapier2d-compat version 0.7.6.
I'm creating a radial gravity based platform game.
I had no issue creating and rendering 2d ball object => I create a body, attach it to a Ball shaped collider, then in the game loop, I iterate over all collider and draw them according to their ShapeType. In case of ball ShapeType, I use the body translation property and the collider radius property.
Then I tried to create a simple square with cuboid() with the following code
const heroBodyDesc = RAPIER.RigidBodyDesc.newDynamic().setTranslation(
100,
100
);
const heroColliderDesc = RAPIER.ColliderDesc.cuboid(10, 10).setDensity(
1
);
let heroBody = world.createRigidBody(heroBodyDesc);
let heroCollider = world.createCollider(
heroColliderDesc,
heroBody.handle
);
console.log(heroCollider.vertices(), heroBody.mass());
// logs : undefined 400
I do not understand how to retrieve the shape infos, there is no width or height nor vertices on the collider. Could someone give me a hand ?
The example codepen linked from this "getting started" page of the docs errors due to RAPIER.BodyStatus
not existing. Per the v0.7.0 changelog it needs to be updated to RAPIER.RigidBodyType
, or use the shorthand .newStatic()
/.newDynamic()
.
I'm not able to submit a pull request to fix this because the code is on CodeMirror rather than Github. I wonder if there's some way to move the example code to Github but also keep them interactive/editable like on codepen? It would be handy if codepen had a URL-based import like https://codepen.io/?js=https://github.com/dimforge/rapier.js/path/to/example.js
Hi,
I was wondering if it would be possible to adjust the local_anchor1 and local_anchor2 values of a ball joint after the joint had been created?
I have been digging through the code, but do not know the rust language. It seems that the anchors are simply defined within the ball joint class, but I do see that other classes take copies (or references?) to their values. If a method to change the anchors was added to the ball joint, would the changed value be used throughout the system? And then could this method be exposed via the JavaScript interface?
Many thanks, Rapier looks like an awesome physics engine.
I would like to use rapier inside a web-worker through the rapier2d-compat
module, for an easy setup.
I am blocked by a problem in the file node_modules/@dimforge/rapier2d-compat/rapier.js
at the very last line of the file.
A=A.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),g.p=A})(),g.b=document.baseURI||self.location.href,g(123)})()}));
I do not know what the source code is because I have only access to the minified version, but the use of document
makes the library unusable inside a web-worker.
Here is the error:
rapier.js?28fd:1 Uncaught ReferenceError: document is not defined
at eval (rapier.js?28fd:1)
at eval (rapier.js?28fd:1)
at eval (rapier.js?28fd:1)
at eval (rapier.js?28fd:1)
at Object../node_modules/@dimforge/rapier2d-compat/rapier.js (src_simulation_worker_ts.js:18)
A feature request to add linear and angular velocity scaling factor on a rigidbody, which would allow to control each axis individually:
For example, in Bullet engine:
void btRigidBody::setLinearFactor(const btVector3 &linearFactor);
void btRigidBody::setAngularFactor(const btVector3 &angFac);
I need to create a 2d body made by a circle and a rectangle. According to the documentation on the website I should use a compound collider for this, correct?
I've been looking into how to use a compound shape with rapier2d, but couldn't find much: the "Compound = 8" definition in the typescript source is commented out and there's no constructor or function to handle them.
Would it be possible to port support to compound shapes?
Otherwise what's the recommended way to create my shape?
For some reasons, Rollup hangs indefinitely after a successful build of rapier-compat (cd compat; npm run build;
).
This makes the release process annoying as I have to manually kill the task. And this prevents the CI from terminating.
Env: PC, Win10
Version: TS / JS
error when call multiple substeps
code snippet:
const fixedTimeStep = 1000 / 60;
this._world.timestep = fixedTimeStep;
private stepPhysicsWorld(delta: number) {
this._accumulator += delta;
let substepIndex = 0;
while (substepIndex++ < this._maxSubSteps && this._accumulator > fixedTimeStep) {
this._world.step();
this._accumulator -= fixedTimeStep;
}
}
if the delta always small enough, then while
will always loop just for 1 times, which works fine.
but once the _accumulator
has enough lagged time value, then the while
will call twice or more world.step
times, and then it will throw error:
this means i can't call step
immedately after a step
call? otherwise how to implement fixed time step on web? because even use webworker in web, you actually can't implement a real fixed time interval calling still...
hmmm, with wasm this is the obvious disadvantage, i can do nothing when find a bug.... 😅
thank you.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.