matthias-research / pages Goto Github PK
View Code? Open in Web Editor NEWMy web page containing all the demos from my youtube channel "Ten Minute Physics" www.youtube.com/c/TenMinutePhysics
My web page containing all the demos from my youtube channel "Ten Minute Physics" www.youtube.com/c/TenMinutePhysics
Title
<script src='https://threejs.org/examples/js/controls/OrbitControls.js'></script>
<script src="OrbitControls.js"></script>
I tried to find but could not find what is the best way to submit a contribution that make something on top of the ten minute physics tutorials? Do we submit a pull request here?
I guess the intent is to display the fluid as white and the walls as black if you deactivate both the smoke and the pressure. To make that work the "var color = [255, 255, 255, 255]" has to be inside of the two for loops in "draw" method. Otherwise everything becomes just black.
Hi there!
I noticed a typo/bug while watching your video about this plugin. Namely, one of the directions is incorrect, which results in one missing direction and one duplicate. This line should have -1 on the X coordinate rather than the Y coordinate, I believe:
https://github.com/matthias-research/pages/blob/master/tenMinutePhysics/BlenderTetPlugin.py#L44
Thanks for your videos! :)
PS: While I'm here, a quick q, is xpbd a good solution for simulating cube or cuboid physics? Mainly collisions with each other and perhaps with spheres.
Not sure if it helps someone. To avoid too much loss of energy during collisions, in my particular implementation, I added an energy conservation restriction in the postSolve phase which scales all velocities with a factor, also it avoids invalid gain of energy in specific cases. Potential and kinetic energies are calculated as the sum over all particles using the well known formular. This simple approach is valid for a single moving object and would need to be modified if energy exchange happens between multiple moving objects though.
const epot = this.obj.Epot(this.obj.akceleration); // potential ernergy in respect to gravity field
const ekin = this.obj.Ekin();
const E = epot + ekin;
if (debugging) console.log(`E(pot|kin): ${epot/1000+ekin/1000} (${epot/1000}|${ekin/1000})`);
const at = this.alpha*dt;
if (E/this.E0 < (1-at) || E > this.E0) {
const E1 = this.E0*(1-at);
const lambda = Math.sqrt((E1-E)/E+1);
this.obj.vel.scale(lambda); // scale all velocities by a factor lambda
}
The handling of ground contact in 10-softBodies:preSolve looks a bit hacky to me!? Is there a physical motivation to do it that way, or was it just to keep calculations simple?
Normally for a bouncing particle I would expect a reflection at the ground, so that y-coordinates between pos and prevPos are exchanged whereas the x,z-coordinates are that projected below ground into vel-direction, so not touched after adding the velocity vector to previous pos (and finally, according to elasticity the vector between the contact point and new pos would be multiplied with a value between 0..1)
The demos that rely on Three.js don't work because
Uncaught TypeError: THREE.OrbitControls is not a constructor
THREE.PlaneBufferGeometry has been renamed to THREE.PlaneGeometry.
)Maybe this can be solved easily by adding the correct version of Three.js in the repository instead of hot loading it from threejs.org.
pages/challenges/pendulum.html
Line 511 in 88020c0
I may be wrong but wouldn't the gravity force need to be multiplied by inverse mass here?
P.S.: I love your tutorials, they are very informative!
Dear Matthias,
thanks a lot for setting up this repository! While topic of PBD is already pretty well-covered in terms of implementations of various constraints, XPBD is still not quite there yet. Hence, reference implementations would be definitely very useful for educational purposes. Plus the javascript app is also very cool!
I am working on a surgical simulator using PBD. Please, have a quick look here. I am trying to implement better damping as currently the anatomo is either unresponsive or oscillates too much. I have adapted the solveDistVel() method from this repo but it does not make any noticeable difference for volumetric meshes.
A friend of mine came up with the following implementation during position solve but there is something not quite right in its behavior. Would you be so kind to have a quick look. Maybe you would spot an error in code.
Thank you
PS: My apologies, but I couldn't get the code formatted correctly...
`float dtSq = dt * dt;
float alphaHat = compliance / dtSq;
float betaHat = damping * dtSq;
float gamma = (alphaHat * betaHat) / dt;
for (int i = 0; i < cnstrsCount; i++)
{
DistanceConstraint cnstr = cnstrs[i];
//positions at start of the substep
float4 posA = positions[cnstr.idA];
float4 posB = positions[cnstr.idB];
float4 predPosA = predictedPositions[cnstr.idA];
float4 predPosB = predictedPositions[cnstr.idB];
float wA = massesInv[cnstr.idA];
float wB = massesInv[cnstr.idB];
float wSum = wA + wB;
if (cnstr.restLength == 0 || wSum == 0)
continue;
float4 N= predPosB - predPosA;
float len = math.length(N);
if (len <= float.Epsilon)
continue;
float C = len - cnstr.restLength;
N = N/ len;
float4 gradA = -N;
float4 gradB = N;
float4 velA = predPosA - posA;
float4 velB = predPosB - posB;
float numA = C + (alphaHat * lambdasA[i]) + (gamma * (math.dot(gradA, velA)));
float denA = ((1.0f + gamma) * wSum) + alphaHat;
float lambdaA = -numA / denA;
float numB = C + (alphaHat * lambdasB[i]) + (gamma * (math.dot(gradB, velB)));
float denB = ((1.0f + gamma) * wSum) + alphaHat;
float lambdaB = -numB / denB;
//these lambda arrays are zeroed at start of each substep
lambdasA[i] += lambdaA;
lambdasB[i] += lambdaB;
predictedPositions[cnstr.idA] += lambdaA * gradA * wA;
predictedPositions[cnstr.idB] += lambdaB * gradB * wB;
}`
Hello, I am a self-taught programmer. When I attempted to transform a square cloth into a triangle, I encountered a bug. Could anyone provide guidance on modifying the code based on "tenMinutePhysics/16-GPUCloth.py"? It would be really helpful if you could indicate the specific locations for modification and explain the reasons behind them. Trying to alter the shape is quite challenging for a beginner like me. Thank you for your assistance.
Line 2 of Algorithm 3 (LimitAngle) in PBDBodies.pdf states
if n <dot> n < 0 then phi <- 2Pi - phi
However, in lines 243 - 244 of PBD.js the 2Pi
is replaced with Pi
if (a.dot(b) < 0.0) phi = Math.PI - phi;
Using the algorithm in PBDBodies.pdf causes strange behavior when joint limits are set to values over 0.5 Pi.
If this part of the algorithm is meant to distinguish between the two solutions of the inverse sine function, then I believe the implementation in PBD.js is correct, and Algorithm 3 in PBDBodies.pdf contains an error.
I am following your tutorial about writing an Eulerian fluid simulation. May I ask about the meaning of h, p, s, and m
in the constructor of the Fluid
class?
When I try to play this pinball game on my iPhone 13, I can't move the flippers. The page doesn't react to the touch action. I debugged the code and found that the problem lies with the touch.identifier.
Initially, the flipper's touchIdentifier was set to -1. I checked if touchIdentifier >= 0 to determine if there was a press action.
this.touchIdentifier = -1;
var pressed = this.touchIdentifier >= 0;
if (flipper.select(touchPos)) {
flipper.touchIdentifier = touch.identifier;
}
The problem was the touch.identifier was not always >= 0, for example , it didn't work in iphone 13 (real phone not the web virtual phone.).
So I changed the initial touchIdentifier to null, and determined the press action by checked if touch.identifier was null. The key code is as below:
this.touchIdentifier = null;
var pressed = !!this.touchIdentifier;
if (flipper.select(touchPos)) {
flipper.touchIdentifier = touch.identifier;
}
I am trying to make 10-softBodies.html bunny completely stiff. With no luck by now. Can anybody suggest best strategy for this?
Hello! Having been taking a look at the demo "A Constraint-based Formulation of Stable Neo-Hookean Materials". In the paper the deviatoric constraint function is defined as C_D(F) = sqrt(tr(F^t * F))
. However in the demo implementation it's defined as
C = vecLengthSquared(this.F,0) + vecLengthSquared(this.F,1) + vecLengthSquared(this.F,2) - 3.0;
It makes sense to me that the constraint function is defined like as such (zero when there is no deformation) but is there a reason for the discrepancy with the paper? (The hydrostatic constraint seems to match up with the paper). Any insights would be greatly appreciated and thanks again for making all of this public!
I think there is some recent changes on the Webkit/v8 engines that the simulation time is like 5-10x slower since early 2024 that it no longer runs on mobile for examples like soft body sim. My guess is the engine tried to optimize it and making things worse. The biggest bottle I have is the solveVolumes
. I had to remove all those math helper function and directly execute it and unroll some loops. I also noticed that for small array like those temp
and grads
, using typed array is way slower so it is better to use regular array like new Array(4*3)
instead. Array access is super slow for some reason in the big loop as well.
Hello,
in this file, initPhysics() and Ball constructor are prepared to receive a "scene" parameter. But they use the global threeScene variable instead.
For consistency, the local parameter should either go, or be used and initPysics() called with the threeScene argument.
Regards
if (this.type == JointType.FIXED) {
let q = globalPose0.q;
q.conjugate();
q.multiplyQuaternions(globalPose1.q, q);
let omega = new THREE.Vector3();
omega.set(2.0 * q.x, 2.0 * q.y, 2.0 * q.z);
if (omega.w < 0.0)
omega.multiplyScalar(-1.0);
applyBodyPairCorrection(body0, body1, omega, this.compliance, dt);
}
line 322 in pages/challenges/PBD.js:
if (omega.w < 0.0)
omega is vector3, has no member w. Was q meant?
Hi, Matthias, love your tutorials-- I'm trying to duplicate your tutorial 12 soft body example with my own mesh I tetrahedralized in Blender using your addon. It looks like the addon worked properly, but I can't figure out how to export the tet mesh in the format you used in the Three.js example. Is there some trick to getting the "tetIds" and "edgeIds" data out of Blender?
How is the data generated?"verts":[], "tetIds": [],"tetEdgeIds": [],"tetSurfaceTriIds":[],thank you very much.
Give me a case study.
Hey Matthias,
Since I dont see a correspondence address on your XPBD paper, I thought id ask here. In your XPBD paper, joint damping is implemented on the velocity level, as per eq 31/32.
I wonder if you ever compared that to the approach to damping proposed here
It strikes me that the latter formulation has some advantages, mainly that any competition between strong stiffness and damping forces is handled correctly within the position solve. In your XPBD paper there doesnt seem to be a section discussing the relative advantages of different damping methods, so I was curious if you would care to elaborate what your thinking on the matter is today.
And by the way; thanks for all you do for the physics simulation community!
Line 322 in 88020c0
Hello,
Sorry if this is not the right place, I couldn't find an e-mail address to contact you @matthias-research. Also sorry if this has been reported before, it wasn't in the errata for the article.
In the paper 'Detailed Rigid Body Simulation with Extended Position Based Dynamics' I think there is an error in equation 30:
Looking at the units:
vt / |vt| -> unitless
h -> s
μd -> unitless
fn -> N = kg m / s^2
so the units of Δv are:
s kg m / s^2 = kg m / s
If we use Δv in eq 33:
The p / m1 term is also in kg m / s instead of m / s.
Because impulse:
P = F dt = m Δv
I would expect:
Δv = F dt / m
Where m is the effective mass at the contact point which is 1 / (w1 + w2).
So I think eq 30 should be:
Δv = vt / |vt| min(h μd |fn| * (w1 + w2), |vt|)
nTableSize = 2000
nX = 1
nY = 1
nZ = 1
h1 = abs((nX * 92837111) ^ (nY * 689287499) ^ (nZ * 283923481)) % nTableSize
h2 = (73856093 * nX + 19349663 * nY + 83492791 * nZ) % nTableSize
print("----------hash-function for (x=1 y=1 z=1)-----------")
print("ten minutes physics:", h1)
print("interactive-graphics:",h2)
print("")
nX = 1
nY = 1
nZ = -1
h1 = abs((nX * 92837111) ^ (nY * 689287499) ^ (nZ * 283923481)) % nTableSize
h2 = (73856093 * nX + 19349663 * nY + 83492791 * nZ) % nTableSize
print("----------hash-function for (x=1 y=1 z=-1)-----------")
print("ten minutes physics:", h1)
print("interactive-graphics:",h2)
----------hash-function for (x=1 y=1 z=1)-----------
ten minutes physics: 1621
interactive-graphics: 547
----------hash-function for (x=1 y=1 z=-1)-----------
ten minutes physics: 1621
interactive-graphics: 965
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.