type Vec2Integer
   x as integer
   y as integer
endtype
type Vec2Float
   x as float
   y as float
endtype
type Vec3Integer
   x as integer
   y as integer
   z as integer
endtype
type Vec3Float
   x as float
   y as float
   z as float
endtype
type Vec4Integer
   x as integer
   y as integer
   z as integer
   w as integer
endtype
type Vec4Float
   x as float
   y as float
   z as float
   w as float
endtype

`--------------
` Free Up
`--------------
function FreeUpImage(iFreeup as integer)
   repeat
      inc iFreeup
   until Image exist(iFreeup)=0
endfunction iFreeup
function FreeUpObject(iFreeup as integer)
   repeat
      inc iFreeup
   until object exist(iFreeup)=0
endfunction iFreeup
function FreeUpSound(iFreeup as integer)
   repeat
      inc iFreeup
   until Sound exist(iFreeup)=0
endfunction iFreeup
function FreeUpEffect(iFreeup as integer)
   repeat
      inc iFreeup
   until Effect exist(iFreeup)=0
endfunction iFreeup
function FreeUpCamera()
   tFreeup=0
   repeat
      inc tFreeup
   until camera exist(tFreeup)=0
endfunction tFreeup
function FreeUpMesh()
   tFreeup=35000
   repeat
      inc tFreeup
   until mesh exist(tFreeup)=0
endfunction tFreeup
function FreeUpFile()
   tFreeup=0
   repeat
      inc tFreeup
   until file open(tFreeup)=0
endfunction tFreeup
function FreeUpMemblock()
   tFreeup=0
   repeat
      inc tFreeup
   until Memblock exist(tFreeup)=0
endfunction tFreeup
function FreeUpDll()
   tFreeup=0
   repeat
      inc tFreeup
   until dll exist(tFreeup)=0
endfunction tFreeup

`--------------
` Peek
`--------------
function PeekByte1(iPTR as dword)
   local tReturn as byte
   iPTR= *iPTR
   tReturn=iPTR && 0xff
endfunction tReturn
function PeekByte2(iPTR as dword)
   local tReturn as byte
   iPTR= *iPTR
   tReturn=(iPTR >> 8) && 0xff
endfunction tReturn
function PeekByte3(iPTR as dword)
   local tReturn as byte
   iPTR= *iPTR
   tReturn=(iPTR >> 16) && 0xff
endfunction tReturn
function PeekByte4(iPTR as dword)
   local tReturn as byte
   iPTR= *iPTR
   tReturn=(iPTR >> 24) && 0xff
endfunction tReturn
function PeekWord1(iPTR as dword)
   local tReturn as word
   iPTR= *iPTR
   tReturn=iPTR && 0xffff
endfunction tReturn
function PeekWord2(iPTR as dword)
   local tReturn as word
   iPTR= *iPTR
   tReturn=(iPTR >> 16) && 0xffff
endfunction tReturn
function PeekDword(iPTR as dword)
   local tReturn as dword
   tReturn= *iPTR
endfunction tReturn
function PeekInteger(iPTR as dword)
   tReturn= *iPTR
endfunction tReturn
function PeekFloat(iPTR as DWORD)
   tResult= *iPTR
   tExponent#=((tResult >> 23) and %00000000000000000000000011111111)-127
   tMantissa#=((tResult and %00000000011111111111111111111111)/8388608.0)+1.0
   if tResult and %10000000000000000000000000000000 then tSign=-1.0 else tSign=1.0
   tReturn#=tSign*(2^tExponent#)*tMantissa#
endfunction tReturn#

`--------------
` Poke
`--------------
function PokeByte1(iPTR as dword,iValue as byte)
   local tDword as dword
   tDword= *iPTR
   tDword=(tDword && 0xffffff00) || (iValue && 0xff)
   *iPTR=tDword
endfunction
function PokeByte2(iPTR as dword,iValue as byte)
   local tDword as dword
   tDword= *iPTR
   tDword=(tDword && 0xffff00ff) || ((iValue && 0xff) << 8)
   *iPTR=tDword
endfunction
function PokeByte3(iPTR as dword,iValue as byte)
   local tDword as dword
   tDword= *iPTR
   tDword=(tDword && 0xff00ffff) || ((iValue && 0xff) << 16)
   *iPTR=tDword
endfunction
function PokeByte4(iPTR as dword,iValue as byte)
   local tDword as dword
   tDword= *iPTR
   tDword=(tDword && 0x00ffffff) || ((iValue && 0xff) << 24)
   *iPTR=tDword
endfunction
function PokeWord1(iPTR as dword,iValue as word)
   local tDword as dword
   tDword= *iPTR
   tDword=(tDword && 0xffff0000) || (iValue && 0xffff)
   *iPTR=tDword
endfunction
function PokeWord2(iPTR as dword,iValue as word)
   local tDword as dword
   tDword= *iPTR
   tDword=(tDword && 0x0000ffff) || ((iValue && 0xffff) << 16)
   *iPTR=tDword
endfunction
function PokeDword(iPTR as dword,iValue as dword)
   *iPTR=iValue
endfunction
function PokeInteger(iPTR as dword,iValue as integer)
   *iPTR=iValue
endfunction
function PokeFloat(iPTR as dword,iValue as float)
   *iPTR=iValue
endfunction

`--------------
` Common Globals
`--------------
function InitCommonGlobals()
   global MinVec as Vec3Float
   global MaxVec as Vec3Float
   global MinMaxPos as Vec3Float
   global MinMaxSize as Vec3Float
   global ShaderEffectDefineCount as integer
   global dim Vector4Float(268) as Vec4Float
   global dim Vector4Integer(268) as Vec4Integer
   global dim Matrix4Float(4,4) as Vec4Float
   global dim Matrix4X1Float(16) as float
   global dim Matrix4X2Float(16) as float
   global dim Matrix4X3Float(16) as float
   global dim Vector2(32) as integer
   global dim Vector3(32) as integer
   global dim Vector4(32) as integer
   global dim Matrix(32) as integer
   global dim ViewProjectVec(15) as float
   global dim ViewProjectFrustumVec(32,5,3) as float
   global dim AABBox(7) as Vec3Float
   global dim ShaderEffectDefineStr(64) as string
   global dim ShaderEffectDefineVal(64) as float
   ShaderEffectDefineCount=-1
   tFreeUp3DMaths=100
   for v=1 to 32
      Vector2(v)=tFreeUp3DMaths:null=make vector2(tFreeUp3DMaths):inc tFreeUp3DMaths
      Vector3(v)=tFreeUp3DMaths:null=make vector3(tFreeUp3DMaths):inc tFreeUp3DMaths
      Vector4(v)=tFreeUp3DMaths:null=make vector4(tFreeUp3DMaths):inc tFreeUp3DMaths
      Matrix(v)=tFreeUp3DMaths:null=make matrix4(tFreeUp3DMaths):inc tFreeUp3DMaths
   next v
   for b=0 to 7
      AABBox(b).x=0.5:AABBox(b).y=0.5:AABBox(b).z=0.5
   next b
   AABBox(1).x=-0.5:AABBox(2).y=-0.5:AABBox(3).x=-0.5:AABBox(3).y=-0.5
   AABBox(4).z=-0.5:AABBox(5).x=-0.5:AABBox(5).z=-0.5:AABBox(6).y=-0.5
   AABBox(6).z=-0.5:AABBox(7).x=-0.5:AABBox(7).y=-0.5:AABBox(7).z=-0.5
