Select multiple objects with NewtonWorldConvexCast?

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Select multiple objects with NewtonWorldConvexCast?

Postby arkdemon » Tue Jul 22, 2014 6:48 am

Hello everyone. :)
I will "format" my question in a way to make it easier for you to understand :P

It will be structured as follow:
Goal
How I am trying to achieve it
Code
Possible Error Zones (My opinion)
Question


Goal:

I want to select multiple objects within a box or a rectangle. This box is resized whenever the user drags the mouse somewhere. Here is an example: https://dl.dropboxusercontent.com/u/949 ... .46.53.wmv (the objects are in 3D)
The picked NewtonBodies would be put into a vector containing all the picked objects (or NewtonBodies)


How I am trying to achieve it:

I found that NewtonWorldConvexCast could resolve my problem, the collision shape would be a box that is resized whenever the mouse moves(or only when the user releases the mouse). I have seen there is a demo (in the sandbox) and I have copied, pasted and formatted its picking step. However, I have a problem with it (of course), but I think it comes from the initialization of the NewtonCollision shape.

Edi:t or should I use NewtonWorldForEachBodyInAABBDo? But then how can I calculate p0 and p1 (the AABB extent)?
ReEdit: Or is there a function that allows us to use this function NewtonWorldForEachBodyInAABBDo not for a aabb but for a frustum? (pyramid form)

Here is my code:


Code:

Picking function:

Code: Select all
bool Pick(float x1, float y1, float w, float h, float x2, float y2, fst::mat4 proj, fst::mat4 view){
    //x1 = click mouse x, x2 = release mouse x
    //y1 = click mouse y, y2 = release mouse y
    //w = width of screen, h = height of screen, proj = projection matrix, view = camera view matrix
    fst::vec3 p0, p1;
    float dx = x2-x1, dy = y2-y1;

      p0 = fst::unproject(x1, h-y1, w, h, proj, view, 0.f);
      p1 = fst::unproject(x1, h-y1, w, h, proj, view, 1.f);
     //I also think I have to change this code for the cases where dx < 0 or/and dy < 0 (I am not sure but I think there might be some problems for those cases)

    fst::mat4 matrix = fst::translate(fst::mat4(1.f), p0);

    float hitParam;
    NewtonWorldConvexCastReturnInfo info[16];
    NewtonCollision* const shape = NewtonCreateBox(pl::world, fst::abs(dx), fst::abs(dy), 1.f, 0, NULL); //I create the collision shape with x = dx, y = dy
    int count = NewtonWorldConvexCast (pl::world, &matrix[0].x, &p1.x, shape, &hitParam, NULL, NULL, &info[0], 4, 0);
    for (int i = 0; i < count; ++i) { // I copy the result to the vector containing the picked bodies
        picked.push_back((NewtonBody*)info[i].m_hitBody);
    }


asnd here is the code for unproject:
Code: Select all
inline fst::vec3 unproject(float x, float y, float w, float h, fst::mat4 proj, fst::mat4 mv, float depth){

    fst::vec4 r = fst::vec4((x/w)*2.f-1.f,
                            (y/h)*2.f-1.f,
                            depth*2.f-1.f,
                             1.f);
    fst::vec4 rw = fst::inverse(proj * mv) * r;
    return fst::vec3(rw) / rw.w;
}



Possible Error Zones (My opinion)

Code: Select all
NewtonCollision* const shape = NewtonCreateBox(pl::world, fst::abs(dx), fst::abs(dy), 1.f, 0, NULL); //I create the collision shape with x = dx, y = dy
(and more precisely, the size of the box (x and y)
Code: Select all
      p0 = fst::unproject(x1, h-y1, w, h, proj, view, 0.f);
      p1 = fst::unproject(x1, h-y1, w, h, proj, view, 1.f);
(This code works for NewtonWorldRayCast but I think I am not initializing it well for the NewtonWorldConvexCast)

All those snippets are found in the Picking function I provided you with


Question:

Do you know how I can initialize the NewtonCollision with changing x and y values?
Thank you for your answers :)

If you need more information, please ask me (I can also post short videos if you want)
My name is arkdemon and I don't approve this message :D
User avatar
arkdemon
 
Posts: 90
Joined: Sat Jan 18, 2014 12:38 pm

Re: Select multiple objects with NewtonWorldConvexCast?

Postby JoeJ » Tue Jul 22, 2014 10:21 am

Wow, nice formatting :)

