conditional jitter matrix operations on a matrix level (a bit like numpy)
I want to implement a 'bounce' like behavior for a number of objects moving in space and bouncing off walls. I can do this in javascript, or using a million patches iterating each cell, but I'm wondering if it's possible to do without iterating the cells, and just use smart jit operator and expressions.
i have one dimensional (1 cell per object), 3 plane (xyz) matrices
- pos
- vel
- dir // think of this as a 'bounce' property for each plane (component). either +1 or -1. This is what I flip when an object hits a wall. (I don't want to flip the sign of the vel matrix on bounce, because it's being written into by external processes. So I want to store the 'flippedness' in a separate matrix).
pos = vel * dir + pos
this is easy with jit.+ and jit.*
but I also want to bounce (i.e. flip the sign of dir) of any individual cell plane, when the current cell plane value goes beyond a threshold. And the threshold is dependent on the plane.
i.e. my world boundary is [xmin ymin zmin] -> [xmax ymax zmax]
for each cell i:
if(pos[i].x < xmin) { pos[i].x = xmin; dir[i].x *= -1; }
else if(pos[i].x > xmax) { pos[i].x = xmax; dir[i].x *= -1; }
if(pos[i].y < ymin) { pos[i].y = ymin; dir[i].y *= -1; }
else if(pos[i].y > ymax) { pos[i].y = ymax; dir[i].y *= -1; }
if(pos[i].z < zmin) { pos[i].z = zmin; dir[i].z *= -1; }
else if(pos[i].z > zmax) { pos[i].z = zmax; dir[i].z *= -1; }
Is it possible to do the above on a matrix level (i.e. not cell level)? e.g. in numpy (python matrix lib) there'd be syntax something like
dir[pos < worldmin] *= -1
pos[pos
------
update: here's a toy example
I believe there's a typo in your code -- all of the "else if" statements appear to be testing if > max value, not min value.
Assuming I understand correctly, there's a fairly simple answer, but it requires two separate jit.op driven streams to accomplish what you want.
jit.min and jit.max can be used to constrain the pos values.
jit.> and jit.< can be used to create a multiplication mask to flip the dir values.
Hi Jesse, yes apologies there was a typo in my code. I've fixed that now.
thanks for the sample, I've learnt a lot from it. though the conditional multiplication mask for dir matrix has lots of zeros in it. That would zero out the dir matrix. Wouldn't they need to be 1, not 0?. What's a good way of doing that? Based on what you've done I've attempted to do this by jit.== against a freshly initted jit.matrix (full of zeros) and then add to your conditional mask (which is 0s, and -1s) to give the multiplication matrix (1s and -1s), which I can multiply my dir matrix with. Or is there a quicker way?
I've put it all together. It still seems like an awful lot of nodes for something so simple. I'm wondering if I'd rather just do it in javascript and iterate!
Is there a way of doing it in a jit.expr?
i would do it with jit.gen.
here's a bit of your patch converted to get you started:
Wow, thanks for sending me on the delicious rabbit hole that is gen! I'd never seen it before, I wish I knew about it a year ago.
I'd love to be able to do this whole thing in jit.gen / codebox, I was hoping I could do it in 3 lines of code! But i was wrong. I'm still getting stuck on flipping only some components of dir, not all simultaneously. I've attached my patch, and just the codebox code (most of it is for readability, the actual code is just 3 lines. ). is it possible to do the bounce in codebox?
Param mins(-1., -2., -3.);
Param maxs(1., 2., 3.);
pos = in1;
vel = in2;
dir = in3;
// advect
pos += vel * dir;
// bounce
//dir[posmaxs)] *= -1; // this is what I really want to do
if(pos=maxs) dir*= -1; // this only checks the first component of the vector, and flips the entire dir vector
out2 = dir;
// clamp
pos = clamp(pos, mins, maxs);
out1 = pos;
I'm sure there's a more elegant way to do this, but this appears to work:
Param mins(-1., -2., -3.);
Param maxs(1., 2., 3.);
pos = in1;
vel = in2;
dir = in3;
// advect
pos += vel * dir;
// bounce
//dir[posmaxs)] *= -1; // this is what I really want to do
dir_x = dir.x;
dir_y = dir.y;
dir_z = dir.z;
if(pos.x=maxs.x) dir_x *= -1;
if(pos.y=maxs.y) dir_y *= -1;
if(pos.z=maxs.z) dir_z *= -1;
dir = vec( dir_x, dir_y, dir_z );
out2 = dir;
// clamp
pos = clamp(pos, mins, maxs);
out1 = pos;
cool thx, that does the trick.