endfunction

`--------------
` Clamp 
`--------------
function ClampA(iValue as float,iMin as float,iMax as float)
   rVal#=iValue
   if rVal#<iMin then rVal#=iMin
   if rVal#>iMax then rVal#=iMax
endfunction rVal#

`--------------
` Linear Interpolation
`--------------
function LerpA(iA as float,iB as float,iValue as float)
   rVal#=iA+iValue*(iB-iA)
endfunction rVal#

`--------------
` Min Max Set
`--------------
function MinMaxVecReset()
   MinVec.x=9999999999:MinVec.y=9999999999:MinVec.z=9999999999
   MaxVec.x=-9999999999:MaxVec.y=-9999999999:MaxVec.z=-9999999999
endfunction

`--------------
` Min Max Get
`--------------
function MinMaxVec(iX as float,iY as float,iZ as float)
   if iX<MinVec.x then MinVec.x=iX
   if iX>MaxVec.x then MaxVec.x=iX
   if iY<MinVec.y then MinVec.y=iY
   if iY>MaxVec.y then MaxVec.y=iY
   if iZ<MinVec.z then MinVec.z=iZ
   if iZ>MaxVec.z then MaxVec.z=iZ
endfunction

`--------------
` Min Max Vec
`--------------
function MinMaxPositionSize()
   MinMaxSize.x=(MaxVec.x-MinVec.x)
   MinMaxSize.y=(MaxVec.y-MinVec.y)
   MinMaxSize.z=(MaxVec.z-MinVec.z)
   MinMaxPos.x=MinVec.x+(MinMaxSize.x/2)
   MinMaxPos.y=MinVec.y+(MinMaxSize.y/2)
   MinMaxPos.z=MinVec.z+(MinMaxSize.z/2)
endfunction

`--------------
` Box Collision
`--------------
function BoxCollision(iX as float,iY as float,iZ as float,iPx as float,iPy as float,iPz as float,iSx as float,iSy as float,iSz as float)
   if iX<(iPx+(iSx*0.5)) and iX>(iPx-(iSx*0.5))
      if iY<(iPy+(iSy*0.5)) and iY>(iPy-(iSy*0.5))
         if iZ<(iPz+(iSz*0.5)) and iZ>(iPz-(iSz*0.5)) then exitfunction 1
      endif
   endif
endfunction 0

`--------------
` In Normal
`--------------
function InNormal(iFromX as float,iFromY as float,iFromZ as float,iX as float,iY as float,iZ as float,iNorX as float,iNorY as float,iNorZ as float)
   iFromX=iFromX-iX : iFromY=iFromY-iY : iFromZ=iFromZ-iZ
   tReturn#=iNorX*iFromX+iNorY*iFromY+iNorZ*iFromZ
endfunction tReturn#

`--------------
` Plane Ray Cast
`--------------
function RayPlaneCast(iFromX as float,iFromY as float,iFromZ as float,iToX as float,iToY as float,iToZ as float,iX as float,iY as float,iZ as float,iNorX as float,iNorY as float,iNorZ as float)
   iFromX=iFromX-iX : iFromY=iFromY-iY : iFromZ=iFromZ-iZ
   iToX=iToX-iX : iToY=iToY-iY : iToZ=iToZ-iZ
   Vector4Float(0).w=iNorX*iFromX+iNorY*iFromY+iNorZ*iFromZ
   Vector4Float(0).w=-Vector4Float(0).w/(iNorX*(iToX-iFromX)+iNorY*(iToY-iFromY)+iNorZ*(iToZ-iFromZ))
   Vector4Float(0).x=iX+(iFromX+Vector4Float(0).w*(iToX-iFromX))
   Vector4Float(0).y=iY+(iFromY+Vector4Float(0).w*(iToY-iFromY))
   Vector4Float(0).z=iZ+(iFromZ+Vector4Float(0).w*(iToZ-iFromZ))
   tReturn#=iNorX*iToX+iNorY*iToY+iNorZ*iToZ
endfunction tReturn#

