Get entity Box of 3D object
Blitz3D Forums/Blitz3D Programming/Get entity Box of 3D object
| ||
I'm having a problem with Rob's Get entity box of 3D object. His example works fine but when I move the Box function to my program, all i get boxed is my entities head! (body, arms legs outside the box) I assumed the function should be a black-box, all it needs is the entity? ; perfect bounding box detection for entities - ideal for ; huds, cameras, and more! targetting squares... endless uses! ; use cursors and mouse to fly around. Global mxspd#,myspd#,campitch#,vx#,vz#,temp# Global camera Graphics3D 800,600,16,2 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,500,0 light=CreateLight() RotateEntity light,45,45,0 ; setup a small world to play within plane=CreatePlane() EntityColor plane,100,100,200 For i=0 To 10 temp=CreateSphere(8) ScaleEntity temp,Rnd(-100,100),Rnd(-100,100),Rnd(-100,100) PositionEntity temp,Rnd(-500,500),Rnd(500),Rnd(-500,500) EntityPickMode temp,2 Next Color 0,255,0 ;small test app While Not KeyHit(1) picked=CameraPick(camera,GraphicsWidth()/2,GraphicsHeight()/2) freelook UpdateWorld RenderWorld targetbox(picked) Flip Wend End ;------------------------------------------------------- Function targetbox(ent) If ent=0 Return 0 If EntityInView(ent,camera)=0 Return 0 ;CameraProject camera,EntityX(ent,True),EntityY(ent,True),EntityZ(ent,True) leftmost#=10000;ProjectedX() rightmost#=-10000;ProjectedX() topmost#=10000;ProjectedY() bottommost#=-10000;ProjectedY() For i=1 To CountSurfaces(ent) s=GetSurface(ent,1) For v=0 To CountVertices(s)-1 TFormPoint VertexX(s,v),VertexY(s,v),VertexZ(s,v),ent,0 CameraProject camera,TFormedX(),TFormedY(),TFormedZ() If ProjectedX()<leftmost leftmost=ProjectedX() If ProjectedX()>rightmost rightmost=ProjectedX() If ProjectedY()<topmost topmost=ProjectedY() If ProjectedY()>bottommost bottommost=ProjectedY() Next Next Rect leftmost,topmost,rightmost-leftmost,bottommost-topmost,0 End Function ;------------------------------------------------------- Function freelook() mxspd#=MouseXSpeed()*0.4 myspd#=MouseYSpeed()*0.4 MoveMouse GraphicsWidth()/2,GraphicsHeight()/2 campitch=campitch+myspd If campitch<-85 Then campitch=-85 If campitch>85 Then campitch=85 RotateEntity camera,campitch,EntityYaw(camera)-mxspd,0 If KeyDown(203) Then vx=vx-.1 If KeyDown(205) Then vx=vx+.1 If KeyDown(200) Then vz=vz+.1 If KeyDown(208) Then vz=vz-.1 vx=vx/1.05 vz=vz/1.05 MoveEntity camera,vx,vy,vz End Function |
| ||
I guess this is because you use animated 3ds meshes. So in fact you've got several meshes that are linked together (some are parented to others). In the targetbox function, only the root is taken into account, where you would need to also take into account all the children. Here is a modifed version of targetbox, with a little test: Function targetbox$(ent,cam%,rec%=True,parentBox$="") isRoot% = (parentBox="") If ent=0 Return "10000:10000,-10000:-10000" If Not EntityInView(ent,cam) Return "10000:10000,-10000:-10000" If (isRoot) Then leftmost#=10000 rightmost#=-10000 topmost#=10000 bottommost#=-10000 Else leftmost#=parentBox parentBox=Right(parentBox,Len(parentBox)-Instr(parentBox,":")) topmost#=parentBox parentBox=Right(parentBox,Len(parentBox)-Instr(parentBox,",")) rightmost#=parentBox parentBox=Right(parentBox,Len(parentBox)-Instr(parentBox,":")) bottommost#=parentBox EndIf For i=1 To CountSurfaces(ent) s=GetSurface(ent,1) For v=0 To CountVertices(s)-1 TFormPoint VertexX(s,v),VertexY(s,v),VertexZ(s,v),ent,0 CameraProject cam,TFormedX(),TFormedY(),TFormedZ() If ProjectedX()<leftmost leftmost=ProjectedX() If ProjectedX()>rightmost rightmost=ProjectedX() If ProjectedY()<topmost topmost=ProjectedY() If ProjectedY()>bottommost bottommost=ProjectedY() Next Next childcount%=CountChildren(ent) parentBox = leftmost+":"+topmost+","+rightmost+":"+bottommost For i = 1 To childcount childBox$=targetbox(GetChild(ent, i), cam, True, parentBox) leftmost_#=childBox childBox=Right(childBox,Len(childBox)-Instr(childBox,":")) topmost_#=childBox childBox=Right(childBox,Len(childBox)-Instr(childBox,",")) rightmost_#=childBox childBox=Right(childBox,Len(childBox)-Instr(childBox,":")) bottommost_#=childBox If leftmost_<leftmost leftmost=leftmost_ If rightmost_>rightmost rightmost=rightmost_ If topmost_<topmost topmost=topmost_ If bottommost_>bottommost bottommost=bottommost_ parentBox = leftmost+":"+topmost+","+rightmost+":"+bottommost Next If (isRoot) Then Rect leftmost,topmost,rightmost-leftmost,bottommost-topmost,0 EndIf Return parentBox End Function Graphics3D 640,480,32,2 cube% = CreateCube() sphere% = CreateSphere(8, cube) cone% = CreateCone(8,True,sphere) cyl% = CreateCylinder(8,True,sphere) PositionEntity(sphere, 4,1,-1) PositionEntity(cone, 2,0.5,1) PositionEntity(cone, -2,-1,0.5) cam% = CreateCamera() PositionEntity(cam, 0,0, -5) While Not KeyHit(1) TurnEntity(cube, 0.1,0.3,0.2) TurnEntity(sphere, 0.2,0.5,0.3) UpdateWorld RenderWorld Text(5,5,targetbox(cube, cam)) Flip() Wend End It's not very nice (I use a string to store the 4 corrdinates) but it works. Just a note: this way of computing the box (iterate through each vertex) is far from being efficient. If you don't need the box being too accurate, you could precompute a 3d bounding box, and then at runtime deduce the 2d bounding box. |
| ||
thanks |