box selecting 3d
Blitz3D Forums/Blitz3D Beginners Area/box selecting 3d| 
 | ||
| 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? | 
| 
 | ||
| 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)? | 
| 
 | ||
| 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 .... | 
| 
 | ||
| even with the change the program does not work.  Here is an example illustrating what I am trying to do. | 
| 
 | ||
| I get a MAV with that program.  Do you? | 
| 
 | ||
| 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? | 
| 
 | ||
| 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)? | 
| 
 | ||
| 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. | 
| 
 | ||
| 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
 | 
| 
 | ||
| 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) | 
| 
 | ||
| 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 | 
| 
 | ||
| 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) | 
| 
 | ||
|  Long picks are slow Hmm, yeah - I wonder why CameraPick doesn't have an optional 'pick_distance' parameter?! Mark!!! :P | 
| 
 | ||
| It does, it's called CameraRange. | 
| 
 | ||
| Er, OK, but that's not exactly what I meant. :) | 
| 
 | ||
| Thanks for all the help! It really showed me a lot about camera project and entity pick. Thanks! |