`--------------
` Ray Box Cast
`--------------
function RayBoxCast(iFromX as float,iFromY as float,iFromZ as float,iToX as float,iToY as float,iToZ as float,iPx as float,iPy as float,iPz as float,iSx as float,iSy as float,iSz as float)
   if BoxCollision(iFromX,iFromY,iFromZ,iPx,iPy,iPz,iSx,iSy,iSz)=1
      Vector4Float(0).x=iFromX : Vector4Float(0).y=iFromY : Vector4Float(0).z=iFromZ
      Vector4Float(1).x=0 : Vector4Float(1).y=1 : Vector4Float(1).z=0
      exitfunction 1
   endif
   tMinX#=iPx-iSx*0.5 : tMinY#=iPy-iSy*0.5 : tMinZ#=iPz-iSz*0.5
   tMaxX#=iPx+iSx*0.5 : tMaxY#=iPy+iSy*0.5 : tMaxZ#=iPz+iSz*0.5
   tDist1#=RayPlaneCast(iFromX,iFromY,iFromZ,iToX,iToY,iToZ,tMinX#,0,0,-1,0,0)
   Vector4Float(1).x=Vector4Float(0).x : Vector4Float(1).y=Vector4Float(0).y : Vector4Float(1).z=Vector4Float(0).z : Vector4Float(1).w=Vector4Float(0).w
   tDist2#=RayPlaneCast(iFromX,iFromY,iFromZ,iToX,iToY,iToZ,tMaxX#,0,0,1,0,0)
   if tDist1#<tDist2#
      if Vector4Float(1).y>tMinY# and Vector4Float(1).y<tMaxY# and Vector4Float(1).w>0.0
         if Vector4Float(1).z>tMinZ# and Vector4Float(1).z<tMaxZ# and Vector4Float(1).w<1.0
            Vector4Float(0).x=Vector4Float(1).x : Vector4Float(0).y=Vector4Float(1).y : Vector4Float(0).z=Vector4Float(1).z
            Vector4Float(1).x=-1 : Vector4Float(1).y=0 : Vector4Float(1).z=0
            exitfunction 1
         endif
      endif
   else
      if Vector4Float(0).y>tMinY# and Vector4Float(0).y<tMaxY# and Vector4Float(0).w>0.0
         if Vector4Float(0).z>tMinZ# and Vector4Float(0).z<tMaxZ# and Vector4Float(0).w<1.0
            Vector4Float(1).x=1 : Vector4Float(1).y=0 : Vector4Float(1).z=0
            exitfunction 1
         endif
      endif
   endif
   tDist1#=RayPlaneCast(iFromX,iFromY,iFromZ,iToX,iToY,iToZ,0,tMinY#,0,0,-1,0)
   Vector4Float(1).x=Vector4Float(0).x : Vector4Float(1).y=Vector4Float(0).y : Vector4Float(1).z=Vector4Float(0).z : Vector4Float(1).w=Vector4Float(0).w
   tDist2#=RayPlaneCast(iFromX,iFromY,iFromZ,iToX,iToY,iToZ,0,tMaxY#,0,0,1,0)
   if tDist1#<tDist2#
      if Vector4Float(1).x>tMinX# and Vector4Float(1).x<tMaxX# and Vector4Float(1).w>0.0
         if Vector4Float(1).z>tMinZ# and Vector4Float(1).z<tMaxZ# and Vector4Float(1).w<1.0 
            Vector4Float(0).x=Vector4Float(1).x : Vector4Float(0).y=Vector4Float(1).y : Vector4Float(0).z=Vector4Float(1).z
            Vector4Float(1).x=0 : Vector4Float(1).y=-1 : Vector4Float(1).z=0
            exitfunction 1
         endif
      endif
   else
      if Vector4Float(0).x>tMinX# and Vector4Float(0).x<tMaxX# and Vector4Float(0).w>0.0
         if Vector4Float(0).z>tMinZ# and Vector4Float(0).z<tMaxZ# and Vector4Float(0).w<1.0
            Vector4Float(1).x=0 : Vector4Float(1).y=1 : Vector4Float(1).z=0
            exitfunction 1
         endif
      endif
   endif
   tDist1#=RayPlaneCast(iFromX,iFromY,iFromZ,iToX,iToY,iToZ,0,0,tMinZ#,0,0,-1)
   Vector4Float(1).x=Vector4Float(0).x : Vector4Float(1).y=Vector4Float(0).y : Vector4Float(1).z=Vector4Float(0).z : Vector4Float(1).w=Vector4Float(0).w
   tDist2#=RayPlaneCast(iFromX,iFromY,iFromZ,iToX,iToY,iToZ,0,0,tMaxZ#,0,0,1)
   if tDist1#<tDist2#
      if Vector4Float(1).x>tMinX# and Vector4Float(1).x<tMaxX# and Vector4Float(1).w>0.0
         if Vector4Float(1).y>tMinY# and Vector4Float(1).y<tMaxY# and Vector4Float(1).w<1.0
            Vector4Float(0).x=Vector4Float(1).x : Vector4Float(0).y=Vector4Float(1).y : Vector4Float(0).z=Vector4Float(1).z
            Vector4Float(1).x=0 : Vector4Float(1).y=0 : Vector4Float(1).z=-1
            exitfunction 1
         endif
      endif
   else
      if Vector4Float(0).x>tMinX# and Vector4Float(0).x<tMaxX# and Vector4Float(0).w>0.0 
         if Vector4Float(0).y>tMinY# and Vector4Float(0).y<tMaxY# and Vector4Float(0).w<1.0
            Vector4Float(1).x=0 : Vector4Float(1).y=0 : Vector4Float(1).z=1
            exitfunction 1
        endif
      endif
   endif
endfunction 0

`--------------
` Triangle Ray Cast
`--------------
function RayTriangleCast(iFromX as float,iFromY as float,iFromZ as float,iToX as float,iToY as float,iToZ as float)
   iToX=iToX-iFromX:iToY=iToY-iFromY:iToZ=iToZ-iFromZ
   Vector4Float(260).x=Vector4Float(3).x-Vector4Float(1).x
   Vector4Float(260).y=Vector4Float(3).y-Vector4Float(1).y
   Vector4Float(260).z=Vector4Float(3).z-Vector4Float(1).z
   Vector4Float(261).x=Vector4Float(2).x-Vector4Float(1).x
   Vector4Float(261).y=Vector4Float(2).y-Vector4Float(1).y
   Vector4Float(261).z=Vector4Float(2).z-Vector4Float(1).z
   Vector4Float(262).x=(iToY*Vector4Float(261).z)-(Vector4Float(261).y*iToZ)
   Vector4Float(262).y=(iToZ*Vector4Float(261).x)-(Vector4Float(261).z*iToX)
   Vector4Float(262).z=(iToX*Vector4Float(261).y)-(Vector4Float(261).x*iToY)
   Vector4Float(260).w=(Vector4Float(260).x* Vector4Float(262).x)+(Vector4Float(260).y*Vector4Float(262).y)+(Vector4Float(260).z*Vector4Float(262).z)
   if Vector4Float(260).w>-0.00001 and Vector4Float(260).w<0.00001 then exitfunction 0
   Vector4Float(260).w=1.0/Vector4Float(260).w
   Vector4Float(263).x=iFromX-Vector4Float(1).x
   Vector4Float(263).y=iFromY-Vector4Float(1).y
   Vector4Float(263).z=iFromZ-Vector4Float(1).z
   Vector4Float(261).w=Vector4Float(260).w*((Vector4Float(263).x*Vector4Float(262).x)+(Vector4Float(263).y*Vector4Float(262).y)+(Vector4Float(263).z*Vector4Float(262).z))
   if Vector4Float(261).w<0 or Vector4Float(261).w>1 then exitfunction 0
   Vector4Float(264).x=(Vector4Float(263).y*Vector4Float(260).z)-(Vector4Float(260).y*Vector4Float(263).z)
   Vector4Float(264).y=(Vector4Float(263).z*Vector4Float(260).x)-(Vector4Float(260).z*Vector4Float(263).x)
   Vector4Float(264).z=(Vector4Float(263).x*Vector4Float(260).y)-(Vector4Float(260).x*Vector4Float(263).y)
   Vector4Float(262).w=Vector4Float(260).w*((iToX*Vector4Float(264).x)+(iToY*Vector4Float(264).y)+(iToZ*Vector4Float(264).z))
   if Vector4Float(262).w<0.0 or Vector4Float(261).w+Vector4Float(262).w>1.0 then exitfunction 0
   Vector4Float(263).w=Vector4Float(260).w*((Vector4Float(261).x*Vector4Float(264).x)+(Vector4Float(261).y*Vector4Float(264).y)+(Vector4Float(261).z*Vector4Float(264).z))
   if Vector4Float(263).w<0 or Vector4Float(263).w>1 then exitfunction 0
   Vector4Float(265).x=(Vector4Float(260).y*Vector4Float(261).z)-(Vector4Float(260).z*Vector4Float(261).y)
   Vector4Float(265).y=(Vector4Float(260).z*Vector4Float(261).x)-(Vector4Float(260).x*Vector4Float(261).z)
   Vector4Float(265).z=(Vector4Float(260).x*Vector4Float(261).y)-(Vector4Float(260).y*Vector4Float(261).x)
   Vector4Float(266).x=-Vector4Float(265).x*Vector4Float(1).x-Vector4Float(265).y*Vector4Float(1).y-Vector4Float(265).z*Vector4Float(1).z
   Vector4Float(266).y=Vector4Float(265).x*iToX+Vector4Float(265).y*iToY+Vector4Float(265).z*iToZ
   Vector4Float(266).z=-(Vector4Float(266).x+Vector4Float(265).x*iFromX+Vector4Float(265).y*iFromY+Vector4Float(265).z*iFromZ)/Vector4Float(266).y
   Vector4Float(0).x=iFromX+Vector4Float(266).z*iToX
   Vector4Float(0).y=iFromY+Vector4Float(266).z*iToY
   Vector4Float(0).z=iFromZ+Vector4Float(266).z*iToZ
