How to know which surface of a cube has been clicked on?

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
dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

How to know which surface of a cube has been clicked on?

Post by dude3d »

Hi all,

I need to let the user to customize a cube's textures. A typical scenario is as the following:

1) My system renders a cube with default textures for the cube's six surfaces.

2) The user clicks on a surfaces.

3) A pop-up menu appears and let the user to choose a local texture file.

4) My system renders the clicked cube surface with the new texture.

I know how to decide whether the cube has been clicked on by functions within collision manager.

The problem is how to determine which surface the user has picked.

Any ideas?

Thanks.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

Can you get the normal of the surface clicked on? You can get a triangle3df which i think has normal information, is there someway you could use the normal of the surface to decide which side it was?

Or alternatively presumably you have the 6 sides of the cube somehow seperate so maybe you could compare the position of the intersection from the click with the bounding boxes around the sides of the cubes?
Image Image Image
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

You should be able to get access to the mesh for the cube. Access the mesh of the object, and check to see if the ray intersects the mesh bounding box. If it does, then you iterate over each mesh buffer to see if the ray intersects the front face of each triangle in the mesh buffer. If it does, then you know the mesh buffer that has been intersected. This is the mesh buffer that you want to change the material of.

Travis
dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

Post by dude3d »

Thank you guys for these quick replies.

What I did was to combine your suggestions together:

1) find the triangle that the mouse clicks on by casting a ray from the mouse 's 2D screen coordinate using collisionManager->getCollisionPoint() method.

2) Using the same ray to get which scene node has been clicked on, collisionManager->getSceneNodeFromRayBB().

3) Traverse through mesh buffers of the clicked scene node and compare its surface normal with that of the clicked triangle to determine which surface has been clicked.

It works like a charm.

Thanks a lot.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

Thinking about it i reckon you need to check more than the normal...

With a simple cube it's fine as there are 6 normals and each face has one of them meaning there are no 2 faces with the same normal.

But if you then want to move onto more complicated shapes there could be two faces with the same normal and with your current method you may change the material of the wrong one. So i guess you should check that the vertex indices or vertex positions of the hit triangle are the same as the one you've found in the mesh buffer too.
Image Image Image
PI
Posts: 176
Joined: Tue Oct 09, 2007 7:15 pm
Location: Hungary

Re:

Post by PI »

Hi! Here's my idea:

1. If you place the surfaces (2 or more triangles) that have the same triangle normals (this content will be a "side" of the mesh) and put these into 1 meshbuffer, then you have a side.

It's good, because you can change it's texture with one call. Also, it's good because you know that this was the "right" side of your mesh, for example (so it'll be easy to identify which "side" was hit by it's meshbuffer index).

You should make all the "sides" (= meshbuffers) this way, and add all of these to a mesh. In your case, this mesh will be the cube.


2. Project the ray from screen coordinates, define the ray's length.


3. The collision part: Cycle through every meshbuffers (and cycle through every triangle of the current meshbuffer) and check with a ray-collision function to decide:
- if there was collision at all,
- which triangle,
- and which "side" (= meshbuffer) was hit = what it's index,

This last one is what you're interested in.


4. Select the closest (to the ray.Start) of these hits, that'll tell you which "side" was hit, which triangle of that side (= meshbuffer), exactly where it was hit, and even give you the index number of the meshbuffer -> so you can easily change it's texture.


Cheers,
PI
paddy
Posts: 25
Joined: Tue Oct 23, 2007 12:30 pm

Post by paddy »

i would just place 6 seperate quads (invisible SceneNodes) with an
id (back, front, left, right, top, bottom) infront of the original cube Node an attach the invisible quads as childs of the cube SceneNode. ... then you could use getSceneNodeFromRayBB()

or do I'm thinking wrong ?! Its simple isn't ? :)
Post Reply