I'm not experienced with this, but at least...

ForEachPolygonInAABBDo would be the fastest and easiest way, but you can only use it if your selection rectangle is axis aligned like the windows desktop.
If the user can rotate the playfield, the selection rectangle angle would bee rotated too, which is bad.
I guess p0 is the minimal coordinates (-1,5,3), and p1 the maximum (2,6,4). In the Callback function you could add the objects to the vector.

I think convex cast has another meaning: Shooting a virtual polyhedra along a ray and see where it would hit something.
If that's true it's no option.

If you need non axis aligned selections, maybe trigger volumes is the way to go.
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: Select multiple objects with NewtonWorldConvexCast?

Postby Julio Jerez » Tue Jul 22, 2014 11:55 am

arkdemon wrote:Edi:t or should I use NewtonWorldForEachBodyInAABBDo? But then how can I calculate p0 and p1 (the AABB extent)?
ReEdit: Or is there a function that allows us to use this function NewtonWorldForEachBodyInAABBDo not for a aabb but for a frustum? (pyramid form)


what I would do is this:

make a convex hull shape out of the 5 or 8 corner of the frustum pyramid

then us use for NewtonWorldForEachBodyInAABBDo? and for body collected buy the function test if the Frustum collision shape and the and the collsion shape of the body
using function NewtonCollisionIntersectionTest
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Select multiple objects with NewtonWorldConvexCast?

Postby arkdemon » Tue Jul 22, 2014 1:17 pm

Hello.

Thank you for your answers.

I tried doing what you recommmended me: create a pyramid shape, call NewtonWorldForEachBodyInAABBDo and inside its callback, do NewtonCollisionIntersectionTest but it does not work (as usual). I know (did not debug but I am certain) that the problem comes from the initialization of p0, and p1 because I have no idea how to initialize them.

So my question is: How can I calculate the values of p0 and p1 for the function NewtonWorldForEachBodyInAABBDo?

I prefer not to give you the code source of how I initialize those 2 values (I use unproject) but I can give you the code of how I call NewtonWorldForEachBodyInAABBDo and how I create the shape ( which is in comments)
Pick function:
Code: Select all
    fst::vec3 min = fst::min(p0, p1),
              max = fst::max(p0, p1);

    /*fst::vec3 frustum[5] = {view[POS], p00, p01, p10, p11}; //these values also need to be fixed
    NewtonCollision *shape = NewtonCreateConvexHull(pl::world, 5, &frustum[0].x, 4*5*3, 0.f, 0, NULL);*/
    NewtonWorldForEachBodyInAABBDo(pl::world, &min.x, &max.x, BoxPick, /*shape*/NULL);


BoxPick callback
Code: Select all
int BoxPick(const NewtonBody *b, void *userData){
    /*NewtonCollision *shape = (NewtonCollision*)userData;
    NewtonCollision *bc = NewtonBodyGetCollision(b);
    fst::mat4 m0; NewtonCollisionGetMatrix(shape, &m0[0].x);
    fst::mat4 m1 = pl::BodyMatrix(b);
    if(NewtonCollisionIntersectionTest(pl::world, shape, &m0[0].x, bc, &m1[0].x, 0))*/
        picked.push_back((NewtonBody*)b);
    return 1;
}


@JeoJ what is a trigger volume?
My name is arkdemon and I don't approve this message :D
User avatar
arkdemon
 
Posts: 90
Joined: Sat Jan 18, 2014 12:38 pm

Re: Select multiple objects with NewtonWorldConvexCast?

Postby JoeJ » Tue Jul 22, 2014 3:00 pm

arkdemon wrote:I know (did not debug but I am certain) that the problem comes from the initialization of p0, and p1 because I have no idea how to initialize them.


There's no simple answer - the problem is similar to your picking problem a while ago. It's not clear what's exactly the problem, most probably p0 and p1 but it seems you (and thus we) are not 100% sure. You need to split your problem to smaller parts to find the bug, and for that you need to make test cases to track the problem down:

