| this is just an initial design, but it shows some of the possibilities.  this builds off the animator MiniB3D addition i posted earlier.  again no modifications to MiniB3D.  save this to a file called animator.bmx in the same directory as MiniB3D.bmx. 
 
Import "MiniB3D.bmx"
Import Pub.ColDet
' animator.bmx
Type IEntityAnimator Extends TMesh
	Const ORDER_BASE:Int=999999
	
	Method Update()
		Local entity:TEntity=GetParent()
		If entity Then AnimateEntity(entity,MilliSecs()) Else DebugLog("IEntityAnimator: No Entity")
	EndMethod
	' called each update to animate an entity	
	Method AnimateEntity(entity:TEntity,timeMS:Int) Abstract
EndType
Type TColDetCollisionAdapter Extends ICollisionAdapter
	Field model:TCollisionModel3D=Null
	
	Method New()
		model=New TCollisionModel3D
	EndMethod
	Function EntityAddAdapter(entity:TEntity,order:Int=0)		
		Local coll:TColDetCollisionAdapter=TColDetCollisionAdapter.Create(entity)
		' set the order so the animator update is called before the update to the entity
		EntityOrder(coll,(ORDER_BASE-order)) 
	EndFunction
	
	Function create:TColDetCollisionAdapter(parent_ent:TEntity)
		If Not TMesh(parent_ent) Then RuntimeError "TColDetCollisionAdapter.create(): invalid entity passed"
		
		Local coll:TColDetCollisionAdapter=New TColDetCollisionAdapter
		coll.class$="TColDetCollisionAdapter"
		
		coll.AddParent(parent_ent)
		coll.EntityListAdd(entity_list)
		' update matrix
		If coll.parent<>Null
			coll.mat.Overwrite(coll.parent.mat)
			coll.UpdateMat()
		Else
			coll.UpdateMat(True)
		EndIf
		
		' populate the collision model with triangles
		coll.FillCollisionModel()
		
		Return coll
	EndFunction	
	
	' populates the collision model with the mesh triangles
	Method FillCollisionModel()
		Local entity:TMesh=TMesh(getParent())
		' loop through each surface		
		For Local s:Int=1 To entity.CountSurfaces()
			
			Local surf:TSurface=entity.GetSurface(s)
			
			' loop through each triangle of the surface
			For Local t:Int=1 To surf.CountTriangles()
				' add each triangle to the collision model
				model.addTriangle( ..
					surf.VertexX(surf.TriangleVertex(t,0)), ..
					surf.VertexY(surf.TriangleVertex(t,0)), ..
					surf.VertexZ(surf.TriangleVertex(t,0)), ..
					surf.VertexX(surf.TriangleVertex(t,1)), ..
					surf.VertexY(surf.TriangleVertex(t,1)), ..
					surf.VertexZ(surf.TriangleVertex(t,1)), ..
					surf.VertexX(surf.TriangleVertex(t,2)), ..
					surf.VertexY(surf.TriangleVertex(t,2)), ..
					surf.VertexZ(surf.TriangleVertex(t,2)))					
			Next							
		Next
		
		' finalize the model
		model.finalize()
	EndMethod
	Method OnUpdate(entity:TEntity)
		' check for a collision
		For Local mesh:TEntity=EachIn TEntity.entity_list
			If mesh<>Self And mesh.class="TColDetCollisionAdapter"
				If model.Collision(TColDetCollisionAdapter(mesh).model)					
					DebugLog(MilliSecs()+": "+entity.EntityName()+" hit "+mesh.getParent().EntityName())
				EndIf
			EndIf
		Next
	EndMethod
	' because this is a child, this gets called every time the parent is updated	
	Method OnUpdateMat(entity:TEntity)
		' update the model transformation with the parents matrix
		model.setTransform(entity.mat.grid)		
	EndMethod
	
	' 
	Method OnFreeEntity(entity:TEntity)
	EndMethod
