CameraPick and animated .X files

Blitz3D Forums/Blitz3D Beginners Area/CameraPick and animated .X files

Moraldi(Posted 2008) [#1]
I don't know if this has been discussed before:
CameraPick function is not working with animated .X models

; LoadMesh Example 
; ---------------- 

Graphics3D 640,480 
SetBuffer BackBuffer() 

camera=CreateCamera() 

light=CreateLight() 
RotateEntity light,90,0,0 

model% = LoadMesh("mak_running.x")
If model <> 0 Then PositionEntity camera,0,0,-MeshDepth(model)*3
FreeEntity model

; Load mesh 
animmodel% = LoadAnimMesh("mak_running.x")
EntityPickMode animmodel, 2

Animate animmodel

While Not KeyDown( 1 ) 

	RenderWorld
	UpdateWorld
	If CameraPick(camera, MouseX(), MouseY()) Then Text 0,0, "Picked"
	Flip 

Wend

End



Warner(Posted 2008) [#2]
You need to apply the pickmode to each child entity as well.


Beaker(Posted 2008) [#3]
Try adding this:
animmodel= LoadAnimMesh("mak_running.x")

ent = animmodel
While ent
	If EntityClass(ent)="Mesh"
		EntityPickMode ent, 2
	EndIf
	ent = NextChild(ent)
Wend


Function NextChild(ent)
	Local siblingcnt
	If CountChildren(ent)>0
		Return GetChild(ent,1)
	EndIf

	Local foundunused=False
	Local foundent = 0, parent,sibling
	While foundunused=False And ent<>0
		parent = GetParent(ent)
		If parent<>0
			If CountChildren(parent)>1
				If GetChild(parent,CountChildren(parent))<>ent
					For siblingcnt = 1 To CountChildren(parent)
						sibling = GetChild(parent,siblingcnt)
						If sibling=ent
							foundunused = True
							foundent = GetChild(parent,siblingcnt+1)
						EndIf
					Next
				EndIf
			EndIf
		EndIf
		ent = parent
	Wend
	Return foundent
End Function

From NextChild in code archive


Warner(Posted 2008) [#4]
Setting the picking mode for an entire animated mesh could be fairly slow, so in some cases, you could better enable the spherical or box pickmode on the model.


Moraldi(Posted 2008) [#5]
Thank you both guys!. You turned on my lights!

Edit:
you could better enable the spherical or box pickmode on the model.

You mean to each child entity, as the example above, right?


Warner(Posted 2008) [#6]
Depending on what you need it to do, sure. The fastest method would be to only enable it on the model as a whole, I guess.


Zethrax(Posted 2008) [#7]
I think CopyMesh() creates an unanimated version of the mesh using its default animation frame. Assuming this is the case, then another option would be to use CopyMesh() to create a copy of the default animation for the mesh, EntityAlpha it to zero visibility, parent that to the animated version, and pick against that instead.

I believe I found in past experiments that .b3d's don't have this problem. Pick operations seem to pick against the default animation frame.


Moraldi(Posted 2008) [#8]
@Bill Stanbrook: I didn't try it but your solution looks very clever.

Edit:
I tried. CopyMesh does not copy all hierarchy.
Before your work flow, you must copy all meshes and then make a new one.
Graphics3D 640,480 
SetBuffer BackBuffer() 

camera=CreateCamera() 

light=CreateLight() 
RotateEntity light,90,0,0 

modelname$ = "mak_running.3ds"
staticmesh% = LoadMesh(modelname$)
If staticmesh <> 0 Then PositionEntity camera,0,0,-MeshDepth(staticmesh)*3
FreeEntity staticmesh

; Load mesh 

animmesh% = LoadAnimMesh(modelname$)

staticmesh = CopyMesh(animmesh)

; alpha entity
ent = animmesh
While ent
	If EntityClass(ent)="Mesh"
		EntityAlpha ent, 0
	EndIf
	ent = NextChild(ent)
Wend

; pick entity
ent = animmesh
While ent
	If EntityClass(ent)="Mesh"
		EntityPickMode ent, 2
	EndIf
	ent = NextChild(ent)
Wend

Animate animmesh

While Not KeyDown( 1 ) 

	RenderWorld
	UpdateWorld
	If CameraPick(camera, MouseX(), MouseY()) Then Text 0,0, "Picked"
	Flip 

Wend

FreeEntity animmesh
FreeEntity staticmesh

End


Function NextChild(ent)
	Local siblingcnt
	If CountChildren(ent)>0
		Return GetChild(ent,1)
	EndIf

	Local foundunused=False
	Local foundent = 0, parent,sibling
	While foundunused=False And ent<>0
		parent = GetParent(ent)
		If parent<>0
			If CountChildren(parent)>1
				If GetChild(parent,CountChildren(parent))<>ent
					For siblingcnt = 1 To CountChildren(parent)
						sibling = GetChild(parent,siblingcnt)
						If sibling=ent
							foundunused = True
							foundent = GetChild(parent,siblingcnt+1)
						EndIf
					Next
				EndIf
			EndIf
		EndIf
		ent = parent
	Wend
	Return foundent
End Function


You will see nothing. This means that a simple copy mesh is not enough.

Note: You can locate mak_running.3ds (or mak_running.x) in sample\mak\anim\makbot folder of the Blitz3D installation