Hardcode p0 and p1 in worldspace - forget about screen to world projection for now.
Visualize the bounding box. Visualize p0 and p1 as red and green dots. Visualize everything - always - i tell you once more! ;)
Create some bodies, and based on the result from NewtonWorldForEachBodyInAABBDo draw the bodies red or green.
This is the only way to ensure you use NewtonWorldForEachBodyInAABBDo properly.
I include bounding box code i've used for some testing recently, maybe you can copy paste the Vis code, minmax[0] = p0 and minmax[1] = p1.

When you are sure you can find the bodies inside the box (let us know if so), you can go to the next problem, which is projecting user input to p0 and p1.
I assume you do by raycasting user input, i'm not sure a frustum is necessary for that at all.
At first i'd just get mouse button down and up positions. if ground is a flat plane, you get a 2d rectangle and no 3d box, so you need to add some constant height.
When all this works you can think about the rectangle rotation and building a frustum pyramid for that for more precise intersection...

You then can say "Intersection stuff works, but i fail only at raycasting from mouse to ground", for example...


Pseudo-code using my box class:

vec mouseDown (2,3,0); // later try to get them from raycast, or a simple ray / plane intersection test
vec mouseUp (4,4,0);
RenderPoint (mouseUp , red);
RenderPoint (mouseDown , green);
mouseUp.z += 10.0; // make higher than ground plane
mouseUp.z -= 10.0: // and deeper
RenderPoint (mouseUp , red);
RenderPoint (mouseDown , green);
AABox box;
box.Init();
box.Extend (mouseDown);
box.Extend (mouseUp); // unnecessary complex to build a box from only 2 points, but it works
box.Vis (); // <- the most important line of code
vec p0 = box.minmax[0];
vec p1 = box.minmax[1];
RenderPoint (p0, blue);
RenderPoint (p1, yellow);
NewtonWorldForEachBodyInAABBDo (p0, p1);


Code: Select all
namespace Bounding
{
   struct AABox
   {
      qVec3 minmax[2];
   
      void Init ()
      {
         minmax[0] = qVec3 (FLT_MAX, FLT_MAX, FLT_MAX);
         minmax[1] = qVec3 (-FLT_MAX, -FLT_MAX, -FLT_MAX);
      }

      void Extend (qVec3 &p)
      {
         minmax[0][0] = fmin (minmax[0][0], p[0]);
         minmax[0][1] = fmin (minmax[0][1], p[1]);
         minmax[0][2] = fmin (minmax[0][2], p[2]);

         minmax[1][0] = fmax (minmax[1][0], p[0]);
         minmax[1][1] = fmax (minmax[1][1], p[1]);
         minmax[1][2] = fmax (minmax[1][2], p[2]);
      }

      void Extend (AABox &b)
      {
         minmax[0][0] = fmin (minmax[0][0], b.minmax[0][0]);
         minmax[0][1] = fmin (minmax[0][1], b.minmax[0][1]);
         minmax[0][2] = fmin (minmax[0][2], b.minmax[0][2]);

         minmax[1][0] = fmax (minmax[1][0], b.minmax[1][0]);
         minmax[1][1] = fmax (minmax[1][1], b.minmax[1][1]);
         minmax[1][2] = fmax (minmax[1][2], b.minmax[1][2]);
      }

      qVec3 Center () const
      {
         return (minmax[0] + minmax[1]) * 0.5f;
      }

      qVec3 Extent () const
      {
         return (minmax[1] - minmax[0]) * 0.5f;
      }

      qVec3 GetVertex (int i) const
      {
         return qVec3 (
            minmax[i>>2][0],
            minmax[(i>>1)&1][1],
            minmax[i&1][2]);
      }

      float GetMaxDim ()
      {
         qVec3 dim = minmax[1] - minmax[0];
         return dim.MaxElem ();
         //float  r = fmax (dim[0], dim[1]);
         //return fmax (r, dim[2]);
      }