EndType
' collision adapter for entity
' this is meant to store/update collision info for an entity and also to 
' allow cleanup via the free entity
' needs to fire after the animators but before the entitys so ORDER_BASE is 10000 lower
Type ICollisionAdapter Extends TMesh
	Const ORDER_BASE:Int=989999
	Method Update()
		Local entity:TEntity=GetParent()
		If entity Then OnUpdate(entity) Else DebugLog("ICollisionAdapter: No Entity")
	EndMethod
	Method UpdateMat(load_identity:Int=False)
		Local entity:TEntity=GetParent()
		If entity Then OnUpdateMat(entity) Else DebugLog("ICollisionAdapter: No Entity")
	EndMethod
	Method FreeEntity()
		Local entity:TEntity=GetParent()
		If entity Then OnFreeEntity(entity) Else DebugLog("ICollisionAdapter: No Entity")
	EndMethod
	
	Method OnUpdate(entity:TEntity) Abstract
	' this updates when the entity updates
	Method OnUpdateMat(entity:TEntity) Abstract
	Method OnFreeEntity(entity:TEntity) Abstract
EndType
now for an implementation.  again, this is based on the MiniB3D test-alpha.bmx program.  save the following code into test-alpha_anim.bmx in the same directory as test-alpha.bmx
 
 
Import "../MiniB3D.bmx"
Import BRL.PNGLoader
Import "../animator.bmx"
Local width=640,height=480,depth=16,mode=0
Graphics3D width,height,depth,mode
Local cam=CreateCamera()
Local light=CreateLight()
Local ent1=CreateCube()
Local tex=LoadTexture("media/test.png")
EntityTexture ent1,tex
Local ent2=CopyEntity(ent1)
Local ent3=CopyEntity(ent1)
Local ent4=CopyEntity(ent1)
Local ent5=CopyEntity(ent1)
Local ent6=CopyEntity(ent1)
' -----------------------------
' add a controller to the cam.  this could just as easily
' be added to one of the cubes
' -----------------------------
TCameraController.EntityAddAnimator(cam,0)
' -----------------------------
' -----------------------------
' create simple rotation animators and add them to 
' ents 1-4
' -----------------------------
TSimpleRotateAnimator.EntityAddAnimator(ent1,.5)
TSimpleRotateAnimator.EntityAddAnimator(ent2,-.5)
TSimpleRotateAnimator.EntityAddAnimator(ent3,1)
TSimpleRotateAnimator.EntityAddAnimator(ent4,-1)
NameEntity(ent1,"ent1")
NameEntity(ent2,"ent2")
NameEntity(ent3,"ent3")
NameEntity(ent4,"ent4")
NameEntity(ent5,"ent5")
NameEntity(ent6,"ent6")
' add some collision detection to all the boxes
TColDetCollisionAdapter.EntityAddAdapter(ent1)
TColDetCollisionAdapter.EntityAddAdapter(ent2)
TColDetCollisionAdapter.EntityAddAdapter(ent3)
TColDetCollisionAdapter.EntityAddAdapter(ent4)
TColDetCollisionAdapter.EntityAddAdapter(ent5)
TColDetCollisionAdapter.EntityAddAdapter(ent6)
' -----------------------------
PositionEntity ent1,0,0,10
PositionEntity ent2,0,0,5
PositionEntity ent3,0,0,20
PositionEntity ent4,0,0,15
PositionEntity ent5,0,0,30
PositionEntity ent6,0,0,25
EntityAlpha ent2,0.5
EntityAlpha ent4,0.5
Local cx#=0
Local cy#=0
Local cz#=0
Local pitch#=0
Local yaw#=0
Local roll#=0
' used by fps code
Local old_ms=MilliSecs()
Local renders
Local fps
While Not KeyDown(KEY_ESCAPE)		
	If KeyHit(KEY_ENTER) Then DebugStop
	RenderWorld
	renders=renders+1
	
	' calculate fps
	If MilliSecs()-old_ms>=1000
		old_ms=MilliSecs()
		fps=renders
		renders=0
	EndIf
	
	GLDrawText "FPS: "+String(fps),0,0
	PositionEntity(ent2,0,0,EntityZ(ent2)+.01)
	Flip