endfunction 1

`--------------
` Get View Frustum matrix
`--------------
function GetViewProjectFrustum(iFrustumIndex as integer,iMatrix as integer)
   for i=0 to 15
      ViewProjectVec(i)=get matrix4 element(iMatrix,i)
   next i
   ViewProjectFrustumVec(iFrustumIndex,0,0)=ViewProjectVec(3)-ViewProjectVec(0)
   ViewProjectFrustumVec(iFrustumIndex,0,1)=ViewProjectVec(7)-ViewProjectVec(4)
   ViewProjectFrustumVec(iFrustumIndex,0,2)=ViewProjectVec(11)-ViewProjectVec(8)
   ViewProjectFrustumVec(iFrustumIndex,0,3)=ViewProjectVec(15)-ViewProjectVec(12)
   ViewProjectFrustumVec(iFrustumIndex,1,0)=ViewProjectVec(3)+ViewProjectVec(0)
   ViewProjectFrustumVec(iFrustumIndex,1,1)=ViewProjectVec(7)+ViewProjectVec(4)
   ViewProjectFrustumVec(iFrustumIndex,1,2)=ViewProjectVec(11)+ViewProjectVec(8)
   ViewProjectFrustumVec(iFrustumIndex,1,3)=ViewProjectVec(15)+ViewProjectVec(12)
   ViewProjectFrustumVec(iFrustumIndex,2,0)=ViewProjectVec(3)+ViewProjectVec(1)
   ViewProjectFrustumVec(iFrustumIndex,2,1)=ViewProjectVec(7)+ViewProjectVec(5)
   ViewProjectFrustumVec(iFrustumIndex,2,2)=ViewProjectVec(11)+ViewProjectVec(9)
   ViewProjectFrustumVec(iFrustumIndex,2,3)=ViewProjectVec(15)+ViewProjectVec(13)
   ViewProjectFrustumVec(iFrustumIndex,3,0)=ViewProjectVec(3)-ViewProjectVec(1)
   ViewProjectFrustumVec(iFrustumIndex,3,1)=ViewProjectVec(7)-ViewProjectVec(5)
   ViewProjectFrustumVec(iFrustumIndex,3,2)=ViewProjectVec(11)-ViewProjectVec(9)
   ViewProjectFrustumVec(iFrustumIndex,3,3)=ViewProjectVec(15)-ViewProjectVec(13)
   ViewProjectFrustumVec(iFrustumIndex,4,0)=ViewProjectVec(3)-ViewProjectVec(2)
   ViewProjectFrustumVec(iFrustumIndex,4,1)=ViewProjectVec(7)-ViewProjectVec(6)
   ViewProjectFrustumVec(iFrustumIndex,4,2)=ViewProjectVec(11)-ViewProjectVec(10)
   ViewProjectFrustumVec(iFrustumIndex,4,3)=ViewProjectVec(15)-ViewProjectVec(14)
   ViewProjectFrustumVec(iFrustumIndex,5,0)=ViewProjectVec(3)+ViewProjectVec(2)
   ViewProjectFrustumVec(iFrustumIndex,5,1)=ViewProjectVec(7)+ViewProjectVec(6)
   ViewProjectFrustumVec(iFrustumIndex,5,2)=ViewProjectVec(11)+ViewProjectVec(10)
   ViewProjectFrustumVec(iFrustumIndex,5,3)=ViewProjectVec(15)+ViewProjectVec(14)
   set vector3 Vector3(32),ViewProjectFrustumVec(iFrustumIndex,0,0),ViewProjectFrustumVec(iFrustumIndex,0,1),ViewProjectFrustumVec(iFrustumIndex,0,2)
   Vector4Float(260).x=1.0/length vector3(Vector3(32))
   set vector3 Vector3(32),ViewProjectFrustumVec(iFrustumIndex,2,0),ViewProjectFrustumVec(iFrustumIndex,2,1),ViewProjectFrustumVec(iFrustumIndex,2,2)
   Vector4Float(260).y=1.0/length vector3(Vector3(32))
   set vector3 Vector3(32),ViewProjectFrustumVec(iFrustumIndex,4,0),ViewProjectFrustumVec(iFrustumIndex,4,1),ViewProjectFrustumVec(iFrustumIndex,4,2)
   Vector4Float(260).z=1.0/length vector3(Vector3(32))
   set vector3 Vector3(32),ViewProjectFrustumVec(iFrustumIndex,5,0),ViewProjectFrustumVec(iFrustumIndex,5,1),ViewProjectFrustumVec(iFrustumIndex,5,2)
   Vector4Float(260).w=1.0/length vector3(Vector3(32))
   for c=0 to 3
      ViewProjectFrustumVec(iFrustumIndex,0,c)=ViewProjectFrustumVec(iFrustumIndex,0,c)*Vector4Float(260).x
      ViewProjectFrustumVec(iFrustumIndex,1,c)=ViewProjectFrustumVec(iFrustumIndex,1,c)*Vector4Float(260).x
      ViewProjectFrustumVec(iFrustumIndex,2,c)=ViewProjectFrustumVec(iFrustumIndex,2,c)*Vector4Float(260).y
      ViewProjectFrustumVec(iFrustumIndex,3,c)=ViewProjectFrustumVec(iFrustumIndex,3,c)*Vector4Float(260).y
      ViewProjectFrustumVec(iFrustumIndex,4,c)=ViewProjectFrustumVec(iFrustumIndex,4,c)*Vector4Float(260).z
      ViewProjectFrustumVec(iFrustumIndex,5,c)=ViewProjectFrustumVec(iFrustumIndex,5,c)*Vector4Float(260).w
   next c
endfunction

`--------------
` Sphere In Frustum
`--------------
function GetSphereInFrustum(iFrustumIndex as integer,iPosX as float,iPosY as float,iPosZ as float,iRadius as float)
   if (ViewProjectFrustumVec(iFrustumIndex,5,0)*iPosX)+(ViewProjectFrustumVec(iFrustumIndex,5,1)*iPosY)+(ViewProjectFrustumVec(iFrustumIndex,5,2)*iPosZ)+ViewProjectFrustumVec(iFrustumIndex,5,3)<-iRadius then exitfunction 0
   if (ViewProjectFrustumVec(iFrustumIndex,0,0)*iPosX)+(ViewProjectFrustumVec(iFrustumIndex,0,1)*iPosY)+(ViewProjectFrustumVec(iFrustumIndex,0,2)*iPosZ)+ViewProjectFrustumVec(iFrustumIndex,0,3)<-iRadius then exitfunction 0
   if (ViewProjectFrustumVec(iFrustumIndex,1,0)*iPosX)+(ViewProjectFrustumVec(iFrustumIndex,1,1)*iPosY)+(ViewProjectFrustumVec(iFrustumIndex,1,2)*iPosZ)+ViewProjectFrustumVec(iFrustumIndex,1,3)<-iRadius then exitfunction 0
   if (ViewProjectFrustumVec(iFrustumIndex,2,0)*iPosX)+(ViewProjectFrustumVec(iFrustumIndex,2,1)*iPosY)+(ViewProjectFrustumVec(iFrustumIndex,2,2)*iPosZ)+ViewProjectFrustumVec(iFrustumIndex,2,3)<-iRadius then exitfunction 0
   if (ViewProjectFrustumVec(iFrustumIndex,3,0)*iPosX)+(ViewProjectFrustumVec(iFrustumIndex,3,1)*iPosY)+(ViewProjectFrustumVec(iFrustumIndex,3,2)*iPosZ)+ViewProjectFrustumVec(iFrustumIndex,3,3)<-iRadius then exitfunction 0