      void Vis (float extrude = 0)
      {
         glBegin (GL_LINE_STRIP);
            glVertex3f (minmax[0][0]-extrude,   minmax[0][1]-extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[1][0]+extrude,   minmax[0][1]-extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[1][0]+extrude,   minmax[1][1]+extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[0][0]-extrude,   minmax[1][1]+extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[0][0]-extrude,   minmax[0][1]-extrude,   minmax[0][2]-extrude);
         glEnd ();

         glBegin (GL_LINE_STRIP);
            glVertex3f (minmax[0][0]-extrude,   minmax[0][1]-extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[1][0]+extrude,   minmax[0][1]-extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[1][0]+extrude,   minmax[1][1]+extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[0][0]-extrude,   minmax[1][1]+extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[0][0]-extrude,   minmax[0][1]-extrude,   minmax[0][2]-extrude);
         glEnd ();

         glBegin (GL_LINE_STRIP);
            glVertex3f (minmax[0][0]-extrude,   minmax[0][1]-extrude,   minmax[1][2]+extrude);
            glVertex3f (minmax[1][0]+extrude,   minmax[0][1]-extrude,   minmax[1][2]+extrude);
            glVertex3f (minmax[1][0]+extrude,   minmax[1][1]+extrude,   minmax[1][2]+extrude);
            glVertex3f (minmax[0][0]-extrude,   minmax[1][1]+extrude,   minmax[1][2]+extrude);
            glVertex3f (minmax[0][0]-extrude,   minmax[0][1]-extrude,   minmax[1][2]+extrude);
         glEnd ();

         glBegin (GL_LINES);
            glVertex3f (minmax[0][0]-extrude,   minmax[0][1]-extrude,   minmax[1][2]+extrude);
            glVertex3f (minmax[0][0]-extrude,   minmax[0][1]-extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[1][0]+extrude,   minmax[0][1]-extrude,   minmax[1][2]+extrude);
            glVertex3f (minmax[1][0]+extrude,   minmax[0][1]-extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[1][0]+extrude,   minmax[1][1]+extrude,   minmax[1][2]+extrude);
            glVertex3f (minmax[1][0]+extrude,   minmax[1][1]+extrude,   minmax[0][2]-extrude);
            glVertex3f (minmax[0][0]-extrude,   minmax[1][1]+extrude,   minmax[1][2]+extrude);
            glVertex3f (minmax[0][0]-extrude,   minmax[1][1]+extrude,   minmax[0][2]-extrude);
         glEnd ();
      }
   };
}
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: Select multiple objects with NewtonWorldConvexCast?

Postby arkdemon » Tue Jul 22, 2014 3:50 pm

Hi :)
It is true that I need some visualization tools :P I'll try implementing them tonight. Thanks for your code and advice.

After having debugged (just added some boxes; one at p0 and one at p1), I saw that p1 is far away (-417639417524, 5841671, -9434521 - numbers like this) and p0 is on the camera position(really close to it - it is normal). In this case, p0 and p1 are raycasting values.

It's not clear what's exactly the problem [...] it seems you (and thus we) are not 100% sure


I know where the problem comes from. It comes from the values of the AABB (p0 and p1 of NewtonWorldForEachBodyInAABBDo; they are different from the previous p0 and p1). The thing is that I do not know how to "translate" the positions from my screen in 2d to an aabb in 3d; I do not know what to put as p0 and p1 (the arguments of NewtonWorldForEachBodyInAABBDo) for the function :P . This is why I asked how I could calculate the extent of the AABB (p0 and p1 of the NewtonWorldForEachBodyInAABBDo) also because I am a complete newbie in mathematics and physics.
My name is arkdemon and I don't approve this message :D
User avatar
arkdemon
 
Posts: 90
Joined: Sat Jan 18, 2014 12:38 pm

Re: Select multiple objects with NewtonWorldConvexCast?

Postby JoeJ » Tue Jul 22, 2014 4:54 pm

It comes from the values of the AABB (p0 and p1 of NewtonWorldForEachBodyInAABBDo; they are different from the previous p0 and p1). The thing is that I do not know how to "translate" the positions from my screen in 2d to an aabb in 3d;