' problem with freeentity
'FreeEntity(ent6)
Wend
End
' -----------------------------
' begin the animator types
' -----------------------------
' conrols a camera (or potentially any entity) via keyboard
' arrows UP/DOWN/LEFT/RIGHT and keys W/A/S/D
Type TCameraController Extends IEntityAnimator
	Field cx#=0
	Field cy#=0
	Field cz#=0
	Field pitch#=0
	Field yaw#=0
	Field roll#=0
		
	Method AnimateEntity(entity:TEntity,timeMS:Int)
		' control camera	
		If KeyDown(KEY_UP) Then cz#=cz#+1.0
		If KeyDown(KEY_LEFT) Then cx#=cx#-1.0
		If KeyDown(KEY_RIGHT) Then cx#=cx#+1.0
		If KeyDown(KEY_DOWN) Then cz#=cz#-1.0
		
		If KeyDown(KEY_W) Then pitch#=pitch#-1.0
		If KeyDown(KEY_A) Then yaw#=yaw#+1.0
		If KeyDown(KEY_S) Then pitch#=pitch#+1.0
		If KeyDown(KEY_D) Then yaw#=yaw#-1.0
	
		entity.MoveEntity(cx#*0.5,cy#*0.5,cz#*0.5)
		entity.RotateEntity(pitch#,yaw#,roll#)
		cx#=0
		cy#=0
		cz#=0
	EndMethod	
	
	Function EntityAddAnimator(entity:TEntity,order:Int=0)		
		Local anim:TCameraController=TCameraController.Create(entity)
		' set the order so the animator update is called before the update to the entity
		EntityOrder(anim,(ORDER_BASE-order)) 
	EndFunction
	
	Function create:TCameraController(parent_ent:TEntity)
		Local piv:TCameraController=New TCameraController
		piv.class$="TCameraController"
		
		piv.AddParent(parent_ent)
		piv.EntityListAdd(entity_list)
		' update matrix
		If piv.parent<>Null
			piv.mat.Overwrite(piv.parent.mat)
			piv.UpdateMat()
		Else
			piv.UpdateMat(True)
		EndIf
		Return piv
	EndFunction	
EndType
Type TSimpleRotateAnimator Extends IEntityAnimator
	Field rate:Float
	Method AnimateEntity(entity:TEntity,timeMS:Int)
		entity.TurnEntity(0,rate,0)
	EndMethod
	
	Function EntityAddAnimator(entity:TEntity,rate:Float,order:Int=0)		
		Local anim:TSimpleRotateAnimator=TSimpleRotateAnimator.Create(entity)
		anim.rate=rate
		' set the order so the animator update is called before the update to the entity
		EntityOrder(anim,(ORDER_BASE-order)) 
	EndFunction
	
	Function create:TSimpleRotateAnimator(parent_ent:TEntity)
		Local piv:TSimpleRotateAnimator=New TSimpleRotateAnimator
		piv.class$="TSimpleRotateAnimator"
		
		piv.AddParent(parent_ent)
		piv.EntityListAdd(entity_list)
		' update matrix
		If piv.parent<>Null
			piv.mat.Overwrite(piv.parent.mat)
			piv.UpdateMat()
		Else
			piv.UpdateMat(True)
		EndIf
		Return piv
	EndFunction
EndType
' -----------------------------
' -----------------------------
in the animator.bmx code, there are two new types, one is a interface type meant to be extended.  ICollisionAdapter provides a means to store the collision data with the mesh.  due to it being an actual child of the mesh, when the parents matrix is updated so is the childs.  i use this to create an event.  the implementation uses this event to update the model collision transformation.
 
 the second type is the implementation of ICollisionAdapter i called TColDetCollisionAdapter.  it acutally implements the creation of the collision data, the updating of the collision matrix, and the checking for a collision.
 
 NOTE: be sure to run this in debug mode.  2 reasons, first, for some reason you will get an unhandle mem error at the first collision.  im not sure why but im waiting till the next version of MiniB3D to check it out.  ive manually tested outside of MiniB3D and it seems to work fine in debug or runtime.  second, you will see the debug output when the collisions occur.  you will see the millisecs, followed by the names of the two entities that collided.
 
 this is very basic stuff but it does show a simple collision detection implementation.
 
 enjoy :)
 
 one more time, a big THANK YOU to simonh.  cant wait for v0.3!
 
 
 |