Physics Patch-a-Day Thread - Join the fun!!!
Welcome to the physics patch-a-day, part of our spotlight on the Max physics engine and some of its capabilities. We are following the script of the previous patch-a-day series; we ask various members of our staff (and sometimes outside participants) to try their hand at a technology, then see where they take us. Some of the posters will be experts with OpenGL and/or the physics engine, but others may be from other disciplines, and work on matching the tech to their interests.
We hope that you will find something interesting in each of these posts, and that it opens your mind to some of the options provided by the physics system. If you have a comment, please feel free to post it here. If you find a way to improve a patch, post it and share. We want this to be a conversation, and that requires your input!
So enjoy the series (which will continue through September 28), and spend a little time with the physics engine - we think you'll find it worthwhile.
[ddg]
Today's physics patch features a set of musical walls and three equally musical spheres that make noise whenever they collide. Each sphere has its own "collision" subpatch that calculates whether the sphere has collided with another sphere (which produces a low note), or one of the walls (each of the 6 walls that makes up the "world" is associated with a note in a pentatonic scale - hit the wall and the note sounds).
The patch demonstrates the use of jit.phys world dictionaries, which contain all the data necessary to detect collisions, and even to determine when objects collide for the first time (think of it as a sort of equivalent to "debouncing").
The interesting twist on this patch is that it contains a set of 3d LFOs controlled using standard ITM objects. These x/y/z vectored LFOs run quietly in the background as the spheres drift and interact and let you "teleport" them - that is, move them immediately to the location specified by the 3d LFO at a time interval you choose. Whenever the spheres are teleported, they move immediately to their new location and continue with their original momentum for interesting results.
Of course, this patch can be modified to do all kinds of other things. It just felt like a pentotonic tune kind of day here. Beam me up/sideways, Scottie!
Oh yeah. Try it with a softsynth. I recommend a Cimbalon (or Karplus-Strong version thereof) tuned to a nice 7-limit Just Scale....
Great idea, really excited about these.
thanks for sharing !
the patch works fine, but ... I have strange error messages in my max window :
freeobject: 892a058: bad object
zgetfn (nextrecord): corrupt object
zgetfn (clear): corrupt object
zgetfn (nextrecord): corrupt object
freeobject: 892a8a8: bad object
freeobject: 8929290: bad object
freeobject: 892a2d8: bad object
freeobject: 8928138: bad object
freeobject: 892aa70: bad object
freeobject: 89262f0: bad object
freeobject: 8928b38: bad object
freeobject: 89289d0: bad object
freeobject: 892a6e8: bad object
freeobject: 8929f30: bad object
freeobject: 8925170: bad object
freeobject: 892a638: bad object
...
(lattest max 6.0.7, macOs 10.7.4, macPro, ...)
these errors apparently come from the second dict.iter (the one after zl.slice) in color-collision patchers ;
..bug report ?
Mathieu
Get these error messages using max 6.05.
Stephane, the usual standard information will help us avoid playing 20 questions:
1. Machine
2. OS Version
3. Version of Max you're using
Thanks.
'scuse me Sir. Goes like this : mbp 2x2,4 ghz 3 Go Ram osx 10.5.8
Before you suggest that, I can't installe 6.07 for now, because there seems to be an issue with the installer with 10.5.8 (in my case) and at least 10.6.4, as another user reported in the 'max 6.07 released' topic on the forum. I tried to open the patch with 5.19 but max window indicated jit.gl.render couldn't find destination named "".
The spheres worked but there was no midi sent, as I verified the routing to the IAC bus simply connecting a button to the makenote object.
Thank to you !
Thanks, Stephane. I expect that it's may well be a 6.0.7-related problem. Since I know my colleagues are working on the 10.5 OS install problem, the issue might fix itself, but I'll take a look.
hi stephane.
yup, gregory's patch uses some features that are only available in the 6.0.7 release.
sorry about that, hopefully the 10.5.8 installer will be available soon!
mathieu, thanks for the report, and for narrowing down the offending objects.
i can reproduce and will investigate.
these should not keep the patch from functioning.
[makenote 36 80 1000]
vs
[makenote ]
I see this from time to time. The pervert nature of Max.
nice piece staccatissimo pianissimo, molto generativo! bravo!
Mille grazie, Andrzej. Il meglio deve ancora venire!
Non vedo l'ora!
hello fizz-fans!
for today's patch-a-day, we've got a fun demonstration of constraints between rigid-bodies, and enabling motors on those constraints.
the patch creates a structure of 5 rigid-bodies, held together with hinge-constraints. i'm calling it a racer.
the racer has 1 main body shape and 4 "limbs". each limb is constrained to the main body with a hinge constraint, and each hinge constraint is motorized, allowing the racer to travel across the ground. the limb objects are each stored in their own bpather, found on the right side of the patch.
the ground (contained inside the "ground" sub-patcher) is made up of some static bodies (bodies with @mass 0). jit.phys.multiple is used to give some random obstacles to the ground.
the camera view can be controlled (via jit.anim.drive) by dragging in the window with the mouse, and pressing the w,a,s,d,q,z keys.
when you first start the patch, the racer's main-body has @kinematic mode enabled, causing it to remain in place (rather than fall to the ground from gravity). this allows you to adjust properties of the body, limbs, and hinges, without the racer bouncing around in the world. once you've adjusted those properties, you can disable kinematic mode to see your racer in action. the patch comes with two presets for different body, limb, and hinge properties. the first preset sets up the limbs more as legs, and the second preset sets them up as wheels.
you can now propel the racer forward (or backward) by enabling the limb-hinge-motors (motorvelocity and motorstrength). what tends to happen at this point is the racer tips over, so we want to add another constraint to the main-body, using the jit.phys.6dof, to prevent this. the 6dof constraint is adjusted so that there are no limitations on linear movement (the lowerlimit_lin values are greater than the upperlimit_lin), allowing the body to move anywhere in the world. the only thing we constrain is the angular orientation of the body, thereby preventing the tip-over. as a side-effect, we can now adjust the racer's direction by adjusting the world-space y-rotation of this "up" constraint. the patch allows you to use the up and down arrow keys to adjust the motorvelocity and left and right arrow keys to adjust the constraint y-rotation, thereby driving the racer.
as a last bonus, a javascript file can create some opponent racers, using the same basic structure in the main patch, with some randomness applied to certain properties. this demonstrates how physics and gl objects can be managed via javascript.
if you are feeling mirthful, comment out the lines of code that add the "up" constraint, and watch hilarity ensue as the little guys struggle to cross the terrain.
happy racing!
Hello, and time for another patch (or two) a day!
I'm exploring the jit.phys.multiple system, and particularly the use of constraints and impulses within the multiple set. My first patch - AngryHuddle - I pay homage to the complete anarchy that has become of the NFL (National Football League) with the use of replacement referees. Not only are players fighting their opponents, but they've begun fighting each other as well. I've created a simple "huddle" of 11 spheres, each constrained to an overhead 6dof that keeps them in place, with impulses that cause them to "knock heads" every once in a while.
Two important points in this patch: first, the use of the @name attribute to give names to the individual bodies that are then used by the jit.phys.6dof object. By giving the name "hangers" to the multiple set, I can access bodies with a 'hangers_n' name, where n is the body number (starting at 0). If I was using a 2-dimensional array for multiple setup, I would use 'hangers_x_y' to access the row and column of the multiple set. This gives me the ability to directly access the individual bodies by my constraints.
The second interesting feature is the use of a force matrix to impulse individual bodies. This is done by creating a matrix with a single force entity, then turning it off (by zeroing out the matrix) 100 ms later. In this way, I can have the random objects properly select and pulse one of the objects, rather than impulsing them all (which is what happens when we sent an impulse message to the jit.phys.multiple).
The jit.phys.multiple can also have an embedded constraint, where these constraints are automatically connected from body to body within the multiple set. With his permission, I am including a patch by forum user matmat (Mathieu Constans): the NurbsSheet patch, which shows a simple use of 6dof constraints within the multiple set, and using nurbs rendering to create a cool, smooth sheet-in-the-wind model that is mesmerizing to watch. You can see how using a multiple-constraint makes patching a lot simpler; as long as body-to-body constrains are what you want, you will find it much easier to accomplish using the built-in multiple mechanism.
Enjoy the patches, and enjoy the series!
[ddg]
Today's patch combines a couple of things together to make a fun time-waster. The important thing to note are the bodies using @kinematic 1. This prevents the physics of other bodies from knocking those objects around. This is useful for things where you want to control exactly where they are and move them around. With @kinematic 1, the moving walls can actually kick things around a little when they move too. I couldn't help throwing in a little GL Camera feedback in the backdrop for good measure.
Wonderful stuff ^_^
Thanks!
Very useful examples for the phys!
Thanks! :-)
A while back I was interested in creating a mini particle system that had points of force exerting themselves on the particles. After I got into it a bit, things became a little too complex to manage, and I abandoned it. Then along came Jitter Physics! Using jit.phys.multiple and jit.phys.ghost, was able to prototype this idea in about an hour, and I really love the results. Its endlessly tweakable, and as I have attempted to keep it simple, there is lots of room for expanding the idea. The patterns that emerge are really mesmerizing, and playing with various colors, materials, shapes, and positions of everything can provide some great visuals.
The set up for this patch is that there are four "force points" in a diamond shape. These are jit.phys.ghost objects. They can be attractors or repellers. Then, in the middle, there is a moveable force point, which is a combination of a jit.phys.body and a jit.phys.ghost. This gives the effect of having a body which also can attract or repel. The functionality is achieved by using the 'kinematic' attribute of the jit.phys.body, and handling all of the positioning of the object (and force), by mouse tracking in the jit.window. A jit.gl.sketch object is used to visualize the center ghost/body position.
The "particles" are all handled by the combination of jit.phys.multiple and jit.gl.multiple. In this patch, there are 400 bodies generated, and their color, torque, scale and mass are all generated by a single jit.noise object. The random matrix is then scaled by the use of jit.expr objects. Another even easier way to do it is in jit.gen, where you have the 'scale' operator. Depending on your computer, you may have to alter the amount of bodies to maintain smooth performance.
Try changing the central_force of all of the jit.phys.ghost objects. Positive repels and negative attracts. Setting the central_force to 0 effectively disables the ghost force. Sending central_impulse messages to the ghost objects create single shockwave-like forces through the physics world. Move the central "Moveable Force" around by click-dragging in the jit.window. See how the spheres are colliding with it, but also attracted or repelled.
This is just the tip of the jit.phys iceberg, so experiment and enjoy!
Hmm, no particles on my screen. I can see them if I turn jit.gl.physdraw on but otherwise not. Any reason for this? I don't get any error messages.
@deligut I had this problem! its probably because you don have this material.
delete jit.gl.material and jit.gl.gridshape objects and
make new gridshape.
it should work.
Hmm, this material file is in the standard distro, so something else must be going on. I'll take a closer look.
-Ben
For me it works out of the box on OSX 10.6.8. (On a MacbookPro 6.2)
On my Windows7 machine only deleting the jit.gl.material makes the objects appear.
(No errors in the max window)
Both systems run with max 6.0.7
Another question tough: With the 400 objects and a central force applied to the ghosts my framerate drops below the 20 fps.
So every single ghost with a central force costs 3-4 fps.
However if I set the central force to 0 it goes back to 30fps (while the objects still move around).
I am curious. Is it that much more "heavy" to calculate constant forces?
Is that because the "force" gets weaker the further away the objects are from the emitter?
Thank you all for those cool patches!
hi mark2e.
thanks for sharing your findings.
we've identified some inefficiencies with jit.phys.ghost, and will be working to fix those for the next update.
as fun and easy as jit.phys.ghost is, it's not the only way to apply forces to multiple rigid-bodies. there is also the jit.phys.multiple force matrix.
one of the benefits to using jit.phys.multiple is that since it takes matrices, we can use all the great matrix tools jitter has to offer to generate those matrices.
for today's patch, i wanted to demonstrate how we can use jit.phys.multiple with jit.path and jit.gen, to simulate bodies in a vortex or tornado.
disclaimer: in no way is this simulation intended to be scientifically accurate.
so what kind of forces are involved in this?
well, first a tornado has a long spiral shape, and objects are pulled along the shape of the spiral. and second objects are sucked upward into the spiral shape.
to create a spiral, the patch uses jit.expr and jit.path. i simply copied the jit.expr from the jit.gl.path help-file, and slightly modified the expr. i then used the "outputeval" message to jit.path to send a matrix containing the path points to a jit.gen.
the jit.gen simply takes the path matrix, and the phys.multiple position matrix, and tries to find the closest point on the path to each body. a jit.gen attribute @steps will determine how many path-points are iterated to find the closest. the more steps, the more cpu is consumed. once the closest point is found, a tangent is calculated by subtracting the previous path point from the current. this tangent will pull bodies along the path, so in order to pull bodies toward the path, we mix the tangent with the distance from the body position to the path point (adjusted by the jit.gen @fade attribute).
that's it! the force matrix is then sent to phys.multiple to apply the forces to each of the bodies. we also send the force matrix to gl.multiple color matrix, mainly for debugging. there is also a jit.phys.ghost that can be enabled to add more forces to the equation.
the real fun happens when you interpolate between presets, so a pattrstorage is provided to get you started with that.
Today's fizzy patch-a-day explores the use of the jit.phys.body object to create non-rectangular bounding regions for rigid bodies.
It uses the matrixoutput attribute of the jit.gl.gridshape object to feed into the jit.phys.body object, but any 3 plane float32 matrix can be used. By setting the shape attribute to concave, we can place objects inside the rigid body, allowing us to contain objects within any type of static or even dynamic bounding space. While this example is not perfect (some objects have a tendency to escape!) I found the implications very exciting.
Some things to play with are: the xfade amount between the primary gridshape and noise; selecting different gridshapes as boundaries; showing and hiding the bounding form and vector indicators using enable on the jit.gl.physdraw object; the difference between concave and convex hulls; amount of gravity; your own dynamic meshes (3 plane, float matrices).
Have fun!
-Cory
thank you guys a lot for all this very elucidative and inspiring patches.
We've already seen some good usage of jit.phys.ghost to push things around in a physics world. Taking inspiration from the "ghost" part (and maybe spending too much time indoors), today's patch uses jit.phys.ghost to animate a bunch of boxes as a big mass that shifts around and smashes into the walls. To add a little more liveliness to things, we also have a some force being applied to the individual boxes to make them shake and wiggle via the force matrix of jit.phys.multiple. To top it all off, the scene is surrounded by jit.gl.camera objects that are feeding their captured view onto the walls. Look inside the camera subpatches to manipulate how those are set up.
great composition! I can't take my eyes off the screen. Congrats!
I try to understand how jxs-less jit.gl.slab introduces this nice feedback effect – is it described somewhere?
btw. When trying to grasp that, I probably found a bug: color attribute of videoplane (and I suppose other jit.gl.*) doesn't appear in inspector... there is aux_color, fog_color, but not this 'color'. Maybe because there is 'color' as an attribute of patcher box ('Border color') and there occurs some clever attribute masking... Is it intended? ]:->
Hi Andrzej,
Glad you like it! The empty jit.gl.slab object is there to create a copy of the texture that is being captured to by the camera. This is done because OpenGL doesn't like it when you use a texture in the same scene that you are capturing. Usually that will result in a bunch of texture garbage. So, anytime I do OpenGL texture capture feedback I throw a jit.gl.slab object in there. The nice thing here is that if I decide later that I want to add some filters to the feedback, the jit.gl.slab is already there.
I'll leave the inspector stuff up to someone more technical to answer. You can always access attributes from the wheel menu and use attrui to change them.
The missing color attribute is due to a conflict with the box attribute of the same name. This has been previously logged as a bug, but thanks for noticing!
-Ben
@andrew: if I bypass jit.gl.slab there are no trails on videoplane, but no glitches also; like a kind of mirror. I'm curious how to control amount of those trails – there is no erase_color anywhere in the slab, and changing 'color' attr (alpha ch.) in videoplane or slab just makes whole texture paler (and in extreme case - just white). So this empty slab isn't just for security. So how it works? Below 3 screenshots illustrating my inquiry. (all other camera-videplane have slab bypassed).
1. without slab, vp color 1 1 1 1
2. with slab, vp color 1 1 1 1
3. with slab, vp color 1 1 1 0.5
@Andrzej I'm not 100% sure ;) but I think that this feedback comes from the fact that cameras are 'seeing' its own output on a jit.gl.videoplane and that's why there is no erasecolor attribute.
Ok, seems Im getting it. Please tell me if I am correct.
1. Slab intoduces one frame delay.
2. We look at the back of videoplane
3. camera (this behind videoplane) sees previous frame on video plane and objects behind it.
and here is a little quirk for me. layers. so the camera sees first colorful cubes as if it was in front of videoplane (from camera's perspective) and then (closer) videoplane with previous frame. Rather unusual situation in real world ;).
4. without slab: camera sees first more distant cubes and then just empty videoplane.
how to make some objects visible for one camera, but not for other?
"how to make some objects visible for one camera, but not for other?"
this is only possible by using jit.gl.node, however it is something we hope to allow for in a future version.
Hi Andrzej,
Nice reverse engineering! Indeed OpenGL is not really a reflection of reality, which sometimes makes it confusing to explain what is going on in natural terms. Without the slab, there is no saying what will end up in that texture. Often you will get views of other applications and other GPU junk. Rule of thumb is just to put a slab in there if you're going to use capture feedback in OpenGL. In case it's not clear, the jit.gl.cameras have been carefullly aligned so that they are pointed directly at their associated jit.gl.videoplane. The alpha color of the videoplane will change the trails. Anyways, sorry for causing this tangent. Let's get back to physics!
Today's PAD shows two different ways to do the same type of thing, create a 3D simulation of a snake erratically twitching about in a zero gravity environment, just the thing that everyone needs more of in their life!
The first method involves connecting a bunch of gridshape/body pairs with 6dof constraints, and driving them with impulses for movement and torque. This method is perhaps more descriptive of what is going on, but it also gets a little cumbersome to patch together all of these objects.
As I was building this version, Rob R. pointed out that you could do something similar with jit.phys.multiple. In addition, you can create a snake-like form by using jit.gl.path, and a "head" to the snake with another gridshape that is being driven by the rotation and position matricies from the phys.multiple object. In addition, using a two-level jit.anim.node hierarchy allows for an offset for the "head" position.
There are some interesting differences in both simulations, and both have their advantages and disadvantages. But, it helped me understand a few features I hadn't played with before. It gets really fun when you add a few more snakes to the pit and see how they interact. I've placed a jit.phys.picker object in the patch so you can toss around the snakes too.
Extra credit: how would you add a "tail" to the phys.multiple snake? How would you include the "head" to be part of the rest of the physics body?
for our final patch-a-day, i demonstrate how to create Inverse Kinematics (IK) with jit.phys and jit.gl.model. you can read more about IK here, but basically it allows you to pose a model using single position values, rather than by orienting each joint individually. eg, you can pose a model by positioning it's wrist, and the elbow and shoulder angles will be calculated automatically.
you can take this even further to create an entire skeleton structure using rigid-bodies and constraints, but in this patch we just stick to the arms. there is a sub-patcher that contains the gory details for those interested brave souls.
this wraps up our physics spotlight, and i hope that you got a taste for what can be done using ole Newton's laws. more so, i hope you got a taste for what can be done by abusing those laws. this is really the tip of the iceberg, so please dive in to these objects and show us what crazy things you come up with.
for any of you feeling confused by these patches, make sure you check out the physics-intro videos found here:
https://cycling74.com/physics/
thanks for following along with us as we explored "making things bounce", and see you on the forums!
This concludes our physics Patch-a-Day series. I want to thank all the participants, as well as all of the posters that helped keep us fired up. And I want to especially thank Rob Ramirez, whose work has inspired us, and whose examples have amazed us. Make sure you check out the video tutorials and examples on the physics page (https://cycling74.com/physics/), and feel free to post questions, enhancements or comments on this thread.
And, above all, have fun!
Hey Guys, not sure if anybody checks this anymore, but I'm gonna go ahead and throw out a question.
Have any of you ever tried to to use the Kinect's XYZ joint coordinates to re-create(not so much animate) a live person?
I'd like to see what a straight real-time recreation would like, and then see if i can add some interactivity and "enhanced reality" playback.
I'm currently just grabbing the data from Kinect-via-synapse https://cycling74.com/tools/kinect-via-synapse-max-interface/
The nitty gritty seems to be how do you control gridshapes with just two points in space? multiple conetwists?
thanks!
Hey, i'm trying to do that more or less actually, and i have no idea how to.
A question regarding Ben's snake pit PAD:
For the head of the jit.phys.multiple snake (the cube), is there a simple possibility to attach a jit.phys.body here as well? So that the head itself can be physically responsive as well, and output collision notification. Whenever i try to attach a phys.body, the head starts to struggle with the body (jittering)
Hi Tobias,
You should be able to attach a jit.phys.body to the gridshape, but in order to be able to use the anim input, and still get collisions, you will need to set the attached jit.phys.body's @kinematic attribute to 1.
-Ben
thanks ben, i still didn't it get working the way i wanted, but now i found a solution using a hinge...