box selecting 3d

Blitz3D Forums/Blitz3D Beginners Area/box selecting 3d

mindstorms(Posted 2006) [#1]
I am getting frusterated at this code. It is used when the mouse is released after dragging. It determines if a unit is inside the box or not.
	For unit.unit = Each unit
		CameraProject camera,EntityX#(unit\entity),EntityY#(unit\entity),EntityZ#(unit\entity)
		tempx# = ProjectedX#(): tempy# = Projectedy#()
		If ((tempx > x1) And (tempx < x2)) And ((tempy > y1) And (tempy < y1)) Then 
			unit\selected = True
		Else
			unit\selected = False	
		End If
	Next
End Function

where x1 and y1 is top left corner and x2,y2 is bottom right corner. Why does this code not work?


WolRon(Posted 2006) [#2]
Hard to say. You don't tell us much information, like what kind of results you get.

All I can say at this point is;
Have you tried using the Global flag with your EntityXYZ# commands?
Have you verified that x1,x2,y1,y2 all have valid values (I can't tell from your code)?


Matty(Posted 2006) [#3]
You realise that in the code above you have used 'y1' twice.

It should read:

if ((tempx>x1) and (tempx<x2)) and ((tempy>y1) and (tempy<y2)) then ....



mindstorms(Posted 2006) [#4]
even with the change the program does not work. Here is an example illustrating what I am trying to do.




Steven Noyce(Posted 2006) [#5]
I get a MAV with that program. Do you?


Ross C(Posted 2006) [#6]
If this is 3d, why not, grab the XYZ co-ords of a CameraPick, for the initial positions, then grab the XYZ co-ords of a CameraPick on releasing the mouse, and see if an of the entities centre points lie within this?


mindstorms(Posted 2006) [#7]
sorry blitznerd, forgot to put in graphics 3d. if you try it now it should work.

Ross, that is a great suggestion! I will try it out. In the meantime, why would the way I did it not work (for future reference)?


mindstorms(Posted 2006) [#8]
How exactly does camera pick work? I know that it goes the way the camera is facing at screen coordinates inputed in the function. If it encounters no entities,however, how do I get the coordinates of the camera pick? If no entity is picked then pickedx, pickedy, and pickedz all return nothing.


Ross C(Posted 2006) [#9]
I'm not entirely sure why. I take it your projecting the entity's co-ords, into the screen co-ords, and then checking to see if the point lies within the box? (Come to think of it, that's prolly a better idea :o))

Try this:

Graphics3D 800,600
SetBuffer BackBuffer()


Global camera = CreateCamera()
PositionEntity camera,0,5,-10
RotateEntity camera,45,0,0

Global light = CreateLight()

Global plane = CreatePlane()
PositionEntity plane,0,-0.5,0
EntityColor plane,100,255,100
EntityPickMode plane,2

Global sx = 0
Global sy = 0

Global st_x# = 0
Global st_z# = 0
Global fin_x# = 0
Global fin_z# = 0
Global mouse_down = 0

Type entity
	Field mesh
	Field selected
End Type

e.entity = New entity
e\mesh = CreateCube()
EntityColor e\mesh,0,100,0
e\selected = 0
PositionEntity e\mesh,3,0,3

e.entity = New entity
e\mesh = CreateCube()
EntityColor e\mesh,0,100,0
e\selected = 0
PositionEntity e\mesh,3,0,-3



While Not KeyHit(1)


	If MouseDown(1) Then
		If mouse_down = 0 Then
			mouse_down = 1
			CameraPick(camera,MouseX(),MouseY())
			st_x = PickedX()
			st_z = PickedZ()
			DebugLog("setting - "+st_x+","+st_z)
			sx = MouseX()
			sy = MouseY()
		End If
	Else
		If mouse_down = 1 Then
			CameraPick(camera,MouseX(),MouseY())
			fin_x = PickedX()
			fin_z = PickedZ()
			If fin_x < st_x Then
				temp# = st_x
				st_x = fin_x
				fin_x = temp
			End If
			If fin_z < st_z Then
				temp# = st_z
				st_z = fin_z
				fin_z = temp
			End If
			mouse_down = 0
			select_entity()
		End If
	End If
	
	UpdateWorld
	RenderWorld
	draw_bounding_box()
	Rect MouseX(),MouseY(),2,2
	Text 0,0,st_x+" , "+st_z
	Flip
Wend
End

Function draw_bounding_box()

	If mouse_down = 1 Then
		temp_sx = sx
		temp_sy = sy
		temp_fx = MouseX()
		temp_fy = MouseY()
			If temp_fx < temp_sx Then
				temp# = temp_sx
				temp_sx = temp_fx
				temp_fx = temp
			End If
			If temp_fy < temp_sy Then
				temp# = temp_sy
				temp_sy = temp_fy
				temp_fy = temp
			End If
		Rect temp_sx,temp_sy,temp_fx-temp_sx,temp_fy-temp_sy,0
	End If

End Function

Function select_entity()

	For e.entity = Each entity
		If EntityX(e\mesh) > st_x And EntityX(e\mesh) < fin_x Then
			If EntityZ(e\mesh) > st_z And EntityZ(e\mesh) < fin_z Then
				e\selected = 1
				EntityColor e\mesh,0,255,0
				DebugLog("selected!")
			Else
				e\selected = 0
				EntityColor e\mesh,0,100,0
			End If
		Else
			e\selected = 0
			EntityColor e\mesh,0,100,0
		End If
	Next
	
End Function



Ross C(Posted 2006) [#10]
Ok, i've looked at your code. You entity is being selected. If you debuglog() the unit\selected part:

		If tempx > x1 And tempx < x2 And tempy > y1 And tempy < y2 Then 
			unit\selected = True
			DebugLog("Selected")
		Else
			unit\selected = False	
		End If


It's just that your selected_entity variable doesn't get set. But, if your bandbox selecting, you could only hold one entity in that anyway. So, your selection method works ;o)


Ross C(Posted 2006) [#11]
WHat to do, if your using a camera pick, is put a large, invisible quad/sprite (Entity alpha, NOT hide entity), to stop the pick reaching too far. Long picks are slow, so this will act as a stopper. If the pick returns nothing, it will be:

If PickedEntity() = 0 then
  ; no entity picked
end if



Ross C(Posted 2006) [#12]
In my example, i use a plane to pick from. The camerapick collides with the plane, i grab the co-ords from that. Your way of doing this, is alot better, so i'd definetly stick with it :o)


big10p(Posted 2006) [#13]
Long picks are slow
Hmm, yeah - I wonder why CameraPick doesn't have an optional 'pick_distance' parameter?!

Mark!!! :P


WolRon(Posted 2006) [#14]
It does, it's called CameraRange.


big10p(Posted 2006) [#15]
Er, OK, but that's not exactly what I meant. :)


mindstorms(Posted 2006) [#16]
Thanks for all the help! It really showed me a lot about camera project and entity pick.

Thanks!