Visible entity

Blitz3D Forums/Blitz3D Beginners Area/Visible entity

Moraldi(Posted 2008) [#1]
Hi all,
How to detect if an entity is visible by a rectangle area of a screen. Let's say an area specified by: upper_left, upper_top, width, height

Thanks!


Ross C(Posted 2008) [#2]
Crude but effective. Parent 8 pivots to your entity, at the extremities of the meshes corners. Then do EntityInView () on the pivot you want to check for. That's the only practical way i'm afraid.


Moraldi(Posted 2008) [#3]
Thanks Ross C.
I tried the

bbCameraViewport(cam, upper_left, upper_top, width, height)


in combination with the

bbEntityInView(entity, cam)


but it didn't work :(


Guy Fawkes(Posted 2008) [#4]
i may not be 1 of the top coders, but i may know this, correct if i am wrong.

try this:

bbCameraViewport(cam, upper_left, upper_top, width, height)

bbentityinview(cam, entity)

use this if you wish for the cam to see the entity, or the way you used if you wish for the entity to see the cam.

hope this helps! =)

g/l w/ ur project! =)

~DarkShadowWing~


Moraldi(Posted 2008) [#5]
Thanks DarkShadowWing.
Your idea is very clever but Blitz3D seems does not like clever people...
I am getting an error: "Entity is not a camera"


Moraldi(Posted 2008) [#6]
Another way is similar to Ross C solution:
I can project the bounding box, 8 points total, for each entity to screen coordinates and see if these points are ALL lies within the rectangle.
This check could be only for visible meshes in order to increase speed


Guy Fawkes(Posted 2008) [#7]
Wait 1 second Moraldi. What have you named the camera variable? and did you make sure you turned it into a Global variable?

An example:

Graphics3D 800, 600, 0, 2
AmbientLight 255, 255, 255

Global show_text
Global show

Global cam = CreateCamera()
CameraRange cam, 1, 5000

PositionEntity cam, 0, 1, 0

Global my_object = CreateCube()
EntityColor my_object, 0, 0, 255

PositionEntity my_object, 0, 1, 4

Global sky = CreateSphere(25)
ScaleEntity sky, 1000, 1000, 1000

EntityColor sky, 0, 192, 255

EntityOrder sky, 9
FlipMesh sky

EntityAlpha my_object, .7
EntityShininess my_object, 1.0

Global land = CreatePlane()
Global landtex

landtex = LoadTexture("grass.jpg")
EntityTexture land, landtex

While 1-KeyDown(1)

PositionEntity sky, EntityX(cam), EntityY(cam), EntityZ(cam) ;position sky at cam coordinates so player cannot walk through sky object

MoveEntity cam, 0, 0, 0.4*(KeyDown(200)-KeyDown(208))
TurnEntity cam, 0, 1.0*(KeyDown(203)-KeyDown(205)), 0

UpdateWorld()
RenderWorld()

keyz = KeyHit(44)
keyx = KeyHit(45)

If keyz = 1 show = 1

If keyx = 1 show = 0

If show = 1

If EntityInView(my_object, cam) ;my_object: any object that you want the object to see the camera with or switch it around and same thing.

Text 10, 10, "I can see object: "+my_object

Text 10, 30, "Hint: move camera around until object is not seen"

Else

Text 10, 10, "I cant see object: "+my_object

Text 10, 30, "Hint: move camera around until object is not seen"

Text 10, 50, EntityX(cam)

Text 10, 70, EntityY(cam)

Text 10, 90, EntityZ(cam)

EndIf

EndIf

Flip
Wend

End


Arrow keys to move camera


Z key to show debug menu

X key to hide debug menu


Note: You will need the grass.jpg texture from the media file inside of samples/mak/castle =)


hope that helps u! =)

g/l w/ ur project! =)


~DarkShadowWing~


Moraldi(Posted 2008) [#8]
I am way from a Blitz3D installation now. I'll check your code ASAP and let you know :)
Thanks!


Uncle(Posted 2008) [#9]
Its not 100% clear what you are trying to achieve. Some of the above ideas check if the corners of the entity are visible to the camera. But from your question it looks like you want to know if an entity is visible in a certain section of the screen. If so then it would be easier to use to the camerproject function. You could simply grab the 2D x,y pos of entity and then check where it appears on the screen i.e. if it appears in the top left half of the screen and the screen resolution is 1024 x 768 then x<512 and y would be <384.


Moraldi(Posted 2008) [#10]
But from your question it looks like you want to know if an entity is visible in a certain section of the screen.

You are right! But it is not that so simple
I want to select objects using a rubber rectangle selection with the mouse. Like the way you do select icons on your XP desktop using a rectangle selection.

DarkShadowWing:
Thanks for your code but it is not what I am looking for.


Uncle(Posted 2008) [#11]

You are right! But it is not that so simple
I want to select objects using a rubber rectangle selection with the mouse. Like the way you do select icons on your XP desktop using a rectangle selection.


How accurate does your selection need to be? If you use a single cameraproject on the entity, it will return the position of the center of object. Therefore it is possible if the center of the object it not in the selection rectangle then the it wont be selected. If however this isn't an issue then its quite easy to do.

Otherwise it becomes a little tricky, and you would need a mixture of the solutions above i.e. you would need to check the extremities of each object - you could to this in a couple of ways (cycling through each vertex to see if they in the rectangle, or a less precise method of attaching a bounding box to each object based on its meshsize) Once you know the extremities of your object you can then project them into 2D and check if they are in your rectangle.


Stevie G(Posted 2008) [#12]
It should be simple ...

You should know what the top left and bottom right 2d coords are for the rubber rect in screen space, call them x0, y0 and x1, y1 respectively.

Then iterate through all the entities in the scene ( you may want to attach them to a global Mypivot for easier iteration ) and check that their 2d screen coords are within this defined rectangle.

Entities = Countchildren( MyPivot )
For c = 1 to Entities
   entity = getchild( MyPivot, c )
  cameraproject Camera, entityx( entity,1 ) , entityy( entity,1 ) , entityz( entity,1 )
  if rectsoverlap( x0 , y0 , ( x1-x0), ( y1-y0 ) , projectedx(), projectedy(), 1, 1 )
     ;this entity is within the rubber rectangle
  endif 
next



Does that work for you?


Uncle(Posted 2008) [#13]
As Stevie G says... here's a full demo

Graphics3D 1024,768,0,2
HidePointer
Color 255,255,0

Global camera=CreateCamera()
Global boxX%=100
Global boxY%=100
Global boxW%=300
Global boxH%=300

Type objs
	Field entity
End Type

Function addObjects()
	For x=1 To 40
		obj.objs=New objs
		obj\entity=CreateCube()
		EntityColor obj\entity,255,0,0
		PositionEntity obj\entity,Rand(-100,100),Rand(-100,100),Rand(-200,200)
	Next
End Function

Function checkBox()
	For obj.objs=Each objs
		CameraProject camera,EntityX(obj\entity),EntityY(obj\entity),EntityZ(obj\entity)
		If ProjectedX()>=boxX And ProjectedX()<=boxX+boxW And ProjectedY()>=boxY And ProjectedY()<=boxY+boxH Then
			EntityColor obj\entity,0,255,0
		Else
			EntityColor obj\entity,255,0,0
		EndIf
	Next
End Function

Function moveBox()
	boxX=MouseX()
	boxY=MouseY()
End Function

addObjects()
While Not KeyDown(1)
	TurnEntity camera,0.5,0.5,0
	moveBox()
	checkBox()
	RenderWorld
	Text 10,10, "Move mouse to move selection box"
	Rect boxX,boxY,boxW,boxH,0
	Flip
Wend


You can swap the "If ProjectedX()>=boxX And ProjectedX()<=boxX+boxW And ProjectedY()>=boxY And ProjectedY()<=boxY+boxH Then" for the rectoverlap command. I didnt know that one existed ;)


Moraldi(Posted 2008) [#14]
Stevie G, Uncle: You are great guys. Thank you both for your code.
I need a more precise selection and I will follow the bounding box method:

or a less precise method of attaching a bounding box to each object based on its meshsize)

I will project the bounding box of the entity and then I will check if this projection lies within my rubber selection


Ross C(Posted 2008) [#15]
Sorry for the bad info man. I mis-read your post. I though you wanted to check whether a corner of the mesh was visible to the camera.


Moraldi(Posted 2008) [#16]
No problem Ross C. I do not speak very well the English language…


Ross C(Posted 2008) [#17]
I do, i'm just sometimes terrible at reading it ;o)