multi selection

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
aiman
Posts: 19
Joined: Thu Nov 06, 2014 5:04 pm

multi selection

Post by aiman »

usually I select sceneNod using ray from camera toward the sceneNode,
I want to select more than sceneNode by drawing rectangle on the screen by dragging mouse and select all nodes behind this rectangle
any idea ?
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: multi selection

Post by thanhle »

To multiselect by draw rectangle.
You need to record 2 rays projection to screen coordinate (begin and end) using e.g.

core::position2di pos = device->getCursorControl()->getPosition();
device->getSceneManager()->getSceneCollisionManager()->getRayFromScreenCoordinates(pos, camera);

// Get node position in 2D projection coordinate.
vector2d<irr::s32> screenpos = device->getSceneManager()->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(scenNodePos);

Compare if screenpos are inside your rectangle--> Add node to selected list if it does.

To Draw rectangle:
device->getVideoDriver()->draw2DRectangleOutline(rec, video::SColor(255, 0, 255, 0));

Goodluck
thanh
aiman
Posts: 19
Joined: Thu Nov 06, 2014 5:04 pm

Re: multi selection

Post by aiman »

what do you mean by "scenNodePos" ?

I think we well catch only sceneNodes which the mouse cursor move over, is that true ?
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: multi selection

Post by thanhle »

You loop through all you nodes and get the nodes 3D position.


Regards
thanh
aiman
Posts: 19
Joined: Thu Nov 06, 2014 5:04 pm

Re: multi selection

Post by aiman »

You need to record 2 rays projection to screen coordinate (begin and end) using e.g.

core::position2di pos = device->getCursorControl()->getPosition();
device->getSceneManager()->getSceneCollisionManager()->getRayFromScreenCoordinates(pos, camera);

i have do that for every time or only for the left upper corner and right lower corner of rectangle
then loop for all nodes and do the following

// Get node position in 2D projection coordinate.
vector2d<irr::s32> screenpos = device->getSceneManager()->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(scenNodePos);

Compare if screenpos are inside your rectangle--> Add node to selected list if it does.


is that true?
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: multi selection

Post by thanhle »

Yes, that's how I do it.

There is another method, where you use the x and z coordinate in 3D.
But I don't think I need that. So I used the method I showed you.

Regards
thanh
aiman
Posts: 19
Joined: Thu Nov 06, 2014 5:04 pm

Re: multi selection

Post by aiman »

core::position2di pos = device->getCursorControl()->getPosition();
device->getSceneManager()->getSceneCollisionManager()->getRayFromScreenCoordinates(pos, camera);

i have do that for every time or only for the left upper corner and right lower corner of rectangle
then loop for all nodes and do the following
true or false ?
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: multi selection

Post by thanhle »

1) only for the left upper corner and right lower corner of rectangle
On mouse click event get upper corner.
On mouse release event get lower corner.

Then loop through all sceneNode .
On each sceneNode use other function I gave previously to project 3D pos into 2D screen pos.
If node 2D screen pos lies inside 2d rectangle then add to select node list.


Regards
thanh
aiman
Posts: 19
Joined: Thu Nov 06, 2014 5:04 pm

Re: multi selection

Post by aiman »

i did as you advice me but the result was empty or not complete.
what should i do after
vector2d<irr::s32> screenpos = device->getSceneManager()->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(scenNodePos);
is there any transformation i have to do for screenpos ???

------------------------------------------------------------------------------
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: multi selection

Post by thanhle »

After that you just check if the point is inside the 2d rectangle.
Regards
Thanh
aiman
Posts: 19
Joined: Thu Nov 06, 2014 5:04 pm

Re: multi selection

Post by aiman »

Code: Select all