what do you mean with "previous" p0/1? The values you get from your fst::unproject?
If they work for raycast, they should also help us here, and your screen to world projection should work (even if you don't know how).
Assuming it works, it should be like:

mouseDownRay0 = fst::unproject(x1, h-y1, w, h, proj, view, 0.f);
mouseDownRay1 = fst::unproject(x1, h-y1, w, h, proj, view, 1.f);
mouseDownHitPoint = NewtonRayCast (mouseDownRay0, mouseDownRay1);

mouseUpRay0 = fst::unproject(x2, h-y2, w, h, proj, view, 0.f);
mouseUpRay1 = fst::unproject(x2, h-y2, w, h, proj, view, 1.f);
mouseUpHitPoint = NewtonRayCast (mouseUpRay0, mouseUpRay1);

p0 = vec (min(mouseDownHitPoint.x, mouseUpHitPoint.x),
min(mouseDownHitPoint.y, mouseUpHitPoint.y),
min(mouseDownHitPoint.z, mouseUpHitPoint.z));

p1 = vec (max(mouseDownHitPoint.x, mouseUpHitPoint.x),
max(mouseDownHitPoint.y, mouseUpHitPoint.y),
max(mouseDownHitPoint.z, mouseUpHitPoint.z));

But i assumed you tried exactly that and it does not work for some unknown reason.

The visualization is a great tool to solve geometrical problems (especially if trial and error is your best bet), and that is great to learn math.
I use functions like:
RenderLine (float width, vec p0, vec p1, float r, g, b);
RenderVector (float width, vec origin, vec vector, float r, g, b);
RenderPoint (float radius, vec origin, float r, g, b);
You can display and verify 90% af all values you calculate when solving geometrical problems so you always see what happens.
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: Select multiple objects with NewtonWorldConvexCast?

Postby arkdemon » Tue Jul 22, 2014 5:26 pm

I didn't go that far actually :P but with your code it works :D
Thank you so much!!!! (and thank you too Julio ;) )

You guys are so strong with maths and physics, I am lucky there are people like you here ^^
(and thanks for the time you spent trying to figure out my problem and how to solve it. It is very kind :mrgreen: )

For the vizualization tool, I will do it tomorrow (it is getting a bit late where I am) but it is a good idea

And thanks again for your help :)

Edit: If you want to know, I "only" did this (I tried several other combinations but I never tried using twice the RayCast function):
Code: Select all
fst::vec3 p0 = fst::unproject(x1, h-y1, w, h, proj, view, 0.f);
fst::vec3 p11 = fst::unproject(x2, h-y2, w, h, proj, view, 1.f);


Reedit: I did not do the pyramid thing yet but I will do it tomorrow too :P
My name is arkdemon and I don't approve this message :D
User avatar
arkdemon
 
Posts: 90
Joined: Sat Jan 18, 2014 12:38 pm

Re: Select multiple objects with NewtonWorldConvexCast?

Postby JoeJ » Tue Jul 22, 2014 5:34 pm

Fine, but then what was wrong? Sounds a bit like you take the code, be happy and move forward to the next obstacle.
Be sure to understand what was your mistake, and why it now works... otherwise my spent time is not worth much ;)
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: Select multiple objects with NewtonWorldConvexCast?

Postby arkdemon » Wed Jul 23, 2014 5:33 am

Hi. Yeah after I went to bed, I understood how you did it :P. It wouldn't be the approach I would have taken if I didn't know the result ... :mrgreen:
To tell you the truth, sometimes it is too complex for me to understand (I might understand most of it in 3 to 6 years :P , more 6 though but I will still have to adapt with the english terms). Anyway, now I have to make the vizualization tool and after that the pyramid thing.

Fine, but then what was wrong? [...] your mistake

Actually, it wasn't a mistake but something I did not know how to do; I did not know how to calculate p0 and p1 of the AABB and you gave me (with your code) the answer to that question ;)
My name is arkdemon and I don't approve this message :D
User avatar
arkdemon
 
Posts: 90
Joined: Sat Jan 18, 2014 12:38 pm

Re: Select multiple objects with NewtonWorldConvexCast?

Postby JoeJ » Wed Jul 23, 2014 10:44 am

arkdemon wrote:it wasn't a mistake but something I did not know how to do


This is something i simply did not recognize. I remember well the diffulicties learning programming and 3d graphics, but when i did, there where no libraries available to me. I can't imagine someone can do raytracing, but does not know about bounding boxes (because i had to implement this stuff myself at first, so i did much later). It's just that you have a very different learning experience today than i have had.
That can be confusing and thus i may head in the wrong direction at first :)
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 1 guest