瀏覽代碼

Added initial assimp.mod

markcwm 8 年之前
父節點
當前提交
fc655f9cf7
共有 3 個文件被更改,包括 691 次插入0 次删除
  1. 66 0
      assimp.mod/assimp.bmx
  2. 49 0
      assimp.mod/doc/commands.html
  3. 576 0
      assimp.mod/types.bmx

+ 66 - 0
assimp.mod/assimp.bmx

@@ -0,0 +1,66 @@
+' Copyright (c) 2009-2011 Peter Scheutz
+' All rights reserved.
+'
+' Redistribution and use in source and binary forms, with or without
+' modification, are permitted provided that the following conditions are met:
+'   * Redistributions of source code must retain the above copyright
+'     notice, this list of conditions and the following disclaimer.
+'   * Redistributions in binary form must reproduce the above copyright
+'     notice, this list of conditions and the following disclaimer in the
+'     documentation and/or other materials provided with the distribution.
+'   * Neither the name of copyright holder nor the names of its contributors
+'     may be used to endorse or promote products derived from this software
+'     without specific prior written permission.
+'
+' THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
+' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+' IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+' ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+' LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+' CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+' SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+' INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+' CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+' ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+' THE POSSIBILITY OF SUCH DAMAGE.
+
+Strict
+
+Rem
+bbdoc: Assimp wrapper for Openb3d
+about: Assimp mesh loader and helper functions.
+End Rem
+Module Openb3dlibs.Assimp
+
+ModuleInfo "Version: 0.40"
+ModuleInfo "License: BSD-3-Clause License"
+ModuleInfo "Copyright: 2009-2011 Peter Scheutz"
+ModuleInfo "Authors: Peter Scheutz, Mark Mcvittie"
+ModuleInfo "Source: https://github.com/markcwm/openb3dlibs.mod"
+ModuleInfo "Original: https://github.com/Difference/blitzmax-assimp"
+
+Import Openb3d.B3dglgraphics
+Import Openb3dlibs.Assimplib
+
+Include "types.bmx"
+
+Rem
+bbdoc: Like <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadMesh">LoadMesh</a> but without a parent parameter.
+End Rem
+Function aiLoadMesh:TMesh( filename:String )
+	Return aiLoader.LoadMesh( filename )
+End Function
+
+Rem
+bbdoc: Like <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadMesh">FitMesh</a>.
+End Rem
+Function aiFitAnimMesh( m:TEntity, x#, y#, z#, w#, h#, d#, uniform:Int=False )
+	aiHelper.FitAnimMesh( m, x, y, z, w, h, d, uniform )
+End Function
+
+Rem
+bbdoc: Creates a list of valid files to load.
+EndRem
+Function aiEnumFiles( list:TList, dir:String, skipExt:TList )
+	aiHelper.EnumFiles( list, dir, skipExt )
+End Function

+ 49 - 0
assimp.mod/doc/commands.html

@@ -0,0 +1,49 @@
+<html><head><title>Assimp wrapper for Openb3d reference</title>
+<link rel=stylesheet Type=text/css href='../../../../doc/bmxstyle.css'>
+</head><body>
+<table width=100% cellspacing=0><tr align=center><td class=small>&nbsp;</td>
+<td class=small width=1%><b>Openb3dlibs.Assimp:</b></td>
+<td class=small width=1%><a href=#functions class=small>Functions</a></td>
+<td class=small width=1%><a href=#modinfo class=small>Modinfo</a></td>
+<td class=small width=1%><a href='../../../../mod/openb3dlibs.mod/assimp.mod/assimp.bmx' class=small>Source</a></td>
+<td class=small>&nbsp;</td></tr></table>
+<h1>Assimp wrapper for Openb3d</h1>
+Assimp mesh loader and helper functions.
+<h2><a name=functions></a>Functions Summary</h2><table class=doc width=100%>
+<tr><td class=docleft width=1%><a href=#aiEnumFiles>aiEnumFiles</a></td><td class=docright>
+Creates a list of valid files to load.
+</td></tr>
+<tr><td class=docleft width=1%><a href=#aiFitAnimMesh>aiFitAnimMesh</a></td><td class=docright>
+Like <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadMesh">FitMesh</a>.
+</td></tr>
+<tr><td class=docleft width=1%><a href=#aiLoadMesh>aiLoadMesh</a></td><td class=docright>
+Like <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadMesh">LoadMesh</a> but without a parent parameter.
+</td></tr>
+</table>
+<h2
+ id=functionsdet>Functions
+</h2>
+<table class=doc width=100% cellspacing=3 id=aiEnumFiles>
+<tr><td class=doctop colspan=2>Function aiEnumFiles( list:TList, dir:String, skipExt:TList )</td></tr>
+<tr><td class=docleft width=1%>Description</td><td class=docright>Creates a list of valid files to load.</td></tr>
+</table>
+<br>
+<table class=doc width=100% cellspacing=3 id=aiFitAnimMesh>
+<tr><td class=doctop colspan=2>Function aiFitAnimMesh( m:TEntity, x#, y#, z#, w#, h#, d#, uniform:Int=False )</td></tr>
+<tr><td class=docleft width=1%>Description</td><td class=docright>Like <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadMesh">FitMesh</a>.</td></tr>
+</table>
+<br>
+<table class=doc width=100% cellspacing=3 id=aiLoadMesh>
+<tr><td class=doctop colspan=2>Function aiLoadMesh:TMesh( filename:String )</td></tr>
+<tr><td class=docleft width=1%>Description</td><td class=docright>Like <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadMesh">LoadMesh</a> but without a parent parameter.</td></tr>
+</table>
+<br>
+<h2 id=modinfo>Module Information</h2>
+<table width=100%>
+<tr><th width=1%>Version</th><td>0.40</td></tr>
+<tr><th width=1%>License</th><td>BSD-3-Clause License</td></tr>
+<tr><th width=1%>Copyright</th><td>2009-2011 Peter Scheutz</td></tr>
+<tr><th width=1%>Authors</th><td>Peter Scheutz, Mark Mcvittie</td></tr>
+<tr><th width=1%>Source</th><td>https://github.com/markcwm/openb3dlibs.mod</td></tr>
+<tr><th width=1%>Original</th><td>https://github.com/Difference/blitzmax-assimp</td></tr>
+</body></html>

+ 576 - 0
assimp.mod/types.bmx

@@ -0,0 +1,576 @@
+' types.bmx
+
+' Mesh bounds values, used in FitAnimMesh()
+Type aiMinMax3D
+
+	Field maxx#,maxy#,maxz#
+	Field minx#,miny#,minz#
+	
+End Type
+
+Rem
+ Contains functions which apply to all children of an entity:
+ CountTrianglesAll:Int( mesh:TMesh )
+ RotateEntityAxisAll ent:TEntity, axis:Int
+ UpdateNormalsAll ent:TEntity
+ FlipMeshAll ent:TEntity
+ ScaleMeshAxisAll ent:TEntity, axis:Int
+EndRem
+Type aiLoader
+
+	Global meshflags:Int=0
+	
+	Function LoadMesh:TMesh( filename:String )
+	
+		Local scene:aiScene = New aiScene
+		
+		'aiSetImportPropertyInteger(aipropertystore?, AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT )
+		
+		Local flags:Int
+		If meshflags=0
+			flags = ..
+			aiProcess_Triangulate | ..
+			aiProcess_GenSmoothNormals | ..
+			aiProcess_SortByPType | ..
+			aiProcess_PreTransformVertices | ..
+			aiProcess_FlipUVs | ..
+			aiProcess_JoinIdenticalVertices
+		ElseIf meshflags=1
+			flags = ..
+			aiProcess_Triangulate | ..
+			aiProcess_GenNormals | ..
+			aiProcess_SortByPType | ..
+			aiProcess_CalcTangentSpace | ..
+			aiProcess_FindDegenerates | ..
+			aiProcess_FindInvalidData | ..
+			aiProcess_GenUVCoords | ..
+			aiProcess_TransformUVCoords | ..
+			aiProcess_FlipUVs | ..
+			aiProcess_PreTransformVertices
+		EndIf
+	'	aiProcess_SplitLargeMeshes | ..
+	'	aiProcess_ValidateDataStructure | ..
+	'	aiProcess_ImproveCacheLocality | ..
+	'	aiProcess_RemoveRedundantMaterials | ..	
+	'	aiProcess_ConvertToLeftHanded | ..	
+		
+		If scene.ImportFile(filename, flags)
+		
+			' Make brushes
+			
+			Local brushes:TBrush[scene.NumMaterials]
+			Local i:Int
+			
+			For Local mat:aiMaterial = EachIn scene.Materials
+'Rem
+				DebugLog " "
+				DebugLog " ----    Material Name " + mat.GetMaterialName()
+				DebugLog " ----    mat.IsTwoSided() " + mat.IsTwoSided()
+				DebugLog " ----    mat.GetShininess() " + mat.GetShininess()
+				DebugLog " ----    mat.GetAlpha() " + mat.GetAlpha()
+'EndRem
+'Rem
+				Local names:String[] = mat.GetPropertyNames()
+				
+				For Local s:String = EachIn names
+					DebugLog "Property: *" + s + "*"
+					
+					'DebugLog "matbase " + mat.GetFloatValue(s)
+					
+					Select s
+						Case AI_MATKEY_TEXTURE_BASE
+							DebugLog "matbase " +  mat.GetMaterialString(s)
+					End Select
+					
+				Next
+'EndRem
+				Local DiffuseColors:Float[] = mat.GetMaterialColor(AI_MATKEY_COLOR_DIFFUSE)	
+				
+				brushes[i] = CreateBrush(mat.GetDiffuseRed()*255,mat.GetDiffuseGreen()*255,mat.GetDiffuseBlue()*255)
+				
+				' seems alpha comes in different places denpending om model format.
+				' seems wavefront obj alpha doen't load
+				'BrushAlpha brushes[i],mat.GetAlpha()' * mat.GetDiffuseAlpha() (might be 0 so not good)
+				
+				BrushShininess brushes[i],mat.GetShininess()
+				
+				If mat.IsTwoSided()
+					'BrushFX brushes[i] ,16
+				EndIf
+				
+				Local texFilename:String = mat.GetMaterialTexture()
+				
+				DebugLog "TEXTURE filename: " + texFilename
+				
+				If Len(texFilename)
+				
+					' remove currentdir prefix, but leave relative subfolder path intact
+					If  texFilename[..2] = ".\" Or texFilename[..2] = "./"
+						texFilename = texFilename [2..]
+					EndIf
+					
+					'assume the texture names are stored relative to the file
+					texFilename  = ExtractDir(filename) + "/" + texFilename
+					
+					If Not FileType(texFilename  )
+						texFilename   = ExtractDir(filename) + "/" + StripDir(texFilename)
+					EndIf
+					
+					DebugLog texFilename
+					
+					If FileType(texFilename  )
+						'DebugStop
+						Local tex:TTexture=LoadTexture(texFilename)
+						
+						If tex
+							BrushTexture brushes[i],tex	
+						EndIf
+						
+					EndIf
+					
+				EndIf
+				
+				i:+1
+			Next
+			
+			' Make mesh - was ProccessAiNodeAndChildren()
+			
+			Local mesh:TMesh = CreateMesh()
+			
+			DebugLog "scene.numMeshes:  "  + scene.numMeshes
+			
+			For Local m:aiMesh = EachIn scene.meshes
+			
+				Local surf:TSurface = CreateSurface(mesh,brushes[m.MaterialIndex])
+				
+				' vertices, normals and texturecoords - was MakeAiMesh()
+				
+				For i = 0 To m.NumVertices - 1
+				
+					'DebugLog  m.VertexX(i) + " , "  + m.VertexY(i) + " , "  + m.VertexZ(i)
+					
+					Local index:Int
+					index = AddVertex(surf,m.VertexX(i) ,m.VertexY(i),m.VertexZ(i))
+					
+					If m.HasNormals()
+						VertexNormal(surf,index,m.VertexNX(i) ,m.VertexNY(i),m.VertexNZ(i))
+					EndIf
+					
+					If m.HasTextureCoords(0)
+						VertexTexCoords(surf,index,m.VertexU(i) ,m.VertexV(i),m.VertexW(i))
+					EndIf
+					
+					If m.HasTextureCoords(1)
+						VertexTexCoords(surf,index,m.VertexU(i,1) ,m.VertexV(i,1),m.VertexW(i,1))
+					EndIf
+					
+				Next
+				
+				For i = 0 To m.NumFaces - 1
+				
+					'DebugLog  m.TriangleVertex(i,0) + " , "  + m.TriangleVertex(i,1) + " , "  + m.TriangleVertex(i,2)
+					
+					' this check is only in because assimp seems to be returning out of range indexes
+					' on rare occasions with aiProcess_PreTransformVertices on.
+					Local validIndex:Int = True
+					
+					' added 3.1.1: fix for MAV when garbage index values < zero
+					If m.TriangleVertex(i,0) < 0 Then validIndex = False
+					If m.TriangleVertex(i,1) < 0 Then validIndex = False
+					If m.TriangleVertex(i,2) < 0 Then validIndex = False
+					
+					If m.TriangleVertex(i,0) >=m.NumVertices Then validIndex = False
+					If m.TriangleVertex(i,1) >=m.NumVertices Then validIndex = False
+					If m.TriangleVertex(i,2) >=m.NumVertices Then validIndex = False				
+					
+					If validIndex
+						AddTriangle(surf, m.TriangleVertex(i,0) ,  m.TriangleVertex(i,1) , m.TriangleVertex(i,2))
+					Else
+						DebugLog "TriangleVertex index was out of range for triangle nr. : " + i
+						DebugLog "indexes: " + m.TriangleVertex(i,0) + " , "  + m.TriangleVertex(i,1) + " , "  + m.TriangleVertex(i,2)
+					EndIf
+					
+				Next
+				
+			Next
+			
+			Return mesh	
+			
+		Else
+		
+			DebugLog "nothing imported"
+			
+		EndIf
+		
+		Scene.ReleaseImport()
+		
+	End Function
+		
+End Type
+
+' helper functions
+Type aiHelper
+
+	Global mm:aiMinMax3D=New aiMinMax3D
+	
+	' Non-essential helper functions
+	
+	Function CountTrianglesAll:Int( ent:TEntity )
+	
+		If ent = Null Then Return 0
+		Local all%
+		
+		For Local id% = 1 To CountSurfaces(TMesh(ent))
+			Local surf:TSurface=GetSurface( TMesh(ent),id )
+			Local nt% = CountTriangles(surf)
+			all:+nt
+		Next
+		
+		Return all
+		
+	End Function
+	
+	' renamed from FlipRot (applied to all children of an entity)
+	Function RotateEntityAxisAll( ent:TEntity, axis:Int )
+	
+		If ent = Null Then Return
+		Local cc:Int = CountChildren(ent)
+		
+		If cc
+			For Local id:Int = 1 To cc
+				RotateEntityAxisAll( GetChild(ent,id),axis )
+			Next	
+		EndIf
+		
+		Local rotX:Float = EntityPitch(ent)
+		Local rotY:Float = EntityYaw(ent)
+		Local rotZ:Float = EntityRoll(ent)
+		
+		Select axis
+			Case 1
+				rotX = -rotX
+			Case 2
+				rotY = -rotY		
+			Case 3
+				rotZ = -rotZ
+		End Select
+		
+		RotateEntity( ent,rotX,rotY,rotZ )
+		
+	End Function
+	
+	' dirty x model fixer - renamed from UpdateEntityNormals (applied to all children of an entity)
+	Function UpdateNormalsAll( ent:TEntity )
+	
+		If ent = Null Then Return
+		Local childcount:Int = CountChildren(ent)
+		
+		If childcount
+			For Local id:Int = 1 To childcount
+				UpdateNormalsAll( GetChild(ent,id) )
+			Next
+		EndIf
+		
+		If EntityClass(ent) = "Mesh"
+			UpdateNormals( TMesh(ent) )
+		EndIf
+		
+	End Function
+	
+	' renamed from FlipEntity (applied to all children of an entity)
+	Function FlipMeshAll( ent:TEntity )
+	
+		If ent = Null Then Return
+		Local childcount:Int = CountChildren(ent)
+		
+		If childcount
+			For Local id:Int = 1 To childcount
+				FlipMeshAll( GetChild(ent,id) )
+			Next
+		EndIf
+		
+		If EntityClass(ent) = "Mesh"
+			FlipMesh( TMesh(ent) )
+		EndIf
+		
+	End Function
+	
+	' dirty x model fixer - renamed from ScaleFlipEntity (applied to all children of an entity)
+	Function ScaleMeshAxisAll( ent:TEntity, axis:Int )
+	
+		If ent = Null Then Return
+		Local childcount:Int = CountChildren(ent)
+		
+		If childcount
+			For Local id:Int = 1 To childcount
+				ScaleMeshAxisAll( GetChild(ent,id),axis )
+			Next
+		EndIf
+		
+		Local scaleX:Float = 1
+		Local scaleY:Float = 1
+		Local scaleZ:Float = 1
+		
+		Select axis
+			Case 1
+				scaleX = -scaleX
+			Case 2
+				scaleY = -scaleY		
+			Case 3
+				scaleZ = -scaleZ
+		End Select
+		
+		If EntityClass(ent) = "Mesh"
+			ScaleMesh( TMesh(ent),scaleX,scaleY,scaleZ )
+		EndIf
+		
+	End Function
+	
+	' uses doFitAnimMesh() and getAnimMeshMinMax()
+	Function FitAnimMesh( m:TEntity, x#, y#, z#, w#, h#, d#, uniform:Int=False )
+	
+		Local scalefactor#
+		Local xoff#,yoff#,zoff#
+		Local gFactor#=100000.0
+		
+		mm.maxx=-100000
+		mm.maxy=-100000
+		mm.maxz=-100000
+		
+		mm.minx=100000
+		mm.miny=100000
+		mm.minz=100000
+		
+		getAnimMeshMinMax( m,mm )
+		
+		'DebugLog "getAnimMeshMinMax " + String(mm.minx).ToInt() + ", " + String(mm.miny).ToInt() + ", " + String(mm.minz).ToInt() + ", " +..
+		'String(mm.maxx).ToInt() + ", " + String(mm.Maxy).ToInt() + ", " + String(mm.maxz).ToInt()	
+		
+		Local xspan#=(mm.maxx-mm.minx)
+		Local yspan#=(mm.maxy-mm.miny)
+		Local zspan#=(mm.maxz-mm.minz)
+		
+		Local xscale#=w/xspan
+		Local yscale#=h/yspan
+		Local zscale#=d/zspan
+		
+		'DebugLog "Scales: " + xscale + " , " +  yscale + " , " + zscale + " , " 
+		
+		If uniform
+		
+			If xscale<yscale
+				yscale=xscale
+			Else
+				xscale=yscale
+			EndIf
+			
+			If zscale<xscale
+				xscale=zscale
+				yscale=zscale			
+			Else
+				zscale=xscale
+			EndIf
+			
+		EndIf	
+		
+		'DebugLog "Scales: " + String(xscale).ToInt() + " , " +  String(yscale).ToInt() + " , " + String(zscale).ToInt() + " , " 
+		
+		xoff# = -mm.minx * xscale-(xspan/2.0) * xscale+x+w/2.0
+		yoff# = -mm.miny * yscale-(yspan/2.0) * yscale+y+h/2.0
+		zoff# = -mm.minz * zscale-(zspan/2.0) * zscale+z+d/2.0
+		
+		doFitAnimMesh( m,xoff,yoff,zoff,xscale,yscale,zscale )	
+'		Delete mm
+		
+	End Function
+	
+	' internal functions for FitAnimMesh
+	
+	' used in FitAnimMesh()
+	Function doFitAnimMesh( m:TEntity, xoff#, yoff#, zoff#, xscale#, yscale#, zscale# )
+	
+		Local c:Int
+		Local childcount:Int=CountChildren(m)
+		
+		If childcount
+		
+			For c=1 To childcount
+				'myFitEntity( m,xoff#,yoff#,zoff#,xscale#,yscale#,zscale# )
+				doFitAnimMesh( GetChild(m,c),xoff#,yoff#,zoff#,xscale#,yscale#,zscale# )
+			Next
+			
+		'Else
+		EndIf
+		
+		myFitEntity( m,xoff#,yoff#,zoff#,xscale#,yscale#,zscale# )
+		
+	End Function
+	
+Rem
+	Function doFitAnimMeshOLD( m:TEntity, xoff#, yoff#, zoff#, xscale#, yscale#, zscale# )
+	
+		Local c:Int
+		Local childcount:Int=CountChildren(m)
+		
+		If childcount
+		
+			For c=1 To childcount
+				myFitEntity( m,xoff#,yoff#,zoff#,xscale#,yscale#,zscale# )
+				doFitAnimMesh( GetChild(m,c),xoff#,yoff#,zoff#,xscale#,yscale#,zscale# )
+			Next
+			
+		Else
+		
+			myFitEntity( m,xoff#,yoff#,zoff#,xscale#,yscale#,zscale# )
+		
+		EndIf
+		
+	End Function
+EndRem
+	
+	' used in doFitAnimMesh()
+	Function myFitEntity( e:TEntity, xoff#, yoff#, zoff#, xscale#, yscale#, zscale# )
+	
+		Local x#,y#,z#
+		Local x2#,y2#,z2#
+		Local txoff#,tyoff#,tzoff#
+		
+		TFormPoint( 0,0,0,e,Null )
+		
+		x2=TFormedX()
+		y2=TFormedY()
+		z2=TFormedZ()
+		
+		TFormPoint( x2+xoff,y2+yoff,z2+zoff,Null,e )
+		
+		txoff=TFormedX() 
+		tyoff=TFormedY()
+		tzoff=TFormedZ()
+		
+		Local m:TMesh = TMesh(e)
+		
+		If m 'only if it's a mesh
+		
+			For Local sc:Int=1 To CountSurfaces(m)
+				Local s:TSurface=GetSurface(m,sc)	
+				
+				For Local vc:Int=0 To CountVertices(s)-1
+					x=VertexX(s,vc)
+					y=VertexY(s,vc)
+					z=VertexZ(s,vc)
+					
+					VertexCoords s,vc,x*xscale+txoff,y*yscale+tyoff,z*zscale+tzoff
+				Next
+				
+			Next
+			
+		EndIf
+		
+		PositionEntity( e,EntityX(e)*xscale,EntityY(e)*yscale,EntityZ(e)*zscale )
+		
+	End Function
+	
+	' used in FitAnimMesh()
+	Function getAnimMeshMinMax#( m:TEntity, mm:aiMinMax3D )
+	
+		Local c:Int
+		Local wfac#,hfac#,dfac#
+		'Local tfactor
+		Local cc:Int=CountChildren(m)
+		
+		If EntityClass(m) = "Mesh"
+		
+			'If m.class = "Mesh" 
+			mm = getEntityMinMax( TMesh(m),mm )
+			'Else
+			'	DebugLog "Class -- " + m.class
+			'Endif
+			
+		EndIf
+		
+		If cc
+			For c=1 To cc
+				getAnimMeshMinMax( GetChild(m,c),mm )
+			Next
+	'	Else
+		EndIf
+		
+	End Function
+
+	' used in getAnimMeshMinMax()
+	Function getEntityMinMax:aiMinMax3D( m:TMesh, mm:aiMinMax3D )
+	
+		Local x#,y#,z#
+		Local sc:Int
+		Local vc:Int
+		Local s:TSurface	
+		
+		For sc=1 To CountSurfaces(m)
+			s=GetSurface(m,sc)	
+			
+			For vc=0 To CountVertices(s)-1
+				TFormPoint(VertexX(s,vc),VertexY(s,vc),VertexZ(s,vc),m,Null)
+				
+				x=TFormedX()
+				y=TFormedY()
+				z=TFormedZ()
+				
+				If x<mm.minx Then mm.minx=x
+				If y<mm.miny Then mm.miny=y
+				If z<mm.minz Then mm.minz=z				
+				
+				If x>mm.maxx Then mm.maxx=x
+				If y>mm.maxy Then mm.maxy=y
+				If z>mm.maxz Then mm.maxz=z
+			Next
+			
+		Next
+		
+		Return mm
+		
+	End Function
+	
+	' Creates a list of valid files to load
+	Function EnumFiles( list:TList, dir:String, skipExt:TList )
+	
+		Local folder:Byte Ptr=ReadDir(dir)
+		Local file:String
+		
+		Repeat
+			file=NextFile(folder)
+			
+			If (file <> ".") And (file <> "..") And (file)
+			
+				Local fullPath:String=RealPath(dir+"/"+file)
+				
+				If FileType(fullPath)=FILETYPE_DIR
+				
+					'DebugLog file
+					'If(dir[0]) <> "."
+						EnumFiles( list,fullPath,skipExt )
+					'EndIf
+					
+				Else
+				
+					DebugLog "fullpath: " + fullPath
+					
+					If aiIsExtensionSupported( Lower(ExtractExt(fullPath)) )
+					
+						'DebugStop
+						If Not skipExt.Contains( Lower(ExtractExt(fullPath)) ) ' Filter out nff for now
+							' assimp author is looking into a fix
+							list.AddLast(fullPath)
+						EndIf
+						
+					EndIf
+					
+				EndIf
+				
+			EndIf
+			
+		Until file=Null
+		CloseDir folder
+		
+	End Function
+	
+End Type