endfunction 1

`--------------
` Box In Frustum
`--------------
function GetBoxInFrustum(iFrustumIndex as integer,iPosX as float,iPosY as float,iPosZ as float,iSizeX as float,iSizeY as float,iSizeZ as float)
   for e=0 to 3
      Vector4Float(260).x=ViewProjectFrustumVec(iFrustumIndex,e,0)*(iPosX-iSizeX)
      Vector4Float(261).x=ViewProjectFrustumVec(iFrustumIndex,e,0)*(iPosX+iSizeX)
      Vector4Float(260).y=ViewProjectFrustumVec(iFrustumIndex,e,1)*(iPosY-iSizeY)
      Vector4Float(261).y=ViewProjectFrustumVec(iFrustumIndex,e,1)*(iPosY+iSizeY)
      Vector4Float(260).z=ViewProjectFrustumVec(iFrustumIndex,e,2)*(iPosZ-iSizeZ)
      Vector4Float(261).z=ViewProjectFrustumVec(iFrustumIndex,e,2)*(iPosZ+iSizeZ)
      rCull=0
      if Vector4Float(260).x+Vector4Float(260).y+Vector4Float(260).z+ViewProjectFrustumVec(iFrustumIndex,e,3)>0 then rCull=1
      if Vector4Float(261).x+Vector4Float(260).y+Vector4Float(260).z+ViewProjectFrustumVec(iFrustumIndex,e,3)>0 then rCull=1
      if Vector4Float(260).x+Vector4Float(261).y+Vector4Float(260).z+ViewProjectFrustumVec(iFrustumIndex,e,3)>0 then rCull=1
      if Vector4Float(261).x+Vector4Float(261).y+Vector4Float(260).z+ViewProjectFrustumVec(iFrustumIndex,e,3)>0 then rCull=1
      if rCull=0         
         if Vector4Float(260).x+Vector4Float(260).y+Vector4Float(261).z+ViewProjectFrustumVec(iFrustumIndex,e,3)>0 then rCull=1
         if Vector4Float(261).x+Vector4Float(260).y+Vector4Float(261).z+ViewProjectFrustumVec(iFrustumIndex,e,3)>0 then rCull=1
         if Vector4Float(260).x+Vector4Float(261).y+Vector4Float(261).z+ViewProjectFrustumVec(iFrustumIndex,e,3)>0 then rCull=1
         if Vector4Float(261).x+Vector4Float(261).y+Vector4Float(261).z+ViewProjectFrustumVec(iFrustumIndex,e,3)>0 then rCull=1
      endif
      if rCull=0 then exitfunction 0
   next e
endfunction 1

`--------------
` Get Directory
`--------------
function GetDirectory(iFile as string)
   local tDirPath as string
   x=len(iFile)
   for t=0 to x
      if mid$(iFile,x-t)="\" or mid$(iFile,x-t)="/" then exit
   next t
   tDirPath=left$(iFile,x-(t+1))
