zabaki
May 25, 2011, 2:05am
#1
Hi, it’s me again.
I’m still working on the same project and I’m now stuck with two problems. The first one concern PlaneNodes and the other one is about clicking on a 3D object.
I wanted to use PlaneNode to create a sort of “base” on my scene by putting a texture on it. I tried this :
Planef plan(LPoint3f(0,0,0),LPoint3f(0,1,0),LPoint3f(1,0,0));
PlaneNode* planenode = new PlaneNode("ground");
planenode->set_plane(plan);
Filename filename = Filename("Myfile.png");
Texture * tex = TexturePool::load_texture(filename);
NodePath nodepath(planenode);
tex->set_wrap_u(Texture::WM_repeat);
tex->set_wrap_v(Texture::WM_repeat);
nodepath.set_texture(tex);
nodepath.reparent_to(_win_fr->get_render());
But unfortunately, it doesn’t seems to work. Do you have any solution ?
I’ve also been trying to “click” on 3D objects and I came up with this :
CollisionTraverser myTraverser = CollisionTraverser("ctraverser");
CollisionNode* pickerNode = new CollisionNode("mouseRay");
NodePath pickerNP = _win_fr->get_camera_group().attach_new_node(pickerNode);
pickerNode->set_from_collide_mask(GeomNode::get_default_collide_mask());
CollisionRay* pickerRay = new CollisionRay();
pickerNode->add_solid(pickerRay);
CollisionHandlerQueue* myHandler = new CollisionHandlerQueue();
myTraverser.add_collider(pickerNP, myHandler);
pickerRay->set_from_lens(_camera, x, y);
myTraverser.traverse(_win_fr->get_render());
if(myHandler->get_num_entries() > 0)
{
std::cout<<"it works"<<std::endl;
myHandler->sort_entries();
NodePath pickedObj = myHandler->get_entry(0)->get_into_node_path();
return PandaEntity::get(pickedObj.node());
}
else{
std::cout<<"nope"<<std::endl;
return NULL;
}
But again, it doesn’t work. Any suggestion ?
Thank you again,
Quentin.
zabaki
May 26, 2011, 4:17am
#2
No one has even just a clue of how I could solve these problems ? I’ve been working on it the whole day and I diddn’t came up with anything.
tah
May 26, 2011, 4:27am
#3
Hi
I don’t know about using the PlaneNode to create a ground plane to use as the base of your scene. I tried your code and can’t see anything.
Here is another method using card maker:
CardMaker cm("ground");
cm.set_frame(0.,512.,0.,512);
PT(PandaNode) card = cm.generate();
Filename filename = Filename("Myfile.png");
Texture * tex = TexturePool::load_texture(filename);
NodePath nodepath(card);
nodepath.set_p(-90.);
tex->set_wrap_u(Texture::WM_repeat);
tex->set_wrap_v(Texture::WM_repeat);
nodepath.set_texture(tex);
nodepath.reparent_to(_win_fr->get_render());
I use GeoMipTerrain for my scene base and use the get_elevation function to find the z value on the terrain, but since you are making a flat world then maybe CardMaker is okay.
As for the picking, I don’t see how you set your x and y; but here is how I do it:
Viewer::Viewer(PandaFramework *fw, QtGUI *gui){
.
.
mPickerRay = new CollisionRay(0., 0., 0., 0., 1., 0.);
PT(CollisionNode) camGroundCol = new CollisionNode("mPickerRay");
camGroundCol->add_solid(mPickerRay);
camGroundCol->set_from_collide_mask(BitMask32::bit(0));
camGroundCol->set_into_collide_mask(BitMask32::all_off());
camGroundNode = mCameraNode.attach_new_node(camGroundCol);
mCamGroundHandler = new CollisionHandlerQueue();
mGroundTraverse.add_collider(camGroundNode,mCamGroundHandler);
.
.
}
bool Viewer::getPick(NodePath &hitNode,LPoint3f &hitPt,float &minDist){
bool pickOk = false;
float xsize = (float)window->get_graphics_window()->get_x_size();
float ysize = (float)window->get_graphics_window()->get_y_size();
mMouseX = window->get_graphics_window()->get_pointer(0).get_x();
mMouseY = window->get_graphics_window()->get_pointer(0).get_y();
int yy = ysize - mMouseY;
float xp = 2.*(float)mMouseX/xsize - 1.;
float yp = 2.*(float)yy/ysize - 1.;
mPickerRay->set_from_lens(window->get_camera(0), xp, yp);
mGroundTraverse.traverse(mRootNode);
CollisionEntry *entry;
if(mCamGroundHandler->get_num_entries()){
pickOk = true;
LVecBase3f pos = mCameraNode.get_pos();
mCamGroundHandler->sort_entries();
entry = mCamGroundHandler->get_entry(0);
hitPt = entry->get_surface_point(mRootNode);
hitNode = entry->get_into_node_path();
minDist = (hitPt - pos).length();
printf("hit node:%s pt:%f %f %f\n",hitNode.get_name().c_str(),hitPt.get_x(),hitPt.get_y(),hitPt.get_z());
}
return(pickOk);
}
any model that you want to be pickable should have its collide mask set the same as the CollisionNode,
in my case I use model_node.set_collide_mask(BitMask32::bit(0));
drwr
May 26, 2011, 11:42pm
#4
Note, for the record, that a PlaneNode is used to describe a plane as a mathematical concept; it is not normally visible and doesn’t work with setTexture() and whatnot. If you want to make a visible polygon for a floor plane, either load the intended polygon from an egg file, or use something like CardMaker to create a visible polygon.
David