Entity Obscures another
BlitzMax Forums/MiniB3D Module/Entity Obscures another
| ||
Is there an easy way to tell if 1 entity is obscuring another? I think EntityVisible is what I need, but I don't quite understand the function description. Can someone explain what see in "Returns true if src_entity and dest_entity can 'see' each other." means exactly? |
| ||
Its very simple: In fact EntityVisible is nothing more than a Line pickpick between the src_entity and the dest_entity. Imagine 2 Spheres (like the B3D exsample for EntityVisible) and a cube in the middle of this two stretched like a wall. No a ray is shoot from src to dest and if the line hits the wall, then EntityVisible returns false else if the ray hits the dest sphere, then EntityVisible returns true, because no obstacle is between the 2 spheres. |
| ||
Thanks klepto! I've been poking at the example a bit and it seems that it is a line pick from pivot to pivot of the 2 objects. Is there anyway to find out if the object is only partially obscured? for example, using the above/B3D example as a reference. If the wall slides to the left you can see the second sphere peek around the edge before the centers become visible to each other. Additionally you can move the sphere so that it is poking through the wall but the center point is still obscured. I was digging further into line pick and it seems I could possibly use that with a radius, but it's not quite the same. Using line pick from sphere1 it would find sphere 2 if it were poking through the wall, but it would still see the wall in the way if sphere2 were peeking around the side... I think I have a work around for my project but I'm curious about other possible solutions to this for future reference. Off Topic: when do you think we might get to start playing with your new extended version? :0) |
| ||
Hey my brain is working again. What about a modified version of entityinview()? I think for my purposes I can get what I need by either moving the camera temporarily, or creating a second camera just for the view test (not sure what will be better for my code yet) and then using entityinview. This should work for me since I am only concerned with 1 direction, however a modified version of entityinview in theory could detect 1 entity to another (assuming the target is a mesh of course since that's what makes it work off bounding boxes according to the B3D docs)... Just a thought, I'll have a snout around at it when I get a chance, but perhaps someone more familiar with the functions could mash it together. In essence it just needs to be a line pick but between a point and a bounding box instead of a point and a point. if any of the box is un-obscured then it would return true... |
| ||
hmm, there are many possibilities to achieve this: solution no.1: Import klepto.minib3dextnew Strict Local width=640,height=480,depth=16,mode=2 Graphics3D width,height,depth,mode Local light:TLight=CreateLight(1) RotateEntity light,90,0,0 Local cam:TCamera=CreateCamera() PositionEntity cam,0,10,-10 Local sphere1:TMesh=CreateSphere() PositionEntity sphere1,0,0,-2 EntityColor sphere1,255,0,0 Local box:TMesh=CreateCube() ScaleMesh box,2,1.5,0.5 EntityPickMode box,2,True Local sphere2:TMesh=CreateSphere() PositionEntity sphere2,0,0,2 EntityColor sphere2,0,255,0 Local SphereVisual:TVisual = TVisual.Create(sphere2,True) PointEntity cam,sphere2 While Not KeyHit(KEY_ESCAPE) TurnEntity sphere2,0.1,0.1,0.0 If KeyDown(KEY_LEFT) Then MoveEntity box,-0.1,0,0 If KeyDown(KEY_RIGHT) Then MoveEntity box,0.1,0,0 Local visible = SphereVisual.CheckVisible(sphere1) RenderWorld Text 0,0,"Use left/right cursor keys to move block" Select visible Case 1 Text 0 , 20 , "Balls can see each other fully" Case 2 Text 0 , 20 , "Balls can see each other partial" Case 0 Text 0 , 20 , "Balls can't see each other" End Select Flip Wend End Type TVisual Field Main:TEntity Field Bounding:TPivot[8] Field Debug:TMesh[8] Function Create:TVisual(E:TEntity , Debug:Byte = False) Local V:TVisual = New TVisual V.Main = E V.Bounding[0] = CreatePivot(E) V.Bounding[1] = CreatePivot(E) V.Bounding[2] = CreatePivot(E) V.Bounding[3] = CreatePivot(E) V.Bounding[4] = CreatePivot(E) V.Bounding[5] = CreatePivot(E) V.Bounding[6] = CreatePivot(E) V.Bounding[7] = CreatePivot(E) Local W:Float = MeshWidth(TMesh(E)) Local H:Float = MeshHeight(TMesh(E)) Local D:Float = MeshDepth(TMesh(E)) TranslateEntity V.Bounding[0] , W / 2 , H / 2 , D / 2 TranslateEntity V.Bounding[1] , -W / 2 , H / 2 , D / 2 TranslateEntity V.Bounding[2] , W / 2 , -H / 2 , D / 2 TranslateEntity V.Bounding[3] , -W / 2 , -H / 2 , D / 2 TranslateEntity V.Bounding[4] , W / 2 , H / 2 , -D / 2 TranslateEntity V.Bounding[5] , -W / 2 , H / 2 , -D / 2 TranslateEntity V.Bounding[6] , W / 2 ,-H / 2 , -D / 2 TranslateEntity V.Bounding[7] , -W / 2 ,-H / 2 , -D / 2 If Debug Then V.Debug[0] = CreateSphere(,E) ScaleEntity V.Debug[0] , 0.1 , 0.1 , 0.1 V.Debug[1] = CreateSphere(,E) ScaleEntity V.Debug[1] , 0.1 , 0.1 , 0.1 V.Debug[2] = CreateSphere(,E) ScaleEntity V.Debug[2] , 0.1 , 0.1 , 0.1 V.Debug[3] = CreateSphere(,E) ScaleEntity V.Debug[3] , 0.1 , 0.1 , 0.1 V.Debug[4] = CreateSphere(,E) ScaleEntity V.Debug[4] , 0.1 , 0.1 , 0.1 V.Debug[5] = CreateSphere(,E) ScaleEntity V.Debug[5] , 0.1 , 0.1 , 0.1 V.Debug[6] = CreateSphere(,E) ScaleEntity V.Debug[6] , 0.1 , 0.1 , 0.1 V.Debug[7] = CreateSphere(,E) ScaleEntity V.Debug[7] , 0.1 , 0.1 , 0.1 Local W:Float = MeshWidth(TMesh(E)) Local H:Float = MeshHeight(TMesh(E)) Local D:Float = MeshDepth(TMesh(E)) TranslateEntity V.Debug[0] , W / 2 , H / 2 , D / 2 TranslateEntity V.Debug[1] , -W / 2 , H / 2 , D / 2 TranslateEntity V.Debug[2] , W / 2 , -H / 2 , D / 2 TranslateEntity V.Debug[3] , -W / 2 , -H / 2 , D / 2 TranslateEntity V.Debug[4] , W / 2 , H / 2 , -D / 2 TranslateEntity V.Debug[5] , -W / 2 , H / 2 , -D / 2 TranslateEntity V.Debug[6] , W / 2 ,-H / 2 , -D / 2 TranslateEntity V.Debug[7] , -W / 2 ,-H / 2 , -D / 2 End If Return V End Function Method CheckVisible:Int(src:TEntity) Local count:Int = 0 For Local I:Int = 0 To 7 count:+ EntityVisible(src , Bounding[I]) Next If Count = 8 Then Return 1 If Count = 0 Then Return 0 Return 2 End Method End Type the other method is graphics wise: Create a camera with the source as a target, hide it. Set the Viewport to a small value eg 128*128 Create a image or a pixmap Renderworld Hide the main cam, show the source cam Give the target a color and the obstacle another. Grab the image/pixmap and compare how many pixels are on screen. If no pixel is on screen, target is not in view. if all pixels (hard to guess) are on, then it is fully and every value between is partial. |
| ||
Very interesting, thank you for the code. It's a bit elegant for where my thinking is at at the moment, but if I understand it correctly there is a swarm of detectors around the object you want to see, and those detectors look back at the entity you're looking out from, and depending on how many are visible you can tell roughly how visible it is. I can see myself using this concept quite easily later in my project actually. I probably won't even need to tweak your code. One idea I was toying with, though I failed to get a model I was happy with was similar to the second method you described but using EntityInView in stead of the pixmap digging. My rough, ugly and currently abandoned concept went a little like this. Create a camera on the source entity Point the camera at the target, or in a direction set CameraProjMode to 2 for orthographic to prevent things on the sides from creeping in set the viewport to the width/height of the source entity renderworld then EntityInView, I think, should do bounding box checks on the meshes one wants to test. reset camera postion viewport etc. Additionally I was toying with creating a cube around the camera, using flipmesh and stretching it to act as a view shield. It was all horrifyingly ugly and I don't know how fast EntityInView is compared to multiple line picks... it probably depends on the number of things one is testing. with 1 target it's probably faster to run 8 line picks, but with say 20 targets that would be 20 entityinview compared to 160 line picks... My meshs are based on 2d sprites so I'm just going to do a sprite collision detection to see if I've got overlap/visibility etc, that won't work for most other uses I think. However if you used an orthographic camera view of an object, or even a regular camera view you could create a sprite from that and do 2D collision detection on that... or take a picture from the source, then hide the target entity and take another, then compare the 2 pictures, but that's going to get bogged down in digging through a pixmap like your second method... Thank you for the insight, it was quite helpfull! |
| ||
EntityInView doesn't care of obstacles so in the sphere wall scene the sphere is always visible, even if the wall is completly hiding the sphere. Also EntityInView only performs a sphere culling test and no bounding box test. |
| ||
Klepto, when i can expect the new version of miniB3d? |
| ||
in short? i'don't know exactly (too much work and too few time) currently i'm working on new concepts for the terrain engine and the scenemangement. Maybe i'm able to publish something at the end of next month, but this is just a vague guess. |