if(Receiver.leftMouseDown())
        {
            if(firstCorner == core::position2d<s32>(0,0))
                firstCorner = device->getCursorControl()->getPosition();
            secondCorner = device->getCursorControl()->getPosition();
            
        }
        if(Receiver.leftMouseUp())
        {
                length1=0;
                core::list<scene::ISceneNode*> sn1 ;
                scene::IMeshSceneNode* node = 0;
                Rect = core::rect<s32>(firstCorner.X,firstCorner.Y,secondCorner.X,secondCorner.Y);
 
                collMan->getRayFromScreenCoordinates(firstCorner, maincamera);
                collMan->getRayFromScreenCoordinates(secondCorner, maincamera);
                
                core::list<scene::ISceneNode*> childs =smgr->getRootSceneNode()->getChildren();
                core::list<scene::ISceneNode*>::Iterator childs1 = childs.begin();
                core::list<scene::ISceneNode*> childs2 =(*childs1)->getChildren();
                //char** Selected_Node_Ids = new char*[100];
                int index=0;
                for(core::list<scene::ISceneNode*>::Iterator it1 = childs2.begin(); it1 != childs2.end(); ++it1)
                {
                    scene::ISceneNode* n = *it1;
                    sn1=(*it1)->getChildren();
 
                    for(core::list<scene::ISceneNode*>::Iterator it2 = sn1.begin(); it2 != sn1.end(); ++it2)
                    {
        
                        node = static_cast<scene::IMeshSceneNode*>(*it2);
                        core::matrix4 t = node->getAbsoluteTransformation();
                        core::vector3df v = core::vector3df(t[13],t[14],t[15]);
                        core::vector2d<irr::s32> screenpos = device->getSceneManager()->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(v);
                        if(screenpos.X>Rect.UpperLeftCorner.X && screenpos.X<Rect.LowerRightCorner.X && screenpos.Y>Rect.UpperLeftCorner.Y && screenpos.Y<Rect.LowerRightCorner.Y )
                        {
                            Selected_Node_Id = (char*)node->getParent()->getName();
                            funcMultiSelect();
                        }
                        
                    }
                }
                length1=index;
                firstCorner = core::position2d<s32>(0,0);
                secondCorner = core::position2d<s32>(0,0);
                Selected_Node_Id = "#";
                funcMultiSelect();
            }
        }
aiman
Posts: 19
Joined: Thu Nov 06, 2014 5:04 pm

Re: multi selection

Post by aiman »

bur the result is false
so i tried frustum

Code: Select all