endfunction tDirPath

`--------------
` Get Directory Name
`--------------
function GetDirectoryName(iFile as string)
   local tDirPath as string
   tDirPath=GetDirectory(iFile)
   tDirPath=GetFileName(tDirPath)
endfunction tDirPath

`--------------
` Get File Name
`--------------
function GetFileName(iFile as string)
   local tDirPath as string
   x=len(iFile)
   for t=0 to x
      if mid$(iFile,x-t)="\" or mid$(iFile,x-t)="/" then exit
   next t
   tDirPath=right$(iFile,t)
endfunction tDirPath

`--------------
` Get Local Directory Path
`--------------
function GetDirectoryPath(iFile as string,iDirectory as string)
   local tDirPath as string
   local tCurrDir as string
   tCurrDir=get dir$()
   set dir iDirectory
   if lower$(left$(iFile,len(iDirectory)))=lower$(iDirectory) then tDirPath=right$(iFile,(len(iFile)-len(iDirectory))-1)
   if file exist(tDirPath)=0 then tDirPath=iFile
   set dir tCurrDir
endfunction tDirPath

`--------------
` Get MyDoc Dir
`--------------
function GetMyDocDir()
   local tMydocDir as string
   tMydocDir=mydocdir$()
   tOneDrive=0
   for l=0 to len(tMydocDir)
      tstr$=mid$(tMydocDir,l+0)+mid$(tMydocDir,l+1)+mid$(tMydocDir,l+2)+mid$(tMydocDir,l+3)+mid$(tMydocDir,l+4)+mid$(tMydocDir,l+5)+mid$(tMydocDir,l+6)+mid$(tMydocDir,l+7)
      tstr$=lower$(tstr$)
      if tstr$="onedrive" then tOneDrive=1:exit
   next l
   if tOneDrive=1
      tNewDir$=""
      for l=0 to len(tMydocDir)
         tstr$=mid$(tMydocDir,l+0)+mid$(tMydocDir,l+1)+mid$(tMydocDir,l+2)+mid$(tMydocDir,l+3)+mid$(tMydocDir,l+4)+mid$(tMydocDir,l+5)+mid$(tMydocDir,l+6)+mid$(tMydocDir,l+7)
         tstr$=lower$(tstr$)
         if tstr$="onedrive" then inc l,9
         tNewDir$=tNewDir$+mid$(tMydocDir,l)
      next l      
      if path exist(tNewDir$)=1 then tMydocDir=tNewDir$: tOneDrive=0
   endif
   if  tOneDrive=1 or path exist(tMydocDir)=0 then tMydocDir=OldDir$+"\sys"
endfunction tMydocDir

