finding XY coordinates for entities

Blitz3D Forums/Blitz3D Beginners Area/finding XY coordinates for entities

BlackD(Posted 2004) [#1]
I have a bunch of entity's on screen (namely sprites). Now, I've got entitypickmode and camerapick working fine, so that once I move the cursor over an entity, it is correctly targeted. However, I want to draw a box around it. I tried doing this with a sprite, ie - have a box sprite, position the box sprite where the entity is when its "picked", but of course with using a sprite comes blurry lines, missing lines, etc - with distance.

Is there an easy way to figure out the XY size of an entity AS rendered on-screen? Or is it going to take a whole bunch of calculations to turn the entity XYZ information into useable XY coordinates?

Thanks,
BlackD


BlackD(Posted 2004) [#2]
deleted..


GitTech(Posted 2004) [#3]
Have a look at the CameraProject commmand.


BlackD(Posted 2004) [#4]
err.. CameraProject command appears to have absolutely nothing to do with what I'm trying except to see if a given XYZ coordinate is visible. I'm way past that. :) I want to convert an already known visible entity at an XYZ position into XY,WH coords. I even already know the XY position, but how do I find out the width and height of that object as rendered on the screen?


jfk EO-11110(Posted 2004) [#5]
cameraproject will give you the screen coordinates of a 3d-coordinate, but still not the screen size of an entity. I'd suggest to use camerazoom (default is 1.0) * distance * real entity size.

Unfortunately the real entitysize sometimes cannot be found using MeshWidth etc. THere are some ways around this, eg:

parse all vertices of a mesh and find the min and max x,y,z (using tformpoint with vertexX etc.). These 6 Coordinates will give you a box of the real size of the entity.

But now this box is still not aligned to the screen.

A very quick and dirty workaround is to create a big screen-oriented cube around the entity, then move it towards all 6 directions seperately until MeshesIntersect will signal that the box was touching the entity (because they won't intersect as long as the entity is completely inside the box). I know, this is a silly method, but at least it works and you won't get too much headache.

If you would seek the locations of intersetion with a boolen stepwidth concept, it would also be extremly fast.


BlackD(Posted 2004) [#6]
thanks a bunch JFK. Although not direct, you answered my question - ur ideas there stimulated some thinking.

I think it'll take less space to code it than explain it, but heres how I'll do it.

- I already know what sizes the entities are.
- Create a cube around the entity and orient it to the screen.
- extract the XYZ coordinates of the 4 facing corners.
- create pivots on these points.
- Find the Screen XY locations of each of these pivots.
- Voila! You have 4 sets of coordinates from which you can make up X1,Y1 to X2,Y2

With X1,Y1,X2,Y2 I can do a lot more than just draw a box. :) Only a small amount of hacking would be required to take into account entities that are partly off screen, since the entity size is already known.

Hehe.. you'd think there'd be a single command to do it. Theres still lots of us 2D-USING-3D programmers. :)
Mark - EntityVisWidth() EntityVisHeight() ;)

Thanks again,
+BlackD


BlackD(Posted 2004) [#7]
Okay.. figured out the quickest way to do it. Buggy when two entities are overlapped, would need a little more coding there. Used CAMERAPROJECT as suggested simply to remove another loop from the code and double the speed.

Quick and easy (and very dirty) 2D entity-bounding box:

	Graphics3D 800,600,0,2
	camera=CreateCamera()
	light=CreateLight()
	SeedRnd MilliSecs()
	
	;create some pickable entities
	Type thing
	Field mesh
	Field x
	Field y
	Field z
	End Type
	For i = 1 To 20
	sphere.thing = New thing
	sphere\mesh = CreateSphere()
	sphere\x=Rnd(-20,20)
	sphere\y=Rnd(-20,20)
	sphere\z=Rnd(10,40)
	EntityPickMode sphere\mesh,1
	EntityRadius sphere\mesh,1
	PositionEntity sphere\mesh,sphere\x,sphere\y,sphere\z
	Next
		
	While Not KeyHit(1)	
	
	UpdateWorld
	RenderWorld
	
	For sphere.thing = Each thing
		If sphere\mesh=CameraPick(camera,MouseX(),MouseY()) Then
			CameraProject camera,sphere\x,sphere\y,sphere\z
			x=ProjectedX()
			y=ProjectedY()
			;find top
				ty=y
				While sphere\mesh=CameraPick(camera,x,ty)
				ty=ty-1
				Wend
			;find bottom
				by=y
				While sphere\mesh=CameraPick(camera,x,by)
				by=by+1
				Wend
			;find left
				lx=x
				While sphere\mesh=CameraPick(camera,lx,y)
				lx=lx-1
				Wend
			;find right
				rx=x
				While sphere\mesh=CameraPick(camera,rx,y)
				rx=rx+1
				Wend
			w=rx-lx
			h=by-ty
			Rect lx,ty,w,h,0
			End If		
		Next
	Flip
	Wend
	End



big10p(Posted 2004) [#8]
You should be able to use PickedTime() multiplied by a constant to scale the box sprite. It should then remain at a constant size onscreen, regardless of the distance the selected sprite is away from the camera.

I've used this method before to scale a small sphere I was using as a 3D mouse cursor. It seems to work well.