PositionEntity bug?

Blitz3D Forums/Blitz3D Beginners Area/PositionEntity bug?

Sir Gak(Posted 2006) [#1]
I am building a game using the Create...primitives commands (CreateCube, etc). I first created a camera, set ambient light, and then a couple of planes for ceiling and floor. After creating and positioning my meshes (using PositionEntity). I checked the position of my camera (pcam) using EntityX(pcam), EntityY(pcam), and EntityZ(pcam), I had a "what the...?" revelation: my camera was nowhere the starting x-y-z positions I had set for the camera. Instead of being at PositionEntity pcam, x=20,y=0.25,z=16, I was sitting at 4.718374, -1.17, and 5.13543. My reaction: "What the??" and "Huh??"

I did some testing, and found that if I checked my camera's entity position BEFORE setting up all the meshes in their respective positions, it read the correct coordinates. After setting the meshes set-ups, it read the bogus. It wasn't just a mis-read, either. My camera REALLY was at those coords. In fact, the game was starting me off inside a wall section.

I don't know what was skewing my coordinates for the camera, but I found a workaround solution: after installing all my map meshes made from the primitives, I ran the command UpdateWorld, and then used PositionEntity for the camera, and it sat exactly where I wanted it to start. Problem solved.

But...

Does anybody have any idea as to why the positioning error was occurring in the first place? I checked the code for installing the various mesh primitives, and there is absolutely no reference to the camera (ie pcam) whatsoever. So how come it was skewed to a totally bogus starting location?


Ross C(Posted 2006) [#2]
The position entity command, moves an entity, so, if you have set up any collisions, then, the camera will move until it collides, and move no further. PositionEntity doesn't transport an entity, it moves it. If there's anything in the way, it will get stuck.

Another possiblity, is you moving the camera, then parenting it, and getting back local co-ords, instead of global ones? Try EntityX(camera,TRUE), to get it's global co-ords.

To me though, is sounds like collisions are getting in the way. Set your EntityType's after positions entities. :o) Hope that helps!


Sir Gak(Posted 2006) [#3]
As I understand the command PositionEntity, it sets coordinates in absolute space. MoveEntity moves the entity. However, I set the camera position before I did any positioning of any of the meshes, so there existed nothing for the camera to collide with, as per your suggestion. I did create a pivot as a parent, and attached the camera to it. Anyway, as I already explained, the difficulty went away following an UpdateWorld command. I was just wondering why setting up entities after setting the camera, would mess up the camera's positioning.


Ross C(Posted 2006) [#4]
Can you post your code? I could tell from that :o)


Andy(Posted 2006) [#5]
>As I understand the command PositionEntity, it sets
>coordinates in absolute space. MoveEntity moves the entity.

This is how it seems, but internally PositionEntity actually moves the entity to the new position.


Andy


Happy Sammy(Posted 2006) [#6]
Hi Sir Gak,

According to the discovery of ervin,
EntityType must be used "AFTER" PositionEntity!!!!!
Or you may get wrong initial coordinates.

Reference link:
http://www.blitzbasic.com/Community/posts.php?topic=54098#606337

Hope this helps
Sammy
:)


jfk EO-11110(Posted 2006) [#7]
When you use collision, you should, as Sammy said, set EntityType to zero until you have repositioned the object, or you may use HideEntity during Positioning, that has the same effect.


Sir Gak(Posted 2006) [#8]
Played with my code a bit, and it looks like the PositionEntity bug has not, in fact, gone away. When I tried a larger value for initially positioning my camera, I got the weird results again. I can post the code here via copy and paste, but there are a couple of textures that need to be uploaded and I don't know how to post them, so I guess would have to alter the code so as to not use those textures (unless I send them to you via email attachments).


WolRon(Posted 2006) [#9]
Have you tried the ResetEntity command? Use it after you position your entity.


Sledge(Posted 2006) [#10]

I can post the code here via copy and paste, but there are a couple of textures that need to be uploaded and I don't know how to post them, so I guess would have to alter the code so as to not use those textures



Just post it - assuming it even needs running, we can all drop temp textures in at the drop of a hat.


Sir Gak(Posted 2006) [#11]
OK. Here's the code:

;;Barebones 3D Dungeon V.013.2  01-08-2006

Graphics3D 800,600 

caps= GfxDriverCaps3D() ; 110 means it supports cube face mapping
If caps<110 Then RuntimeError "Sorry, but you need a 3D capable video card to play this game."
SetBuffer BackBuffer() 

Dim map(width,height)

Const width=20,height=20
Const closed=1, opened=2
Const wall=2, door=3, port=4, emptydoorframe=5

Type entity    ;a type to tell us what entity category we're looking at 
	Field parent
	Field entity
	Field child
	Field kind    ;wall, portcullis, door, fountian
	Field state   ;closed=1, opened=2
	Field seq
End Type

;camera stuff
pcam=CreatePivot()
camera=CreateCamera(pcam) 
EntityRadius pcam,1.45  ;doors are 3.2 wide, this is diameter 2.9, so can go through doorways
EntityType pcam,1
PositionEntity pcam,6.0,.25,6.0
CameraFogMode camera,1
Const fogrange# = 30
CameraFogRange camera,1,fogrange

;light stuff
AmbientLight 0,0,0   ;dungeon to be dark, except for torch (local) lighting
light=CreateLight(2,pcam) 
LightRange light,5
 
;image stuff
t_mag=LoadImage("data/magnifier.png")  
cursor=CreateImage(11,19)
SetBuffer ImageBuffer(cursor)
;create cursor arrow by colors and lines
	Color 128,128,128: Line 0,1,0,13: Line 4,12,4,13: Line 5,14,5,15: Line 6,16,6,17
	Color 192,192,192: Line 1,2,1,12: Line 2,3,2,11:  Line 3,4,3,10:  Line 4,5,4,9
	Line  5,6,5,9:     Line 6,7,6,9:  Line 7,8,7,9:   Line 7,14,7,17: Plot 5,11 
	Line  6,12,6,13:   Plot 8,9:      Line 8,16,8,17
	Color 255,255,255: Line 1,4,1,11: Line 2,6,2,10:  Line 4,11,7,16: Line 3,8,3,9
SetBuffer BackBuffer()
t_door   = LoadTexture("data/cdoor_no_hinge.png")
t_stone  = LoadTexture("data/stone.png")
t_ceil   = LoadTexture("data/mouldy concrete.png")
t_stone2 = LoadTexture("data/stone2.png")
t_port   = LoadTexture("data/metalrusty.png",1+4)

;plane stuff
plane=CreatePlane()
NameEntity plane,"Ground"
EntityPickMode plane,2 ;make ground pickable
EntityTexture plane,t_stone
MoveEntity plane,0,-1.5,0

ceiling=CreatePlane()
NameEntity ceiling, "Ceiling"
EntityPickMode ceiling,2
EntityTexture ceiling,t_ceil
RotateEntity ceiling,180,0,0
MoveEntity ceiling,0,-2.5,0


.mainloop
Gosub DrawMap
snake=False
Global dm#=2, d#=0, doormove#=0.0
While Not KeyDown(1) ;ESCape key
	ClearCollisions

	For e.entity =  Each entity
	Next
	strafe=False:dir#=0
	If KeyDown(205)       ;turn right
		If KeyDown(56) Or KeyDown(184) ;either ALT key
			strafe=True	
			dir=0.1
		Else
			cam_y=cam_y-2
		EndIf
	Else If KeyDown(203)  ;turn left 
		If KeyDown(56) Or KeyDown(184) ;either ALT key
			strafe=True	
			dir=-0.1
		Else	
			cam_y=cam_y+2
		EndIf
	EndIf
	cam_z#=0		
	If KeyDown(200)       ;Up arrow, go forward
		If KeyDown(42) Or KeyDown(54) ;either Shift key
			cam_z = .3  ;running
		Else
			cam_z = .1
		EndIf
	Else If KeyDown(208)  ;Down arrow, go back
		If KeyDown(42) Or KeyDown(54) ;either Shift key
			cam_z = -.3 ;running
		Else
			cam_z = -.1
		EndIf
	EndIf
	If strafe
		MoveEntity pcam,dir,0,0     ;go left or right
	Else
		RotateEntity pcam,0,cam_y,0 ;turn to left or right
		MoveEntity pcam,0,0,cam_z   ;go foward or back
	EndIf
	FlushKeys
	Collisions 1,2,2,2 ;Camera collision with objects, slide from point of collision
	If snake=True
		PositionEntity pcam,EntityX(pcam),-1.15,EntityZ(pcam)
	Else
		PositionEntity pcam,EntityX(pcam),.25,EntityZ(pcam)
	EndIf
	UpdateWorld
	RenderWorld 
	DrawImage cursor,MouseX(),MouseY()
	
	If MouseDown(1)=True 
		CameraPick(camera,MouseX(),MouseY()) 	
		message$="PickedEntity is "
		pe=PickedEntity()
		px# = (EntityX(pcam)-PickedX#()) 
		pz# = (EntityZ(pcam)-PickedZ#())
		seerange# = Sqr((px*px)+(pz*pz))
		If pe = 0
			message$ = message$+"nothing."
		ElseIf seerange => fogrange-3
			message$ = message$+"Out of Range"
		Else
			message$ = message$+EntityName$(pe)+"."
			For e.entity = Each entity
				If e\entity=pe
					If seerange <4.5
						If e\kind = door
							If Animating(e\entity) = False  ;if door is not moving
								If e\state=closed
									Animate e\entity,3,.5    
									e\state = opened 
								ElseIf e\state = opened
									Animate e\entity,3,-.5
									e\state = closed 
								EndIf
							EndIf
						ElseIf e\kind = port
							If Animating(e\entity) = False
								If e\state=closed
									Animate e\entity,3,.5    ;play animationm forward (ie raise port)
									e\state = opened 
								ElseIf e\state = opened
									Animate e\entity,3,-.5
									e\state = closed 
								EndIf
							EndIf
						EndIf
					Else
						Text 0,220,"Too far to operate!"
					EndIf
				EndIf
			Next
		EndIf
		picked$="PickedX: "+PickedX#() 
		picked$=picked$+" PickedY: "+PickedY#() 
		picked$=picked$+" PickedZ: "+PickedZ#() 
		Text 0, 200, message$ ;text here, so that renderworld does not overwrite it
	EndIf
	cam$="Camera X: "+EntityX(pcam)+" Camera Y: "+EntityY(pcam)+" Camera Z: "+EntityZ(pcam)
	Text 0,100,cam$
	Text 0,120, picked$
	Text 0,140,"See Range = "+seerange
	Flip 
Wend 
End

.createdoor
	e.entity = New entity  	 ;create a new instance of the entity type variable
	e\parent=CreatePivot()
	e\entity=CreateCube(e\parent)
	NameEntity e\entity,"Door"
	EntityPickMode e\entity,2
	PositionMesh e\entity,1,1,1 		;move "door" so that it hinges on left side
	ScaleMesh e\entity,1.6,1.8,.125 	;reshape cube to look like door (flatten, etc)
	EntityTexture e\entity,t_door 		;paint the door to look like one
	EntityType e\entity,2
	If EastWest=False Then RotateEntity e\entity,0,90,0
	epitch= EntityPitch(e\entity)
	eyaw  = EntityYaw(e\entity)
	eroll = EntityRoll(e\entity)
	For frame=1 To 45
		TurnEntity e\entity,0,2.0,0 ;turn door on its hinges
		SetAnimKey e\entity,frame
	Next	
	e\seq   = AddAnimSeq(e\entity,frame-1) ;minus 1 because For-Next loops end 1 too many
	e\kind  = door
	e\state = closed
	RotateEntity e\entity,epitch,eyaw,eroll ;undo the positioning done by the animation
Return

.createdoorframe
	e.entity = New entity  	 			;create a new instance of the entity type variable
	e\entity=CreateCube()	 			;store entity handle in the Type variable
	NameEntity e\entity,"Door Frame"
	ScaleMesh e\entity,0.2,2.0,0.4 		;reshape it into a doorpost column
	PositionMesh e\entity,0,.5,0 
	EntityPickMode e\entity,2
	
	topframe = CreateCube(e\entity)
	ScaleMesh topframe,1.6,0.2,0.4
	PositionMesh topframe,1.8,2.3,0
	
	doorframe2 = CopyMesh(e\entity,e\entity) ;copy the doorpost column
	PositionMesh doorframe2,3.6,0,0 

	AddMesh topframe,e\entity
	AddMesh doorframe2,e\entity
	EntityTexture e\entity,t_stone		;paint doorframe with concrete pic
	EntityType e\entity,2
	FreeEntity topframe
	FreeEntity doorframe2
Return

.createportcullis  ;for now, just re-using code for vertical door opening
	Const slatspace#=.291
	e.entity = New entity  	 ;create a new instance of the entity type variable
	e\parent=CreatePivot()
	e\entity=CreateCube(e\parent)
	NameEntity e\entity,"Portcullis"
	ScaleMesh e\entity,.16,1.8,.05 	;reshape cube to look like port slat (flatten, etc)
	PositionMesh e\entity,.4,1.8,.1 		;move "portcullis" 
	EntityPickMode e\entity,2
	EntityTexture e\entity,t_port 		;paint the port slat to look like one

	bar1=CreateCube(e\entity)
	ScaleMesh bar1,1.6,.16,.05
	PositionMesh bar1,1.6,3.2,0
	EntityTexture bar1,t_port 		;paint the port slat to look like one

	bar2=CreateCube(e\entity)
	ScaleMesh bar2,1.6,.16,.05
	PositionMesh bar2,1.6,3.2-slatspace*2,0
	EntityTexture bar2,t_port 		;paint the port slat to look like one

	bar3=CreateCube(e\entity)
	ScaleMesh bar3,1.6,.16,.05
	PositionMesh bar3,1.6,3.2-slatspace*4,0
	EntityTexture bar3,t_port 		;paint the port slat to look like one

	bar4=CreateCube(e\entity)
	ScaleMesh bar4,1.6,.16,.05
	PositionMesh bar4,1.6,3.2-slatspace*6,0
	EntityTexture bar4,t_port 		;paint the port slat to look like one

	bar5=CreateCube(e\entity)
	ScaleMesh bar5,1.6,.16,.05
	PositionMesh bar5,1.6,3.2-slatspace*8,0
	EntityTexture bar5,t_port 		;paint the port slat to look like one

	bar6=CreateCube(e\entity)
	ScaleMesh bar6,1.6,.16,.05
	PositionMesh bar6,1.6,3.2-slatspace*10,0
	EntityTexture bar6,t_port 		;paint the port slat to look like one

	slat1=CreateCube(e\entity)
	ScaleMesh slat1,.16,1.8,.05 	;reshape cube to look like port slat (flatten, etc)
	PositionMesh slat1,.4+slatspace*2,1.8,.1 		;move "portcullis" 
	EntityTexture slat1,t_port 		;paint the port slat to look like one

	slat2=CreateCube(e\entity)
	ScaleMesh slat2,.16,1.8,.05 	;reshape cube to look like port slat (flatten, etc)
	PositionMesh slat2,.4+slatspace*4,1.8,.1 		;move "portcullis" 
	EntityTexture slat2,t_port 		;paint the port slat to look like one

	slat3=CreateCube(e\entity)
	ScaleMesh slat3,.16,1.8,.05 	;reshape cube to look like port slat (flatten, etc)
	PositionMesh slat3,.4+slatspace*6,1.8,.1 		;move "portcullis" 
	EntityTexture slat3,t_port 		;paint the port slat to look like one

	slat4=CreateCube(e\entity)
	ScaleMesh slat4,.16,1.8,.05 	;reshape cube to look like port slat (flatten, etc)
	PositionMesh slat4,.4+slatspace*8,1.8,.1 		;move "portcullis" 
	EntityTexture slat4,t_port 		;paint the port slat to look like one

	AddMesh bar1,e\entity : FreeEntity bar1
	AddMesh bar2,e\entity : FreeEntity bar2
	AddMesh bar3,e\entity : FreeEntity bar3
	AddMesh bar4,e\entity : FreeEntity bar4
	AddMesh bar5,e\entity : FreeEntity bar5
	AddMesh bar6,e\entity : FreeEntity bar6
	AddMesh slat1,e\entity: FreeEntity slat1	
	AddMesh slat2,e\entity:	FreeEntity slat2
	AddMesh slat3,e\entity:	FreeEntity slat3
	AddMesh slat4,e\entity:	FreeEntity slat4
	EntityType e\entity,2
	EntityTexture e\entity,t_port
	
	If EastWest=False Then RotateEntity e\entity,0,90,0
	ex=EntityX(e\entity)
	ey=EntityY(e\entity)
	ez=EntityZ(e\entity)
	d=0.05
	For frame=1 To 68
		MoveEntity e\entity,0,d,0   ;for vertical portcullis effect 
		SetAnimKey e\entity,frame
	Next
	e\seq   = AddAnimSeq(e\entity,frame-1) ;minus 1 because For-Next loops end 1 too many
	e\kind  = port
	e\state = closed
	PositionEntity e\entity,ex,ey,ez ;undo the positioning done by the animation
Return

.DrawMap  ;put map out onto 3d field
	Restore mapdata
	For z=0 To height
		For x=0 To width
			Read map(x,z)
			Select map(x,z)  ;can be from 0 (nothing) to 999
			Case 1
				e.entity = New entity  	 ;create a new instance of the entity type variable
				e\entity=CreateCube()	 ;store entity handle in the Type variable
				e\kind = wall ;store what kind of entity it is (my own system)
				NameEntity e\entity,"Wall" ;give it a name
				EntityType e\entity,2    ;camera is 1, everything else is type 2 (for now)
				ScaleMesh e\entity,2,2,2
				EntityTexture e\entity,t_stone
				PositionEntity e\entity,x*4,.5,z*4
				EntityPickMode e\entity,2
			Case 2 ;empty doorframe - running East-West
				Gosub createdoorframe
				PositionEntity e\entity,x*4-1.8,0,z*4
			Case 3 ;empty doorframe - running North-South
				Gosub createdoorframe
				RotateEntity e\entity,0,90,0
				PositionEntity e\entity,x*4,0,z*4-1.8
			Case 4	;doorframe and door - running East-West
				Gosub createdoorframe
				PositionEntity e\entity,x*4-1.8,0,z*4
				EastWest=True:Gosub createdoor
				PositionEntity e\parent,x*4-1.6,-1.5,z*4-.1			
			Case 5	;doorframe and door - running North-South
				Gosub createdoorframe
				RotateEntity e\entity,0,90,0
				PositionEntity e\entity,x*4,0,z*4-1.8
				EastWest=False:Gosub createdoor
				PositionEntity e\parent,x*4+0.14,-1.5,z*4-1.6			
			Case 6	;doorframe and portcullis - running East-West
				Gosub createdoorframe
				PositionEntity e\entity,x*4-1.8,0,z*4
				EastWest=True :Gosub createportcullis
				PositionEntity e\parent,x*4-1.6,-1.5,z*4-.14			
			Case 7	;doorframe and portcullis - running North-South
				Gosub createdoorframe
				RotateEntity e\entity,0,90,0
				PositionEntity e\entity,x*4,0,z*4-1.8
				EastWest=False:Gosub createportcullis
				PositionEntity e\parent,x*4+0.14,-1.5,z*4-1.6			
			End Select
		Next
	Next
	UpdateWorld
	PositionEntity pcam,6.0,.25,6.0
Return

.mapdata
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,1
Data 1,2,1,1,2,6,1,0,0,0,0,0,0,0,7,0,0,0,0,0,1
Data 1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,6,1,1,1,6,1
Data 1,2,1,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,1,0,0,0,1,0,1,1,1,1,1,1,0,0,0,0,0,0,1
Data 1,2,1,0,0,0,1,0,1,0,0,5,0,1,0,0,0,0,0,0,1
Data 1,0,1,1,1,1,1,0,1,4,1,1,1,1,0,0,0,0,0,0,1
Data 1,2,1,0,0,0,5,0,1,0,0,0,0,3,0,0,0,0,0,0,1
Data 1,0,1,1,1,1,1,4,1,4,1,1,2,1,0,0,0,0,0,0,1
Data 1,2,1,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1
Data 1,0,1,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1
Data 1,2,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,1
Data 1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1


You can see that, early on in the code where the camera is created (pcam), PositionEntity is OK for small initial x,y,z values. If I increase x or z values to large (say, 50, etc), then I get the weird 4-point-something instead of 50 for the X, etc.

Movement around the dungeon is via the cursor keys. Hit ALT with left/right to strafe, and use SHIFT ro run instead of walk. Doors, etc, are opened by merely clicking on them with the mouse.


Ross C(Posted 2006) [#12]
Position your camera, before you give it an EntityType. Try that.


Sir Gak(Posted 2006) [#13]
Wel, Ross C, that doesn't make sense. PositionEntity for small values works OK; it's when I try to position the camera entity farther out, that I run into problems. My machine at work here won't run 3D, so I'll have to wait until I get home, but I am doubtful the suggestion you offer will work. (But, I'll try it, and the ResetEneity command suggestion, too, from WolRon.) As I mentioned before, PositionEntity works OK, no matter how far out I go, before I add all my mesh objects (the DrawMap subroutine). It's only after I've added them to my 3D world, that the PositionEntity for the camera goes bonkers.


Ross C(Posted 2006) [#14]

As I mentioned before, PositionEntity works OK, no matter how far out I go, before I add all my mesh objects (the DrawMap subroutine). It's only after I've added them to my 3D world, that the PositionEntity for the camera goes bonkers



That sounds exactly whats happening. This is what happens. You set up a collision for the camera, THEN move it. Updateworld remembers the order the things were done, so to speak. So, if you've set up the other meshes with collisions, the camera will collide with them, because you have set up the entity type, before moving. It sounds like the camera is getting caught on something.


Sir Gak(Posted 2006) [#15]
Well, I'll try things when I get home, see if any of the suggestions make any difference. Have you tried running the posted code?


Sir Gak(Posted 2006) [#16]
@Ross C:
Position your camera, before you give it an EntityType. Try that.

Tried your suggestion,. Sonnavagun! It works! Truth be told, I was skeptical, but hey, the proof is in the pudding, as the saying goes. Thanks!


Sledge(Posted 2006) [#17]

I was skeptical



Well don't be - it's not the first time this has come up, which is why your problem was solved in the first response... it shouldn't really take twelve more posts before you've been convinced to give it a whirl on the off chance it's right!


As I understand the command PositionEntity, it sets coordinates in absolute space. MoveEntity moves the entity.


The difference between them is that MoveEntity takes values that are relative to the entity's current position (either in local or global space) while PositionEntity takes values that are absolute (again, either in local or global space). It's two different ways of describing the target coodinates, not two different ways of describing how to get there.

If you want a collision-less way to place entities that have been involved in Blitz's collision system then try something like...
Function PlaceEntity(ent,x#,y#,z#,Global)
HideEntity ent
PositionEntity(ent,x,y,z,Global)
ShowEntity ent
End Function



Sir Gak(Posted 2006) [#18]
Well, I was skeptical, but I DID try it, skepticism or not, and was gratified to find it worked. Thanks for the feedback. Guess I should have tried it earlier. Just goes to show you, that you can be convinced in your mind that you know something, and be utterly wrong in that conviction. Sincerity is no substitute for the truth. Appreciate the help from all of you (and the mild rebuke, too.)