`--------------
` Create Camera
`--------------
function CreateCamera(iImage as integer,iWidth as float,iHeight as float,iD3DFormat as integer)
   tCamera=FreeUpCamera()
   if image exist(iImage)=1 then delete image iImage
   make camera tCamera
   set camera to image tCamera,iImage,iWidth,iHeight,3,iD3DFormat
   set camera view tCamera,0,0,iWidth,iHeight
   backdrop off tCamera
   set camera aspect tCamera,1
   set camera range tCamera,1,2
   set camera fov tCamera,90
endfunction tCamera

`--------------
` Camera To Render Target
`--------------
function CameraToRenderTarget(iCamera as integer,iObject as integer,iEffectFile as string)
   if camera exist(iCamera)=1 and file exist(iEffectFile)=1
      tEffect=FreeUpEffect(3500)
      if object exist(iObject)=1 then delete object iObject
      make object plane iObject,2,2,1
      if ShaderEffectDefineCount=-1 then load effect iEffectFile,tEffect,0,1 else LoadShaderEffect(iEffectFile,tEffect,1)      
      set object effect iObject,tEffect
      disable object zwrite iObject
      disable object zdepth iObject
      set object radius iObject,0
      set object mask iObject,2^iCamera
      position object iObject,-9999999,-9999999,-9999999
   endif
endfunction tEffect

`--------------
` Create Color Image
`--------------
function CreateColorImage(iImage as integer,iRed as integer,iGreen as integer,iBlue as integer,iAlpha as integer)
   tFreememblock=FreeUpmemblock()
   make memblock tFreememblock,12+4
   write memblock dword tFreememblock,0,1
   write memblock dword tFreememblock,4,1
   write memblock dword tFreememblock,8,32
   if iAlpha>255 then iAlpha=255
   write memblock byte tFreememblock,15,iAlpha
   write memblock byte tFreememblock,14,iRed
   write memblock byte tFreememblock,13,iGreen
   write memblock byte tFreememblock,12,iBlue
   if image exist(iImage)=1 then delete image iImage
   make image from memblock iImage,tFreememblock
   delete memblock tFreememblock
endfunction

`--------------
` Set Shader Effect Define (preprocessor directives)
`--------------
function SetShaderEffectDefine(iDefine as string,iValue as integer)
   inc ShaderEffectDefineCount
   ShaderEffectDefineStr(ShaderEffectDefineCount)=iDefine
   ShaderEffectDefineVal(ShaderEffectDefineCount)=iValue
endfunction

`--------------
` Load Effect With Preprocessor Directives
`--------------
function LoadShaderEffect(iEffectFile as string,iEffect as integer,iDoNotGenerateExtraData as integer)
   local tStr as string
   local tDefine as string
   local tFileName as string
   if file exist(iEffectFile)=1
      if ShaderEffectDefineCount>-1
         tFileName=GetFileName(iEffectFile)
         tEffectFile=FreeUpFile()
         open to read tEffectFile,iEffectFile
         tTempFile=FreeUpFile()
         tMyDocDir$=GetMyDocDir()
         if path exist(tMyDocDir$+"\My Games")=0 then make directory tMyDocDir$+"\My Games"
         if path exist(tMyDocDir$+"\My Games\Game Data")=0 then make directory tMyDocDir$+"\My Games\Game Data"
         if path exist(tMyDocDir$+"\My Games\Game Data\Shaders")=0 then make directory tMyDocDir$+"\My Games\Game Data\Shaders"
         if file exist(tMyDocDir$+"\My Games\Game Data\Shaders\"+tFileName)=1 then delete file tMyDocDir$+"\My Games\Game Data\Shaders\"+tFileName
         if file exist(tMyDocDir$+"\My Games\Game Data\Shaders\"+tFileName)=0
            open to write tTempFile,tMyDocDir$+"\My Games\Game Data\Shaders\"+tFileName
               repeat
                  read string tEffectFile,tStr
                  if tStr<>""
                     if left$(tStr,2)<>"//"
                        if left$(tStr,7)="#define"
                           tDefine=right$(tStr,len(tStr)-8)
                           tDefine=left$(tDefine,len(tDefine)-2)
                           for i=0 to ShaderEffectDefineCount
                              if tDefine=ShaderEffectDefineStr(i) then tStr="#define "+tDefine+" "+str$(ShaderEffectDefineVal(i))
                           next i
                        endif
                        write string tTempFile,tStr
                     endif
                  endif
               until file end(tEffectFile)=1
            close file tTempFile
            close file tEffectFile
         endif
         if iEffect>0
            if effect exist(iEffect)=1 then delete effect iEffect
            load effect tMyDocDir$+"\My Games\Game Data\Shaders\"+tFileName,iEffect,0,iDoNotGenerateExtraData
          endif
      else
         load effect iEffectFile,iEffect,0,iDoNotGenerateExtraData
      endif
   endif
   ShaderEffectDefineCount=-1
endfunction

`--------------
` Shader View Vector
`--------------
function SetViewVec(iVector4 as integer,iViewX as float,iViewY as float)
   set vector4 iVector4,0.5/iViewX,0.5/iViewY,0,0
endfunction iVector4