if(Receiver.leftMouseDown())
        {
            mouse_up = false;
            if(firstCorner == core::position2d<s32>(0,0))
                firstCorner = device->getCursorControl()->getPosition();
            secondCorner = device->getCursorControl()->getPosition();
            
        }
        if(Receiver.leftMouseUp())
        {
            if(mouse_up==false)
            {
                mouse_up = true;
                length1=0;
                core::list<scene::ISceneNode*> sn1 ;
                scene::IMeshSceneNode* node = 0;
                Rect = core::rect<s32>(firstCorner.X,firstCorner.Y,secondCorner.X,secondCorner.Y);
 
                collMan->getRayFromScreenCoordinates(firstCorner, maincamera);
                collMan->getRayFromScreenCoordinates(secondCorner, maincamera);
 
                core::line3d<f32> Rays[4];
                core::position2d<s32> UpperRightCorner = core::position2d<s32>(Rect.LowerRightCorner.X,Rect.UpperLeftCorner.Y);
                core::position2d<s32> LowerLeftCorner=core::position2d<s32>(Rect.UpperLeftCorner.X,Rect.LowerRightCorner.Y);
                Rays[0]=collMan->getRayFromScreenCoordinates(Rect.UpperLeftCorner);
                Rays[1]=collMan->getRayFromScreenCoordinates(UpperRightCorner);
                Rays[2]=collMan->getRayFromScreenCoordinates(Rect.LowerRightCorner);
                Rays[3]=collMan->getRayFromScreenCoordinates(LowerLeftCorner);
 
                SViewFrustum SelectFrustum;
                SelectFrustum.planes[SViewFrustum::VF_FAR_PLANE] = core::plane3d<f32>(Rays[0].end,Rays[2].end,Rays[1].end);
 
                SelectFrustum.planes[SViewFrustum::VF_NEAR_PLANE] = core::plane3d<f32>(Rays[0].start,Rays[1].start,Rays[2].start);
 
                SelectFrustum.planes[SViewFrustum::VF_LEFT_PLANE] = core::plane3d<f32>(Rays[0].start,Rays[3].start,Rays[0].end);
 
                SelectFrustum.planes[SViewFrustum::VF_RIGHT_PLANE] = core::plane3d<f32>(Rays[1].start,Rays[1].end,Rays[2].end);
 
                SelectFrustum.planes[SViewFrustum::VF_BOTTOM_PLANE] = core::plane3d<f32>(Rays[2].start,Rays[2].end,Rays[3].end);
 
                SelectFrustum.planes[SViewFrustum::VF_TOP_PLANE] = core::plane3d<f32>(Rays[0].start,Rays[0].end,Rays[1].end);
                
                core::aabbox3df box = SelectFrustum.getBoundingBox();
                
                
                
                core::list<scene::ISceneNode*> childs =smgr->getRootSceneNode()->getChildren();
                core::list<scene::ISceneNode*>::Iterator childs1 = childs.begin();
                core::list<scene::ISceneNode*> childs2 =(*childs1)->getChildren();
                //char** Selected_Node_Ids = new char*[100];
                int index=0;
                for(core::list<scene::ISceneNode*>::Iterator it1 = childs2.begin(); it1 != childs2.end(); ++it1)
                {
                    scene::ISceneNode* n = *it1;
                    sn1=(*it1)->getChildren();
 
                    for(core::list<scene::ISceneNode*>::Iterator it2 = sn1.begin(); it2 != sn1.end(); ++it2)
                    {
        
                        node = static_cast<scene::IMeshSceneNode*>(*it2);
                        core::matrix4 t = node->getAbsoluteTransformation();
                        core::vector3df v = core::vector3df(t[13],t[14],t[15]);
                        core::vector2d<irr::s32> screenpos = device->getSceneManager()->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(v);
                        /*if(screenpos.X>Rect.UpperLeftCorner.X && screenpos.X<Rect.LowerRightCorner.X && screenpos.Y>Rect.UpperLeftCorner.Y && screenpos.Y<Rect.LowerRightCorner.Y )
                        {
                            Selected_Node_Id = (char*)node->getParent()->getName();
                            funcMultiSelect();
                        }*/
                        if((v.X > box.MinEdge.X && v.X < box.MaxEdge.X &&
                            v.Y > box.MinEdge.Y && v.Y < box.MaxEdge.Y &&
                            v.Z > box.MinEdge.Z && v.Z < box.MaxEdge.Z))
                        {
                            Selected_Node_Id = (char*)node->getParent()->getName();
                            funcMultiSelect();
                        }
                    }
                }
                length1=index;
                firstCorner = core::position2d<s32>(0,0);
                secondCorner = core::position2d<s32>(0,0);
                Selected_Node_Id = "#";
                funcMultiSelect();
            }
        }
is that true????????????????????????????
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: multi selection

Post by thanhle »

It should be about 15 lines of codes.
You don't need anything else beside the functions I mentioned in this post.
Regards
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: multi selection

Post by thanhle »

Assume you already get the rectangle shape.

Code: Select all

irr::core::rect<irr::f32> rect(lastPos.X, lastPos.Y, mousePos.X, mousePos.Y);
irr::core::list<irr::scene::ISceneNode *> children = root->getChildren();
core::list< scene::ISceneNode* >::Iterator IT = children.begin();
for (; IT != children.end(); ++IT)
{
            ISceneNode *node = (*IT);
            if (node== cameraNode || node == TerrainNode) continue;   //Ignore camera and terrain node
          vector3df vec = (*IT)->getPosition();
          vector2d<irr::s32> screenpos = device->getSceneManager()->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(vec);
          vector2df v(screenpos.X, screenpos.Y);
            if (rect.isPointInside(v))
            {
                                AddToSelectionList(node);
                        }
}
Post Reply