`--------------
` Axis Aligned Bounding Box
`--------------
function AxisAlignedBoundingBox(iObject as integer)
   rotate x matrix4 Matrix(30),wrapvalue(object angle x(iObject))*0.01745329251
   rotate y matrix4 Matrix(31),wrapvalue(object angle y(iObject))*0.01745329251
   rotate z matrix4 Matrix(32),wrapvalue(object angle z(iObject))*0.01745329251
   multiply matrix4 Matrix(30),Matrix(30),Matrix(31)
   multiply matrix4 Matrix(30),Matrix(30),Matrix(32)
   Vector4Float(260).x=object size x(iObject,1)
   Vector4Float(260).y=object size y(iObject,1)
   Vector4Float(260).z=object size z(iObject,1)
   if object size x(iObject,1)=0 then Vector4Float(260).x=100
   if object size y(iObject,1)=0 then Vector4Float(260).y=100
   if object size z(iObject,1)=0 then Vector4Float(260).z=100
   MinMaxVecReSet()
   for b=0 to 7
      set vector3 Vector3(32),Vector4Float(260).x*AABBox(b).x,Vector4Float(260).y*AABBox(b).y,Vector4Float(260).z*AABBox(b).z
      transform coords vector3 Vector3(32),Vector3(32),Matrix(30)
      MinMaxVec(x vector3(Vector3(32)),y vector3(Vector3(32)),z vector3(Vector3(32)))
   next b
   MinMaxPositionSize()   
   Vector4Float(261).x=object size x(iObject)/100
   Vector4Float(261).y=object size y(iObject)/100
   Vector4Float(261).z=object size z(iObject)/100   
   if object size x(iObject)=0 then Vector4Float(261).x=1
   if object size y(iObject)=0 then Vector4Float(261).y=1
   if object size z(iObject)=0 then Vector4Float(261).z=1         
   Vector4Float(260).x=Vector4Float(260).x/Vector4Float(261).x
   Vector4Float(260).y=Vector4Float(260).y/Vector4Float(261).y
   Vector4Float(260).z=Vector4Float(260).z/Vector4Float(261).z
   MinMaxPos.x=object position x(iObject)+(object collision center x(iObject)*(Vector4Float(260).x/100))
   MinMaxPos.y=object position y(iObject)+(object collision center y(iObject)*(Vector4Float(260).y/100))
   MinMaxPos.z=object position z(iObject)+(object collision center z(iObject)*(Vector4Float(260).z/100))
endfunction

`--------------
` Message Box Dialog
`--------------
#constant MB_ABORTRETRYIGNORE 0x00000002
#constant MB_CANCELTRYCONTINUE 0x00000006
#constant MB_HELP 0x00004000
#constant MB_OK 0x00000000
#constant MB_OKCANCEL 0x00000001
#constant MB_RETRYCANCEL 0x00000005
#constant MB_YESNO 0x00000004
#constant MB_YESNOCANCEL 0x00000003
#constant MB_ICONEXCLAMATION 0x00000030
#constant MB_ICONWARNING 0x00000030
#constant MB_ICONINFORMATION 0x00000040
#constant MB_ICONASTERISK 0x00000040
#constant MB_ICONQUESTION 0x00000020
#constant MB_ICONSTOP 0x00000010
#constant MB_ICONERROR 0x00000010
#constant MB_ICONHAND 0x00000010
function MessageBox(iCaption as string,iMessage as string,iFlag as dword)
   local tHWND as dword
   tDLL=FreeUpDll()
   load dll "user32.dll",tDLL
   if dll exist(tDLL)=1
      tHWND=call dll(tDLL,"GetActiveWindow")
      tVal=call dll(tDLL,"MessageBoxA",tHWND,iMessage,iCaption,iFlag)
      delete dll tDLL
   endif
endfunction tVal

`--------------
` Choose Color Dialog
`--------------
#constant CC_ANYCOLOR 0x00000100
#constant CC_FULLOPEN 0x00000002
#constant CC_RGBINIT 0x00000001
function ChooseColor(iRed as integer,iGreen as integer,iBlue as integer,iFlag as dword)
   local tHWND as dword
   local dim tDLL(2) as integer
   local dim tMemblock(2) as integer
   tDLL(1)=FreeUpDll()
   load dll "user32.dll",tDLL(1)
   tDLL(2)=FreeUpDll()
   load dll "comdlg32.dll",tDLL(2)
   if dll exist(tDLL(1))=1 and dll exist(tDLL(2))=1
      if CC_ACTIVE=0
         global CC_ACTIVE as boolean
         global CC_NextColors as integer
         global dim CC_Colors(15,2) as byte
         CC_ACTIVE=1
         for c=0 to 15
            CC_Colors(c,0)=255
            CC_Colors(c,1)=255
            CC_Colors(c,2)=255
         next c
      endif
      tHWND=call dll(tDLL(1),"GetForegroundWindow")
      tMemblock(1)=FreeUpMemblock()
      make memblock tMemblock(1),36
      tMemblock(2)=FreeUpMemblock()
      make memblock tMemblock(2),64
      for c=0 to 15
         write memblock dword tMemblock(2),c*4,(CC_Colors(c,2)*65536)+(CC_Colors(c,1)*256)+CC_Colors(c,0)
      next c
      write memblock dword tMemblock(1),0,36
      write memblock dword tMemblock(1),4,tHWND
      write memblock dword tMemblock(1),12,iRed
      write memblock dword tMemblock(1),13,iGreen
      write memblock dword tMemblock(1),14,iBlue
      write memblock dword tMemblock(1),16,get memblock ptr(tMemblock(2))
      write memblock dword tMemblock(1),20,iFlag
      tVal=call dll(tDLL(2),"ChooseColorA",get memblock ptr(tMemblock(1)))
      if tVal=0
         tVal=1
      else
         tVal=rgb(memblock byte(tMemblock(1),12),memblock byte(tMemblock(1),13),memblock byte(tMemblock(1),14))
         CC_Colors(CC_NextColors,0)=memblock byte(tMemblock(1),12)
         CC_Colors(CC_NextColors,1)=memblock byte(tMemblock(1),13)
         CC_Colors(CC_NextColors,2)=memblock byte(tMemblock(1),14)
         inc CC_NextColors
         if CC_NextColors>15 then CC_NextColors=0
      endif
      delete memblock tMemblock(1)
      delete memblock tMemblock(2)
      delete dll tDLL(1)
      delete dll tDLL(2)
   endif
endfunction tVal
